cjson
.github
workflows CI.yml ci-fuzz.yml
CONTRIBUTING.md
fuzzing
inputs test1 test10 test11 test2 test3 test3.bu test3.uf test3.uu test4 test5 test6 test7 test8 test9
.gitignore CMakeLists.txt afl-prepare-linux.sh afl.c afl.sh cjson_read_fuzzer.c fuzz_main.c json.dict ossfuzz.sh
library_config cJSONConfig.cmake.in cJSONConfigVersion.cmake.in libcjson.pc.in libcjson_utils.pc.in uninstall.cmake
tests
inputs test1 test1.expected test10 test10.expected test11 test11.expected test2 test2.expected test3 test3.expected test4 test4.expected test5 test5.expected test6 test7 test7.expected test8 test8.expected test9 test9.expected
json-patch-tests .editorconfig .gitignore .npmignore README.md cjson-utils-tests.json package.json spec_tests.json tests.json
unity
auto colour_prompt.rb colour_reporter.rb generate_config.yml generate_module.rb generate_test_runner.rb parse_output.rb stylize_as_junit.rb test_file_filter.rb type_sanitizer.rb unity_test_summary.py unity_test_summary.rb unity_to_junit.py
docs ThrowTheSwitchCodingStandard.md UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf UnityAssertionsReference.md UnityConfigurationGuide.md UnityGettingStartedGuide.md UnityHelperScriptsGuide.md license.txt
examples
example_1
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
makefile readme.txt
example_2
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
makefile readme.txt
example_3
helper UnityHelper.c UnityHelper.h
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
rakefile.rb rakefile_helper.rb readme.txt target_gcc_32.yml
unity_config.h
extras
eclipse error_parsers.txt
fixture
src unity_fixture.c unity_fixture.h unity_fixture_internals.h unity_fixture_malloc_overrides.h
rakefile.rb rakefile_helper.rb readme.txt
release build.info version.info
src unity.c unity.h unity_internals.h
.gitattributes .gitignore .travis.yml README.md
CMakeLists.txt cjson_add.c common.h compare_tests.c json_patch_tests.c minify_tests.c misc_tests.c misc_utils_tests.c old_utils_tests.c parse_array.c parse_examples.c parse_hex4.c parse_number.c parse_object.c parse_string.c parse_value.c parse_with_opts.c print_array.c print_number.c print_object.c print_string.c print_value.c readme_examples.c unity_setup.c
.editorconfig .gitattributes .gitignore .travis.yml CHANGELOG.md CMakeLists.txt CONTRIBUTORS.md LICENSE Makefile README.md SECURITY.md appveyor.yml cJSON.c cJSON.h cJSON_Utils.c cJSON_Utils.h test.c valgrind.supp
curl
.circleci config.yml
.github
ISSUE_TEMPLATE bug_report.yml config.yml docs.yml
scripts cleancmd.pl cmp-config.pl cmp-pkg-config.sh codespell-ignore.words codespell.sh distfiles.sh pyspelling.words pyspelling.yaml randcurl.pl requirements-docs.txt requirements-proselint.txt requirements.txt shellcheck-ci.sh shellcheck.sh spellcheck.curl trimmarkdownheader.pl typos.sh typos.toml verify-examples.pl verify-synopsis.pl yamlcheck.sh yamlcheck.yaml
workflows appveyor-status.yml checkdocs.yml checksrc.yml checkurls.yml codeql.yml configure-vs-cmake.yml curl-for-win.yml distcheck.yml fuzz.yml http3-linux.yml label.yml linux-old.yml linux.yml macos.yml non-native.yml windows.yml
CODEOWNERS CONTRIBUTING.md FUNDING.yml dependabot.yml labeler.yml lock.yml stale.yml
CMake CurlSymbolHiding.cmake CurlTests.c FindBrotli.cmake FindCares.cmake FindGSS.cmake FindGnuTLS.cmake FindLDAP.cmake FindLibbacktrace.cmake FindLibgsasl.cmake FindLibidn2.cmake FindLibpsl.cmake FindLibssh.cmake FindLibssh2.cmake FindLibuv.cmake FindMbedTLS.cmake FindNGHTTP2.cmake FindNGHTTP3.cmake FindNGTCP2.cmake FindNettle.cmake FindQuiche.cmake FindRustls.cmake FindWolfSSL.cmake FindZstd.cmake Macros.cmake OtherTests.cmake PickyWarnings.cmake Utilities.cmake cmake_uninstall.in.cmake curl-config.in.cmake unix-cache.cmake win32-cache.cmake
LICENSES BSD-4-Clause-UC.txt ISC.txt curl.txt
docs
cmdline-opts .gitignore CMakeLists.txt MANPAGE.md Makefile.am Makefile.inc _AUTHORS.md _BUGS.md _DESCRIPTION.md _ENVIRONMENT.md _EXITCODES.md _FILES.md _GLOBBING.md _NAME.md _OPTIONS.md _OUTPUT.md _PROGRESS.md _PROTOCOLS.md _PROXYPREFIX.md _SEEALSO.md _SYNOPSIS.md _URL.md _VARIABLES.md _VERSION.md _WWW.md abstract-unix-socket.md alt-svc.md anyauth.md append.md aws-sigv4.md basic.md ca-native.md cacert.md capath.md cert-status.md cert-type.md cert.md ciphers.md compressed-ssh.md compressed.md config.md connect-timeout.md connect-to.md continue-at.md cookie-jar.md cookie.md create-dirs.md create-file-mode.md crlf.md crlfile.md curves.md data-ascii.md data-binary.md data-raw.md data-urlencode.md data.md delegation.md digest.md disable-eprt.md disable-epsv.md disable.md disallow-username-in-url.md dns-interface.md dns-ipv4-addr.md dns-ipv6-addr.md dns-servers.md doh-cert-status.md doh-insecure.md doh-url.md dump-ca-embed.md dump-header.md ech.md egd-file.md engine.md etag-compare.md etag-save.md expect100-timeout.md fail-early.md fail-with-body.md fail.md false-start.md follow.md form-escape.md form-string.md form.md ftp-account.md ftp-alternative-to-user.md ftp-create-dirs.md ftp-method.md ftp-pasv.md ftp-port.md ftp-pret.md ftp-skip-pasv-ip.md ftp-ssl-ccc-mode.md ftp-ssl-ccc.md ftp-ssl-control.md get.md globoff.md happy-eyeballs-timeout-ms.md haproxy-clientip.md haproxy-protocol.md head.md header.md help.md hostpubmd5.md hostpubsha256.md hsts.md http0.9.md http1.0.md http1.1.md http2-prior-knowledge.md http2.md http3-only.md http3.md ignore-content-length.md insecure.md interface.md ip-tos.md ipfs-gateway.md ipv4.md ipv6.md json.md junk-session-cookies.md keepalive-cnt.md keepalive-time.md key-type.md key.md knownhosts.md krb.md libcurl.md limit-rate.md list-only.md local-port.md location-trusted.md location.md login-options.md mail-auth.md mail-from.md mail-rcpt-allowfails.md mail-rcpt.md mainpage.idx manual.md max-filesize.md max-redirs.md max-time.md metalink.md mptcp.md negotiate.md netrc-file.md netrc-optional.md netrc.md next.md no-alpn.md no-buffer.md no-clobber.md no-keepalive.md no-npn.md no-progress-meter.md no-sessionid.md noproxy.md ntlm-wb.md ntlm.md oauth2-bearer.md out-null.md output-dir.md output.md parallel-immediate.md parallel-max-host.md parallel-max.md parallel.md pass.md path-as-is.md pinnedpubkey.md post301.md post302.md post303.md preproxy.md progress-bar.md proto-default.md proto-redir.md proto.md proxy-anyauth.md proxy-basic.md proxy-ca-native.md proxy-cacert.md proxy-capath.md proxy-cert-type.md proxy-cert.md proxy-ciphers.md proxy-crlfile.md proxy-digest.md proxy-header.md proxy-http2.md proxy-insecure.md proxy-key-type.md proxy-key.md proxy-negotiate.md proxy-ntlm.md proxy-pass.md proxy-pinnedpubkey.md proxy-service-name.md proxy-ssl-allow-beast.md proxy-ssl-auto-client-cert.md proxy-tls13-ciphers.md proxy-tlsauthtype.md proxy-tlspassword.md proxy-tlsuser.md proxy-tlsv1.md proxy-user.md proxy.md proxy1.0.md proxytunnel.md pubkey.md quote.md random-file.md range.md rate.md raw.md referer.md remote-header-name.md remote-name-all.md remote-name.md remote-time.md remove-on-error.md request-target.md request.md resolve.md retry-all-errors.md retry-connrefused.md retry-delay.md retry-max-time.md retry.md sasl-authzid.md sasl-ir.md service-name.md show-error.md show-headers.md sigalgs.md silent.md skip-existing.md socks4.md socks4a.md socks5-basic.md socks5-gssapi-nec.md socks5-gssapi-service.md socks5-gssapi.md socks5-hostname.md socks5.md speed-limit.md speed-time.md ssl-allow-beast.md ssl-auto-client-cert.md ssl-no-revoke.md ssl-reqd.md ssl-revoke-best-effort.md ssl-sessions.md ssl.md sslv2.md sslv3.md stderr.md styled-output.md suppress-connect-headers.md tcp-fastopen.md tcp-nodelay.md telnet-option.md tftp-blksize.md tftp-no-options.md time-cond.md tls-earlydata.md tls-max.md tls13-ciphers.md tlsauthtype.md tlspassword.md tlsuser.md tlsv1.0.md tlsv1.1.md tlsv1.2.md tlsv1.3.md tlsv1.md tr-encoding.md trace-ascii.md trace-config.md trace-ids.md trace-time.md trace.md unix-socket.md upload-file.md upload-flags.md url-query.md url.md use-ascii.md user-agent.md user.md variable.md verbose.md version.md vlan-priority.md write-out.md xattr.md
examples .checksrc .gitignore 10-at-a-time.c CMakeLists.txt Makefile.am Makefile.example Makefile.inc README.md adddocsref.pl address-scope.c altsvc.c anyauthput.c block_ip.c cacertinmem.c certinfo.c chkspeed.c connect-to.c cookie_interface.c crawler.c debug.c default-scheme.c ephiperfifo.c evhiperfifo.c externalsocket.c fileupload.c ftp-delete.c ftp-wildcard.c ftpget.c ftpgetinfo.c ftpgetresp.c ftpsget.c ftpupload.c ftpuploadfrommem.c ftpuploadresume.c getinfo.c getinmemory.c getredirect.c getreferrer.c ghiper.c headerapi.c hiperfifo.c hsts-preload.c htmltidy.c htmltitle.cpp http-options.c http-post.c http2-download.c http2-pushinmemory.c http2-serverpush.c http2-upload.c http3-present.c http3.c httpcustomheader.c httpput-postfields.c httpput.c https.c imap-append.c imap-authzid.c imap-copy.c imap-create.c imap-delete.c imap-examine.c imap-fetch.c imap-list.c imap-lsub.c imap-multi.c imap-noop.c imap-search.c imap-ssl.c imap-store.c imap-tls.c interface.c ipv6.c keepalive.c localport.c log_failed_transfers.c maxconnects.c multi-app.c multi-debugcallback.c multi-double.c multi-event.c multi-formadd.c multi-legacy.c multi-post.c multi-single.c multi-uv.c netrc.c parseurl.c persistent.c pop3-authzid.c pop3-dele.c pop3-list.c pop3-multi.c pop3-noop.c pop3-retr.c pop3-ssl.c pop3-stat.c pop3-tls.c pop3-top.c pop3-uidl.c post-callback.c postinmemory.c postit2-formadd.c postit2.c progressfunc.c protofeats.c range.c resolve.c rtsp-options.c sendrecv.c sepheaders.c sessioninfo.c sftpget.c sftpuploadresume.c shared-connection-cache.c simple.c simplepost.c simplessl.c smooth-gtk-thread.c smtp-authzid.c smtp-expn.c smtp-mail.c smtp-mime.c smtp-multi.c smtp-ssl.c smtp-tls.c smtp-vrfy.c sslbackend.c synctime.c threaded.c unixsocket.c url2file.c urlapi.c usercertinmem.c version-check.pl websocket-cb.c websocket-updown.c websocket.c xmlstream.c
internals BUFQ.md BUFREF.md CHECKSRC.md CLIENT-READERS.md CLIENT-WRITERS.md CODE_STYLE.md CONNECTION-FILTERS.md CREDENTIALS.md CURLX.md DYNBUF.md HASH.md LLIST.md MID.md MQTT.md MULTI-EV.md NEW-PROTOCOL.md PEERS.md PORTING.md RATELIMITS.md README.md SCORECARD.md SPLAY.md STRPARSE.md THRDPOOL-AND-QUEUE.md TIME-KEEPING.md TLS-SESSIONS.md UINT_SETS.md WEBSOCKET.md
libcurl
opts CMakeLists.txt CURLINFO_ACTIVESOCKET.md CURLINFO_APPCONNECT_TIME.md CURLINFO_APPCONNECT_TIME_T.md CURLINFO_CAINFO.md CURLINFO_CAPATH.md CURLINFO_CERTINFO.md CURLINFO_CONDITION_UNMET.md CURLINFO_CONNECT_TIME.md CURLINFO_CONNECT_TIME_T.md CURLINFO_CONN_ID.md CURLINFO_CONTENT_LENGTH_DOWNLOAD.md CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md CURLINFO_CONTENT_LENGTH_UPLOAD.md CURLINFO_CONTENT_LENGTH_UPLOAD_T.md CURLINFO_CONTENT_TYPE.md CURLINFO_COOKIELIST.md CURLINFO_EARLYDATA_SENT_T.md CURLINFO_EFFECTIVE_METHOD.md CURLINFO_EFFECTIVE_URL.md CURLINFO_FILETIME.md CURLINFO_FILETIME_T.md CURLINFO_FTP_ENTRY_PATH.md CURLINFO_HEADER_SIZE.md CURLINFO_HTTPAUTH_AVAIL.md CURLINFO_HTTPAUTH_USED.md CURLINFO_HTTP_CONNECTCODE.md CURLINFO_HTTP_VERSION.md CURLINFO_LASTSOCKET.md CURLINFO_LOCAL_IP.md CURLINFO_LOCAL_PORT.md CURLINFO_NAMELOOKUP_TIME.md CURLINFO_NAMELOOKUP_TIME_T.md CURLINFO_NUM_CONNECTS.md CURLINFO_OS_ERRNO.md CURLINFO_POSTTRANSFER_TIME_T.md CURLINFO_PRETRANSFER_TIME.md CURLINFO_PRETRANSFER_TIME_T.md CURLINFO_PRIMARY_IP.md CURLINFO_PRIMARY_PORT.md CURLINFO_PRIVATE.md CURLINFO_PROTOCOL.md CURLINFO_PROXYAUTH_AVAIL.md CURLINFO_PROXYAUTH_USED.md CURLINFO_PROXY_ERROR.md CURLINFO_PROXY_SSL_VERIFYRESULT.md CURLINFO_QUEUE_TIME_T.md CURLINFO_REDIRECT_COUNT.md CURLINFO_REDIRECT_TIME.md CURLINFO_REDIRECT_TIME_T.md CURLINFO_REDIRECT_URL.md CURLINFO_REFERER.md CURLINFO_REQUEST_SIZE.md CURLINFO_RESPONSE_CODE.md CURLINFO_RETRY_AFTER.md CURLINFO_RTSP_CLIENT_CSEQ.md CURLINFO_RTSP_CSEQ_RECV.md CURLINFO_RTSP_SERVER_CSEQ.md CURLINFO_RTSP_SESSION_ID.md CURLINFO_SCHEME.md CURLINFO_SIZE_DELIVERED.md CURLINFO_SIZE_DOWNLOAD.md CURLINFO_SIZE_DOWNLOAD_T.md CURLINFO_SIZE_UPLOAD.md CURLINFO_SIZE_UPLOAD_T.md CURLINFO_SPEED_DOWNLOAD.md CURLINFO_SPEED_DOWNLOAD_T.md CURLINFO_SPEED_UPLOAD.md CURLINFO_SPEED_UPLOAD_T.md CURLINFO_SSL_ENGINES.md CURLINFO_SSL_VERIFYRESULT.md CURLINFO_STARTTRANSFER_TIME.md CURLINFO_STARTTRANSFER_TIME_T.md CURLINFO_TLS_SESSION.md CURLINFO_TLS_SSL_PTR.md CURLINFO_TOTAL_TIME.md CURLINFO_TOTAL_TIME_T.md CURLINFO_USED_PROXY.md CURLINFO_XFER_ID.md CURLMINFO_XFERS_ADDED.md CURLMINFO_XFERS_CURRENT.md CURLMINFO_XFERS_DONE.md CURLMINFO_XFERS_PENDING.md CURLMINFO_XFERS_RUNNING.md CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.md CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.md CURLMOPT_MAXCONNECTS.md CURLMOPT_MAX_CONCURRENT_STREAMS.md CURLMOPT_MAX_HOST_CONNECTIONS.md CURLMOPT_MAX_PIPELINE_LENGTH.md CURLMOPT_MAX_TOTAL_CONNECTIONS.md CURLMOPT_NETWORK_CHANGED.md CURLMOPT_NOTIFYDATA.md CURLMOPT_NOTIFYFUNCTION.md CURLMOPT_PIPELINING.md CURLMOPT_PIPELINING_SERVER_BL.md CURLMOPT_PIPELINING_SITE_BL.md CURLMOPT_PUSHDATA.md CURLMOPT_PUSHFUNCTION.md CURLMOPT_QUICK_EXIT.md CURLMOPT_RESOLVE_THREADS_MAX.md CURLMOPT_SOCKETDATA.md CURLMOPT_SOCKETFUNCTION.md CURLMOPT_TIMERDATA.md CURLMOPT_TIMERFUNCTION.md CURLOPT_ABSTRACT_UNIX_SOCKET.md CURLOPT_ACCEPTTIMEOUT_MS.md CURLOPT_ACCEPT_ENCODING.md CURLOPT_ADDRESS_SCOPE.md CURLOPT_ALTSVC.md CURLOPT_ALTSVC_CTRL.md CURLOPT_APPEND.md CURLOPT_AUTOREFERER.md CURLOPT_AWS_SIGV4.md CURLOPT_BUFFERSIZE.md CURLOPT_CAINFO.md CURLOPT_CAINFO_BLOB.md CURLOPT_CAPATH.md CURLOPT_CA_CACHE_TIMEOUT.md CURLOPT_CERTINFO.md CURLOPT_CHUNK_BGN_FUNCTION.md CURLOPT_CHUNK_DATA.md CURLOPT_CHUNK_END_FUNCTION.md CURLOPT_CLOSESOCKETDATA.md CURLOPT_CLOSESOCKETFUNCTION.md CURLOPT_CONNECTTIMEOUT.md CURLOPT_CONNECTTIMEOUT_MS.md CURLOPT_CONNECT_ONLY.md CURLOPT_CONNECT_TO.md CURLOPT_CONV_FROM_NETWORK_FUNCTION.md CURLOPT_CONV_FROM_UTF8_FUNCTION.md CURLOPT_CONV_TO_NETWORK_FUNCTION.md CURLOPT_COOKIE.md CURLOPT_COOKIEFILE.md CURLOPT_COOKIEJAR.md CURLOPT_COOKIELIST.md CURLOPT_COOKIESESSION.md CURLOPT_COPYPOSTFIELDS.md CURLOPT_CRLF.md CURLOPT_CRLFILE.md CURLOPT_CURLU.md CURLOPT_CUSTOMREQUEST.md CURLOPT_DEBUGDATA.md CURLOPT_DEBUGFUNCTION.md CURLOPT_DEFAULT_PROTOCOL.md CURLOPT_DIRLISTONLY.md CURLOPT_DISALLOW_USERNAME_IN_URL.md CURLOPT_DNS_CACHE_TIMEOUT.md CURLOPT_DNS_INTERFACE.md CURLOPT_DNS_LOCAL_IP4.md CURLOPT_DNS_LOCAL_IP6.md CURLOPT_DNS_SERVERS.md CURLOPT_DNS_SHUFFLE_ADDRESSES.md CURLOPT_DNS_USE_GLOBAL_CACHE.md CURLOPT_DOH_SSL_VERIFYHOST.md CURLOPT_DOH_SSL_VERIFYPEER.md CURLOPT_DOH_SSL_VERIFYSTATUS.md CURLOPT_DOH_URL.md CURLOPT_ECH.md CURLOPT_EGDSOCKET.md CURLOPT_ERRORBUFFER.md CURLOPT_EXPECT_100_TIMEOUT_MS.md CURLOPT_FAILONERROR.md CURLOPT_FILETIME.md CURLOPT_FNMATCH_DATA.md CURLOPT_FNMATCH_FUNCTION.md CURLOPT_FOLLOWLOCATION.md CURLOPT_FORBID_REUSE.md CURLOPT_FRESH_CONNECT.md CURLOPT_FTPPORT.md CURLOPT_FTPSSLAUTH.md CURLOPT_FTP_ACCOUNT.md CURLOPT_FTP_ALTERNATIVE_TO_USER.md CURLOPT_FTP_CREATE_MISSING_DIRS.md CURLOPT_FTP_FILEMETHOD.md CURLOPT_FTP_SKIP_PASV_IP.md CURLOPT_FTP_SSL_CCC.md CURLOPT_FTP_USE_EPRT.md CURLOPT_FTP_USE_EPSV.md CURLOPT_FTP_USE_PRET.md CURLOPT_GSSAPI_DELEGATION.md CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.md CURLOPT_HAPROXYPROTOCOL.md CURLOPT_HAPROXY_CLIENT_IP.md CURLOPT_HEADER.md CURLOPT_HEADERDATA.md CURLOPT_HEADERFUNCTION.md CURLOPT_HEADEROPT.md CURLOPT_HSTS.md CURLOPT_HSTSREADDATA.md CURLOPT_HSTSREADFUNCTION.md CURLOPT_HSTSWRITEDATA.md CURLOPT_HSTSWRITEFUNCTION.md CURLOPT_HSTS_CTRL.md CURLOPT_HTTP09_ALLOWED.md CURLOPT_HTTP200ALIASES.md CURLOPT_HTTPAUTH.md CURLOPT_HTTPGET.md CURLOPT_HTTPHEADER.md CURLOPT_HTTPPOST.md CURLOPT_HTTPPROXYTUNNEL.md CURLOPT_HTTP_CONTENT_DECODING.md CURLOPT_HTTP_TRANSFER_DECODING.md CURLOPT_HTTP_VERSION.md CURLOPT_IGNORE_CONTENT_LENGTH.md CURLOPT_INFILESIZE.md CURLOPT_INFILESIZE_LARGE.md CURLOPT_INTERFACE.md CURLOPT_INTERLEAVEDATA.md CURLOPT_INTERLEAVEFUNCTION.md CURLOPT_IOCTLDATA.md CURLOPT_IOCTLFUNCTION.md CURLOPT_IPRESOLVE.md CURLOPT_ISSUERCERT.md CURLOPT_ISSUERCERT_BLOB.md CURLOPT_KEEP_SENDING_ON_ERROR.md CURLOPT_KEYPASSWD.md CURLOPT_KRBLEVEL.md CURLOPT_LOCALPORT.md CURLOPT_LOCALPORTRANGE.md CURLOPT_LOGIN_OPTIONS.md CURLOPT_LOW_SPEED_LIMIT.md CURLOPT_LOW_SPEED_TIME.md CURLOPT_MAIL_AUTH.md CURLOPT_MAIL_FROM.md CURLOPT_MAIL_RCPT.md CURLOPT_MAIL_RCPT_ALLOWFAILS.md CURLOPT_MAXAGE_CONN.md CURLOPT_MAXCONNECTS.md CURLOPT_MAXFILESIZE.md CURLOPT_MAXFILESIZE_LARGE.md CURLOPT_MAXLIFETIME_CONN.md CURLOPT_MAXREDIRS.md CURLOPT_MAX_RECV_SPEED_LARGE.md CURLOPT_MAX_SEND_SPEED_LARGE.md CURLOPT_MIMEPOST.md CURLOPT_MIME_OPTIONS.md CURLOPT_NETRC.md CURLOPT_NETRC_FILE.md CURLOPT_NEW_DIRECTORY_PERMS.md CURLOPT_NEW_FILE_PERMS.md CURLOPT_NOBODY.md CURLOPT_NOPROGRESS.md CURLOPT_NOPROXY.md CURLOPT_NOSIGNAL.md CURLOPT_OPENSOCKETDATA.md CURLOPT_OPENSOCKETFUNCTION.md CURLOPT_PASSWORD.md CURLOPT_PATH_AS_IS.md CURLOPT_PINNEDPUBLICKEY.md CURLOPT_PIPEWAIT.md CURLOPT_PORT.md CURLOPT_POST.md CURLOPT_POSTFIELDS.md CURLOPT_POSTFIELDSIZE.md CURLOPT_POSTFIELDSIZE_LARGE.md CURLOPT_POSTQUOTE.md CURLOPT_POSTREDIR.md CURLOPT_PREQUOTE.md CURLOPT_PREREQDATA.md CURLOPT_PREREQFUNCTION.md CURLOPT_PRE_PROXY.md CURLOPT_PRIVATE.md CURLOPT_PROGRESSDATA.md CURLOPT_PROGRESSFUNCTION.md CURLOPT_PROTOCOLS.md CURLOPT_PROTOCOLS_STR.md CURLOPT_PROXY.md CURLOPT_PROXYAUTH.md CURLOPT_PROXYHEADER.md CURLOPT_PROXYPASSWORD.md CURLOPT_PROXYPORT.md CURLOPT_PROXYTYPE.md CURLOPT_PROXYUSERNAME.md CURLOPT_PROXYUSERPWD.md CURLOPT_PROXY_CAINFO.md CURLOPT_PROXY_CAINFO_BLOB.md CURLOPT_PROXY_CAPATH.md CURLOPT_PROXY_CRLFILE.md CURLOPT_PROXY_ISSUERCERT.md CURLOPT_PROXY_ISSUERCERT_BLOB.md CURLOPT_PROXY_KEYPASSWD.md CURLOPT_PROXY_PINNEDPUBLICKEY.md CURLOPT_PROXY_SERVICE_NAME.md CURLOPT_PROXY_SSLCERT.md CURLOPT_PROXY_SSLCERTTYPE.md CURLOPT_PROXY_SSLCERT_BLOB.md CURLOPT_PROXY_SSLKEY.md CURLOPT_PROXY_SSLKEYTYPE.md CURLOPT_PROXY_SSLKEY_BLOB.md CURLOPT_PROXY_SSLVERSION.md CURLOPT_PROXY_SSL_CIPHER_LIST.md CURLOPT_PROXY_SSL_OPTIONS.md CURLOPT_PROXY_SSL_VERIFYHOST.md CURLOPT_PROXY_SSL_VERIFYPEER.md CURLOPT_PROXY_TLS13_CIPHERS.md CURLOPT_PROXY_TLSAUTH_PASSWORD.md CURLOPT_PROXY_TLSAUTH_TYPE.md CURLOPT_PROXY_TLSAUTH_USERNAME.md CURLOPT_PROXY_TRANSFER_MODE.md CURLOPT_PUT.md CURLOPT_QUICK_EXIT.md CURLOPT_QUOTE.md CURLOPT_RANDOM_FILE.md CURLOPT_RANGE.md CURLOPT_READDATA.md CURLOPT_READFUNCTION.md CURLOPT_REDIR_PROTOCOLS.md CURLOPT_REDIR_PROTOCOLS_STR.md CURLOPT_REFERER.md CURLOPT_REQUEST_TARGET.md CURLOPT_RESOLVE.md CURLOPT_RESOLVER_START_DATA.md CURLOPT_RESOLVER_START_FUNCTION.md CURLOPT_RESUME_FROM.md CURLOPT_RESUME_FROM_LARGE.md CURLOPT_RTSP_CLIENT_CSEQ.md CURLOPT_RTSP_REQUEST.md CURLOPT_RTSP_SERVER_CSEQ.md CURLOPT_RTSP_SESSION_ID.md CURLOPT_RTSP_STREAM_URI.md CURLOPT_RTSP_TRANSPORT.md CURLOPT_SASL_AUTHZID.md CURLOPT_SASL_IR.md CURLOPT_SEEKDATA.md CURLOPT_SEEKFUNCTION.md CURLOPT_SERVER_RESPONSE_TIMEOUT.md CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md CURLOPT_SERVICE_NAME.md CURLOPT_SHARE.md CURLOPT_SOCKOPTDATA.md CURLOPT_SOCKOPTFUNCTION.md CURLOPT_SOCKS5_AUTH.md CURLOPT_SOCKS5_GSSAPI_NEC.md CURLOPT_SOCKS5_GSSAPI_SERVICE.md CURLOPT_SSH_AUTH_TYPES.md CURLOPT_SSH_COMPRESSION.md CURLOPT_SSH_HOSTKEYDATA.md CURLOPT_SSH_HOSTKEYFUNCTION.md CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md CURLOPT_SSH_KEYDATA.md CURLOPT_SSH_KEYFUNCTION.md CURLOPT_SSH_KNOWNHOSTS.md CURLOPT_SSH_PRIVATE_KEYFILE.md CURLOPT_SSH_PUBLIC_KEYFILE.md CURLOPT_SSLCERT.md CURLOPT_SSLCERTTYPE.md CURLOPT_SSLCERT_BLOB.md CURLOPT_SSLENGINE.md CURLOPT_SSLENGINE_DEFAULT.md CURLOPT_SSLKEY.md CURLOPT_SSLKEYTYPE.md CURLOPT_SSLKEY_BLOB.md CURLOPT_SSLVERSION.md CURLOPT_SSL_CIPHER_LIST.md CURLOPT_SSL_CTX_DATA.md CURLOPT_SSL_CTX_FUNCTION.md CURLOPT_SSL_EC_CURVES.md CURLOPT_SSL_ENABLE_ALPN.md CURLOPT_SSL_ENABLE_NPN.md CURLOPT_SSL_FALSESTART.md CURLOPT_SSL_OPTIONS.md CURLOPT_SSL_SESSIONID_CACHE.md CURLOPT_SSL_SIGNATURE_ALGORITHMS.md CURLOPT_SSL_VERIFYHOST.md CURLOPT_SSL_VERIFYPEER.md CURLOPT_SSL_VERIFYSTATUS.md CURLOPT_STDERR.md CURLOPT_STREAM_DEPENDS.md CURLOPT_STREAM_DEPENDS_E.md CURLOPT_STREAM_WEIGHT.md CURLOPT_SUPPRESS_CONNECT_HEADERS.md CURLOPT_TCP_FASTOPEN.md CURLOPT_TCP_KEEPALIVE.md CURLOPT_TCP_KEEPCNT.md CURLOPT_TCP_KEEPIDLE.md CURLOPT_TCP_KEEPINTVL.md CURLOPT_TCP_NODELAY.md CURLOPT_TELNETOPTIONS.md CURLOPT_TFTP_BLKSIZE.md CURLOPT_TFTP_NO_OPTIONS.md CURLOPT_TIMECONDITION.md CURLOPT_TIMEOUT.md CURLOPT_TIMEOUT_MS.md CURLOPT_TIMEVALUE.md CURLOPT_TIMEVALUE_LARGE.md CURLOPT_TLS13_CIPHERS.md CURLOPT_TLSAUTH_PASSWORD.md CURLOPT_TLSAUTH_TYPE.md CURLOPT_TLSAUTH_USERNAME.md CURLOPT_TRAILERDATA.md CURLOPT_TRAILERFUNCTION.md CURLOPT_TRANSFERTEXT.md CURLOPT_TRANSFER_ENCODING.md CURLOPT_UNIX_SOCKET_PATH.md CURLOPT_UNRESTRICTED_AUTH.md CURLOPT_UPKEEP_INTERVAL_MS.md CURLOPT_UPLOAD.md CURLOPT_UPLOAD_BUFFERSIZE.md CURLOPT_UPLOAD_FLAGS.md CURLOPT_URL.md CURLOPT_USERAGENT.md CURLOPT_USERNAME.md CURLOPT_USERPWD.md CURLOPT_USE_SSL.md CURLOPT_VERBOSE.md CURLOPT_WILDCARDMATCH.md CURLOPT_WRITEDATA.md CURLOPT_WRITEFUNCTION.md CURLOPT_WS_OPTIONS.md CURLOPT_XFERINFODATA.md CURLOPT_XFERINFOFUNCTION.md CURLOPT_XOAUTH2_BEARER.md CURLSHOPT_LOCKFUNC.md CURLSHOPT_SHARE.md CURLSHOPT_UNLOCKFUNC.md CURLSHOPT_UNSHARE.md CURLSHOPT_USERDATA.md Makefile.am Makefile.inc
.gitignore ABI.md CMakeLists.txt Makefile.am Makefile.inc curl_easy_cleanup.md curl_easy_duphandle.md curl_easy_escape.md curl_easy_getinfo.md curl_easy_header.md curl_easy_init.md curl_easy_nextheader.md curl_easy_option_by_id.md curl_easy_option_by_name.md curl_easy_option_next.md curl_easy_pause.md curl_easy_perform.md curl_easy_recv.md curl_easy_reset.md curl_easy_send.md curl_easy_setopt.md curl_easy_ssls_export.md curl_easy_ssls_import.md curl_easy_strerror.md curl_easy_unescape.md curl_easy_upkeep.md curl_escape.md curl_formadd.md curl_formfree.md curl_formget.md curl_free.md curl_getdate.md curl_getenv.md curl_global_cleanup.md curl_global_init.md curl_global_init_mem.md curl_global_sslset.md curl_global_trace.md curl_mime_addpart.md curl_mime_data.md curl_mime_data_cb.md curl_mime_encoder.md curl_mime_filedata.md curl_mime_filename.md curl_mime_free.md curl_mime_headers.md curl_mime_init.md curl_mime_name.md curl_mime_subparts.md curl_mime_type.md curl_mprintf.md curl_multi_add_handle.md curl_multi_assign.md curl_multi_cleanup.md curl_multi_fdset.md curl_multi_get_handles.md curl_multi_get_offt.md curl_multi_info_read.md curl_multi_init.md curl_multi_notify_disable.md curl_multi_notify_enable.md curl_multi_perform.md curl_multi_poll.md curl_multi_remove_handle.md curl_multi_setopt.md curl_multi_socket.md curl_multi_socket_action.md curl_multi_socket_all.md curl_multi_strerror.md curl_multi_timeout.md curl_multi_wait.md curl_multi_waitfds.md curl_multi_wakeup.md curl_pushheader_byname.md curl_pushheader_bynum.md curl_share_cleanup.md curl_share_init.md curl_share_setopt.md curl_share_strerror.md curl_slist_append.md curl_slist_free_all.md curl_strequal.md curl_strnequal.md curl_unescape.md curl_url.md curl_url_cleanup.md curl_url_dup.md curl_url_get.md curl_url_set.md curl_url_strerror.md curl_version.md curl_version_info.md curl_ws_meta.md curl_ws_recv.md curl_ws_send.md curl_ws_start_frame.md libcurl-easy.md libcurl-env-dbg.md libcurl-env.md libcurl-errors.md libcurl-multi.md libcurl-security.md libcurl-share.md libcurl-thread.md libcurl-tutorial.md libcurl-url.md libcurl-ws.md libcurl.m4 libcurl.md mksymbolsmanpage.pl symbols-in-versions symbols.pl
tests CI.md FILEFORMAT.md HTTP.md TEST-SUITE.md
.gitignore ALTSVC.md BINDINGS.md BUG-BOUNTY.md BUGS.md CIPHERS-TLS12.md CIPHERS.md CMakeLists.txt CODE_OF_CONDUCT.md CODE_REVIEW.md CONTRIBUTE.md CURL-DISABLE.md CURLDOWN.md DEPRECATE.md DISTROS.md EARLY-RELEASE.md ECH.md EXPERIMENTAL.md FAQ.md FEATURES.md GOVERNANCE.md HELP-US.md HISTORY.md HSTS.md HTTP-COOKIES.md HTTP3.md HTTPSRR.md INFRASTRUCTURE.md INSTALL-CMAKE.md INSTALL.md INTERNALS.md IPFS.md KNOWN_BUGS.md KNOWN_RISKS.md MAIL-ETIQUETTE.md MANUAL.md Makefile.am README.md RELEASE-PROCEDURE.md ROADMAP.md RUSTLS.md SECURITY-ADVISORY.md SPONSORS.md SSL-PROBLEMS.md SSLCERTS.md THANKS THANKS-filter TODO.md TheArtOfHttpScripting.md URL-SYNTAX.md VERIFY.md VERSIONS.md VULN-DISCLOSURE-POLICY.md curl-config.md mk-ca-bundle.md options-in-versions runtests.md testcurl.md wcurl.md
include
curl Makefile.am curl.h curlver.h easy.h header.h mprintf.h multi.h options.h stdcheaders.h system.h typecheck-gcc.h urlapi.h websockets.h
Makefile.am README.md
lib
curlx base64.c base64.h basename.c basename.h dynbuf.c dynbuf.h fopen.c fopen.h inet_ntop.c inet_ntop.h inet_pton.c inet_pton.h multibyte.c multibyte.h nonblock.c nonblock.h snprintf.c snprintf.h strcopy.c strcopy.h strdup.c strdup.h strerr.c strerr.h strparse.c strparse.h timediff.c timediff.h timeval.c timeval.h version_win32.c version_win32.h wait.c wait.h warnless.c warnless.h winapi.c winapi.h
vauth cleartext.c cram.c digest.c digest.h digest_sspi.c gsasl.c krb5_gssapi.c krb5_sspi.c ntlm.c ntlm_sspi.c oauth2.c spnego_gssapi.c spnego_sspi.c vauth.c vauth.h
vquic curl_ngtcp2.c curl_ngtcp2.h curl_quiche.c curl_quiche.h vquic-tls.c vquic-tls.h vquic.c vquic.h vquic_int.h
vssh libssh.c libssh2.c ssh.h vssh.c vssh.h
vtls apple.c apple.h cipher_suite.c cipher_suite.h gtls.c gtls.h hostcheck.c hostcheck.h keylog.c keylog.h mbedtls.c mbedtls.h openssl.c openssl.h rustls.c rustls.h schannel.c schannel.h schannel_int.h schannel_verify.c vtls.c vtls.h vtls_int.h vtls_scache.c vtls_scache.h vtls_spack.c vtls_spack.h wolfssl.c wolfssl.h x509asn1.c x509asn1.h
.gitignore CMakeLists.txt Makefile.am Makefile.inc Makefile.soname altsvc.c altsvc.h amigaos.c amigaos.h arpa_telnet.h asyn-ares.c asyn-base.c asyn-thrdd.c asyn.h bufq.c bufq.h bufref.c bufref.h cf-dns.c cf-dns.h cf-h1-proxy.c cf-h1-proxy.h cf-h2-proxy.c cf-h2-proxy.h cf-haproxy.c cf-haproxy.h cf-https-connect.c cf-https-connect.h cf-ip-happy.c cf-ip-happy.h cf-socket.c cf-socket.h cfilters.c cfilters.h config-mac.h config-os400.h config-riscos.h config-win32.h conncache.c conncache.h connect.c connect.h content_encoding.c content_encoding.h cookie.c cookie.h creds.c creds.h cshutdn.c cshutdn.h curl_addrinfo.c curl_addrinfo.h curl_config-cmake.h.in curl_ctype.h curl_endian.c curl_endian.h curl_fnmatch.c curl_fnmatch.h curl_fopen.c curl_fopen.h curl_get_line.c curl_get_line.h curl_gethostname.c curl_gethostname.h curl_gssapi.c curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memrchr.c curl_memrchr.h curl_ntlm_core.c curl_ntlm_core.h curl_printf.h curl_range.c curl_range.h curl_sasl.c curl_sasl.h curl_setup.h curl_sha256.h curl_sha512_256.c curl_sha512_256.h curl_share.c curl_share.h curl_sspi.c curl_sspi.h curl_threads.c curl_threads.h curl_trc.c curl_trc.h cw-out.c cw-out.h cw-pause.c cw-pause.h dict.c dict.h dllmain.c dnscache.c dnscache.h doh.c doh.h dynhds.c dynhds.h easy.c easy_lock.h easygetopt.c easyif.h easyoptions.c easyoptions.h escape.c escape.h fake_addrinfo.c fake_addrinfo.h file.c file.h fileinfo.c fileinfo.h formdata.c formdata.h ftp-int.h ftp.c ftp.h ftplistparser.c ftplistparser.h functypes.h getenv.c getinfo.c getinfo.h gopher.c gopher.h hash.c hash.h headers.c headers.h hmac.c hostip.c hostip.h hostip4.c hostip6.c hsts.c hsts.h http.c http.h http1.c http1.h http2.c http2.h http_aws_sigv4.c http_aws_sigv4.h http_chunks.c http_chunks.h http_digest.c http_digest.h http_negotiate.c http_negotiate.h http_ntlm.c http_ntlm.h http_proxy.c http_proxy.h httpsrr.c httpsrr.h idn.c idn.h if2ip.c if2ip.h imap.c imap.h ldap.c libcurl.def libcurl.rc libcurl.vers.in llist.c llist.h macos.c macos.h md4.c md5.c memdebug.c mime.c mime.h mprintf.c mqtt.c mqtt.h multi.c multi_ev.c multi_ev.h multi_ntfy.c multi_ntfy.h multihandle.h multiif.h netrc.c netrc.h noproxy.c noproxy.h openldap.c optiontable.pl parsedate.c parsedate.h peer.c peer.h pingpong.c pingpong.h pop3.c pop3.h progress.c progress.h protocol.c protocol.h psl.c psl.h rand.c rand.h ratelimit.c ratelimit.h request.c request.h rtsp.c rtsp.h select.c select.h sendf.c sendf.h setopt.c setopt.h setup-os400.h setup-vms.h setup-win32.h sha256.c sigpipe.h slist.c slist.h smb.c smb.h smtp.c smtp.h sockaddr.h socketpair.c socketpair.h socks.c socks.h socks_gssapi.c socks_sspi.c splay.c splay.h strcase.c strcase.h strequal.c strerror.c strerror.h system_win32.c system_win32.h telnet.c telnet.h tftp.c tftp.h thrdpool.c thrdpool.h thrdqueue.c thrdqueue.h transfer.c transfer.h uint-bset.c uint-bset.h uint-hash.c uint-hash.h uint-spbset.c uint-spbset.h uint-table.c uint-table.h url.c url.h urlapi-int.h urlapi.c urldata.h version.c ws.c ws.h
m4 .gitignore curl-amissl.m4 curl-apple-sectrust.m4 curl-compilers.m4 curl-confopts.m4 curl-functions.m4 curl-gnutls.m4 curl-mbedtls.m4 curl-openssl.m4 curl-override.m4 curl-reentrant.m4 curl-rustls.m4 curl-schannel.m4 curl-sysconfig.m4 curl-wolfssl.m4 xc-am-iface.m4 xc-cc-check.m4 xc-lt-iface.m4 xc-val-flgs.m4 zz40-xc-ovr.m4 zz50-xc-ovr.m4
projects
OS400
rpg-examples HEADERAPI HTTPPOST INMEMORY SIMPLE1 SIMPLE2 SMTPSRCMBR
.checksrc README.OS400 ccsidcurl.c ccsidcurl.h config400.default curl.cmd curl.inc.in curlcl.c curlmain.c initscript.sh make-docs.sh make-include.sh make-lib.sh make-src.sh make-tests.sh makefile.sh os400sys.c os400sys.h
Windows
tmpl .gitattributes README.txt curl-all.sln curl.sln curl.vcxproj curl.vcxproj.filters libcurl.sln libcurl.vcxproj libcurl.vcxproj.filters
.gitignore README.md generate.bat
vms Makefile.am backup_gnv_curl_src.com build_curl-config_script.com build_gnv_curl.com build_gnv_curl_pcsi_desc.com build_gnv_curl_pcsi_text.com build_gnv_curl_release_notes.com build_libcurl_pc.com build_vms.com clean_gnv_curl.com compare_curl_source.com config_h.com curl_crtl_init.c curl_gnv_build_steps.txt curl_release_note_start.txt curl_startup.com curlmsg.h curlmsg.msg curlmsg.sdl curlmsg_vms.h generate_config_vms_h_curl.com generate_vax_transfer.com gnv_conftest.c_first gnv_curl_configure.sh gnv_libcurl_symbols.opt gnv_link_curl.com macro32_exactcase.patch make_gnv_curl_install.sh make_pcsi_curl_kit_name.com pcsi_gnv_curl_file_list.txt pcsi_product_gnv_curl.com readme report_openssl_version.c setup_gnv_curl_build.com stage_curl_install.com vms_eco_level.h
Makefile.am README.md
scripts .checksrc CMakeLists.txt Makefile.am badwords badwords-all badwords.txt cd2cd cd2nroff cdall checksrc-all.pl checksrc.pl cmakelint.sh completion.pl contributors.sh contrithanks.sh coverage.sh delta dmaketgz extract-unit-protos firefox-db2pem.sh installcheck.sh maketgz managen mdlinkcheck mk-ca-bundle.pl mk-unity.pl nroff2cd perlcheck.sh pythonlint.sh randdisable release-notes.pl release-tools.sh schemetable.c singleuse.pl spacecheck.pl top-complexity top-length verify-release wcurl
src
toolx tool_time.c tool_time.h
.checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc config2setopts.c config2setopts.h curl.rc curlinfo.c mk-file-embed.pl mkhelp.pl slist_wc.c slist_wc.h terminal.c terminal.h tool_cb_dbg.c tool_cb_dbg.h tool_cb_hdr.c tool_cb_hdr.h tool_cb_prg.c tool_cb_prg.h tool_cb_rea.c tool_cb_rea.h tool_cb_see.c tool_cb_see.h tool_cb_soc.c tool_cb_soc.h tool_cb_wrt.c tool_cb_wrt.h tool_cfgable.c tool_cfgable.h tool_dirhie.c tool_dirhie.h tool_doswin.c tool_doswin.h tool_easysrc.c tool_easysrc.h tool_filetime.c tool_filetime.h tool_findfile.c tool_findfile.h tool_formparse.c tool_formparse.h tool_getparam.c tool_getparam.h tool_getpass.c tool_getpass.h tool_help.c tool_help.h tool_helpers.c tool_helpers.h tool_hugehelp.h tool_ipfs.c tool_ipfs.h tool_libinfo.c tool_libinfo.h tool_listhelp.c tool_main.c tool_main.h tool_msgs.c tool_msgs.h tool_operate.c tool_operate.h tool_operhlp.c tool_operhlp.h tool_paramhlp.c tool_paramhlp.h tool_parsecfg.c tool_parsecfg.h tool_progress.c tool_progress.h tool_sdecls.h tool_setopt.c tool_setopt.h tool_setup.h tool_ssls.c tool_ssls.h tool_stderr.c tool_stderr.h tool_urlglob.c tool_urlglob.h tool_util.c tool_util.h tool_version.h tool_vms.c tool_vms.h tool_writeout.c tool_writeout.h tool_writeout_json.c tool_writeout_json.h tool_xattr.c tool_xattr.h var.c var.h
tests
certs .gitignore CMakeLists.txt Makefile.am Makefile.inc genserv.pl srp-verifier-conf srp-verifier-db test-ca.cnf test-ca.prm test-client-cert.prm test-client-eku-only.prm test-localhost-san-first.prm test-localhost-san-last.prm test-localhost.nn.prm test-localhost.prm test-localhost0h.prm
cmake CMakeLists.txt test.c test.cpp test.sh
data .gitignore DISABLED Makefile.am data-xml1 data1400.c data1401.c data1402.c data1403.c data1404.c data1405.c data1406.c data1407.c data1420.c data1461.txt data1463.txt data1465.c data1481.c data1705-1.md data1705-2.md data1705-3.md data1705-4.md data1705-stdout.1 data1706-1.md data1706-2.md data1706-3.md data1706-4.md data1706-stdout.txt data320.html test1 test10 test100 test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 test1008 test1009 test101 test1010 test1011 test1012 test1013 test1014 test1015 test1016 test1017 test1018 test1019 test102 test1020 test1021 test1022 test1023 test1024 test1025 test1026 test1027 test1028 test1029 test103 test1030 test1031 test1032 test1033 test1034 test1035 test1036 test1037 test1038 test1039 test104 test1040 test1041 test1042 test1043 test1044 test1045 test1046 test1047 test1048 test1049 test105 test1050 test1051 test1052 test1053 test1054 test1055 test1056 test1057 test1058 test1059 test106 test1060 test1061 test1062 test1063 test1064 test1065 test1066 test1067 test1068 test1069 test107 test1070 test1071 test1072 test1073 test1074 test1075 test1076 test1077 test1078 test1079 test108 test1080 test1081 test1082 test1083 test1084 test1085 test1086 test1087 test1088 test1089 test109 test1090 test1091 test1092 test1093 test1094 test1095 test1096 test1097 test1098 test1099 test11 test110 test1100 test1101 test1102 test1103 test1104 test1105 test1106 test1107 test1108 test1109 test111 test1110 test1111 test1112 test1113 test1114 test1115 test1116 test1117 test1118 test1119 test112 test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 test1128 test1129 test113 test1130 test1131 test1132 test1133 test1134 test1135 test1136 test1137 test1138 test1139 test114 test1140 test1141 test1142 test1143 test1144 test1145 test1146 test1147 test1148 test1149 test115 test1150 test1151 test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 test116 test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 test1168 test1169 test117 test1170 test1171 test1172 test1173 test1174 test1175 test1176 test1177 test1178 test1179 test118 test1180 test1181 test1182 test1183 test1184 test1185 test1186 test1187 test1188 test1189 test119 test1190 test1191 test1192 test1193 test1194 test1195 test1196 test1197 test1198 test1199 test12 test120 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 test1208 test1209 test121 test1210 test1211 test1212 test1213 test1214 test1215 test1216 test1217 test1218 test1219 test122 test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 test1228 test1229 test123 test1230 test1231 test1232 test1233 test1234 test1235 test1236 test1237 test1238 test1239 test124 test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 test1248 test1249 test125 test1250 test1251 test1252 test1253 test1254 test1255 test1256 test1257 test1258 test1259 test126 test1260 test1261 test1262 test1263 test1264 test1265 test1266 test1267 test1268 test1269 test127 test1270 test1271 test1272 test1273 test1274 test1275 test1276 test1277 test1278 test1279 test128 test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 test1288 test1289 test129 test1290 test1291 test1292 test1293 test1294 test1295 test1296 test1297 test1298 test1299 test13 test130 test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 test1308 test1309 test131 test1310 test1311 test1312 test1313 test1314 test1315 test1316 test1317 test1318 test1319 test132 test1320 test1321 test1322 test1323 test1324 test1325 test1326 test1327 test1328 test1329 test133 test1330 test1331 test1332 test1333 test1334 test1335 test1336 test1337 test1338 test1339 test134 test1340 test1341 test1342 test1343 test1344 test1345 test1346 test1347 test1348 test1349 test135 test1350 test1351 test1352 test1353 test1354 test1355 test1356 test1357 test1358 test1359 test136 test1360 test1361 test1362 test1363 test1364 test1365 test1366 test1367 test1368 test1369 test137 test1370 test1371 test1372 test1373 test1374 test1375 test1376 test1377 test1378 test1379 test138 test1380 test1381 test1382 test1383 test1384 test1385 test1386 test1387 test1388 test1389 test139 test1390 test1391 test1392 test1393 test1394 test1395 test1396 test1397 test1398 test1399 test14 test140 test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 test1408 test1409 test141 test1410 test1411 test1412 test1413 test1414 test1415 test1416 test1417 test1418 test1419 test142 test1420 test1421 test1422 test1423 test1424 test1425 test1426 test1427 test1428 test1429 test143 test1430 test1431 test1432 test1433 test1434 test1435 test1436 test1437 test1438 test1439 test144 test1440 test1441 test1442 test1443 test1444 test1445 test1446 test1447 test1448 test1449 test145 test1450 test1451 test1452 test1453 test1454 test1455 test1456 test1457 test1458 test1459 test146 test1460 test1461 test1462 test1463 test1464 test1465 test1466 test1467 test1468 test1469 test147 test1470 test1471 test1472 test1473 test1474 test1475 test1476 test1477 test1478 test1479 test148 test1480 test1481 test1482 test1483 test1484 test1485 test1486 test1487 test1488 test1489 test149 test1490 test1491 test1492 test1493 test1494 test1495 test1496 test1497 test1498 test1499 test15 test150 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 test1508 test1509 test151 test1510 test1511 test1512 test1513 test1514 test1515 test1516 test1517 test1518 test1519 test152 test1520 test1521 test1522 test1523 test1524 test1525 test1526 test1527 test1528 test1529 test153 test1530 test1531 test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 test154 test1540 test1541 test1542 test1543 test1544 test1545 test1546 test1547 test1548 test1549 test155 test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 test1558 test1559 test156 test1560 test1561 test1562 test1563 test1564 test1565 test1566 test1567 test1568 test1569 test157 test1570 test1571 test1572 test1573 test1574 test1575 test1576 test1577 test1578 test1579 test158 test1580 test1581 test1582 test1583 test1584 test1585 test1586 test1587 test1588 test1589 test159 test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 test1598 test1599 test16 test160 test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 test1608 test1609 test161 test1610 test1611 test1612 test1613 test1614 test1615 test1616 test1617 test1618 test1619 test162 test1620 test1621 test1622 test1623 test1624 test1625 test1626 test1627 test1628 test1629 test163 test1630 test1631 test1632 test1633 test1634 test1635 test1636 test1637 test1638 test1639 test164 test1640 test1641 test1642 test1643 test1644 test1645 test165 test1650 test1651 test1652 test1653 test1654 test1655 test1656 test1657 test1658 test1659 test166 test1660 test1661 test1662 test1663 test1664 test1665 test1666 test1667 test1668 test1669 test167 test1670 test1671 test1672 test1673 test1674 test1675 test1676 test168 test1680 test1681 test1682 test1683 test1684 test1685 test169 test17 test170 test1700 test1701 test1702 test1703 test1704 test1705 test1706 test1707 test1708 test1709 test171 test1710 test1711 test1712 test1713 test1714 test1715 test172 test1720 test1721 test173 test174 test175 test176 test177 test178 test179 test18 test180 test1800 test1801 test1802 test181 test182 test183 test184 test1847 test1848 test1849 test185 test1850 test1851 test186 test187 test188 test189 test19 test190 test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 test1908 test1909 test191 test1910 test1911 test1912 test1913 test1914 test1915 test1916 test1917 test1918 test1919 test192 test1920 test1921 test193 test1933 test1934 test1935 test1936 test1937 test1938 test1939 test194 test1940 test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 test195 test1955 test1956 test1957 test1958 test1959 test196 test1960 test1964 test1965 test1966 test197 test1970 test1971 test1972 test1973 test1974 test1975 test1976 test1977 test1978 test1979 test198 test1980 test1981 test1982 test1983 test1984 test199 test2 test20 test200 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 test2008 test2009 test201 test2010 test2011 test2012 test2013 test2014 test202 test2023 test2024 test2025 test2026 test2027 test2028 test2029 test203 test2030 test2031 test2032 test2033 test2034 test2035 test2037 test2038 test2039 test204 test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 test2048 test2049 test205 test2050 test2051 test2052 test2053 test2054 test2055 test2056 test2057 test2058 test2059 test206 test2060 test2061 test2062 test2063 test2064 test2065 test2066 test2067 test2068 test2069 test207 test2070 test2071 test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 test208 test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 test2088 test2089 test209 test2090 test2091 test2092 test21 test210 test2100 test2101 test2102 test2103 test2104 test211 test212 test213 test214 test215 test216 test217 test218 test219 test22 test220 test2200 test2201 test2202 test2203 test2204 test2205 test2206 test2207 test221 test222 test223 test224 test225 test226 test227 test228 test229 test23 test230 test2300 test2301 test2302 test2303 test2304 test2306 test2307 test2308 test2309 test231 test232 test233 test234 test235 test236 test237 test238 test239 test24 test240 test2400 test2401 test2402 test2403 test2404 test2405 test2406 test2407 test2408 test2409 test241 test2410 test2411 test242 test243 test244 test245 test246 test247 test248 test249 test25 test250 test2500 test2501 test2502 test2503 test2504 test2505 test2506 test251 test252 test253 test254 test255 test256 test257 test258 test259 test26 test260 test2600 test2601 test2602 test2603 test2604 test2605 test261 test262 test263 test264 test265 test266 test267 test268 test269 test27 test270 test2700 test2701 test2702 test2703 test2704 test2705 test2706 test2707 test2708 test2709 test271 test2710 test2711 test2712 test2713 test2714 test2715 test2716 test2717 test2718 test2719 test272 test2720 test2721 test2722 test2723 test273 test274 test275 test276 test277 test278 test279 test28 test280 test281 test282 test283 test284 test285 test286 test287 test288 test289 test29 test290 test291 test292 test293 test294 test295 test296 test297 test298 test299 test3 test30 test300 test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 test3008 test3009 test301 test3010 test3011 test3012 test3013 test3014 test3015 test3016 test3017 test3018 test3019 test302 test3020 test3021 test3022 test3023 test3024 test3025 test3026 test3027 test3028 test3029 test303 test3030 test3031 test3032 test3033 test3034 test3035 test3036 test304 test305 test306 test307 test308 test309 test31 test310 test3100 test3101 test3102 test3103 test3104 test3105 test3106 test311 test312 test313 test314 test315 test316 test317 test318 test319 test32 test320 test3200 test3201 test3202 test3203 test3204 test3205 test3206 test3207 test3208 test3209 test321 test3210 test3211 test3212 test3213 test3214 test3215 test3216 test3217 test3218 test3219 test322 test3220 test323 test324 test325 test326 test327 test328 test329 test33 test330 test3300 test3301 test3302 test331 test332 test333 test334 test335 test336 test337 test338 test339 test34 test340 test341 test342 test343 test344 test345 test346 test347 test348 test349 test35 test350 test351 test352 test353 test354 test355 test356 test357 test358 test359 test36 test360 test361 test362 test363 test364 test365 test366 test367 test368 test369 test37 test370 test371 test372 test373 test374 test375 test376 test378 test379 test38 test380 test381 test383 test384 test385 test386 test387 test388 test389 test39 test390 test391 test392 test393 test394 test395 test396 test397 test398 test399 test4 test40 test400 test4000 test4001 test401 test402 test403 test404 test405 test406 test407 test408 test409 test41 test410 test411 test412 test413 test414 test415 test416 test417 test418 test419 test42 test420 test421 test422 test423 test424 test425 test426 test427 test428 test429 test43 test430 test431 test432 test433 test434 test435 test436 test437 test438 test439 test44 test440 test441 test442 test443 test444 test445 test446 test447 test448 test449 test45 test450 test451 test452 test453 test454 test455 test456 test457 test458 test459 test46 test460 test461 test462 test463 test467 test468 test469 test47 test470 test471 test472 test473 test474 test475 test476 test477 test478 test479 test48 test480 test481 test482 test483 test484 test485 test486 test487 test488 test489 test49 test490 test491 test492 test493 test494 test495 test496 test497 test498 test499 test5 test50 test500 test501 test502 test503 test504 test505 test506 test507 test508 test509 test51 test510 test511 test512 test513 test514 test515 test516 test517 test518 test519 test52 test520 test521 test522 test523 test524 test525 test526 test527 test528 test529 test53 test530 test531 test532 test533 test534 test535 test536 test537 test538 test539 test54 test540 test541 test542 test543 test544 test545 test546 test547 test548 test549 test55 test550 test551 test552 test553 test554 test555 test556 test557 test558 test559 test56 test560 test561 test562 test563 test564 test565 test566 test567 test568 test569 test57 test570 test571 test572 test573 test574 test575 test576 test577 test578 test579 test58 test580 test581 test582 test583 test584 test585 test586 test587 test588 test589 test59 test590 test591 test592 test593 test594 test595 test596 test597 test598 test599 test6 test60 test600 test601 test602 test603 test604 test605 test606 test607 test608 test609 test61 test610 test611 test612 test613 test614 test615 test616 test617 test618 test619 test62 test620 test621 test622 test623 test624 test625 test626 test627 test628 test629 test63 test630 test631 test632 test633 test634 test635 test636 test637 test638 test639 test64 test640 test641 test642 test643 test644 test645 test646 test647 test648 test649 test65 test650 test651 test652 test653 test654 test655 test656 test658 test659 test66 test660 test661 test662 test663 test664 test665 test666 test667 test668 test669 test67 test670 test671 test672 test673 test674 test675 test676 test677 test678 test679 test68 test680 test681 test682 test683 test684 test685 test686 test687 test688 test689 test69 test690 test691 test692 test693 test694 test695 test696 test697 test698 test699 test7 test70 test700 test701 test702 test703 test704 test705 test706 test707 test708 test709 test71 test710 test711 test712 test713 test714 test715 test716 test717 test718 test719 test72 test720 test721 test722 test723 test724 test725 test726 test727 test728 test729 test73 test730 test731 test732 test733 test734 test735 test736 test737 test738 test739 test74 test740 test741 test742 test743 test744 test745 test746 test747 test748 test749 test75 test750 test751 test752 test753 test754 test755 test756 test757 test758 test759 test76 test760 test761 test762 test763 test764 test765 test766 test767 test768 test769 test77 test770 test771 test772 test773 test774 test775 test776 test777 test778 test779 test78 test780 test781 test782 test783 test784 test785 test786 test787 test788 test789 test79 test790 test791 test792 test793 test794 test795 test796 test797 test798 test799 test8 test80 test800 test801 test802 test803 test804 test805 test806 test807 test808 test809 test81 test810 test811 test812 test813 test814 test815 test816 test817 test818 test819 test82 test820 test821 test822 test823 test824 test825 test826 test827 test828 test829 test83 test830 test831 test832 test833 test834 test835 test836 test837 test838 test839 test84 test840 test841 test842 test843 test844 test845 test846 test847 test848 test849 test85 test850 test851 test852 test853 test854 test855 test856 test857 test858 test859 test86 test860 test861 test862 test863 test864 test865 test866 test867 test868 test869 test87 test870 test871 test872 test873 test874 test875 test876 test877 test878 test879 test88 test880 test881 test882 test883 test884 test885 test886 test887 test888 test889 test89 test890 test891 test892 test893 test894 test895 test896 test897 test898 test899 test9 test90 test900 test901 test902 test903 test904 test905 test906 test907 test908 test909 test91 test910 test911 test912 test913 test914 test915 test916 test917 test918 test919 test92 test920 test921 test922 test923 test924 test925 test926 test927 test928 test929 test93 test930 test931 test932 test933 test934 test935 test936 test937 test938 test939 test94 test940 test941 test942 test943 test944 test945 test946 test947 test948 test949 test95 test950 test951 test952 test953 test954 test955 test956 test957 test958 test959 test96 test960 test961 test962 test963 test964 test965 test966 test967 test968 test969 test97 test970 test971 test972 test973 test974 test975 test976 test977 test978 test979 test98 test980 test981 test982 test983 test984 test985 test986 test987 test988 test989 test99 test990 test991 test992 test993 test994 test995 test996 test997 test998 test999
http
testenv
mod_curltest .gitignore mod_curltest.c
__init__.py caddy.py certs.py client.py curl.py dante.py dnsd.py env.py httpd.py nghttpx.py ports.py sshd.py vsftpd.py ws_echo_server.py
.gitignore CMakeLists.txt Makefile.am config.ini.in conftest.py requirements.txt scorecard.py test_01_basic.py test_02_download.py test_03_goaway.py test_04_stuttered.py test_05_errors.py test_06_eyeballs.py test_07_upload.py test_08_caddy.py test_09_push.py test_10_proxy.py test_11_unix.py test_12_reuse.py test_13_proxy_auth.py test_14_auth.py test_15_tracing.py test_16_info.py test_17_ssl_use.py test_18_methods.py test_19_shutdown.py test_20_websockets.py test_21_resolve.py test_22_httpsrr.py test_30_vsftpd.py test_31_vsftpds.py test_32_ftps_vsftpd.py test_40_socks.py test_50_scp.py test_51_sftp.py
libtest .gitignore CMakeLists.txt Makefile.am Makefile.inc cli_ftp_upload.c cli_h2_pausing.c cli_h2_serverpush.c cli_h2_upgrade_extreme.c cli_hx_download.c cli_hx_upload.c cli_tls_session_reuse.c cli_upload_pausing.c cli_ws_data.c cli_ws_pingpong.c first.c first.h lib1156.c lib1301.c lib1308.c lib1485.c lib1500.c lib1501.c lib1502.c lib1506.c lib1507.c lib1508.c lib1509.c lib1510.c lib1511.c lib1512.c lib1513.c lib1514.c lib1515.c lib1517.c lib1518.c lib1520.c lib1522.c lib1523.c lib1525.c lib1526.c lib1527.c lib1528.c lib1529.c lib1530.c lib1531.c lib1532.c lib1533.c lib1534.c lib1535.c lib1536.c lib1537.c lib1538.c lib1540.c lib1541.c lib1542.c lib1545.c lib1549.c lib1550.c lib1551.c lib1552.c lib1553.c lib1554.c lib1555.c lib1556.c lib1557.c lib1558.c lib1559.c lib1560.c lib1564.c lib1565.c lib1567.c lib1568.c lib1569.c lib1571.c lib1576.c lib1582.c lib1587.c lib1588.c lib1589.c lib1591.c lib1592.c lib1593.c lib1594.c lib1597.c lib1598.c lib1599.c lib1662.c lib1900.c lib1901.c lib1902.c lib1903.c lib1905.c lib1906.c lib1907.c lib1908.c lib1910.c lib1911.c lib1912.c lib1913.c lib1915.c lib1916.c lib1918.c lib1919.c lib1920.c lib1921.c lib1933.c lib1934.c lib1935.c lib1936.c lib1937.c lib1938.c lib1939.c lib1940.c lib1945.c lib1947.c lib1948.c lib1955.c lib1956.c lib1957.c lib1958.c lib1959.c lib1960.c lib1964.c lib1965.c lib1970.c lib1971.c lib1972.c lib1973.c lib1974.c lib1975.c lib1977.c lib1978.c lib2023.c lib2032.c lib2082.c lib2301.c lib2302.c lib2304.c lib2306.c lib2308.c lib2309.c lib2402.c lib2404.c lib2405.c lib2502.c lib2504.c lib2505.c lib2506.c lib2700.c lib3010.c lib3025.c lib3026.c lib3027.c lib3033.c lib3034.c lib3100.c lib3101.c lib3102.c lib3103.c lib3104.c lib3105.c lib3207.c lib3208.c lib500.c lib501.c lib502.c lib503.c lib504.c lib505.c lib506.c lib507.c lib508.c lib509.c lib510.c lib511.c lib512.c lib513.c lib514.c lib515.c lib516.c lib517.c lib518.c lib519.c lib520.c lib521.c lib523.c lib524.c lib525.c lib526.c lib530.c lib533.c lib536.c lib537.c lib539.c lib540.c lib541.c lib542.c lib543.c lib544.c lib547.c lib549.c lib552.c lib553.c lib554.c lib555.c lib556.c lib557.c lib558.c lib559.c lib560.c lib562.c lib564.c lib566.c lib567.c lib568.c lib569.c lib570.c lib571.c lib572.c lib573.c lib574.c lib575.c lib576.c lib578.c lib579.c lib582.c lib583.c lib586.c lib589.c lib590.c lib591.c lib597.c lib598.c lib599.c lib643.c lib650.c lib651.c lib652.c lib653.c lib654.c lib655.c lib658.c lib659.c lib661.c lib666.c lib667.c lib668.c lib670.c lib674.c lib676.c lib677.c lib678.c lib694.c lib695.c lib751.c lib753.c lib757.c lib758.c lib766.c memptr.c mk-lib1521.pl test1013.pl test1022.pl test307.pl test610.pl test613.pl testtrace.c testtrace.h testutil.c testutil.h unitcheck.h
server .checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc dnsd.c first.c first.h getpart.c mqttd.c resolve.c rtspd.c sockfilt.c socksd.c sws.c tftpd.c util.c
tunit .gitignore CMakeLists.txt Makefile.am Makefile.inc README.md tool1394.c tool1604.c tool1621.c tool1622.c tool1623.c tool1720.c
unit .gitignore CMakeLists.txt Makefile.am Makefile.inc README.md unit1300.c unit1302.c unit1303.c unit1304.c unit1305.c unit1307.c unit1309.c unit1323.c unit1330.c unit1395.c unit1396.c unit1397.c unit1398.c unit1399.c unit1600.c unit1601.c unit1602.c unit1603.c unit1605.c unit1606.c unit1607.c unit1608.c unit1609.c unit1610.c unit1611.c unit1612.c unit1614.c unit1615.c unit1616.c unit1620.c unit1625.c unit1626.c unit1627.c unit1636.c unit1650.c unit1651.c unit1652.c unit1653.c unit1654.c unit1655.c unit1656.c unit1657.c unit1658.c unit1660.c unit1661.c unit1663.c unit1664.c unit1666.c unit1667.c unit1668.c unit1669.c unit1674.c unit1675.c unit1676.c unit1979.c unit1980.c unit2600.c unit2601.c unit2602.c unit2603.c unit2604.c unit2605.c unit3200.c unit3205.c unit3211.c unit3212.c unit3213.c unit3214.c unit3216.c unit3219.c unit3300.c unit3301.c unit3302.c
.gitignore CMakeLists.txt Makefile.am allversions.pm appveyor.pm azure.pm config.in configurehelp.pm.in devtest.pl dictserver.py directories.pm ech_combos.py ech_tests.sh ftpserver.pl getpart.pm globalconfig.pm http-server.pl http2-server.pl http3-server.pl memanalyze.pl memanalyzer.pm negtelnetserver.py nghttpx.conf pathhelp.pm processhelp.pm requirements.txt rtspserver.pl runner.pm runtests.pl secureserver.pl serverhelp.pm servers.pm smbserver.py sshhelp.pm sshserver.pl test1119.pl test1135.pl test1139.pl test1140.pl test1165.pl test1167.pl test1173.pl test1175.pl test1177.pl test1222.pl test1275.pl test1276.pl test1477.pl test1486.pl test1488.pl test1544.pl test1707.pl test745.pl test971.pl testcurl.pl testutil.pm tftpserver.pl util.py valgrind.pm valgrind.supp
.clang-tidy.yml .dir-locals.el .editorconfig .git-blame-ignore-revs .gitattributes .gitignore .mailmap CHANGES.md CMakeLists.txt COPYING Dockerfile GIT-INFO.md Makefile.am README README.md RELEASE-NOTES REUSE.toml SECURITY.md acinclude.m4 appveyor.sh appveyor.yml configure.ac curl-config.in libcurl.pc.in renovate.json
examples .env config.ini crypto_test.lua env_test.lua fs_example.lua http_server.lua https_test.lua ini_example.lua json.lua log.lua path_fs_example.lua process_example.lua request_download.lua request_test.lua run_all.lua sqlite_example.lua sqlite_http_template.lua stash_test.lua template_test.lua timer.lua websocket.lua
iniparser
.github
ISSUE_TEMPLATE config.yml
workflows disable-pull-requests.yml trigger-gitlab-ci.yml
cmake JoinPaths.cmake config.cmake.in pc.in
example iniexample.c iniwrite.c parse.c twisted-errors.ini twisted-genhuge.py twisted-ofkey.ini twisted-ofval.ini twisted.ini
src dictionary.c dictionary.h iniparser.c iniparser.h
test
ressources
bad_ini ends_well.ini twisted-errors.ini twisted-ofkey.ini twisted-ofval.ini
good_ini empty.ini spaced.ini spaced2.ini twisted.ini
gruezi.ini old.ini quotes.ini utf8.ini
CMakeLists.txt test_dictionary.c test_iniparser.c unity-config.yml unity_config.h
.cmake-format.py .gitignore .gitlab-ci.yml .gitmessage .travis.yml AUTHORS CMakeLists.txt FAQ-en.md FAQ-zhcn.md INSTALL LICENSE README.md compile_commands.json
jinjac
example CMakeLists.txt example.c
jinjac_test_app CMakeLists.txt jinjac_test_app.c
libjinjac
include jinjac.h
src CMakeLists.txt ast.c ast.h block_statement.c block_statement.h buffer.c buffer.h buildin.c buildin.h common.h convert.c convert.h flex_decl.h jfunction.c jfunction.h jinja_expression.l jinja_expression.y jinjac_parse.c jinjac_parse.h jinjac_stream.c jinjac_stream.h jlist.c jlist.h jobject.c jobject.h parameter.c parameter.h str_obj.c str_obj.h trace.c trace.h
CMakeLists.txt
test .gitignore CMakeLists.txt autotest.rb test_01.expected test_01.jinja test_01b.expected test_01b.jinja test_01c.expected test_01c.jinja test_01d.expected test_01d.jinja test_02.expected test_02.jinja test_03.expected test_03.jinja test_04.expected test_04.jinja test_05.expected test_05.jinja test_06.expected test_06.jinja test_07.expected test_07.jinja test_08.expected test_08.jinja test_08b.expected test_08b.jinja test_09.expected test_09.jinja test_10.expected test_10.jinja test_11.expected test_11.jinja test_12.expected test_12.jinja test_13.expected test_13.jinja test_14.expected test_14.jinja test_15.expected test_15.jinja test_16.expected test_16.jinja test_17.expected test_17.jinja test_18.expected test_18.jinja test_18b.expected test_18b.jinja test_18c.expected test_18c.jinja test_19.expected test_19.jinja test_19b.expected test_19b.jinja test_19c.expected test_19c.jinja test_19d.expected test_19d.jinja test_19e.expected test_19e.jinja test_19f.expected test_19f.jinja test_20.expected test_20.jinja test_21.expected test_21.jinja test_22.expected test_22.jinja test_22a.expected test_22a.jinja test_22b.expected test_22b.jinja test_23.expected test_23.jinja test_24.expected test_24.jinja
.gitignore CMakeLists.txt LICENSE.txt README.md build_coverage.sh build_debug.sh build_release.sh cppcheck_analysis.sh
libev Changes LICENSE Makefile Makefile.am Makefile.in README Symbols.ev Symbols.event aclocal.m4 autogen.sh compile config.guess config.h config.h.in config.status config.sub configure configure.ac depcomp ev++.h ev.3 ev.c ev.h ev.pod ev_epoll.c ev_kqueue.c ev_poll.c ev_port.c ev_select.c ev_vars.h ev_win32.c ev_wrap.h event.c event.h install-sh libev.m4 libtool ltmain.sh missing mkinstalldirs stamp-h1
luajit
doc
img contact.png
bluequad-print.css bluequad.css contact.html ext_buffer.html ext_c_api.html ext_ffi.html ext_ffi_api.html ext_ffi_semantics.html ext_ffi_tutorial.html ext_jit.html ext_profiler.html extensions.html install.html luajit.html running.html
dynasm dasm_arm.h dasm_arm.lua dasm_arm64.h dasm_arm64.lua dasm_mips.h dasm_mips.lua dasm_mips64.lua dasm_ppc.h dasm_ppc.lua dasm_proto.h dasm_x64.lua dasm_x86.h dasm_x86.lua dynasm.lua
etc luajit.1 luajit.pc
src
host .gitignore README buildvm.c buildvm.h buildvm_asm.c buildvm_fold.c buildvm_lib.c buildvm_libbc.h buildvm_peobj.c genlibbc.lua genminilua.lua genversion.lua minilua.c
jit .gitignore bc.lua bcsave.lua dis_arm.lua dis_arm64.lua dis_arm64be.lua dis_mips.lua dis_mips64.lua dis_mips64el.lua dis_mips64r6.lua dis_mips64r6el.lua dis_mipsel.lua dis_ppc.lua dis_x64.lua dis_x86.lua dump.lua p.lua v.lua zone.lua
.gitignore Makefile Makefile.dep lauxlib.h lib_aux.c lib_base.c lib_bit.c lib_buffer.c lib_debug.c lib_ffi.c lib_init.c lib_io.c lib_jit.c lib_math.c lib_os.c lib_package.c lib_string.c lib_table.c lj_alloc.c lj_alloc.h lj_api.c lj_arch.h lj_asm.c lj_asm.h lj_asm_arm.h lj_asm_arm64.h lj_asm_mips.h lj_asm_ppc.h lj_asm_x86.h lj_assert.c lj_bc.c lj_bc.h lj_bcdump.h lj_bcread.c lj_bcwrite.c lj_buf.c lj_buf.h lj_carith.c lj_carith.h lj_ccall.c lj_ccall.h lj_ccallback.c lj_ccallback.h lj_cconv.c lj_cconv.h lj_cdata.c lj_cdata.h lj_char.c lj_char.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_crecord.c lj_crecord.h lj_ctype.c lj_ctype.h lj_debug.c lj_debug.h lj_def.h lj_dispatch.c lj_dispatch.h lj_emit_arm.h lj_emit_arm64.h lj_emit_mips.h lj_emit_ppc.h lj_emit_x86.h lj_err.c lj_err.h lj_errmsg.h lj_ff.h lj_ffrecord.c lj_ffrecord.h lj_frame.h lj_func.c lj_func.h lj_gc.c lj_gc.h lj_gdbjit.c lj_gdbjit.h lj_ir.c lj_ir.h lj_ircall.h lj_iropt.h lj_jit.h lj_lex.c lj_lex.h lj_lib.c lj_lib.h lj_load.c lj_mcode.c lj_mcode.h lj_meta.c lj_meta.h lj_obj.c lj_obj.h lj_opt_dce.c lj_opt_fold.c lj_opt_loop.c lj_opt_mem.c lj_opt_narrow.c lj_opt_sink.c lj_opt_split.c lj_parse.c lj_parse.h lj_prng.c lj_prng.h lj_profile.c lj_profile.h lj_record.c lj_record.h lj_serialize.c lj_serialize.h lj_snap.c lj_snap.h lj_state.c lj_state.h lj_str.c lj_str.h lj_strfmt.c lj_strfmt.h lj_strfmt_num.c lj_strscan.c lj_strscan.h lj_tab.c lj_tab.h lj_target.h lj_target_arm.h lj_target_arm64.h lj_target_mips.h lj_target_ppc.h lj_target_x86.h lj_trace.c lj_trace.h lj_traceerr.h lj_udata.c lj_udata.h lj_vm.h lj_vmevent.c lj_vmevent.h lj_vmmath.c ljamalg.c lua.h lua.hpp luaconf.h luajit.c luajit_rolling.h lualib.h msvcbuild.bat nxbuild.bat ps4build.bat ps5build.bat psvitabuild.bat vm_arm.dasc vm_arm64.dasc vm_mips.dasc vm_mips64.dasc vm_ppc.dasc vm_x64.dasc vm_x86.dasc xb1build.bat xedkbuild.bat
.gitattributes .gitignore .relver COPYRIGHT Makefile README
sqlite shell.c sqlite3.c sqlite3.h sqlite3ext.h
wolfssl
.github
ISSUE_TEMPLATE bug_report.yaml other.yaml
actions
install-apt-deps action.yml
scripts
zephyr-4.x external_libc.conf zephyr-test.sh
openssl-ech.sh tls-anvil-test.sh
workflows
disabled haproxy.yml hitch.yml hostap.yml
hostap-files
configs
07c9f183ea744ac04585fb6dd10220c75a5e2e74 hostapd.config tests wpa_supplicant.config
b607d2723e927a3446d89aed813f1aa6068186bb hostapd.config tests wpa_supplicant.config
hostap_2_10 extra.patch hostapd.config tests wpa_supplicant.config
Makefile README dbus-wpa_supplicant.conf
ada.yml arduino.yml async-examples.yml async.yml atecc608-sim.yml bind.yml cmake-autoconf.yml cmake.yml codespell.yml coverity-scan-fixes.yml cryptocb-only.yml curl.yml cyrus-sasl.yml disable-pk-algs.yml docker-Espressif.yml docker-OpenWrt.yml emnet-nonblock.yml fil-c.yml freertos-mem-track.yml gencertbuf.yml grpc.yml haproxy.yml hostap-vm.yml intelasm-c-fallback.yml ipmitool.yml jwt-cpp.yml krb5.yml libspdm.yml libssh2.yml libvncserver.yml linuxkm.yml macos-apple-native-cert-validation.yml mbedtls.sh mbedtls.yml membrowse-comment.yml membrowse-onboard.yml membrowse-report.yml memcached.sh memcached.yml mono.yml mosquitto.yml msmtp.yml msys2.yml multi-arch.yml multi-compiler.yml net-snmp.yml nginx.yml no-malloc.yml no-tls.yml nss.sh nss.yml ntp.yml ocsp.yml openldap.yml openssh.yml openssl-ech.yml opensslcoexist.yml openvpn.yml os-check.yml packaging.yml pam-ipmi.yml pq-all.yml pr-commit-check.yml psk.yml puf.yml python.yml rng-tools.yml rust-wrapper.yml se050-sim.yml smallStackSize.yml socat.yml softhsm.yml sssd.yml stm32-sim.yml stsafe-a120-sim.yml stunnel.yml symbol-prefixes.yml threadx.yml tls-anvil.yml trackmemory.yml watcomc.yml win-csharp-test.yml wolfCrypt-Wconversion.yml wolfboot-integration.yml wolfsm.yml xcode.yml zephyr-4.x.yml zephyr.yml
PULL_REQUEST_TEMPLATE.md SECURITY.md membrowse-targets.json
Docker
OpenWrt Dockerfile README.md runTests.sh
packaging
debian Dockerfile
fedora Dockerfile
wolfCLU Dockerfile README.md
yocto Dockerfile buildAndPush.sh
Dockerfile Dockerfile.cross-compiler README.md buildAndPush.sh include.am run.sh
IDE
ARDUINO
sketches
wolfssl_client README.md
wolfssl_server README.md
wolfssl_version README.md
README.md
Arduino_README_prepend.md README.md include.am keywords.txt library.properties.template wolfssl-arduino.cpp wolfssl-arduino.sh wolfssl.h
AURIX Cpu0_Main.c README.md include.am user_settings.h wolf_main.c
Android Android.bp README.md include.am user_settings.h
CRYPTOCELL README.md include.am main.c user_settings.h
CSBENCH include.am user_settings.h
ECLIPSE
DEOS
deos_wolfssl .options
README.md deos_malloc.c include.am tls_wolfssl.c tls_wolfssl.h user_settings.h
MICRIUM README.md client_wolfssl.c client_wolfssl.h include.am server_wolfssl.c server_wolfssl.h user_settings.h wolfsslRunTests.c
RTTHREAD README.md include.am user_settings.h wolfssl_test.c
SIFIVE README.md include.am
Espressif
ESP-IDF
examples
template
VisualGDB wolfssl_template_IDF_v5.1_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp8266
wolfssl_benchmark
VisualGDB wolfssl_benchmark_IDF_v4.4_ESP32.sln wolfssl_benchmark_IDF_v4.4_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32.sln wolfssl_benchmark_IDF_v5_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32C3.sln wolfssl_benchmark_IDF_v5_ESP32C3.vgdbproj wolfssl_benchmark_IDF_v5_ESP32S3.sln wolfssl_benchmark_IDF_v5_ESP32S3.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp8266
wolfssl_client
VisualGDB README.md wolfssl_client_IDF_v5_ESP32.sln wolfssl_client_IDF_v5_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include client-tls.h main.h time_helper.h wifi_connect.h
CMakeLists.txt Kconfig.projbuild client-tls.c component.mk main.c time_helper.c wifi_connect.c
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_client_ESP8266.vgdbproj
wolfssl_server
VisualGDB README.md wolfssl_server_IDF_v5_ESP32.sln wolfssl_server_IDF_v5_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h server-tls.h time_helper.h wifi_connect.h
CMakeLists.txt Kconfig.projbuild component.mk main.c server-tls.c time_helper.c wifi_connect.c
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_server_ESP8266.vgdbproj
wolfssl_test
VisualGDB wolfssl_test-IDF_v5_ESP32.sln wolfssl_test-IDF_v5_ESP32.vgdbproj wolfssl_test-IDF_v5_ESP32C3.sln wolfssl_test-IDF_v5_ESP32C3.vgdbproj wolfssl_test-IDF_v5_ESP32C6.sln wolfssl_test-IDF_v5_ESP32C6.vgdbproj wolfssl_test_IDF_v5_ESP32S3.sln wolfssl_test_IDF_v5_ESP32S3.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32 sdkconfig.defaults.esp32c3 sdkconfig.defaults.esp32c6 sdkconfig.defaults.esp32h2 sdkconfig.defaults.esp32s2 sdkconfig.defaults.esp32s3 sdkconfig.defaults.esp8266 testAll.sh testMonitor.sh wolfssl_test_ESP8266.sln wolfssl_test_ESP8266.vgdbproj
wolfssl_test_idf
VisualGDB VisualGDB_wolfssl_test_idf.sln VisualGDB_wolfssl_test_idf.vgdbproj
main CMakeLists.txt Kconfig.projbuild component.mk main.c main_wip.c.ex time_helper.c time_helper.h
CMakeLists.txt Kconfig.projbuild README.md component.mk sdkconfig.defaults
README.md
libs CMakeLists.txt README.md component.mk tigard.cfg
test CMakeLists.txt README.md component.mk test_wolfssl.c
README.md README_32se.md UPDATE.md compileAllExamples.sh dummy_config_h dummy_test_paths.h setup.sh setup_win.bat user_settings.h
README.md include.am
GCC-ARM
Header user_settings.h
Source armtarget.c benchmark_main.c test_main.c tls_client.c tls_server.c wolf_main.c
Makefile Makefile.bench Makefile.client Makefile.common Makefile.server Makefile.static Makefile.test README.md include.am linker.ld linker_fips.ld
Gaisler-BCC README.md include.am
HEXAGON
DSP Makefile wolfssl_dsp.idl
Makefile README.md build.sh ecc-verify-benchmark.c ecc-verify.c include.am user_settings.h
HEXIWEAR
wolfSSL_HW .cwGeneratedFileSetLog user_settings.h
IAR-EWARM
Projects
benchmark benchmark-main.c current_time.c wolfCrypt-benchmark.ewd wolfCrypt-benchmark.ewp
common minimum-startup.c wolfssl.icf
lib wolfSSL-Lib.ewd wolfSSL-Lib.ewp
test test-main.c wolfCrypt-test.ewd wolfCrypt-test.ewp
user_settings.h wolfssl.eww
embOS
SAMV71_XULT
embOS_SAMV71_XULT_Linker_Script samv71q21_wolfssl.icf
embOS_SAMV71_XULT_user_settings user_settings.h user_settings_simple_example.h user_settings_verbose_example.h
embOS_wolfcrypt_benchmark_SAMV71_XULT
Application runBenchmarks.c
README_wolfcrypt_benchmark wolfcrypt_benchmark.ewd wolfcrypt_benchmark.ewp
embOS_wolfcrypt_lib_SAMV71_XULT README_wolfcrypt_lib wolfcrypt_lib.ewd wolfcrypt_lib.ewp
embOS_wolfcrypt_test_SAMV71_XULT
Application runWolfcryptTests.c
README_wolfcrypt_test wolfcrypt_test.ewd wolfcrypt_test.ewp
README_SAMV71
custom_port
custom_port_Linker_Script samv71q21_wolfssl.icf
custom_port_user_settings user_settings.h
wolfcrypt_benchmark_custom_port
Application runBenchmarks.c
wolfcrypt_test_custom_port
Application runWolfcryptTests.c
README_custom_port
extract_trial_here README_extract_trial_here
README
.gitignore README
IAR-MSP430 Makefile README.md include.am main.c user_settings.h
INTIME-RTOS Makefile README.md include.am libwolfssl.c libwolfssl.vcxproj user_settings.h wolfExamples.c wolfExamples.h wolfExamples.sln wolfExamples.vcxproj wolfssl-lib.sln wolfssl-lib.vcxproj
Infineon README.md include.am user_settings.h
KDS
config user_settings.h
include.am
LINUX-SGX README.md build.sh clean.sh include.am sgx_t_static.mk
LPCXPRESSO
lib_wolfssl lpc_18xx_port.c user_settings.h
wolf_example
src lpc_18xx_startup.c wolfssl_example.c
readme.txt
README.md
M68K
benchmark Makefile main.cpp
testwolfcrypt Makefile main.cpp
Makefile README.md include.am user_settings.h
MCUEXPRESSO
RT1170 fsl_caam_c.patch fsl_caam_h.patch user_settings.h
benchmark
source run_benchmark.c
wolfssl liblinks.xml
README.md include.am user_settings.h wolfcrypt_test.c
MDK-ARM
LPC43xx time-LCP43xx.c
MDK-ARM
wolfSSL Retarget.c cert_data.c cert_data.h config-BARE-METAL.h config-FS.h config-RTX-TCP-FS.h config-WOLFLIB.h main.c shell.c time-CortexM3-4.c time-dummy.c wolfssl_MDK_ARM.c wolfssl_MDK_ARM.h
STM32F2xx_StdPeriph_Lib time-STM32F2xx.c
MDK5-ARM
Conf user_settings.h
Inc wolfssl_MDK_ARM.h
Projects
CryptBenchmark Abstract.txt CryptBenchmark.sct CryptBenchmark.uvoptx CryptBenchmark.uvprojx main.c
CryptTest Abstract.txt CryptTest.sct CryptTest.uvoptx CryptTest.uvprojx main.c
EchoClient Abstract.txt EchoClient.uvoptx EchoClient.uvprojx main.c wolfssl-link.sct
EchoServer Abstract.txt EchoServer.uvoptx EchoServer.uvprojx main.c wolfssl-link.sct
SimpleClient Abstract.txt SimpleClient.uvoptx SimpleClient.uvprojx main.c wolfssl-link.sct
SimpleServer Abstract.txt SimpleServer.uvoptx SimpleServer.uvprojx main.c wolfssl-link.sct
wolfSSL-Full Abstract.txt main.c shell.c time-CortexM3-4.c wolfsslFull.uvoptx wolfsslFull.uvprojx
wolfSSL-Lib Abstract.txt wolfSSL-Lib.uvoptx wolfSSL-Lib.uvprojx
Src ssl-dummy.c
README.md include.am
MPLABX16
wolfcrypt_test.X
nbproject
private configurations.xml private.xml
configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
README.md include.am main.c user_settings.h
MQX Makefile README-jp.md README.md client-tls.c include.am server-tls.c user_config.h user_settings.h
MSVS-2019-AZSPHERE
client client.c client.h
server server.c server.h
shared util.h
wolfssl_new_azsphere
HardwareDefinitions
avnet_mt3620_sk
inc
hw template_appliance.h
template_appliance.json
mt3620_rdb
inc
hw template_appliance.h
template_appliance.json
seeed_mt3620_mdb
inc
hw template_appliance.h
template_appliance.json
.gitignore CMakeLists.txt CMakeSettings.json app_manifest.json applibs_versions.h launch.vs.json main.c
README.md include.am user_settings.h
MYSQL CMakeLists_wolfCrypt.txt CMakeLists_wolfSSL.txt do.sh
NDS README.md
NETOS Makefile.wolfcrypt.inc README.md include.am user_settings.h user_settings.h-cert2425 user_settings.h-cert3389 wolfssl_netos_custom.c
OPENSTM32 README.md
PlatformIO
examples
wolfssl_benchmark
include README main.h
lib README
src CMakeLists.txt main.c
test README
CMakeLists.txt README.md platformio.ini sdkconfig.defaults wolfssl_benchmark.code-workspace
wolfssl_test
include README main.h
lib README
src CMakeLists.txt main.c
test README
CMakeLists.txt README.md platformio.ini sdkconfig.defaults wolfssl_test.code-workspace
README.md wolfssl_platformio.code-workspace
README.md include.am
QNX
CAAM-DRIVER Makefile
example-client Makefile client-tls.c
example-cmac Makefile cmac-test.c
example-server Makefile server-tls.c
testwolfcrypt Makefile
wolfssl Makefile user_settings.h
README.md include.am
RISCV
SIFIVE-HIFIVE1 Makefile README.md include.am main.c user_settings.h
SIFIVE-UNLEASHED README.md include.am
include.am
ROWLEY-CROSSWORKS-ARM Kinetis_FlashPlacement.xml README.md arm_startup.c benchmark_main.c hw.h include.am kinetis_hw.c retarget.c test_main.c user_settings.h wolfssl.hzp wolfssl_ltc.hzp
Renesas
cs+
Projects
common strings.h unistd.h user_settings.h wolfssl_dummy.c
t4_demo README_en.txt README_jp.txt t4_demo.mtpj wolf_client.c wolf_demo.h wolf_main.c wolf_server.c
test test.mtpj test_main.c
wolfssl_lib wolfssl_lib.mtpj
README include.am
e2studio
DK-S7G2
benchmark-template
src app_entry.c
example_server-template
src app_entry.c
wolfcrypttest-template
src app_entry.c
wolfssl-template-project configuration.xml
README.md include.am user_settings.h
Projects
common strings.h unistd.h user_settings.h wolfssl_dummy.c
test
src key_data.c key_data.h test_main.c wolf_client.c wolf_server.c wolfssl_demo.h
tools generate_rsa_keypair.sh genhexbuf.pl rsa_pss_sign.sh
wolfssl
src .gitkeep
wolfcrypt
src .gitkeep
README include.am
RA6M3
benchmark-wolfcrypt
common .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
client-wolfssl
common
src .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl_thread_entry.h
common
ra6m3g README.md
src freertos_tcp_port.c
user_settings.h util.h
server-wolfssl
common
src .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl_thread_entry.h
test-wolfcrypt
common .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl
src .gitkeep
wolfcrypt .gitkeep
README.md README_APRA6M_en.md README_APRA6M_jp.md include.am
RA6M3G README.md
RA6M4
common user_settings.h wolfssl_demo.h
test
key_data key_data.h key_data_sce.c
src
SEGGER_RTT myprint.c
common .gitignore
test_main.c wolf_client.c wolfssl_sce_unit_test.c
test_RA6M4Debug.launch
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
README.md include.am
RX65N
GR-ROSE
common strings.h unistd.h user_settings.h wolfssl_dummy.c
smc smc.scfg
test
src key_data.c key_data.h test_main.c wolf_client.c wolf_server.c wolfssl_demo.h
test.rcpc test_HardwareDebug.launch
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
wolfssl wolfssl.rcpc
README_EN.md README_JP.md include.am
RSK
resource section.esi
wolfssl wolfssl.rcpc
wolfssl_demo key_data.c key_data.h user_settings.h wolfssl_demo.c wolfssl_demo.h
InstructionManualForExample_RSK+RX65N-2MB_EN.pdf InstructionManualForExample_RSK+RX65N-2MB_JP.pdf README_EN.md README_JP.md include.am
RX72N
EnvisionKit
Simple
common sectioninfo.esi wolfssl_dummy.c
test
src
client simple_tcp_client.c simple_tls_tsip_client.c
server simple_tcp_server.c simple_tls_server.c
test_main.c wolfssl_simple_demo.h
test.rcpc test.scfg test_HardwareDebug.launch
wolfssl wolfssl.rcpc
README_EN.md README_JP.md
resource section.esi
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
wolfssl wolfssl.rcpc
wolfssl_demo key_data.c key_data.h user_settings.h wolfssl_demo.c wolfssl_demo.h wolfssl_tsip_unit_test.c
InstructionManualForExample_RX72N_EnvisonKit_EN.pdf InstructionManualForExample_RX72N_EnvisonKit_JP.pdf README_EN.md README_JP.md include.am
RZN2L
common user_settings.h wolfssl_demo.h
test
src
serial_io app_print.c
test wolf_client.c wolf_server.c wolfssl_rsip_unit_test.c
wolfCrypt .gitignore
wolfSSL .gitignore
local_system_init.c rzn2l_tst_thread_entry.c wolfssl_dummy.c
README.md include.am
SK-S7G2
common user_settings.h
wolfssl_lib configuration.xml
.gitignore README.md include.am
STARCORE README.txt include.am starcore_test.c user_settings.h
STM32Cube README.md STM32_Benchmarks.md default_conf.ftl include.am main.c wolfssl_example.c wolfssl_example.h
SimplicityStudio README.md include.am test_wolf.c user_settings.h
TRUESTUDIO
wolfssl user_settings.h
README include.am
VS-ARM README.md include.am user_settings.h wolfssl.sln wolfssl.vcxproj
VS-AZURE-SPHERE
client app_manifest.json client.c client.h client.vcxproj
server app_manifest.json server.c server.h server.vcxproj
shared util.h
wolfcrypt_test app_manifest.json wolfcrypt_test.vcxproj
README.md include.am user_settings.h wolfssl.sln wolfssl.vcxproj
VisualDSP include.am user_settings.h wolf_tasks.c
WICED-STUDIO README include.am user_settings.h
WIN README.txt include.am test.vcxproj user_settings.h user_settings_dtls.h wolfssl-fips.sln wolfssl-fips.vcxproj
WIN-SGX ReadMe.txt include.am wolfSSL_SGX.edl wolfSSL_SGX.sln wolfSSL_SGX.vcxproj
WIN-SRTP-KDF-140-3 README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxproj
WIN10 README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxproj
WINCE README.md include.am user_settings.h user_settings.h.140-2-deprecated
WORKBENCH README.md include.am
XCODE
Benchmark
wolfBench
Assets.xcassets
AppIcon.appiconset Contents.json
Base.lproj LaunchScreen.storyboard Main.storyboard
AppDelegate.h AppDelegate.m Info.plist ViewController.h ViewController.m main.m
wolfBench.xcodeproj project.pbxproj
include.am
wolfssl-FIPS.xcodeproj project.pbxproj
wolfssl.xcodeproj project.pbxproj
wolfssl_testsuite.xcodeproj project.pbxproj
README.md build-for-i386.sh include.am user_settings.h
XCODE-FIPSv2
macOS-C++
Intel user_settings.h
M1 user_settings.h
include.am user_settings.h
XCODE-FIPSv5 README include.am user_settings.h
XCODE-FIPSv6 README include.am user_settings.h
XilinxSDK
2018_2 lscript.ld
2019_2
wolfCrypt_example
src lscript.ld
wolfCrypt_example_system wolfCrypt_example_system.sprj
2022_1
wolfCrypt_FreeRTOS_example wolfCrypt_FreeRTOS_example.prj
wolfCrypt_FreeRTOS_example_system wolfCrypt_FreeRTOS_example_system.sprj
wolfCrypt_example wolfCrypt_example.prj
wolfCrypt_example_system wolfCrypt_example_system.sprj
.gitignore
README.md bench.sh combine.sh eclipse_formatter_profile.xml graph.sh include.am user_settings.h wolfssl_example.c
apple-universal
wolfssl-multiplatform
wolfssl-multiplatform
Assets.xcassets
AccentColor.colorset Contents.json
AppIcon.appiconset Contents.json
Contents.json
ContentView.swift simple_client_example.c simple_client_example.h wolfssl-multiplatform-Bridging-Header.h wolfssl_multiplatform.entitlements wolfssl_multiplatformApp.swift wolfssl_test_driver.c wolfssl_test_driver.h
wolfssl-multiplatform.xcodeproj project.pbxproj
.gitignore README.md build-wolfssl-framework.sh include.am
iotsafe Makefile README.md ca-cert.c devices.c devices.h include.am main.c memory-tls.c startup.c target.ld user_settings.h
iotsafe-raspberrypi Makefile README.md client-tls13.c include.am main.c
mynewt README.md apps.wolfcrypttest.pkg.yml crypto.wolfssl.pkg.yml crypto.wolfssl.syscfg.yml include.am setup.sh
zephyr README.md include.am
include.am
RTOS
nuttx
wolfssl .gitignore Kconfig Make.defs Makefile README.md setup-wolfssl.sh user_settings.h
include.am
bsdkm Makefile README.md bsdkm_wc_port.h include.am wolfkmod.c wolfkmod_aes.c x86_vecreg.c
certs
1024 ca-cert.der ca-cert.pem ca-key.der ca-key.pem client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der dh1024.der dh1024.pem dsa-pub-1024.pem dsa1024.der dsa1024.pem include.am rsa1024.der server-cert.der server-cert.pem server-key.der server-key.pem
3072 client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der include.am
4096 client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der include.am
acert
rsa_pss acert.pem acert_ietf.pem acert_ietf_pubkey.pem acert_pubkey.pem
acert.pem acert_ietf.pem acert_ietf_pubkey.pem acert_pubkey.pem include.am
aia ca-issuers-cert.pem multi-aia-cert.pem overflow-aia-cert.pem
crl
extra-crls ca-int-cert-revoked.pem claim-root.pem crl_critical_entry.pem crlnum_57oct.pem crlnum_64oct.pem general-server-crl.pem large_crlnum.pem large_crlnum2.pem
hash_der 0fdb2da4.r0
hash_pem 0fdb2da4.r0
bad_time_fmt.pem ca-int-ecc.pem ca-int.pem ca-int2-ecc.pem ca-int2.pem caEcc384Crl.pem caEccCrl.der caEccCrl.pem cliCrl.pem client-int-ecc.pem client-int.pem crl.der crl.pem crl.revoked crl2.der crl2.pem crl_reason.pem crl_rsapss.pem eccCliCRL.pem eccSrvCRL.pem gencrls.sh include.am server-goodaltCrl.pem server-goodaltwildCrl.pem server-goodcnCrl.pem server-goodcnwildCrl.pem server-int-ecc.pem server-int.pem wolfssl.cnf
dilithium bench_dilithium_level2_key.der bench_dilithium_level3_key.der bench_dilithium_level5_key.der include.am
ecc bp256r1-key.der bp256r1-key.pem ca-secp256k1-cert.pem ca-secp256k1-key.pem client-bp256r1-cert.der client-bp256r1-cert.pem client-secp256k1-cert.der client-secp256k1-cert.pem genecc.sh include.am secp256k1-key.der secp256k1-key.pem secp256k1-param.pem secp256k1-privkey.der secp256k1-privkey.pem server-bp256r1-cert.der server-bp256r1-cert.pem server-secp256k1-cert.der server-secp256k1-cert.pem server2-secp256k1-cert.der server2-secp256k1-cert.pem wolfssl.cnf wolfssl_384.cnf
ed25519 ca-ed25519-key.der ca-ed25519-key.pem ca-ed25519-priv.der ca-ed25519-priv.pem ca-ed25519.der ca-ed25519.pem client-ed25519-key.der client-ed25519-key.pem client-ed25519-priv.der client-ed25519-priv.pem client-ed25519.der client-ed25519.pem eddsa-ed25519.der eddsa-ed25519.pem gen-ed25519-certs.sh gen-ed25519-keys.sh gen-ed25519.sh include.am root-ed25519-key.der root-ed25519-key.pem root-ed25519-priv.der root-ed25519-priv.pem root-ed25519.der root-ed25519.pem server-ed25519-cert.pem server-ed25519-key.der server-ed25519-key.pem server-ed25519-priv.der server-ed25519-priv.pem server-ed25519.der server-ed25519.pem
ed448 ca-ed448-key.der ca-ed448-key.pem ca-ed448-priv.der ca-ed448-priv.pem ca-ed448.der ca-ed448.pem client-ed448-key.der client-ed448-key.pem client-ed448-priv.der client-ed448-priv.pem client-ed448.der client-ed448.pem gen-ed448-certs.sh gen-ed448-keys.sh include.am root-ed448-key.der root-ed448-key.pem root-ed448-priv.der root-ed448-priv.pem root-ed448.der root-ed448.pem server-ed448-cert.pem server-ed448-key.der server-ed448-key.pem server-ed448-priv.der server-ed448-priv.pem server-ed448.der server-ed448.pem
external DigiCertGlobalRootCA.pem README.txt ca-digicert-ev.pem ca-globalsign-root.pem ca-google-root.pem ca_collection.pem include.am
falcon bench_falcon_level1_key.der bench_falcon_level5_key.der include.am
intermediate
ca_false_intermediate gentestcert.sh int_ca.key server.key test_ca.key test_ca.pem test_int_not_cacert.pem test_sign_bynoca_srv.pem wolfssl_base.conf wolfssl_srv.conf
ca-ecc-bad-aki.der ca-ecc-bad-aki.pem ca-int-cert.der ca-int-cert.pem ca-int-ecc-cert.der ca-int-ecc-cert.pem ca-int-ecc-key.der ca-int-ecc-key.pem ca-int-key.der ca-int-key.pem ca-int2-cert.der ca-int2-cert.pem ca-int2-ecc-cert.der ca-int2-ecc-cert.pem ca-int2-ecc-key.der ca-int2-ecc-key.pem ca-int2-key.der ca-int2-key.pem client-chain-alt-ecc.pem client-chain-alt.pem client-chain-ecc.der client-chain-ecc.pem client-chain.der client-chain.pem client-int-cert.der client-int-cert.pem client-int-ecc-cert.der client-int-ecc-cert.pem genintcerts.sh include.am server-chain-alt-ecc.pem server-chain-alt.pem server-chain-ecc.der server-chain-ecc.pem server-chain-short.pem server-chain.der server-chain.pem server-int-cert.der server-int-cert.pem server-int-ecc-cert.der server-int-ecc-cert.pem
lms bc_hss_L2_H5_W8_root.der bc_hss_L3_H5_W4_root.der bc_lms_chain_ca.der bc_lms_chain_leaf.der bc_lms_native_bc_root.der bc_lms_sha256_h10_w8_root.der bc_lms_sha256_h5_w4_root.der include.am
mldsa README.txt include.am mldsa44-cert.der mldsa44-cert.pem mldsa44-key.pem mldsa44_bare-priv.der mldsa44_bare-seed.der mldsa44_oqskeypair.der mldsa44_priv-only.der mldsa44_pub-spki.der mldsa44_seed-only.der mldsa44_seed-priv.der mldsa65-cert.der mldsa65-cert.pem mldsa65-key.pem mldsa65_bare-priv.der mldsa65_bare-seed.der mldsa65_oqskeypair.der mldsa65_priv-only.der mldsa65_pub-spki.der mldsa65_seed-only.der mldsa65_seed-priv.der mldsa87-cert.der mldsa87-cert.pem mldsa87-key.pem mldsa87_bare-priv.der mldsa87_bare-seed.der mldsa87_oqskeypair.der mldsa87_priv-only.der mldsa87_pub-spki.der mldsa87_seed-only.der mldsa87_seed-priv.der
ocsp imposter-root-ca-cert.der imposter-root-ca-cert.pem imposter-root-ca-key.der imposter-root-ca-key.pem include.am index-ca-and-intermediate-cas.txt index-ca-and-intermediate-cas.txt.attr index-intermediate1-ca-issued-certs.txt index-intermediate1-ca-issued-certs.txt.attr index-intermediate2-ca-issued-certs.txt index-intermediate2-ca-issued-certs.txt.attr index-intermediate3-ca-issued-certs.txt index-intermediate3-ca-issued-certs.txt.attr intermediate1-ca-cert.der intermediate1-ca-cert.pem intermediate1-ca-key.der intermediate1-ca-key.pem intermediate2-ca-cert.der intermediate2-ca-cert.pem intermediate2-ca-key.der intermediate2-ca-key.pem intermediate3-ca-cert.der intermediate3-ca-cert.pem intermediate3-ca-key.der intermediate3-ca-key.pem ocsp-responder-cert.der ocsp-responder-cert.pem ocsp-responder-key.der ocsp-responder-key.pem openssl.cnf renewcerts-for-test.sh renewcerts.sh root-ca-cert.der root-ca-cert.pem root-ca-crl.pem root-ca-key.der root-ca-key.pem server1-cert.der server1-cert.pem server1-chain-noroot.pem server1-key.der server1-key.pem server2-cert.der server2-cert.pem server2-key.der server2-key.pem server3-cert.der server3-cert.pem server3-key.der server3-key.pem server4-cert.der server4-cert.pem server4-key.der server4-key.pem server5-cert.der server5-cert.pem server5-key.der server5-key.pem test-leaf-response.der test-multi-response.der test-response-nointern.der test-response-rsapss.der test-response.der
p521 ca-p521-key.der ca-p521-key.pem ca-p521-priv.der ca-p521-priv.pem ca-p521.der ca-p521.pem client-p521-key.der client-p521-key.pem client-p521-priv.der client-p521-priv.pem client-p521.der client-p521.pem gen-p521-certs.sh gen-p521-keys.sh include.am root-p521-key.der root-p521-key.pem root-p521-priv.der root-p521-priv.pem root-p521.der root-p521.pem server-p521-cert.pem server-p521-key.der server-p521-key.pem server-p521-priv.der server-p521-priv.pem server-p521.der server-p521.pem
renewcerts wolfssl.cnf
rpk client-cert-rpk.der client-ecc-cert-rpk.der include.am server-cert-rpk.der server-ecc-cert-rpk.der
rsapss ca-3072-rsapss-key.der ca-3072-rsapss-key.pem ca-3072-rsapss-priv.der ca-3072-rsapss-priv.pem ca-3072-rsapss.der ca-3072-rsapss.pem ca-rsapss-key.der ca-rsapss-key.pem ca-rsapss-priv.der ca-rsapss-priv.pem ca-rsapss.der ca-rsapss.pem client-3072-rsapss-key.der client-3072-rsapss-key.pem client-3072-rsapss-priv.der client-3072-rsapss-priv.pem client-3072-rsapss.der client-3072-rsapss.pem client-rsapss-key.der client-rsapss-key.pem client-rsapss-priv.der client-rsapss-priv.pem client-rsapss.der client-rsapss.pem gen-rsapss-keys.sh include.am renew-rsapss-certs.sh root-3072-rsapss-key.der root-3072-rsapss-key.pem root-3072-rsapss-priv.der root-3072-rsapss-priv.pem root-3072-rsapss.der root-3072-rsapss.pem root-rsapss-key.der root-rsapss-key.pem root-rsapss-priv.der root-rsapss-priv.pem root-rsapss.der root-rsapss.pem server-3072-rsapss-cert.pem server-3072-rsapss-key.der server-3072-rsapss-key.pem server-3072-rsapss-priv.der server-3072-rsapss-priv.pem server-3072-rsapss.der server-3072-rsapss.pem server-mix-rsapss-cert.pem server-rsapss-cert.pem server-rsapss-key.der server-rsapss-key.pem server-rsapss-priv.der server-rsapss-priv.pem server-rsapss.der server-rsapss.pem
sia timestamping-sia-cert.pem
slhdsa bench_slhdsa_sha2_128f_key.der bench_slhdsa_sha2_128s_key.der bench_slhdsa_sha2_192f_key.der bench_slhdsa_sha2_192s_key.der bench_slhdsa_sha2_256f_key.der bench_slhdsa_sha2_256s_key.der bench_slhdsa_shake128f_key.der bench_slhdsa_shake128s_key.der bench_slhdsa_shake192f_key.der bench_slhdsa_shake192s_key.der bench_slhdsa_shake256f_key.der bench_slhdsa_shake256s_key.der client-mldsa44-priv.pem client-mldsa44-sha2.der client-mldsa44-sha2.pem client-mldsa44-shake.der client-mldsa44-shake.pem gen-slhdsa-mldsa-certs.sh include.am root-slhdsa-sha2-128s-priv.der root-slhdsa-sha2-128s-priv.pem root-slhdsa-sha2-128s.der root-slhdsa-sha2-128s.pem root-slhdsa-shake-128s-priv.der root-slhdsa-shake-128s-priv.pem root-slhdsa-shake-128s.der root-slhdsa-shake-128s.pem server-mldsa44-priv.pem server-mldsa44-sha2.der server-mldsa44-sha2.pem server-mldsa44-shake.der server-mldsa44-shake.pem
sm2 ca-sm2-key.der ca-sm2-key.pem ca-sm2-priv.der ca-sm2-priv.pem ca-sm2.der ca-sm2.pem client-sm2-key.der client-sm2-key.pem client-sm2-priv.der client-sm2-priv.pem client-sm2.der client-sm2.pem fix_sm2_spki.py gen-sm2-certs.sh gen-sm2-keys.sh include.am root-sm2-key.der root-sm2-key.pem root-sm2-priv.der root-sm2-priv.pem root-sm2.der root-sm2.pem self-sm2-cert.pem self-sm2-key.pem self-sm2-priv.pem server-sm2-cert.der server-sm2-cert.pem server-sm2-key.der server-sm2-key.pem server-sm2-priv.der server-sm2-priv.pem server-sm2.der server-sm2.pem
statickeys dh-ffdhe2048-params.pem dh-ffdhe2048-pub.der dh-ffdhe2048-pub.pem dh-ffdhe2048.der dh-ffdhe2048.pem ecc-secp256r1.der ecc-secp256r1.pem gen-static.sh include.am x25519-pub.der x25519-pub.pem x25519.der x25519.pem
test
expired expired-ca.der expired-ca.pem expired-cert.der expired-cert.pem
catalog.txt cert-bad-neg-int.der cert-bad-oid.der cert-bad-utf8.der cert-ext-ia.cfg cert-ext-ia.der cert-ext-ia.pem cert-ext-joi.cfg cert-ext-joi.der cert-ext-joi.pem cert-ext-mnc.der cert-ext-multiple.cfg cert-ext-multiple.der cert-ext-multiple.pem cert-ext-nc-combined.der cert-ext-nc-combined.pem cert-ext-nc.cfg cert-ext-nc.der cert-ext-nc.pem cert-ext-ncdns.der cert-ext-ncdns.pem cert-ext-ncip.der cert-ext-ncip.pem cert-ext-ncmixed.der cert-ext-ncmulti.der cert-ext-ncmulti.pem cert-ext-ncrid.der cert-ext-ncrid.pem cert-ext-nct.cfg cert-ext-nct.der cert-ext-nct.pem cert-ext-ndir-exc.cfg cert-ext-ndir-exc.der cert-ext-ndir-exc.pem cert-ext-ndir.cfg cert-ext-ndir.der cert-ext-ndir.pem cert-ext-ns.der cert-over-max-altnames.cfg cert-over-max-altnames.der cert-over-max-altnames.pem cert-over-max-nc.cfg cert-over-max-nc.der cert-over-max-nc.pem client-ecc-cert-ski.hex cn-ip-literal.der cn-ip-wildcard.der crit-cert.pem crit-key.pem dh1024.der dh1024.pem dh512.der dh512.pem digsigku.pem encrypteddata.msg gen-badsig.sh gen-ext-certs.sh gen-testcerts.sh include.am kari-keyid-cms.msg ktri-keyid-cms.msg ossl-trusted-cert.pem server-badaltname.der server-badaltname.pem server-badaltnull.der server-badaltnull.pem server-badcn.der server-badcn.pem server-badcnnull.der server-badcnnull.pem server-cert-ecc-badsig.der server-cert-ecc-badsig.pem server-cert-rsa-badsig.der server-cert-rsa-badsig.pem server-duplicate-policy.pem server-garbage.der server-garbage.pem server-goodalt.der server-goodalt.pem server-goodaltwild.der server-goodaltwild.pem server-goodcn.der server-goodcn.pem server-goodcnwild.der server-goodcnwild.pem server-localhost.der server-localhost.pem smime-test-canon.p7s smime-test-multipart-badsig.p7s smime-test-multipart.p7s smime-test.p7s
test-pathlen assemble-chains.sh chainA-ICA1-key.pem chainA-ICA1-pathlen0.pem chainA-assembled.pem chainA-entity-key.pem chainA-entity.pem chainB-ICA1-key.pem chainB-ICA1-pathlen0.pem chainB-ICA2-key.pem chainB-ICA2-pathlen1.pem chainB-assembled.pem chainB-entity-key.pem chainB-entity.pem chainC-ICA1-key.pem chainC-ICA1-pathlen1.pem chainC-assembled.pem chainC-entity-key.pem chainC-entity.pem chainD-ICA1-key.pem chainD-ICA1-pathlen127.pem chainD-assembled.pem chainD-entity-key.pem chainD-entity.pem chainE-ICA1-key.pem chainE-ICA1-pathlen128.pem chainE-assembled.pem chainE-entity-key.pem chainE-entity.pem chainF-ICA1-key.pem chainF-ICA1-pathlen1.pem chainF-ICA2-key.pem chainF-ICA2-pathlen0.pem chainF-assembled.pem chainF-entity-key.pem chainF-entity.pem chainG-ICA1-key.pem chainG-ICA1-pathlen0.pem chainG-ICA2-key.pem chainG-ICA2-pathlen1.pem chainG-ICA3-key.pem chainG-ICA3-pathlen99.pem chainG-ICA4-key.pem chainG-ICA4-pathlen5.pem chainG-ICA5-key.pem chainG-ICA5-pathlen20.pem chainG-ICA6-key.pem chainG-ICA6-pathlen10.pem chainG-ICA7-key.pem chainG-ICA7-pathlen100.pem chainG-assembled.pem chainG-entity-key.pem chainG-entity.pem chainH-ICA1-key.pem chainH-ICA1-pathlen0.pem chainH-ICA2-key.pem chainH-ICA2-pathlen2.pem chainH-ICA3-key.pem chainH-ICA3-pathlen2.pem chainH-ICA4-key.pem chainH-ICA4-pathlen2.pem chainH-assembled.pem chainH-entity-key.pem chainH-entity.pem chainI-ICA1-key.pem chainI-ICA1-no_pathlen.pem chainI-ICA2-key.pem chainI-ICA2-no_pathlen.pem chainI-ICA3-key.pem chainI-ICA3-pathlen2.pem chainI-assembled.pem chainI-entity-key.pem chainI-entity.pem chainJ-ICA1-key.pem chainJ-ICA1-no_pathlen.pem chainJ-ICA2-key.pem chainJ-ICA2-no_pathlen.pem chainJ-ICA3-key.pem chainJ-ICA3-no_pathlen.pem chainJ-ICA4-key.pem chainJ-ICA4-pathlen2.pem chainJ-assembled.pem chainJ-entity-key.pem chainJ-entity.pem include.am refreshkeys.sh
test-serial0 ee_normal.pem ee_serial0.pem generate_certs.sh include.am intermediate_serial0.pem root_serial0.pem root_serial0_key.pem selfsigned_nonca_serial0.pem
xmss bc_xmss_chain_ca.der bc_xmss_chain_leaf.der bc_xmss_sha2_10_256_root.der bc_xmss_sha2_16_256_root.der bc_xmssmt_sha2_20_2_256_root.der bc_xmssmt_sha2_20_4_256_root.der bc_xmssmt_sha2_40_8_256_root.der include.am
ca-cert-chain.der ca-cert.der ca-cert.pem ca-ecc-cert.der ca-ecc-cert.pem ca-ecc-key.der ca-ecc-key.pem ca-ecc384-cert.der ca-ecc384-cert.pem ca-ecc384-key.der ca-ecc384-key.pem ca-key-pkcs8-attribute.der ca-key.der ca-key.pem check_dates.sh client-absolute-urn.pem client-ca-cert.der client-ca-cert.pem client-ca.pem client-cert-ext.der client-cert-ext.pem client-cert.der client-cert.pem client-crl-dist.der client-crl-dist.pem client-ecc-ca-cert.der client-ecc-ca-cert.pem client-ecc-cert.der client-ecc-cert.pem client-ecc384-cert.der client-ecc384-cert.pem client-ecc384-key.der client-ecc384-key.pem client-key.der client-key.pem client-keyEnc.pem client-keyPub.der client-keyPub.pem client-relative-uri.pem client-uri-cert.pem csr.attr.der csr.dsa.der csr.dsa.pem csr.ext.der csr.signed.der dh-priv-2048.der dh-priv-2048.pem dh-pub-2048.der dh-pub-2048.pem dh-pubkey-2048.der dh2048.der dh2048.pem dh3072.der dh3072.pem dh4096.der dh4096.pem dsa-pubkey-2048.der dsa2048.der dsa2048.pem dsa3072.der dsaparams.der dsaparams.pem ecc-client-key.der ecc-client-key.pem ecc-client-keyPub.der ecc-client-keyPub.pem ecc-key-comp.pem ecc-keyPkcs8.der ecc-keyPkcs8.pem ecc-keyPkcs8Enc.der ecc-keyPkcs8Enc.pem ecc-keyPub.der ecc-keyPub.pem ecc-params.der ecc-params.pem ecc-privOnlyCert.pem ecc-privOnlyKey.pem ecc-privkey.der ecc-privkey.pem ecc-privkeyPkcs8.der ecc-privkeyPkcs8.pem ecc-rsa-server.p12 empty-issuer-cert.pem entity-no-ca-bool-cert.pem entity-no-ca-bool-key.pem fpki-cert.der fpki-certpol-cert.der gen_revoked.sh include.am renewcerts.sh rid-cert.der rsa-pub-2048.pem rsa2048.der rsa3072.der server-cert-chain.der server-cert.der server-cert.pem server-ecc-comp.der server-ecc-comp.pem server-ecc-rsa.der server-ecc-rsa.pem server-ecc-self.der server-ecc-self.pem server-ecc.der server-ecc.pem server-ecc384-cert.der server-ecc384-cert.pem server-ecc384-key.der server-ecc384-key.pem server-key.der server-key.pem server-keyEnc.pem server-keyPkcs8.der server-keyPkcs8.pem server-keyPkcs8Enc.der server-keyPkcs8Enc.pem server-keyPkcs8Enc12.pem server-keyPkcs8Enc2.pem server-keyPub.der server-keyPub.pem server-revoked-cert.pem server-revoked-key.pem taoCert.txt test-ber-exp02-05-2022.p7b test-degenerate.p7b test-multiple-recipients.p7b test-servercert-rc2.p12 test-servercert.p12 test-stream-dec.p7b test-stream-sign.p7b wolfssl-website-ca.pem x942dh2048.der x942dh2048.pem
cmake
consumer CMakeLists.txt README.md main.c
modules FindARIA.cmake FindOQS.cmake
Config.cmake.in README.md config.in functions.cmake include.am options.h.in wolfssl-config-version.cmake.in wolfssl-targets.cmake.in
debian
source format
changelog.in control.in copyright include.am libwolfssl-dev.install libwolfssl.install rules.in
doc
dox_comments
header_files aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h puf.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wc_she.h wc_slhdsa.h wolfio.h
header_files-ja aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wolfio.h
formats
html
html_changes
search search.css search.js
customdoxygen.css doxygen.css menu.js menudata.js tabs.css
Doxyfile footer.html header.html mainpage.dox
pdf Doxyfile header.tex
images wolfssl_logo.png
QUIC.md README.txt README_DOXYGEN check_api.sh generate_documentation.sh include.am
examples
asn1 asn1.c dumpasn1.cfg gen_oid_names.rb include.am oid_names.h
async Makefile README.md async_client.c async_server.c async_tls.c async_tls.h include.am user_settings.h
benchmark include.am tls_bench.c tls_bench.h
client client.c client.h client.sln client.vcproj client.vcxproj include.am
configs README.md include.am user_settings_EBSnet.h user_settings_all.h user_settings_arduino.h user_settings_baremetal.h user_settings_ca.h user_settings_curve25519nonblock.h user_settings_dtls13.h user_settings_eccnonblock.h user_settings_espressif.h user_settings_fipsv2.h user_settings_fipsv5.h user_settings_min_ecc.h user_settings_openssl_compat.h user_settings_pkcs7.h user_settings_platformio.h user_settings_pq.h user_settings_rsa_only.h user_settings_stm32.h user_settings_template.h user_settings_tls12.h user_settings_tls13.h user_settings_wolfboot_keytools.h user_settings_wolfssh.h user_settings_wolftpm.h
crypto_policies
default wolfssl.txt
future wolfssl.txt
legacy wolfssl.txt
echoclient echoclient.c echoclient.h echoclient.sln echoclient.vcproj echoclient.vcxproj include.am quit
echoserver echoserver.c echoserver.h echoserver.sln echoserver.vcproj echoserver.vcxproj include.am
ocsp_responder include.am ocsp_responder.c ocsp_responder.h
pem include.am pem.c
sctp include.am sctp-client-dtls.c sctp-client.c sctp-server-dtls.c sctp-server.c
server include.am server.c server.h server.sln server.vcproj server.vcxproj
README.md include.am
linuxkm
patches
5.10.17 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v10v17.patch
5.10.236 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v10v236.patch
5.14.0-570.58.1.el9_6 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v14-570v58v1-el9_6.patch
5.15 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v15.patch
5.17 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v17.patch
5.17-ubuntu-jammy-tegra WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v17-ubuntu-jammy-tegra.patch
6.1.73 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v1v73.patch
6.12 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v12.patch
6.15 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v15.patch
7.0 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-7v0.patch
regen-patches.sh
Kbuild Makefile README.md get_thread_size.c include.am linuxkm-fips-hash-wrapper.sh linuxkm-fips-hash.c linuxkm_memory.c linuxkm_memory.h linuxkm_wc_port.h lkcapi_aes_glue.c lkcapi_dh_glue.c lkcapi_ecdh_glue.c lkcapi_ecdsa_glue.c lkcapi_glue.c lkcapi_rsa_glue.c lkcapi_sha_glue.c module_exports.c.template module_hooks.c pie_redirect_table.c wolfcrypt.lds x86_vector_register_glue.c
m4 ax_add_am_macro.m4 ax_am_jobserver.m4 ax_am_macros.m4 ax_append_compile_flags.m4 ax_append_flag.m4 ax_append_link_flags.m4 ax_append_to_file.m4 ax_atomic.m4 ax_bsdkm.m4 ax_check_compile_flag.m4 ax_check_link_flag.m4 ax_compiler_version.m4 ax_count_cpus.m4 ax_create_generic_config.m4 ax_debug.m4 ax_file_escapes.m4 ax_harden_compiler_flags.m4 ax_linuxkm.m4 ax_print_to_file.m4 ax_pthread.m4 ax_require_defined.m4 ax_tls.m4 ax_vcs_checkout.m4 hexversion.m4 lib_socket_nsl.m4 visibility.m4
mcapi
wolfcrypt_mcapi.X
nbproject configurations.xml include.am project.xml
Makefile
wolfcrypt_test.X
nbproject configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
zlib.X
nbproject configurations.xml include.am project.xml
Makefile
PIC32MZ-serial.h README crypto.c crypto.h include.am mcapi_test.c user_settings.h
mplabx
wolfcrypt_benchmark.X
nbproject configurations.xml include.am project.xml
Makefile
wolfcrypt_test.X
nbproject configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
PIC32MZ-serial.h README benchmark_main.c include.am test_main.c user_settings.h
mqx
util_lib
Sources include.am util.c util.h
wolfcrypt_benchmark
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
wolfcrypt_test
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
wolfssl include.am
wolfssl_client
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
README
rpm include.am spec.in
scripts
bench bench_functions.sh
aria-cmake-build-test.sh asn1_oid_sum.pl benchmark.test benchmark_compare.sh cleanup_testfiles.sh crl-gen-openssl.test crl-revoked.test dertoc.pl dtls.test dtlscid.test external.test google.test include.am makedistsmall.sh memtest.sh ocsp-responder-openssl-interop.test ocsp-stapling-with-ca-as-responder.test ocsp-stapling-with-wolfssl-responder.test ocsp-stapling.test ocsp-stapling2.test ocsp-stapling_tls13multi.test ocsp.test openssl.test openssl_srtp.test pem.test ping.test pkcallbacks.test psk.test resume.test rsapss.test sniffer-gen.sh sniffer-ipv6.pcap sniffer-static-rsa.pcap sniffer-testsuite.test sniffer-tls12-keylog.out sniffer-tls12-keylog.pcap sniffer-tls12-keylog.sslkeylog sniffer-tls13-dh-resume.pcap sniffer-tls13-dh.pcap sniffer-tls13-ecc-resume.pcap sniffer-tls13-ecc.pcap sniffer-tls13-hrr.pcap sniffer-tls13-keylog.out sniffer-tls13-keylog.pcap sniffer-tls13-keylog.sslkeylog sniffer-tls13-x25519-resume.pcap sniffer-tls13-x25519.pcap stm32l4-v4_0_1_build.sh tls13.test trusted_peer.test unit.test.in user_settings_asm.sh
src bio.c conf.c crl.c dtls.c dtls13.c include.am internal.c keys.c ocsp.c pk.c pk_ec.c pk_rsa.c quic.c sniffer.c ssl.c ssl_api_cert.c ssl_api_crl_ocsp.c ssl_api_pk.c ssl_asn1.c ssl_bn.c ssl_certman.c ssl_crypto.c ssl_ech.c ssl_load.c ssl_misc.c ssl_p7p12.c ssl_sess.c ssl_sk.c tls.c tls13.c wolfio.c x509.c x509_str.c
sslSniffer
sslSnifferTest README_WIN.md include.am snifftest.c sslSniffTest.vcproj sslSniffTest.vcxproj
README.md sslSniffer.vcproj sslSniffer.vcxproj
support gen-debug-trace-error-codes.sh include.am wolfssl.pc.in
tests
api api.h api_decl.h create_ocsp_test_blobs.py include.am test_aes.c test_aes.h test_arc4.c test_arc4.h test_ascon.c test_ascon.h test_ascon_kats.h test_asn.c test_asn.h test_blake2.c test_blake2.h test_camellia.c test_camellia.h test_certman.c test_certman.h test_chacha.c test_chacha.h test_chacha20_poly1305.c test_chacha20_poly1305.h test_cmac.c test_cmac.h test_curve25519.c test_curve25519.h test_curve448.c test_curve448.h test_des3.c test_des3.h test_dh.c test_dh.h test_digest.h test_dsa.c test_dsa.h test_dtls.c test_dtls.h test_ecc.c test_ecc.h test_ed25519.c test_ed25519.h test_ed448.c test_ed448.h test_evp.c test_evp.h test_evp_cipher.c test_evp_cipher.h test_evp_digest.c test_evp_digest.h test_evp_pkey.c test_evp_pkey.h test_hash.c test_hash.h test_hmac.c test_hmac.h test_md2.c test_md2.h test_md4.c test_md4.h test_md5.c test_md5.h test_mldsa.c test_mldsa.h test_mlkem.c test_mlkem.h test_ocsp.c test_ocsp.h test_ocsp_test_blobs.h test_ossl_asn1.c test_ossl_asn1.h test_ossl_bio.c test_ossl_bio.h test_ossl_bn.c test_ossl_bn.h test_ossl_cipher.c test_ossl_cipher.h test_ossl_dgst.c test_ossl_dgst.h test_ossl_dh.c test_ossl_dh.h test_ossl_dsa.c test_ossl_dsa.h test_ossl_ec.c test_ossl_ec.h test_ossl_ecx.c test_ossl_ecx.h test_ossl_mac.c test_ossl_mac.h test_ossl_obj.c test_ossl_obj.h test_ossl_p7p12.c test_ossl_p7p12.h test_ossl_pem.c test_ossl_pem.h test_ossl_rand.c test_ossl_rand.h test_ossl_rsa.c test_ossl_rsa.h test_ossl_sk.c test_ossl_sk.h test_ossl_x509.c test_ossl_x509.h test_ossl_x509_acert.c test_ossl_x509_acert.h test_ossl_x509_crypto.c test_ossl_x509_crypto.h test_ossl_x509_ext.c test_ossl_x509_ext.h test_ossl_x509_info.c test_ossl_x509_info.h test_ossl_x509_io.c test_ossl_x509_io.h test_ossl_x509_lu.c test_ossl_x509_lu.h test_ossl_x509_name.c test_ossl_x509_name.h test_ossl_x509_pk.c test_ossl_x509_pk.h test_ossl_x509_str.c test_ossl_x509_str.h test_ossl_x509_vp.c test_ossl_x509_vp.h test_pkcs12.c test_pkcs12.h test_pkcs7.c test_pkcs7.h test_poly1305.c test_poly1305.h test_random.c test_random.h test_rc2.c test_rc2.h test_ripemd.c test_ripemd.h test_rsa.c test_rsa.h test_sha.c test_sha.h test_sha256.c test_sha256.h test_sha3.c test_sha3.h test_sha512.c test_sha512.h test_she.c test_she.h test_signature.c test_signature.h test_slhdsa.c test_slhdsa.h test_sm2.c test_sm2.h test_sm3.c test_sm3.h test_sm4.c test_sm4.h test_tls.c test_tls.h test_tls13.c test_tls13.h test_tls_ext.c test_tls_ext.h test_wc_encrypt.c test_wc_encrypt.h test_wolfmath.c test_wolfmath.h test_x509.c test_x509.h
emnet
IP IP.h
Makefile emnet_nonblock_test.c emnet_shim.c
freertos-mem-track-repro FreeRTOS.h repro.c run.sh semphr.h task.h user_settings.h
swdev .gitignore Makefile README.md swdev.c swdev.h swdev_loader.c swdev_loader.h user_settings.h
CONF_FILES_README.md NCONF_test.cnf README TXT_DB.txt api.c include.am quic.c srp.c suites.c test-altchains.conf test-chains.conf test-dhprime.conf test-dtls-downgrade.conf test-dtls-fails-cipher.conf test-dtls-fails.conf test-dtls-group.conf test-dtls-mtu.conf test-dtls-reneg-client.conf test-dtls-reneg-server.conf test-dtls-resume.conf test-dtls-sha2.conf test-dtls-srtp-fails.conf test-dtls-srtp.conf test-dtls.conf test-dtls13-cid.conf test-dtls13-downgrade-fails.conf test-dtls13-downgrade.conf test-dtls13-pq-hybrid-extra-frag.conf test-dtls13-pq-hybrid-extra.conf test-dtls13-pq-hybrid-frag.conf test-dtls13-pq-standalone-frag.conf test-dtls13-pq-standalone.conf test-dtls13-psk.conf test-dtls13.conf test-ecc-cust-curves.conf test-ed25519.conf test-ed448.conf test-enckeys.conf test-fails.conf test-maxfrag-dtls.conf test-maxfrag.conf test-p521.conf test-psk-no-id-sha2.conf test-psk-no-id.conf test-psk.conf test-rsapss.conf test-sctp-sha2.conf test-sctp.conf test-sha2.conf test-sig.conf test-sm2.conf test-tls-downgrade.conf test-tls13-down.conf test-tls13-ecc.conf test-tls13-pq-hybrid-extra.conf test-tls13-pq-hybrid.conf test-tls13-pq-standalone.conf test-tls13-psk-certs.conf test-tls13-psk.conf test-tls13-slhdsa-fail.conf test-tls13-slhdsa-sha2.conf test-tls13-slhdsa-shake.conf test-tls13.conf test-trustpeer.conf test.conf unit.c unit.h utils.c utils.h w64wrapper.c
testsuite include.am testsuite.c testsuite.sln testsuite.vcproj testsuite.vcxproj utils.c utils.h
tirtos
packages
ti
net
wolfssl
tests
EK_TM4C1294XL
wolfcrypt
benchmark TM4C1294NC.icf benchmark.cfg main.c package.bld.hide package.xdc
test TM4C1294NC.icf main.c package.bld.hide package.xdc test.cfg
package.bld package.xdc package.xs
.gitignore README include.am products.mak wolfssl.bld wolfssl.mak
wolfcrypt
benchmark README.md benchmark-VS2022.sln benchmark-VS2022.vcxproj benchmark-VS2022.vcxproj.user benchmark.c benchmark.h benchmark.sln benchmark.vcproj benchmark.vcxproj include.am
src
port
Espressif
esp_crt_bundle README.md cacrt_all.pem cacrt_deprecated.pem cacrt_local.pem esp_crt_bundle.c gen_crt_bundle.py pio_install_cryptography.py
README.md esp32_aes.c esp32_mp.c esp32_sha.c esp32_util.c esp_sdk_mem_lib.c esp_sdk_time_lib.c esp_sdk_wifi_lib.c
Renesas README.md renesas_common.c renesas_fspsm_aes.c renesas_fspsm_rsa.c renesas_fspsm_sha.c renesas_fspsm_util.c renesas_rx64_hw_sha.c renesas_rx64_hw_util.c renesas_tsip_aes.c renesas_tsip_rsa.c renesas_tsip_sha.c renesas_tsip_util.c
af_alg afalg_aes.c afalg_hash.c wc_afalg.c
aria aria-crypt.c aria-cryptocb.c
arm armv8-32-aes-asm.S armv8-32-aes-asm_c.c armv8-32-chacha-asm.S armv8-32-chacha-asm_c.c armv8-32-curve25519.S armv8-32-curve25519_c.c armv8-32-mlkem-asm.S armv8-32-mlkem-asm_c.c armv8-32-poly1305-asm.S armv8-32-poly1305-asm_c.c armv8-32-sha256-asm.S armv8-32-sha256-asm_c.c armv8-32-sha3-asm.S armv8-32-sha3-asm_c.c armv8-32-sha512-asm.S armv8-32-sha512-asm_c.c armv8-aes-asm.S armv8-aes-asm_c.c armv8-aes.c armv8-chacha-asm.S armv8-chacha-asm_c.c armv8-curve25519.S armv8-curve25519_c.c armv8-mlkem-asm.S armv8-mlkem-asm_c.c armv8-poly1305-asm.S armv8-poly1305-asm_c.c armv8-sha256-asm.S armv8-sha256-asm_c.c armv8-sha256.c armv8-sha3-asm.S armv8-sha3-asm_c.c armv8-sha512-asm.S armv8-sha512-asm_c.c armv8-sha512.c cryptoCell.c cryptoCellHash.c thumb2-aes-asm.S thumb2-aes-asm_c.c thumb2-chacha-asm.S thumb2-chacha-asm_c.c thumb2-curve25519.S thumb2-curve25519_c.c thumb2-mlkem-asm.S thumb2-mlkem-asm_c.c thumb2-poly1305-asm.S thumb2-poly1305-asm_c.c thumb2-sha256-asm.S thumb2-sha256-asm_c.c thumb2-sha3-asm.S thumb2-sha3-asm_c.c thumb2-sha512-asm.S thumb2-sha512-asm_c.c
atmel README.md atmel.c
autosar README.md cryif.c crypto.c csm.c include.am test.c
caam README.md caam_aes.c caam_doc.pdf caam_driver.c caam_error.c caam_integrity.c caam_qnx.c caam_sha.c wolfcaam_aes.c wolfcaam_cmac.c wolfcaam_ecdsa.c wolfcaam_fsl_nxp.c wolfcaam_hash.c wolfcaam_hmac.c wolfcaam_init.c wolfcaam_qnx.c wolfcaam_rsa.c wolfcaam_seco.c wolfcaam_x25519.c
cavium README.md README_Octeon.md cavium_nitrox.c cavium_octeon_sync.c
cuda README.md aes-cuda.cu
cypress README.md psoc6_crypto.c
devcrypto README.md devcrypto_aes.c devcrypto_ecdsa.c devcrypto_hash.c devcrypto_hmac.c devcrypto_rsa.c devcrypto_x25519.c wc_devcrypto.c
intel README.md quickassist.c quickassist_mem.c quickassist_sync.c
iotsafe iotsafe.c
kcapi README.md kcapi_aes.c kcapi_dh.c kcapi_ecc.c kcapi_hash.c kcapi_hmac.c kcapi_rsa.c
liboqs liboqs.c
maxim README.md max3266x.c maxq10xx.c
mynewt mynewt_port.c
nxp README.md README_SE050.md casper_port.c dcp_port.c hashcrypt_port.c ksdk_port.c se050_port.c
pic32 pic32mz-crypt.c
ppc32 ppc32-sha256-asm.S ppc32-sha256-asm_c.c ppc32-sha256-asm_cr.c
psa README.md psa.c psa_aes.c psa_hash.c psa_pkcbs.c
riscv riscv-64-aes.c riscv-64-chacha.c riscv-64-poly1305.c riscv-64-sha256.c riscv-64-sha3.c riscv-64-sha512.c
rpi_pico README.md pico.c
silabs README.md silabs_aes.c silabs_ecc.c silabs_hash.c silabs_random.c
st README.md STM32MP13.md STM32MP25.md stm32.c stsafe.c
ti ti-aes.c ti-ccm.c ti-des3.c ti-hash.c
tropicsquare README.md tropic01.c
xilinx xil-aesgcm.c xil-sha3.c xil-versal-glue.c xil-versal-trng.c
nrf51.c
ASN_TEMPLATE.md aes.c aes_asm.S aes_asm.asm aes_gcm_asm.S aes_gcm_asm.asm aes_gcm_x86_asm.S aes_xts_asm.S aes_xts_asm.asm arc4.c ascon.c asm.c asn.c asn_orig.c async.c blake2b.c blake2s.c camellia.c chacha.c chacha20_poly1305.c chacha_asm.S chacha_asm.asm cmac.c coding.c compress.c cpuid.c cryptocb.c curve25519.c curve448.c des3.c dh.c dilithium.c dsa.c ecc.c ecc_fp.c eccsi.c ed25519.c ed448.c error.c evp.c evp_pk.c falcon.c fe_448.c fe_low_mem.c fe_operations.c fe_x25519_128.h fe_x25519_asm.S fp_mont_small.i fp_mul_comba_12.i fp_mul_comba_17.i fp_mul_comba_20.i fp_mul_comba_24.i fp_mul_comba_28.i fp_mul_comba_3.i fp_mul_comba_32.i fp_mul_comba_4.i fp_mul_comba_48.i fp_mul_comba_6.i fp_mul_comba_64.i fp_mul_comba_7.i fp_mul_comba_8.i fp_mul_comba_9.i fp_mul_comba_small_set.i fp_sqr_comba_12.i fp_sqr_comba_17.i fp_sqr_comba_20.i fp_sqr_comba_24.i fp_sqr_comba_28.i fp_sqr_comba_3.i fp_sqr_comba_32.i fp_sqr_comba_4.i fp_sqr_comba_48.i fp_sqr_comba_6.i fp_sqr_comba_64.i fp_sqr_comba_7.i fp_sqr_comba_8.i fp_sqr_comba_9.i fp_sqr_comba_small_set.i ge_448.c ge_low_mem.c ge_operations.c hash.c hmac.c hpke.c include.am integer.c kdf.c logging.c md2.c md4.c md5.c memory.c misc.c pkcs12.c pkcs7.c poly1305.c poly1305_asm.S poly1305_asm.asm puf.c pwdbased.c random.c rc2.c ripemd.c rng_bank.c rsa.c sakke.c sha.c sha256.c sha256_asm.S sha3.c sha3_asm.S sha512.c sha512_asm.S signature.c siphash.c sm2.c sm3.c sm3_asm.S sm4.c sp_arm32.c sp_arm64.c sp_armthumb.c sp_c32.c sp_c64.c sp_cortexm.c sp_dsp32.c sp_int.c sp_sm2_arm32.c sp_sm2_arm64.c sp_sm2_armthumb.c sp_sm2_c32.c sp_sm2_c64.c sp_sm2_cortexm.c sp_sm2_x86_64.c sp_sm2_x86_64_asm.S sp_x86_64.c sp_x86_64_asm.S sp_x86_64_asm.asm srp.c tfm.c wc_dsp.c wc_encrypt.c wc_lms.c wc_lms_impl.c wc_mldsa_asm.S wc_mlkem.c wc_mlkem_asm.S wc_mlkem_poly.c wc_pkcs11.c wc_port.c wc_she.c wc_slhdsa.c wc_xmss.c wc_xmss_impl.c wolfentropy.c wolfevent.c wolfmath.c
test README.md include.am test-VS2022.sln test-VS2022.vcxproj test-VS2022.vcxproj.user test.c test.h test.sln test.vcproj test_paths.h.in
wolfssl
openssl aes.h asn1.h asn1t.h bio.h bn.h buffer.h camellia.h cmac.h cms.h compat_types.h conf.h crypto.h des.h dh.h dsa.h ec.h ec25519.h ec448.h ecdh.h ecdsa.h ed25519.h ed448.h engine.h err.h evp.h fips_rand.h hmac.h include.am kdf.h lhash.h md4.h md5.h modes.h obj_mac.h objects.h ocsp.h opensslconf.h opensslv.h ossl_typ.h pem.h pkcs12.h pkcs7.h rand.h rc4.h ripemd.h rsa.h safestack.h sha.h sha3.h srp.h ssl.h ssl23.h stack.h tls1.h txt_db.h ui.h x509.h x509_vfy.h x509v3.h
wolfcrypt
port
Espressif esp-sdk-lib.h esp32-crypt.h esp_crt_bundle.h
Renesas renesas-fspsm-crypt.h renesas-fspsm-types.h renesas-rx64-hw-crypt.h renesas-tsip-crypt.h renesas_cmn.h renesas_fspsm_internal.h renesas_sync.h renesas_tsip_internal.h renesas_tsip_types.h
af_alg afalg_hash.h wc_afalg.h
aria aria-crypt.h aria-cryptocb.h
arm cryptoCell.h
atmel atmel.h
autosar CryIf.h Crypto.h Csm.h StandardTypes.h
caam caam_driver.h caam_error.h caam_qnx.h wolfcaam.h wolfcaam_aes.h wolfcaam_cmac.h wolfcaam_ecdsa.h wolfcaam_fsl_nxp.h wolfcaam_hash.h wolfcaam_qnx.h wolfcaam_rsa.h wolfcaam_seco.h wolfcaam_sha.h wolfcaam_x25519.h
cavium cavium_nitrox.h cavium_octeon_sync.h
cypress psoc6_crypto.h
devcrypto wc_devcrypto.h
intel quickassist.h quickassist_mem.h quickassist_sync.h
iotsafe iotsafe.h
kcapi kcapi_dh.h kcapi_ecc.h kcapi_hash.h kcapi_hmac.h kcapi_rsa.h wc_kcapi.h
liboqs liboqs.h
maxim max3266x-cryptocb.h max3266x.h maxq10xx.h
nxp casper_port.h dcp_port.h hashcrypt_port.h ksdk_port.h se050_port.h
pic32 pic32mz-crypt.h
psa psa.h
riscv riscv-64-asm.h
rpi_pico pico.h
silabs silabs_aes.h silabs_ecc.h silabs_hash.h silabs_random.h
st stm32.h stsafe.h
ti ti-ccm.h ti-hash.h
tropicsquare tropic01.h
xilinx xil-sha3.h xil-versal-glue.h xil-versal-trng.h
nrf51.h
aes.h arc4.h ascon.h asn.h asn_public.h async.h blake2-impl.h blake2-int.h blake2.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cpuid.h cryptocb.h curve25519.h curve448.h des3.h dh.h dilithium.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h falcon.h fe_448.h fe_operations.h fips_test.h ge_448.h ge_operations.h hash.h hmac.h hpke.h include.am integer.h kdf.h libwolfssl_sources.h libwolfssl_sources_asm.h logging.h md2.h md4.h md5.h mem_track.h memory.h misc.h mpi_class.h mpi_superclass.h oid_sum.h pkcs11.h pkcs12.h pkcs7.h poly1305.h puf.h pwdbased.h random.h rc2.h ripemd.h rng_bank.h rsa.h sakke.h selftest.h settings.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h sm2.h sm3.h sm4.h sp.h sp_int.h srp.h tfm.h types.h visibility.h wc_encrypt.h wc_lms.h wc_mlkem.h wc_pkcs11.h wc_port.h wc_she.h wc_slhdsa.h wc_xmss.h wolfentropy.h wolfevent.h wolfmath.h
callbacks.h certs_test.h certs_test_sm.h crl.h error-ssl.h include.am internal.h ocsp.h options.h.in quic.h sniffer.h sniffer_error.h sniffer_error.rc ssl.h test.h version.h version.h.in wolfio.h
wrapper
Ada
examples
src aes_verify_main.adb rsa_verify_main.adb sha256_main.adb spark_sockets.adb spark_sockets.ads spark_terminal.adb spark_terminal.ads tls_client.adb tls_client.ads tls_client_main.adb tls_server.adb tls_server.ads tls_server_main.adb
.gitignore alire.toml examples.gpr
tests
src
support test_support.adb test_support.ads tests_root_suite.adb tests_root_suite.ads
aes_bindings_tests.adb aes_bindings_tests.ads rsa_verify_bindings_tests.adb rsa_verify_bindings_tests.ads sha256_bindings_tests.adb sha256_bindings_tests.ads tests.adb
.gitignore README.md alire.toml tests.gpr valgrind.supp
.gitignore README.md ada_binding.c alire.toml default.gpr include.am restricted.adc user_settings.h wolfssl-full_runtime.adb wolfssl-full_runtime.ads wolfssl.adb wolfssl.ads wolfssl.gpr
CSharp
wolfCrypt-Test
Properties AssemblyInfo.cs
App.config wolfCrypt-Test.cs wolfCrypt-Test.csproj
wolfSSL-DTLS-PSK-Server
Properties AssemblyInfo.cs
App.config wolfSSL-DTLS-PSK-Server.cs wolfSSL-DTLS-PSK-Server.csproj
wolfSSL-DTLS-Server
Properties AssemblyInfo.cs
App.config wolfSSL-DTLS-Server.cs wolfSSL-DTLS-Server.csproj
wolfSSL-Example-IOCallbacks
Properties AssemblyInfo.cs
App.config wolfSSL-Example-IOCallbacks.cs wolfSSL-Example-IOCallbacks.csproj
wolfSSL-TLS-Client
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-Client.cs wolfSSL-TLS-Client.csproj
wolfSSL-TLS-PSK-Client
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-PSK-Client.cs wolfSSL-TLS-PSK-Client.csproj
wolfSSL-TLS-PSK-Server
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-PSK-Server.cs wolfSSL-TLS-PSK-Server.csproj
wolfSSL-TLS-Server
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-Server.cs wolfSSL-TLS-Server.csproj
wolfSSL-TLS-ServerThreaded
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-ServerThreaded.cs wolfSSL-TLS-ServerThreaded.csproj
wolfSSL_CSharp
Properties AssemblyInfo.cs Resources.Designer.cs Resources.resx
X509.cs wolfCrypt.cs wolfSSL.cs wolfSSL_CSharp.csproj
README.md include.am user_settings.h wolfSSL_CSharp.sln wolfssl.vcxproj
python README.md
rust
wolfssl-wolfcrypt
src aes.rs blake2.rs chacha20_poly1305.rs cmac.rs cmac_mac.rs curve25519.rs dh.rs dilithium.rs ecc.rs ecdsa.rs ed25519.rs ed448.rs fips.rs hkdf.rs hmac.rs hmac_mac.rs kdf.rs lib.rs lms.rs mlkem.rs mlkem_kem.rs pbkdf2_password_hash.rs prf.rs random.rs rsa.rs rsa_pkcs1v15.rs sha.rs sha_digest.rs sys.rs
tests
common mod.rs
test_aes.rs test_blake2.rs test_chacha20_poly1305.rs test_cmac.rs test_cmac_mac.rs test_curve25519.rs test_dh.rs test_dilithium.rs test_ecc.rs test_ecdsa.rs test_ed25519.rs test_ed448.rs test_hkdf.rs test_hmac.rs test_hmac_mac.rs test_kdf.rs test_lms.rs test_mlkem.rs test_mlkem_kem.rs test_pbkdf2_password_hash.rs test_prf.rs test_random.rs test_rsa.rs test_rsa_pkcs1v15.rs test_sha.rs test_sha_digest.rs test_wolfcrypt.rs
CHANGELOG.md Cargo.lock Cargo.toml Makefile README.md build.rs headers.h
Makefile README.md include.am
include.am
zephyr
samples
wolfssl_benchmark
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
CMakeLists.txt README install_test.sh prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_test
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
CMakeLists.txt README install_test.sh prj-no-malloc.conf prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_tls_sock
boards native_sim.conf
src tls_sock.c
CMakeLists.txt README install_sample.sh prj-no-malloc.conf prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_tls_thread
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
src tls_threaded.c
CMakeLists.txt README install_sample.sh prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl options.h
CMakeLists.txt Kconfig Kconfig.tls-generic README.md include.am module.yml user_settings-no-malloc.h user_settings.h zephyr_init.c
.codespellexcludelines .cyignore .editorconfig .gitignore .wolfssl_known_macro_extras AUTHORS CMakeLists.txt CMakePresets.json CMakeSettings.json COPYING ChangeLog.md INSTALL LICENSING LPCExpresso.cproject LPCExpresso.project Makefile.am README README-async.md README.md SCRIPTS-LIST SECURITY-POLICY.md SECURITY-REPORT-TEMPLATE.md Vagrantfile autogen.sh commit-tests.sh configure.ac fips-check.sh fips-hash.sh gencertbuf.pl input pull_to_vagrant.sh quit resource.h stamp-h.in valgrind-bash.supp valgrind-error.sh wnr-example.conf wolfssl-VS2022.vcxproj wolfssl.rc wolfssl.vcproj wolfssl.vcxproj wolfssl64.sln
.clangd .gitignore DOCS.md Makefile README.md assert.c core.c crypto.c env.c fs.c http.c ini.c json.c log.c luna.h main.c makext.mk path.c process.c request.c sqlite.c stash.c template.c util.c
curl/lib/ftp.c raw
   1/***************************************************************************
   2 *                                  _   _ ____  _
   3 *  Project                     ___| | | |  _ \| |
   4 *                             / __| | | | |_) | |
   5 *                            | (__| |_| |  _ <| |___
   6 *                             \___|\___/|_| \_\_____|
   7 *
   8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
   9 *
  10 * This software is licensed as described in the file COPYING, which
  11 * you should have received as part of this distribution. The terms
  12 * are also available at https://curl.se/docs/copyright.html.
  13 *
  14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15 * copies of the Software, and permit persons to whom the Software is
  16 * furnished to do so, under the terms of the COPYING file.
  17 *
  18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19 * KIND, either express or implied.
  20 *
  21 * SPDX-License-Identifier: curl
  22 *
  23 ***************************************************************************/
  24#include "curl_setup.h"
  25#include "urldata.h"
  26
  27#ifndef CURL_DISABLE_FTP
  28
  29#ifdef HAVE_NETINET_IN_H
  30#include <netinet/in.h>
  31#endif
  32#ifdef HAVE_ARPA_INET_H
  33#include <arpa/inet.h>
  34#endif
  35#ifdef HAVE_NETDB_H
  36#include <netdb.h>
  37#endif
  38#ifdef __VMS
  39#include <in.h>
  40#include <inet.h>
  41#endif
  42
  43#include "sendf.h"
  44#include "curl_addrinfo.h"
  45#include "curl_trc.h"
  46#include "if2ip.h"
  47#include "hostip.h"
  48#include "progress.h"
  49#include "transfer.h"
  50#include "escape.h"
  51#include "ftp.h"
  52#include "ftp-int.h"
  53#include "ftplistparser.h"
  54#include "curl_range.h"
  55#include "strcase.h"
  56#include "vtls/vtls.h"
  57#include "cfilters.h"
  58#include "cf-socket.h"
  59#include "connect.h"
  60#include "curlx/inet_ntop.h"
  61#include "curlx/inet_pton.h"
  62#include "select.h"
  63#include "parsedate.h" /* for the week day and month names */
  64#include "sockaddr.h" /* required for Curl_sockaddr_storage */
  65#include "multiif.h"
  66#include "url.h"
  67#include "http_proxy.h"
  68#include "curlx/strdup.h"
  69#include "curlx/strerr.h"
  70#include "curlx/strparse.h"
  71#include "curl_ctype.h"
  72
  73#ifndef NI_MAXHOST
  74#define NI_MAXHOST 1025
  75#endif
  76#ifndef INET_ADDRSTRLEN
  77#define INET_ADDRSTRLEN 16
  78#endif
  79
  80/* macro to check for a three-digit ftp status code at the start of the
  81   given string */
  82#define STATUSCODE(line) \
  83  (ISDIGIT((line)[0]) && ISDIGIT((line)[1]) && ISDIGIT((line)[2]))
  84
  85/* macro to check for the last line in an FTP server response */
  86#define LASTLINE(line) (STATUSCODE(line) && (' ' == (line)[3]))
  87
  88#ifdef CURLVERBOSE
  89/* for tracing purposes */
  90static const char * const ftp_state_names[] = {
  91  "STOP",
  92  "WAIT220",
  93  "AUTH",
  94  "USER",
  95  "PASS",
  96  "ACCT",
  97  "PBSZ",
  98  "PROT",
  99  "CCC",
 100  "PWD",
 101  "SYST",
 102  "NAMEFMT",
 103  "QUOTE",
 104  "RETR_PREQUOTE",
 105  "STOR_PREQUOTE",
 106  "LIST_PREQUOTE",
 107  "POSTQUOTE",
 108  "CWD",
 109  "MKD",
 110  "MDTM",
 111  "TYPE",
 112  "LIST_TYPE",
 113  "RETR_LIST_TYPE",
 114  "RETR_TYPE",
 115  "STOR_TYPE",
 116  "SIZE",
 117  "RETR_SIZE",
 118  "STOR_SIZE",
 119  "REST",
 120  "RETR_REST",
 121  "PORT",
 122  "PRET",
 123  "PASV",
 124  "LIST",
 125  "RETR",
 126  "STOR",
 127  "QUIT"
 128};
 129#define FTP_CSTATE(ftpc)   ((ftpc) ? ftp_state_names[(ftpc)->state] : "???")
 130
 131#endif /* CURLVERBOSE */
 132
 133/* This is the ONLY way to change FTP state! */
 134static void ftp_state_low(struct Curl_easy *data,
 135                          struct ftp_conn *ftpc,
 136                          ftpstate newstate
 137#ifdef DEBUGBUILD
 138                          , int lineno
 139#endif
 140  )
 141{
 142  if(ftpc->state != newstate) {
 143#ifdef DEBUGBUILD
 144    NOVERBOSE((void)lineno);
 145    CURL_TRC_FTP(data, "[%s] -> [%s] (line %d)", FTP_CSTATE(ftpc),
 146                 ftp_state_names[newstate], lineno);
 147#else
 148    CURL_TRC_FTP(data, "[%s] -> [%s]", FTP_CSTATE(ftpc),
 149                 ftp_state_names[newstate]);
 150#endif
 151  }
 152  ftpc->state = newstate;
 153}
 154
 155/* Local API functions */
 156#ifndef DEBUGBUILD
 157#define ftp_state(x, y, z) ftp_state_low(x, y, z)
 158#else /* !DEBUGBUILD */
 159#define ftp_state(x, y, z) ftp_state_low(x, y, z, __LINE__)
 160#endif /* DEBUGBUILD */
 161
 162static CURLcode ftp_state_mdtm(struct Curl_easy *data,
 163                               struct ftp_conn *ftpc,
 164                               struct FTP *ftp);
 165static CURLcode ftp_state_quote(struct Curl_easy *data,
 166                                struct ftp_conn *ftpc,
 167                                struct FTP *ftp,
 168                                bool init, ftpstate instate);
 169static CURLcode ftp_nb_type(struct Curl_easy *data,
 170                            struct ftp_conn *ftpc,
 171                            struct FTP *ftp,
 172                            bool ascii, ftpstate newstate);
 173static CURLcode getftpresponse(struct Curl_easy *data, size_t *nreadp,
 174                               int *ftpcodep);
 175
 176static void freedirs(struct ftp_conn *ftpc)
 177{
 178  curlx_safefree(ftpc->dirs);
 179  ftpc->dirdepth = 0;
 180  curlx_safefree(ftpc->rawpath);
 181  ftpc->file = NULL;
 182}
 183
 184static size_t numof_slashes(const char *str)
 185{
 186  const char *slashPos;
 187  size_t num = 0;
 188  do {
 189    slashPos = strchr(str, '/');
 190    if(slashPos) {
 191      ++num;
 192      str = slashPos + 1;
 193    }
 194  } while(slashPos);
 195  return num;
 196}
 197
 198#define FTP_MAX_DIR_DEPTH 1000
 199
 200/***********************************************************************
 201 *
 202 * ftp_parse_url_path()
 203 *
 204 * Parse the URL path into separate path components.
 205 *
 206 */
 207static CURLcode ftp_parse_url_path(struct Curl_easy *data,
 208                                   struct ftp_conn *ftpc,
 209                                   struct FTP *ftp)
 210{
 211  const char *slashPos = NULL;
 212  const char *fileName = NULL;
 213  CURLcode result = CURLE_OK;
 214  const char *rawPath = NULL; /* URL-decoded "raw" path */
 215  size_t pathLen = 0;
 216
 217  ftpc->ctl_valid = FALSE;
 218  ftpc->cwdfail = FALSE;
 219
 220  if(ftpc->rawpath)
 221    freedirs(ftpc);
 222  /* URL-decode ftp path before further evaluation */
 223  result = Curl_urldecode(ftp->path, 0, &ftpc->rawpath, &pathLen, REJECT_CTRL);
 224  if(result) {
 225    failf(data, "path contains control characters");
 226    return result;
 227  }
 228  rawPath = ftpc->rawpath;
 229
 230  switch(data->set.ftp_filemethod) {
 231  case FTPFILE_NOCWD: /* fastest, but less standard-compliant */
 232
 233    if((pathLen > 0) && (rawPath[pathLen - 1] != '/'))
 234      fileName = rawPath;  /* this is a full file path */
 235    /*
 236      else: ftpc->file is not used anywhere other than for operations on
 237            a file. In other words, never for directory operations,
 238            so we can safely leave filename as NULL here and use it as a
 239            argument in dir/file decisions.
 240    */
 241    break;
 242
 243  case FTPFILE_SINGLECWD:
 244    slashPos = strrchr(rawPath, '/');
 245    if(slashPos) {
 246      /* get path before last slash, except for / */
 247      size_t dirlen = slashPos - rawPath;
 248      if(dirlen == 0)
 249        dirlen = 1;
 250
 251      ftpc->dirs = curlx_calloc(1, sizeof(ftpc->dirs[0]));
 252      if(!ftpc->dirs)
 253        return CURLE_OUT_OF_MEMORY;
 254
 255      ftpc->dirs[0].start = 0;
 256      ftpc->dirs[0].len = (int)dirlen;
 257      ftpc->dirdepth = 1; /* we consider it to be a single directory */
 258      fileName = slashPos + 1; /* rest is filename */
 259    }
 260    else
 261      fileName = rawPath; /* filename only (or empty) */
 262    break;
 263
 264  default: /* allow pretty much anything */
 265  case FTPFILE_MULTICWD: {
 266    /* current position: begin of next path component */
 267    const char *curPos = rawPath;
 268
 269    /* number of entries to allocate for the 'dirs' array */
 270    size_t dirAlloc = numof_slashes(rawPath);
 271
 272    if(dirAlloc >= FTP_MAX_DIR_DEPTH)
 273      /* suspiciously deep directory hierarchy */
 274      return CURLE_URL_MALFORMAT;
 275
 276    if(dirAlloc) {
 277      ftpc->dirs = curlx_calloc(dirAlloc, sizeof(ftpc->dirs[0]));
 278      if(!ftpc->dirs)
 279        return CURLE_OUT_OF_MEMORY;
 280
 281      /* parse the URL path into separate path components */
 282      while(dirAlloc--) {
 283        const char *spos = strchr(curPos, '/');
 284        size_t clen = spos - curPos;
 285
 286        /* path starts with a slash: add that as a directory */
 287        if(!clen && (ftpc->dirdepth == 0))
 288          ++clen;
 289
 290        /* we skip empty path components, like "x//y" since the FTP command
 291           CWD requires a parameter and a non-existent parameter a) does not
 292           work on many servers and b) has no effect on the others. */
 293        if(clen) {
 294          ftpc->dirs[ftpc->dirdepth].start = (int)(curPos - rawPath);
 295          ftpc->dirs[ftpc->dirdepth].len = (int)clen;
 296          ftpc->dirdepth++;
 297        }
 298        curPos = spos + 1;
 299      }
 300    }
 301    fileName = curPos; /* the rest is the filename (or empty) */
 302  }
 303    break;
 304  } /* switch */
 305
 306  if(fileName && *fileName)
 307    ftpc->file = fileName;
 308  else
 309    ftpc->file = NULL; /* instead of point to a zero byte,
 310                          we make it a NULL pointer */
 311
 312  if(data->state.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) {
 313    /* We need a filename when uploading. Return error! */
 314    failf(data, "Uploading to a URL without a filename");
 315    return CURLE_URL_MALFORMAT;
 316  }
 317
 318  ftpc->cwddone = FALSE; /* default to not done */
 319
 320  if((data->set.ftp_filemethod == FTPFILE_NOCWD) && (rawPath[0] == '/'))
 321    ftpc->cwddone = TRUE; /* skip CWD for absolute paths */
 322  else { /* newly created FTP connections are already in entry path */
 323    const char *oldPath = data->conn->bits.reuse ? ftpc->prevpath : "";
 324    if(oldPath) {
 325      size_t n = pathLen;
 326      if(data->set.ftp_filemethod == FTPFILE_NOCWD)
 327        n = 0; /* CWD to entry for relative paths */
 328      else
 329        n -= ftpc->file ? strlen(ftpc->file) : 0;
 330
 331      if((strlen(oldPath) == n) && rawPath && !strncmp(rawPath, oldPath, n)) {
 332        infof(data, "Request has same path as previous transfer");
 333        ftpc->cwddone = TRUE;
 334      }
 335    }
 336  }
 337
 338  return CURLE_OK;
 339}
 340
 341/***********************************************************************
 342 *
 343 * ftp_need_type()
 344 *
 345 * Returns TRUE if we in the current situation should send TYPE
 346 */
 347static int ftp_need_type(struct ftp_conn *ftpc,
 348                         bool ascii_wanted)
 349{
 350  return ftpc->transfertype != (ascii_wanted ? 'A' : 'I');
 351}
 352
 353static void close_secondarysocket(struct Curl_easy *data,
 354                                  struct ftp_conn *ftpc)
 355{
 356  (void)ftpc;
 357  CURL_TRC_FTP(data, "[%s] closing DATA connection", FTP_CSTATE(ftpc));
 358  Curl_conn_close(data, SECONDARYSOCKET);
 359  Curl_conn_cf_discard_all(data, data->conn, SECONDARYSOCKET);
 360}
 361
 362#ifdef CURL_PREFER_LF_LINEENDS
 363/*
 364 * Lineend Conversions
 365 * On ASCII transfers, e.g. directory listings, we might get lines
 366 * ending in '\r\n' and we prefer '\n'.
 367 * We might also get a lonely '\r' which we convert into a '\n'.
 368 */
 369struct ftp_cw_lc_ctx {
 370  struct Curl_cwriter super;
 371  bool newline_pending;
 372};
 373
 374static CURLcode ftp_cw_lc_write(struct Curl_easy *data,
 375                                struct Curl_cwriter *writer, int type,
 376                                const char *buf, size_t blen)
 377{
 378  static const char nl = '\n';
 379  struct ftp_cw_lc_ctx *ctx = writer->ctx;
 380  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
 381
 382  if(!ftpc)
 383    return CURLE_FAILED_INIT;
 384
 385  if(!(type & CLIENTWRITE_BODY) || ftpc->transfertype != 'A')
 386    return Curl_cwriter_write(data, writer->next, type, buf, blen);
 387
 388  /* ASCII mode BODY data, convert lineends */
 389  while(blen) {
 390    /* do not pass EOS when writing parts */
 391    int chunk_type = (type & ~CLIENTWRITE_EOS);
 392    const char *cp;
 393    size_t chunk_len;
 394    CURLcode result;
 395
 396    if(ctx->newline_pending) {
 397      if(buf[0] != '\n') {
 398        /* previous chunk ended in '\r' and we do not see a '\n' in this one,
 399         * need to write a newline. */
 400        result = Curl_cwriter_write(data, writer->next, chunk_type, &nl, 1);
 401        if(result)
 402          return result;
 403      }
 404      /* either we wrote the newline or it is part of the next chunk of bytes
 405       * we write. */
 406      ctx->newline_pending = FALSE;
 407    }
 408
 409    cp = memchr(buf, '\r', blen);
 410    if(!cp)
 411      break;
 412
 413    /* write the bytes before the '\r', excluding the '\r' */
 414    chunk_len = cp - buf;
 415    if(chunk_len) {
 416      result = Curl_cwriter_write(data, writer->next, chunk_type,
 417                                  buf, chunk_len);
 418      if(result)
 419        return result;
 420    }
 421    /* skip the '\r', we now have a newline pending */
 422    buf = cp + 1;
 423    blen = blen - chunk_len - 1;
 424    ctx->newline_pending = TRUE;
 425  }
 426
 427  /* Any remaining data does not contain a '\r' */
 428  if(blen) {
 429    DEBUGASSERT(!ctx->newline_pending);
 430    return Curl_cwriter_write(data, writer->next, type, buf, blen);
 431  }
 432  else if(type & CLIENTWRITE_EOS) {
 433    /* EndOfStream, if we have a trailing cr, now is the time to write it */
 434    if(ctx->newline_pending) {
 435      ctx->newline_pending = FALSE;
 436      return Curl_cwriter_write(data, writer->next, type, &nl, 1);
 437    }
 438    /* Always pass on the EOS type indicator */
 439    return Curl_cwriter_write(data, writer->next, type, buf, 0);
 440  }
 441  return CURLE_OK;
 442}
 443
 444static const struct Curl_cwtype ftp_cw_lc = {
 445  "ftp-lineconv",
 446  NULL,
 447  Curl_cwriter_def_init,
 448  ftp_cw_lc_write,
 449  Curl_cwriter_def_close,
 450  sizeof(struct ftp_cw_lc_ctx)
 451};
 452
 453#endif /* CURL_PREFER_LF_LINEENDS */
 454
 455/***********************************************************************
 456 *
 457 * ftp_check_ctrl_on_data_wait()
 458 *
 459 */
 460static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data,
 461                                            struct ftp_conn *ftpc)
 462{
 463  struct connectdata *conn = data->conn;
 464  curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
 465  struct pingpong *pp = &ftpc->pp;
 466  size_t nread;
 467  int ftpcode;
 468  bool response = FALSE;
 469
 470  /* First check whether there is a cached response from server */
 471  if(curlx_dyn_len(&pp->recvbuf)) {
 472    const char *l = curlx_dyn_ptr(&pp->recvbuf);
 473    if(!ISDIGIT(*l) || (*l > '3')) {
 474      /* Data connection could not be established, let's return */
 475      infof(data, "There is negative response in cache while serv connect");
 476      (void)getftpresponse(data, &nread, &ftpcode);
 477      return CURLE_FTP_ACCEPT_FAILED;
 478    }
 479  }
 480
 481  if(pp->overflow)
 482    /* there is pending control data still in the buffer to read */
 483    response = TRUE;
 484  else {
 485    int socketstate = SOCKET_READABLE(ctrl_sock, 0);
 486    /* see if the connection request is already here */
 487    switch(socketstate) {
 488    case -1: /* error */
 489      /* let's die here */
 490      failf(data, "Error while waiting for server connect");
 491      return CURLE_FTP_ACCEPT_FAILED;
 492    default:
 493      if(socketstate & CURL_CSELECT_IN)
 494        response = TRUE;
 495      break;
 496    }
 497  }
 498
 499  if(response) {
 500    infof(data, "Ctrl conn has data while waiting for data conn");
 501    if(pp->overflow > 3) {
 502      const char *r = curlx_dyn_ptr(&pp->recvbuf);
 503      size_t len = curlx_dyn_len(&pp->recvbuf);
 504
 505      DEBUGASSERT((pp->overflow + pp->nfinal) <= curlx_dyn_len(&pp->recvbuf));
 506      /* move over the most recently handled response line */
 507      r += pp->nfinal;
 508      len -= pp->nfinal;
 509
 510      if((len > 3) && LASTLINE(r)) {
 511        curl_off_t status;
 512        if(!curlx_str_number(&r, &status, 999) && (status == 226)) {
 513          /* funny timing situation where we get the final message on the
 514             control connection before traffic on the data connection has been
 515             noticed. Leave the 226 in there and use this as a trigger to read
 516             the data socket. */
 517          infof(data, "Got 226 before data activity");
 518          return CURLE_OK;
 519        }
 520      }
 521    }
 522
 523    (void)getftpresponse(data, &nread, &ftpcode);
 524
 525    infof(data, "FTP code: %03d", ftpcode);
 526
 527    if(ftpcode / 100 > 3)
 528      return CURLE_FTP_ACCEPT_FAILED;
 529
 530    return CURLE_WEIRD_SERVER_REPLY;
 531  }
 532
 533  return CURLE_OK;
 534}
 535
 536/***********************************************************************
 537 *
 538 * ftp_initiate_transfer()
 539 *
 540 * After connection from server is accepted this function is called to
 541 * setup transfer parameters and initiate the data transfer.
 542 *
 543 */
 544static CURLcode ftp_initiate_transfer(struct Curl_easy *data,
 545                                      struct ftp_conn *ftpc)
 546{
 547  CURLcode result = CURLE_OK;
 548  bool connected;
 549
 550  CURL_TRC_FTP(data, "ftp_initiate_transfer()");
 551  result = Curl_conn_connect(data, SECONDARYSOCKET, TRUE, &connected);
 552  if(result || !connected)
 553    return result;
 554
 555  if(data->state.upload) {
 556    /* When we know we are uploading a specified file, we can get the file
 557       size prior to the actual upload. */
 558    Curl_pgrsSetUploadSize(data, data->state.infilesize);
 559
 560    /* FTP upload, shutdown DATA, ignore shutdown errors, as we rely
 561     * on the server response on the CONTROL connection. */
 562    Curl_xfer_setup_send(data, SECONDARYSOCKET);
 563    Curl_xfer_set_shutdown(data, TRUE, TRUE);
 564  }
 565  else {
 566    /* FTP download, shutdown, do not ignore errors */
 567    Curl_xfer_setup_recv(data, SECONDARYSOCKET, data->req.size);
 568    Curl_xfer_set_shutdown(data, TRUE, FALSE);
 569  }
 570
 571  ftpc->pp.pending_resp = TRUE; /* expect server response */
 572  ftp_state(data, ftpc, FTP_STOP);
 573
 574  return CURLE_OK;
 575}
 576
 577static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
 578                          const char *line, size_t len, int *code)
 579{
 580  curl_off_t status;
 581  (void)data;
 582  (void)conn;
 583
 584  if((len > 3) && LASTLINE(line) && !curlx_str_number(&line, &status, 999)) {
 585    *code = (int)status;
 586    return TRUE;
 587  }
 588
 589  return FALSE;
 590}
 591
 592static CURLcode ftp_readresp(struct Curl_easy *data,
 593                             struct ftp_conn *ftpc,
 594                             int sockindex,
 595                             struct pingpong *pp,
 596                             int *ftpcodep, /* return the ftp-code if done */
 597                             size_t *size) /* size of the response */
 598{
 599  int code;
 600  CURLcode result = Curl_pp_readresp(data, sockindex, pp, &code, size);
 601  DEBUGASSERT(ftpcodep);
 602
 603  /* store the latest code for later retrieval, except during shutdown */
 604  if(!ftpc->shutdown)
 605    data->info.httpcode = code;
 606
 607  *ftpcodep = code;
 608
 609  if(code == 421) {
 610    /* 421 means "Service not available, closing control connection." and FTP
 611     * servers use it to signal that idle session timeout has been exceeded.
 612     * If we ignored the response, it could end up hanging in some cases.
 613     *
 614     * This response code can come at any point so having it treated
 615     * generically is a good idea.
 616     */
 617    infof(data, "We got a 421 - timeout");
 618    ftp_state(data, ftpc, FTP_STOP);
 619    return CURLE_OPERATION_TIMEDOUT;
 620  }
 621
 622  return result;
 623}
 624
 625/* --- parse FTP server responses --- */
 626
 627/*
 628 * getftpresponse() is a BLOCKING function to read the full response from a
 629 * server after a command.
 630 *
 631 */
 632static CURLcode getftpresponse(struct Curl_easy *data,
 633                               size_t *nreadp, /* return number of bytes
 634                                                  read */
 635                               int *ftpcodep) /* return the ftp-code */
 636{
 637  /*
 638   * We cannot read one byte per read() and then go back to select() as the
 639   * OpenSSL read() does not grok that properly.
 640   *
 641   * Alas, read as much as possible, split up into lines, use the ending
 642   * line in a response or continue reading. */
 643
 644  struct connectdata *conn = data->conn;
 645  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
 646  CURLcode result = CURLE_OK;
 647  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
 648  struct pingpong *pp = &ftpc->pp;
 649  size_t nread;
 650  int cache_skip = 0;
 651  DEBUGASSERT(ftpcodep);
 652
 653  CURL_TRC_FTP(data, "getftpresponse start");
 654  *nreadp = 0;
 655  *ftpcodep = 0; /* 0 for errors */
 656
 657  if(!ftpc)
 658    return CURLE_FAILED_INIT;
 659
 660  while(!*ftpcodep && !result) {
 661    /* check and reset timeout value every lap */
 662    timediff_t timeout = Curl_pp_state_timeleft_ms(data, pp);
 663    timediff_t interval_ms;
 664
 665    if(timeout <= 0) {
 666      failf(data, "FTP response timeout");
 667      return CURLE_OPERATION_TIMEDOUT; /* already too little time */
 668    }
 669
 670    interval_ms = 1000;  /* use 1 second timeout intervals */
 671    if(timeout < interval_ms)
 672      interval_ms = timeout;
 673
 674    /*
 675     * Since this function is blocking, we need to wait here for input on the
 676     * connection and only then we call the response reading function. We do
 677     * timeout at least every second to make the timeout check run.
 678     *
 679     * A caution here is that the ftp_readresp() function has a cache that may
 680     * contain pieces of a response from the previous invoke and we need to
 681     * make sure we do not wait for input while there is unhandled data in
 682     * that cache. Also, if the cache is there, we call ftp_readresp() and
 683     * the cache was not good enough to continue we must not busy-loop around
 684     * this function.
 685     *
 686     */
 687
 688    if(curlx_dyn_len(&pp->recvbuf) && (cache_skip < 2)) {
 689      /*
 690       * There is a cache left since before. We then skipping the wait for
 691       * socket action, unless this is the same cache like the previous round
 692       * as then the cache was deemed not enough to act on and we then need to
 693       * wait for more data anyway.
 694       */
 695    }
 696    else if(!Curl_conn_data_pending(data, FIRSTSOCKET)) {
 697      curl_socket_t wsock = Curl_pp_needs_flush(data, pp) ?
 698        sockfd : CURL_SOCKET_BAD;
 699      int ev = Curl_socket_check(sockfd, CURL_SOCKET_BAD, wsock, interval_ms);
 700      if(ev < 0) {
 701        failf(data, "FTP response aborted due to select/poll error: %d",
 702              SOCKERRNO);
 703        return CURLE_RECV_ERROR;
 704      }
 705      else if(ev == 0) {
 706        result = Curl_pgrsUpdate(data);
 707        continue; /* continue in our loop for the timeout duration */
 708      }
 709    }
 710
 711    if(Curl_pp_needs_flush(data, pp)) {
 712      result = Curl_pp_flushsend(data, pp);
 713      if(result)
 714        break;
 715    }
 716
 717    result = ftp_readresp(data, ftpc, FIRSTSOCKET, pp, ftpcodep, &nread);
 718    if(result)
 719      break;
 720
 721    if(!nread && curlx_dyn_len(&pp->recvbuf))
 722      /* bump cache skip counter as on repeated skips we must wait for more
 723         data */
 724      cache_skip++;
 725    else
 726      /* when we got data or there is no cache left, we reset the cache skip
 727         counter */
 728      cache_skip = 0;
 729
 730    *nreadp += nread;
 731
 732  } /* while there is buffer left and loop is requested */
 733
 734  pp->pending_resp = FALSE;
 735  CURL_TRC_FTP(data, "getftpresponse -> result=%d, nread=%zu, ftpcode=%d",
 736               result, *nreadp, *ftpcodep);
 737
 738  return result;
 739}
 740
 741static CURLcode ftp_state_user(struct Curl_easy *data,
 742                               struct ftp_conn *ftpc,
 743                               struct connectdata *conn)
 744{
 745  CURLcode result = Curl_pp_sendf(data, &ftpc->pp, "USER %s",
 746                                  Curl_creds_user(conn->creds));
 747  if(!result) {
 748    ftpc->ftp_trying_alternative = FALSE;
 749    ftp_state(data, ftpc, FTP_USER);
 750  }
 751  return result;
 752}
 753
 754static CURLcode ftp_state_pwd(struct Curl_easy *data,
 755                              struct ftp_conn *ftpc)
 756{
 757  CURLcode result;
 758#ifdef DEBUGBUILD
 759  if(!data->id && getenv("CURL_FTP_PWD_STOP"))
 760    return CURLE_OK;
 761#endif
 762  result = Curl_pp_sendf(data, &ftpc->pp, "%s", "PWD");
 763  if(!result)
 764    ftp_state(data, ftpc, FTP_PWD);
 765
 766  return result;
 767}
 768
 769/* For the FTP "protocol connect" and "doing" phases only */
 770static CURLcode ftp_pollset(struct Curl_easy *data,
 771                            struct easy_pollset *ps)
 772{
 773  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
 774  return ftpc ? Curl_pp_pollset(data, &ftpc->pp, ps) : CURLE_OK;
 775}
 776
 777/* For the FTP "DO_MORE" phase only */
 778static CURLcode ftp_domore_pollset(struct Curl_easy *data,
 779                                   struct easy_pollset *ps)
 780{
 781  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
 782
 783  if(!ftpc)
 784    return CURLE_OK;
 785
 786  /* When in DO_MORE state, we could be either waiting for us to connect to a
 787   * remote site, or we could wait for that site to connect to us. Or handle
 788   * ordinary commands.
 789   */
 790  CURL_TRC_FTP(data, "[%s] ftp_domore_pollset()", FTP_CSTATE(ftpc));
 791
 792  if(FTP_STOP == ftpc->state) {
 793    /* if stopped and still in this state, then we are also waiting for a
 794       connect on the secondary connection */
 795    DEBUGASSERT(data->conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD ||
 796                (data->conn->cfilter[SECONDARYSOCKET] &&
 797                 !Curl_conn_is_connected(data->conn, SECONDARYSOCKET)));
 798    /* An unconnected SECONDARY will add its socket by itself
 799     * via its adjust_pollset() */
 800    return Curl_pollset_add_in(data, ps, data->conn->sock[FIRSTSOCKET]);
 801  }
 802  return Curl_pp_pollset(data, &ftpc->pp, ps);
 803}
 804
 805static int pathlen(struct ftp_conn *ftpc, int num)
 806{
 807  DEBUGASSERT(ftpc->dirs);
 808  DEBUGASSERT(ftpc->dirdepth > num);
 809  return ftpc->dirs[num].len;
 810}
 811
 812static const char *pathpiece(struct ftp_conn *ftpc, int num)
 813{
 814  DEBUGASSERT(ftpc->dirs);
 815  DEBUGASSERT(ftpc->dirdepth > num);
 816  return &ftpc->rawpath[ftpc->dirs[num].start];
 817}
 818
 819/* This is called after the FTP_QUOTE state is passed.
 820
 821   ftp_state_cwd() sends the range of CWD commands to the server to change to
 822   the correct directory. It may also need to send MKD commands to create
 823   missing ones, if that option is enabled.
 824*/
 825static CURLcode ftp_state_cwd(struct Curl_easy *data,
 826                              struct ftp_conn *ftpc,
 827                              struct FTP *ftp)
 828{
 829  CURLcode result = CURLE_OK;
 830
 831  if(ftpc->cwddone)
 832    /* already done and fine */
 833    result = ftp_state_mdtm(data, ftpc, ftp);
 834  else {
 835    /* FTPFILE_NOCWD with full path: expect ftpc->cwddone! */
 836    DEBUGASSERT((data->set.ftp_filemethod != FTPFILE_NOCWD) ||
 837                !(ftpc->dirdepth && ftpc->rawpath[0] == '/'));
 838
 839    ftpc->count2 = 0; /* count2 counts failed CWDs */
 840
 841    if(data->conn->bits.reuse && ftpc->entrypath &&
 842       /* no need to go to entrypath when we have an absolute path */
 843       !(ftpc->dirdepth && ftpc->rawpath[0] == '/')) {
 844      /* This is a reused connection. Since we change directory to where the
 845         transfer is taking place, we must first get back to the original dir
 846         where we ended up after login: */
 847      ftpc->cwdcount = 0; /* we count this as the first path, then we add one
 848                             for all upcoming ones in the ftp->dirs[] array */
 849      result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->entrypath);
 850      if(!result)
 851        ftp_state(data, ftpc, FTP_CWD);
 852    }
 853    else {
 854      if(ftpc->dirdepth) {
 855        ftpc->cwdcount = 1;
 856        /* issue the first CWD, the rest is sent when the CWD responses are
 857           received... */
 858        result = Curl_pp_sendf(data, &ftpc->pp, "CWD %.*s",
 859                               pathlen(ftpc, 0), pathpiece(ftpc, 0));
 860        if(!result)
 861          ftp_state(data, ftpc, FTP_CWD);
 862      }
 863      else {
 864        /* No CWD necessary */
 865        result = ftp_state_mdtm(data, ftpc, ftp);
 866      }
 867    }
 868  }
 869  return result;
 870}
 871
 872typedef enum {
 873  EPRT,
 874  PORT,
 875  DONE
 876} ftpport;
 877
 878/*
 879 * Parse the CURLOPT_FTPPORT string
 880 * "(ipv4|ipv6|domain|interface)?(:port(-range)?)?"
 881 * and extract addr/addrlen and port_min/port_max.
 882 */
 883static CURLcode ftp_port_parse_string(struct Curl_easy *data,
 884                                      struct connectdata *conn,
 885                                      const char *string_ftpport,
 886                                      struct Curl_sockaddr_storage *ss,
 887                                      unsigned short *port_minp,
 888                                      unsigned short *port_maxp,
 889                                      const char **hostp,
 890                                      char *hbuf, size_t hbuflen)
 891{
 892  const char *ip_end = NULL;
 893  const char *addr = NULL;
 894  size_t addrlen = 0;
 895  unsigned short port_min = 0;
 896  unsigned short port_max = 0;
 897  char ipstr[50];
 898#ifndef USE_IPV6
 899  (void)conn;
 900  (void)ss;
 901#endif
 902
 903  /* default to nothing */
 904  *hostp = NULL;
 905  *port_minp = *port_maxp = 0;
 906
 907  if(!string_ftpport || (strlen(string_ftpport) <= 1))
 908    goto done;
 909
 910#ifdef USE_IPV6
 911  if(*string_ftpport == '[') {
 912    /* [ipv6]:port(-range) */
 913    const char *ip_start = string_ftpport + 1;
 914    ip_end = strchr(ip_start, ']');
 915    if(ip_end) {
 916      addrlen = ip_end - ip_start;
 917      addr = ip_start;
 918    }
 919  }
 920  else
 921#endif
 922    if(*string_ftpport == ':') {
 923      /* :port */
 924      ip_end = string_ftpport;
 925    }
 926    else {
 927      ip_end = strchr(string_ftpport, ':');
 928      addr = string_ftpport;
 929      if(ip_end) {
 930#ifdef USE_IPV6
 931        struct sockaddr_in6 * const sa6 = (void *)ss;
 932#endif
 933        /* either ipv6 or (ipv4|domain|interface):port(-range) */
 934        addrlen = ip_end - string_ftpport;
 935#ifdef USE_IPV6
 936        if(curlx_inet_pton(AF_INET6, string_ftpport, &sa6->sin6_addr) == 1) {
 937          /* ipv6 */
 938          addrlen = strlen(string_ftpport);
 939          ip_end = NULL; /* this got no port ! */
 940        }
 941#endif
 942      }
 943      else
 944        /* ipv4|interface */
 945        addrlen = strlen(string_ftpport);
 946    }
 947
 948  /* parse the port */
 949  if(ip_end) {
 950    const char *portp = strchr(ip_end, ':');
 951    if(portp) {
 952      curl_off_t start;
 953      curl_off_t end;
 954      portp++;
 955      if(!curlx_str_number(&portp, &start, 0xffff)) {
 956        port_min = (unsigned short)start;
 957        if(!curlx_str_single(&portp, '-') &&
 958           !curlx_str_number(&portp, &end, 0xffff))
 959          port_max = (unsigned short)end;
 960        else
 961          port_max = port_min;
 962      }
 963    }
 964  }
 965
 966  /* correct errors like :1234-1230 or :-4711 */
 967  if(port_min > port_max)
 968    port_min = port_max = 0;
 969
 970  if(addrlen) {
 971    const struct Curl_sockaddr_ex *remote_addr =
 972      Curl_conn_get_remote_addr(data, FIRSTSOCKET);
 973
 974    DEBUGASSERT(remote_addr);
 975    DEBUGASSERT(addr);
 976    if(!remote_addr || (addrlen >= sizeof(ipstr)) || (addrlen >= hbuflen))
 977      return CURLE_FTP_PORT_FAILED;
 978    memcpy(ipstr, addr, addrlen);
 979    ipstr[addrlen] = 0;
 980
 981    /* attempt to get the address of the given interface name */
 982    switch(Curl_if2ip(remote_addr->family,
 983#ifdef USE_IPV6
 984                      Curl_ipv6_scope(&remote_addr->curl_sa_addr),
 985                      conn->scope_id,
 986#endif
 987                      ipstr, hbuf, hbuflen)) {
 988    case IF2IP_NOT_FOUND:
 989      /* not an interface, use the string as hostname instead */
 990      memcpy(hbuf, addr, addrlen);
 991      hbuf[addrlen] = 0;
 992      *hostp = hbuf;
 993      break;
 994    case IF2IP_AF_NOT_SUPPORTED:
 995      return CURLE_FTP_PORT_FAILED;
 996    case IF2IP_FOUND:
 997      *hostp = hbuf; /* use the hbuf for hostname */
 998      break;
 999    }
1000  }
1001  /* else: only a port(-range) given, leave host as NULL */
1002
1003done:
1004  *port_minp = port_min;
1005  *port_maxp = port_max;
1006  return CURLE_OK;
1007}
1008
1009/*
1010 * If no host was derived from the FTPPORT string, fall back to the IP address
1011 * of the control connection's local socket.
1012 */
1013static CURLcode ftp_port_default_host(struct Curl_easy *data,
1014                                      struct connectdata *conn,
1015                                      struct Curl_sockaddr_storage *ss,
1016                                      curl_socklen_t *sslenp,
1017                                      const char **hostp,
1018                                      char *hbuf, size_t hbuflen,
1019                                      bool *non_localp)
1020{
1021  struct sockaddr *sa = (struct sockaddr *)ss;
1022  struct sockaddr_in * const sa4 = (void *)sa;
1023#ifdef USE_IPV6
1024  struct sockaddr_in6 * const sa6 = (void *)sa;
1025#endif
1026  char buffer[STRERROR_LEN];
1027  const char *r;
1028
1029  *sslenp = sizeof(*ss);
1030  if(getsockname(conn->sock[FIRSTSOCKET], sa, sslenp)) {
1031    failf(data, "getsockname() failed: %s",
1032          curlx_strerror(SOCKERRNO, buffer, sizeof(buffer)));
1033    return CURLE_FTP_PORT_FAILED;
1034  }
1035  switch(sa->sa_family) {
1036#ifdef USE_IPV6
1037  case AF_INET6:
1038    r = curlx_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, hbuflen);
1039    break;
1040#endif
1041  default:
1042    r = curlx_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, hbuflen);
1043    break;
1044  }
1045  if(!r)
1046    return CURLE_FTP_PORT_FAILED;
1047
1048  *hostp = hbuf;
1049  *non_localp = FALSE; /* we know it is local now */
1050  return CURLE_OK;
1051}
1052
1053/*
1054 * Resolve the host string to a list of addresses.
1055 */
1056static CURLcode ftp_port_resolve_host(struct Curl_easy *data,
1057                                      struct connectdata *conn,
1058                                      const char *host,
1059                                      struct Curl_dns_entry **dns_entryp,
1060                                      const struct Curl_addrinfo **resp)
1061{
1062  CURLcode result;
1063
1064  *resp = NULL;
1065  result = Curl_resolv_blocking(
1066    data, Curl_resolv_dns_queries(data, conn->ip_version),
1067    host, 0, Curl_conn_get_transport(data, conn), dns_entryp);
1068  if(result)
1069    failf(data, "failed to resolve the address provided to PORT: %s", host);
1070  else {
1071    DEBUGASSERT(*dns_entryp);
1072    *resp = (*dns_entryp)->addr;
1073  }
1074  return result;
1075}
1076
1077/*
1078 * Open a TCP socket for the resolved address family.
1079 */
1080static CURLcode ftp_port_open_socket(struct Curl_easy *data,
1081                                     struct connectdata *conn,
1082                                     const struct Curl_addrinfo *res,
1083                                     const struct Curl_addrinfo **aip,
1084                                     curl_socket_t *portsockp)
1085{
1086  char buffer[STRERROR_LEN];
1087  int error = 0;
1088  const struct Curl_addrinfo *ai;
1089  CURLcode result = CURLE_FTP_PORT_FAILED;
1090
1091  for(ai = res; ai; ai = ai->ai_next) {
1092    result =
1093      Curl_socket_open(data, ai, NULL,
1094                       Curl_conn_get_transport(data, conn), portsockp);
1095    if(result) {
1096      if(result == CURLE_OUT_OF_MEMORY)
1097        return result;
1098      result = CURLE_FTP_PORT_FAILED;
1099      error = SOCKERRNO;
1100      continue;
1101    }
1102    break;
1103  }
1104  if(!ai) {
1105    failf(data, "socket failure: %s",
1106          curlx_strerror(error, buffer, sizeof(buffer)));
1107    return CURLE_FTP_PORT_FAILED;
1108  }
1109  *aip = ai;
1110  return result;
1111}
1112
1113/*
1114 * Bind the socket to a local address and port within the requested range.
1115 * Falls back to the control-connection address if the user-requested address
1116 * is non-local.
1117 */
1118static CURLcode ftp_port_bind_socket(struct Curl_easy *data,
1119                                     struct connectdata *conn,
1120                                     curl_socket_t portsock,
1121                                     const struct Curl_addrinfo *ai,
1122                                     struct Curl_sockaddr_storage *ss,
1123                                     curl_socklen_t *sslen_io,
1124                                     unsigned short port_min,
1125                                     unsigned short port_max,
1126                                     bool non_local)
1127{
1128  struct sockaddr *sa = (struct sockaddr *)ss;
1129  struct sockaddr_in * const sa4 = (void *)sa;
1130#ifdef USE_IPV6
1131  struct sockaddr_in6 * const sa6 = (void *)sa;
1132#endif
1133  char buffer[STRERROR_LEN];
1134  unsigned short port;
1135  int error;
1136
1137  memcpy(sa, ai->ai_addr, ai->ai_addrlen);
1138  *sslen_io = ai->ai_addrlen;
1139
1140  for(port = port_min; port <= port_max;) {
1141    if(sa->sa_family == AF_INET)
1142      sa4->sin_port = htons(port);
1143#ifdef USE_IPV6
1144    else
1145      sa6->sin6_port = htons(port);
1146#endif
1147    if(bind(portsock, sa, *sslen_io)) {
1148      error = SOCKERRNO;
1149      if(non_local && (error == SOCKEADDRNOTAVAIL)) {
1150        /* The requested bind address is not local. Use the address used for
1151         * the control connection instead and restart the port loop.
1152         */
1153        infof(data, "bind(port=%hu) on non-local address failed: %s", port,
1154              curlx_strerror(error, buffer, sizeof(buffer)));
1155
1156        *sslen_io = sizeof(*ss);
1157        if(getsockname(conn->sock[FIRSTSOCKET], sa, sslen_io)) {
1158          failf(data, "getsockname() failed: %s",
1159                curlx_strerror(SOCKERRNO, buffer, sizeof(buffer)));
1160          return CURLE_FTP_PORT_FAILED;
1161        }
1162        port = port_min;
1163        non_local = FALSE; /* do not try this again */
1164        continue;
1165      }
1166      if(error != SOCKEADDRINUSE && error != SOCKEACCES) {
1167        failf(data, "bind(port=%hu) failed: %s", port,
1168              curlx_strerror(error, buffer, sizeof(buffer)));
1169        return CURLE_FTP_PORT_FAILED;
1170      }
1171    }
1172    else
1173      break;
1174
1175    /* check if port is the maximum value here, because it might be 0xffff
1176       and then the increment below will wrap the 16-bit counter */
1177    if(port == port_max) {
1178      failf(data, "bind() failed, ran out of ports");
1179      return CURLE_FTP_PORT_FAILED;
1180    }
1181    port++;
1182  }
1183
1184  /* re-read the name so we can extract the actual port chosen */
1185  *sslen_io = sizeof(*ss);
1186  if(getsockname(portsock, sa, sslen_io)) {
1187    failf(data, "getsockname() failed: %s",
1188          curlx_strerror(SOCKERRNO, buffer, sizeof(buffer)));
1189    return CURLE_FTP_PORT_FAILED;
1190  }
1191  CURL_TRC_FTP(data, "ftp_port_bind_socket(), socket bound to port %d",
1192               port);
1193  return CURLE_OK;
1194}
1195
1196/*
1197 * Start listening on the data socket.
1198 */
1199static CURLcode ftp_port_listen(struct Curl_easy *data, curl_socket_t portsock)
1200{
1201  char buffer[STRERROR_LEN];
1202
1203  if(listen(portsock, 1)) {
1204    failf(data, "socket failure: %s",
1205          curlx_strerror(SOCKERRNO, buffer, sizeof(buffer)));
1206    return CURLE_FTP_PORT_FAILED;
1207  }
1208  CURL_TRC_FTP(data, "ftp_port_listen(), listening on port");
1209  return CURLE_OK;
1210}
1211
1212/*
1213 * Send the EPRT or PORT command to the server.
1214 */
1215static CURLcode ftp_port_send_command(struct Curl_easy *data,
1216                                      struct ftp_conn *ftpc,
1217                                      struct connectdata *conn,
1218                                      struct Curl_sockaddr_storage *ss,
1219                                      const struct Curl_addrinfo *ai,
1220                                      ftpport fcmd)
1221{
1222  static const char mode[][5] = { "EPRT", "PORT" };
1223  struct sockaddr *sa = (struct sockaddr *)ss;
1224  struct sockaddr_in * const sa4 = (void *)sa;
1225#ifdef USE_IPV6
1226  struct sockaddr_in6 * const sa6 = (void *)sa;
1227#endif
1228  char myhost[MAX_IPADR_LEN + 1] = "";
1229  unsigned short port;
1230  CURLcode result;
1231
1232  /* Get a plain printable version of the numerical address to work with. This
1233     logic uses the address provided by the FTPPORT option, which at times
1234     might differ from the address in 'ss' used to bind to: when a user asks
1235     the server to connect to a specific address knowing that it works, but
1236     curl instead selects to listen to the local address because it cannot use
1237     the provided address. FTP is strange. */
1238  Curl_printable_address(ai, myhost, sizeof(myhost));
1239
1240#ifdef USE_IPV6
1241  if(!conn->bits.ftp_use_eprt && conn->bits.ipv6)
1242    /* EPRT is disabled but we are connected to an IPv6 host, so we ignore the
1243       request and enable EPRT again! */
1244    conn->bits.ftp_use_eprt = TRUE;
1245#endif
1246
1247  for(; fcmd != DONE; fcmd++) {
1248
1249    if(!conn->bits.ftp_use_eprt && (EPRT == fcmd))
1250      /* if disabled, goto next */
1251      continue;
1252
1253    if((PORT == fcmd) && sa->sa_family != AF_INET)
1254      /* PORT is IPv4 only */
1255      continue;
1256
1257    switch(sa->sa_family) {
1258    case AF_INET:
1259      port = ntohs(sa4->sin_port);
1260      break;
1261#ifdef USE_IPV6
1262    case AF_INET6:
1263      port = ntohs(sa6->sin6_port);
1264      break;
1265#endif
1266    default:
1267      continue; /* might as well skip this */
1268    }
1269
1270    if(EPRT == fcmd) {
1271      /*
1272       * Two fine examples from RFC2428;
1273       *
1274       * EPRT |1|132.235.1.2|6275|
1275       *
1276       * EPRT |2|1080::8:800:200C:417A|5282|
1277       */
1278      result = Curl_pp_sendf(data, &ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
1279                             sa->sa_family == AF_INET ? 1 : 2,
1280                             myhost, port);
1281      if(result) {
1282        failf(data, "Failure sending EPRT command: %s",
1283              curl_easy_strerror(result));
1284        return result;
1285      }
1286      break;
1287    }
1288    if(PORT == fcmd) {
1289      /* large enough for [IP address],[num],[num] */
1290      char target[sizeof(myhost) + 20];
1291      const char *source = myhost;
1292      char *dest = target;
1293
1294      /* translate x.x.x.x to x,x,x,x */
1295      while(*source) {
1296        if(*source == '.')
1297          *dest = ',';
1298        else
1299          *dest = *source;
1300        dest++;
1301        source++;
1302      }
1303      *dest = 0;
1304      curl_msnprintf(dest, 20, ",%d,%d", (int)(port >> 8), (int)(port & 0xff));
1305
1306      result = Curl_pp_sendf(data, &ftpc->pp, "%s %s", mode[fcmd], target);
1307      if(result) {
1308        failf(data, "Failure sending PORT command: %s",
1309              curl_easy_strerror(result));
1310        return result;
1311      }
1312      break;
1313    }
1314  }
1315
1316  /* store which command was sent */
1317  ftpc->count1 = fcmd;
1318  ftp_state(data, ftpc, FTP_PORT);
1319  return CURLE_OK;
1320}
1321
1322/*
1323 * ftp_state_use_port()
1324 *
1325 * Set up an active-mode FTP data connection (using PORT or EPRT) and start
1326 * listening for the server's incoming connection on SECONDARYSOCKET.
1327 */
1328static CURLcode ftp_state_use_port(struct Curl_easy *data,
1329                                   struct ftp_conn *ftpc,
1330                                   ftpport fcmd) /* start with this */
1331{
1332  CURLcode result = CURLE_FTP_PORT_FAILED;
1333  struct connectdata *conn = data->conn;
1334  curl_socket_t portsock = CURL_SOCKET_BAD;
1335
1336  struct Curl_sockaddr_storage ss;
1337  curl_socklen_t sslen;
1338  char hbuf[NI_MAXHOST];
1339  const char *host = NULL;
1340  const char *string_ftpport = data->set.str[STRING_FTPPORT];
1341  struct Curl_dns_entry *dns_entry = NULL;
1342  const struct Curl_addrinfo *res = NULL;
1343  const struct Curl_addrinfo *ai = NULL;
1344  unsigned short port_min = 0;
1345  unsigned short port_max = 0;
1346  bool non_local = TRUE;
1347
1348  /* parse the FTPPORT string for address and port range */
1349  result = ftp_port_parse_string(data, conn, string_ftpport,
1350                                 &ss, &port_min, &port_max,
1351                                 &host, hbuf, sizeof(hbuf));
1352  if(!result && !host)
1353    /* if no host was specified, use the control connection's local IP */
1354    result = ftp_port_default_host(data, conn, &ss, &sslen, &host,
1355                                   hbuf, sizeof(hbuf), &non_local);
1356
1357  /* resolve host string to address list */
1358  if(!result)
1359    result = ftp_port_resolve_host(data, conn, host, &dns_entry, &res);
1360
1361  /* Open a TCP socket for the data connection */
1362  if(!result)
1363    result = ftp_port_open_socket(data, conn, res, &ai, &portsock);
1364  if(!result) {
1365    CURL_TRC_FTP(data, "[%s] ftp_state_use_port(), opened socket",
1366                 FTP_CSTATE(ftpc));
1367
1368    /* bind to a suitable local address / port */
1369    result = ftp_port_bind_socket(data, conn, portsock, ai, &ss, &sslen,
1370                                  port_min, port_max, non_local);
1371  }
1372
1373  /* listen */
1374  if(!result)
1375    result = ftp_port_listen(data, portsock);
1376
1377  /* send the PORT / EPRT command */
1378  if(!result)
1379    result = ftp_port_send_command(data, ftpc, conn, &ss, ai, fcmd);
1380
1381  /* replace any filter on SECONDARY with one listening on this socket */
1382  if(!result)
1383    result = Curl_conn_tcp_listen_set(data, conn, SECONDARYSOCKET, &portsock);
1384
1385  if(!result)
1386    portsock = CURL_SOCKET_BAD; /* now held in filter */
1387
1388  /* cleanup */
1389
1390  if(dns_entry)
1391    Curl_dns_entry_unlink(data, &dns_entry);
1392  if(result) {
1393    ftp_state(data, ftpc, FTP_STOP);
1394  }
1395  else {
1396    /* successfully set up the listen socket filter. SSL needed? */
1397    if(conn->bits.ftp_use_data_ssl && data->set.ftp_use_port &&
1398       !Curl_conn_is_ssl(conn, SECONDARYSOCKET)) {
1399      result = Curl_ssl_cfilter_add(data, conn, SECONDARYSOCKET);
1400    }
1401    conn->bits.do_more = FALSE;
1402    Curl_pgrsTime(data, TIMER_STARTACCEPT);
1403    Curl_expire(data, (data->set.accepttimeout > 0) ?
1404                data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT,
1405                EXPIRE_FTP_ACCEPT);
1406  }
1407  if(portsock != CURL_SOCKET_BAD)
1408    Curl_socket_close(data, conn, portsock);
1409  return result;
1410}
1411
1412static CURLcode ftp_state_use_pasv(struct Curl_easy *data,
1413                                   struct ftp_conn *ftpc,
1414                                   struct connectdata *conn)
1415{
1416  CURLcode result = CURLE_OK;
1417  /*
1418    Here's the executive summary on what to do:
1419
1420    PASV is RFC959, expect:
1421    227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
1422
1423    LPSV is RFC1639, expect:
1424    228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2)
1425
1426    EPSV is RFC2428, expect:
1427    229 Entering Extended Passive Mode (|||port|)
1428
1429  */
1430
1431  static const char mode[][5] = { "EPSV", "PASV" };
1432  int modeoff;
1433
1434#ifdef PF_INET6
1435  if(!conn->bits.ftp_use_epsv && conn->bits.ipv6)
1436    /* EPSV is disabled but we are connected to an IPv6 host, so we ignore the
1437       request and enable EPSV again! */
1438    conn->bits.ftp_use_epsv = TRUE;
1439#endif
1440
1441  modeoff = conn->bits.ftp_use_epsv ? 0 : 1;
1442
1443  result = Curl_pp_sendf(data, &ftpc->pp, "%s", mode[modeoff]);
1444  if(!result) {
1445    ftpc->count1 = modeoff;
1446    ftp_state(data, ftpc, FTP_PASV);
1447    infof(data, "Connect data stream passively");
1448  }
1449  return result;
1450}
1451
1452/*
1453 * ftp_state_prepare_transfer() starts PORT, PASV or PRET etc.
1454 *
1455 * REST is the last command in the chain of commands when a "head"-like
1456 * request is made. Thus, if an actual transfer is to be made this is where we
1457 * take off for real.
1458 */
1459static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data,
1460                                           struct ftp_conn *ftpc,
1461                                           struct FTP *ftp)
1462{
1463  CURLcode result = CURLE_OK;
1464  struct connectdata *conn = data->conn;
1465
1466  if(ftp->transfer != PPTRANSFER_BODY) {
1467    /* does not transfer any data */
1468
1469    /* still possibly do PRE QUOTE jobs */
1470    ftp_state(data, ftpc, FTP_RETR_PREQUOTE);
1471    result = ftp_state_quote(data, ftpc, ftp, TRUE, FTP_RETR_PREQUOTE);
1472  }
1473  else if(data->set.ftp_use_port) {
1474    /* We have chosen to use the PORT (or similar) command */
1475    result = ftp_state_use_port(data, ftpc, EPRT);
1476  }
1477  else {
1478    /* We have chosen (this is default) to use the PASV (or similar) command */
1479    if(data->set.ftp_use_pret) {
1480      /* The user has requested that we send a PRET command
1481         to prepare the server for the upcoming PASV */
1482      if(!ftpc->file)
1483        result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s",
1484                               data->set.str[STRING_CUSTOMREQUEST] ?
1485                               data->set.str[STRING_CUSTOMREQUEST] :
1486                               (data->state.list_only ? "NLST" : "LIST"));
1487      else if(data->state.upload)
1488        result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s", ftpc->file);
1489      else
1490        result = Curl_pp_sendf(data, &ftpc->pp, "PRET RETR %s", ftpc->file);
1491      if(!result)
1492        ftp_state(data, ftpc, FTP_PRET);
1493    }
1494    else
1495      result = ftp_state_use_pasv(data, ftpc, conn);
1496  }
1497  return result;
1498}
1499
1500static CURLcode ftp_state_rest(struct Curl_easy *data,
1501                               struct ftp_conn *ftpc,
1502                               struct FTP *ftp)
1503{
1504  CURLcode result = CURLE_OK;
1505
1506  if((ftp->transfer != PPTRANSFER_BODY) && ftpc->file) {
1507    /* if a "head"-like request is being made (on a file) */
1508
1509    /* Determine if server can respond to REST command and therefore
1510       whether it supports range */
1511    result = Curl_pp_sendf(data, &ftpc->pp, "REST %d", 0);
1512    if(!result)
1513      ftp_state(data, ftpc, FTP_REST);
1514  }
1515  else
1516    result = ftp_state_prepare_transfer(data, ftpc, ftp);
1517
1518  return result;
1519}
1520
1521static CURLcode ftp_state_size(struct Curl_easy *data,
1522                               struct ftp_conn *ftpc,
1523                               struct FTP *ftp)
1524{
1525  CURLcode result = CURLE_OK;
1526
1527  if((ftp->transfer == PPTRANSFER_INFO) && ftpc->file) {
1528    /* if a "head"-like request is being made (on a file) */
1529
1530    /* we know ftpc->file is a valid pointer to a filename */
1531    result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
1532    if(!result)
1533      ftp_state(data, ftpc, FTP_SIZE);
1534  }
1535  else
1536    result = ftp_state_rest(data, ftpc, ftp);
1537
1538  return result;
1539}
1540
1541static CURLcode ftp_state_list(struct Curl_easy *data,
1542                               struct ftp_conn *ftpc,
1543                               struct FTP *ftp)
1544{
1545  CURLcode result = CURLE_OK;
1546
1547  /* If this output is to be machine-parsed, the NLST command might be better
1548     to use, since the LIST command output is not specified or standard in any
1549     way. It has turned out that the NLST list output is not the same on all
1550     servers either... */
1551
1552  /*
1553     if FTPFILE_NOCWD was specified, we should add the path
1554     as argument for the LIST / NLST / or custom command.
1555     Whether the server will support this, is uncertain.
1556
1557     The other ftp_filemethods will CWD into dir/dir/ first and
1558     then do LIST (in that case: nothing to do here)
1559  */
1560  const char *lstArg = NULL;
1561  int lstArglen = 0;
1562  char *cmd;
1563
1564  if((data->set.ftp_filemethod == FTPFILE_NOCWD) && ftp->path) {
1565    /* URL-decode before evaluation: e.g. paths starting/ending with %2f */
1566    const char *rawPath = ftpc->rawpath;
1567    const char *slashPos = strrchr(rawPath, '/');
1568    if(slashPos) {
1569      /* chop off the file part if format is dir/file otherwise remove
1570         the trailing slash for dir/dir/ except for absolute path / */
1571      size_t n = slashPos - rawPath;
1572      if(n == 0)
1573        ++n;
1574
1575      lstArg = rawPath;
1576      lstArglen = (int)n;
1577    }
1578  }
1579
1580  cmd = curl_maprintf("%s%s%.*s",
1581                      data->set.str[STRING_CUSTOMREQUEST] ?
1582                      data->set.str[STRING_CUSTOMREQUEST] :
1583                      (data->state.list_only ? "NLST" : "LIST"),
1584                      lstArg ? " " : "",
1585                      lstArglen, lstArg ? lstArg : "");
1586
1587  if(!cmd)
1588    return CURLE_OUT_OF_MEMORY;
1589
1590  result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
1591  curlx_free(cmd);
1592
1593  if(!result)
1594    ftp_state(data, ftpc, FTP_LIST);
1595
1596  return result;
1597}
1598
1599static CURLcode ftp_state_list_prequote(struct Curl_easy *data,
1600                                        struct ftp_conn *ftpc,
1601                                        struct FTP *ftp)
1602{
1603  /* We have sent the TYPE, now we must send the list of prequote strings */
1604  return ftp_state_quote(data, ftpc, ftp, TRUE, FTP_LIST_PREQUOTE);
1605}
1606
1607static CURLcode ftp_state_retr_prequote(struct Curl_easy *data,
1608                                        struct ftp_conn *ftpc,
1609                                        struct FTP *ftp)
1610{
1611  /* We have sent the TYPE, now we must send the list of prequote strings */
1612  return ftp_state_quote(data, ftpc, ftp, TRUE, FTP_RETR_PREQUOTE);
1613}
1614
1615static CURLcode ftp_state_stor_prequote(struct Curl_easy *data,
1616                                        struct ftp_conn *ftpc,
1617                                        struct FTP *ftp)
1618{
1619  /* We have sent the TYPE, now we must send the list of prequote strings */
1620  return ftp_state_quote(data, ftpc, ftp, TRUE, FTP_STOR_PREQUOTE);
1621}
1622
1623static CURLcode ftp_state_type(struct Curl_easy *data,
1624                               struct ftp_conn *ftpc,
1625                               struct FTP *ftp)
1626{
1627  CURLcode result = CURLE_OK;
1628
1629  /* If we have selected NOBODY and HEADER, it means that we only want file
1630     information. Which in FTP cannot be much more than the file size and
1631     date. */
1632  if(data->req.no_body && ftpc->file &&
1633     ftp_need_type(ftpc, (bool)data->state.prefer_ascii)) {
1634    /* The SIZE command is _not_ RFC 959 specified, and therefore many servers
1635       may not support it! It is however the only way we have to get a file's
1636       size! */
1637
1638    ftp->transfer = PPTRANSFER_INFO;
1639    /* this means no actual transfer will be made */
1640
1641    /* Some servers return different sizes for different modes, and thus we
1642       must set the proper type before we check the size */
1643    result = ftp_nb_type(data, ftpc, ftp, (bool)data->state.prefer_ascii,
1644                         FTP_TYPE);
1645    if(result)
1646      return result;
1647  }
1648  else
1649    result = ftp_state_size(data, ftpc, ftp);
1650
1651  return result;
1652}
1653
1654/* This is called after the CWD commands have been done in the beginning of
1655   the DO phase */
1656static CURLcode ftp_state_mdtm(struct Curl_easy *data,
1657                               struct ftp_conn *ftpc,
1658                               struct FTP *ftp)
1659{
1660  CURLcode result = CURLE_OK;
1661
1662  /* Requested time of file or time-depended transfer? */
1663  if((data->set.get_filetime || data->set.timecondition) && ftpc->file) {
1664
1665    /* we have requested to get the modified-time of the file, this is a white
1666       spot as the MDTM is not mentioned in RFC959 */
1667    result = Curl_pp_sendf(data, &ftpc->pp, "MDTM %s", ftpc->file);
1668
1669    if(!result)
1670      ftp_state(data, ftpc, FTP_MDTM);
1671  }
1672  else
1673    result = ftp_state_type(data, ftpc, ftp);
1674
1675  return result;
1676}
1677
1678/* This is called after the TYPE and possible quote commands have been sent */
1679static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
1680                                   struct ftp_conn *ftpc,
1681                                   struct FTP *ftp,
1682                                   bool sizechecked)
1683{
1684  CURLcode result = CURLE_OK;
1685  curl_bit append = data->set.remote_append;
1686
1687  if((data->state.resume_from && !sizechecked) ||
1688     ((data->state.resume_from > 0) && sizechecked)) {
1689    /* we are about to continue the uploading of a file
1690       1. get already existing file's size. We use the SIZE command for this
1691          which may not exist in the server!  The SIZE command is not in
1692          RFC959.
1693
1694       2. This used to set REST, but since we can do append, we issue no
1695          another ftp command. Skip the source file offset and APPEND the rest
1696          on the file instead
1697
1698       3. pass file-size number of bytes in the source file
1699       4. lower the infilesize counter */
1700    /* => transfer as usual */
1701    int seekerr = CURL_SEEKFUNC_OK;
1702
1703    if(data->state.resume_from < 0) {
1704      /* Got no given size to start from, figure it out */
1705      result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
1706      if(!result)
1707        ftp_state(data, ftpc, FTP_STOR_SIZE);
1708      return result;
1709    }
1710
1711    /* enable append */
1712    append = TRUE;
1713
1714    /* Let's read off the proper amount of bytes from the input. */
1715    if(data->set.seek_func) {
1716      Curl_set_in_callback(data, TRUE);
1717      seekerr = data->set.seek_func(data->set.seek_client,
1718                                    data->state.resume_from, SEEK_SET);
1719      Curl_set_in_callback(data, FALSE);
1720    }
1721
1722    if(seekerr != CURL_SEEKFUNC_OK) {
1723      curl_off_t passed = 0;
1724      if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
1725        failf(data, "Could not seek stream");
1726        return CURLE_FTP_COULDNT_USE_REST;
1727      }
1728      /* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */
1729      do {
1730        char scratch[4 * 1024];
1731        size_t readthisamountnow =
1732          (data->state.resume_from - passed > (curl_off_t)sizeof(scratch)) ?
1733          sizeof(scratch) :
1734          curlx_sotouz(data->state.resume_from - passed);
1735
1736        size_t actuallyread =
1737          data->state.fread_func(scratch, 1, readthisamountnow,
1738                                 data->state.in);
1739
1740        passed += actuallyread;
1741        if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
1742          /* this checks for greater-than only to make sure that the
1743             CURL_READFUNC_ABORT return code still aborts */
1744          failf(data, "Failed to read data");
1745          return CURLE_FTP_COULDNT_USE_REST;
1746        }
1747      } while(passed < data->state.resume_from);
1748    }
1749    /* now, decrease the size of the read */
1750    if(data->state.infilesize > 0) {
1751      data->state.infilesize -= data->state.resume_from;
1752
1753      if(data->state.infilesize <= 0) {
1754        infof(data, "File already completely uploaded");
1755
1756        /* no data to transfer */
1757        Curl_xfer_setup_nop(data);
1758
1759        /* Set ->transfer so that we will not get any error in
1760         * ftp_done() because we did not transfer anything! */
1761        ftp->transfer = PPTRANSFER_NONE;
1762
1763        ftp_state(data, ftpc, FTP_STOP);
1764        return CURLE_OK;
1765      }
1766    }
1767    /* we have passed, proceed as normal */
1768  } /* resume_from */
1769
1770  result = Curl_pp_sendf(data, &ftpc->pp, append ? "APPE %s" : "STOR %s",
1771                         ftpc->file);
1772  if(!result)
1773    ftp_state(data, ftpc, FTP_STOR);
1774
1775  return result;
1776}
1777
1778static CURLcode ftp_state_retr(struct Curl_easy *data,
1779                               struct ftp_conn *ftpc,
1780                               struct FTP *ftp,
1781                               curl_off_t filesize)
1782{
1783  CURLcode result = CURLE_OK;
1784
1785  CURL_TRC_FTP(data, "[%s] ftp_state_retr()", FTP_CSTATE(ftpc));
1786  if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
1787    failf(data, "Maximum file size exceeded");
1788    return CURLE_FILESIZE_EXCEEDED;
1789  }
1790  ftp->downloadsize = filesize;
1791
1792  if(data->state.resume_from) {
1793    /* We always (attempt to) get the size of downloads, so it is done before
1794       this even when not doing resumes. */
1795    if(filesize == -1) {
1796      infof(data, "ftp server does not support SIZE");
1797      /* We could not get the size and therefore we cannot know if there
1798         really is a part of the file left to get, although the server will
1799         close the connection when we start the connection so it will not
1800         cause us any harm, not make us exit as nicely. */
1801    }
1802    else {
1803      /* We got a file size report, so we check that there actually is a
1804         part of the file left to get, or else we go home. */
1805      if(data->state.resume_from < 0) {
1806        /* We are supposed to download the last abs(from) bytes */
1807        if(filesize < -data->state.resume_from) {
1808          failf(data, "Offset (%" FMT_OFF_T
1809                ") was beyond file size (%" FMT_OFF_T ")",
1810                data->state.resume_from, filesize);
1811          return CURLE_BAD_DOWNLOAD_RESUME;
1812        }
1813        /* convert to size to download */
1814        ftp->downloadsize = -data->state.resume_from;
1815        /* download from where? */
1816        data->state.resume_from = filesize - ftp->downloadsize;
1817      }
1818      else {
1819        if(filesize < data->state.resume_from) {
1820          failf(data, "Offset (%" FMT_OFF_T
1821                ") was beyond file size (%" FMT_OFF_T ")",
1822                data->state.resume_from, filesize);
1823          return CURLE_BAD_DOWNLOAD_RESUME;
1824        }
1825        /* Now store the number of bytes we are expected to download */
1826        ftp->downloadsize = filesize - data->state.resume_from;
1827      }
1828    }
1829
1830    if(ftp->downloadsize == 0) {
1831      /* no data to transfer */
1832      Curl_xfer_setup_nop(data);
1833      infof(data, "File already completely downloaded");
1834
1835      /* Set ->transfer so that we will not get any error in ftp_done()
1836       * because we did not transfer the any file */
1837      ftp->transfer = PPTRANSFER_NONE;
1838      ftp_state(data, ftpc, FTP_STOP);
1839      return CURLE_OK;
1840    }
1841
1842    /* Set resume file transfer offset */
1843    infof(data, "Instructs server to resume from offset %" FMT_OFF_T,
1844          data->state.resume_from);
1845
1846    result = Curl_pp_sendf(data, &ftpc->pp, "REST %" FMT_OFF_T,
1847                           data->state.resume_from);
1848    if(!result)
1849      ftp_state(data, ftpc, FTP_RETR_REST);
1850  }
1851  else {
1852    /* no resume */
1853    result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
1854    if(!result)
1855      ftp_state(data, ftpc, FTP_RETR);
1856  }
1857
1858  return result;
1859}
1860
1861static CURLcode ftp_state_quote(struct Curl_easy *data,
1862                                struct ftp_conn *ftpc,
1863                                struct FTP *ftp,
1864                                bool init,
1865                                ftpstate instate)
1866{
1867  CURLcode result = CURLE_OK;
1868  bool quote = FALSE;
1869  struct curl_slist *item;
1870
1871  switch(instate) {
1872  case FTP_QUOTE:
1873  default:
1874    item = data->set.quote;
1875    break;
1876  case FTP_RETR_PREQUOTE:
1877  case FTP_STOR_PREQUOTE:
1878  case FTP_LIST_PREQUOTE:
1879    item = data->set.prequote;
1880    break;
1881  case FTP_POSTQUOTE:
1882    item = data->set.postquote;
1883    break;
1884  }
1885
1886  /*
1887   * This state uses:
1888   * 'count1' to iterate over the commands to send
1889   * 'count2' to store whether to allow commands to fail
1890   */
1891
1892  if(init)
1893    ftpc->count1 = 0;
1894  else
1895    ftpc->count1++;
1896
1897  if(item) {
1898    int i = 0;
1899
1900    /* Skip count1 items in the linked list */
1901    while((i < ftpc->count1) && item) {
1902      item = item->next;
1903      i++;
1904    }
1905    if(item) {
1906      const char *cmd = item->data;
1907      if(cmd[0] == '*') {
1908        cmd++;
1909        ftpc->count2 = 1; /* the sent command is allowed to fail */
1910      }
1911      else
1912        ftpc->count2 = 0; /* failure means cancel operation */
1913
1914      result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
1915      if(result)
1916        return result;
1917      ftp_state(data, ftpc, instate);
1918      quote = TRUE;
1919    }
1920  }
1921
1922  if(!quote) {
1923    /* No more quote to send, continue to ... */
1924    switch(instate) {
1925    case FTP_QUOTE:
1926    default:
1927      result = ftp_state_cwd(data, ftpc, ftp);
1928      break;
1929    case FTP_RETR_PREQUOTE:
1930      if(ftp->transfer != PPTRANSFER_BODY)
1931        ftp_state(data, ftpc, FTP_STOP);
1932      else {
1933        if(ftpc->known_filesize != -1) {
1934          Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
1935          result = ftp_state_retr(data, ftpc, ftp, ftpc->known_filesize);
1936        }
1937        else {
1938          if(data->set.ignorecl || data->state.prefer_ascii) {
1939            /* 'ignorecl' is used to support download of growing files. It
1940               prevents the state machine from requesting the file size from
1941               the server. With an unknown file size the download continues
1942               until the server terminates it, otherwise the client stops if
1943               the received byte count exceeds the reported file size. Set
1944               option CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this
1945               behavior.
1946
1947               In addition: asking for the size for 'TYPE A' transfers is not
1948               constructive since servers do not report the converted size.
1949               Thus, skip it.
1950            */
1951            result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
1952            if(!result)
1953              ftp_state(data, ftpc, FTP_RETR);
1954          }
1955          else {
1956            result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
1957            if(!result)
1958              ftp_state(data, ftpc, FTP_RETR_SIZE);
1959          }
1960        }
1961      }
1962      break;
1963    case FTP_STOR_PREQUOTE:
1964      result = ftp_state_ul_setup(data, ftpc, ftp, FALSE);
1965      break;
1966    case FTP_POSTQUOTE:
1967      break;
1968    case FTP_LIST_PREQUOTE:
1969      ftp_state(data, ftpc, FTP_LIST_TYPE);
1970      result = ftp_state_list(data, ftpc, ftp);
1971      break;
1972    }
1973  }
1974
1975  return result;
1976}
1977
1978/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV
1979   problems */
1980static CURLcode ftp_epsv_disable(struct Curl_easy *data,
1981                                 struct ftp_conn *ftpc,
1982                                 struct connectdata *conn)
1983{
1984  CURLcode result = CURLE_OK;
1985
1986  if(conn->bits.ipv6
1987#ifndef CURL_DISABLE_PROXY
1988     && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)
1989#endif
1990    ) {
1991    /* We cannot disable EPSV when doing IPv6, so this is instead a fail */
1992    failf(data, "Failed EPSV attempt, exiting");
1993    return CURLE_WEIRD_SERVER_REPLY;
1994  }
1995
1996  infof(data, "Failed EPSV attempt. Disabling EPSV");
1997  /* disable it for next transfer */
1998  conn->bits.ftp_use_epsv = FALSE;
1999  close_secondarysocket(data, ftpc);
2000  data->state.errorbuf = FALSE; /* allow error message to get
2001                                         rewritten */
2002  result = Curl_pp_sendf(data, &ftpc->pp, "%s", "PASV");
2003  if(!result) {
2004    ftpc->count1++;
2005    /* remain in/go to the FTP_PASV state */
2006    ftp_state(data, ftpc, FTP_PASV);
2007  }
2008  return result;
2009}
2010
2011static CURLcode ftp_control_addr_dup(struct Curl_easy *data, char **newhostp)
2012{
2013  struct connectdata *conn = data->conn;
2014  struct ip_quadruple ipquad;
2015  bool is_ipv6;
2016
2017  /* Returns the control connection IP address.
2018     If a proxy tunnel is used, returns the original hostname instead, because
2019     the effective control connection address is the proxy address,
2020     not the ftp host. */
2021#ifndef CURL_DISABLE_PROXY
2022  if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
2023    *newhostp = curlx_strdup(conn->origin->hostname);
2024  else
2025#endif
2026  if(!Curl_conn_get_ip_info(data, conn, FIRSTSOCKET, &is_ipv6, &ipquad) &&
2027     *ipquad.remote_ip)
2028    *newhostp = curlx_strdup(ipquad.remote_ip);
2029  else {
2030    /* failed to get the remote_ip of the DATA connection */
2031    failf(data, "unable to get peername of DATA connection");
2032    *newhostp = NULL;
2033    return CURLE_FTP_CANT_GET_HOST;
2034  }
2035  return *newhostp ? CURLE_OK : CURLE_OUT_OF_MEMORY;
2036}
2037
2038static bool match_pasv_6nums(const char *p,
2039                             unsigned int *array) /* 6 numbers */
2040{
2041  int i;
2042  for(i = 0; i < 6; i++) {
2043    curl_off_t num;
2044    if(i) {
2045      if(*p != ',')
2046        return FALSE;
2047      p++;
2048    }
2049    if(curlx_str_number(&p, &num, 0xff))
2050      return FALSE;
2051    array[i] = (unsigned int)num;
2052  }
2053  return TRUE;
2054}
2055
2056static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
2057                                    struct ftp_conn *ftpc,
2058                                    int ftpcode)
2059{
2060  struct connectdata *conn = data->conn;
2061  CURLcode result;
2062  const struct pingpong *pp = &ftpc->pp;
2063  char *newhost = NULL;
2064  unsigned short newport = 0;
2065  const char *str = curlx_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
2066                                                        letter */
2067  if((ftpc->count1 == 0) &&
2068     (ftpcode == 229)) {
2069    /* positive EPSV response */
2070    const char *ptr = strchr(str, '(');
2071    if(ptr) {
2072      char sep;
2073      ptr++;
2074      /* |||12345| */
2075      sep = ptr[0];
2076      if(sep && (ptr[1] == sep) && (ptr[2] == sep) && ISDIGIT(ptr[3])) {
2077        const char *p = &ptr[3];
2078        curl_off_t num;
2079        if(curlx_str_number(&p, &num, 0xffff) || (*p != sep)) {
2080          failf(data, "Illegal port number in EPSV reply");
2081          return CURLE_FTP_WEIRD_PASV_REPLY;
2082        }
2083        newport = (unsigned short)num;
2084        result = ftp_control_addr_dup(data, &newhost);
2085        if(result)
2086          return result;
2087      }
2088      else
2089        ptr = NULL;
2090    }
2091    if(!ptr) {
2092      failf(data, "Weirdly formatted EPSV reply");
2093      return CURLE_FTP_WEIRD_PASV_REPLY;
2094    }
2095  }
2096  else if((ftpc->count1 == 1) &&
2097          (ftpcode == 227)) {
2098    /* positive PASV response */
2099    unsigned int ip[6];
2100
2101    /*
2102     * Scan for a sequence of six comma-separated numbers and use them as
2103     * IP+port indicators.
2104     *
2105     * Found reply-strings include:
2106     * "227 Entering Passive Mode (127,0,0,1,4,51)"
2107     * "227 Data transfer will passively listen to 127,0,0,1,4,51"
2108     * "227 Entering passive mode. 127,0,0,1,4,51"
2109     */
2110    while(*str) {
2111      if(match_pasv_6nums(str, ip))
2112        break;
2113      str++;
2114    }
2115
2116    if(!*str) {
2117      failf(data, "Could not interpret the 227-response");
2118      return CURLE_FTP_WEIRD_227_FORMAT;
2119    }
2120
2121    /* we got OK from server */
2122    if(data->set.ftp_skip_ip) {
2123      /* told to ignore the remotely given IP but instead use the host we used
2124         for the control connection */
2125      infof(data, "Skip %u.%u.%u.%u for data connection, reuse %s instead",
2126            ip[0], ip[1], ip[2], ip[3], conn->origin->hostname);
2127      result = ftp_control_addr_dup(data, &newhost);
2128      if(result)
2129        return result;
2130    }
2131    else
2132      newhost = curl_maprintf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
2133
2134    if(!newhost)
2135      return CURLE_OUT_OF_MEMORY;
2136
2137    newport = (unsigned short)(((ip[4] << 8) + ip[5]) & 0xffff);
2138  }
2139  else if(ftpc->count1 == 0) {
2140    /* EPSV failed, move on to PASV */
2141    return ftp_epsv_disable(data, ftpc, conn);
2142  }
2143  else {
2144    failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
2145    return CURLE_FTP_WEIRD_PASV_REPLY;
2146  }
2147
2148  DEBUGASSERT(newhost);
2149  Curl_peer_unlink(&conn->origin2);
2150  result = Curl_peer_create(data, conn->scheme, newhost, newport,
2151                            &conn->origin2);
2152  if(result)
2153    goto error;
2154
2155  /* If FIRSTSOCKET goes via another peer, SECONDARY needs as well,
2156   * but with its new port. */
2157  if(conn->via_peer) {
2158    Curl_peer_unlink(&conn->via_peer2);
2159    result = Curl_peer_create(data, conn->via_peer->scheme,
2160                              conn->via_peer->hostname, newport,
2161                              &conn->via_peer2);
2162    if(result)
2163      goto error;
2164  }
2165
2166  result = Curl_conn_setup(data, conn, SECONDARYSOCKET,
2167                           conn->bits.ftp_use_data_ssl ?
2168                           CURL_CF_SSL_ENABLE : CURL_CF_SSL_DISABLE);
2169
2170  if(result) {
2171    if((result != CURLE_OUT_OF_MEMORY) &&
2172       (ftpc->count1 == 0) && (ftpcode == 229)) {
2173      result = ftp_epsv_disable(data, ftpc, conn);
2174    }
2175    goto error;
2176  }
2177
2178  /*
2179   * When this is used from the multi interface, this might have returned with
2180   * the 'connected' set to FALSE and thus we are now awaiting a non-blocking
2181   * connect to connect.
2182   */
2183
2184#ifdef CURLVERBOSE
2185  if(data->set.verbose) {
2186    /* Dump information about this second connection when we have issued
2187     * a PASV command. */
2188    infof(data, "Connecting to %s port %d",
2189          conn->origin2->hostname, conn->origin2->port);
2190  }
2191#endif
2192
2193  conn->bits.do_more = TRUE;
2194  ftp_state(data, ftpc, FTP_STOP); /* this phase is completed */
2195
2196error:
2197  curlx_free(newhost);
2198  return result;
2199}
2200
2201/* called repeatedly until done from multi.c */
2202static CURLcode ftp_statemach(struct Curl_easy *data,
2203                              struct ftp_conn *ftpc,
2204                              bool *done)
2205{
2206  CURLcode result = Curl_pp_statemach(data, &ftpc->pp, FALSE, FALSE);
2207
2208  /* Check for the state outside of the Curl_socket_check() return code checks
2209     since at times we are in fact already in this state when this function
2210     gets called. */
2211  *done = (ftpc->state == FTP_STOP);
2212
2213  return result;
2214}
2215
2216/*
2217 * ftp_do_more()
2218 *
2219 * This function shall be called when the second FTP (data) connection is
2220 * connected.
2221 *
2222 * 'more' can return DOMORE_INCOMPLETE, DOMORE_DONE or DOMORE_GOBACK
2223 * (which is for when PASV is being sent to retry a failed EPSV).
2224 */
2225static CURLcode ftp_do_more(struct Curl_easy *data, domore *more)
2226{
2227  struct connectdata *conn = data->conn;
2228  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
2229  struct FTP *ftp = Curl_meta_get(data, CURL_META_FTP_EASY);
2230  CURLcode result = CURLE_OK;
2231  bool connected = FALSE;
2232  bool complete = FALSE;
2233  /* the ftp struct is inited in ftp_connect(). If we are connecting to an HTTP
2234   * proxy then the state will not be valid until after that connection is
2235   * complete */
2236
2237  if(!ftpc || !ftp)
2238    return CURLE_FAILED_INIT;
2239
2240  *more = DOMORE_INCOMPLETE; /* default to stay in the state */
2241
2242  /* if the second connection has been set up, try to connect it fully
2243   * to the remote host. This may not complete at this time, for several
2244   * reasons:
2245   * - we do EPTR and the server will not connect to our listen socket
2246   *   until we send more FTP commands
2247   * - an SSL filter is in place and the server will not start the TLS
2248   *   handshake until we send more FTP commands
2249   */
2250  if(conn->cfilter[SECONDARYSOCKET]) {
2251    bool is_eptr = Curl_conn_is_tcp_listen(data, SECONDARYSOCKET);
2252    result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &connected);
2253    if(result == CURLE_OUT_OF_MEMORY)
2254      return result;
2255    if(result || (!connected && !is_eptr &&
2256                  !Curl_conn_is_ip_connected(data, SECONDARYSOCKET))) {
2257      if(result && !is_eptr && (ftpc->count1 == 0)) {
2258        *more = DOMORE_GOBACK; /* go back to DOING please */
2259        /* this is a EPSV connect failing, try PASV instead */
2260        return ftp_epsv_disable(data, ftpc, conn);
2261      }
2262      return result;
2263    }
2264  }
2265
2266  if(ftpc->state) {
2267    /* already in a state so skip the initial commands.
2268       They are only done to kickstart the do_more state */
2269    result = ftp_statemach(data, ftpc, &complete);
2270
2271    if(complete)
2272      *more = DOMORE_DONE;
2273
2274    /* if we got an error or if we do not wait for a data connection return
2275       immediately */
2276    if(result || !ftpc->wait_data_conn)
2277      return result;
2278
2279    /* if we reach the end of the FTP state machine here, *complete will be
2280       TRUE but so is ftpc->wait_data_conn, which says we need to wait for the
2281       data connection and therefore we are not actually complete */
2282    *more = DOMORE_INCOMPLETE;
2283  }
2284
2285  if(ftp->transfer <= PPTRANSFER_INFO) {
2286    /* a transfer is about to take place, or if not a filename was given so we
2287       will do a SIZE on it later and then we need the right TYPE first */
2288
2289    if(ftpc->wait_data_conn) {
2290      bool serv_conned;
2291
2292      result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &serv_conned);
2293      if(result)
2294        return result; /* Failed to accept data connection */
2295
2296      if(serv_conned) {
2297        /* It looks data connection is established */
2298        ftpc->wait_data_conn = FALSE;
2299        result = ftp_initiate_transfer(data, ftpc);
2300
2301        if(result)
2302          return result;
2303
2304        *more = DOMORE_DONE; /* this state is now complete when the server has
2305                                connected back to us */
2306      }
2307      else {
2308        result = ftp_check_ctrl_on_data_wait(data, ftpc);
2309        if(result)
2310          return result;
2311      }
2312    }
2313    else if(data->state.upload) {
2314      result = ftp_nb_type(data, ftpc, ftp, (bool)data->state.prefer_ascii,
2315                           FTP_STOR_TYPE);
2316      if(result)
2317        return result;
2318
2319      result = ftp_statemach(data, ftpc, &complete);
2320      /* ftp_nb_type() might have skipped sending `TYPE A|I` when not
2321       * deemed necessary and directly sent `STORE name`. If this was
2322       * then complete, but we are still waiting on the data connection,
2323       * the transfer has not been initiated yet. */
2324      *more = (!ftpc->wait_data_conn && complete) ?
2325        DOMORE_DONE : DOMORE_INCOMPLETE;
2326    }
2327    else {
2328      /* download */
2329      ftp->downloadsize = -1; /* unknown as of yet */
2330
2331      result = Curl_range(data);
2332
2333      if(result == CURLE_OK && data->req.maxdownload >= 0) {
2334        /* Do not check for successful transfer */
2335        ftpc->dont_check = TRUE;
2336      }
2337
2338      if(result)
2339        ;
2340      else if((data->state.list_only || !ftpc->file) &&
2341              !(data->set.prequote)) {
2342        /* The specified path ends with a slash, and therefore we think this
2343           is a directory that is requested, use LIST. Before that, we also
2344           need to set ASCII transfer mode. */
2345
2346        /* Only if a body transfer was requested. */
2347        if(ftp->transfer == PPTRANSFER_BODY) {
2348          result = ftp_nb_type(data, ftpc, ftp, TRUE, FTP_LIST_TYPE);
2349          if(result)
2350            return result;
2351        }
2352        /* otherwise fall through */
2353      }
2354      else {
2355        if(data->set.prequote && !ftpc->file) {
2356          result = ftp_nb_type(data, ftpc, ftp, TRUE,
2357                               FTP_RETR_LIST_TYPE);
2358        }
2359        else {
2360          result = ftp_nb_type(data, ftpc, ftp, (bool)data->state.prefer_ascii,
2361                               FTP_RETR_TYPE);
2362        }
2363        if(result)
2364          return result;
2365      }
2366
2367      result = ftp_statemach(data, ftpc, &complete);
2368      if(complete)
2369        *more = DOMORE_DONE;
2370    }
2371    return result;
2372  }
2373
2374  /* no data to transfer */
2375  Curl_xfer_setup_nop(data);
2376
2377  if(!ftpc->wait_data_conn) {
2378    /* no waiting for the data connection so this is now complete */
2379    *more = DOMORE_DONE;
2380    CURL_TRC_FTP(data, "[%s] DO-MORE phase ends with %d", FTP_CSTATE(ftpc),
2381                 (int)result);
2382  }
2383
2384  return result;
2385}
2386
2387/* call this when the DO phase has completed */
2388static CURLcode ftp_dophase_done(struct Curl_easy *data,
2389                                 struct ftp_conn *ftpc,
2390                                 struct FTP *ftp,
2391                                 bool connected)
2392{
2393  if(connected) {
2394    domore completed;
2395    CURLcode result = ftp_do_more(data, &completed);
2396
2397    if(result) {
2398      close_secondarysocket(data, ftpc);
2399      return result;
2400    }
2401  }
2402
2403  if(ftp->transfer != PPTRANSFER_BODY)
2404    /* no data to transfer */
2405    Curl_xfer_setup_nop(data);
2406  else if(!connected)
2407    /* since we did not connect now, we want do_more to get called */
2408    data->conn->bits.do_more = TRUE;
2409
2410  ftpc->ctl_valid = TRUE; /* seems good */
2411
2412  return CURLE_OK;
2413}
2414
2415static CURLcode ftp_state_port_resp(struct Curl_easy *data,
2416                                    struct ftp_conn *ftpc,
2417                                    struct FTP *ftp,
2418                                    int ftpcode)
2419{
2420  struct connectdata *conn = data->conn;
2421  ftpport fcmd = (ftpport)ftpc->count1;
2422  CURLcode result = CURLE_OK;
2423
2424  /* The FTP spec tells a positive response should have code 200.
2425     Be more permissive here to tolerate deviant servers. */
2426  if(ftpcode / 100 != 2) {
2427    /* the command failed */
2428
2429    if(EPRT == fcmd) {
2430      infof(data, "disabling EPRT usage");
2431      conn->bits.ftp_use_eprt = FALSE;
2432    }
2433    fcmd++;
2434
2435    if(fcmd == DONE) {
2436      failf(data, "Failed to do PORT");
2437      result = CURLE_FTP_PORT_FAILED;
2438    }
2439    else
2440      /* try next */
2441      result = ftp_state_use_port(data, ftpc, fcmd);
2442  }
2443  else {
2444    infof(data, "Connect data stream actively");
2445    ftp_state(data, ftpc, FTP_STOP); /* end of DO phase */
2446    result = ftp_dophase_done(data, ftpc, ftp, FALSE);
2447  }
2448
2449  return result;
2450}
2451
2452/* return TRUE on error, FALSE on success */
2453static bool twodigit(const char *p, int *val)
2454{
2455  if(!ISDIGIT(p[0]) || !ISDIGIT(p[1]))
2456    return TRUE;
2457  /* curlx_hexval() works fine here since we make sure it is decimal above */
2458  *val = (curlx_hexval(p[0]) * 10) + curlx_hexval(p[1]);
2459  return FALSE;
2460}
2461
2462/*
2463 * @unittest 1668
2464 */
2465UNITTEST bool ftp_213_date(const char *p, int *year, int *month, int *day,
2466                           int *hour, int *minute, int *second);
2467UNITTEST bool ftp_213_date(const char *p, int *year, int *month, int *day,
2468                           int *hour, int *minute, int *second)
2469{
2470  int century;
2471  if((strlen(p) < 14) || twodigit(&p[0], &century) || twodigit(&p[2], year) ||
2472     twodigit(&p[4], month) || twodigit(&p[6], day) ||
2473     twodigit(&p[8], hour) || twodigit(&p[10], minute) ||
2474     twodigit(&p[12], second))
2475    return FALSE;
2476
2477  *year += century * 100;
2478  if((*month > 12) || (*day > 31) || (*hour > 23) || (*minute > 59) ||
2479     (*second > 60))
2480    return FALSE;
2481  return TRUE;
2482}
2483
2484static CURLcode client_write_header(struct Curl_easy *data,
2485                                    char *buf, size_t blen)
2486{
2487  /* Some replies from an FTP server are written to the client
2488   * as CLIENTWRITE_HEADER, formatted as if they came from a
2489   * HTTP conversation.
2490   * In all protocols, CLIENTWRITE_HEADER data is only passed to
2491   * the body write callback when data->set.include_header is set
2492   * via CURLOPT_HEADER.
2493   * For historic reasons, FTP never played this game and expects
2494   * all its headers to do that always. Set that flag during the
2495   * call to Curl_client_write() so it does the right thing.
2496   *
2497   * Notice that we cannot enable this flag for FTP in general,
2498   * as an FTP transfer might involve an HTTP proxy connection and
2499   * headers from CONNECT should not automatically be part of the
2500   * output. */
2501  CURLcode result;
2502  bool save = (bool)data->set.include_header;
2503  data->set.include_header = TRUE;
2504  result = Curl_client_write(data, CLIENTWRITE_HEADER, buf, blen);
2505  data->set.include_header = save;
2506  return result;
2507}
2508
2509static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
2510                                    struct ftp_conn *ftpc,
2511                                    struct FTP *ftp,
2512                                    int ftpcode)
2513{
2514  CURLcode result = CURLE_OK;
2515
2516  switch(ftpcode) {
2517  case 213: {
2518    /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
2519       last .sss part is optional and means fractions of a second */
2520    int year, month, day, hour, minute, second;
2521    struct pingpong *pp = &ftpc->pp;
2522    const char *resp = curlx_dyn_ptr(&pp->recvbuf) + 4;
2523    bool showtime = FALSE;
2524    if(ftp_213_date(resp, &year, &month, &day, &hour, &minute, &second)) {
2525      /* we have a time, reformat it */
2526      char timebuf[24];
2527      curl_msnprintf(timebuf, sizeof(timebuf),
2528                     "%04d%02d%02d %02d:%02d:%02d GMT",
2529                     year, month, day, hour, minute, second);
2530      /* now, convert this into a time() value: */
2531      if(!Curl_getdate_capped(timebuf, &data->info.filetime))
2532        showtime = TRUE;
2533    }
2534
2535    /* If we asked for a time of the file and we actually got one as well,
2536       we "emulate" an HTTP-style header in our output. */
2537
2538#if defined(CURL_HAVE_DIAG) && (defined(__DJGPP__) || defined(__AMIGA__))
2539#pragma GCC diagnostic push
2540/* 'time_t' is unsigned in MSDOS and AmigaOS. Silence:
2541   warning: comparison of unsigned expression in '>= 0' is always true */
2542#pragma GCC diagnostic ignored "-Wtype-limits"
2543#endif
2544    if(data->req.no_body && ftpc->file &&
2545       data->set.get_filetime && showtime) {
2546#if defined(CURL_HAVE_DIAG) && (defined(__DJGPP__) || defined(__AMIGA__))
2547#pragma GCC diagnostic pop
2548#endif
2549      char headerbuf[128];
2550      int headerbuflen;
2551      time_t filetime = data->info.filetime;
2552      struct tm buffer;
2553      const struct tm *tm = &buffer;
2554
2555      result = curlx_gmtime(filetime, &buffer);
2556      if(result)
2557        return result;
2558
2559      /* format: "Tue, 15 Nov 1994 12:45:26" */
2560      headerbuflen =
2561        curl_msnprintf(headerbuf, sizeof(headerbuf),
2562                       "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d "
2563                       "GMT\r\n",
2564                       Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6],
2565                       tm->tm_mday,
2566                       Curl_month[tm->tm_mon],
2567                       tm->tm_year + 1900,
2568                       tm->tm_hour,
2569                       tm->tm_min,
2570                       tm->tm_sec);
2571      result = client_write_header(data, headerbuf, headerbuflen);
2572      if(result)
2573        return result;
2574    } /* end of a ridiculous amount of conditionals */
2575  }
2576    break;
2577  default:
2578    infof(data, "unsupported MDTM reply format");
2579    break;
2580  case 550: /* 550 is used for several different problems, e.g.
2581               "No such file or directory" or "Permission denied".
2582               It does not mean that the file does not exist at all. */
2583    infof(data, "MDTM failed: file does not exist or permission problem,"
2584          " continuing");
2585    break;
2586  }
2587
2588  if(data->set.timecondition) {
2589    if((data->info.filetime > 0) && (data->set.timevalue > 0)) {
2590      switch(data->set.timecondition) {
2591      case CURL_TIMECOND_IFMODSINCE:
2592      default:
2593        if(data->info.filetime <= data->set.timevalue) {
2594          infof(data, "The requested document is not new enough");
2595          ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
2596          data->info.timecond = TRUE;
2597          ftp_state(data, ftpc, FTP_STOP);
2598          return CURLE_OK;
2599        }
2600        break;
2601      case CURL_TIMECOND_IFUNMODSINCE:
2602        if(data->info.filetime > data->set.timevalue) {
2603          infof(data, "The requested document is not old enough");
2604          ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
2605          data->info.timecond = TRUE;
2606          ftp_state(data, ftpc, FTP_STOP);
2607          return CURLE_OK;
2608        }
2609        break;
2610      } /* switch */
2611    }
2612    else {
2613      infof(data, "Skipping time comparison");
2614    }
2615  }
2616
2617  if(!result)
2618    result = ftp_state_type(data, ftpc, ftp);
2619
2620  return result;
2621}
2622
2623static CURLcode ftp_state_type_resp(struct Curl_easy *data,
2624                                    struct ftp_conn *ftpc,
2625                                    struct FTP *ftp,
2626                                    int ftpcode,
2627                                    ftpstate instate)
2628{
2629  CURLcode result = CURLE_OK;
2630
2631  if(ftpcode / 100 != 2) {
2632    /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
2633       successful 'TYPE I'. While that is not as RFC959 says, it is still a
2634       positive response code and we allow that. */
2635    failf(data, "Could not set desired mode");
2636    return CURLE_FTP_COULDNT_SET_TYPE;
2637  }
2638  if(ftpcode != 200)
2639    infof(data, "Got a %03d response code instead of the assumed 200",
2640          ftpcode);
2641
2642  if(instate == FTP_TYPE)
2643    result = ftp_state_size(data, ftpc, ftp);
2644  else if(instate == FTP_LIST_TYPE)
2645    result = ftp_state_list(data, ftpc, ftp);
2646  else if(instate == FTP_RETR_TYPE)
2647    result = ftp_state_retr_prequote(data, ftpc, ftp);
2648  else if(instate == FTP_STOR_TYPE)
2649    result = ftp_state_stor_prequote(data, ftpc, ftp);
2650  else if(instate == FTP_RETR_LIST_TYPE)
2651    result = ftp_state_list_prequote(data, ftpc, ftp);
2652
2653  return result;
2654}
2655
2656static CURLcode ftp_state_size_resp(struct Curl_easy *data,
2657                                    struct ftp_conn *ftpc,
2658                                    struct FTP *ftp,
2659                                    int ftpcode,
2660                                    ftpstate instate)
2661{
2662  CURLcode result = CURLE_OK;
2663  curl_off_t filesize = -1;
2664  const char *buf = curlx_dyn_ptr(&ftpc->pp.recvbuf);
2665  size_t len = ftpc->pp.nfinal;
2666
2667  /* get the size from the ascii string: */
2668  if(ftpcode == 213) {
2669    /* To allow servers to prepend "rubbish" in the response string, we scan
2670       for all the digits at the end of the response and parse only those as a
2671       number. */
2672    const char *start = &buf[4];
2673    const char *fdigit = memchr(start, '\r', len - 4);
2674    if(fdigit) {
2675      fdigit--;
2676      if(*fdigit == '\n')
2677        fdigit--;
2678      while(ISDIGIT(fdigit[-1]) && (fdigit > start))
2679        fdigit--;
2680    }
2681    else
2682      fdigit = start;
2683    if(curlx_str_number(&fdigit, &filesize, CURL_OFF_T_MAX))
2684      filesize = -1; /* size remain unknown */
2685  }
2686  else if(ftpcode == 550) { /* "No such file or directory" */
2687    /* allow a SIZE failure for (resumed) uploads, when probing what command
2688       to use */
2689    if(instate != FTP_STOR_SIZE) {
2690      failf(data, "The file does not exist");
2691      return CURLE_REMOTE_FILE_NOT_FOUND;
2692    }
2693  }
2694
2695  if(instate == FTP_SIZE) {
2696    if(filesize != -1) {
2697      char clbuf[128];
2698      int clbuflen = curl_msnprintf(clbuf, sizeof(clbuf),
2699                                    "Content-Length: %" FMT_OFF_T "\r\n",
2700                                    filesize);
2701      result = client_write_header(data, clbuf, clbuflen);
2702      if(result)
2703        return result;
2704    }
2705    Curl_pgrsSetDownloadSize(data, filesize);
2706    result = ftp_state_rest(data, ftpc, ftp);
2707  }
2708  else if(instate == FTP_RETR_SIZE) {
2709    Curl_pgrsSetDownloadSize(data, filesize);
2710    result = ftp_state_retr(data, ftpc, ftp, filesize);
2711  }
2712  else if(instate == FTP_STOR_SIZE) {
2713    data->state.resume_from = filesize;
2714    result = ftp_state_ul_setup(data, ftpc, ftp, TRUE);
2715  }
2716
2717  return result;
2718}
2719
2720static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
2721                                    struct ftp_conn *ftpc,
2722                                    struct FTP *ftp,
2723                                    int ftpcode,
2724                                    ftpstate instate)
2725{
2726  CURLcode result = CURLE_OK;
2727
2728  switch(instate) {
2729  case FTP_REST:
2730  default:
2731    if(ftpcode == 350) {
2732      char buffer[24] = { "Accept-ranges: bytes\r\n" };
2733      result = client_write_header(data, buffer, strlen(buffer));
2734      if(result)
2735        return result;
2736    }
2737    result = ftp_state_prepare_transfer(data, ftpc, ftp);
2738    break;
2739
2740  case FTP_RETR_REST:
2741    if(ftpcode != 350) {
2742      failf(data, "Could not use REST");
2743      result = CURLE_FTP_COULDNT_USE_REST;
2744    }
2745    else {
2746      result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
2747      if(!result)
2748        ftp_state(data, ftpc, FTP_RETR);
2749    }
2750    break;
2751  }
2752
2753  return result;
2754}
2755
2756static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
2757                                    struct ftp_conn *ftpc,
2758                                    int ftpcode)
2759{
2760  CURLcode result = CURLE_OK;
2761
2762  if(ftpcode >= 400) {
2763    failf(data, "Failed FTP upload: %0d", ftpcode);
2764    ftp_state(data, ftpc, FTP_STOP);
2765    return CURLE_UPLOAD_FAILED;
2766  }
2767
2768  /* PORT means we are now awaiting the server to connect to us. */
2769  if(data->set.ftp_use_port) {
2770    bool connected;
2771
2772    ftp_state(data, ftpc, FTP_STOP); /* no longer in STOR state */
2773
2774    result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &connected);
2775    if(result)
2776      return result;
2777
2778    if(!connected) {
2779      infof(data, "Data conn was not available immediately");
2780      ftpc->wait_data_conn = TRUE;
2781      return ftp_check_ctrl_on_data_wait(data, ftpc);
2782    }
2783    ftpc->wait_data_conn = FALSE;
2784  }
2785  return ftp_initiate_transfer(data, ftpc);
2786}
2787
2788/* for LIST and RETR responses */
2789static CURLcode ftp_state_get_resp(struct Curl_easy *data,
2790                                   struct ftp_conn *ftpc,
2791                                   struct FTP *ftp,
2792                                   int ftpcode,
2793                                   ftpstate instate)
2794{
2795  CURLcode result = CURLE_OK;
2796
2797  if((ftpcode == 150) || (ftpcode == 125)) {
2798
2799    /*
2800      A;
2801      150 Opening BINARY mode data connection for /etc/passwd (2241
2802      bytes).  (ok, the file is being transferred)
2803
2804      B:
2805      150 Opening ASCII mode data connection for /bin/ls
2806
2807      C:
2808      150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes).
2809
2810      D:
2811      150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes)
2812
2813      E:
2814      125 Data connection already open; Transfer starting. */
2815
2816    data->req.size = -1; /* default unknown size */
2817
2818    /*
2819     * It appears that there are FTP-servers that return size 0 for files when
2820     * SIZE is used on the file while being in BINARY mode. To work around
2821     * that (stupid) behavior, we attempt to parse the RETR response even if
2822     * the SIZE returned size zero.
2823     *
2824     * Debugging help from Salvatore Sorrentino on February 26, 2003.
2825     */
2826
2827    if((instate != FTP_LIST) &&
2828       !data->state.prefer_ascii &&
2829       !data->set.ignorecl &&
2830       (ftp->downloadsize < 1)) {
2831      /*
2832       * It seems directory listings either do not show the size or often uses
2833       * size 0 anyway. ASCII transfers may cause that the transferred amount
2834       * of data is not the same as this line tells, why using this number in
2835       * those cases only confuses us.
2836       *
2837       * Example D above makes this parsing a little tricky */
2838      size_t len = curlx_dyn_len(&ftpc->pp.recvbuf);
2839      if(len >= 7) { /* "1 bytes" is 7 characters */
2840        size_t i;
2841        for(i = 0; i < len - 7; i++) {
2842          curl_off_t what;
2843          const char *buf = curlx_dyn_ptr(&ftpc->pp.recvbuf);
2844          const char *c = &buf[i];
2845          if(!curlx_str_number(&c, &what, CURL_OFF_T_MAX) &&
2846             !curlx_str_single(&c, ' ') &&
2847             !strncmp(c, "bytes", 5)) {
2848            data->req.size = what;
2849            break;
2850          }
2851        }
2852      }
2853    }
2854    else if(ftp->downloadsize > -1)
2855      data->req.size = ftp->downloadsize;
2856
2857    if(data->req.size > data->req.maxdownload && data->req.maxdownload > 0)
2858      data->req.size = data->req.maxdownload;
2859    else if((instate != FTP_LIST) && (data->state.prefer_ascii))
2860      data->req.size = -1; /* for servers that understate ASCII mode file
2861                              size */
2862
2863    infof(data, "Maxdownload = %" FMT_OFF_T, data->req.maxdownload);
2864
2865    if(instate != FTP_LIST)
2866      infof(data, "Getting file with size: %" FMT_OFF_T, data->req.size);
2867
2868    if(data->set.ftp_use_port) {
2869      bool connected;
2870
2871      result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &connected);
2872      if(result)
2873        return result;
2874
2875      if(!connected) {
2876        infof(data, "Data conn was not available immediately");
2877        ftp_state(data, ftpc, FTP_STOP);
2878        ftpc->wait_data_conn = TRUE;
2879        return ftp_check_ctrl_on_data_wait(data, ftpc);
2880      }
2881      ftpc->wait_data_conn = FALSE;
2882    }
2883    return ftp_initiate_transfer(data, ftpc);
2884  }
2885  else {
2886    if((instate == FTP_LIST) && (ftpcode == 450)) {
2887      /* no matching files in the directory listing */
2888      ftp->transfer = PPTRANSFER_NONE; /* do not download anything */
2889      ftp_state(data, ftpc, FTP_STOP); /* this phase is over */
2890    }
2891    else {
2892      failf(data, "RETR response: %03d", ftpcode);
2893      return instate == FTP_RETR && ftpcode == 550 ?
2894        CURLE_REMOTE_FILE_NOT_FOUND :
2895        CURLE_FTP_COULDNT_RETR_FILE;
2896    }
2897  }
2898
2899  return result;
2900}
2901
2902/* after USER, PASS and ACCT */
2903static CURLcode ftp_state_loggedin(struct Curl_easy *data,
2904                                   struct ftp_conn *ftpc)
2905{
2906  CURLcode result = CURLE_OK;
2907
2908  if(Curl_conn_is_ssl(data->conn, FIRSTSOCKET)) {
2909    /* PBSZ = PROTECTION BUFFER SIZE.
2910
2911    The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says:
2912
2913    Specifically, the PROT command MUST be preceded by a PBSZ
2914    command and a PBSZ command MUST be preceded by a successful
2915    security data exchange (the TLS negotiation in this case)
2916
2917    ... (and on page 8):
2918
2919    Thus the PBSZ command must still be issued, but must have a
2920    parameter of '0' to indicate that no buffering is taking place
2921    and the data connection should not be encapsulated.
2922    */
2923    result = Curl_pp_sendf(data, &ftpc->pp, "PBSZ %d", 0);
2924    if(!result)
2925      ftp_state(data, ftpc, FTP_PBSZ);
2926  }
2927  else {
2928    result = ftp_state_pwd(data, ftpc);
2929  }
2930  return result;
2931}
2932
2933/* for USER and PASS responses */
2934static CURLcode ftp_state_user_resp(struct Curl_easy *data,
2935                                    struct ftp_conn *ftpc,
2936                                    int ftpcode)
2937{
2938  CURLcode result = CURLE_OK;
2939
2940  /* some need password anyway, and others return 2xx ignored */
2941  if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
2942    /* 331 Password required for ...
2943       (the server requires to send the user's password too) */
2944    result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s",
2945                           Curl_creds_passwd(data->conn->creds));
2946    if(!result)
2947      ftp_state(data, ftpc, FTP_PASS);
2948  }
2949  else if(ftpcode / 100 == 2) {
2950    /* 230 User ... logged in.
2951       (the user logged in with or without password) */
2952    result = ftp_state_loggedin(data, ftpc);
2953  }
2954  else if(ftpcode == 332) {
2955    if(data->set.str[STRING_FTP_ACCOUNT]) {
2956      result = Curl_pp_sendf(data, &ftpc->pp, "ACCT %s",
2957                             data->set.str[STRING_FTP_ACCOUNT]);
2958      if(!result)
2959        ftp_state(data, ftpc, FTP_ACCT);
2960    }
2961    else {
2962      failf(data, "ACCT requested but none available");
2963      result = CURLE_LOGIN_DENIED;
2964    }
2965  }
2966  else {
2967    /* All other response codes, like:
2968
2969    530 User ... access denied
2970    (the server denies to log the specified user) */
2971
2972    if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
2973       !ftpc->ftp_trying_alternative) {
2974      /* Ok, USER failed. Let's try the supplied command. */
2975      result = Curl_pp_sendf(data, &ftpc->pp, "%s",
2976                             data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
2977      if(!result) {
2978        ftpc->ftp_trying_alternative = TRUE;
2979        ftp_state(data, ftpc, FTP_USER);
2980      }
2981    }
2982    else {
2983      failf(data, "Access denied: %03d", ftpcode);
2984      result = CURLE_LOGIN_DENIED;
2985    }
2986  }
2987  return result;
2988}
2989
2990/* for ACCT response */
2991static CURLcode ftp_state_acct_resp(struct Curl_easy *data,
2992                                    struct ftp_conn *ftpc,
2993                                    int ftpcode)
2994{
2995  CURLcode result = CURLE_OK;
2996  if(ftpcode != 230) {
2997    failf(data, "ACCT rejected by server: %03d", ftpcode);
2998    result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */
2999  }
3000  else
3001    result = ftp_state_loggedin(data, ftpc);
3002
3003  return result;
3004}
3005
3006static CURLcode ftp_pwd_resp(struct Curl_easy *data,
3007                             struct ftp_conn *ftpc,
3008                             int ftpcode)
3009{
3010  struct pingpong *pp = &ftpc->pp;
3011  CURLcode result;
3012
3013  if(ftpcode == 257) {
3014    const char *ptr = curlx_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
3015                                                          letter */
3016    bool entry_extracted = FALSE;
3017    struct dynbuf out;
3018    curlx_dyn_init(&out, 1000);
3019
3020    /* Reply format is like
3021       257<space>[rubbish]"<directory-name>"<space><commentary> and the
3022       RFC959 says
3023
3024       The directory name can contain any character; embedded
3025       double-quotes should be escaped by double-quotes (the
3026       "quote-doubling" convention).
3027    */
3028
3029    /* scan for the first double-quote for non-standard responses */
3030    while(*ptr != '\n' && *ptr != '\0' && *ptr != '"')
3031      ptr++;
3032
3033    if('\"' == *ptr) {
3034      /* it started good */
3035      for(ptr++; *ptr; ptr++) {
3036        if('\"' == *ptr) {
3037          if('\"' == ptr[1]) {
3038            /* "quote-doubling" */
3039            result = curlx_dyn_addn(&out, &ptr[1], 1);
3040            ptr++;
3041          }
3042          else {
3043            /* end of path */
3044            if(curlx_dyn_len(&out))
3045              entry_extracted = TRUE;
3046            break; /* get out of this loop */
3047          }
3048        }
3049        else {
3050          if(ISCNTRL(*ptr)) {
3051            /* control characters have no business in a path */
3052            curlx_dyn_free(&out);
3053            return CURLE_WEIRD_SERVER_REPLY;
3054          }
3055          result = curlx_dyn_addn(&out, ptr, 1);
3056        }
3057        if(result) {
3058          curlx_dyn_free(&out);
3059          return result;
3060        }
3061      }
3062    }
3063    if(entry_extracted) {
3064      /* If the path name does not look like an absolute path (i.e.: it
3065         does not start with a '/'), we probably need some server-dependent
3066         adjustments. For example, this is the case when connecting to
3067         an OS400 FTP server: this server supports two name syntaxes,
3068         the default one being incompatible with standard paths. In
3069         addition, this server switches automatically to the regular path
3070         syntax when one is encountered in a command: this results in
3071         having an entrypath in the wrong syntax when later used in CWD.
3072         The method used here is to check the server OS: we do it only
3073         if the path name looks strange to minimize overhead on other
3074         systems. */
3075      char *dir = curlx_dyn_ptr(&out);
3076
3077      if(!ftpc->server_os && dir[0] != '/') {
3078        result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SYST");
3079        if(result) {
3080          curlx_dyn_free(&out);
3081          return result;
3082        }
3083      }
3084
3085      curlx_free(ftpc->entrypath);
3086      ftpc->entrypath = dir; /* remember this */
3087      infof(data, "Entry path is '%s'", ftpc->entrypath);
3088      /* also save it where getinfo can access it: */
3089      curlx_free(data->state.most_recent_ftp_entrypath);
3090      data->state.most_recent_ftp_entrypath = curlx_strdup(ftpc->entrypath);
3091      if(!data->state.most_recent_ftp_entrypath)
3092        return CURLE_OUT_OF_MEMORY;
3093
3094      if(!ftpc->server_os && dir[0] != '/') {
3095        ftp_state(data, ftpc, FTP_SYST);
3096        return CURLE_OK;
3097      }
3098    }
3099    else {
3100      /* could not get the path */
3101      curlx_dyn_free(&out);
3102      infof(data, "Failed to figure out path");
3103    }
3104  }
3105  ftp_state(data, ftpc, FTP_STOP); /* we are done with CONNECT phase! */
3106  CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_CSTATE(ftpc));
3107  return CURLE_OK;
3108}
3109
3110static const char * const ftpauth[] = { "SSL", "TLS" };
3111
3112static CURLcode ftp_wait_resp(struct Curl_easy *data,
3113                              struct connectdata *conn,
3114                              struct ftp_conn *ftpc,
3115                              int ftpcode)
3116{
3117  CURLcode result = CURLE_OK;
3118  if(ftpcode == 230) {
3119    /* 230 User logged in - already! Take as 220 if TLS required. */
3120    if(data->set.use_ssl <= CURLUSESSL_TRY ||
3121       Curl_conn_is_ssl(conn, FIRSTSOCKET))
3122      return ftp_state_user_resp(data, ftpc, ftpcode);
3123  }
3124  else if(ftpcode != 220) {
3125    failf(data, "Got a %03d ftp-server response when 220 was expected",
3126          ftpcode);
3127    return CURLE_WEIRD_SERVER_REPLY;
3128  }
3129
3130  if(data->set.use_ssl && !Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
3131    /* We do not have an SSL/TLS control connection yet, but FTPS is
3132       requested. Try an FTPS connection now */
3133
3134    ftpc->count3 = 0;
3135    switch((long)data->set.ftpsslauth) {
3136    case CURLFTPAUTH_DEFAULT:
3137    case CURLFTPAUTH_SSL:
3138      ftpc->count2 = 1; /* add one to get next */
3139      ftpc->count1 = 0;
3140      break;
3141    case CURLFTPAUTH_TLS:
3142      ftpc->count2 = -1; /* subtract one to get next */
3143      ftpc->count1 = 1;
3144      break;
3145    default:
3146      failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d",
3147            (int)data->set.ftpsslauth);
3148      return CURLE_UNKNOWN_OPTION; /* we do not know what to do */
3149    }
3150    result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
3151    if(!result)
3152      ftp_state(data, ftpc, FTP_AUTH);
3153  }
3154  else
3155    result = ftp_state_user(data, ftpc, conn);
3156  return result;
3157}
3158
3159static CURLcode ftp_pp_statemachine(struct Curl_easy *data,
3160                                    struct connectdata *conn)
3161{
3162  CURLcode result;
3163  int ftpcode;
3164  struct ftp_conn *ftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
3165  struct FTP *ftp = Curl_meta_get(data, CURL_META_FTP_EASY);
3166  struct pingpong *pp;
3167  size_t nread = 0;
3168
3169  if(!ftpc || !ftp)
3170    return CURLE_FAILED_INIT;
3171  pp = &ftpc->pp;
3172  if(pp->sendleft)
3173    return Curl_pp_flushsend(data, pp);
3174
3175  result = ftp_readresp(data, ftpc, FIRSTSOCKET, pp, &ftpcode, &nread);
3176  if(result || !ftpcode)
3177    return result;
3178
3179  /* we have now received a full FTP server response */
3180  switch(ftpc->state) {
3181  case FTP_WAIT220:
3182    result = ftp_wait_resp(data, conn, ftpc, ftpcode);
3183    break;
3184
3185  case FTP_AUTH:
3186    /* we have gotten the response to a previous AUTH command */
3187
3188    if(pp->overflow)
3189      return CURLE_WEIRD_SERVER_REPLY; /* Forbid pipelining in response. */
3190
3191    /* RFC2228 (page 5) says:
3192     *
3193     * If the server is willing to accept the named security mechanism,
3194     * and does not require any security data, it must respond with
3195     * reply code 234/334.
3196     */
3197
3198    if((ftpcode == 234) || (ftpcode == 334)) {
3199      /* this was BLOCKING, keep it so for now */
3200      bool done;
3201      if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
3202        result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
3203        if(result) {
3204          /* we failed and bail out */
3205          return CURLE_USE_SSL_FAILED;
3206        }
3207      }
3208      /* BLOCKING */
3209      result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, &done);
3210      if(!result) {
3211        conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
3212        result = ftp_state_user(data, ftpc, conn);
3213      }
3214    }
3215    else if(ftpc->count3 < 1) {
3216      ftpc->count3++;
3217      ftpc->count1 += ftpc->count2; /* get next attempt */
3218      result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
3219                             ftpauth[ftpc->count1]);
3220      /* remain in this same state */
3221    }
3222    else {
3223      if(data->set.use_ssl > CURLUSESSL_TRY)
3224        /* we failed and CURLUSESSL_CONTROL or CURLUSESSL_ALL is set */
3225        result = CURLE_USE_SSL_FAILED;
3226      else
3227        /* ignore the failure and continue */
3228        result = ftp_state_user(data, ftpc, conn);
3229    }
3230    break;
3231
3232  case FTP_USER:
3233  case FTP_PASS:
3234    result = ftp_state_user_resp(data, ftpc, ftpcode);
3235    break;
3236
3237  case FTP_ACCT:
3238    result = ftp_state_acct_resp(data, ftpc, ftpcode);
3239    break;
3240
3241  case FTP_PBSZ:
3242    result =
3243      Curl_pp_sendf(data, &ftpc->pp, "PROT %c",
3244                    data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
3245    if(!result)
3246      ftp_state(data, ftpc, FTP_PROT);
3247    break;
3248
3249  case FTP_PROT:
3250    if(ftpcode / 100 == 2)
3251      /* We have enabled SSL for the data connection! */
3252      conn->bits.ftp_use_data_ssl = (data->set.use_ssl != CURLUSESSL_CONTROL);
3253    /* FTP servers typically responds with 500 if they decide to reject
3254       our 'P' request */
3255    else if(data->set.use_ssl > CURLUSESSL_CONTROL)
3256      /* we failed and bails out */
3257      return CURLE_USE_SSL_FAILED;
3258
3259    if(data->set.ftp_ccc) {
3260      /* CCC - Clear Command Channel
3261       */
3262      result = Curl_pp_sendf(data, &ftpc->pp, "%s", "CCC");
3263      if(!result)
3264        ftp_state(data, ftpc, FTP_CCC);
3265    }
3266    else
3267      result = ftp_state_pwd(data, ftpc);
3268    break;
3269
3270  case FTP_CCC:
3271    if(ftpcode < 500) {
3272      /* First shut down the SSL layer (note: this call will block) */
3273      /* This has only been tested on the proftpd server, and the mod_tls
3274       * code sends a close notify alert without waiting for a close notify
3275       * alert in response. Thus we wait for a close notify alert from the
3276       * server, but we do not send one. Let's hope other servers do
3277       * the same... */
3278      result = Curl_ssl_cfilter_remove(data, FIRSTSOCKET,
3279                                       (data->set.ftp_ccc ==
3280                                        (unsigned char)CURLFTPSSL_CCC_ACTIVE));
3281      if(result)
3282        failf(data, "Failed to clear the command channel (CCC)");
3283    }
3284    if(!result)
3285      /* Then continue as normal */
3286      result = ftp_state_pwd(data, ftpc);
3287    break;
3288
3289  case FTP_PWD:
3290    result = ftp_pwd_resp(data, ftpc, ftpcode);
3291    break;
3292
3293  case FTP_SYST:
3294    if(ftpcode == 215) {
3295      const char *ptr = curlx_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
3296                                                            letter */
3297      const char *start;
3298      char *os;
3299
3300      /* Reply format is like
3301         215<space><OS-name><space><commentary>
3302      */
3303      while(*ptr == ' ')
3304        ptr++;
3305      for(start = ptr; *ptr && *ptr != ' '; ptr++)
3306        ;
3307      os = curlx_memdup0(start, ptr - start);
3308      if(!os)
3309        return CURLE_OUT_OF_MEMORY;
3310
3311      /* Check for special servers here. */
3312      if(curl_strequal(os, "OS/400")) {
3313        /* Force OS400 name format 1. */
3314        result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SITE NAMEFMT 1");
3315        if(result) {
3316          curlx_free(os);
3317          return result;
3318        }
3319        /* remember target server OS */
3320        curlx_free(ftpc->server_os);
3321        ftpc->server_os = os;
3322        ftp_state(data, ftpc, FTP_NAMEFMT);
3323        break;
3324      }
3325      /* Nothing special for the target server. */
3326      /* remember target server OS */
3327      curlx_free(ftpc->server_os);
3328      ftpc->server_os = os;
3329    }
3330    else {
3331      /* Cannot identify server OS. Continue anyway and cross fingers. */
3332    }
3333
3334    ftp_state(data, ftpc, FTP_STOP); /* we are done with CONNECT phase! */
3335    CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_CSTATE(ftpc));
3336    break;
3337
3338  case FTP_NAMEFMT:
3339    if(ftpcode == 250) {
3340      /* Name format change successful: reload initial path. */
3341      ftp_state_pwd(data, ftpc);
3342      break;
3343    }
3344
3345    ftp_state(data, ftpc, FTP_STOP); /* we are done with CONNECT phase! */
3346    CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_CSTATE(ftpc));
3347    break;
3348
3349  case FTP_QUOTE:
3350  case FTP_POSTQUOTE:
3351  case FTP_RETR_PREQUOTE:
3352  case FTP_STOR_PREQUOTE:
3353  case FTP_LIST_PREQUOTE:
3354    if((ftpcode >= 400) && !ftpc->count2) {
3355      /* failure response code, and not allowed to fail */
3356      failf(data, "QUOT command failed with %03d", ftpcode);
3357      result = CURLE_QUOTE_ERROR;
3358    }
3359    else
3360      result = ftp_state_quote(data, ftpc, ftp, FALSE, ftpc->state);
3361    break;
3362
3363  case FTP_CWD:
3364    if(ftpcode / 100 != 2) {
3365      /* failure to CWD there */
3366      if(data->set.ftp_create_missing_dirs &&
3367         ftpc->cwdcount && !ftpc->count2) {
3368        /* try making it */
3369        ftpc->count2++; /* counter to prevent CWD-MKD loops */
3370
3371        /* count3 is set to allow MKD to fail once per dir. In the case when
3372           CWD fails and then MKD fails (due to another session raced it to
3373           create the dir) this then allows for a second try to CWD to it. */
3374        ftpc->count3 = (data->set.ftp_create_missing_dirs == 2) ? 1 : 0;
3375
3376        result = Curl_pp_sendf(data, &ftpc->pp, "MKD %.*s",
3377                               pathlen(ftpc, ftpc->cwdcount - 1),
3378                               pathpiece(ftpc, ftpc->cwdcount - 1));
3379        if(!result)
3380          ftp_state(data, ftpc, FTP_MKD);
3381      }
3382      else {
3383        /* return failure */
3384        failf(data, "Server denied you to change to the given directory");
3385        ftpc->cwdfail = TRUE; /* do not remember this path as we failed
3386                                 to enter it */
3387        result = CURLE_REMOTE_ACCESS_DENIED;
3388      }
3389    }
3390    else {
3391      /* success */
3392      ftpc->count2 = 0;
3393      if(ftpc->cwdcount >= ftpc->dirdepth)
3394        result = ftp_state_mdtm(data, ftpc, ftp);
3395      else {
3396        ftpc->cwdcount++;
3397        /* send next CWD */
3398        result = Curl_pp_sendf(data, &ftpc->pp, "CWD %.*s",
3399                               pathlen(ftpc, ftpc->cwdcount - 1),
3400                               pathpiece(ftpc, ftpc->cwdcount - 1));
3401      }
3402    }
3403    break;
3404
3405  case FTP_MKD:
3406    if((ftpcode / 100 != 2) && !ftpc->count3--) {
3407      /* failure to MKD the directory */
3408      failf(data, "Failed to MKD dir: %03d", ftpcode);
3409      result = CURLE_REMOTE_ACCESS_DENIED;
3410    }
3411    else {
3412      ftp_state(data, ftpc, FTP_CWD);
3413      /* send CWD */
3414      result = Curl_pp_sendf(data, &ftpc->pp, "CWD %.*s",
3415                             pathlen(ftpc, ftpc->cwdcount - 1),
3416                             pathpiece(ftpc, ftpc->cwdcount - 1));
3417    }
3418    break;
3419
3420  case FTP_MDTM:
3421    result = ftp_state_mdtm_resp(data, ftpc, ftp, ftpcode);
3422    break;
3423
3424  case FTP_TYPE:
3425  case FTP_LIST_TYPE:
3426  case FTP_RETR_TYPE:
3427  case FTP_STOR_TYPE:
3428  case FTP_RETR_LIST_TYPE:
3429    result = ftp_state_type_resp(data, ftpc, ftp, ftpcode, ftpc->state);
3430    break;
3431
3432  case FTP_SIZE:
3433  case FTP_RETR_SIZE:
3434  case FTP_STOR_SIZE:
3435    result = ftp_state_size_resp(data, ftpc, ftp, ftpcode, ftpc->state);
3436    break;
3437
3438  case FTP_REST:
3439  case FTP_RETR_REST:
3440    result = ftp_state_rest_resp(data, ftpc, ftp, ftpcode, ftpc->state);
3441    break;
3442
3443  case FTP_PRET:
3444    if(ftpcode != 200) {
3445      /* there only is this one standard OK return code. */
3446      failf(data, "PRET command not accepted: %03d", ftpcode);
3447      return CURLE_FTP_PRET_FAILED;
3448    }
3449    result = ftp_state_use_pasv(data, ftpc, conn);
3450    break;
3451
3452  case FTP_PASV:
3453    result = ftp_state_pasv_resp(data, ftpc, ftpcode);
3454    break;
3455
3456  case FTP_PORT:
3457    result = ftp_state_port_resp(data, ftpc, ftp, ftpcode);
3458    break;
3459
3460  case FTP_LIST:
3461  case FTP_RETR:
3462    result = ftp_state_get_resp(data, ftpc, ftp, ftpcode, ftpc->state);
3463    break;
3464
3465  case FTP_STOR:
3466    result = ftp_state_stor_resp(data, ftpc, ftpcode);
3467    break;
3468
3469  case FTP_QUIT:
3470  default:
3471    /* internal error */
3472    ftp_state(data, ftpc, FTP_STOP);
3473    break;
3474  }
3475
3476  return result;
3477}
3478
3479/* called repeatedly until done from multi.c */
3480static CURLcode ftp_multi_statemach(struct Curl_easy *data,
3481                                    bool *done)
3482{
3483  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
3484  return ftpc ? ftp_statemach(data, ftpc, done) : CURLE_FAILED_INIT;
3485}
3486
3487static CURLcode ftp_block_statemach(struct Curl_easy *data,
3488                                    struct ftp_conn *ftpc)
3489{
3490  struct pingpong *pp = &ftpc->pp;
3491  CURLcode result = CURLE_OK;
3492
3493  while(ftpc->state != FTP_STOP) {
3494    if(ftpc->shutdown)
3495      CURL_TRC_FTP(data, "in shutdown, waiting for server response");
3496    result = Curl_pp_statemach(data, pp, TRUE, TRUE /* disconnecting */);
3497    if(result)
3498      break;
3499  }
3500
3501  return result;
3502}
3503
3504/*
3505 * ftp_connect() should do everything that is to be considered a part of
3506 * the connection phase.
3507 *
3508 * The variable 'done' points to will be TRUE if the protocol-layer connect
3509 * phase is done when this function returns, or FALSE if not.
3510 *
3511 */
3512static CURLcode ftp_connect(struct Curl_easy *data,
3513                            bool *done) /* see description above */
3514{
3515  CURLcode result;
3516  struct connectdata *conn = data->conn;
3517  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
3518  struct pingpong *pp;
3519
3520  *done = FALSE; /* default to not done yet */
3521  if(!ftpc)
3522    return CURLE_FAILED_INIT;
3523  pp = &ftpc->pp;
3524  PINGPONG_SETUP(pp, ftp_pp_statemachine, ftp_endofresp);
3525
3526  if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
3527    /* BLOCKING */
3528    result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, done);
3529    if(result)
3530      return result;
3531  }
3532
3533  Curl_pp_init(pp, Curl_pgrs_now(data)); /* once per transfer */
3534
3535  /* When we connect, we start in the state where we await the 220
3536     response */
3537  ftp_state(data, ftpc, FTP_WAIT220);
3538
3539  result = ftp_statemach(data, ftpc, done);
3540
3541  return result;
3542}
3543
3544/***********************************************************************
3545 *
3546 * ftp_sendquote()
3547 *
3548 * Where a 'quote' means a list of custom commands to send to the server.
3549 * The quote list is passed as an argument.
3550 *
3551 * BLOCKING
3552 */
3553static CURLcode ftp_sendquote(struct Curl_easy *data,
3554                              struct ftp_conn *ftpc,
3555                              struct curl_slist *quote)
3556{
3557  struct curl_slist *item;
3558  struct pingpong *pp = &ftpc->pp;
3559
3560  item = quote;
3561  while(item) {
3562    if(item->data) {
3563      size_t nread;
3564      const char *cmd = item->data;
3565      bool acceptfail = FALSE;
3566      CURLcode result;
3567      int ftpcode = 0;
3568
3569      /* if a command starts with an asterisk, which a legal FTP command never
3570         can, the command will be allowed to fail without it causing any
3571         aborts or cancels etc. It will cause libcurl to act as if the command
3572         is successful, whatever the server responds. */
3573
3574      if(cmd[0] == '*') {
3575        cmd++;
3576        acceptfail = TRUE;
3577      }
3578
3579      result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
3580      if(!result) {
3581        pp->response = *Curl_pgrs_now(data); /* timeout relative now */
3582        result = getftpresponse(data, &nread, &ftpcode);
3583      }
3584      if(result)
3585        return result;
3586
3587      if(!acceptfail && (ftpcode >= 400)) {
3588        failf(data, "QUOT string not accepted: %s", cmd);
3589        return CURLE_QUOTE_ERROR;
3590      }
3591    }
3592
3593    item = item->next;
3594  }
3595
3596  return CURLE_OK;
3597}
3598
3599static CURLcode ftp_done_status(struct connectdata *conn,
3600                                struct ftp_conn *ftpc, CURLcode status,
3601                                bool premature)
3602{
3603  switch(status) {
3604  case CURLE_BAD_DOWNLOAD_RESUME:
3605  case CURLE_FTP_WEIRD_PASV_REPLY:
3606  case CURLE_FTP_PORT_FAILED:
3607  case CURLE_FTP_ACCEPT_FAILED:
3608  case CURLE_FTP_ACCEPT_TIMEOUT:
3609  case CURLE_FTP_COULDNT_SET_TYPE:
3610  case CURLE_FTP_COULDNT_RETR_FILE:
3611  case CURLE_PARTIAL_FILE:
3612  case CURLE_UPLOAD_FAILED:
3613  case CURLE_REMOTE_ACCESS_DENIED:
3614  case CURLE_FILESIZE_EXCEEDED:
3615  case CURLE_REMOTE_FILE_NOT_FOUND:
3616  case CURLE_WRITE_ERROR:
3617    /* the connection stays alive fine even though this happened */
3618  case CURLE_OK: /* does not affect the control connection's status */
3619    if(!premature)
3620      break;
3621
3622    /* until we cope better with prematurely ended requests, let them
3623     * fallback as if in complete failure */
3624    FALLTHROUGH();
3625  default:       /* by default, an error means the control connection is
3626                    wedged and should not be used anymore */
3627    ftpc->ctl_valid = FALSE;
3628    ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the
3629                             current path, as this connection is going */
3630    connclose(conn, "FTP ended with bad error code");
3631    return status;      /* use the already set error code */
3632  }
3633  return CURLE_OK;
3634}
3635
3636static void ftp_done_wildcard(struct Curl_easy *data, struct ftp_conn *ftpc)
3637{
3638  if(data->state.wildcardmatch) {
3639    if(data->set.chunk_end && ftpc->file) {
3640      Curl_set_in_callback(data, TRUE);
3641      data->set.chunk_end(data->set.wildcardptr);
3642      Curl_set_in_callback(data, FALSE);
3643      freedirs(ftpc);
3644    }
3645    ftpc->known_filesize = -1;
3646  }
3647}
3648
3649static void ftp_done_path(struct Curl_easy *data, struct ftp_conn *ftpc,
3650                          CURLcode result)
3651{
3652  struct connectdata *conn = data->conn;
3653  if(result) {
3654    /* We can limp along anyway (and should try to since we may already be in
3655     * the error path) */
3656    ftpc->ctl_valid = FALSE; /* mark control connection as bad */
3657    connclose(conn, "FTP: out of memory!"); /* mark for connection closure */
3658    curlx_free(ftpc->prevpath);
3659    ftpc->prevpath = NULL; /* no path remembering */
3660  }
3661  else { /* remember working directory for connection reuse */
3662    const char *rawPath = ftpc->rawpath;
3663    if(rawPath) {
3664      if((data->set.ftp_filemethod == FTPFILE_NOCWD) && (rawPath[0] == '/'))
3665        ; /* full path => no CWDs happened => keep ftpc->prevpath */
3666      else {
3667        size_t pathLen = strlen(ftpc->rawpath);
3668
3669        curlx_free(ftpc->prevpath);
3670
3671        if(!ftpc->cwdfail) {
3672          if(data->set.ftp_filemethod == FTPFILE_NOCWD)
3673            pathLen = 0; /* relative path => working directory is FTP home */
3674          else
3675            /* file is URL-decoded */
3676            pathLen -= ftpc->file ? strlen(ftpc->file) : 0;
3677          ftpc->prevpath = curlx_memdup0(rawPath, pathLen);
3678        }
3679        else
3680          ftpc->prevpath = NULL; /* no path */
3681      }
3682    }
3683    if(ftpc->prevpath)
3684      infof(data, "Remembering we are in directory \"%s\"", ftpc->prevpath);
3685  }
3686}
3687
3688static CURLcode ftp_done_secondary_socket(struct Curl_easy *data,
3689                                          struct ftp_conn *ftpc,
3690                                          CURLcode result)
3691{
3692  struct connectdata *conn = data->conn;
3693  if(Curl_conn_is_setup(conn, SECONDARYSOCKET)) {
3694    if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
3695      /* partial download completed */
3696      result = Curl_pp_sendf(data, &ftpc->pp, "%s", "ABOR");
3697      if(result) {
3698        failf(data, "Failure sending ABOR command: %s",
3699              curl_easy_strerror(result));
3700        ftpc->ctl_valid = FALSE; /* mark control connection as bad */
3701        connclose(conn, "ABOR command failed"); /* connection closure */
3702      }
3703    }
3704
3705    close_secondarysocket(data, ftpc);
3706  }
3707  return result;
3708}
3709
3710static CURLcode ftp_done_control_reply(struct Curl_easy *data,
3711                                       struct ftp_conn *ftpc,
3712                                       struct FTP *ftp, CURLcode result,
3713                                       bool premature)
3714{
3715  struct connectdata *conn = data->conn;
3716  size_t nread;
3717  int ftpcode;
3718
3719  if(!result && (ftp->transfer == PPTRANSFER_BODY) && ftpc->ctl_valid &&
3720     ftpc->pp.pending_resp && !premature) {
3721    /*
3722     * Let's see what the server says about the transfer we performed, but
3723     * lower the timeout as sometimes this connection has died while the data
3724     * has been transferred. This happens when doing through NATs etc that
3725     * abandon old silent connections.
3726     */
3727    ftpc->pp.response = *Curl_pgrs_now(data); /* timeout relative now */
3728    result = getftpresponse(data, &nread, &ftpcode);
3729
3730    if(!nread && (result == CURLE_OPERATION_TIMEDOUT)) {
3731      failf(data, "control connection looks dead");
3732      ftpc->ctl_valid = FALSE; /* mark control connection as bad */
3733      connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */
3734    }
3735
3736    if(result)
3737      return result;
3738
3739    if(ftpc->dont_check && data->req.maxdownload > 0) {
3740      /* we have sent ABOR and there is no reliable way to check if it was
3741       * successful or not; we have to close the connection now */
3742      infof(data, "partial download completed, closing connection");
3743      connclose(conn, "Partial download with no ability to check");
3744      return result;
3745    }
3746
3747    if(!ftpc->dont_check) {
3748      /* 226 Transfer complete, 250 Requested file action okay, completed. */
3749      switch(ftpcode) {
3750      case 226:
3751      case 250:
3752        break;
3753      case 552:
3754        failf(data, "Exceeded storage allocation");
3755        result = CURLE_REMOTE_DISK_FULL;
3756        break;
3757      default:
3758        failf(data, "server did not report OK, got %d", ftpcode);
3759        result = CURLE_PARTIAL_FILE;
3760        break;
3761      }
3762    }
3763  }
3764  return result;
3765}
3766
3767static CURLcode ftp_done_check_partial(struct Curl_easy *data,
3768                                       struct ftp_conn *ftpc,
3769                                       struct FTP *ftp, CURLcode result,
3770                                       bool premature)
3771{
3772  if(result || premature)
3773    /* the response code from the transfer showed an error already so no
3774       use checking further */
3775    ;
3776  else if(data->state.upload) {
3777    if((ftp->transfer == PPTRANSFER_BODY) &&
3778       (data->state.infilesize != -1) && /* upload with known size */
3779       ((!data->set.crlf && !data->state.prefer_ascii && /* no conversion */
3780         (data->state.infilesize != data->req.writebytecount)) ||
3781        ((data->set.crlf || data->state.prefer_ascii) && /* maybe crlf conv */
3782         (data->state.infilesize > data->req.writebytecount))
3783       )) {
3784      failf(data, "Uploaded unaligned file size (%" FMT_OFF_T
3785            " out of %" FMT_OFF_T " bytes)",
3786            data->req.writebytecount, data->state.infilesize);
3787      result = CURLE_PARTIAL_FILE;
3788    }
3789  }
3790  else {
3791    if((data->req.size != -1) &&
3792       (data->req.size != data->req.bytecount) &&
3793       (data->req.maxdownload != data->req.bytecount)) {
3794      failf(data, "Received only partial file: %" FMT_OFF_T " bytes",
3795            data->req.bytecount);
3796      result = CURLE_PARTIAL_FILE;
3797    }
3798    else if(!ftpc->dont_check &&
3799            !data->req.bytecount &&
3800            (data->req.size > 0)) {
3801      failf(data, "No data was received");
3802      result = CURLE_FTP_COULDNT_RETR_FILE;
3803    }
3804  }
3805  return result;
3806}
3807
3808/***********************************************************************
3809 *
3810 * ftp_done()
3811 *
3812 * The DONE function. This does what needs to be done after a single DO has
3813 * performed.
3814 *
3815 * Input argument is already checked for validity.
3816 */
3817static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
3818                         bool premature)
3819{
3820  struct FTP *ftp = Curl_meta_get(data, CURL_META_FTP_EASY);
3821  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
3822  CURLcode result;
3823
3824  if(!ftp || !ftpc)
3825    return CURLE_OK;
3826
3827  result = ftp_done_status(data->conn, ftpc, status, premature);
3828
3829  ftp_done_wildcard(data, ftpc);
3830  ftp_done_path(data, ftpc, result);
3831  result = ftp_done_secondary_socket(data, ftpc, result);
3832  result = ftp_done_control_reply(data, ftpc, ftp, result, premature);
3833  result = ftp_done_check_partial(data, ftpc, ftp, result, premature);
3834
3835  /* clear these for next connection */
3836  ftp->transfer = PPTRANSFER_BODY;
3837  ftpc->dont_check = FALSE;
3838
3839  /* Send any post-transfer QUOTE strings? */
3840  if(!status && !result && !premature && data->set.postquote)
3841    result = ftp_sendquote(data, ftpc, data->set.postquote);
3842  CURL_TRC_FTP(data, "[%s] done, result=%d", FTP_CSTATE(ftpc), result);
3843  return result;
3844}
3845
3846/***********************************************************************
3847 *
3848 * ftp_nb_type()
3849 *
3850 * Set TYPE. We only deal with ASCII or BINARY so this function
3851 * sets one of them.
3852 * If the transfer type is not sent, simulate on OK response in newstate
3853 */
3854static CURLcode ftp_nb_type(struct Curl_easy *data,
3855                            struct ftp_conn *ftpc,
3856                            struct FTP *ftp,
3857                            bool ascii, ftpstate newstate)
3858{
3859  CURLcode result;
3860  char want = (char)(ascii ? 'A' : 'I');
3861
3862  if(ftpc->transfertype == want) {
3863    ftp_state(data, ftpc, newstate);
3864    return ftp_state_type_resp(data, ftpc, ftp, 200, newstate);
3865  }
3866
3867  result = Curl_pp_sendf(data, &ftpc->pp, "TYPE %c", want);
3868  if(!result) {
3869    ftp_state(data, ftpc, newstate);
3870
3871    /* keep track of our current transfer type */
3872    ftpc->transfertype = want;
3873  }
3874  return result;
3875}
3876
3877/***********************************************************************
3878 *
3879 * ftp_perform()
3880 *
3881 * This is the actual DO function for FTP. Get a file/directory according to
3882 * the options previously setup.
3883 */
3884static CURLcode ftp_perform(
3885  struct Curl_easy *data,
3886  struct ftp_conn *ftpc,
3887  struct FTP *ftp,
3888  bool *connected,  /* connect status after PASV / PORT */
3889  bool *dophase_done)
3890{
3891  /* this is FTP and no proxy */
3892  CURLcode result = CURLE_OK;
3893
3894  CURL_TRC_FTP(data, "[%s] DO phase starts", FTP_CSTATE(ftpc));
3895
3896  if(data->req.no_body) {
3897    /* requested no body means no transfer... */
3898    ftp->transfer = PPTRANSFER_INFO;
3899  }
3900
3901  *dophase_done = FALSE; /* not done yet */
3902
3903  /* start the first command in the DO phase */
3904  result = ftp_state_quote(data, ftpc, ftp, TRUE, FTP_QUOTE);
3905  if(result)
3906    return result;
3907
3908  /* run the state-machine */
3909  result = ftp_statemach(data, ftpc, dophase_done);
3910
3911  *connected = Curl_conn_is_connected(data->conn, SECONDARYSOCKET);
3912
3913  if(*connected)
3914    infof(data, "[FTP] [%s] perform, DATA connection established",
3915          FTP_CSTATE(ftpc));
3916  else
3917    CURL_TRC_FTP(data, "[%s] perform, awaiting DATA connect",
3918                 FTP_CSTATE(ftpc));
3919
3920  if(*dophase_done)
3921    CURL_TRC_FTP(data, "[%s] DO phase is complete1", FTP_CSTATE(ftpc));
3922
3923  return result;
3924}
3925
3926static void wc_data_dtor(void *ptr)
3927{
3928  struct ftp_wc *ftpwc = ptr;
3929  if(ftpwc && ftpwc->parser)
3930    Curl_ftp_parselist_data_free(&ftpwc->parser);
3931  curlx_free(ftpwc);
3932}
3933
3934static CURLcode init_wc_data(struct Curl_easy *data,
3935                             struct ftp_conn *ftpc,
3936                             struct FTP *ftp)
3937{
3938  char *last_slash;
3939  char *path = ftp->path;
3940  struct WildcardData *wildcard = data->wildcard;
3941  CURLcode result = CURLE_OK;
3942  struct ftp_wc *ftpwc = NULL;
3943
3944  last_slash = strrchr(ftp->path, '/');
3945  if(last_slash) {
3946    last_slash++;
3947    if(last_slash[0] == '\0') {
3948      wildcard->state = CURLWC_CLEAN;
3949      return ftp_parse_url_path(data, ftpc, ftp);
3950    }
3951    wildcard->pattern = curlx_strdup(last_slash);
3952    if(!wildcard->pattern)
3953      return CURLE_OUT_OF_MEMORY;
3954    last_slash[0] = '\0'; /* cut file from path */
3955  }
3956  else { /* there is only 'wildcard pattern' or nothing */
3957    if(path[0]) {
3958      wildcard->pattern = curlx_strdup(path);
3959      if(!wildcard->pattern)
3960        return CURLE_OUT_OF_MEMORY;
3961      path[0] = '\0';
3962    }
3963    else { /* only list */
3964      wildcard->state = CURLWC_CLEAN;
3965      return ftp_parse_url_path(data, ftpc, ftp);
3966    }
3967  }
3968
3969  /* program continues only if URL is not ending with slash, allocate needed
3970     resources for wildcard transfer */
3971
3972  /* allocate ftp protocol specific wildcard data */
3973  ftpwc = curlx_calloc(1, sizeof(struct ftp_wc));
3974  if(!ftpwc) {
3975    result = CURLE_OUT_OF_MEMORY;
3976    goto fail;
3977  }
3978
3979  /* INITIALIZE parselist structure */
3980  ftpwc->parser = Curl_ftp_parselist_data_alloc();
3981  if(!ftpwc->parser) {
3982    result = CURLE_OUT_OF_MEMORY;
3983    goto fail;
3984  }
3985
3986  wildcard->ftpwc = ftpwc; /* put it to the WildcardData tmp pointer */
3987  wildcard->dtor = wc_data_dtor;
3988
3989  /* wildcard does not support NOCWD option (assert it?) */
3990  if(data->set.ftp_filemethod == FTPFILE_NOCWD)
3991    data->set.ftp_filemethod = FTPFILE_MULTICWD;
3992
3993  /* try to parse ftp URL */
3994  result = ftp_parse_url_path(data, ftpc, ftp);
3995  if(result) {
3996    goto fail;
3997  }
3998
3999  wildcard->path = curlx_strdup(ftp->path);
4000  if(!wildcard->path) {
4001    result = CURLE_OUT_OF_MEMORY;
4002    goto fail;
4003  }
4004
4005  /* backup old write_function */
4006  ftpwc->backup.write_function = data->set.fwrite_func;
4007  /* parsing write function */
4008  data->set.fwrite_func = Curl_ftp_parselist;
4009  /* backup old file descriptor */
4010  ftpwc->backup.file_descriptor = data->set.out;
4011  /* let the writefunc callback know the transfer */
4012  data->set.out = data;
4013
4014  infof(data, "Wildcard - Parsing started");
4015  return CURLE_OK;
4016
4017fail:
4018  if(ftpwc) {
4019    Curl_ftp_parselist_data_free(&ftpwc->parser);
4020    curlx_free(ftpwc);
4021  }
4022  curlx_safefree(wildcard->pattern);
4023  wildcard->dtor = ZERO_NULL;
4024  wildcard->ftpwc = NULL;
4025  return result;
4026}
4027
4028static CURLcode wc_statemach(struct Curl_easy *data,
4029                             struct ftp_conn *ftpc,
4030                             struct FTP *ftp)
4031{
4032  struct WildcardData * const wildcard = data->wildcard;
4033  CURLcode result = CURLE_OK;
4034
4035  for(;;) {
4036    switch(wildcard->state) {
4037    case CURLWC_INIT:
4038      result = init_wc_data(data, ftpc, ftp);
4039      if(wildcard->state == CURLWC_CLEAN)
4040        /* only listing! */
4041        return result;
4042      wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
4043      return result;
4044
4045    case CURLWC_MATCHING: {
4046      /* In this state is LIST response successfully parsed, so lets restore
4047         previous WRITEFUNCTION callback and WRITEDATA pointer */
4048      struct ftp_wc *ftpwc = wildcard->ftpwc;
4049      data->set.fwrite_func = ftpwc->backup.write_function;
4050      data->set.out = ftpwc->backup.file_descriptor;
4051      ftpwc->backup.write_function = ZERO_NULL;
4052      ftpwc->backup.file_descriptor = NULL;
4053      wildcard->state = CURLWC_DOWNLOADING;
4054
4055      if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
4056        /* error found in LIST parsing */
4057        wildcard->state = CURLWC_CLEAN;
4058        continue;
4059      }
4060      if(Curl_llist_count(&wildcard->filelist) == 0) {
4061        /* no corresponding file */
4062        wildcard->state = CURLWC_CLEAN;
4063        return CURLE_REMOTE_FILE_NOT_FOUND;
4064      }
4065      continue;
4066    }
4067
4068    case CURLWC_DOWNLOADING: {
4069      /* filelist has at least one file, lets get first one */
4070      struct Curl_llist_node *head = Curl_llist_head(&wildcard->filelist);
4071      struct curl_fileinfo *finfo = Curl_node_elem(head);
4072
4073      char *tmp_path = curl_maprintf("%s%s", wildcard->path, finfo->filename);
4074      if(!tmp_path)
4075        return CURLE_OUT_OF_MEMORY;
4076
4077      /* switch default ftp->path and tmp_path */
4078      curlx_free(ftp->pathalloc);
4079      ftp->pathalloc = ftp->path = tmp_path;
4080
4081      infof(data, "Wildcard - START of \"%s\"", finfo->filename);
4082      if(data->set.chunk_bgn) {
4083        long userresponse;
4084        Curl_set_in_callback(data, TRUE);
4085        userresponse = data->set.chunk_bgn(
4086          finfo, data->set.wildcardptr,
4087          (int)Curl_llist_count(&wildcard->filelist));
4088        Curl_set_in_callback(data, FALSE);
4089        switch(userresponse) {
4090        case CURL_CHUNK_BGN_FUNC_SKIP:
4091          infof(data, "Wildcard - \"%s\" skipped by user", finfo->filename);
4092          wildcard->state = CURLWC_SKIP;
4093          continue;
4094        case CURL_CHUNK_BGN_FUNC_FAIL:
4095          return CURLE_CHUNK_FAILED;
4096        }
4097      }
4098
4099      if(finfo->filetype != CURLFILETYPE_FILE) {
4100        wildcard->state = CURLWC_SKIP;
4101        continue;
4102      }
4103
4104      if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
4105        ftpc->known_filesize = finfo->size;
4106
4107      result = ftp_parse_url_path(data, ftpc, ftp);
4108      if(result)
4109        return result;
4110
4111      /* we do not need the Curl_fileinfo of first file anymore */
4112      Curl_node_remove(Curl_llist_head(&wildcard->filelist));
4113
4114      if(Curl_llist_count(&wildcard->filelist) == 0) {
4115        /* remains only one file to down. */
4116        wildcard->state = CURLWC_CLEAN;
4117        /* after that will be ftp_do called once again and no transfer
4118           will be done because of CURLWC_CLEAN state */
4119        return CURLE_OK;
4120      }
4121      return result;
4122    }
4123
4124    case CURLWC_SKIP: {
4125      if(data->set.chunk_end) {
4126        Curl_set_in_callback(data, TRUE);
4127        data->set.chunk_end(data->set.wildcardptr);
4128        Curl_set_in_callback(data, FALSE);
4129      }
4130      Curl_node_remove(Curl_llist_head(&wildcard->filelist));
4131      wildcard->state = (Curl_llist_count(&wildcard->filelist) == 0) ?
4132        CURLWC_CLEAN : CURLWC_DOWNLOADING;
4133      continue;
4134    }
4135
4136    case CURLWC_CLEAN: {
4137      struct ftp_wc *ftpwc = wildcard->ftpwc;
4138      result = CURLE_OK;
4139      if(ftpwc)
4140        result = Curl_ftp_parselist_geterror(ftpwc->parser);
4141
4142      wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
4143      return result;
4144    }
4145
4146    case CURLWC_DONE:
4147    case CURLWC_ERROR:
4148    case CURLWC_CLEAR:
4149      if(wildcard->dtor) {
4150        wildcard->dtor(wildcard->ftpwc);
4151        wildcard->ftpwc = NULL;
4152      }
4153      return result;
4154    }
4155  }
4156  /* UNREACHABLE */
4157}
4158
4159/***********************************************************************
4160 *
4161 * ftp_regular_transfer()
4162 *
4163 * The input argument is already checked for validity.
4164 *
4165 * Performs all commands done before a regular transfer between a local and a
4166 * remote host.
4167 *
4168 * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
4169 * ftp_done() function without finding any major problem.
4170 */
4171static CURLcode ftp_regular_transfer(struct Curl_easy *data,
4172                                     struct ftp_conn *ftpc,
4173                                     struct FTP *ftp,
4174                                     bool *dophase_done)
4175{
4176  CURLcode result = CURLE_OK;
4177  bool connected = FALSE;
4178  data->req.size = -1; /* make sure this is unknown at this point */
4179
4180  Curl_pgrsReset(data);
4181
4182  ftpc->ctl_valid = TRUE; /* starts good */
4183
4184  result = ftp_perform(data, ftpc, ftp,
4185                       &connected, /* have we connected after PASV/PORT */
4186                       dophase_done); /* all commands in the DO-phase done? */
4187
4188  if(!result) {
4189
4190    if(!*dophase_done)
4191      /* the DO phase has not completed yet */
4192      return CURLE_OK;
4193
4194    result = ftp_dophase_done(data, ftpc, ftp, connected);
4195
4196    if(result)
4197      return result;
4198  }
4199  else
4200    freedirs(ftpc);
4201
4202  return result;
4203}
4204
4205/***********************************************************************
4206 *
4207 * ftp_do()
4208 *
4209 * This function is registered as 'curl_do' function. It decodes the path
4210 * parts etc as a wrapper to the actual DO function (ftp_perform).
4211 *
4212 * The input argument is already checked for validity.
4213 */
4214static CURLcode ftp_do(struct Curl_easy *data, bool *done)
4215{
4216  CURLcode result = CURLE_OK;
4217  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
4218  struct FTP *ftp = Curl_meta_get(data, CURL_META_FTP_EASY);
4219
4220  *done = FALSE; /* default to false */
4221  if(!ftpc || !ftp)
4222    return CURLE_FAILED_INIT;
4223  ftpc->wait_data_conn = FALSE; /* default to no such wait */
4224
4225#ifdef CURL_PREFER_LF_LINEENDS
4226  {
4227    /* FTP data may need conversion. */
4228    struct Curl_cwriter *ftp_lc_writer;
4229
4230    result = Curl_cwriter_create(&ftp_lc_writer, data, &ftp_cw_lc,
4231                                 CURL_CW_CONTENT_DECODE);
4232    if(result)
4233      return result;
4234
4235    result = Curl_cwriter_add(data, ftp_lc_writer);
4236    if(result) {
4237      Curl_cwriter_free(data, ftp_lc_writer);
4238      return result;
4239    }
4240  }
4241#endif /* CURL_PREFER_LF_LINEENDS */
4242
4243  if(data->state.wildcardmatch) {
4244    result = wc_statemach(data, ftpc, ftp);
4245    if(data->wildcard->state == CURLWC_SKIP ||
4246       data->wildcard->state == CURLWC_DONE) {
4247      /* do not call ftp_regular_transfer */
4248      return CURLE_OK;
4249    }
4250    if(result) /* error, loop or skipping the file */
4251      return result;
4252  }
4253  else { /* no wildcard FSM needed */
4254    result = ftp_parse_url_path(data, ftpc, ftp);
4255    if(result)
4256      return result;
4257  }
4258
4259  result = ftp_regular_transfer(data, ftpc, ftp, done);
4260
4261  return result;
4262}
4263
4264/***********************************************************************
4265 *
4266 * ftp_quit()
4267 *
4268 * This should be called before calling sclose() on an ftp control connection
4269 * (not data connections). We should then wait for the response from the
4270 * server before returning. The calling code should then try to close the
4271 * connection.
4272 *
4273 */
4274static CURLcode ftp_quit(struct Curl_easy *data,
4275                         struct ftp_conn *ftpc)
4276{
4277  CURLcode result = CURLE_OK;
4278
4279  if(ftpc->ctl_valid) {
4280    CURL_TRC_FTP(data, "sending QUIT to close session");
4281    result = Curl_pp_sendf(data, &ftpc->pp, "%s", "QUIT");
4282    if(result) {
4283      failf(data, "Failure sending QUIT command: %s",
4284            curl_easy_strerror(result));
4285      ftpc->ctl_valid = FALSE; /* mark control connection as bad */
4286      connclose(data->conn, "QUIT command failed"); /* mark for closure */
4287      ftp_state(data, ftpc, FTP_STOP);
4288      return result;
4289    }
4290
4291    ftp_state(data, ftpc, FTP_QUIT);
4292
4293    result = ftp_block_statemach(data, ftpc);
4294  }
4295
4296  return result;
4297}
4298
4299/***********************************************************************
4300 *
4301 * ftp_disconnect()
4302 *
4303 * Disconnect from an FTP server. Cleanup protocol-specific per-connection
4304 * resources. BLOCKING.
4305 */
4306static CURLcode ftp_disconnect(struct Curl_easy *data,
4307                               struct connectdata *conn,
4308                               bool dead_connection)
4309{
4310  struct ftp_conn *ftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
4311
4312  if(!ftpc)
4313    return CURLE_FAILED_INIT;
4314  /* We cannot send quit unconditionally. If this connection is stale or
4315     bad in any way, sending quit and waiting around here will make the
4316     disconnect wait in vain and cause more problems than we need to.
4317
4318     ftp_quit() will check the state of ftp->ctl_valid. If it is ok it
4319     will try to send the QUIT command, otherwise it will return.
4320  */
4321  ftpc->shutdown = TRUE;
4322  if(dead_connection || Curl_pp_needs_flush(data, &ftpc->pp))
4323    ftpc->ctl_valid = FALSE;
4324
4325  /* The FTP session may or may not have been allocated/setup at this point! */
4326  (void)ftp_quit(data, ftpc); /* ignore errors on the QUIT */
4327  return CURLE_OK;
4328}
4329
4330/* called from multi.c while DOing */
4331static CURLcode ftp_doing(struct Curl_easy *data,
4332                          bool *dophase_done)
4333{
4334  struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
4335  struct FTP *ftp = Curl_meta_get(data, CURL_META_FTP_EASY);
4336  CURLcode result;
4337
4338  if(!ftpc || !ftp)
4339    return CURLE_FAILED_INIT;
4340  result = ftp_statemach(data, ftpc, dophase_done);
4341
4342  if(result)
4343    CURL_TRC_FTP(data, "[%s] DO phase failed", FTP_CSTATE(ftpc));
4344  else if(*dophase_done) {
4345    result = ftp_dophase_done(data, ftpc, ftp, FALSE /* not connected */);
4346
4347    CURL_TRC_FTP(data, "[%s] DO phase is complete2", FTP_CSTATE(ftpc));
4348  }
4349  return result;
4350}
4351
4352static void ftp_easy_dtor(void *key, size_t klen, void *entry)
4353{
4354  struct FTP *ftp = entry;
4355  (void)key;
4356  (void)klen;
4357  curlx_safefree(ftp->pathalloc);
4358  curlx_free(ftp);
4359}
4360
4361static void ftp_conn_dtor(void *key, size_t klen, void *entry)
4362{
4363  struct ftp_conn *ftpc = entry;
4364  (void)key;
4365  (void)klen;
4366  freedirs(ftpc);
4367  curlx_safefree(ftpc->account);
4368  curlx_safefree(ftpc->alternative_to_user);
4369  curlx_safefree(ftpc->entrypath);
4370  curlx_safefree(ftpc->prevpath);
4371  curlx_safefree(ftpc->server_os);
4372  Curl_pp_disconnect(&ftpc->pp);
4373  curlx_free(ftpc);
4374}
4375
4376static void type_url_check(struct Curl_easy *data, struct FTP *ftp)
4377{
4378  size_t len = strlen(ftp->path);
4379  /* FTP URLs support an extension like ";type=<typecode>" that
4380   * we will try to get now! */
4381  if((len >= 7) && !memcmp(&ftp->path[len - 7], ";type=", 6)) {
4382    char *type = &ftp->path[len - 7];
4383    char command = Curl_raw_toupper(type[6]);
4384
4385    *type = 0; /* cut it off */
4386
4387    switch(command) {
4388    case 'A': /* ASCII mode */
4389      data->state.prefer_ascii = TRUE;
4390      break;
4391
4392    case 'D': /* directory mode */
4393      data->state.list_only = TRUE;
4394      break;
4395
4396    case 'I': /* binary mode */
4397    default:
4398      /* switch off ASCII */
4399      data->state.prefer_ascii = FALSE;
4400      break;
4401    }
4402  }
4403}
4404
4405static CURLcode ftp_setup_connection(struct Curl_easy *data,
4406                                     struct connectdata *conn)
4407{
4408  struct FTP *ftp;
4409  CURLcode result = CURLE_OK;
4410  struct ftp_conn *ftpc;
4411
4412  ftp = curlx_calloc(1, sizeof(*ftp));
4413  if(!ftp ||
4414     Curl_meta_set(data, CURL_META_FTP_EASY, ftp, ftp_easy_dtor))
4415    return CURLE_OUT_OF_MEMORY;
4416
4417  ftpc = curlx_calloc(1, sizeof(*ftpc));
4418  if(!ftpc ||
4419     Curl_conn_meta_set(conn, CURL_META_FTP_CONN, ftpc, ftp_conn_dtor))
4420    return CURLE_OUT_OF_MEMORY;
4421
4422  /* clone connection related data that is FTP specific */
4423  if(data->set.str[STRING_FTP_ACCOUNT]) {
4424    ftpc->account = curlx_strdup(data->set.str[STRING_FTP_ACCOUNT]);
4425    if(!ftpc->account) {
4426      Curl_conn_meta_remove(conn, CURL_META_FTP_CONN);
4427      return CURLE_OUT_OF_MEMORY;
4428    }
4429  }
4430  if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]) {
4431    ftpc->alternative_to_user =
4432      curlx_strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
4433    if(!ftpc->alternative_to_user) {
4434      curlx_safefree(ftpc->account);
4435      Curl_conn_meta_remove(conn, CURL_META_FTP_CONN);
4436      return CURLE_OUT_OF_MEMORY;
4437    }
4438  }
4439
4440  ftp->path = &data->state.up.path[1]; /* do not include the initial slash */
4441
4442  type_url_check(data, ftp);
4443
4444  /* get some initial data into the ftp struct */
4445  ftp->transfer = PPTRANSFER_BODY;
4446  ftp->downloadsize = 0;
4447  ftpc->known_filesize = -1; /* unknown size for now */
4448  ftpc->use_ssl = data->set.use_ssl;
4449  ftpc->ccc = data->set.ftp_ccc;
4450
4451  CURL_TRC_FTP(data, "[%s] setup connection -> %d", FTP_CSTATE(ftpc), result);
4452  return result;
4453}
4454
4455bool ftp_conns_match(struct connectdata *needle, struct connectdata *conn)
4456{
4457  struct ftp_conn *nftpc = Curl_conn_meta_get(needle, CURL_META_FTP_CONN);
4458  struct ftp_conn *cftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
4459  /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
4460  if(!nftpc || !cftpc ||
4461     Curl_timestrcmp(nftpc->account, cftpc->account) ||
4462     Curl_timestrcmp(nftpc->alternative_to_user,
4463                     cftpc->alternative_to_user) ||
4464     (nftpc->use_ssl != cftpc->use_ssl) ||
4465     (nftpc->ccc != cftpc->ccc))
4466    return FALSE;
4467  return TRUE;
4468}
4469
4470/*
4471 * FTP protocol.
4472 */
4473const struct Curl_protocol Curl_protocol_ftp = {
4474  ftp_setup_connection,            /* setup_connection */
4475  ftp_do,                          /* do_it */
4476  ftp_done,                        /* done */
4477  ftp_do_more,                     /* do_more */
4478  ftp_connect,                     /* connect_it */
4479  ftp_multi_statemach,             /* connecting */
4480  ftp_doing,                       /* doing */
4481  ftp_pollset,                     /* proto_pollset */
4482  ftp_pollset,                     /* doing_pollset */
4483  ftp_domore_pollset,              /* domore_pollset */
4484  ZERO_NULL,                       /* perform_pollset */
4485  ftp_disconnect,                  /* disconnect */
4486  ZERO_NULL,                       /* write_resp */
4487  ZERO_NULL,                       /* write_resp_hd */
4488  ZERO_NULL,                       /* connection_is_dead */
4489  ZERO_NULL,                       /* attach connection */
4490  ZERO_NULL,                       /* follow */
4491};
4492
4493#endif /* CURL_DISABLE_FTP */