[Cmake-commits] CMake branch, master, updated. v3.14.4-1097-g2b8e5a3

Kitware Robot kwrobot at kitware.com
Fri May 24 10:43:10 EDT 2019


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, master has been updated
       via  2b8e5a3ba772d6df6e56a28d8645127008636b03 (commit)
       via  3b7894b96c53dad1818588ebb3577d5ef863e5c2 (commit)
       via  96189e99e10493ba9cd50be0f26177bd6bd599a8 (commit)
       via  96a013d44c020163865d5f2f270c4cc609e76322 (commit)
       via  ff0fb58fb5e0c543d97359c39ce4108cb55e3b86 (commit)
       via  25b2c7e4cd4e24a7723f5701afc1555a1a065301 (commit)
       via  006229278b54ee92003100773a0430565fb8fe87 (commit)
       via  999516478d56d8604d1413fe3c677a860357516c (commit)
       via  32e4f236b7635fe5008966065ec4099ba23ecf58 (commit)
       via  7b4b61a4d38e4c7fe3fe992a6263d8d1f0785858 (commit)
       via  90766347dbee280a6fd911d5242fa2342c1e7dd2 (commit)
       via  a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f (commit)
       via  b26487c663ec29d972fd61adc2b14ac5880b78c7 (commit)
       via  2de8af0121c3ca64dcb82a1220d2ba255aab3553 (commit)
      from  c22693b99df12f540480438275cd5bae1cfc5846 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2b8e5a3ba772d6df6e56a28d8645127008636b03
commit 2b8e5a3ba772d6df6e56a28d8645127008636b03
Merge: 3b7894b 25b2c7e
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri May 24 14:38:41 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri May 24 10:41:48 2019 -0400

    Merge topic 'ninja-pool-link-doc-nit'
    
    25b2c7e4cd Help/CMAKE_JOB_POOL_LINK: match the header line with the variable
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3369


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3b7894b96c53dad1818588ebb3577d5ef863e5c2
commit 3b7894b96c53dad1818588ebb3577d5ef863e5c2
Merge: 96189e9 32e4f23
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri May 24 14:37:02 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri May 24 10:40:39 2019 -0400

    Merge topic 'fix-armclang-policy'
    
    32e4f236b7 ARMClang: fix policy manipulation in the compiler module
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3365


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=96189e99e10493ba9cd50be0f26177bd6bd599a8
commit 96189e99e10493ba9cd50be0f26177bd6bd599a8
Merge: 96a013d 0062292
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri May 24 14:37:49 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri May 24 10:39:01 2019 -0400

    Merge topic 'cmAppend'
    
    006229278b Use cmAppend to append ranges to std::vector instances
    999516478d cmAlgorithms: Add cmAppend function
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3366


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=96a013d44c020163865d5f2f270c4cc609e76322
commit 96a013d44c020163865d5f2f270c4cc609e76322
Merge: ff0fb58 7b4b61a
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri May 24 14:36:36 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri May 24 10:37:38 2019 -0400

    Merge topic 'cmTargetMap_definition'
    
    7b4b61a4d3 cmMakefile: Define cmTargetMap type in cmMakefile instead of cmTarget
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3364


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ff0fb58fb5e0c543d97359c39ce4108cb55e3b86
commit ff0fb58fb5e0c543d97359c39ce4108cb55e3b86
Merge: c22693b 9076634
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri May 24 14:36:16 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri May 24 10:36:24 2019 -0400

    Merge topic 'update-curl'
    
    90766347db curl: Update build within CMake to account for 7.65 changes
    a39138ef9a Merge branch 'upstream-curl' into update-curl
    b26487c663 curl 2019-05-22 (885ce314)
    2de8af0121 curl: Update script to get curl 7.65.0
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3363


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=25b2c7e4cd4e24a7723f5701afc1555a1a065301
commit 25b2c7e4cd4e24a7723f5701afc1555a1a065301
Author:     Ben Boeckel <ben.boeckel at kitware.com>
AuthorDate: Fri May 24 09:31:56 2019 -0400
Commit:     Ben Boeckel <ben.boeckel at kitware.com>
CommitDate: Fri May 24 09:31:56 2019 -0400

    Help/CMAKE_JOB_POOL_LINK: match the header line with the variable

diff --git a/Help/variable/CMAKE_JOB_POOL_LINK.rst b/Help/variable/CMAKE_JOB_POOL_LINK.rst
index 338f771..eeee6e0 100644
--- a/Help/variable/CMAKE_JOB_POOL_LINK.rst
+++ b/Help/variable/CMAKE_JOB_POOL_LINK.rst
@@ -1,5 +1,5 @@
 CMAKE_JOB_POOL_LINK
-----------------------
+-------------------
 
 This variable is used to initialize the :prop_tgt:`JOB_POOL_LINK`
 property on all the targets. See :prop_tgt:`JOB_POOL_LINK`

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=006229278b54ee92003100773a0430565fb8fe87
commit 006229278b54ee92003100773a0430565fb8fe87
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu May 23 14:49:54 2019 +0200
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Thu May 23 16:19:49 2019 +0200

    Use cmAppend to append ranges to std::vector instances

diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx
index 83aeb64..b957856 100644
--- a/Source/CTest/cmCTestBZR.cxx
+++ b/Source/CTest/cmCTestBZR.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestBZR.h"
 
+#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestVC.h"
 #include "cmProcessTools.h"
@@ -242,7 +243,7 @@ private:
 
   void CharacterDataHandler(const char* data, int length) override
   {
-    this->CData.insert(this->CData.end(), data, data + length);
+    cmAppend(this->CData, data, data + length);
   }
 
   void EndElement(const std::string& name) override
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 1e17e1c..c8e4fa1 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -978,8 +978,7 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length,
     if (it != queue->end()) {
       // Create a contiguous array for the line
       this->CurrentProcessingLine.clear();
-      this->CurrentProcessingLine.insert(this->CurrentProcessingLine.end(),
-                                         queue->begin(), it);
+      cmAppend(this->CurrentProcessingLine, queue->begin(), it);
       this->CurrentProcessingLine.push_back(0);
       const char* line = this->CurrentProcessingLine.data();
 
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index d76bd2a..f6028c4 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestCoverageHandler.h"
 
+#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
@@ -813,15 +814,11 @@ int cmCTestCoverageHandler::HandleJacocoCoverage(
 
   // ...and in the binary directory.
   cmsys::Glob g2;
-  std::vector<std::string> binFiles;
   g2.SetRecurse(true);
   std::string binaryDir = this->CTest->GetCTestConfiguration("BuildDirectory");
   std::string binCoverageFile = binaryDir + "/*jacoco.xml";
   g2.FindFiles(binCoverageFile);
-  binFiles = g2.GetFiles();
-  if (!binFiles.empty()) {
-    files.insert(files.end(), binFiles.begin(), binFiles.end());
-  }
+  cmAppend(files, g2.GetFiles());
 
   if (!files.empty()) {
     cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -1465,8 +1462,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
         "   looking for LCOV files in: " << daGlob << std::endl, this->Quiet);
       gl.FindFiles(daGlob);
       // Keep a list of all LCOV files
-      lcovFiles.insert(lcovFiles.end(), gl.GetFiles().begin(),
-                       gl.GetFiles().end());
+      cmAppend(lcovFiles, gl.GetFiles());
 
       for (std::string const& file : lcovFiles) {
         lcovFile = file;
@@ -1604,11 +1600,11 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files)
     std::string daGlob = lm.first;
     daGlob += "/*.da";
     gl.FindFiles(daGlob);
-    files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end());
+    cmAppend(files, gl.GetFiles());
     daGlob = lm.first;
     daGlob += "/*.gcda";
     gl.FindFiles(daGlob);
-    files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end());
+    cmAppend(files, gl.GetFiles());
   }
 }
 
@@ -1645,7 +1641,7 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
                "Error while finding files matching " << daGlob << std::endl);
     return false;
   }
-  files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end());
+  cmAppend(files, gl.GetFiles());
   cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                      "Now searching in: " << daGlob << std::endl, this->Quiet);
   return true;
diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx
index 6eb4354..cc63e45 100644
--- a/Source/CTest/cmCTestCurl.cxx
+++ b/Source/CTest/cmCTestCurl.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestCurl.h"
 
+#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCurl.h"
 #include "cmSystemTools.h"
@@ -43,19 +44,15 @@ size_t curlWriteMemoryCallback(void* ptr, size_t size, size_t nmemb,
                                void* data)
 {
   int realsize = static_cast<int>(size * nmemb);
-
-  std::vector<char>* vec = static_cast<std::vector<char>*>(data);
   const char* chPtr = static_cast<char*>(ptr);
-  vec->insert(vec->end(), chPtr, chPtr + realsize);
+  cmAppend(*static_cast<std::vector<char>*>(data), chPtr, chPtr + realsize);
   return realsize;
 }
 
 size_t curlDebugCallback(CURL* /*unused*/, curl_infotype /*unused*/,
                          char* chPtr, size_t size, void* data)
 {
-  std::vector<char>* vec = static_cast<std::vector<char>*>(data);
-  vec->insert(vec->end(), chPtr, chPtr + size);
-
+  cmAppend(*static_cast<std::vector<char>*>(data), chPtr, chPtr + size);
   return size;
 }
 }
diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx
index 727c59c..ba2252a 100644
--- a/Source/CTest/cmCTestHG.cxx
+++ b/Source/CTest/cmCTestHG.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestHG.h"
 
+#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestVC.h"
 #include "cmProcessTools.h"
@@ -202,7 +203,7 @@ private:
 
   void CharacterDataHandler(const char* data, int length) override
   {
-    this->CData.insert(this->CData.end(), data, data + length);
+    cmAppend(this->CData, data, data + length);
   }
 
   void EndElement(const std::string& name) override
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 477161a..ef63073 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -3,6 +3,7 @@
 #include "cmCTestMultiProcessHandler.h"
 
 #include "cmAffinity.h"
+#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestRunTest.h"
 #include "cmCTestTestHandler.h"
@@ -653,13 +654,10 @@ void cmCTestMultiProcessHandler::CreateParallelTestCostList()
   // Reverse iterate over the different dependency levels (deepest first).
   // Sort tests within each level by COST and append them to the cost list.
   for (TestSet const& currentSet : cmReverseRange(priorityStack)) {
-    TestComparator comp(this);
-
     TestList sortedCopy;
-
-    sortedCopy.insert(sortedCopy.end(), currentSet.begin(), currentSet.end());
-
-    std::stable_sort(sortedCopy.begin(), sortedCopy.end(), comp);
+    cmAppend(sortedCopy, currentSet);
+    std::stable_sort(sortedCopy.begin(), sortedCopy.end(),
+                     TestComparator(this));
 
     for (auto const& j : sortedCopy) {
       if (alreadySortedTests.find(j) == alreadySortedTests.end()) {
@@ -688,8 +686,8 @@ void cmCTestMultiProcessHandler::CreateSerialTestCostList()
     presortedList.push_back(i.first);
   }
 
-  TestComparator comp(this);
-  std::stable_sort(presortedList.begin(), presortedList.end(), comp);
+  std::stable_sort(presortedList.begin(), presortedList.end(),
+                   TestComparator(this));
 
   TestSet alreadySortedTests;
 
@@ -992,7 +990,7 @@ static Json::Value DumpCTestInfo(
     const std::vector<std::string>& args = testRun.GetArguments();
     if (!args.empty()) {
       commandAndArgs.reserve(args.size() + 1);
-      commandAndArgs.insert(commandAndArgs.end(), args.begin(), args.end());
+      cmAppend(commandAndArgs, args);
     }
     testInfo["command"] = DumpToJsonArray(commandAndArgs);
   }
diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx
index aa42810..2eb8dba 100644
--- a/Source/CTest/cmCTestP4.cxx
+++ b/Source/CTest/cmCTestP4.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestP4.h"
 
+#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestVC.h"
 #include "cmProcessTools.h"
@@ -324,9 +325,7 @@ void cmCTestP4::SetP4Options(std::vector<char const*>& CommandOptions)
     // The CTEST_P4_OPTIONS variable adds additional Perforce command line
     // options before the main command
     std::string opts = this->CTest->GetCTestConfiguration("P4Options");
-    std::vector<std::string> args = cmSystemTools::ParseArguments(opts);
-
-    P4Options.insert(P4Options.end(), args.begin(), args.end());
+    cmAppend(P4Options, cmSystemTools::ParseArguments(opts));
   }
 
   CommandOptions.clear();
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index 04749b7..c834686 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestSVN.h"
 
+#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestVC.h"
 #include "cmProcessTools.h"
@@ -269,9 +270,7 @@ bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters,
 
   std::vector<char const*> args;
   args.push_back(this->CommandLineTool.c_str());
-
-  args.insert(args.end(), parameters.begin(), parameters.end());
-
+  cmAppend(args, parameters);
   args.push_back("--non-interactive");
 
   std::string userOptions = this->CTest->GetCTestConfiguration("SVNOptions");
@@ -344,7 +343,7 @@ private:
 
   void CharacterDataHandler(const char* data, int length) override
   {
-    this->CData.insert(this->CData.end(), data, data + length);
+    cmAppend(this->CData, data, data + length);
   }
 
   void EndElement(const std::string& name) override
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 2b54365..1fa7988 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -63,7 +63,7 @@ private:
 
   void CharacterDataHandler(const char* data, int length) override
   {
-    this->CurrentValue.insert(this->CurrentValue.end(), data, data + length);
+    cmAppend(this->CurrentValue, data, data + length);
   }
 
   void EndElement(const std::string& name) override
@@ -93,12 +93,9 @@ static size_t cmCTestSubmitHandlerWriteMemoryCallback(void* ptr, size_t size,
                                                       size_t nmemb, void* data)
 {
   int realsize = static_cast<int>(size * nmemb);
-
-  cmCTestSubmitHandlerVectorOfChar* vec =
-    static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
   const char* chPtr = static_cast<char*>(ptr);
-  vec->insert(vec->end(), chPtr, chPtr + realsize);
-
+  cmAppend(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr,
+           chPtr + realsize);
   return realsize;
 }
 
@@ -107,10 +104,8 @@ static size_t cmCTestSubmitHandlerCurlDebugCallback(CURL* /*unused*/,
                                                     char* chPtr, size_t size,
                                                     void* data)
 {
-  cmCTestSubmitHandlerVectorOfChar* vec =
-    static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
-  vec->insert(vec->end(), chPtr, chPtr + size);
-
+  cmAppend(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr,
+           chPtr + size);
   return size;
 }
 
@@ -769,8 +764,7 @@ int cmCTestSubmitHandler::ProcessHandler()
 
   if (!this->Files.empty()) {
     // Submit the explicitly selected files:
-    //
-    files.insert(files.end(), this->Files.begin(), this->Files.end());
+    cmAppend(files, this->Files);
   }
 
   // Add to the list of files to submit from any selected, existing parts:
@@ -816,8 +810,7 @@ int cmCTestSubmitHandler::ProcessHandler()
     }
 
     // Submit files from this part.
-    std::vector<std::string> const& pfiles = this->CTest->GetSubmitFiles(p);
-    files.insert(files.end(), pfiles.begin(), pfiles.end());
+    cmAppend(files, this->CTest->GetSubmitFiles(p));
   }
 
   // Make sure files are unique, but preserve order.
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index a2c30bb..7a3b82e 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmProcess.h"
 
+#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestRunTest.h"
 #include "cmCTestTestHandler.h"
@@ -215,7 +216,7 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf)
   if (nread > 0) {
     std::string strdata;
     this->Conv.DecodeText(buf->base, static_cast<size_t>(nread), strdata);
-    this->Output.insert(this->Output.end(), strdata.begin(), strdata.end());
+    cmAppend(this->Output, strdata);
 
     while (this->Output.GetLine(line)) {
       this->Runner.CheckOutput(line);
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index adf4464..ad12e89 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -4,6 +4,7 @@
 
 #include <sstream>
 
+#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
@@ -338,7 +339,7 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
     return true;
   }
 
-  srclists.insert(srclists.end(), s, args.end());
+  cmAppend(srclists, s, args.end());
 
   this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);
 
diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx
index 3a3afdb..bf28702 100644
--- a/Source/cmAddTestCommand.cxx
+++ b/Source/cmAddTestCommand.cxx
@@ -27,8 +27,7 @@ bool cmAddTestCommand::InitialPass(std::vector<std::string> const& args,
   }
 
   // Collect the command with arguments.
-  std::vector<std::string> command;
-  command.insert(command.end(), args.begin() + 1, args.end());
+  std::vector<std::string> command(args.begin() + 1, args.end());
 
   // Create the test but add a generator only the first time it is
   // seen.  This preserves behavior from before test generators.
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 003ebdc..071ff56 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -1282,7 +1282,7 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
   while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
     processOutput.DecodeText(data, length, strdata);
     if (output) {
-      tempOutput.insert(tempOutput.end(), data, data + length);
+      cmAppend(tempOutput, data, data + length);
     }
     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
                cmCTestLogWrite(strdata.c_str(), strdata.size()));
@@ -2194,8 +2194,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
   bool SRArgumentSpecified = false;
 
   // copy the command line
-  this->Impl->InitialCommandLineArguments.insert(
-    this->Impl->InitialCommandLineArguments.end(), args.begin(), args.end());
+  cmAppend(this->Impl->InitialCommandLineArguments, args);
 
   // process the command line arguments
   for (size_t i = 1; i < args.size(); ++i) {
@@ -2958,10 +2957,10 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args,
     res = cmsysProcess_WaitForData(cp, &data, &length, nullptr);
     switch (res) {
       case cmsysProcess_Pipe_STDOUT:
-        tempOutput.insert(tempOutput.end(), data, data + length);
+        cmAppend(tempOutput, data, data + length);
         break;
       case cmsysProcess_Pipe_STDERR:
-        tempError.insert(tempError.end(), data, data + length);
+        cmAppend(tempError, data, data + length);
         break;
       default:
         done = true;
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 303b147..e7e91c1 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -94,10 +94,7 @@ bool cmConditionEvaluator::IsTrue(
   }
 
   // store the reduced args in this vector
-  cmArgumentList newArgs;
-
-  // copy to the list structure
-  newArgs.insert(newArgs.end(), args.begin(), args.end());
+  cmArgumentList newArgs(args.begin(), args.end());
 
   // now loop through the arguments and see if we can reduce any of them
   // we do this multiple times. Once for each level of precedence
@@ -398,7 +395,7 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,
         // copy to the list structure
         cmArgumentList::iterator argP1 = arg;
         argP1++;
-        newArgs2.insert(newArgs2.end(), argP1, argClose);
+        cmAppend(newArgs2, argP1, argClose);
         newArgs2.pop_back();
         // now recursively invoke IsTrue to handle the values inside the
         // parenthetical expression
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index ad8c9b9..7402eeb 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCustomCommand.h"
 
+#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 
 #include <utility>
@@ -54,13 +55,12 @@ const char* cmCustomCommand::GetComment() const
 
 void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines)
 {
-  this->CommandLines.insert(this->CommandLines.end(), commandLines.begin(),
-                            commandLines.end());
+  cmAppend(this->CommandLines, commandLines);
 }
 
 void cmCustomCommand::AppendDepends(const std::vector<std::string>& depends)
 {
-  this->Depends.insert(this->Depends.end(), depends.begin(), depends.end());
+  cmAppend(this->Depends, depends);
 }
 
 bool cmCustomCommand::GetEscapeOldStyle() const
@@ -101,8 +101,7 @@ void cmCustomCommand::SetImplicitDepends(ImplicitDependsList const& l)
 
 void cmCustomCommand::AppendImplicitDepends(ImplicitDependsList const& l)
 {
-  this->ImplicitDepends.insert(this->ImplicitDepends.end(), l.begin(),
-                               l.end());
+  cmAppend(this->ImplicitDepends, l);
 }
 
 bool cmCustomCommand::GetUsesTerminal() const
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 6bf9946..e58fc76 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCustomCommandGenerator.h"
 
+#include "cmAlgorithms.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandLines.h"
 #include "cmGeneratorExpression.h"
@@ -33,9 +34,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
         this->GE->Parse(clarg);
       std::string parsed_arg = cge->Evaluate(this->LG, this->Config);
       if (this->CC.GetCommandExpandLists()) {
-        std::vector<std::string> ExpandedArg;
-        cmSystemTools::ExpandListArgument(parsed_arg, ExpandedArg);
-        argv.insert(argv.end(), ExpandedArg.begin(), ExpandedArg.end());
+        cmAppend(argv, cmSystemTools::ExpandedListArgument(parsed_arg));
       } else {
         argv.push_back(std::move(parsed_arg));
       }
@@ -54,15 +53,14 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
   std::vector<std::string> depends = this->CC.GetDepends();
   for (std::string const& d : depends) {
     std::unique_ptr<cmCompiledGeneratorExpression> cge = this->GE->Parse(d);
-    std::vector<std::string> result;
-    cmSystemTools::ExpandListArgument(cge->Evaluate(this->LG, this->Config),
-                                      result);
+    std::vector<std::string> result = cmSystemTools::ExpandedListArgument(
+      cge->Evaluate(this->LG, this->Config));
     for (std::string& it : result) {
       if (cmSystemTools::FileIsFullPath(it)) {
         it = cmSystemTools::CollapseFullPath(it);
       }
     }
-    this->Depends.insert(this->Depends.end(), result.begin(), result.end());
+    cmAppend(this->Depends, result);
   }
 
   const std::string& workingdirectory = this->CC.GetWorkingDirectory();
diff --git a/Source/cmDocumentationSection.h b/Source/cmDocumentationSection.h
index 7031b52..19c7407 100644
--- a/Source/cmDocumentationSection.h
+++ b/Source/cmDocumentationSection.h
@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cmAlgorithms.h"
 #include "cmDocumentationEntry.h"
 
 #include <string>
@@ -46,7 +47,7 @@ public:
   }
   void Append(const std::vector<cmDocumentationEntry>& entries)
   {
-    this->Entries.insert(this->Entries.end(), entries.begin(), entries.end());
+    cmAppend(this->Entries, entries);
   }
 
   /** Append an entry to this section using NULL terminated chars */
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index 27f9131..2226463 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmELF.h"
 
+#include "cmAlgorithms.h"
 #include "cm_kwiml.h"
 #include "cmsys/FStream.hxx"
 #include <map>
@@ -572,7 +573,7 @@ std::vector<char> cmELFInternalImpl<Types>::EncodeDynamicEntries(
     }
 
     char* pdyn = reinterpret_cast<char*>(&dyn);
-    result.insert(result.end(), pdyn, pdyn + sizeof(ELF_Dyn));
+    cmAppend(result, pdyn, pdyn + sizeof(ELF_Dyn));
   }
 
   return result;
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 0d9859e..494afbb 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -393,5 +393,5 @@ void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data,
     --length;
   }
 #endif
-  output.insert(output.end(), data, data + length);
+  cmAppend(output, data, data + length);
 }
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index ada2709..0a1e755 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cmAlgorithms.h"
 #include "cmExportFileGenerator.h"
 #include "cmStateTypes.h"
 
@@ -39,7 +40,7 @@ public:
   void GetTargets(std::vector<std::string>& targets) const;
   void AppendTargets(std::vector<std::string> const& targets)
   {
-    this->Targets.insert(this->Targets.end(), targets.begin(), targets.end());
+    cmAppend(this->Targets, targets);
   }
   void SetExportSet(cmExportSet*);
 
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index c6e44e3..f47744b 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -209,9 +209,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
     // Collect all files
     std::vector<std::string> listFiles;
     for (cmLocalGenerator* lg : it.second) {
-      const std::vector<std::string>& files =
-        lg->GetMakefile()->GetListFiles();
-      listFiles.insert(listFiles.end(), files.begin(), files.end());
+      cmAppend(listFiles, lg->GetMakefile()->GetListFiles());
     }
 
     // Convert
@@ -563,27 +561,24 @@ void cmExtraCodeBlocksGenerator::AppendTarget(
 
     // the include directories for this target
     std::vector<std::string> allIncludeDirs;
-
-    std::vector<std::string> includes;
-    lg->GetIncludeDirectories(includes, target, "C", buildType);
-
-    allIncludeDirs.insert(allIncludeDirs.end(), includes.begin(),
-                          includes.end());
+    {
+      std::vector<std::string> includes;
+      lg->GetIncludeDirectories(includes, target, "C", buildType);
+      cmAppend(allIncludeDirs, includes);
+    }
 
     std::string systemIncludeDirs = makefile->GetSafeDefinition(
       "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
     if (!systemIncludeDirs.empty()) {
-      std::vector<std::string> dirs;
-      cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
-      allIncludeDirs.insert(allIncludeDirs.end(), dirs.begin(), dirs.end());
+      cmAppend(allIncludeDirs,
+               cmSystemTools::ExpandedListArgument(systemIncludeDirs));
     }
 
     systemIncludeDirs = makefile->GetSafeDefinition(
       "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
     if (!systemIncludeDirs.empty()) {
-      std::vector<std::string> dirs;
-      cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
-      allIncludeDirs.insert(allIncludeDirs.end(), dirs.begin(), dirs.end());
+      cmAppend(allIncludeDirs,
+               cmSystemTools::ExpandedListArgument(systemIncludeDirs));
     }
 
     std::vector<std::string>::const_iterator end =
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 45e8303..0fb166a 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFileAPICodemodel.h"
 
+#include "cmAlgorithms.h"
 #include "cmCryptoHash.h"
 #include "cmFileAPI.h"
 #include "cmGeneratorExpression.h"
@@ -477,8 +478,7 @@ Json::Value CodemodelConfig::DumpTargets()
   cmGlobalGenerator* gg =
     this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
   for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) {
-    std::vector<cmGeneratorTarget*> const& list = lg->GetGeneratorTargets();
-    targetList.insert(targetList.end(), list.begin(), list.end());
+    cmAppend(targetList, lg->GetGeneratorTargets());
   }
   std::sort(targetList.begin(), targetList.end(),
             [](cmGeneratorTarget* l, cmGeneratorTarget* r) {
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index c0e263a..7a3954e 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -890,7 +890,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
       }
 
       std::vector<std::string>& foundFiles = g.GetFiles();
-      files.insert(files.end(), foundFiles.begin(), foundFiles.end());
+      cmAppend(files, foundFiles);
 
       if (configureDepends) {
         std::sort(foundFiles.begin(), foundFiles.end());
@@ -1476,23 +1476,22 @@ size_t cmWriteToMemoryCallback(void* ptr, size_t size, size_t nmemb,
                                void* data)
 {
   int realsize = static_cast<int>(size * nmemb);
-  cmFileCommandVectorOfChar* vec =
-    static_cast<cmFileCommandVectorOfChar*>(data);
   const char* chPtr = static_cast<char*>(ptr);
-  vec->insert(vec->end(), chPtr, chPtr + realsize);
+  cmAppend(*static_cast<cmFileCommandVectorOfChar*>(data), chPtr,
+           chPtr + realsize);
   return realsize;
 }
 
 size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr,
                                       size_t size, void* data)
 {
-  cmFileCommandVectorOfChar* vec =
-    static_cast<cmFileCommandVectorOfChar*>(data);
+  cmFileCommandVectorOfChar& vec =
+    *static_cast<cmFileCommandVectorOfChar*>(data);
   switch (type) {
     case CURLINFO_TEXT:
     case CURLINFO_HEADER_IN:
     case CURLINFO_HEADER_OUT:
-      vec->insert(vec->end(), chPtr, chPtr + size);
+      cmAppend(vec, chPtr, chPtr + size);
       break;
     case CURLINFO_DATA_IN:
     case CURLINFO_DATA_OUT:
@@ -1502,7 +1501,7 @@ size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr,
       int n = sprintf(buf, "[%" KWIML_INT_PRIu64 " bytes data]\n",
                       static_cast<KWIML_INT_uint64_t>(size));
       if (n > 0) {
-        vec->insert(vec->end(), buf, buf + n);
+        cmAppend(vec, buf, buf + n);
       }
     } break;
     default:
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 2e5e29c..e590802 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -146,8 +146,7 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
     std::vector<std::string> shortArgs = this->Names;
     this->Names.clear(); // clear out any values in Names
     this->Names.push_back(shortArgs[0]);
-    this->UserGuessArgs.insert(this->UserGuessArgs.end(),
-                               shortArgs.begin() + 1, shortArgs.end());
+    cmAppend(this->UserGuessArgs, shortArgs.begin() + 1, shortArgs.end());
   }
   this->ExpandPaths();
 
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index 9aaa000..954558f 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -6,6 +6,7 @@
 #include <string.h>
 #include <utility>
 
+#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
 
@@ -221,7 +222,7 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
   // If searching both rooted and unrooted paths add the original
   // paths again.
   if (this->FindRootPathMode == RootPathModeBoth) {
-    paths.insert(paths.end(), unrootedPaths.begin(), unrootedPaths.end());
+    cmAppend(paths, unrootedPaths);
   }
 }
 
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index 9d75b72..9067a5f 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -177,7 +177,7 @@ bool cmFunctionCommand::InitialPass(std::vector<std::string> const& args,
 
   // create a function blocker
   cmFunctionFunctionBlocker* f = new cmFunctionFunctionBlocker();
-  f->Args.insert(f->Args.end(), args.begin(), args.end());
+  cmAppend(f->Args, args);
   this->Makefile->AddFunctionBlocker(f);
   return true;
 }
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index 7aa3314..304378d 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGeneratorExpressionParser.h"
 
+#include "cmAlgorithms.h"
 #include "cmGeneratorExpressionEvaluator.h"
 
 #include <assert.h>
@@ -52,9 +53,9 @@ static void extendResult(
     textContent->Extend(
       static_cast<TextContent*>(contents.front())->GetLength());
     delete contents.front();
-    result.insert(result.end(), contents.begin() + 1, contents.end());
+    cmAppend(result, contents.begin() + 1, contents.end());
   } else {
-    result.insert(result.end(), contents.begin(), contents.end());
+    cmAppend(result, contents);
   }
 }
 
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 88c586a..dcd8c5f 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -67,7 +67,7 @@ struct GeneratedMakeCommand
   void Add(std::vector<std::string>::const_iterator start,
            std::vector<std::string>::const_iterator end)
   {
-    PrimaryCommand.insert(PrimaryCommand.end(), start, end);
+    cmAppend(PrimaryCommand, start, end);
   }
 
   std::string Printable() const { return cmJoin(PrimaryCommand, " "); }
diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx
index 43c9666..ff54288 100644
--- a/Source/cmGlobalJOMMakefileGenerator.cxx
+++ b/Source/cmGlobalJOMMakefileGenerator.cxx
@@ -66,8 +66,7 @@ cmGlobalJOMMakefileGenerator::GenerateBuildCommand(
   // Since we have full control over the invocation of JOM, let us
   // make it quiet.
   jomMakeOptions.push_back(this->MakeSilentFlag);
-  jomMakeOptions.insert(jomMakeOptions.end(), makeOptions.begin(),
-                        makeOptions.end());
+  cmAppend(jomMakeOptions, makeOptions);
 
   // JOM does parallel builds by default, the -j is only needed if a specific
   // number is given
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index a4838bc..2273c00 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -66,8 +66,7 @@ cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
   // Since we have full control over the invocation of nmake, let us
   // make it quiet.
   nmakeMakeOptions.push_back(this->MakeSilentFlag);
-  nmakeMakeOptions.insert(nmakeMakeOptions.end(), makeOptions.begin(),
-                          makeOptions.end());
+  cmAppend(nmakeMakeOptions, makeOptions);
 
   return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
     makeProgram, projectName, projectDir, targetNames, config, fast,
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 5ddaaa3..ea65a77 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -1016,7 +1016,7 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
       this->AppendTargetOutputs(targetDep, outs, depends);
     }
     std::sort(outs.begin(), outs.end());
-    outputs.insert(outputs.end(), outs.begin(), outs.end());
+    cmAppend(outputs, outs);
   }
 }
 
@@ -1025,8 +1025,7 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
 {
   cmNinjaOuts outs;
   this->AppendTargetDependsClosure(target, outs, true);
-
-  outputs.insert(outputs.end(), outs.begin(), outs.end());
+  cmAppend(outputs, outs);
 }
 
 void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 8053f61..aa584ad 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -282,11 +282,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
   // for each cmMakefile get its list of dependencies
   std::vector<std::string> lfiles;
   for (cmLocalGenerator* localGen : this->LocalGenerators) {
-    lg = static_cast<cmLocalUnixMakefileGenerator3*>(localGen);
-
     // Get the list of files contributing to this generation step.
-    lfiles.insert(lfiles.end(), lg->GetMakefile()->GetListFiles().begin(),
-                  lg->GetMakefile()->GetListFiles().end());
+    cmAppend(lfiles, localGen->GetMakefile()->GetListFiles());
   }
 
   cmake* cm = this->GetCMakeInstance();
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 0da9986..85ddc85 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -141,10 +141,8 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
     // Collect the input files used to generate all targets in this
     // project.
     std::vector<std::string> listFiles;
-    for (unsigned int j = 0; j < generators.size(); ++j) {
-      cmMakefile* lmf = generators[j]->GetMakefile();
-      listFiles.insert(listFiles.end(), lmf->GetListFiles().begin(),
-                       lmf->GetListFiles().end());
+    for (cmLocalGenerator* gen : generators) {
+      cmAppend(listFiles, gen->GetMakefile()->GetListFiles());
     }
 
     // Add a custom prebuild target to run the VerifyGlobs script.
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index f2eb0ce..7c2bcd3 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -583,8 +583,7 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
 {
   std::vector<std::string> lfiles;
   for (auto gen : gens) {
-    std::vector<std::string> const& lf = gen->GetMakefile()->GetListFiles();
-    lfiles.insert(lfiles.end(), lf.begin(), lf.end());
+    cmAppend(lfiles, gen->GetMakefile()->GetListFiles());
   }
 
   // sort the array
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index ea67d45..7b992d7 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -6,6 +6,7 @@
 #include <iterator>
 #include <string.h>
 
+#include "cmAlgorithms.h"
 #include "cmIDEFlagTable.h"
 #include "cmSystemTools.h"
 
@@ -170,7 +171,7 @@ void cmIDEOptions::AddDefines(std::string const& defines)
 }
 void cmIDEOptions::AddDefines(const std::vector<std::string>& defines)
 {
-  this->Defines.insert(this->Defines.end(), defines.begin(), defines.end());
+  cmAppend(this->Defines, defines);
 }
 
 std::vector<std::string> const& cmIDEOptions::GetDefines() const
@@ -192,8 +193,7 @@ void cmIDEOptions::AddIncludes(std::string const& includes)
 }
 void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes)
 {
-  this->Includes.insert(this->Includes.end(), includes.begin(),
-                        includes.end());
+  cmAppend(this->Includes, includes);
 }
 
 std::vector<std::string> const& cmIDEOptions::GetIncludes() const
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index 549a263..62e2abd 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -6,6 +6,7 @@
 #include <set>
 #include <utility>
 
+#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
@@ -52,11 +53,9 @@ bool cmIncludeDirectoryCommand::InitialPass(
     this->GetIncludes(*i, includes);
 
     if (before) {
-      beforeIncludes.insert(beforeIncludes.end(), includes.begin(),
-                            includes.end());
+      cmAppend(beforeIncludes, includes);
     } else {
-      afterIncludes.insert(afterIncludes.end(), includes.begin(),
-                           includes.end());
+      cmAppend(afterIncludes, includes);
     }
     if (system) {
       systemIncludes.insert(includes.begin(), includes.end());
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index b068e46..efbcb67 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallFilesCommand.h"
 
+#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmGlobalGenerator.h"
 #include "cmInstallFilesGenerator.h"
@@ -35,8 +36,7 @@ bool cmInstallFilesCommand::InitialPass(std::vector<std::string> const& args,
     this->CreateInstallGenerator();
   } else {
     this->IsFilesForm = false;
-    this->FinalArgs.insert(this->FinalArgs.end(), args.begin() + 1,
-                           args.end());
+    cmAppend(this->FinalArgs, args.begin() + 1, args.end());
   }
 
   this->Makefile->GetGlobalGenerator()->AddInstallComponent(
diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx
index f01a4c1..a58f875 100644
--- a/Source/cmInstallProgramsCommand.cxx
+++ b/Source/cmInstallProgramsCommand.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallProgramsCommand.h"
 
+#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmGlobalGenerator.h"
 #include "cmInstallFilesGenerator.h"
@@ -25,7 +26,7 @@ bool cmInstallProgramsCommand::InitialPass(
 
   this->Destination = args[0];
 
-  this->FinalArgs.insert(this->FinalArgs.end(), args.begin() + 1, args.end());
+  cmAppend(this->FinalArgs, args.begin() + 1, args.end());
 
   this->Makefile->GetGlobalGenerator()->AddInstallComponent(
     this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx
index d723ced..636a8e1 100644
--- a/Source/cmJsonObjects.cxx
+++ b/Source/cmJsonObjects.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmJsonObjects.h" // IWYU pragma: keep
 
+#include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
@@ -601,8 +602,7 @@ static Json::Value DumpTargetsList(
 
   std::vector<cmGeneratorTarget*> targetList;
   for (auto const& lgIt : generators) {
-    const auto& list = lgIt->GetGeneratorTargets();
-    targetList.insert(targetList.end(), list.begin(), list.end());
+    cmAppend(targetList, lgIt->GetGeneratorTargets());
   }
   std::sort(targetList.begin(), targetList.end());
 
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 047d405..787e98e 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -351,9 +351,8 @@ void cmLocalGenerator::CreateEvaluationFileOutputs(std::string const& config)
 void cmLocalGenerator::ProcessEvaluationFiles(
   std::vector<std::string>& generatedFiles)
 {
-  std::vector<cmGeneratorExpressionEvaluationFile*> ef =
-    this->Makefile->GetEvaluationFiles();
-  for (cmGeneratorExpressionEvaluationFile* geef : ef) {
+  for (cmGeneratorExpressionEvaluationFile* geef :
+       this->Makefile->GetEvaluationFiles()) {
     geef->Generate(this);
     if (cmSystemTools::GetFatalErrorOccured()) {
       return;
@@ -372,10 +371,10 @@ void cmLocalGenerator::ProcessEvaluationFiles(
       return;
     }
 
-    generatedFiles.insert(generatedFiles.end(), files.begin(), files.end());
-    std::vector<std::string>::iterator newIt =
-      generatedFiles.end() - files.size();
-    std::inplace_merge(generatedFiles.begin(), newIt, generatedFiles.end());
+    cmAppend(generatedFiles, files);
+    std::inplace_merge(generatedFiles.begin(),
+                       generatedFiles.end() - files.size(),
+                       generatedFiles.end());
   }
 }
 
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 04e3d12..c392e97 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -862,7 +862,7 @@ void cmLocalUnixMakefileGenerator3::AppendRuleDepends(
   // Add a dependency on the rule file itself unless an option to skip
   // it is specifically enabled by the user or project.
   if (!this->Makefile->IsOn("CMAKE_SKIP_RULE_DEPENDENCY")) {
-    depends.insert(depends.end(), ruleFiles.begin(), ruleFiles.end());
+    cmAppend(depends, ruleFiles);
   }
 }
 
@@ -1037,7 +1037,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
   this->CreateCDCommand(commands1, dir, relative);
 
   // push back the custom commands
-  commands.insert(commands.end(), commands1.begin(), commands1.end());
+  cmAppend(commands, commands1);
 }
 
 void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index 6565f02..e9c6aea 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -212,7 +212,7 @@ bool cmMacroCommand::InitialPass(std::vector<std::string> const& args,
 
   // create a function blocker
   cmMacroFunctionBlocker* f = new cmMacroFunctionBlocker();
-  f->Args.insert(f->Args.end(), args.begin(), args.end());
+  cmAppend(f->Args, args);
   this->Makefile->AddFunctionBlocker(f);
   return true;
 }
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index ca5f009..c601e6a 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2534,8 +2534,7 @@ const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const
 std::vector<std::string> cmMakefile::GetDefinitions() const
 {
   std::vector<std::string> res = this->StateSnapshot.ClosureKeys();
-  std::vector<std::string> cacheKeys = this->GetState()->GetCacheEntryKeys();
-  res.insert(res.end(), cacheKeys.begin(), cacheKeys.end());
+  cmAppend(res, this->GetState()->GetCacheEntryKeys());
   std::sort(res.begin(), res.end());
   return res;
 }
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 571da1a..552463d 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -268,7 +268,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
   this->LocalGenerator->CreateCDCommand(
     commands1, this->Makefile->GetCurrentBinaryDirectory(),
     this->LocalGenerator->GetBinaryDirectory());
-  commands.insert(commands.end(), commands1.begin(), commands1.end());
+  cmAppend(commands, commands1);
   commands1.clear();
 
   // Write the build rule.
@@ -638,7 +638,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   this->LocalGenerator->CreateCDCommand(
     commands1, this->Makefile->GetCurrentBinaryDirectory(),
     this->LocalGenerator->GetBinaryDirectory());
-  commands.insert(commands.end(), commands1.begin(), commands1.end());
+  cmAppend(commands, commands1);
   commands1.clear();
 
   // Add a rule to create necessary symlinks for the library.
@@ -651,7 +651,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     this->LocalGenerator->CreateCDCommand(
       commands1, this->Makefile->GetCurrentBinaryDirectory(),
       this->LocalGenerator->GetBinaryDirectory());
-    commands.insert(commands.end(), commands1.begin(), commands1.end());
+    cmAppend(commands, commands1);
     commands1.clear();
   }
 
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index d4d565d..99f0df8 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -399,7 +399,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
   this->LocalGenerator->CreateCDCommand(
     commands1, this->Makefile->GetCurrentBinaryDirectory(),
     this->LocalGenerator->GetBinaryDirectory());
-  commands.insert(commands.end(), commands1.begin(), commands1.end());
+  cmAppend(commands, commands1);
   commands1.clear();
 
   // Compute the list of outputs.
@@ -575,7 +575,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     this->LocalGenerator->CreateCDCommand(
       commands1, this->Makefile->GetCurrentBinaryDirectory(),
       this->LocalGenerator->GetBinaryDirectory());
-    commands.insert(commands.end(), commands1.begin(), commands1.end());
+    cmAppend(commands, commands1);
     commands1.clear();
   }
 
@@ -915,7 +915,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
   this->LocalGenerator->CreateCDCommand(
     commands1, this->Makefile->GetCurrentBinaryDirectory(),
     this->LocalGenerator->GetBinaryDirectory());
-  commands.insert(commands.end(), commands1.begin(), commands1.end());
+  cmAppend(commands, commands1);
   commands1.clear();
 
   // Add a rule to create necessary symlinks for the library.
@@ -932,7 +932,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     this->LocalGenerator->CreateCDCommand(
       commands1, this->Makefile->GetCurrentBinaryDirectory(),
       this->LocalGenerator->GetBinaryDirectory());
-    commands.insert(commands.end(), commands1.begin(), commands1.end());
+    cmAppend(commands, commands1);
     commands1.clear();
   }
 
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index d326ec5..b3bab4b 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -219,14 +219,9 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
     std::vector<cmCustomCommand> buildEventCommands =
       this->GeneratorTarget->GetPreBuildCommands();
 
-    buildEventCommands.insert(
-      buildEventCommands.end(),
-      this->GeneratorTarget->GetPreLinkCommands().begin(),
-      this->GeneratorTarget->GetPreLinkCommands().end());
-    buildEventCommands.insert(
-      buildEventCommands.end(),
-      this->GeneratorTarget->GetPostBuildCommands().begin(),
-      this->GeneratorTarget->GetPostBuildCommands().end());
+    cmAppend(buildEventCommands, this->GeneratorTarget->GetPreLinkCommands());
+    cmAppend(buildEventCommands,
+             this->GeneratorTarget->GetPostBuildCommands());
 
     for (const auto& be : buildEventCommands) {
       const std::vector<std::string>& byproducts = be.GetByproducts();
@@ -819,8 +814,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
     this->LocalGenerator->CreateCDCommand(
       compileCommands, this->LocalGenerator->GetCurrentBinaryDirectory(),
       this->LocalGenerator->GetBinaryDirectory());
-    commands.insert(commands.end(), compileCommands.begin(),
-                    compileCommands.end());
+    cmAppend(commands, compileCommands);
   }
 
   // Check for extra outputs created by the compilation.
@@ -882,8 +876,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
           preprocessCommands,
           this->LocalGenerator->GetCurrentBinaryDirectory(),
           this->LocalGenerator->GetBinaryDirectory());
-        commands.insert(commands.end(), preprocessCommands.begin(),
-                        preprocessCommands.end());
+        cmAppend(commands, preprocessCommands);
       } else {
         std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
         cmd += preprocessRuleVar;
@@ -929,8 +922,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
         this->LocalGenerator->CreateCDCommand(
           assemblyCommands, this->LocalGenerator->GetCurrentBinaryDirectory(),
           this->LocalGenerator->GetBinaryDirectory());
-        commands.insert(commands.end(), assemblyCommands.begin(),
-                        assemblyCommands.end());
+        cmAppend(commands, assemblyCommands);
       } else {
         std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
         cmd += assemblyRuleVar;
@@ -1177,8 +1169,7 @@ void cmMakefileTargetGenerator::DriveCustomCommands(
     if (cmCustomCommand* cc = source->GetCustomCommand()) {
       cmCustomCommandGenerator ccg(*cc, this->ConfigName,
                                    this->LocalGenerator);
-      const std::vector<std::string>& outputs = ccg.GetOutputs();
-      depends.insert(depends.end(), outputs.begin(), outputs.end());
+      cmAppend(depends, ccg.GetOutputs());
     }
   }
 }
@@ -1402,8 +1393,7 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule(
     }
 
     // Make sure the extra files are built.
-    depends.insert(depends.end(), this->ExtraFiles.begin(),
-                   this->ExtraFiles.end());
+    cmAppend(depends, this->ExtraFiles);
   }
 
   // Write the driver rule.
@@ -1425,8 +1415,7 @@ void cmMakefileTargetGenerator::AppendTargetDepends(
   const std::string& cfg = this->LocalGenerator->GetConfigName();
   if (cmComputeLinkInformation* cli =
         this->GeneratorTarget->GetLinkInformation(cfg)) {
-    std::vector<std::string> const& libDeps = cli->GetDepends();
-    depends.insert(depends.end(), libDeps.begin(), libDeps.end());
+    cmAppend(depends, cli->GetDepends());
   }
 }
 
@@ -1443,8 +1432,7 @@ void cmMakefileTargetGenerator::AppendObjectDepends(
   }
 
   // Add dependencies on the external object files.
-  depends.insert(depends.end(), this->ExternalObjects.begin(),
-                 this->ExternalObjects.end());
+  cmAppend(depends, this->ExternalObjects);
 
   // Add a dependency on the rule file itself.
   this->LocalGenerator->AppendRuleDepend(depends,
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index e6a13bb..9652a51 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -841,8 +841,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
     this->GeneratorTarget, orderOnlyDeps, DependOnTargetOrdering);
 
   // Add order-only dependencies on other files associated with the target.
-  orderOnlyDeps.insert(orderOnlyDeps.end(), this->ExtraFiles.begin(),
-                       this->ExtraFiles.end());
+  cmAppend(orderOnlyDeps, this->ExtraFiles);
 
   // Add order-only dependencies on custom command outputs.
   for (cmCustomCommand const* cc : this->CustomCommands) {
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index 2c28fc0..585db42 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -329,15 +329,13 @@ void cmOrderDirectories::AddLinkLibrary(std::string const& fullPath)
 void cmOrderDirectories::AddUserDirectories(
   std::vector<std::string> const& extra)
 {
-  this->UserDirectories.insert(this->UserDirectories.end(), extra.begin(),
-                               extra.end());
+  cmAppend(this->UserDirectories, extra);
 }
 
 void cmOrderDirectories::AddLanguageDirectories(
   std::vector<std::string> const& dirs)
 {
-  this->LanguageDirectories.insert(this->LanguageDirectories.end(),
-                                   dirs.begin(), dirs.end());
+  cmAppend(this->LanguageDirectories, dirs);
 }
 
 void cmOrderDirectories::SetImplicitDirectories(
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index a245b54..3683edd 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -68,7 +68,7 @@ void MergeOptions(std::vector<std::string>& baseOpts,
     }
   }
   // Append options
-  baseOpts.insert(baseOpts.end(), extraOpts.begin(), extraOpts.end());
+  cmAppend(baseOpts, extraOpts);
 }
 
 // - Class definitions
@@ -347,8 +347,7 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile,
     {
       std::vector<std::string> cmd;
       cmd.emplace_back(this->RccExcutable_);
-      cmd.insert(cmd.end(), this->ListOptions_.begin(),
-                 this->ListOptions_.end());
+      cmAppend(cmd, this->ListOptions_);
       cmd.emplace_back(cmSystemTools::GetFilenameName(qrcFile));
 
       // Log command
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 36794d6..dbabba0 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -293,11 +293,10 @@ void cmQtAutoMocUic::JobMocPredefsT::Process()
       // Compose command
       std::vector<std::string> cmd = MocConst().PredefsCmd;
       // Add includes
-      cmd.insert(cmd.end(), MocConst().Includes.begin(),
-                 MocConst().Includes.end());
+      cmAppend(cmd, MocConst().Includes);
       // Add definitions
       for (std::string const& def : MocConst().Definitions) {
-        cmd.push_back("-D" + def);
+        cmd.emplace_back("-D" + def);
       }
       // Execute command
       if (!RunProcess(GenT::MOC, result, cmd, reason.get())) {
@@ -1398,8 +1397,7 @@ void cmQtAutoMocUic::JobMocT::Process()
   std::vector<std::string> cmd;
   cmd.push_back(MocConst().Executable);
   // Add options
-  cmd.insert(cmd.end(), MocConst().AllOptions.begin(),
-             MocConst().AllOptions.end());
+  cmAppend(cmd, MocConst().AllOptions);
   // Add predefs include
   if (!MocConst().PredefsFileAbs.empty()) {
     cmd.emplace_back("--include");
@@ -1452,7 +1450,7 @@ void cmQtAutoMocUic::JobUicT::Process()
       UicMergeOptions(allOpts, optionIt->second,
                       (BaseConst().QtVersionMajor == 5));
     }
-    cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
+    cmAppend(cmd, allOpts);
   }
   cmd.emplace_back("-o");
   cmd.emplace_back(outputFile);
@@ -1881,9 +1879,8 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
     // Sort include directories on demand
     if (BaseConst().IncludeProjectDirsBefore) {
       // Move strings to temporary list
-      std::list<std::string> includes;
-      includes.insert(includes.end(), MocConst().IncludePaths.begin(),
-                      MocConst().IncludePaths.end());
+      std::list<std::string> includes(MocConst().IncludePaths.begin(),
+                                      MocConst().IncludePaths.end());
       MocConst_.IncludePaths.clear();
       MocConst_.IncludePaths.reserve(includes.size());
       // Append project directories only
diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
index 7ac7339..20885df 100644
--- a/Source/cmQtAutoRcc.cxx
+++ b/Source/cmQtAutoRcc.cxx
@@ -431,7 +431,7 @@ bool cmQtAutoRcc::GenerateRcc()
   // Compose rcc command
   std::vector<std::string> cmd;
   cmd.push_back(RccExecutable_);
-  cmd.insert(cmd.end(), Options_.begin(), Options_.end());
+  cmAppend(cmd, Options_);
   cmd.emplace_back("-o");
   cmd.push_back(RccFileOutput_);
   cmd.push_back(QrcFile_);
diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx
index 6425913..1dc7e69 100644
--- a/Source/cmSetTargetPropertiesCommand.cxx
+++ b/Source/cmSetTargetPropertiesCommand.cxx
@@ -4,6 +4,7 @@
 
 #include <iterator>
 
+#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmTarget.h"
 
@@ -30,7 +31,7 @@ bool cmSetTargetPropertiesCommand::InitialPass(
         this->SetError("called with incorrect number of arguments.");
         return false;
       }
-      propertyPairs.insert(propertyPairs.end(), j, args.end());
+      cmAppend(propertyPairs, j, args.end());
       break;
     }
     numFiles++;
diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx
index e27c675..cc9587c 100644
--- a/Source/cmSetTestsPropertiesCommand.cxx
+++ b/Source/cmSetTestsPropertiesCommand.cxx
@@ -4,6 +4,7 @@
 
 #include <iterator>
 
+#include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmTest.h"
 
@@ -30,7 +31,7 @@ bool cmSetTestsPropertiesCommand::InitialPass(
         this->SetError("called with incorrect number of arguments.");
         return false;
       }
-      propertyPairs.insert(propertyPairs.end(), j, args.end());
+      cmAppend(propertyPairs, j, args.end());
       break;
     }
     numFiles++;
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index 31273cc..182d3fe 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -621,9 +621,7 @@ const char* cmStateDirectory::GetProperty(const std::string& prop,
   }
   if (prop == "VARIABLES") {
     std::vector<std::string> res = this->Snapshot_.ClosureKeys();
-    std::vector<std::string> cacheKeys =
-      this->Snapshot_.State->GetCacheEntryKeys();
-    res.insert(res.end(), cacheKeys.begin(), cacheKeys.end());
+    cmAppend(res, this->Snapshot_.State->GetCacheEntryKeys());
     std::sort(res.begin(), res.end());
     output = cmJoin(res, ";");
     return output.c_str();
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 6359d60..612284a 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -501,7 +501,7 @@ std::vector<std::string> cmSystemTools::HandleResponseFile(
 #else
         cmSystemTools::ParseUnixCommandLine(line.c_str(), args2);
 #endif
-        arg_full.insert(arg_full.end(), args2.begin(), args2.end());
+        cmAppend(arg_full, args2);
       }
     } else {
       arg_full.push_back(arg);
@@ -726,7 +726,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
           cmSystemTools::Stdout(strdata);
         }
         if (captureStdOut) {
-          tempStdOut.insert(tempStdOut.end(), data, data + length);
+          cmAppend(tempStdOut, data, data + length);
         }
       } else if (pipe == cmsysProcess_Pipe_STDERR) {
         if (outputflag != OUTPUT_NONE) {
@@ -734,7 +734,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
           cmSystemTools::Stderr(strdata);
         }
         if (captureStdErr) {
-          tempStdErr.insert(tempStdErr.end(), data, data + length);
+          cmAppend(tempStdErr, data, data + length);
         }
       }
     }
@@ -1917,26 +1917,26 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
       processOutput.DecodeText(data, length, strdata, 1);
       // Append to the stdout buffer.
       std::vector<char>::size_type size = out.size();
-      out.insert(out.end(), strdata.begin(), strdata.end());
+      cmAppend(out, strdata);
       outiter = out.begin() + size;
     } else if (pipe == cmsysProcess_Pipe_STDERR) {
       processOutput.DecodeText(data, length, strdata, 2);
       // Append to the stderr buffer.
       std::vector<char>::size_type size = err.size();
-      err.insert(err.end(), strdata.begin(), strdata.end());
+      cmAppend(err, strdata);
       erriter = err.begin() + size;
     } else if (pipe == cmsysProcess_Pipe_None) {
       // Both stdout and stderr pipes have broken.  Return leftover data.
       processOutput.DecodeText(std::string(), strdata, 1);
       if (!strdata.empty()) {
         std::vector<char>::size_type size = out.size();
-        out.insert(out.end(), strdata.begin(), strdata.end());
+        cmAppend(out, strdata);
         outiter = out.begin() + size;
       }
       processOutput.DecodeText(std::string(), strdata, 2);
       if (!strdata.empty()) {
         std::vector<char>::size_type size = err.size();
-        err.insert(err.end(), strdata.begin(), strdata.end());
+        cmAppend(err, strdata);
         erriter = err.begin() + size;
       }
       if (!out.empty()) {
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 8b41e28..cd67586 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -34,13 +34,6 @@
 #include "cmTargetPropertyComputer.h"
 #include "cmake.h"
 
-//! Append all elements from the second container to the first container
-template <class C, class R>
-static inline void CApp(C& container, R const& range)
-{
-  container.insert(container.end(), range.begin(), range.end());
-}
-
 template <>
 const char* cmTargetPropertyComputer::ComputeLocationForBuild<cmTarget>(
   cmTarget const* tgt)
@@ -406,29 +399,30 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
   if (!this->IsImported()) {
     // Initialize the INCLUDE_DIRECTORIES property based on the current value
     // of the same directory property:
-    CApp(impl->IncludeDirectoriesEntries,
-         impl->Makefile->GetIncludeDirectoriesEntries());
-    CApp(impl->IncludeDirectoriesBacktraces,
-         impl->Makefile->GetIncludeDirectoriesBacktraces());
+    cmAppend(impl->IncludeDirectoriesEntries,
+             impl->Makefile->GetIncludeDirectoriesEntries());
+    cmAppend(impl->IncludeDirectoriesBacktraces,
+             impl->Makefile->GetIncludeDirectoriesBacktraces());
 
     {
       auto const& sysInc = impl->Makefile->GetSystemIncludeDirectories();
       impl->SystemIncludeDirectories.insert(sysInc.begin(), sysInc.end());
     }
 
-    CApp(impl->CompileOptionsEntries,
-         impl->Makefile->GetCompileOptionsEntries());
-    CApp(impl->CompileOptionsBacktraces,
-         impl->Makefile->GetCompileOptionsBacktraces());
+    cmAppend(impl->CompileOptionsEntries,
+             impl->Makefile->GetCompileOptionsEntries());
+    cmAppend(impl->CompileOptionsBacktraces,
+             impl->Makefile->GetCompileOptionsBacktraces());
 
-    CApp(impl->LinkOptionsEntries, impl->Makefile->GetLinkOptionsEntries());
-    CApp(impl->LinkOptionsBacktraces,
-         impl->Makefile->GetLinkOptionsBacktraces());
+    cmAppend(impl->LinkOptionsEntries,
+             impl->Makefile->GetLinkOptionsEntries());
+    cmAppend(impl->LinkOptionsBacktraces,
+             impl->Makefile->GetLinkOptionsBacktraces());
 
-    CApp(impl->LinkDirectoriesEntries,
-         impl->Makefile->GetLinkDirectoriesEntries());
-    CApp(impl->LinkDirectoriesBacktraces,
-         impl->Makefile->GetLinkDirectoriesBacktraces());
+    cmAppend(impl->LinkDirectoriesEntries,
+             impl->Makefile->GetLinkDirectoriesEntries());
+    cmAppend(impl->LinkDirectoriesBacktraces,
+             impl->Makefile->GetLinkDirectoriesBacktraces());
   }
 
   if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 0762ae1..f0b53f4 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1045,10 +1045,7 @@ void cmake::GetRegisteredGenerators(std::vector<GeneratorInfo>& generators,
     std::vector<std::string> names = gen->GetGeneratorNames();
 
     if (includeNamesWithPlatform) {
-      std::vector<std::string> namesWithPlatform =
-        gen->GetGeneratorNamesWithPlatform();
-      names.insert(names.end(), namesWithPlatform.begin(),
-                   namesWithPlatform.end());
+      cmAppend(names, gen->GetGeneratorNamesWithPlatform());
     }
 
     for (std::string const& name : names) {
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index e639c66..64026ca 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -122,7 +122,7 @@ static int do_command(int ac, char const* const* av)
   std::vector<std::string> args;
   args.reserve(ac - 1);
   args.emplace_back(av[0]);
-  args.insert(args.end(), av + 2, av + ac);
+  cmAppend(args, av + 2, av + ac);
   return cmcmd::ExecuteCMakeCommand(args);
 }
 
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 3c75957..ad34107 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -173,7 +173,7 @@ static int HandleIWYU(const std::string& runCmd,
   // and adding all the arguments we give to the compiler.
   std::vector<std::string> iwyu_cmd;
   cmSystemTools::ExpandListArgument(runCmd, iwyu_cmd, true);
-  iwyu_cmd.insert(iwyu_cmd.end(), orig_cmd.begin() + 1, orig_cmd.end());
+  cmAppend(iwyu_cmd, orig_cmd.begin() + 1, orig_cmd.end());
   // Run the iwyu command line.  Capture its stderr and hide its stdout.
   // Ignore its return code because the tool always returns non-zero.
   std::string stdErr;
@@ -201,11 +201,11 @@ static int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
   // automatically skip over the compiler itself and extract the
   // options.
   int ret;
-  std::vector<std::string> tidy_cmd;
-  cmSystemTools::ExpandListArgument(runCmd, tidy_cmd, true);
+  std::vector<std::string> tidy_cmd =
+    cmSystemTools::ExpandedListArgument(runCmd, true);
   tidy_cmd.push_back(sourceFile);
   tidy_cmd.emplace_back("--");
-  tidy_cmd.insert(tidy_cmd.end(), orig_cmd.begin(), orig_cmd.end());
+  cmAppend(tidy_cmd, orig_cmd);
 
   // Run the tidy command line.  Capture its stdout and hide its stderr.
   std::string stdOut;
@@ -1919,8 +1919,7 @@ int cmVSLink::RunMT(std::string const& out, bool notify)
   if (this->LinkGeneratesManifest) {
     mtCommand.push_back(this->LinkerManifestFile);
   }
-  mtCommand.insert(mtCommand.end(), this->UserManifests.begin(),
-                   this->UserManifests.end());
+  cmAppend(mtCommand, this->UserManifests);
   mtCommand.push_back(out);
   if (notify) {
     // Add an undocumented option that enables a special return

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=999516478d56d8604d1413fe3c677a860357516c
commit 999516478d56d8604d1413fe3c677a860357516c
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu May 23 14:48:27 2019 +0200
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Thu May 23 15:32:23 2019 +0200

    cmAlgorithms: Add cmAppend function
    
    The new `cmAppend` function simplifies appending ranges of values to a
    `std::vector`.

diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index 0980416..d1e32b0 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -171,6 +171,18 @@ void cmDeleteAll(Range const& r)
                 ContainerAlgorithms::DefaultDeleter<Range>());
 }
 
+template <typename T, typename Range>
+void cmAppend(std::vector<T>& v, Range const& r)
+{
+  v.insert(v.end(), r.begin(), r.end());
+}
+
+template <typename T, typename InputIt>
+void cmAppend(std::vector<T>& v, InputIt first, InputIt last)
+{
+  v.insert(v.end(), first, last);
+}
+
 template <typename Range>
 std::string cmJoin(Range const& r, const char* delimiter)
 {

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=32e4f236b7635fe5008966065ec4099ba23ecf58
commit 32e4f236b7635fe5008966065ec4099ba23ecf58
Author:     Ben Boeckel <ben.boeckel at kitware.com>
AuthorDate: Thu May 23 09:19:59 2019 -0400
Commit:     Ben Boeckel <ben.boeckel at kitware.com>
CommitDate: Thu May 23 09:19:59 2019 -0400

    ARMClang: fix policy manipulation in the compiler module
    
    Policies have their own scoping and cannot be set within a function
    without affecting callers.

diff --git a/Modules/Compiler/ARMClang.cmake b/Modules/Compiler/ARMClang.cmake
index 5ca49df..2518ac7 100644
--- a/Modules/Compiler/ARMClang.cmake
+++ b/Modules/Compiler/ARMClang.cmake
@@ -3,6 +3,9 @@ if(_ARMClang_CMAKE_LOADED)
 endif()
 set(_ARMClang_CMAKE_LOADED TRUE)
 
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
 get_filename_component(_CMAKE_C_TOOLCHAIN_LOCATION "${CMAKE_C_COMPILER}" PATH)
 get_filename_component(_CMAKE_CXX_TOOLCHAIN_LOCATION "${CMAKE_CXX_COMPILER}" PATH)
 
@@ -29,9 +32,6 @@ endfunction()
 # check processor is in list
 function(__armclang_check_processor processor list out_var)
   string(TOLOWER "${processor}" processor)
-  if(POLICY CMP0057)
-    cmake_policy(SET CMP0057 NEW)
-  endif()
   if(processor IN_LIST list)
     set(${out_var} TRUE PARENT_SCOPE)
   else()
@@ -67,3 +67,5 @@ macro(__compiler_armclang lang)
   set(CMAKE_${lang}_OUTPUT_EXTENSION ".o")
   set(CMAKE_${lang}_OUTPUT_EXTENSION_REPLACE 1)
 endmacro()
+
+cmake_policy(POP)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7b4b61a4d38e4c7fe3fe992a6263d8d1f0785858
commit 7b4b61a4d38e4c7fe3fe992a6263d8d1f0785858
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu May 23 12:52:36 2019 +0200
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Thu May 23 13:00:33 2019 +0200

    cmMakefile: Define cmTargetMap type in cmMakefile instead of cmTarget
    
    The `cmTargetMap` type is only used in the context of `cmMakefile`.
    Therefore it is the most appropriate place to declare it.
    
    This moves the `cmTarget.h/cmTargets` type definition to
    `cmMakefile::cmTargetMap`.

diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx
index 0a0646c..b60a053 100644
--- a/Source/cmExportLibraryDependenciesCommand.cxx
+++ b/Source/cmExportLibraryDependenciesCommand.cxx
@@ -76,8 +76,7 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const
   std::map<std::string, std::string> libDepsNew;
   std::map<std::string, std::string> libTypes;
   for (cmMakefile* local : locals) {
-    const cmTargets& tgts = local->GetTargets();
-    for (auto const& tgt : tgts) {
+    for (auto const& tgt : local->GetTargets()) {
       // Get the current target.
       cmTarget const& target = tgt.second;
 
diff --git a/Source/cmInstallTargetsCommand.cxx b/Source/cmInstallTargetsCommand.cxx
index 7e67d4e..ef07e2c 100644
--- a/Source/cmInstallTargetsCommand.cxx
+++ b/Source/cmInstallTargetsCommand.cxx
@@ -23,7 +23,7 @@ bool cmInstallTargetsCommand::InitialPass(std::vector<std::string> const& args,
   // Enable the install target.
   this->Makefile->GetGlobalGenerator()->EnableInstallTarget();
 
-  cmTargets& tgts = this->Makefile->GetTargets();
+  cmMakefile::cmTargetMap& tgts = this->Makefile->GetTargets();
   std::vector<std::string>::const_iterator s = args.begin();
   ++s;
   std::string runtime_dir = "/bin";
@@ -38,7 +38,7 @@ bool cmInstallTargetsCommand::InitialPass(std::vector<std::string> const& args,
 
       runtime_dir = *s;
     } else {
-      cmTargets::iterator ti = tgts.find(*s);
+      cmMakefile::cmTargetMap::iterator ti = tgts.find(*s);
       if (ti != tgts.end()) {
         ti->second.SetInstallPath(args[0]);
         ti->second.SetRuntimeInstallPath(runtime_dir);
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index ca5f009..7d0e318 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -818,7 +818,7 @@ void cmMakefile::AddCustomCommandToTarget(
   bool command_expand_lists, ObjectLibraryCommands objLibraryCommands)
 {
   // Find the target to which to add the custom command.
-  cmTargets::iterator ti = this->Targets.find(target);
+  cmTargetMap::iterator ti = this->Targets.find(target);
 
   if (ti == this->Targets.end()) {
     MessageType messageType = MessageType::AUTHOR_WARNING;
@@ -1099,7 +1099,7 @@ void cmMakefile::AddCustomCommandOldStyle(
     // then add the source to the target to make sure the rule is
     // included.
     if (sf && !sf->GetPropertyAsBool("__CMAKE_RULE")) {
-      cmTargets::iterator ti = this->Targets.find(target);
+      cmTargetMap::iterator ti = this->Targets.find(target);
       if (ti != this->Targets.end()) {
         ti->second.AddSource(sf->GetFullPath());
       } else {
@@ -2036,7 +2036,7 @@ cmTarget* cmMakefile::AddExecutable(const std::string& exeName,
 cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type,
                                    const std::string& name)
 {
-  cmTargets::iterator it =
+  cmTargetMap::iterator it =
     this->Targets
       .emplace(name, cmTarget(name, type, cmTarget::VisibilityNormal, this))
       .first;
@@ -3888,7 +3888,7 @@ std::vector<std::string> cmMakefile::GetPropertyKeys() const
 
 cmTarget* cmMakefile::FindLocalNonAliasTarget(const std::string& name) const
 {
-  cmTargets::iterator i = this->Targets.find(name);
+  cmTargetMap::iterator i = this->Targets.find(name);
   if (i != this->Targets.end()) {
     return &i->second;
   }
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index be1ac5a..d223347 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -373,14 +373,13 @@ public:
     return this->ComplainFileRegularExpression.c_str();
   }
 
-  /**
-   * Get the list of targets
-   */
-  cmTargets& GetTargets() { return this->Targets; }
-  /**
-   * Get the list of targets, const version
-   */
-  const cmTargets& GetTargets() const { return this->Targets; }
+  // -- List of targets
+  typedef std::unordered_map<std::string, cmTarget> cmTargetMap;
+  /** Get the target map */
+  cmTargetMap& GetTargets() { return this->Targets; }
+  /** Get the target map - const version */
+  cmTargetMap const& GetTargets() const { return this->Targets; }
+
   const std::vector<cmTarget*>& GetOwnedImportedTargets() const
   {
     return this->ImportedTargetsOwned;
@@ -896,7 +895,7 @@ protected:
   mutable std::set<cmListFileContext> CMP0054ReportedIds;
 
   // libraries, classes, and executables
-  mutable cmTargets Targets;
+  mutable cmTargetMap Targets;
   std::map<std::string, std::string> AliasTargets;
 
   typedef std::vector<cmSourceFile*> SourceFileVec;
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index 4ed5581..f3276ec 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -111,8 +111,7 @@ public:
     // Now extract any include paths from the targets
     std::set<std::string> uniqueIncludes;
     std::vector<std::string> orderedAndUniqueIncludes;
-    cmTargets& targets = this->Makefile->GetTargets();
-    for (auto const& target : targets) {
+    for (auto const& target : this->Makefile->GetTargets()) {
       const char* incDirProp =
         target.second.GetProperty("INCLUDE_DIRECTORIES");
       if (!incDirProp) {
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 0ac5ca7..fdcca47 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -9,7 +9,6 @@
 #include <memory> // IWYU pragma: keep
 #include <set>
 #include <string>
-#include <unordered_map>
 #include <utility>
 #include <vector>
 
@@ -260,6 +259,4 @@ private:
   std::unique_ptr<cmTargetInternals> impl;
 };
 
-typedef std::unordered_map<std::string, cmTarget> cmTargets;
-
 #endif

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=90766347dbee280a6fd911d5242fa2342c1e7dd2
commit 90766347dbee280a6fd911d5242fa2342c1e7dd2
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed May 22 14:19:41 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed May 22 14:22:22 2019 -0400

    curl: Update build within CMake to account for 7.65 changes

diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 599d62b..37522fc 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -53,10 +53,11 @@ elseif(APPLE)
   endif()
   if(NOT OSX_VERSION VERSION_LESS 10.6 AND
       CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
-    set(CMAKE_USE_DARWINSSL ON CACHE INTERNAL "enable Apple OS native SSL/TLS")
+    set(CMAKE_USE_SECTRANSP ON CACHE INTERNAL "enable Apple OS native SSL/TLS")
   else()
-    set(CMAKE_USE_DARWINSSL OFF CACHE INTERNAL "enable Apple OS native SSL/TLS")
+    set(CMAKE_USE_SECTRANSP OFF CACHE INTERNAL "enable Apple OS native SSL/TLS")
   endif()
+  unset(CMAKE_USE_DARWINSSL CACHE)
 endif()
 set(CMAKE_USE_MBEDTLS OFF CACHE INTERNAL "Enable mbedTLS for SSL/TLS")
 
@@ -169,9 +170,11 @@ if(WIN32)
   option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
 endif()
 
+if(0) # This code not needed for building within CMake.
 cmake_dependent_option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup"
         ON "NOT ENABLE_ARES"
         OFF)
+endif()
 
 option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF)
 option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f
commit a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f
Merge: 2de8af0 b26487c
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed May 22 14:15:06 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed May 22 14:15:06 2019 -0400

    Merge branch 'upstream-curl' into update-curl
    
    * upstream-curl:
      curl 2019-05-22 (885ce314)

diff --cc Utilities/cmcurl/CMakeLists.txt
index 8dc3b2c,0000000..599d62b
mode 100644,000000..100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@@ -1,1482 -1,0 +1,1494 @@@
 +# Set curl options as needed for CMake build
 +set(BUILD_CURL_EXE OFF CACHE INTERNAL "No curl exe")
 +set(BUILD_DASHBOARD_REPORTS OFF CACHE INTERNAL "No curl dashboard reports")
 +set(BUILD_RELEASE_DEBUG_DIRS OFF CACHE INTERNAL "No curl release/debug dirs")
 +set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build shared libraries")
 +set(CMAKE_USE_GSSAPI OFF CACHE INTERNAL "Disable curl gssapi")
 +set(CMAKE_USE_LIBSSH2 OFF CACHE INTERNAL "Disable curl libssh2")
 +set(CMAKE_USE_OPENLDAP OFF CACHE INTERNAL "No curl OpenLDAP")
 +set(CURL_DISABLE_COOKIES OFF CACHE INTERNAL "Do not disable curl cookie support")
 +set(CURL_DISABLE_CRYPTO_AUTH OFF CACHE INTERNAL "Do not disable curl crypto auth")
 +set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?")
 +set(CURL_DISABLE_FILE OFF CACHE INTERNAL "Disable curl file protocol?")
 +set(CURL_DISABLE_FTP OFF CACHE INTERNAL "Disable curl ftp protocol?")
 +set(CURL_DISABLE_GOPHER ON CACHE INTERNAL "Disable curl gopher protocol?")
 +set(CURL_DISABLE_HTTP OFF CACHE INTERNAL "Disable curl http protocol?")
 +set(CURL_DISABLE_IMAP ON CACHE INTERNAL "Disable curl imap protocol?")
 +set(CURL_DISABLE_LDAP ON CACHE INTERNAL "Disable curl ldap protocol?")
 +set(CURL_DISABLE_LDAPS ON CACHE INTERNAL "Disable curl ldaps protocol?")
 +set(CURL_DISABLE_POP3 ON CACHE INTERNAL "Disable curl pop3 protocol?")
 +set(CURL_DISABLE_PROXY OFF CACHE INTERNAL "Do not disable curl proxy")
 +set(CURL_DISABLE_RTSP ON CACHE INTERNAL "Disable curl rtsp protocol?")
 +set(CURL_DISABLE_SMTP ON CACHE INTERNAL "Disable curl smtp protocol?")
 +set(CURL_DISABLE_TELNET ON CACHE INTERNAL "Disable curl telnet protocol?")
 +set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?")
 +set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity")
 +set(CURL_HIDDEN_SYMBOLS OFF CACHE INTERNAL "No curl hidden symbols")
 +set(CURL_WERROR OFF CACHE INTERNAL "Turn compiler warnings into errors")
 +set(DISABLED_THREADSAFE OFF CACHE INTERNAL "Curl can use thread-safe functions")
 +set(ENABLE_ARES OFF CACHE INTERNAL "No curl c-ares support")
 +set(ENABLE_CURLDEBUG OFF CACHE INTERNAL "No curl TrackMemory features")
 +set(ENABLE_DEBUG OFF CACHE INTERNAL "No curl debug features")
 +set(ENABLE_IPV6 ON CACHE INTERNAL "Enable curl IPv6 support detection")
 +set(ENABLE_MANUAL OFF CACHE INTERNAL "No curl built-in manual")
 +set(ENABLE_THREADED_RESOLVER OFF CACHE INTERNAL "No curl POSIX threaded DNS lookup")
 +set(ENABLE_UNIX_SOCKETS OFF CACHE INTERNAL "No curl Unix domain sockets support")
 +set(HTTP_ONLY OFF CACHE INTERNAL "Curl is not http-only")
 +set(PICKY_COMPILER OFF CACHE INTERNAL "Enable picky compiler options")
 +set(USE_WIN32_LDAP OFF CACHE INTERNAL "No curl Windows LDAP")
 +if(CMAKE_USE_OPENSSL)
 +elseif(WIN32)
 +  set(CMAKE_USE_WINSSL ON CACHE INTERNAL "enable Windows native SSL/TLS")
 +  set(CURL_WINDOWS_SSPI ON CACHE INTERNAL "Use windows libraries to allow NTLM authentication without openssl")
 +elseif(APPLE)
 +  # Use OS X SSL/TLS native implementation if available on target version.
 +  if(CMAKE_OSX_DEPLOYMENT_TARGET)
 +    set(OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET})
 +  else()
 +    execute_process(
 +      COMMAND sw_vers -productVersion
 +      OUTPUT_VARIABLE OSX_VERSION
 +      OUTPUT_STRIP_TRAILING_WHITESPACE
 +      )
 +  endif()
 +  if(NOT OSX_VERSION VERSION_LESS 10.6 AND
 +      CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
 +    set(CMAKE_USE_DARWINSSL ON CACHE INTERNAL "enable Apple OS native SSL/TLS")
 +  else()
 +    set(CMAKE_USE_DARWINSSL OFF CACHE INTERNAL "enable Apple OS native SSL/TLS")
 +  endif()
 +endif()
 +set(CMAKE_USE_MBEDTLS OFF CACHE INTERNAL "Enable mbedTLS for SSL/TLS")
 +
 +# Windows Vista and above have inet_pton, but this will link on
 +# older versions and then the executable will fail to launch at
 +# runtime on older versions because no DLL provides the symbol.
 +if(WIN32)
 +  set(HAVE_INET_PTON 0 CACHE INTERNAL "Do not use inet_pton")
 +endif()
 +
 +# Starting with OSX 10.11 there is an unrelated libnetwork library which will
 +# be picked up during curl configuration. Linking against this library is
 +# unnecessary and breaks backward compatibility of the resulting binaries
 +# because libnetwork is unavailable on older OSX versions.
 +if(APPLE)
 +  set(HAVE_LIBNETWORK 0 CACHE INTERNAL "Do not use libnetwork")
 +endif(APPLE)
 +
 +# Disable warnings to avoid changing 3rd party code.
 +if(CMAKE_C_COMPILER_ID MATCHES
 +    "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
 +  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
 +elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
 +  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
 +endif()
 +
 +#***************************************************************************
 +#                                  _   _ ____  _
 +#  Project                     ___| | | |  _ \| |
 +#                             / __| | | | |_) | |
 +#                            | (__| |_| |  _ <| |___
 +#                             \___|\___/|_| \_\_____|
 +#
- # Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
++# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
 +#
 +# This software is licensed as described in the file COPYING, which
 +# you should have received as part of this distribution. The terms
 +# are also available at https://curl.haxx.se/docs/copyright.html.
 +#
 +# You may opt to use, copy, modify, merge, publish, distribute and/or sell
 +# copies of the Software, and permit persons to whom the Software is
 +# furnished to do so, under the terms of the COPYING file.
 +#
 +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 +# KIND, either express or implied.
 +#
 +###########################################################################
 +# curl/libcurl CMake script
 +# by Tetetest and Sukender (Benoit Neil)
 +
 +# TODO:
 +# The output .so file lacks the soname number which we currently have within the lib/Makefile.am file
 +# Add full (4 or 5 libs) SSL support
 +# Add INSTALL target (EXTRA_DIST variables in Makefile.am may be moved to Makefile.inc so that CMake/CPack is aware of what's to include).
 +# Add CTests(?)
 +# Check on all possible platforms
 +# Test with as many configurations possible (With or without any option)
 +# Create scripts that help keeping the CMake build system up to date (to reduce maintenance). According to Tetetest:
 +#  - lists of headers that 'configure' checks for;
 +#  - curl-specific tests (the ones that are in m4/curl-*.m4 files);
 +#  - (most obvious thing:) curl version numbers.
 +# Add documentation subproject
 +#
 +# To check:
 +# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not.
 +# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options.
 +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
 +include(Utilities)
 +include(Macros)
 +include(CMakeDependentOption)
 +include(CheckCCompilerFlag)
 +
 +project(CURL C)
 +
 +if(0) # This code not needed for building within CMake.
 +message(WARNING "the curl cmake build system is poorly maintained. Be aware")
 +endif()
 +
 +file(READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS)
 +string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
 +  CURL_VERSION ${CURL_VERSION_H_CONTENTS})
 +string(REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION})
 +string(REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+"
 +  CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS})
 +string(REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM})
 +
- include_regular_expression("^.*$")    # Sukender: Is it necessary?
 +
 +# Setup package meta-data
 +# SET(PACKAGE "curl")
 +if(0) # This code not needed for building within CMake.
 +message(STATUS "curl version=[${CURL_VERSION}]")
 +endif()
 +# SET(PACKAGE_TARNAME "curl")
 +# SET(PACKAGE_NAME "curl")
 +# SET(PACKAGE_VERSION "-")
 +# SET(PACKAGE_STRING "curl-")
 +# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.haxx.se/mail/")
 +set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
 +set(OS "\"${CMAKE_SYSTEM_NAME}\"")
 +
- include_directories(${PROJECT_BINARY_DIR}/include/curl)
 +include_directories(${CURL_SOURCE_DIR}/include)
 +
 +option(CURL_WERROR "Turn compiler warnings into errors" OFF)
 +option(PICKY_COMPILER "Enable picky compiler options" ON)
 +option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
 +option(BUILD_SHARED_LIBS "Build shared libraries" ON)
 +option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
 +if(WIN32)
 +  option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
 +  option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
 +endif()
 +
 +cmake_dependent_option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup"
 +        ON "NOT ENABLE_ARES"
 +        OFF)
 +
 +option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF)
 +option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF)
 +
 +if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
 +  if(PICKY_COMPILER)
 +    foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers -Wno-pedantic-ms-format)
 +      # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
 +      # test result in.
 +      check_c_compiler_flag(${_CCOPT} OPT${_CCOPT})
 +      if(OPT${_CCOPT})
 +        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
 +      endif()
 +    endforeach()
 +  endif()
 +endif()
 +
 +if(ENABLE_DEBUG)
 +  # DEBUGBUILD will be defined only for Debug builds
-   if(NOT CMAKE_VERSION VERSION_LESS 3.0)
-     set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
-   else()
-     set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUGBUILD)
-   endif()
++  set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
 +  set(ENABLE_CURLDEBUG ON)
 +endif()
 +
 +if(ENABLE_CURLDEBUG)
 +  set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS CURLDEBUG)
 +endif()
 +
 +if(0) # This code not needed for building within CMake.
 +# For debug libs and exes, add "-d" postfix
 +if(NOT DEFINED CMAKE_DEBUG_POSTFIX)
 +  set(CMAKE_DEBUG_POSTFIX "-d")
 +endif()
 +endif()
 +
 +# initialize CURL_LIBS
 +set(CURL_LIBS "")
 +
 +if(ENABLE_ARES)
 +  set(USE_ARES 1)
 +  find_package(CARES REQUIRED)
 +  list(APPEND CURL_LIBS ${CARES_LIBRARY})
 +  set(CURL_LIBS ${CURL_LIBS} ${CARES_LIBRARY})
 +endif()
 +
 +if(0) # This code not needed for building within CMake.
 +include(CurlSymbolHiding)
 +endif()
 +
 +option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF)
 +mark_as_advanced(HTTP_ONLY)
 +option(CURL_DISABLE_FTP "disables FTP" OFF)
 +mark_as_advanced(CURL_DISABLE_FTP)
 +option(CURL_DISABLE_LDAP "disables LDAP" OFF)
 +mark_as_advanced(CURL_DISABLE_LDAP)
 +option(CURL_DISABLE_TELNET "disables Telnet" OFF)
 +mark_as_advanced(CURL_DISABLE_TELNET)
 +option(CURL_DISABLE_DICT "disables DICT" OFF)
 +mark_as_advanced(CURL_DISABLE_DICT)
 +option(CURL_DISABLE_FILE "disables FILE" OFF)
 +mark_as_advanced(CURL_DISABLE_FILE)
 +option(CURL_DISABLE_TFTP "disables TFTP" OFF)
 +mark_as_advanced(CURL_DISABLE_TFTP)
 +option(CURL_DISABLE_HTTP "disables HTTP" OFF)
 +mark_as_advanced(CURL_DISABLE_HTTP)
 +
 +option(CURL_DISABLE_LDAPS "to disable LDAPS" OFF)
 +mark_as_advanced(CURL_DISABLE_LDAPS)
 +
 +option(CURL_DISABLE_RTSP "to disable RTSP" OFF)
 +mark_as_advanced(CURL_DISABLE_RTSP)
 +option(CURL_DISABLE_PROXY "to disable proxy" OFF)
 +mark_as_advanced(CURL_DISABLE_PROXY)
 +option(CURL_DISABLE_POP3 "to disable POP3" OFF)
 +mark_as_advanced(CURL_DISABLE_POP3)
 +option(CURL_DISABLE_IMAP "to disable IMAP" OFF)
 +mark_as_advanced(CURL_DISABLE_IMAP)
 +option(CURL_DISABLE_SMTP "to disable SMTP" OFF)
 +mark_as_advanced(CURL_DISABLE_SMTP)
 +option(CURL_DISABLE_GOPHER "to disable Gopher" OFF)
 +mark_as_advanced(CURL_DISABLE_GOPHER)
 +
 +if(HTTP_ONLY)
 +  set(CURL_DISABLE_FTP ON)
 +  set(CURL_DISABLE_LDAP ON)
 +  set(CURL_DISABLE_LDAPS ON)
 +  set(CURL_DISABLE_TELNET ON)
 +  set(CURL_DISABLE_DICT ON)
 +  set(CURL_DISABLE_FILE ON)
 +  set(CURL_DISABLE_TFTP ON)
 +  set(CURL_DISABLE_RTSP ON)
 +  set(CURL_DISABLE_POP3 ON)
 +  set(CURL_DISABLE_IMAP ON)
 +  set(CURL_DISABLE_SMTP ON)
 +  set(CURL_DISABLE_GOPHER ON)
 +endif()
 +
 +option(CURL_DISABLE_COOKIES "to disable cookies support" OFF)
 +mark_as_advanced(CURL_DISABLE_COOKIES)
 +
 +option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF)
 +mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH)
 +option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF)
 +mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS)
 +option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON)
 +mark_as_advanced(ENABLE_IPV6)
 +if(ENABLE_IPV6 AND NOT WIN32)
 +  include(CheckStructHasMember)
 +  check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h"
 +                          HAVE_SOCKADDR_IN6_SIN6_ADDR)
 +  check_struct_has_member("struct sockaddr_in6" sin6_scope_id "netinet/in.h"
 +                          HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
 +  if(NOT HAVE_SOCKADDR_IN6_SIN6_ADDR)
 +    message(WARNING "struct sockaddr_in6 not available, disabling IPv6 support")
 +    # Force the feature off as this name is used as guard macro...
 +    set(ENABLE_IPV6 OFF
 +        CACHE BOOL "Define if you want to enable IPv6 support" FORCE)
 +  endif()
 +endif()
 +
 +if(0) # This code not needed for building within CMake.
 +# Required for building manual, docs, tests
 +curl_nroff_check()
 +find_package(Perl)
 +
 +cmake_dependent_option(ENABLE_MANUAL "to provide the built-in manual"
 +    ON "NROFF_USEFUL;PERL_FOUND"
 +    OFF)
 +
 +if(NOT PERL_FOUND)
 +  message(STATUS "Perl not found, testing disabled.")
 +  set(BUILD_TESTING OFF)
 +endif()
 +if(ENABLE_MANUAL)
 +  set(USE_MANUAL ON)
 +endif()
 +endif()
 +
 +# We need ansi c-flags, especially on HP
 +set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}")
 +set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS})
 +
 +if(CURL_STATIC_CRT)
 +  set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
 +  set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
 +endif()
 +
 +# Disable warnings on Borland to avoid changing 3rd party code.
 +if(BORLAND)
 +  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-")
 +endif()
 +
 +# If we are on AIX, do the _ALL_SOURCE magic
 +if(${CMAKE_SYSTEM_NAME} MATCHES AIX)
 +  set(_ALL_SOURCE 1)
 +endif()
 +
 +# Include all the necessary files for macros
 +include(CheckFunctionExists)
 +include(CheckIncludeFile)
 +include(CheckIncludeFiles)
 +include(CheckLibraryExists)
 +include(CheckSymbolExists)
 +include(CheckTypeSize)
 +include(CheckCSourceCompiles)
 +
 +# On windows preload settings
 +if(WIN32)
 +  set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_=")
 +  include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
 +endif()
 +
 +if(ENABLE_THREADED_RESOLVER)
 +  find_package(Threads REQUIRED)
 +  if(WIN32)
 +    set(USE_THREADS_WIN32 ON)
 +  else()
 +    set(USE_THREADS_POSIX ${CMAKE_USE_PTHREADS_INIT})
 +    set(HAVE_PTHREAD_H ${CMAKE_USE_PTHREADS_INIT})
 +  endif()
 +  set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
 +endif()
 +
 +# Check for all needed libraries
 +if(0) # This code not needed for building within CMake.
 +check_library_exists_concat("dl"     dlopen       HAVE_LIBDL)
 +else()
 +  # Use the cmake-defined dl libs as dl is should not be used
 +  # on HPUX, but rather dld this avoids a warning
 +  list(APPEND CURL_LIBS ${CMAKE_DL_LIBS})
 +endif()
 +check_library_exists_concat("socket" connect      HAVE_LIBSOCKET)
 +check_library_exists("c" gethostbyname "" NOT_NEED_LIBNSL)
 +
 +# Yellowtab Zeta needs different libraries than BeOS 5.
 +if(BEOS)
 +  set(NOT_NEED_LIBNSL 1)
 +  check_library_exists_concat("bind" gethostbyname HAVE_LIBBIND)
 +  check_library_exists_concat("bnetapi" closesocket HAVE_LIBBNETAPI)
 +endif()
 +
 +check_library_exists_concat("network" recv HAVE_LIBNETWORK)
 +
 +if(NOT NOT_NEED_LIBNSL)
 +  check_library_exists_concat("nsl"    gethostbyname  HAVE_LIBNSL)
 +endif()
 +
 +check_function_exists(gethostname HAVE_GETHOSTNAME)
 +
 +if(WIN32)
 +  check_library_exists_concat("ws2_32" getch        HAVE_LIBWS2_32)
 +  check_library_exists_concat("winmm"  getch        HAVE_LIBWINMM)
 +  list(APPEND CURL_LIBS "advapi32")
 +endif()
 +
 +# check SSL libraries
- # TODO support GNUTLS, NSS, POLARSSL, AXTLS, CYASSL
++# TODO support GNUTLS, NSS, POLARSSL, CYASSL
 +
 +if(APPLE)
-   option(CMAKE_USE_DARWINSSL "enable Apple OS native SSL/TLS" OFF)
++  option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF)
 +endif()
 +if(WIN32)
 +  option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF)
 +  cmake_dependent_option(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without openssl" ON
 +    CMAKE_USE_WINSSL OFF)
 +endif()
 +option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF)
 +
 +set(openssl_default ON)
- if(WIN32 OR CMAKE_USE_DARWINSSL OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
++if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
 +  set(openssl_default OFF)
 +endif()
 +
 +count_true(enabled_ssl_options_count
 +  CMAKE_USE_WINSSL
-   CMAKE_USE_DARWINSSL
++  CMAKE_USE_SECTRANSP
 +  CMAKE_USE_OPENSSL
 +  CMAKE_USE_MBEDTLS
 +)
 +if(enabled_ssl_options_count GREATER "1")
 +  set(CURL_WITH_MULTI_SSL ON)
 +endif()
 +
 +if(CMAKE_USE_WINSSL)
 +  set(SSL_ENABLED ON)
 +  set(USE_SCHANNEL ON) # Windows native SSL/TLS support
 +  set(USE_WINDOWS_SSPI ON) # CMAKE_USE_WINSSL implies CURL_WINDOWS_SSPI
 +  list(APPEND CURL_LIBS "crypt32")
 +endif()
 +if(CURL_WINDOWS_SSPI)
 +  set(USE_WINDOWS_SSPI ON)
 +  set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DSECURITY_WIN32")
 +endif()
 +
 +if(CMAKE_USE_DARWINSSL)
++  message(FATAL_ERROR "The cmake option CMAKE_USE_DARWINSSL was renamed to CMAKE_USE_SECTRANSP.")
++endif()
++
++if(CMAKE_USE_SECTRANSP)
 +  find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation")
 +  if(NOT COREFOUNDATION_FRAMEWORK)
 +      message(FATAL_ERROR "CoreFoundation framework not found")
 +  endif()
 +
 +  find_library(SECURITY_FRAMEWORK "Security")
 +  if(NOT SECURITY_FRAMEWORK)
 +     message(FATAL_ERROR "Security framework not found")
 +  endif()
 +
 +  set(SSL_ENABLED ON)
-   set(USE_DARWINSSL ON)
++  set(USE_SECTRANSP ON)
 +  list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}")
 +endif()
 +
 +if(CMAKE_USE_OPENSSL)
 +  find_package(OpenSSL REQUIRED)
 +  set(SSL_ENABLED ON)
 +  set(USE_OPENSSL ON)
 +  set(HAVE_LIBCRYPTO ON)
 +  set(HAVE_LIBSSL ON)
 +  list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
 +  include_directories(${OPENSSL_INCLUDE_DIR})
 +
 +  set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
 +  check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H)
 +  check_include_file("openssl/err.h"    HAVE_OPENSSL_ERR_H)
 +  check_include_file("openssl/pem.h"    HAVE_OPENSSL_PEM_H)
 +  check_include_file("openssl/rsa.h"    HAVE_OPENSSL_RSA_H)
 +  check_include_file("openssl/ssl.h"    HAVE_OPENSSL_SSL_H)
 +  check_include_file("openssl/x509.h"   HAVE_OPENSSL_X509_H)
 +  check_include_file("openssl/rand.h"   HAVE_OPENSSL_RAND_H)
 +  check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS)
 +  check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN)
 +  check_symbol_exists(RAND_egd    "${CURL_INCLUDES}" HAVE_RAND_EGD)
 +
 +  # Optionally build with a specific CA cert bundle.
 +  if(CURL_CA_BUNDLE)
 +    add_definitions(-DCURL_CA_BUNDLE="${CURL_CA_BUNDLE}")
 +  endif()
 +  # Optionally build with a specific CA cert dir.
 +  if(CURL_CA_PATH)
 +    add_definitions(-DCURL_CA_PATH="${CURL_CA_PATH}")
 +  endif()
 +endif()
 +
 +if(CMAKE_USE_MBEDTLS)
 +  find_package(MbedTLS REQUIRED)
 +  set(SSL_ENABLED ON)
 +  set(USE_MBEDTLS ON)
 +  list(APPEND CURL_LIBS ${MBEDTLS_LIBRARIES})
 +  include_directories(${MBEDTLS_INCLUDE_DIRS})
 +endif()
 +
 +option(USE_NGHTTP2 "Use Nghttp2 library" OFF)
 +if(USE_NGHTTP2)
 +  find_package(NGHTTP2 REQUIRED)
 +  include_directories(${NGHTTP2_INCLUDE_DIRS})
 +  list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
 +endif()
 +
 +if(NOT CURL_DISABLE_LDAP)
 +  if(WIN32)
 +    option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
 +    if(USE_WIN32_LDAP)
 +      check_library_exists_concat("wldap32" cldap_open HAVE_WLDAP32)
 +      if(NOT HAVE_WLDAP32)
 +        set(USE_WIN32_LDAP OFF)
 +      endif()
 +    endif()
 +  endif()
 +
 +  option(CMAKE_USE_OPENLDAP "Use OpenLDAP code." OFF)
 +  mark_as_advanced(CMAKE_USE_OPENLDAP)
 +  set(CMAKE_LDAP_LIB "ldap" CACHE STRING "Name or full path to ldap library")
 +  set(CMAKE_LBER_LIB "lber" CACHE STRING "Name or full path to lber library")
 +
 +  if(CMAKE_USE_OPENLDAP AND USE_WIN32_LDAP)
 +    message(FATAL_ERROR "Cannot use USE_WIN32_LDAP and CMAKE_USE_OPENLDAP at the same time")
 +  endif()
 +
 +  # Now that we know, we're not using windows LDAP...
 +  if(USE_WIN32_LDAP)
 +    check_include_file_concat("winldap.h" HAVE_WINLDAP_H)
 +    check_include_file_concat("winber.h"  HAVE_WINBER_H)
 +  else()
 +    # Check for LDAP
 +    set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
 +    check_library_exists_concat(${CMAKE_LDAP_LIB} ldap_init HAVE_LIBLDAP)
 +    check_library_exists_concat(${CMAKE_LBER_LIB} ber_init HAVE_LIBLBER)
 +
 +    set(CMAKE_REQUIRED_INCLUDES_BAK ${CMAKE_REQUIRED_INCLUDES})
 +    set(CMAKE_LDAP_INCLUDE_DIR "" CACHE STRING "Path to LDAP include directory")
 +    if(CMAKE_LDAP_INCLUDE_DIR)
 +      list(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_LDAP_INCLUDE_DIR})
 +    endif()
 +    check_include_file_concat("ldap.h"           HAVE_LDAP_H)
 +    check_include_file_concat("lber.h"           HAVE_LBER_H)
 +
 +    if(NOT HAVE_LDAP_H)
 +      message(STATUS "LDAP_H not found CURL_DISABLE_LDAP set ON")
 +      set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
 +      set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used
 +    elseif(NOT HAVE_LIBLDAP)
 +      message(STATUS "LDAP library '${CMAKE_LDAP_LIB}' not found CURL_DISABLE_LDAP set ON")
 +      set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
 +      set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used
 +    else()
 +      if(CMAKE_USE_OPENLDAP)
 +        set(USE_OPENLDAP ON)
 +      endif()
 +      if(CMAKE_LDAP_INCLUDE_DIR)
 +        include_directories(${CMAKE_LDAP_INCLUDE_DIR})
 +      endif()
 +      set(NEED_LBER_H ON)
 +      set(_HEADER_LIST)
 +      if(HAVE_WINDOWS_H)
 +        list(APPEND _HEADER_LIST "windows.h")
 +      endif()
 +      if(HAVE_SYS_TYPES_H)
 +        list(APPEND _HEADER_LIST "sys/types.h")
 +      endif()
 +      list(APPEND _HEADER_LIST "ldap.h")
 +
 +      set(_SRC_STRING "")
 +      foreach(_HEADER ${_HEADER_LIST})
 +        set(_INCLUDE_STRING "${_INCLUDE_STRING}#include <${_HEADER}>\n")
 +      endforeach()
 +
 +      set(_SRC_STRING
 +        "
 +        ${_INCLUDE_STRING}
 +        int main(int argc, char ** argv)
 +        {
 +          BerValue *bvp = NULL;
 +          BerElement *bep = ber_init(bvp);
 +          ber_free(bep, 1);
 +          return 0;
 +        }"
 +      )
 +      set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DLDAP_DEPRECATED=1")
 +      list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB})
 +      if(HAVE_LIBLBER)
 +        list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
 +      endif()
 +      check_c_source_compiles("${_SRC_STRING}" NOT_NEED_LBER_H)
++      unset(CMAKE_REQUIRED_LIBRARIES)
 +
 +      if(NOT_NEED_LBER_H)
 +        set(NEED_LBER_H OFF)
 +      else()
 +        set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DNEED_LBER_H")
 +      endif()
 +    endif()
 +  endif()
 +endif()
 +
 +# No ldap, no ldaps.
 +if(CURL_DISABLE_LDAP)
 +  if(NOT CURL_DISABLE_LDAPS)
 +    message(STATUS "LDAP needs to be enabled to support LDAPS")
 +    set(CURL_DISABLE_LDAPS ON CACHE BOOL "" FORCE)
 +  endif()
 +endif()
 +
 +if(NOT CURL_DISABLE_LDAPS)
 +  check_include_file_concat("ldap_ssl.h" HAVE_LDAP_SSL_H)
 +  check_include_file_concat("ldapssl.h"  HAVE_LDAPSSL_H)
 +endif()
 +
 +# Check for idn
 +check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
 +
 +# Check for symbol dlopen (same as HAVE_LIBDL)
 +check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
 +
 +if(0) # This code not needed for building within CMake.
 +option(CURL_ZLIB "Set to ON to enable building curl with zlib support." ON)
 +set(HAVE_LIBZ OFF)
 +set(HAVE_ZLIB_H OFF)
 +set(USE_ZLIB OFF)
 +if(CURL_ZLIB)
 +  find_package(ZLIB QUIET)
 +  if(ZLIB_FOUND)
 +    set(HAVE_ZLIB_H ON)
 +    set(HAVE_LIBZ ON)
 +    set(USE_ZLIB ON)
 +
 +    # Depend on ZLIB via imported targets if supported by the running
 +    # version of CMake.  This allows our dependents to get our dependencies
 +    # transitively.
 +    if(NOT CMAKE_VERSION VERSION_LESS 3.4)
 +      list(APPEND CURL_LIBS ZLIB::ZLIB)
 +    else()
 +      list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
 +      include_directories(${ZLIB_INCLUDE_DIRS})
 +    endif()
 +    list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
 +  endif()
 +endif()
 +endif()
 +
 +#-----------------------------------------------------------------------------
 +# CMake-specific curl code.
 +
 +if(CURL_SPECIAL_LIBZ)
 +  set(CURL_LIBS ${CURL_LIBS} "${CURL_SPECIAL_LIBZ}")
 +  include_directories(${CURL_SPECIAL_LIBZ_INCLUDES})
 +  set(HAVE_LIBZ 0)
 +  set(HAVE_ZLIB_H 0)
 +endif()
 +
 +option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF)
 +set(HAVE_BROTLI OFF)
 +if(CURL_BROTLI)
 +  find_package(BROTLI QUIET)
 +  if(BROTLI_FOUND)
 +    set(HAVE_BROTLI ON)
 +    list(APPEND CURL_LIBS ${BROTLI_LIBRARIES})
 +    include_directories(${BROTLI_INCLUDE_DIRS})
 +    list(APPEND CMAKE_REQUIRED_INCLUDES ${BROTLI_INCLUDE_DIRS})
 +  endif()
 +endif()
 +
 +#libSSH2
 +option(CMAKE_USE_LIBSSH2 "Use libSSH2" ON)
 +mark_as_advanced(CMAKE_USE_LIBSSH2)
 +set(USE_LIBSSH2 OFF)
 +set(HAVE_LIBSSH2 OFF)
 +set(HAVE_LIBSSH2_H OFF)
 +
 +if(CMAKE_USE_LIBSSH2)
 +  find_package(LibSSH2)
 +  if(LIBSSH2_FOUND)
 +    list(APPEND CURL_LIBS ${LIBSSH2_LIBRARY})
 +    set(CMAKE_REQUIRED_LIBRARIES ${LIBSSH2_LIBRARY})
 +    list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSH2_INCLUDE_DIR}")
 +    include_directories("${LIBSSH2_INCLUDE_DIR}")
 +    set(HAVE_LIBSSH2 ON)
 +    set(USE_LIBSSH2 ON)
 +
 +    # find_package has already found the headers
 +    set(HAVE_LIBSSH2_H ON)
 +    set(CURL_INCLUDES ${CURL_INCLUDES} "${LIBSSH2_INCLUDE_DIR}/libssh2.h")
 +    set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DHAVE_LIBSSH2_H")
 +
 +    # now check for specific libssh2 symbols as they were added in different versions
 +    set(CMAKE_EXTRA_INCLUDE_FILES "libssh2.h")
 +    check_function_exists(libssh2_version           HAVE_LIBSSH2_VERSION)
 +    check_function_exists(libssh2_init              HAVE_LIBSSH2_INIT)
 +    check_function_exists(libssh2_exit              HAVE_LIBSSH2_EXIT)
 +    check_function_exists(libssh2_scp_send64        HAVE_LIBSSH2_SCP_SEND64)
 +    check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE)
 +    set(CMAKE_EXTRA_INCLUDE_FILES "")
++    unset(CMAKE_REQUIRED_LIBRARIES)
 +  endif()
 +endif()
 +
 +option(CMAKE_USE_GSSAPI "Use GSSAPI implementation (right now only Heimdal is supported with CMake build)" OFF)
 +mark_as_advanced(CMAKE_USE_GSSAPI)
 +
 +if(CMAKE_USE_GSSAPI)
 +  find_package(GSS)
 +
 +  set(HAVE_GSSAPI ${GSS_FOUND})
 +  if(GSS_FOUND)
 +
 +    message(STATUS "Found ${GSS_FLAVOUR} GSSAPI version: \"${GSS_VERSION}\"")
 +
-     list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIRECTORIES})
++    list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIR})
 +    check_include_file_concat("gssapi/gssapi.h"  HAVE_GSSAPI_GSSAPI_H)
 +    check_include_file_concat("gssapi/gssapi_generic.h" HAVE_GSSAPI_GSSAPI_GENERIC_H)
 +    check_include_file_concat("gssapi/gssapi_krb5.h" HAVE_GSSAPI_GSSAPI_KRB5_H)
 +
 +    if(GSS_FLAVOUR STREQUAL "Heimdal")
 +      set(HAVE_GSSHEIMDAL ON)
 +    else() # MIT
 +      set(HAVE_GSSMIT ON)
 +      set(_INCLUDE_LIST "")
 +      if(HAVE_GSSAPI_GSSAPI_H)
 +        list(APPEND _INCLUDE_LIST "gssapi/gssapi.h")
 +      endif()
 +      if(HAVE_GSSAPI_GSSAPI_GENERIC_H)
 +        list(APPEND _INCLUDE_LIST "gssapi/gssapi_generic.h")
 +      endif()
 +      if(HAVE_GSSAPI_GSSAPI_KRB5_H)
 +        list(APPEND _INCLUDE_LIST "gssapi/gssapi_krb5.h")
 +      endif()
 +
 +      string(REPLACE ";" " " _COMPILER_FLAGS_STR "${GSS_COMPILER_FLAGS}")
 +      string(REPLACE ";" " " _LINKER_FLAGS_STR "${GSS_LINKER_FLAGS}")
 +
 +      foreach(_dir ${GSS_LINK_DIRECTORIES})
 +        set(_LINKER_FLAGS_STR "${_LINKER_FLAGS_STR} -L\"${_dir}\"")
 +      endforeach()
 +
 +      set(CMAKE_REQUIRED_FLAGS "${_COMPILER_FLAGS_STR} ${_LINKER_FLAGS_STR}")
 +      set(CMAKE_REQUIRED_LIBRARIES ${GSS_LIBRARIES})
 +      check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" ${_INCLUDE_LIST} HAVE_GSS_C_NT_HOSTBASED_SERVICE)
 +      if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE)
 +        set(HAVE_OLD_GSSMIT ON)
 +      endif()
++      unset(CMAKE_REQUIRED_LIBRARIES)
 +
 +    endif()
 +
-     include_directories(${GSS_INCLUDE_DIRECTORIES})
++    include_directories(${GSS_INCLUDE_DIR})
 +    link_directories(${GSS_LINK_DIRECTORIES})
 +    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}")
 +    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
 +    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
 +    list(APPEND CURL_LIBS ${GSS_LIBRARIES})
 +
 +  else()
 +    message(WARNING "GSSAPI support has been requested but no supporting libraries found. Skipping.")
 +  endif()
 +endif()
 +
 +option(ENABLE_UNIX_SOCKETS "Define if you want Unix domain sockets support" ON)
 +if(ENABLE_UNIX_SOCKETS)
 +  include(CheckStructHasMember)
 +  check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS)
 +else()
 +  unset(USE_UNIX_SOCKETS CACHE)
 +endif()
 +
 +
 +if(0) # This code not needed for building within CMake.
 +#
 +# CA handling
 +#
 +set(CURL_CA_BUNDLE "auto" CACHE STRING
 +    "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
 +set(CURL_CA_FALLBACK OFF CACHE BOOL
 +    "Set ON to use built-in CA store of TLS backend. Defaults to OFF")
 +set(CURL_CA_PATH "auto" CACHE STRING
 +    "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
 +
 +if("${CURL_CA_BUNDLE}" STREQUAL "")
 +  message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.")
 +elseif("${CURL_CA_BUNDLE}" STREQUAL "none")
 +  unset(CURL_CA_BUNDLE CACHE)
 +elseif("${CURL_CA_BUNDLE}" STREQUAL "auto")
 +  unset(CURL_CA_BUNDLE CACHE)
 +  set(CURL_CA_BUNDLE_AUTODETECT TRUE)
 +else()
 +  set(CURL_CA_BUNDLE_SET TRUE)
 +endif()
 +
 +if("${CURL_CA_PATH}" STREQUAL "")
 +  message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.")
 +elseif("${CURL_CA_PATH}" STREQUAL "none")
 +  unset(CURL_CA_PATH CACHE)
 +elseif("${CURL_CA_PATH}" STREQUAL "auto")
 +  unset(CURL_CA_PATH CACHE)
 +  set(CURL_CA_PATH_AUTODETECT TRUE)
 +else()
 +  set(CURL_CA_PATH_SET TRUE)
 +endif()
 +
 +if(CURL_CA_BUNDLE_SET AND CURL_CA_PATH_AUTODETECT)
 +  # Skip autodetection of unset CA path because CA bundle is set explicitly
 +elseif(CURL_CA_PATH_SET AND CURL_CA_BUNDLE_AUTODETECT)
 +  # Skip autodetection of unset CA bundle because CA path is set explicitly
 +elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
 +  # first try autodetecting a CA bundle, then a CA path
 +
 +  if(CURL_CA_BUNDLE_AUTODETECT)
 +    set(SEARCH_CA_BUNDLE_PATHS
 +        /etc/ssl/certs/ca-certificates.crt
 +        /etc/pki/tls/certs/ca-bundle.crt
 +        /usr/share/ssl/certs/ca-bundle.crt
 +        /usr/local/share/certs/ca-root-nss.crt
 +        /etc/ssl/cert.pem)
 +
 +    foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS})
 +      if(EXISTS "${SEARCH_CA_BUNDLE_PATH}")
 +        message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}")
 +        set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}")
 +        set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
 +        break()
 +      endif()
 +    endforeach()
 +  endif()
 +
 +  if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET))
 +    if(EXISTS "/etc/ssl/certs")
 +      set(CURL_CA_PATH "/etc/ssl/certs")
 +      set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
 +    endif()
 +  endif()
 +endif()
 +
 +if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS)
 +  message(FATAL_ERROR
 +          "CA path only supported by OpenSSL, GnuTLS or mbed TLS. "
 +          "Set CURL_CA_PATH=none or enable one of those TLS backends.")
 +endif()
 +endif()
 +
 +# Check for header files
 +if(NOT UNIX)
 +  check_include_file_concat("windows.h"      HAVE_WINDOWS_H)
 +  check_include_file_concat("winsock.h"      HAVE_WINSOCK_H)
 +  check_include_file_concat("ws2tcpip.h"     HAVE_WS2TCPIP_H)
 +  check_include_file_concat("winsock2.h"     HAVE_WINSOCK2_H)
 +  if(NOT CURL_WINDOWS_SSPI AND USE_OPENSSL)
 +    set(CURL_LIBS ${CURL_LIBS} "crypt32")
 +  endif()
 +else()
 +  set(HAVE_WINDOWS_H 0)
 +  set(HAVE_WINSOCK_H 0)
 +  set(HAVE_WS2TCPIP_H 0)
 +  set(HAVE_WINSOCK2_H 0)
 +endif()
 +
 +check_include_file_concat("stdio.h"          HAVE_STDIO_H)
 +check_include_file_concat("inttypes.h"       HAVE_INTTYPES_H)
 +check_include_file_concat("sys/filio.h"      HAVE_SYS_FILIO_H)
 +check_include_file_concat("sys/ioctl.h"      HAVE_SYS_IOCTL_H)
 +check_include_file_concat("sys/param.h"      HAVE_SYS_PARAM_H)
 +check_include_file_concat("sys/poll.h"       HAVE_SYS_POLL_H)
 +check_include_file_concat("sys/resource.h"   HAVE_SYS_RESOURCE_H)
 +check_include_file_concat("sys/select.h"     HAVE_SYS_SELECT_H)
 +check_include_file_concat("sys/socket.h"     HAVE_SYS_SOCKET_H)
 +check_include_file_concat("sys/sockio.h"     HAVE_SYS_SOCKIO_H)
 +check_include_file_concat("sys/stat.h"       HAVE_SYS_STAT_H)
 +check_include_file_concat("sys/time.h"       HAVE_SYS_TIME_H)
 +check_include_file_concat("sys/types.h"      HAVE_SYS_TYPES_H)
 +check_include_file_concat("sys/uio.h"        HAVE_SYS_UIO_H)
 +check_include_file_concat("sys/un.h"         HAVE_SYS_UN_H)
 +check_include_file_concat("sys/utime.h"      HAVE_SYS_UTIME_H)
 +check_include_file_concat("sys/xattr.h"      HAVE_SYS_XATTR_H)
 +check_include_file_concat("alloca.h"         HAVE_ALLOCA_H)
 +check_include_file_concat("arpa/inet.h"      HAVE_ARPA_INET_H)
 +check_include_file_concat("arpa/tftp.h"      HAVE_ARPA_TFTP_H)
 +check_include_file_concat("assert.h"         HAVE_ASSERT_H)
 +check_include_file_concat("crypto.h"         HAVE_CRYPTO_H)
 +check_include_file_concat("des.h"            HAVE_DES_H)
 +check_include_file_concat("err.h"            HAVE_ERR_H)
 +check_include_file_concat("errno.h"          HAVE_ERRNO_H)
 +check_include_file_concat("fcntl.h"          HAVE_FCNTL_H)
 +check_include_file_concat("idn2.h"           HAVE_IDN2_H)
 +check_include_file_concat("ifaddrs.h"        HAVE_IFADDRS_H)
 +check_include_file_concat("io.h"             HAVE_IO_H)
 +check_include_file_concat("krb.h"            HAVE_KRB_H)
 +check_include_file_concat("libgen.h"         HAVE_LIBGEN_H)
 +check_include_file_concat("locale.h"         HAVE_LOCALE_H)
 +check_include_file_concat("net/if.h"         HAVE_NET_IF_H)
 +check_include_file_concat("netdb.h"          HAVE_NETDB_H)
 +check_include_file_concat("netinet/in.h"     HAVE_NETINET_IN_H)
 +check_include_file_concat("netinet/tcp.h"    HAVE_NETINET_TCP_H)
 +
 +check_include_file_concat("pem.h"            HAVE_PEM_H)
 +check_include_file_concat("poll.h"           HAVE_POLL_H)
 +check_include_file_concat("pwd.h"            HAVE_PWD_H)
 +check_include_file_concat("rsa.h"            HAVE_RSA_H)
 +check_include_file_concat("setjmp.h"         HAVE_SETJMP_H)
 +check_include_file_concat("sgtty.h"          HAVE_SGTTY_H)
 +check_include_file_concat("signal.h"         HAVE_SIGNAL_H)
 +check_include_file_concat("ssl.h"            HAVE_SSL_H)
 +check_include_file_concat("stdbool.h"        HAVE_STDBOOL_H)
 +check_include_file_concat("stdint.h"         HAVE_STDINT_H)
 +check_include_file_concat("stdio.h"          HAVE_STDIO_H)
 +check_include_file_concat("stdlib.h"         HAVE_STDLIB_H)
 +check_include_file_concat("string.h"         HAVE_STRING_H)
 +check_include_file_concat("strings.h"        HAVE_STRINGS_H)
 +check_include_file_concat("stropts.h"        HAVE_STROPTS_H)
 +check_include_file_concat("termio.h"         HAVE_TERMIO_H)
 +check_include_file_concat("termios.h"        HAVE_TERMIOS_H)
 +check_include_file_concat("time.h"           HAVE_TIME_H)
 +check_include_file_concat("unistd.h"         HAVE_UNISTD_H)
 +check_include_file_concat("utime.h"          HAVE_UTIME_H)
 +check_include_file_concat("x509.h"           HAVE_X509_H)
 +
 +check_include_file_concat("process.h"        HAVE_PROCESS_H)
 +check_include_file_concat("stddef.h"         HAVE_STDDEF_H)
 +check_include_file_concat("dlfcn.h"          HAVE_DLFCN_H)
 +check_include_file_concat("malloc.h"         HAVE_MALLOC_H)
 +check_include_file_concat("memory.h"         HAVE_MEMORY_H)
 +check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H)
 +check_include_file_concat("stdint.h"        HAVE_STDINT_H)
 +check_include_file_concat("sockio.h"        HAVE_SOCKIO_H)
 +check_include_file_concat("sys/utsname.h"   HAVE_SYS_UTSNAME_H)
 +
 +check_type_size(size_t  SIZEOF_SIZE_T)
 +check_type_size(ssize_t  SIZEOF_SSIZE_T)
 +check_type_size("long long"  SIZEOF_LONG_LONG)
 +check_type_size("long"  SIZEOF_LONG)
 +check_type_size("short"  SIZEOF_SHORT)
 +check_type_size("int"  SIZEOF_INT)
 +check_type_size("__int64"  SIZEOF___INT64)
 +check_type_size("time_t"  SIZEOF_TIME_T)
 +
 +if(HAVE_SIZEOF_LONG_LONG)
 +  set(HAVE_LONGLONG 1)
 +  set(HAVE_LL 1)
 +endif()
 +
 +find_file(RANDOM_FILE urandom /dev)
 +mark_as_advanced(RANDOM_FILE)
 +
 +# Check for some functions that are used
 +if(HAVE_LIBWS2_32)
 +  set(CMAKE_REQUIRED_LIBRARIES ws2_32)
 +elseif(HAVE_LIBSOCKET)
 +  set(CMAKE_REQUIRED_LIBRARIES socket)
 +elseif(HAVE_LIBNETWORK)
 +  set(CMAKE_REQUIRED_LIBRARIES network)
 +endif()
 +
 +check_symbol_exists(basename      "${CURL_INCLUDES}" HAVE_BASENAME)
 +check_symbol_exists(socket        "${CURL_INCLUDES}" HAVE_SOCKET)
- # poll on macOS is unreliable, it first did not exist, then was broken until
- # fixed in 10.9 only to break again in 10.12.
- if(NOT APPLE)
-   check_symbol_exists(poll        "${CURL_INCLUDES}" HAVE_POLL)
- endif()
 +check_symbol_exists(select        "${CURL_INCLUDES}" HAVE_SELECT)
++check_symbol_exists(poll          "${CURL_INCLUDES}" HAVE_POLL)
 +check_symbol_exists(strdup        "${CURL_INCLUDES}" HAVE_STRDUP)
 +check_symbol_exists(strstr        "${CURL_INCLUDES}" HAVE_STRSTR)
 +check_symbol_exists(strtok_r      "${CURL_INCLUDES}" HAVE_STRTOK_R)
 +check_symbol_exists(strftime      "${CURL_INCLUDES}" HAVE_STRFTIME)
 +check_symbol_exists(uname         "${CURL_INCLUDES}" HAVE_UNAME)
 +check_symbol_exists(strcasecmp    "${CURL_INCLUDES}" HAVE_STRCASECMP)
 +check_symbol_exists(stricmp       "${CURL_INCLUDES}" HAVE_STRICMP)
 +check_symbol_exists(strcmpi       "${CURL_INCLUDES}" HAVE_STRCMPI)
 +check_symbol_exists(strncmpi      "${CURL_INCLUDES}" HAVE_STRNCMPI)
 +check_symbol_exists(alarm         "${CURL_INCLUDES}" HAVE_ALARM)
 +if(NOT HAVE_STRNCMPI)
 +  set(HAVE_STRCMPI)
 +endif()
 +check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR)
 +check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R)
 +check_symbol_exists(gettimeofday  "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
 +check_symbol_exists(inet_addr     "${CURL_INCLUDES}" HAVE_INET_ADDR)
 +check_symbol_exists(inet_ntoa     "${CURL_INCLUDES}" HAVE_INET_NTOA)
 +check_symbol_exists(inet_ntoa_r   "${CURL_INCLUDES}" HAVE_INET_NTOA_R)
 +check_symbol_exists(tcsetattr     "${CURL_INCLUDES}" HAVE_TCSETATTR)
 +check_symbol_exists(tcgetattr     "${CURL_INCLUDES}" HAVE_TCGETATTR)
 +check_symbol_exists(perror        "${CURL_INCLUDES}" HAVE_PERROR)
 +check_symbol_exists(closesocket   "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
 +check_symbol_exists(setvbuf       "${CURL_INCLUDES}" HAVE_SETVBUF)
 +check_symbol_exists(sigsetjmp     "${CURL_INCLUDES}" HAVE_SIGSETJMP)
 +check_symbol_exists(getpass_r     "${CURL_INCLUDES}" HAVE_GETPASS_R)
 +check_symbol_exists(strlcat       "${CURL_INCLUDES}" HAVE_STRLCAT)
 +check_symbol_exists(getpwuid      "${CURL_INCLUDES}" HAVE_GETPWUID)
 +check_symbol_exists(getpwuid_r    "${CURL_INCLUDES}" HAVE_GETPWUID_R)
 +check_symbol_exists(geteuid       "${CURL_INCLUDES}" HAVE_GETEUID)
 +check_symbol_exists(utime         "${CURL_INCLUDES}" HAVE_UTIME)
 +check_symbol_exists(gmtime_r      "${CURL_INCLUDES}" HAVE_GMTIME_R)
 +check_symbol_exists(localtime_r   "${CURL_INCLUDES}" HAVE_LOCALTIME_R)
 +
 +check_symbol_exists(gethostbyname   "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME)
 +check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
 +
 +check_symbol_exists(signal        "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC)
 +check_symbol_exists(SIGALRM       "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO)
 +if(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
 +  set(HAVE_SIGNAL 1)
 +endif()
 +check_symbol_exists(uname          "${CURL_INCLUDES}" HAVE_UNAME)
 +check_symbol_exists(strtoll        "${CURL_INCLUDES}" HAVE_STRTOLL)
 +check_symbol_exists(_strtoi64      "${CURL_INCLUDES}" HAVE__STRTOI64)
 +check_symbol_exists(strerror_r     "${CURL_INCLUDES}" HAVE_STRERROR_R)
 +check_symbol_exists(siginterrupt   "${CURL_INCLUDES}" HAVE_SIGINTERRUPT)
 +check_symbol_exists(perror         "${CURL_INCLUDES}" HAVE_PERROR)
 +check_symbol_exists(fork           "${CURL_INCLUDES}" HAVE_FORK)
 +check_symbol_exists(getaddrinfo    "${CURL_INCLUDES}" HAVE_GETADDRINFO)
 +check_symbol_exists(freeaddrinfo   "${CURL_INCLUDES}" HAVE_FREEADDRINFO)
 +check_symbol_exists(freeifaddrs    "${CURL_INCLUDES}" HAVE_FREEIFADDRS)
 +check_symbol_exists(pipe           "${CURL_INCLUDES}" HAVE_PIPE)
 +check_symbol_exists(ftruncate      "${CURL_INCLUDES}" HAVE_FTRUNCATE)
 +check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
++check_symbol_exists(getpeername    "${CURL_INCLUDES}" HAVE_GETPEERNAME)
++check_symbol_exists(getsockname    "${CURL_INCLUDES}" HAVE_GETSOCKNAME)
 +check_symbol_exists(getrlimit      "${CURL_INCLUDES}" HAVE_GETRLIMIT)
 +check_symbol_exists(setlocale      "${CURL_INCLUDES}" HAVE_SETLOCALE)
 +check_symbol_exists(setmode        "${CURL_INCLUDES}" HAVE_SETMODE)
 +check_symbol_exists(setrlimit      "${CURL_INCLUDES}" HAVE_SETRLIMIT)
 +check_symbol_exists(fcntl          "${CURL_INCLUDES}" HAVE_FCNTL)
 +check_symbol_exists(ioctl          "${CURL_INCLUDES}" HAVE_IOCTL)
 +check_symbol_exists(setsockopt     "${CURL_INCLUDES}" HAVE_SETSOCKOPT)
 +check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME)
 +
 +# symbol exists in win32, but function does not.
 +if(WIN32)
 +  if(ENABLE_INET_PTON)
 +    check_function_exists(inet_pton HAVE_INET_PTON)
 +    # _WIN32_WINNT_VISTA (0x0600)
 +    add_definitions(-D_WIN32_WINNT=0x0600)
 +  else()
 +    # _WIN32_WINNT_WINXP (0x0501)
 +    add_definitions(-D_WIN32_WINNT=0x0501)
 +  endif()
 +else()
 +  check_function_exists(inet_pton HAVE_INET_PTON)
 +endif()
 +
 +check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR)
 +if(HAVE_FSETXATTR)
 +  foreach(CURL_TEST HAVE_FSETXATTR_5 HAVE_FSETXATTR_6)
 +    curl_internal_test(${CURL_TEST})
 +  endforeach()
 +endif()
 +
 +# sigaction and sigsetjmp are special. Use special mechanism for
 +# detecting those, but only if previous attempt failed.
 +if(HAVE_SIGNAL_H)
 +  check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
 +endif()
 +
 +if(NOT HAVE_SIGSETJMP)
 +  if(HAVE_SETJMP_H)
 +    check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP)
 +    if(HAVE_MACRO_SIGSETJMP)
 +      set(HAVE_SIGSETJMP 1)
 +    endif()
 +  endif()
 +endif()
 +
 +# If there is no stricmp(), do not allow LDAP to parse URLs
 +if(NOT HAVE_STRICMP)
 +  set(HAVE_LDAP_URL_PARSE 1)
 +endif()
 +
 +# Do curl specific tests
 +foreach(CURL_TEST
 +    HAVE_FCNTL_O_NONBLOCK
 +    HAVE_IOCTLSOCKET
 +    HAVE_IOCTLSOCKET_CAMEL
 +    HAVE_IOCTLSOCKET_CAMEL_FIONBIO
 +    HAVE_IOCTLSOCKET_FIONBIO
 +    HAVE_IOCTL_FIONBIO
 +    HAVE_IOCTL_SIOCGIFADDR
 +    HAVE_SETSOCKOPT_SO_NONBLOCK
 +    HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
 +    TIME_WITH_SYS_TIME
 +    HAVE_O_NONBLOCK
 +    HAVE_GETHOSTBYADDR_R_5
 +    HAVE_GETHOSTBYADDR_R_7
 +    HAVE_GETHOSTBYADDR_R_8
 +    HAVE_GETHOSTBYADDR_R_5_REENTRANT
 +    HAVE_GETHOSTBYADDR_R_7_REENTRANT
 +    HAVE_GETHOSTBYADDR_R_8_REENTRANT
 +    HAVE_GETHOSTBYNAME_R_3
 +    HAVE_GETHOSTBYNAME_R_5
 +    HAVE_GETHOSTBYNAME_R_6
 +    HAVE_GETHOSTBYNAME_R_3_REENTRANT
 +    HAVE_GETHOSTBYNAME_R_5_REENTRANT
 +    HAVE_GETHOSTBYNAME_R_6_REENTRANT
 +    HAVE_IN_ADDR_T
 +    HAVE_BOOL_T
 +    STDC_HEADERS
 +    RETSIGTYPE_TEST
 +    HAVE_INET_NTOA_R_DECL
 +    HAVE_INET_NTOA_R_DECL_REENTRANT
 +    HAVE_GETADDRINFO
 +    HAVE_FILE_OFFSET_BITS
++    HAVE_VARIADIC_MACROS_C99
++    HAVE_VARIADIC_MACROS_GCC
 +    )
 +  curl_internal_test(${CURL_TEST})
 +endforeach()
 +
 +if(HAVE_FILE_OFFSET_BITS)
 +  set(_FILE_OFFSET_BITS 64)
 +  set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
 +endif()
 +check_type_size("off_t"  SIZEOF_OFF_T)
 +
 +# include this header to get the type
 +set(CMAKE_REQUIRED_INCLUDES "${CURL_SOURCE_DIR}/include")
 +set(CMAKE_EXTRA_INCLUDE_FILES "curl/system.h")
 +check_type_size("curl_off_t"  SIZEOF_CURL_OFF_T)
 +set(CMAKE_EXTRA_INCLUDE_FILES "")
 +
 +set(CMAKE_REQUIRED_FLAGS)
 +
 +foreach(CURL_TEST
 +    HAVE_GLIBC_STRERROR_R
 +    HAVE_POSIX_STRERROR_R
 +    )
 +  curl_internal_test(${CURL_TEST})
 +endforeach()
 +
 +# Check for reentrant
 +foreach(CURL_TEST
 +    HAVE_GETHOSTBYADDR_R_5
 +    HAVE_GETHOSTBYADDR_R_7
 +    HAVE_GETHOSTBYADDR_R_8
 +    HAVE_GETHOSTBYNAME_R_3
 +    HAVE_GETHOSTBYNAME_R_5
 +    HAVE_GETHOSTBYNAME_R_6
 +    HAVE_INET_NTOA_R_DECL_REENTRANT)
 +  if(NOT ${CURL_TEST})
 +    if(${CURL_TEST}_REENTRANT)
 +      set(NEED_REENTRANT 1)
 +    endif()
 +  endif()
 +endforeach()
 +
 +if(NEED_REENTRANT)
 +  foreach(CURL_TEST
 +      HAVE_GETHOSTBYADDR_R_5
 +      HAVE_GETHOSTBYADDR_R_7
 +      HAVE_GETHOSTBYADDR_R_8
 +      HAVE_GETHOSTBYNAME_R_3
 +      HAVE_GETHOSTBYNAME_R_5
 +      HAVE_GETHOSTBYNAME_R_6)
 +    set(${CURL_TEST} 0)
 +    if(${CURL_TEST}_REENTRANT)
 +      set(${CURL_TEST} 1)
 +    endif()
 +  endforeach()
 +endif()
 +
 +if(HAVE_INET_NTOA_R_DECL_REENTRANT)
 +  set(HAVE_INET_NTOA_R_DECL 1)
 +  set(NEED_REENTRANT 1)
 +endif()
 +
 +# Check clock_gettime(CLOCK_MONOTONIC, x) support
 +curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC)
 +
 +# Check compiler support of __builtin_available()
 +curl_internal_test(HAVE_BUILTIN_AVAILABLE)
 +
 +# Some other minor tests
 +
 +if(NOT HAVE_IN_ADDR_T)
 +  set(in_addr_t "unsigned long")
 +endif()
 +
 +# Fix libz / zlib.h
 +
 +if(NOT CURL_SPECIAL_LIBZ)
 +  if(NOT HAVE_LIBZ)
 +    set(HAVE_ZLIB_H 0)
 +  endif()
 +
 +  if(NOT HAVE_ZLIB_H)
 +    set(HAVE_LIBZ 0)
 +  endif()
 +endif()
 +
 +# Check for nonblocking
 +set(HAVE_DISABLED_NONBLOCKING 1)
 +if(HAVE_FIONBIO OR
 +    HAVE_IOCTLSOCKET OR
 +    HAVE_IOCTLSOCKET_CASE OR
 +    HAVE_O_NONBLOCK)
 +  set(HAVE_DISABLED_NONBLOCKING)
 +endif()
 +
 +if(RETSIGTYPE_TEST)
 +  set(RETSIGTYPE void)
 +else()
 +  set(RETSIGTYPE int)
 +endif()
 +
 +if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
 +  include(CheckCCompilerFlag)
 +  check_c_compiler_flag(-Wno-long-double HAVE_C_FLAG_Wno_long_double)
 +  if(HAVE_C_FLAG_Wno_long_double)
 +    # The Mac version of GCC warns about use of long double.  Disable it.
 +    get_source_file_property(MPRINTF_COMPILE_FLAGS mprintf.c COMPILE_FLAGS)
 +    if(MPRINTF_COMPILE_FLAGS)
 +      set(MPRINTF_COMPILE_FLAGS "${MPRINTF_COMPILE_FLAGS} -Wno-long-double")
 +    else()
 +      set(MPRINTF_COMPILE_FLAGS "-Wno-long-double")
 +    endif()
 +    set_source_files_properties(mprintf.c PROPERTIES
 +      COMPILE_FLAGS ${MPRINTF_COMPILE_FLAGS})
 +  endif()
 +endif()
 +
 +# TODO test which of these headers are required
 +if(WIN32)
 +  set(CURL_PULL_WS2TCPIP_H ${HAVE_WS2TCPIP_H})
 +else()
 +  set(CURL_PULL_SYS_TYPES_H ${HAVE_SYS_TYPES_H})
 +  set(CURL_PULL_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H})
 +  set(CURL_PULL_SYS_POLL_H ${HAVE_SYS_POLL_H})
 +endif()
 +set(CURL_PULL_STDINT_H ${HAVE_STDINT_H})
 +set(CURL_PULL_INTTYPES_H ${HAVE_INTTYPES_H})
 +
 +include(CMake/OtherTests.cmake)
 +
 +add_definitions(-DHAVE_CONFIG_H)
 +
 +# For Windows, all compilers used by CMake should support large files
 +if(WIN32)
 +  set(USE_WIN32_LARGE_FILES ON)
 +
 +  # Use the manifest embedded in the Windows Resource
 +  set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DCURL_EMBED_MANIFEST")
 +endif()
 +
 +if(MSVC)
 +  # Disable default manifest added by CMake
 +  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
 +
 +  add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
 +  if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
 +    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
 +  else()
 +    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
 +  endif()
 +endif()
 +
 +if(CURL_WERROR)
 +  if(MSVC_VERSION)
 +    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
 +  else()
 +    # this assumes clang or gcc style options
 +    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
 +  endif()
 +endif()
 +
 +# Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
- function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
++function(transform_makefile_inc INPUT_FILE OUTPUT_FILE)
 +  file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
 +  string(REPLACE "$(top_srcdir)"   "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 +  string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 +
 +  string(REGEX REPLACE "\\\\\n" "!π!α!" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 +  string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "SET(\\1 \\2)" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 +  string(REPLACE "!π!α!" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 +
 +  string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace $() with ${}
 +  string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace @@ with ${}, even if that may not be read by CMake scripts.
 +  file(WRITE ${OUTPUT_FILE} ${MAKEFILE_INC_TEXT})
 +
 +endfunction()
 +
 +if(0) # This code not needed for building within CMake.
 +include(GNUInstallDirs)
 +
 +set(CURL_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
 +set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
 +set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
 +set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
 +set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
 +endif()
 +
 +if(USE_MANUAL)
 +  add_subdirectory(docs)
 +endif()
 +
 +add_subdirectory(lib)
 +
 +if(BUILD_CURL_EXE)
 +  add_subdirectory(src)
 +endif()
 +
 +#-----------------------------------------------------------------------------
 +# CMake-specific curl code.
 +add_executable(curltest curltest.c)
 +target_link_libraries(curltest cmcurl)
 +
 +if(BUILD_TESTING AND CMAKE_CURL_TEST_URL)
 +  add_test(curl curltest ${CMAKE_CURL_TEST_URL})
 +endif()
 +
 +install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmcurl)
 +#-----------------------------------------------------------------------------
 +
 +if(0) # This code not needed for building within CMake.
 +include(CTest)
 +if(BUILD_TESTING)
 +  add_subdirectory(tests)
 +endif()
 +
 +# Helper to populate a list (_items) with a label when conditions (the remaining
 +# args) are satisfied
 +function(_add_if label)
 +  # TODO need to disable policy CMP0054 (CMake 3.1) to allow this indirection
 +  if(${ARGN})
 +    set(_items ${_items} "${label}" PARENT_SCOPE)
 +  endif()
 +endfunction()
 +
 +# Clear list and try to detect available features
 +set(_items)
- _add_if("WinSSL"        SSL_ENABLED AND USE_WINDOWS_SSPI)
- _add_if("OpenSSL"       SSL_ENABLED AND USE_OPENSSL)
- _add_if("DarwinSSL"     SSL_ENABLED AND USE_DARWINSSL)
- _add_if("mbedTLS"       SSL_ENABLED AND USE_MBEDTLS)
++_add_if("SSL"           SSL_ENABLED)
 +_add_if("IPv6"          ENABLE_IPV6)
 +_add_if("unix-sockets"  USE_UNIX_SOCKETS)
 +_add_if("libz"          HAVE_LIBZ)
 +_add_if("AsynchDNS"     USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
 +_add_if("IDN"           HAVE_LIBIDN2)
 +_add_if("Largefile"     (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND
 +                        ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
 +# TODO SSP1 (WinSSL) check is missing
 +_add_if("SSPI"          USE_WINDOWS_SSPI)
 +_add_if("GSS-API"       HAVE_GSSAPI)
 +# TODO SSP1 missing for SPNEGO
 +_add_if("SPNEGO"        NOT CURL_DISABLE_CRYPTO_AUTH AND
 +                        (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
 +_add_if("Kerberos"      NOT CURL_DISABLE_CRYPTO_AUTH AND
 +                        (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
 +# NTLM support requires crypto function adaptions from various SSL libs
 +# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
- if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_DARWINSSL OR USE_MBEDTLS))
++if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_SECTRANSP OR USE_MBEDTLS))
 +  _add_if("NTLM"        1)
 +  # TODO missing option (autoconf: --enable-ntlm-wb)
 +  _add_if("NTLM_WB"     NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
 +endif()
 +# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP
 +_add_if("TLS-SRP"       USE_TLS_SRP)
 +# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
 +_add_if("HTTP2"         USE_NGHTTP2)
 +string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
 +message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
 +
 +# Clear list and try to detect available protocols
 +set(_items)
 +_add_if("HTTP"          NOT CURL_DISABLE_HTTP)
 +_add_if("HTTPS"         NOT CURL_DISABLE_HTTP AND SSL_ENABLED)
 +_add_if("FTP"           NOT CURL_DISABLE_FTP)
 +_add_if("FTPS"          NOT CURL_DISABLE_FTP AND SSL_ENABLED)
 +_add_if("FILE"          NOT CURL_DISABLE_FILE)
 +_add_if("TELNET"        NOT CURL_DISABLE_TELNET)
 +_add_if("LDAP"          NOT CURL_DISABLE_LDAP)
 +# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS
 +# TODO check HAVE_LDAP_SSL (in autoconf this is enabled with --enable-ldaps)
 +_add_if("LDAPS"         NOT CURL_DISABLE_LDAPS AND
 +                        ((USE_OPENLDAP AND SSL_ENABLED) OR
 +                        (NOT USE_OPENLDAP AND HAVE_LDAP_SSL)))
 +_add_if("DICT"          NOT CURL_DISABLE_DICT)
 +_add_if("TFTP"          NOT CURL_DISABLE_TFTP)
 +_add_if("GOPHER"        NOT CURL_DISABLE_GOPHER)
 +_add_if("POP3"          NOT CURL_DISABLE_POP3)
 +_add_if("POP3S"         NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
 +_add_if("IMAP"          NOT CURL_DISABLE_IMAP)
 +_add_if("IMAPS"         NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
 +_add_if("SMTP"          NOT CURL_DISABLE_SMTP)
 +_add_if("SMTPS"         NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
 +_add_if("SCP"           USE_LIBSSH2)
 +_add_if("SFTP"          USE_LIBSSH2)
 +_add_if("RTSP"          NOT CURL_DISABLE_RTSP)
 +_add_if("RTMP"          USE_LIBRTMP)
- list(SORT _items)
++if(_items)
++  list(SORT _items)
++endif()
 +string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
 +message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
 +
++# Clear list and collect SSL backends
++set(_items)
++_add_if("WinSSL"           SSL_ENABLED AND USE_WINDOWS_SSPI)
++_add_if("OpenSSL"          SSL_ENABLED AND USE_OPENSSL)
++_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
++_add_if("mbedTLS"          SSL_ENABLED AND USE_MBEDTLS)
++if(_items)
++  list(SORT _items)
++endif()
++string(REPLACE ";" " " SSL_BACKENDS "${_items}")
++message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
++
 +# curl-config needs the following options to be set.
 +set(CC                      "${CMAKE_C_COMPILER}")
 +# TODO probably put a -D... options here?
 +set(CONFIGURE_OPTIONS       "")
 +# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
 +set(CPPFLAG_CURL_STATICLIB  "")
 +set(CURLVERSION             "${CURL_VERSION}")
 +if(BUILD_SHARED_LIBS)
 +  set(ENABLE_SHARED         "yes")
 +  set(ENABLE_STATIC         "no")
 +else()
 +  set(ENABLE_SHARED         "no")
 +  set(ENABLE_STATIC         "yes")
 +endif()
 +set(exec_prefix             "\${prefix}")
 +set(includedir              "\${prefix}/include")
 +set(LDFLAGS                 "${CMAKE_SHARED_LINKER_FLAGS}")
 +set(LIBCURL_LIBS            "")
 +set(libdir                  "${CMAKE_INSTALL_PREFIX}/lib")
 +foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
 +  if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-")
 +    set(LIBCURL_LIBS          "${LIBCURL_LIBS} ${_lib}")
 +  else()
 +    set(LIBCURL_LIBS          "${LIBCURL_LIBS} -l${_lib}")
 +  endif()
 +endforeach()
 +# "a" (Linux) or "lib" (Windows)
 +string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
 +set(prefix                  "${CMAKE_INSTALL_PREFIX}")
 +# Set this to "yes" to append all libraries on which -lcurl is dependent
 +set(REQUIRE_LIB_DEPS        "no")
 +# SUPPORT_FEATURES
 +# SUPPORT_PROTOCOLS
 +set(VERSIONNUM              "${CURL_VERSION_NUM}")
 +
 +# Finally generate a "curl-config" matching this config
 +# Use:
 +# * ENABLE_SHARED
 +# * ENABLE_STATIC
 +configure_file("${CURL_SOURCE_DIR}/curl-config.in"
 +               "${CURL_BINARY_DIR}/curl-config" @ONLY)
 +install(FILES "${CURL_BINARY_DIR}/curl-config"
 +        DESTINATION ${CMAKE_INSTALL_BINDIR}
 +        PERMISSIONS
 +          OWNER_READ OWNER_WRITE OWNER_EXECUTE
 +          GROUP_READ GROUP_EXECUTE
 +          WORLD_READ WORLD_EXECUTE)
 +
 +# Finally generate a pkg-config file matching this config
 +configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in"
 +               "${CURL_BINARY_DIR}/libcurl.pc" @ONLY)
 +install(FILES "${CURL_BINARY_DIR}/libcurl.pc"
 +        DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
 +
 +# install headers
 +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl"
 +    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
 +    FILES_MATCHING PATTERN "*.h")
 +
 +include(CMakePackageConfigHelpers)
 +write_basic_package_version_file(
 +    "${version_config}"
 +    VERSION ${CURL_VERSION}
 +    COMPATIBILITY SameMajorVersion
 +)
 +
 +# Use:
 +# * TARGETS_EXPORT_NAME
 +# * PROJECT_NAME
 +configure_package_config_file(CMake/curl-config.cmake.in
 +        "${project_config}"
 +        INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR}
 +)
 +
 +install(
 +        EXPORT "${TARGETS_EXPORT_NAME}"
 +        NAMESPACE "${PROJECT_NAME}::"
 +        DESTINATION ${CURL_INSTALL_CMAKE_DIR}
 +)
 +
 +install(
 +        FILES ${version_config} ${project_config}
 +        DESTINATION ${CURL_INSTALL_CMAKE_DIR}
 +)
 +
 +# Workaround for MSVS10 to avoid the Dialog Hell
 +# FIXME: This could be removed with future version of CMake.
 +if(MSVC_VERSION EQUAL 1600)
 +  set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln")
 +  if(EXISTS "${CURL_SLN_FILENAME}")
 +    file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n")
 +  endif()
 +endif()
 +
 +if(NOT TARGET uninstall)
 +  configure_file(
 +      ${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in
 +      ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake
 +      IMMEDIATE @ONLY)
 +
 +  add_custom_target(uninstall
 +      COMMAND ${CMAKE_COMMAND} -P
 +      ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake)
 +endif()
 +endif()
diff --cc Utilities/cmcurl/include/curl/curl.h
index 63bb291,0000000..089c427
mode 100644,000000..100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@@ -1,2819 -1,0 +1,2869 @@@
 +#ifndef __CURL_CURL_H
 +#define __CURL_CURL_H
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
-  * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
++ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
 + *
 + * This software is licensed as described in the file COPYING, which
 + * you should have received as part of this distribution. The terms
 + * are also available at https://curl.haxx.se/docs/copyright.html.
 + *
 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 + * copies of the Software, and permit persons to whom the Software is
 + * furnished to do so, under the terms of the COPYING file.
 + *
 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 + * KIND, either express or implied.
 + *
 + ***************************************************************************/
 +
 +/*
 + * If you have libcurl problems, all docs and details are found here:
 + *   https://curl.haxx.se/libcurl/
 + *
 + * curl-library mailing list subscription and unsubscription web interface:
 + *   https://cool.haxx.se/mailman/listinfo/curl-library/
 + */
 +
 +#ifdef CURL_NO_OLDIES
 +#define CURL_STRICTER
 +#endif
 +
 +#include "curlver.h"         /* libcurl version defines   */
 +#include "system.h"          /* determine things run-time */
 +
 +/*
 + * Define WIN32 when build target is Win32 API
 + */
 +
 +#if (defined(_WIN32) || defined(__WIN32__)) && \
 +     !defined(WIN32) && !defined(__SYMBIAN32__)
 +#define WIN32
 +#endif
 +
 +#include <stdio.h>
 +#include <limits.h>
 +
 +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2)
 +/* Needed for __FreeBSD_version symbol definition */
 +#include <osreldate.h>
 +#endif
 +
 +/* The include stuff here below is mainly for time_t! */
 +#include <sys/types.h>
 +#include <time.h>
 +
 +#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
 +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \
 +      defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H))
 +/* The check above prevents the winsock2 inclusion if winsock.h already was
 +   included, since they can't co-exist without problems */
 +#include <winsock2.h>
 +#include <ws2tcpip.h>
 +#endif
 +#endif
 +
 +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
 +   libc5-based Linux systems. Only include it on systems that are known to
 +   require it! */
 +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
 +    defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
 +    defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
 +    defined(__CYGWIN__) || \
 +   (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
 +#include <sys/select.h>
 +#endif
 +
 +#if !defined(WIN32) && !defined(_WIN32_WCE)
 +#include <sys/socket.h>
 +#endif
 +
 +#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
 +#include <sys/time.h>
 +#endif
 +
 +#if defined __BEOS__ || defined __HAIKU__
 +#include <support/SupportDefs.h>
 +#endif
 +
++/* Compatibility for non-Clang compilers */
++#ifndef __has_declspec_attribute
++#  define __has_declspec_attribute(x) 0
++#endif
++
 +#ifdef  __cplusplus
 +extern "C" {
 +#endif
 +
 +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
 +typedef struct Curl_easy CURL;
 +typedef struct Curl_share CURLSH;
 +#else
 +typedef void CURL;
 +typedef void CURLSH;
 +#endif
 +
 +/*
 + * libcurl external API function linkage decorations.
 + */
 +
 +#ifdef CURL_STATICLIB
 +#  define CURL_EXTERN
- #elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)
++#elif defined(WIN32) || defined(__SYMBIAN32__) || \
++     (__has_declspec_attribute(dllexport) && \
++      __has_declspec_attribute(dllimport))
 +#  if defined(BUILDING_LIBCURL)
 +#    define CURL_EXTERN  __declspec(dllexport)
 +#  else
 +#    define CURL_EXTERN  __declspec(dllimport)
 +#  endif
 +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS)
 +#  define CURL_EXTERN CURL_EXTERN_SYMBOL
 +#else
 +#  define CURL_EXTERN
 +#endif
 +
 +#ifndef curl_socket_typedef
 +/* socket typedef */
 +#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
 +typedef SOCKET curl_socket_t;
 +#define CURL_SOCKET_BAD INVALID_SOCKET
 +#else
 +typedef int curl_socket_t;
 +#define CURL_SOCKET_BAD -1
 +#endif
 +#define curl_socket_typedef
 +#endif /* curl_socket_typedef */
 +
 +/* enum for the different supported SSL backends */
 +typedef enum {
 +  CURLSSLBACKEND_NONE = 0,
 +  CURLSSLBACKEND_OPENSSL = 1,
 +  CURLSSLBACKEND_GNUTLS = 2,
 +  CURLSSLBACKEND_NSS = 3,
 +  CURLSSLBACKEND_OBSOLETE4 = 4,  /* Was QSOSSL. */
 +  CURLSSLBACKEND_GSKIT = 5,
 +  CURLSSLBACKEND_POLARSSL = 6,
 +  CURLSSLBACKEND_WOLFSSL = 7,
 +  CURLSSLBACKEND_SCHANNEL = 8,
-   CURLSSLBACKEND_DARWINSSL = 9,
-   CURLSSLBACKEND_AXTLS = 10,
++  CURLSSLBACKEND_SECURETRANSPORT = 9,
++  CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */
 +  CURLSSLBACKEND_MBEDTLS = 11,
 +  CURLSSLBACKEND_MESALINK = 12
 +} curl_sslbackend;
 +
 +/* aliases for library clones and renames */
 +#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
 +#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
++
++/* deprecated names: */
 +#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
++#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT
 +
 +struct curl_httppost {
 +  struct curl_httppost *next;       /* next entry in the list */
 +  char *name;                       /* pointer to allocated name */
 +  long namelength;                  /* length of name length */
 +  char *contents;                   /* pointer to allocated data contents */
 +  long contentslength;              /* length of contents field, see also
 +                                       CURL_HTTPPOST_LARGE */
 +  char *buffer;                     /* pointer to allocated buffer contents */
 +  long bufferlength;                /* length of buffer field */
 +  char *contenttype;                /* Content-Type */
 +  struct curl_slist *contentheader; /* list of extra headers for this form */
 +  struct curl_httppost *more;       /* if one field name has more than one
 +                                       file, this link should link to following
 +                                       files */
 +  long flags;                       /* as defined below */
 +
 +/* specified content is a file name */
 +#define CURL_HTTPPOST_FILENAME (1<<0)
 +/* specified content is a file name */
 +#define CURL_HTTPPOST_READFILE (1<<1)
 +/* name is only stored pointer do not free in formfree */
 +#define CURL_HTTPPOST_PTRNAME (1<<2)
 +/* contents is only stored pointer do not free in formfree */
 +#define CURL_HTTPPOST_PTRCONTENTS (1<<3)
 +/* upload file from buffer */
 +#define CURL_HTTPPOST_BUFFER (1<<4)
 +/* upload file from pointer contents */
 +#define CURL_HTTPPOST_PTRBUFFER (1<<5)
 +/* upload file contents by using the regular read callback to get the data and
 +   pass the given pointer as custom pointer */
 +#define CURL_HTTPPOST_CALLBACK (1<<6)
 +/* use size in 'contentlen', added in 7.46.0 */
 +#define CURL_HTTPPOST_LARGE (1<<7)
 +
 +  char *showfilename;               /* The file name to show. If not set, the
 +                                       actual file name will be used (if this
 +                                       is a file part) */
 +  void *userp;                      /* custom pointer used for
 +                                       HTTPPOST_CALLBACK posts */
 +  curl_off_t contentlen;            /* alternative length of contents
 +                                       field. Used if CURL_HTTPPOST_LARGE is
 +                                       set. Added in 7.46.0 */
 +};
 +
 +/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered
 +   deprecated but was the only choice up until 7.31.0 */
 +typedef int (*curl_progress_callback)(void *clientp,
 +                                      double dltotal,
 +                                      double dlnow,
 +                                      double ultotal,
 +                                      double ulnow);
 +
 +/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in
 +   7.32.0, it avoids floating point and provides more detailed information. */
 +typedef int (*curl_xferinfo_callback)(void *clientp,
 +                                      curl_off_t dltotal,
 +                                      curl_off_t dlnow,
 +                                      curl_off_t ultotal,
 +                                      curl_off_t ulnow);
 +
 +#ifndef CURL_MAX_READ_SIZE
 +  /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */
 +#define CURL_MAX_READ_SIZE 524288
 +#endif
 +
 +#ifndef CURL_MAX_WRITE_SIZE
 +  /* Tests have proven that 20K is a very bad buffer size for uploads on
 +     Windows, while 16K for some odd reason performed a lot better.
 +     We do the ifndef check to allow this value to easier be changed at build
 +     time for those who feel adventurous. The practical minimum is about
 +     400 bytes since libcurl uses a buffer of this size as a scratch area
 +     (unrelated to network send operations). */
 +#define CURL_MAX_WRITE_SIZE 16384
 +#endif
 +
 +#ifndef CURL_MAX_HTTP_HEADER
 +/* The only reason to have a max limit for this is to avoid the risk of a bad
 +   server feeding libcurl with a never-ending header that will cause reallocs
 +   infinitely */
 +#define CURL_MAX_HTTP_HEADER (100*1024)
 +#endif
 +
 +/* This is a magic return code for the write callback that, when returned,
 +   will signal libcurl to pause receiving on the current transfer. */
 +#define CURL_WRITEFUNC_PAUSE 0x10000001
 +
 +typedef size_t (*curl_write_callback)(char *buffer,
 +                                      size_t size,
 +                                      size_t nitems,
 +                                      void *outstream);
 +
 +/* This callback will be called when a new resolver request is made */
 +typedef int (*curl_resolver_start_callback)(void *resolver_state,
 +                                            void *reserved, void *userdata);
 +
 +/* enumeration of file types */
 +typedef enum {
 +  CURLFILETYPE_FILE = 0,
 +  CURLFILETYPE_DIRECTORY,
 +  CURLFILETYPE_SYMLINK,
 +  CURLFILETYPE_DEVICE_BLOCK,
 +  CURLFILETYPE_DEVICE_CHAR,
 +  CURLFILETYPE_NAMEDPIPE,
 +  CURLFILETYPE_SOCKET,
 +  CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
 +
 +  CURLFILETYPE_UNKNOWN /* should never occur */
 +} curlfiletype;
 +
 +#define CURLFINFOFLAG_KNOWN_FILENAME    (1<<0)
 +#define CURLFINFOFLAG_KNOWN_FILETYPE    (1<<1)
 +#define CURLFINFOFLAG_KNOWN_TIME        (1<<2)
 +#define CURLFINFOFLAG_KNOWN_PERM        (1<<3)
 +#define CURLFINFOFLAG_KNOWN_UID         (1<<4)
 +#define CURLFINFOFLAG_KNOWN_GID         (1<<5)
 +#define CURLFINFOFLAG_KNOWN_SIZE        (1<<6)
 +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT  (1<<7)
 +
 +/* Content of this structure depends on information which is known and is
 +   achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
 +   page for callbacks returning this structure -- some fields are mandatory,
 +   some others are optional. The FLAG field has special meaning. */
 +struct curl_fileinfo {
 +  char *filename;
 +  curlfiletype filetype;
-   time_t time;
++  time_t time; /* always zero! */
 +  unsigned int perm;
 +  int uid;
 +  int gid;
 +  curl_off_t size;
 +  long int hardlinks;
 +
 +  struct {
 +    /* If some of these fields is not NULL, it is a pointer to b_data. */
 +    char *time;
 +    char *perm;
 +    char *user;
 +    char *group;
 +    char *target; /* pointer to the target filename of a symlink */
 +  } strings;
 +
 +  unsigned int flags;
 +
 +  /* used internally */
 +  char *b_data;
 +  size_t b_size;
 +  size_t b_used;
 +};
 +
 +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
 +#define CURL_CHUNK_BGN_FUNC_OK      0
 +#define CURL_CHUNK_BGN_FUNC_FAIL    1 /* tell the lib to end the task */
 +#define CURL_CHUNK_BGN_FUNC_SKIP    2 /* skip this chunk over */
 +
 +/* if splitting of data transfer is enabled, this callback is called before
 +   download of an individual chunk started. Note that parameter "remains" works
 +   only for FTP wildcard downloading (for now), otherwise is not used */
 +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
 +                                        void *ptr,
 +                                        int remains);
 +
 +/* return codes for CURLOPT_CHUNK_END_FUNCTION */
 +#define CURL_CHUNK_END_FUNC_OK      0
 +#define CURL_CHUNK_END_FUNC_FAIL    1 /* tell the lib to end the task */
 +
 +/* If splitting of data transfer is enabled this callback is called after
 +   download of an individual chunk finished.
 +   Note! After this callback was set then it have to be called FOR ALL chunks.
 +   Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
 +   This is the reason why we don't need "transfer_info" parameter in this
 +   callback and we are not interested in "remains" parameter too. */
 +typedef long (*curl_chunk_end_callback)(void *ptr);
 +
 +/* return codes for FNMATCHFUNCTION */
 +#define CURL_FNMATCHFUNC_MATCH    0 /* string corresponds to the pattern */
 +#define CURL_FNMATCHFUNC_NOMATCH  1 /* pattern doesn't match the string */
 +#define CURL_FNMATCHFUNC_FAIL     2 /* an error occurred */
 +
 +/* callback type for wildcard downloading pattern matching. If the
 +   string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
 +typedef int (*curl_fnmatch_callback)(void *ptr,
 +                                     const char *pattern,
 +                                     const char *string);
 +
 +/* These are the return codes for the seek callbacks */
 +#define CURL_SEEKFUNC_OK       0
 +#define CURL_SEEKFUNC_FAIL     1 /* fail the entire transfer */
 +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
 +                                    libcurl might try other means instead */
 +typedef int (*curl_seek_callback)(void *instream,
 +                                  curl_off_t offset,
 +                                  int origin); /* 'whence' */
 +
 +/* This is a return code for the read callback that, when returned, will
 +   signal libcurl to immediately abort the current transfer. */
 +#define CURL_READFUNC_ABORT 0x10000000
 +/* This is a return code for the read callback that, when returned, will
 +   signal libcurl to pause sending data on the current transfer. */
 +#define CURL_READFUNC_PAUSE 0x10000001
 +
++/* Return code for when the trailing headers' callback has terminated
++   without any errors*/
++#define CURL_TRAILERFUNC_OK 0
++/* Return code for when was an error in the trailing header's list and we
++  want to abort the request */
++#define CURL_TRAILERFUNC_ABORT 1
++
 +typedef size_t (*curl_read_callback)(char *buffer,
 +                                      size_t size,
 +                                      size_t nitems,
 +                                      void *instream);
 +
++typedef int (*curl_trailer_callback)(struct curl_slist **list,
++                                      void *userdata);
++
 +typedef enum {
 +  CURLSOCKTYPE_IPCXN,  /* socket created for a specific IP connection */
 +  CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
 +  CURLSOCKTYPE_LAST    /* never use */
 +} curlsocktype;
 +
 +/* The return code from the sockopt_callback can signal information back
 +   to libcurl: */
 +#define CURL_SOCKOPT_OK 0
 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
 +                                CURLE_ABORTED_BY_CALLBACK */
 +#define CURL_SOCKOPT_ALREADY_CONNECTED 2
 +
 +typedef int (*curl_sockopt_callback)(void *clientp,
 +                                     curl_socket_t curlfd,
 +                                     curlsocktype purpose);
 +
 +struct curl_sockaddr {
 +  int family;
 +  int socktype;
 +  int protocol;
 +  unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it
 +                           turned really ugly and painful on the systems that
 +                           lack this type */
 +  struct sockaddr addr;
 +};
 +
 +typedef curl_socket_t
 +(*curl_opensocket_callback)(void *clientp,
 +                            curlsocktype purpose,
 +                            struct curl_sockaddr *address);
 +
 +typedef int
 +(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
 +
 +typedef enum {
 +  CURLIOE_OK,            /* I/O operation successful */
 +  CURLIOE_UNKNOWNCMD,    /* command was unknown to callback */
 +  CURLIOE_FAILRESTART,   /* failed to restart the read */
 +  CURLIOE_LAST           /* never use */
 +} curlioerr;
 +
 +typedef enum {
 +  CURLIOCMD_NOP,         /* no operation */
 +  CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
 +  CURLIOCMD_LAST         /* never use */
 +} curliocmd;
 +
 +typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
 +                                         int cmd,
 +                                         void *clientp);
 +
 +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS
 +/*
 + * The following typedef's are signatures of malloc, free, realloc, strdup and
 + * calloc respectively.  Function pointers of these types can be passed to the
 + * curl_global_init_mem() function to set user defined memory management
 + * callback routines.
 + */
 +typedef void *(*curl_malloc_callback)(size_t size);
 +typedef void (*curl_free_callback)(void *ptr);
 +typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
 +typedef char *(*curl_strdup_callback)(const char *str);
 +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
 +
 +#define CURL_DID_MEMORY_FUNC_TYPEDEFS
 +#endif
 +
 +/* the kind of data that is passed to information_callback*/
 +typedef enum {
 +  CURLINFO_TEXT = 0,
 +  CURLINFO_HEADER_IN,    /* 1 */
 +  CURLINFO_HEADER_OUT,   /* 2 */
 +  CURLINFO_DATA_IN,      /* 3 */
 +  CURLINFO_DATA_OUT,     /* 4 */
 +  CURLINFO_SSL_DATA_IN,  /* 5 */
 +  CURLINFO_SSL_DATA_OUT, /* 6 */
 +  CURLINFO_END
 +} curl_infotype;
 +
 +typedef int (*curl_debug_callback)
 +       (CURL *handle,      /* the handle/transfer this concerns */
 +        curl_infotype type, /* what kind of data */
 +        char *data,        /* points to the data */
 +        size_t size,       /* size of the data pointed to */
 +        void *userptr);    /* whatever the user please */
 +
 +/* All possible error codes from all sorts of curl functions. Future versions
 +   may return other values, stay prepared.
 +
 +   Always add new return codes last. Never *EVER* remove any. The return
 +   codes must remain the same!
 + */
 +
 +typedef enum {
 +  CURLE_OK = 0,
 +  CURLE_UNSUPPORTED_PROTOCOL,    /* 1 */
 +  CURLE_FAILED_INIT,             /* 2 */
 +  CURLE_URL_MALFORMAT,           /* 3 */
 +  CURLE_NOT_BUILT_IN,            /* 4 - [was obsoleted in August 2007 for
 +                                    7.17.0, reused in April 2011 for 7.21.5] */
 +  CURLE_COULDNT_RESOLVE_PROXY,   /* 5 */
 +  CURLE_COULDNT_RESOLVE_HOST,    /* 6 */
 +  CURLE_COULDNT_CONNECT,         /* 7 */
 +  CURLE_WEIRD_SERVER_REPLY,      /* 8 */
 +  CURLE_REMOTE_ACCESS_DENIED,    /* 9 a service was denied by the server
 +                                    due to lack of access - when login fails
 +                                    this is not returned. */
 +  CURLE_FTP_ACCEPT_FAILED,       /* 10 - [was obsoleted in April 2006 for
 +                                    7.15.4, reused in Dec 2011 for 7.24.0]*/
 +  CURLE_FTP_WEIRD_PASS_REPLY,    /* 11 */
 +  CURLE_FTP_ACCEPT_TIMEOUT,      /* 12 - timeout occurred accepting server
 +                                    [was obsoleted in August 2007 for 7.17.0,
 +                                    reused in Dec 2011 for 7.24.0]*/
 +  CURLE_FTP_WEIRD_PASV_REPLY,    /* 13 */
 +  CURLE_FTP_WEIRD_227_FORMAT,    /* 14 */
 +  CURLE_FTP_CANT_GET_HOST,       /* 15 */
 +  CURLE_HTTP2,                   /* 16 - A problem in the http2 framing layer.
 +                                    [was obsoleted in August 2007 for 7.17.0,
 +                                    reused in July 2014 for 7.38.0] */
 +  CURLE_FTP_COULDNT_SET_TYPE,    /* 17 */
 +  CURLE_PARTIAL_FILE,            /* 18 */
 +  CURLE_FTP_COULDNT_RETR_FILE,   /* 19 */
 +  CURLE_OBSOLETE20,              /* 20 - NOT USED */
 +  CURLE_QUOTE_ERROR,             /* 21 - quote command failure */
 +  CURLE_HTTP_RETURNED_ERROR,     /* 22 */
 +  CURLE_WRITE_ERROR,             /* 23 */
 +  CURLE_OBSOLETE24,              /* 24 - NOT USED */
 +  CURLE_UPLOAD_FAILED,           /* 25 - failed upload "command" */
 +  CURLE_READ_ERROR,              /* 26 - couldn't open/read from file */
 +  CURLE_OUT_OF_MEMORY,           /* 27 */
 +  /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
 +           instead of a memory allocation error if CURL_DOES_CONVERSIONS
 +           is defined
 +  */
 +  CURLE_OPERATION_TIMEDOUT,      /* 28 - the timeout time was reached */
 +  CURLE_OBSOLETE29,              /* 29 - NOT USED */
 +  CURLE_FTP_PORT_FAILED,         /* 30 - FTP PORT operation failed */
 +  CURLE_FTP_COULDNT_USE_REST,    /* 31 - the REST command failed */
 +  CURLE_OBSOLETE32,              /* 32 - NOT USED */
 +  CURLE_RANGE_ERROR,             /* 33 - RANGE "command" didn't work */
 +  CURLE_HTTP_POST_ERROR,         /* 34 */
 +  CURLE_SSL_CONNECT_ERROR,       /* 35 - wrong when connecting with SSL */
 +  CURLE_BAD_DOWNLOAD_RESUME,     /* 36 - couldn't resume download */
 +  CURLE_FILE_COULDNT_READ_FILE,  /* 37 */
 +  CURLE_LDAP_CANNOT_BIND,        /* 38 */
 +  CURLE_LDAP_SEARCH_FAILED,      /* 39 */
 +  CURLE_OBSOLETE40,              /* 40 - NOT USED */
 +  CURLE_FUNCTION_NOT_FOUND,      /* 41 - NOT USED starting with 7.53.0 */
 +  CURLE_ABORTED_BY_CALLBACK,     /* 42 */
 +  CURLE_BAD_FUNCTION_ARGUMENT,   /* 43 */
 +  CURLE_OBSOLETE44,              /* 44 - NOT USED */
 +  CURLE_INTERFACE_FAILED,        /* 45 - CURLOPT_INTERFACE failed */
 +  CURLE_OBSOLETE46,              /* 46 - NOT USED */
 +  CURLE_TOO_MANY_REDIRECTS,      /* 47 - catch endless re-direct loops */
 +  CURLE_UNKNOWN_OPTION,          /* 48 - User specified an unknown option */
 +  CURLE_TELNET_OPTION_SYNTAX,    /* 49 - Malformed telnet option */
 +  CURLE_OBSOLETE50,              /* 50 - NOT USED */
 +  CURLE_OBSOLETE51,              /* 51 - NOT USED */
 +  CURLE_GOT_NOTHING,             /* 52 - when this is a specific error */
 +  CURLE_SSL_ENGINE_NOTFOUND,     /* 53 - SSL crypto engine not found */
 +  CURLE_SSL_ENGINE_SETFAILED,    /* 54 - can not set SSL crypto engine as
 +                                    default */
 +  CURLE_SEND_ERROR,              /* 55 - failed sending network data */
 +  CURLE_RECV_ERROR,              /* 56 - failure in receiving network data */
 +  CURLE_OBSOLETE57,              /* 57 - NOT IN USE */
 +  CURLE_SSL_CERTPROBLEM,         /* 58 - problem with the local certificate */
 +  CURLE_SSL_CIPHER,              /* 59 - couldn't use specified cipher */
 +  CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint
 +                                     wasn't verified fine */
 +  CURLE_BAD_CONTENT_ENCODING,    /* 61 - Unrecognized/bad encoding */
 +  CURLE_LDAP_INVALID_URL,        /* 62 - Invalid LDAP URL */
 +  CURLE_FILESIZE_EXCEEDED,       /* 63 - Maximum file size exceeded */
 +  CURLE_USE_SSL_FAILED,          /* 64 - Requested FTP SSL level failed */
 +  CURLE_SEND_FAIL_REWIND,        /* 65 - Sending the data requires a rewind
 +                                    that failed */
 +  CURLE_SSL_ENGINE_INITFAILED,   /* 66 - failed to initialise ENGINE */
 +  CURLE_LOGIN_DENIED,            /* 67 - user, password or similar was not
 +                                    accepted and we failed to login */
 +  CURLE_TFTP_NOTFOUND,           /* 68 - file not found on server */
 +  CURLE_TFTP_PERM,               /* 69 - permission problem on server */
 +  CURLE_REMOTE_DISK_FULL,        /* 70 - out of disk space on server */
 +  CURLE_TFTP_ILLEGAL,            /* 71 - Illegal TFTP operation */
 +  CURLE_TFTP_UNKNOWNID,          /* 72 - Unknown transfer ID */
 +  CURLE_REMOTE_FILE_EXISTS,      /* 73 - File already exists */
 +  CURLE_TFTP_NOSUCHUSER,         /* 74 - No such user */
 +  CURLE_CONV_FAILED,             /* 75 - conversion failed */
 +  CURLE_CONV_REQD,               /* 76 - caller must register conversion
 +                                    callbacks using curl_easy_setopt options
 +                                    CURLOPT_CONV_FROM_NETWORK_FUNCTION,
 +                                    CURLOPT_CONV_TO_NETWORK_FUNCTION, and
 +                                    CURLOPT_CONV_FROM_UTF8_FUNCTION */
 +  CURLE_SSL_CACERT_BADFILE,      /* 77 - could not load CACERT file, missing
 +                                    or wrong format */
 +  CURLE_REMOTE_FILE_NOT_FOUND,   /* 78 - remote file not found */
 +  CURLE_SSH,                     /* 79 - error from the SSH layer, somewhat
 +                                    generic so the error message will be of
 +                                    interest when this has happened */
 +
 +  CURLE_SSL_SHUTDOWN_FAILED,     /* 80 - Failed to shut down the SSL
 +                                    connection */
 +  CURLE_AGAIN,                   /* 81 - socket is not ready for send/recv,
 +                                    wait till it's ready and try again (Added
 +                                    in 7.18.2) */
 +  CURLE_SSL_CRL_BADFILE,         /* 82 - could not load CRL file, missing or
 +                                    wrong format (Added in 7.19.0) */
 +  CURLE_SSL_ISSUER_ERROR,        /* 83 - Issuer check failed.  (Added in
 +                                    7.19.0) */
 +  CURLE_FTP_PRET_FAILED,         /* 84 - a PRET command failed */
 +  CURLE_RTSP_CSEQ_ERROR,         /* 85 - mismatch of RTSP CSeq numbers */
 +  CURLE_RTSP_SESSION_ERROR,      /* 86 - mismatch of RTSP Session Ids */
 +  CURLE_FTP_BAD_FILE_LIST,       /* 87 - unable to parse FTP file list */
 +  CURLE_CHUNK_FAILED,            /* 88 - chunk callback reported error */
 +  CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
 +                                    session will be queued */
 +  CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
 +                                     match */
 +  CURLE_SSL_INVALIDCERTSTATUS,   /* 91 - invalid certificate status */
 +  CURLE_HTTP2_STREAM,            /* 92 - stream error in HTTP/2 framing layer
 +                                    */
 +  CURLE_RECURSIVE_API_CALL,      /* 93 - an api function was called from
 +                                    inside a callback */
 +  CURL_LAST /* never use! */
 +} CURLcode;
 +
- /* added in 7.62.0 */
- #define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
- 
 +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
 +                          the obsolete stuff removed! */
 +
 +/* Previously obsolete error code re-used in 7.38.0 */
 +#define CURLE_OBSOLETE16 CURLE_HTTP2
 +
 +/* Previously obsolete error codes re-used in 7.24.0 */
 +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
 +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
 +
 +/*  compatibility with older names */
 +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
 +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
 +
++/* The following were added in 7.62.0 */
++#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
++
 +/* The following were added in 7.21.5, April 2011 */
 +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
 +
 +/* The following were added in 7.17.1 */
 +/* These are scheduled to disappear by 2009 */
 +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION
 +
 +/* The following were added in 7.17.0 */
 +/* These are scheduled to disappear by 2009 */
 +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */
 +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16
 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32
 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29
 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12
 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20
 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40
 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24
 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57
 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN
 +
 +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED
 +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE
 +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
 +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
 +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
 +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
 +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
 +
 +/* The following were added earlier */
 +
 +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT
 +
 +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
 +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
 +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED
 +
 +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
 +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
 +
 +/* This was the error code 50 in 7.7.3 and a few earlier versions, this
 +   is no longer used by libcurl but is instead #defined here only to not
 +   make programs break */
 +#define CURLE_ALREADY_COMPLETE 99999
 +
 +/* Provide defines for really old option names */
 +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */
 +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */
 +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA
 +
 +/* Since long deprecated options with no code in the lib that does anything
 +   with them. */
 +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
 +
 +#endif /*!CURL_NO_OLDIES*/
 +
 +/* This prototype applies to all conversion callbacks */
 +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
 +
 +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl,    /* easy handle */
 +                                          void *ssl_ctx, /* actually an
 +                                                            OpenSSL SSL_CTX */
 +                                          void *userptr);
 +
 +typedef enum {
 +  CURLPROXY_HTTP = 0,   /* added in 7.10, new in 7.19.4 default is to use
 +                           CONNECT HTTP/1.1 */
 +  CURLPROXY_HTTP_1_0 = 1,   /* added in 7.19.4, force to use CONNECT
 +                               HTTP/1.0  */
 +  CURLPROXY_HTTPS = 2, /* added in 7.52.0 */
 +  CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
 +                           in 7.10 */
 +  CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
 +  CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */
 +  CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the
 +                                   host name rather than the IP address. added
 +                                   in 7.18.0 */
 +} curl_proxytype;  /* this enum was added in 7.10 */
 +
 +/*
 + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options:
 + *
 + * CURLAUTH_NONE         - No HTTP authentication
 + * CURLAUTH_BASIC        - HTTP Basic authentication (default)
 + * CURLAUTH_DIGEST       - HTTP Digest authentication
 + * CURLAUTH_NEGOTIATE    - HTTP Negotiate (SPNEGO) authentication
 + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated)
 + * CURLAUTH_NTLM         - HTTP NTLM authentication
 + * CURLAUTH_DIGEST_IE    - HTTP Digest authentication with IE flavour
 + * CURLAUTH_NTLM_WB      - HTTP NTLM authentication delegated to winbind helper
 + * CURLAUTH_BEARER       - HTTP Bearer token authentication
 + * CURLAUTH_ONLY         - Use together with a single other type to force no
 + *                         authentication or just that single type
 + * CURLAUTH_ANY          - All fine types set
 + * CURLAUTH_ANYSAFE      - All fine types except Basic
 + */
 +
 +#define CURLAUTH_NONE         ((unsigned long)0)
 +#define CURLAUTH_BASIC        (((unsigned long)1)<<0)
 +#define CURLAUTH_DIGEST       (((unsigned long)1)<<1)
 +#define CURLAUTH_NEGOTIATE    (((unsigned long)1)<<2)
 +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */
 +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
 +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */
 +#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE
 +#define CURLAUTH_NTLM         (((unsigned long)1)<<3)
 +#define CURLAUTH_DIGEST_IE    (((unsigned long)1)<<4)
 +#define CURLAUTH_NTLM_WB      (((unsigned long)1)<<5)
 +#define CURLAUTH_BEARER       (((unsigned long)1)<<6)
 +#define CURLAUTH_ONLY         (((unsigned long)1)<<31)
 +#define CURLAUTH_ANY          (~CURLAUTH_DIGEST_IE)
 +#define CURLAUTH_ANYSAFE      (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
 +
 +#define CURLSSH_AUTH_ANY       ~0     /* all types supported by the server */
 +#define CURLSSH_AUTH_NONE      0      /* none allowed, silly but complete */
 +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */
 +#define CURLSSH_AUTH_PASSWORD  (1<<1) /* password */
 +#define CURLSSH_AUTH_HOST      (1<<2) /* host key files */
 +#define CURLSSH_AUTH_KEYBOARD  (1<<3) /* keyboard interactive */
 +#define CURLSSH_AUTH_AGENT     (1<<4) /* agent (ssh-agent, pageant...) */
 +#define CURLSSH_AUTH_GSSAPI    (1<<5) /* gssapi (kerberos, ...) */
 +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
 +
 +#define CURLGSSAPI_DELEGATION_NONE        0      /* no delegation (default) */
 +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */
 +#define CURLGSSAPI_DELEGATION_FLAG        (1<<1) /* delegate always */
 +
 +#define CURL_ERROR_SIZE 256
 +
 +enum curl_khtype {
 +  CURLKHTYPE_UNKNOWN,
 +  CURLKHTYPE_RSA1,
 +  CURLKHTYPE_RSA,
 +  CURLKHTYPE_DSS,
 +  CURLKHTYPE_ECDSA,
 +  CURLKHTYPE_ED25519
 +};
 +
 +struct curl_khkey {
 +  const char *key; /* points to a zero-terminated string encoded with base64
 +                      if len is zero, otherwise to the "raw" data */
 +  size_t len;
 +  enum curl_khtype keytype;
 +};
 +
 +/* this is the set of return values expected from the curl_sshkeycallback
 +   callback */
 +enum curl_khstat {
 +  CURLKHSTAT_FINE_ADD_TO_FILE,
 +  CURLKHSTAT_FINE,
 +  CURLKHSTAT_REJECT, /* reject the connection, return an error */
 +  CURLKHSTAT_DEFER,  /* do not accept it, but we can't answer right now so
 +                        this causes a CURLE_DEFER error but otherwise the
 +                        connection will be left intact etc */
 +  CURLKHSTAT_LAST    /* not for use, only a marker for last-in-list */
 +};
 +
 +/* this is the set of status codes pass in to the callback */
 +enum curl_khmatch {
 +  CURLKHMATCH_OK,       /* match */
 +  CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
 +  CURLKHMATCH_MISSING,  /* no matching host/key found */
 +  CURLKHMATCH_LAST      /* not for use, only a marker for last-in-list */
 +};
 +
 +typedef int
 +  (*curl_sshkeycallback) (CURL *easy,     /* easy handle */
 +                          const struct curl_khkey *knownkey, /* known */
 +                          const struct curl_khkey *foundkey, /* found */
 +                          enum curl_khmatch, /* libcurl's view on the keys */
 +                          void *clientp); /* custom pointer passed from app */
 +
 +/* parameter for the CURLOPT_USE_SSL option */
 +typedef enum {
 +  CURLUSESSL_NONE,    /* do not attempt to use SSL */
 +  CURLUSESSL_TRY,     /* try using SSL, proceed anyway otherwise */
 +  CURLUSESSL_CONTROL, /* SSL for the control connection or fail */
 +  CURLUSESSL_ALL,     /* SSL for all communication or fail */
 +  CURLUSESSL_LAST     /* not an option, never use */
 +} curl_usessl;
 +
 +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */
 +
 +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the
 +   name of improving interoperability with older servers. Some SSL libraries
 +   have introduced work-arounds for this flaw but those work-arounds sometimes
 +   make the SSL communication fail. To regain functionality with those broken
 +   servers, a user can this way allow the vulnerability back. */
 +#define CURLSSLOPT_ALLOW_BEAST (1<<0)
 +
 +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those
 +   SSL backends where such behavior is present. */
 +#define CURLSSLOPT_NO_REVOKE (1<<1)
 +
 +/* The default connection attempt delay in milliseconds for happy eyeballs.
 +   CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
 +   this value, keep them in sync. */
 +#define CURL_HET_DEFAULT 200L
 +
 +/* The default connection upkeep interval in milliseconds. */
 +#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L
 +
 +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
 +                          the obsolete stuff removed! */
 +
 +/* Backwards compatibility with older names */
 +/* These are scheduled to disappear by 2009 */
 +
 +#define CURLFTPSSL_NONE CURLUSESSL_NONE
 +#define CURLFTPSSL_TRY CURLUSESSL_TRY
 +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL
 +#define CURLFTPSSL_ALL CURLUSESSL_ALL
 +#define CURLFTPSSL_LAST CURLUSESSL_LAST
 +#define curl_ftpssl curl_usessl
 +#endif /*!CURL_NO_OLDIES*/
 +
 +/* parameter for the CURLOPT_FTP_SSL_CCC option */
 +typedef enum {
 +  CURLFTPSSL_CCC_NONE,    /* do not send CCC */
 +  CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */
 +  CURLFTPSSL_CCC_ACTIVE,  /* Initiate the shutdown */
 +  CURLFTPSSL_CCC_LAST     /* not an option, never use */
 +} curl_ftpccc;
 +
 +/* parameter for the CURLOPT_FTPSSLAUTH option */
 +typedef enum {
 +  CURLFTPAUTH_DEFAULT, /* let libcurl decide */
 +  CURLFTPAUTH_SSL,     /* use "AUTH SSL" */
 +  CURLFTPAUTH_TLS,     /* use "AUTH TLS" */
 +  CURLFTPAUTH_LAST /* not an option, never use */
 +} curl_ftpauth;
 +
 +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */
 +typedef enum {
 +  CURLFTP_CREATE_DIR_NONE,  /* do NOT create missing dirs! */
 +  CURLFTP_CREATE_DIR,       /* (FTP/SFTP) if CWD fails, try MKD and then CWD
 +                               again if MKD succeeded, for SFTP this does
 +                               similar magic */
 +  CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD
 +                               again even if MKD failed! */
 +  CURLFTP_CREATE_DIR_LAST   /* not an option, never use */
 +} curl_ftpcreatedir;
 +
 +/* parameter for the CURLOPT_FTP_FILEMETHOD option */
 +typedef enum {
 +  CURLFTPMETHOD_DEFAULT,   /* let libcurl pick */
 +  CURLFTPMETHOD_MULTICWD,  /* single CWD operation for each path part */
 +  CURLFTPMETHOD_NOCWD,     /* no CWD at all */
 +  CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
 +  CURLFTPMETHOD_LAST       /* not an option, never use */
 +} curl_ftpmethod;
 +
 +/* bitmask defines for CURLOPT_HEADEROPT */
 +#define CURLHEADER_UNIFIED  0
 +#define CURLHEADER_SEPARATE (1<<0)
 +
++/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */
++#define CURLALTSVC_IMMEDIATELY  (1<<0)
++#define CURLALTSVC_ALTUSED      (1<<1)
++#define CURLALTSVC_READONLYFILE (1<<2)
++#define CURLALTSVC_H1           (1<<3)
++#define CURLALTSVC_H2           (1<<4)
++#define CURLALTSVC_H3           (1<<5)
++
 +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
 +#define CURLPROTO_HTTP   (1<<0)
 +#define CURLPROTO_HTTPS  (1<<1)
 +#define CURLPROTO_FTP    (1<<2)
 +#define CURLPROTO_FTPS   (1<<3)
 +#define CURLPROTO_SCP    (1<<4)
 +#define CURLPROTO_SFTP   (1<<5)
 +#define CURLPROTO_TELNET (1<<6)
 +#define CURLPROTO_LDAP   (1<<7)
 +#define CURLPROTO_LDAPS  (1<<8)
 +#define CURLPROTO_DICT   (1<<9)
 +#define CURLPROTO_FILE   (1<<10)
 +#define CURLPROTO_TFTP   (1<<11)
 +#define CURLPROTO_IMAP   (1<<12)
 +#define CURLPROTO_IMAPS  (1<<13)
 +#define CURLPROTO_POP3   (1<<14)
 +#define CURLPROTO_POP3S  (1<<15)
 +#define CURLPROTO_SMTP   (1<<16)
 +#define CURLPROTO_SMTPS  (1<<17)
 +#define CURLPROTO_RTSP   (1<<18)
 +#define CURLPROTO_RTMP   (1<<19)
 +#define CURLPROTO_RTMPT  (1<<20)
 +#define CURLPROTO_RTMPE  (1<<21)
 +#define CURLPROTO_RTMPTE (1<<22)
 +#define CURLPROTO_RTMPS  (1<<23)
 +#define CURLPROTO_RTMPTS (1<<24)
 +#define CURLPROTO_GOPHER (1<<25)
 +#define CURLPROTO_SMB    (1<<26)
 +#define CURLPROTO_SMBS   (1<<27)
 +#define CURLPROTO_ALL    (~0) /* enable everything */
 +
 +/* long may be 32 or 64 bits, but we should never depend on anything else
 +   but 32 */
 +#define CURLOPTTYPE_LONG          0
 +#define CURLOPTTYPE_OBJECTPOINT   10000
 +#define CURLOPTTYPE_STRINGPOINT   10000
 +#define CURLOPTTYPE_FUNCTIONPOINT 20000
 +#define CURLOPTTYPE_OFF_T         30000
 +
 +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the
 +   string options from the header file */
 +
 +/* name is uppercase CURLOPT_<name>,
 +   type is one of the defined CURLOPTTYPE_<type>
 +   number is unique identifier */
 +#ifdef CINIT
 +#undef CINIT
 +#endif
 +
 +#ifdef CURL_ISOCPP
 +#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
 +#else
 +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
 +#define LONG          CURLOPTTYPE_LONG
 +#define OBJECTPOINT   CURLOPTTYPE_OBJECTPOINT
 +#define STRINGPOINT   CURLOPTTYPE_OBJECTPOINT
 +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
 +#define OFF_T         CURLOPTTYPE_OFF_T
 +#define CINIT(name,type,number) CURLOPT_/**/name = type + number
 +#endif
 +
 +/*
 + * This macro-mania below setups the CURLOPT_[what] enum, to be used with
 + * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
 + * word.
 + */
 +
 +typedef enum {
 +  /* This is the FILE * or void * the regular output should be written to. */
 +  CINIT(WRITEDATA, OBJECTPOINT, 1),
 +
 +  /* The full URL to get/put */
 +  CINIT(URL, STRINGPOINT, 2),
 +
 +  /* Port number to connect to, if other than default. */
 +  CINIT(PORT, LONG, 3),
 +
 +  /* Name of proxy to use. */
 +  CINIT(PROXY, STRINGPOINT, 4),
 +
 +  /* "user:password;options" to use when fetching. */
 +  CINIT(USERPWD, STRINGPOINT, 5),
 +
 +  /* "user:password" to use with proxy. */
 +  CINIT(PROXYUSERPWD, STRINGPOINT, 6),
 +
 +  /* Range to get, specified as an ASCII string. */
 +  CINIT(RANGE, STRINGPOINT, 7),
 +
 +  /* not used */
 +
 +  /* Specified file stream to upload from (use as input): */
 +  CINIT(READDATA, OBJECTPOINT, 9),
 +
 +  /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
 +   * bytes big. */
 +  CINIT(ERRORBUFFER, OBJECTPOINT, 10),
 +
 +  /* Function that will be called to store the output (instead of fwrite). The
 +   * parameters will use fwrite() syntax, make sure to follow them. */
 +  CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
 +
 +  /* Function that will be called to read the input (instead of fread). The
 +   * parameters will use fread() syntax, make sure to follow them. */
 +  CINIT(READFUNCTION, FUNCTIONPOINT, 12),
 +
 +  /* Time-out the read operation after this amount of seconds */
 +  CINIT(TIMEOUT, LONG, 13),
 +
 +  /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
 +   * how large the file being sent really is. That allows better error
 +   * checking and better verifies that the upload was successful. -1 means
 +   * unknown size.
 +   *
 +   * For large file support, there is also a _LARGE version of the key
 +   * which takes an off_t type, allowing platforms with larger off_t
 +   * sizes to handle larger files.  See below for INFILESIZE_LARGE.
 +   */
 +  CINIT(INFILESIZE, LONG, 14),
 +
 +  /* POST static input fields. */
 +  CINIT(POSTFIELDS, OBJECTPOINT, 15),
 +
 +  /* Set the referrer page (needed by some CGIs) */
 +  CINIT(REFERER, STRINGPOINT, 16),
 +
 +  /* Set the FTP PORT string (interface name, named or numerical IP address)
 +     Use i.e '-' to use default address. */
 +  CINIT(FTPPORT, STRINGPOINT, 17),
 +
 +  /* Set the User-Agent string (examined by some CGIs) */
 +  CINIT(USERAGENT, STRINGPOINT, 18),
 +
 +  /* If the download receives less than "low speed limit" bytes/second
 +   * during "low speed time" seconds, the operations is aborted.
 +   * You could i.e if you have a pretty high speed connection, abort if
 +   * it is less than 2000 bytes/sec during 20 seconds.
 +   */
 +
 +  /* Set the "low speed limit" */
 +  CINIT(LOW_SPEED_LIMIT, LONG, 19),
 +
 +  /* Set the "low speed time" */
 +  CINIT(LOW_SPEED_TIME, LONG, 20),
 +
 +  /* Set the continuation offset.
 +   *
 +   * Note there is also a _LARGE version of this key which uses
 +   * off_t types, allowing for large file offsets on platforms which
 +   * use larger-than-32-bit off_t's.  Look below for RESUME_FROM_LARGE.
 +   */
 +  CINIT(RESUME_FROM, LONG, 21),
 +
 +  /* Set cookie in request: */
 +  CINIT(COOKIE, STRINGPOINT, 22),
 +
 +  /* This points to a linked list of headers, struct curl_slist kind. This
 +     list is also used for RTSP (in spite of its name) */
 +  CINIT(HTTPHEADER, OBJECTPOINT, 23),
 +
 +  /* This points to a linked list of post entries, struct curl_httppost */
 +  CINIT(HTTPPOST, OBJECTPOINT, 24),
 +
 +  /* name of the file keeping your private SSL-certificate */
 +  CINIT(SSLCERT, STRINGPOINT, 25),
 +
 +  /* password for the SSL or SSH private key */
 +  CINIT(KEYPASSWD, STRINGPOINT, 26),
 +
 +  /* send TYPE parameter? */
 +  CINIT(CRLF, LONG, 27),
 +
 +  /* send linked-list of QUOTE commands */
 +  CINIT(QUOTE, OBJECTPOINT, 28),
 +
 +  /* send FILE * or void * to store headers to, if you use a callback it
 +     is simply passed to the callback unmodified */
 +  CINIT(HEADERDATA, OBJECTPOINT, 29),
 +
 +  /* point to a file to read the initial cookies from, also enables
 +     "cookie awareness" */
 +  CINIT(COOKIEFILE, STRINGPOINT, 31),
 +
 +  /* What version to specifically try to use.
 +     See CURL_SSLVERSION defines below. */
 +  CINIT(SSLVERSION, LONG, 32),
 +
 +  /* What kind of HTTP time condition to use, see defines */
 +  CINIT(TIMECONDITION, LONG, 33),
 +
 +  /* Time to use with the above condition. Specified in number of seconds
 +     since 1 Jan 1970 */
 +  CINIT(TIMEVALUE, LONG, 34),
 +
 +  /* 35 = OBSOLETE */
 +
 +  /* Custom request, for customizing the get command like
 +     HTTP: DELETE, TRACE and others
 +     FTP: to use a different list command
 +     */
 +  CINIT(CUSTOMREQUEST, STRINGPOINT, 36),
 +
 +  /* FILE handle to use instead of stderr */
 +  CINIT(STDERR, OBJECTPOINT, 37),
 +
 +  /* 38 is not used */
 +
 +  /* send linked-list of post-transfer QUOTE commands */
 +  CINIT(POSTQUOTE, OBJECTPOINT, 39),
 +
 +  CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */
 +
 +  CINIT(VERBOSE, LONG, 41),      /* talk a lot */
 +  CINIT(HEADER, LONG, 42),       /* throw the header out too */
 +  CINIT(NOPROGRESS, LONG, 43),   /* shut off the progress meter */
 +  CINIT(NOBODY, LONG, 44),       /* use HEAD to get http document */
 +  CINIT(FAILONERROR, LONG, 45),  /* no output on http error codes >= 400 */
 +  CINIT(UPLOAD, LONG, 46),       /* this is an upload */
 +  CINIT(POST, LONG, 47),         /* HTTP POST method */
 +  CINIT(DIRLISTONLY, LONG, 48),  /* bare names when listing directories */
 +
 +  CINIT(APPEND, LONG, 50),       /* Append instead of overwrite on upload! */
 +
 +  /* Specify whether to read the user+password from the .netrc or the URL.
 +   * This must be one of the CURL_NETRC_* enums below. */
 +  CINIT(NETRC, LONG, 51),
 +
 +  CINIT(FOLLOWLOCATION, LONG, 52),  /* use Location: Luke! */
 +
 +  CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
 +  CINIT(PUT, LONG, 54),          /* HTTP PUT */
 +
 +  /* 55 = OBSOLETE */
 +
 +  /* DEPRECATED
 +   * Function that will be called instead of the internal progress display
 +   * function. This function should be defined as the curl_progress_callback
 +   * prototype defines. */
 +  CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
 +
 +  /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
 +     callbacks */
 +  CINIT(PROGRESSDATA, OBJECTPOINT, 57),
 +#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
 +
 +  /* We want the referrer field set automatically when following locations */
 +  CINIT(AUTOREFERER, LONG, 58),
 +
 +  /* Port of the proxy, can be set in the proxy string as well with:
 +     "[host]:[port]" */
 +  CINIT(PROXYPORT, LONG, 59),
 +
 +  /* size of the POST input data, if strlen() is not good to use */
 +  CINIT(POSTFIELDSIZE, LONG, 60),
 +
 +  /* tunnel non-http operations through a HTTP proxy */
 +  CINIT(HTTPPROXYTUNNEL, LONG, 61),
 +
 +  /* Set the interface string to use as outgoing network interface */
 +  CINIT(INTERFACE, STRINGPOINT, 62),
 +
 +  /* Set the krb4/5 security level, this also enables krb4/5 awareness.  This
 +   * is a string, 'clear', 'safe', 'confidential' or 'private'.  If the string
 +   * is set but doesn't match one of these, 'private' will be used.  */
 +  CINIT(KRBLEVEL, STRINGPOINT, 63),
 +
 +  /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
 +  CINIT(SSL_VERIFYPEER, LONG, 64),
 +
 +  /* The CApath or CAfile used to validate the peer certificate
 +     this option is used only if SSL_VERIFYPEER is true */
 +  CINIT(CAINFO, STRINGPOINT, 65),
 +
 +  /* 66 = OBSOLETE */
 +  /* 67 = OBSOLETE */
 +
 +  /* Maximum number of http redirects to follow */
 +  CINIT(MAXREDIRS, LONG, 68),
 +
 +  /* Pass a long set to 1 to get the date of the requested document (if
 +     possible)! Pass a zero to shut it off. */
 +  CINIT(FILETIME, LONG, 69),
 +
 +  /* This points to a linked list of telnet options */
 +  CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
 +
 +  /* Max amount of cached alive connections */
 +  CINIT(MAXCONNECTS, LONG, 71),
 +
 +  CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */
 +
 +  /* 73 = OBSOLETE */
 +
 +  /* Set to explicitly use a new connection for the upcoming transfer.
 +     Do not use this unless you're absolutely sure of this, as it makes the
 +     operation slower and is less friendly for the network. */
 +  CINIT(FRESH_CONNECT, LONG, 74),
 +
 +  /* Set to explicitly forbid the upcoming transfer's connection to be re-used
 +     when done. Do not use this unless you're absolutely sure of this, as it
 +     makes the operation slower and is less friendly for the network. */
 +  CINIT(FORBID_REUSE, LONG, 75),
 +
 +  /* Set to a file name that contains random data for libcurl to use to
 +     seed the random engine when doing SSL connects. */
 +  CINIT(RANDOM_FILE, STRINGPOINT, 76),
 +
 +  /* Set to the Entropy Gathering Daemon socket pathname */
 +  CINIT(EGDSOCKET, STRINGPOINT, 77),
 +
 +  /* Time-out connect operations after this amount of seconds, if connects are
 +     OK within this time, then fine... This only aborts the connect phase. */
 +  CINIT(CONNECTTIMEOUT, LONG, 78),
 +
 +  /* Function that will be called to store headers (instead of fwrite). The
 +   * parameters will use fwrite() syntax, make sure to follow them. */
 +  CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
 +
 +  /* Set this to force the HTTP request to get back to GET. Only really usable
 +     if POST, PUT or a custom request have been used first.
 +   */
 +  CINIT(HTTPGET, LONG, 80),
 +
 +  /* Set if we should verify the Common name from the peer certificate in ssl
 +   * handshake, set 1 to check existence, 2 to ensure that it matches the
 +   * provided hostname. */
 +  CINIT(SSL_VERIFYHOST, LONG, 81),
 +
 +  /* Specify which file name to write all known cookies in after completed
 +     operation. Set file name to "-" (dash) to make it go to stdout. */
 +  CINIT(COOKIEJAR, STRINGPOINT, 82),
 +
 +  /* Specify which SSL ciphers to use */
 +  CINIT(SSL_CIPHER_LIST, STRINGPOINT, 83),
 +
 +  /* Specify which HTTP version to use! This must be set to one of the
 +     CURL_HTTP_VERSION* enums set below. */
 +  CINIT(HTTP_VERSION, LONG, 84),
 +
 +  /* Specifically switch on or off the FTP engine's use of the EPSV command. By
 +     default, that one will always be attempted before the more traditional
 +     PASV command. */
 +  CINIT(FTP_USE_EPSV, LONG, 85),
 +
 +  /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
 +  CINIT(SSLCERTTYPE, STRINGPOINT, 86),
 +
 +  /* name of the file keeping your private SSL-key */
 +  CINIT(SSLKEY, STRINGPOINT, 87),
 +
 +  /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
 +  CINIT(SSLKEYTYPE, STRINGPOINT, 88),
 +
 +  /* crypto engine for the SSL-sub system */
 +  CINIT(SSLENGINE, STRINGPOINT, 89),
 +
 +  /* set the crypto engine for the SSL-sub system as default
 +     the param has no meaning...
 +   */
 +  CINIT(SSLENGINE_DEFAULT, LONG, 90),
 +
 +  /* Non-zero value means to use the global dns cache */
 +  CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */
 +
 +  /* DNS cache timeout */
 +  CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
 +
 +  /* send linked-list of pre-transfer QUOTE commands */
 +  CINIT(PREQUOTE, OBJECTPOINT, 93),
 +
 +  /* set the debug function */
 +  CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
 +
 +  /* set the data for the debug function */
 +  CINIT(DEBUGDATA, OBJECTPOINT, 95),
 +
 +  /* mark this as start of a cookie session */
 +  CINIT(COOKIESESSION, LONG, 96),
 +
 +  /* The CApath directory used to validate the peer certificate
 +     this option is used only if SSL_VERIFYPEER is true */
 +  CINIT(CAPATH, STRINGPOINT, 97),
 +
 +  /* Instruct libcurl to use a smaller receive buffer */
 +  CINIT(BUFFERSIZE, LONG, 98),
 +
 +  /* Instruct libcurl to not use any signal/alarm handlers, even when using
 +     timeouts. This option is useful for multi-threaded applications.
 +     See libcurl-the-guide for more background information. */
 +  CINIT(NOSIGNAL, LONG, 99),
 +
 +  /* Provide a CURLShare for mutexing non-ts data */
 +  CINIT(SHARE, OBJECTPOINT, 100),
 +
 +  /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
 +     CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
 +     CURLPROXY_SOCKS5. */
 +  CINIT(PROXYTYPE, LONG, 101),
 +
 +  /* Set the Accept-Encoding string. Use this to tell a server you would like
 +     the response to be compressed. Before 7.21.6, this was known as
 +     CURLOPT_ENCODING */
 +  CINIT(ACCEPT_ENCODING, STRINGPOINT, 102),
 +
 +  /* Set pointer to private data */
 +  CINIT(PRIVATE, OBJECTPOINT, 103),
 +
 +  /* Set aliases for HTTP 200 in the HTTP Response header */
 +  CINIT(HTTP200ALIASES, OBJECTPOINT, 104),
 +
 +  /* Continue to send authentication (user+password) when following locations,
 +     even when hostname changed. This can potentially send off the name
 +     and password to whatever host the server decides. */
 +  CINIT(UNRESTRICTED_AUTH, LONG, 105),
 +
 +  /* Specifically switch on or off the FTP engine's use of the EPRT command (
 +     it also disables the LPRT attempt). By default, those ones will always be
 +     attempted before the good old traditional PORT command. */
 +  CINIT(FTP_USE_EPRT, LONG, 106),
 +
 +  /* Set this to a bitmask value to enable the particular authentications
 +     methods you like. Use this in combination with CURLOPT_USERPWD.
 +     Note that setting multiple bits may cause extra network round-trips. */
 +  CINIT(HTTPAUTH, LONG, 107),
 +
 +  /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx
 +     in second argument. The function must be matching the
 +     curl_ssl_ctx_callback proto. */
 +  CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
 +
 +  /* Set the userdata for the ssl context callback function's third
 +     argument */
 +  CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
 +
 +  /* FTP Option that causes missing dirs to be created on the remote server.
 +     In 7.19.4 we introduced the convenience enums for this option using the
 +     CURLFTP_CREATE_DIR prefix.
 +  */
 +  CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
 +
 +  /* Set this to a bitmask value to enable the particular authentications
 +     methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
 +     Note that setting multiple bits may cause extra network round-trips. */
 +  CINIT(PROXYAUTH, LONG, 111),
 +
 +  /* FTP option that changes the timeout, in seconds, associated with
 +     getting a response.  This is different from transfer timeout time and
 +     essentially places a demand on the FTP server to acknowledge commands
 +     in a timely manner. */
 +  CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
 +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
 +
 +  /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
 +     tell libcurl to resolve names to those IP versions only. This only has
 +     affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
 +  CINIT(IPRESOLVE, LONG, 113),
 +
 +  /* Set this option to limit the size of a file that will be downloaded from
 +     an HTTP or FTP server.
 +
 +     Note there is also _LARGE version which adds large file support for
 +     platforms which have larger off_t sizes.  See MAXFILESIZE_LARGE below. */
 +  CINIT(MAXFILESIZE, LONG, 114),
 +
 +  /* See the comment for INFILESIZE above, but in short, specifies
 +   * the size of the file being uploaded.  -1 means unknown.
 +   */
 +  CINIT(INFILESIZE_LARGE, OFF_T, 115),
 +
 +  /* Sets the continuation offset.  There is also a LONG version of this;
 +   * look above for RESUME_FROM.
 +   */
 +  CINIT(RESUME_FROM_LARGE, OFF_T, 116),
 +
 +  /* Sets the maximum size of data that will be downloaded from
 +   * an HTTP or FTP server.  See MAXFILESIZE above for the LONG version.
 +   */
 +  CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
 +
 +  /* Set this option to the file name of your .netrc file you want libcurl
 +     to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
 +     a poor attempt to find the user's home directory and check for a .netrc
 +     file in there. */
 +  CINIT(NETRC_FILE, STRINGPOINT, 118),
 +
 +  /* Enable SSL/TLS for FTP, pick one of:
 +     CURLUSESSL_TRY     - try using SSL, proceed anyway otherwise
 +     CURLUSESSL_CONTROL - SSL for the control connection or fail
 +     CURLUSESSL_ALL     - SSL for all communication or fail
 +  */
 +  CINIT(USE_SSL, LONG, 119),
 +
 +  /* The _LARGE version of the standard POSTFIELDSIZE option */
 +  CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
 +
 +  /* Enable/disable the TCP Nagle algorithm */
 +  CINIT(TCP_NODELAY, LONG, 121),
 +
 +  /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
 +  /* 123 OBSOLETE. Gone in 7.16.0 */
 +  /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
 +  /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
 +  /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
 +  /* 127 OBSOLETE. Gone in 7.16.0 */
 +  /* 128 OBSOLETE. Gone in 7.16.0 */
 +
 +  /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option
 +     can be used to change libcurl's default action which is to first try
 +     "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK
 +     response has been received.
 +
 +     Available parameters are:
 +     CURLFTPAUTH_DEFAULT - let libcurl decide
 +     CURLFTPAUTH_SSL     - try "AUTH SSL" first, then TLS
 +     CURLFTPAUTH_TLS     - try "AUTH TLS" first, then SSL
 +  */
 +  CINIT(FTPSSLAUTH, LONG, 129),
 +
 +  CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
 +  CINIT(IOCTLDATA, OBJECTPOINT, 131),
 +
 +  /* 132 OBSOLETE. Gone in 7.16.0 */
 +  /* 133 OBSOLETE. Gone in 7.16.0 */
 +
 +  /* zero terminated string for pass on to the FTP server when asked for
 +     "account" info */
 +  CINIT(FTP_ACCOUNT, STRINGPOINT, 134),
 +
 +  /* feed cookie into cookie engine */
 +  CINIT(COOKIELIST, STRINGPOINT, 135),
 +
 +  /* ignore Content-Length */
 +  CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
 +
 +  /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
 +     response. Typically used for FTP-SSL purposes but is not restricted to
 +     that. libcurl will then instead use the same IP address it used for the
 +     control connection. */
 +  CINIT(FTP_SKIP_PASV_IP, LONG, 137),
 +
 +  /* Select "file method" to use when doing FTP, see the curl_ftpmethod
 +     above. */
 +  CINIT(FTP_FILEMETHOD, LONG, 138),
 +
 +  /* Local port number to bind the socket to */
 +  CINIT(LOCALPORT, LONG, 139),
 +
 +  /* Number of ports to try, including the first one set with LOCALPORT.
 +     Thus, setting it to 1 will make no additional attempts but the first.
 +  */
 +  CINIT(LOCALPORTRANGE, LONG, 140),
 +
 +  /* no transfer, set up connection and let application use the socket by
 +     extracting it with CURLINFO_LASTSOCKET */
 +  CINIT(CONNECT_ONLY, LONG, 141),
 +
 +  /* Function that will be called to convert from the
 +     network encoding (instead of using the iconv calls in libcurl) */
 +  CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
 +
 +  /* Function that will be called to convert to the
 +     network encoding (instead of using the iconv calls in libcurl) */
 +  CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
 +
 +  /* Function that will be called to convert from UTF8
 +     (instead of using the iconv calls in libcurl)
 +     Note that this is used only for SSL certificate processing */
 +  CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
 +
 +  /* if the connection proceeds too quickly then need to slow it down */
 +  /* limit-rate: maximum number of bytes per second to send or receive */
 +  CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
 +  CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
 +
 +  /* Pointer to command string to send if USER/PASS fails. */
 +  CINIT(FTP_ALTERNATIVE_TO_USER, STRINGPOINT, 147),
 +
 +  /* callback function for setting socket options */
 +  CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
 +  CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
 +
 +  /* set to 0 to disable session ID re-use for this transfer, default is
 +     enabled (== 1) */
 +  CINIT(SSL_SESSIONID_CACHE, LONG, 150),
 +
 +  /* allowed SSH authentication methods */
 +  CINIT(SSH_AUTH_TYPES, LONG, 151),
 +
 +  /* Used by scp/sftp to do public/private key authentication */
 +  CINIT(SSH_PUBLIC_KEYFILE, STRINGPOINT, 152),
 +  CINIT(SSH_PRIVATE_KEYFILE, STRINGPOINT, 153),
 +
 +  /* Send CCC (Clear Command Channel) after authentication */
 +  CINIT(FTP_SSL_CCC, LONG, 154),
 +
 +  /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
 +  CINIT(TIMEOUT_MS, LONG, 155),
 +  CINIT(CONNECTTIMEOUT_MS, LONG, 156),
 +
 +  /* set to zero to disable the libcurl's decoding and thus pass the raw body
 +     data to the application even when it is encoded/compressed */
 +  CINIT(HTTP_TRANSFER_DECODING, LONG, 157),
 +  CINIT(HTTP_CONTENT_DECODING, LONG, 158),
 +
 +  /* Permission used when creating new files and directories on the remote
 +     server for protocols that support it, SFTP/SCP/FILE */
 +  CINIT(NEW_FILE_PERMS, LONG, 159),
 +  CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
 +
 +  /* Set the behaviour of POST when redirecting. Values must be set to one
 +     of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
 +  CINIT(POSTREDIR, LONG, 161),
 +
 +  /* used by scp/sftp to verify the host's public key */
 +  CINIT(SSH_HOST_PUBLIC_KEY_MD5, STRINGPOINT, 162),
 +
 +  /* Callback function for opening socket (instead of socket(2)). Optionally,
 +     callback is able change the address or refuse to connect returning
 +     CURL_SOCKET_BAD.  The callback should have type
 +     curl_opensocket_callback */
 +  CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
 +  CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
 +
 +  /* POST volatile input fields. */
 +  CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
 +
 +  /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
 +  CINIT(PROXY_TRANSFER_MODE, LONG, 166),
 +
 +  /* Callback function for seeking in the input stream */
 +  CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
 +  CINIT(SEEKDATA, OBJECTPOINT, 168),
 +
 +  /* CRL file */
 +  CINIT(CRLFILE, STRINGPOINT, 169),
 +
 +  /* Issuer certificate */
 +  CINIT(ISSUERCERT, STRINGPOINT, 170),
 +
 +  /* (IPv6) Address scope */
 +  CINIT(ADDRESS_SCOPE, LONG, 171),
 +
 +  /* Collect certificate chain info and allow it to get retrievable with
 +     CURLINFO_CERTINFO after the transfer is complete. */
 +  CINIT(CERTINFO, LONG, 172),
 +
 +  /* "name" and "pwd" to use when fetching. */
 +  CINIT(USERNAME, STRINGPOINT, 173),
 +  CINIT(PASSWORD, STRINGPOINT, 174),
 +
 +    /* "name" and "pwd" to use with Proxy when fetching. */
 +  CINIT(PROXYUSERNAME, STRINGPOINT, 175),
 +  CINIT(PROXYPASSWORD, STRINGPOINT, 176),
 +
 +  /* Comma separated list of hostnames defining no-proxy zones. These should
 +     match both hostnames directly, and hostnames within a domain. For
 +     example, local.com will match local.com and www.local.com, but NOT
 +     notlocal.com or www.notlocal.com. For compatibility with other
 +     implementations of this, .local.com will be considered to be the same as
 +     local.com. A single * is the only valid wildcard, and effectively
 +     disables the use of proxy. */
 +  CINIT(NOPROXY, STRINGPOINT, 177),
 +
 +  /* block size for TFTP transfers */
 +  CINIT(TFTP_BLKSIZE, LONG, 178),
 +
 +  /* Socks Service */
 +  CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), /* DEPRECATED, do not use! */
 +
 +  /* Socks Service */
 +  CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
 +
 +  /* set the bitmask for the protocols that are allowed to be used for the
 +     transfer, which thus helps the app which takes URLs from users or other
 +     external inputs and want to restrict what protocol(s) to deal
 +     with. Defaults to CURLPROTO_ALL. */
 +  CINIT(PROTOCOLS, LONG, 181),
 +
 +  /* set the bitmask for the protocols that libcurl is allowed to follow to,
 +     as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
 +     to be set in both bitmasks to be allowed to get redirected to. Defaults
 +     to all protocols except FILE and SCP. */
 +  CINIT(REDIR_PROTOCOLS, LONG, 182),
 +
 +  /* set the SSH knownhost file name to use */
 +  CINIT(SSH_KNOWNHOSTS, STRINGPOINT, 183),
 +
 +  /* set the SSH host key callback, must point to a curl_sshkeycallback
 +     function */
 +  CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184),
 +
 +  /* set the SSH host key callback custom pointer */
 +  CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
 +
 +  /* set the SMTP mail originator */
 +  CINIT(MAIL_FROM, STRINGPOINT, 186),
 +
 +  /* set the list of SMTP mail receiver(s) */
 +  CINIT(MAIL_RCPT, OBJECTPOINT, 187),
 +
 +  /* FTP: send PRET before PASV */
 +  CINIT(FTP_USE_PRET, LONG, 188),
 +
 +  /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
 +  CINIT(RTSP_REQUEST, LONG, 189),
 +
 +  /* The RTSP session identifier */
 +  CINIT(RTSP_SESSION_ID, STRINGPOINT, 190),
 +
 +  /* The RTSP stream URI */
 +  CINIT(RTSP_STREAM_URI, STRINGPOINT, 191),
 +
 +  /* The Transport: header to use in RTSP requests */
 +  CINIT(RTSP_TRANSPORT, STRINGPOINT, 192),
 +
 +  /* Manually initialize the client RTSP CSeq for this handle */
 +  CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
 +
 +  /* Manually initialize the server RTSP CSeq for this handle */
 +  CINIT(RTSP_SERVER_CSEQ, LONG, 194),
 +
 +  /* The stream to pass to INTERLEAVEFUNCTION. */
 +  CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
 +
 +  /* Let the application define a custom write method for RTP data */
 +  CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
 +
 +  /* Turn on wildcard matching */
 +  CINIT(WILDCARDMATCH, LONG, 197),
 +
 +  /* Directory matching callback called before downloading of an
 +     individual file (chunk) started */
 +  CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
 +
 +  /* Directory matching callback called after the file (chunk)
 +     was downloaded, or skipped */
 +  CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
 +
 +  /* Change match (fnmatch-like) callback for wildcard matching */
 +  CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
 +
 +  /* Let the application define custom chunk data pointer */
 +  CINIT(CHUNK_DATA, OBJECTPOINT, 201),
 +
 +  /* FNMATCH_FUNCTION user pointer */
 +  CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
 +
 +  /* send linked-list of name:port:address sets */
 +  CINIT(RESOLVE, OBJECTPOINT, 203),
 +
 +  /* Set a username for authenticated TLS */
 +  CINIT(TLSAUTH_USERNAME, STRINGPOINT, 204),
 +
 +  /* Set a password for authenticated TLS */
 +  CINIT(TLSAUTH_PASSWORD, STRINGPOINT, 205),
 +
 +  /* Set authentication type for authenticated TLS */
 +  CINIT(TLSAUTH_TYPE, STRINGPOINT, 206),
 +
 +  /* Set to 1 to enable the "TE:" header in HTTP requests to ask for
 +     compressed transfer-encoded responses. Set to 0 to disable the use of TE:
 +     in outgoing requests. The current default is 0, but it might change in a
 +     future libcurl release.
 +
 +     libcurl will ask for the compressed methods it knows of, and if that
 +     isn't any, it will not ask for transfer-encoding at all even if this
 +     option is set to 1.
 +
 +  */
 +  CINIT(TRANSFER_ENCODING, LONG, 207),
 +
 +  /* Callback function for closing socket (instead of close(2)). The callback
 +     should have type curl_closesocket_callback */
 +  CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
 +  CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
 +
 +  /* allow GSSAPI credential delegation */
 +  CINIT(GSSAPI_DELEGATION, LONG, 210),
 +
 +  /* Set the name servers to use for DNS resolution */
 +  CINIT(DNS_SERVERS, STRINGPOINT, 211),
 +
 +  /* Time-out accept operations (currently for FTP only) after this amount
 +     of milliseconds. */
 +  CINIT(ACCEPTTIMEOUT_MS, LONG, 212),
 +
 +  /* Set TCP keepalive */
 +  CINIT(TCP_KEEPALIVE, LONG, 213),
 +
 +  /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */
 +  CINIT(TCP_KEEPIDLE, LONG, 214),
 +  CINIT(TCP_KEEPINTVL, LONG, 215),
 +
 +  /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
 +  CINIT(SSL_OPTIONS, LONG, 216),
 +
 +  /* Set the SMTP auth originator */
 +  CINIT(MAIL_AUTH, STRINGPOINT, 217),
 +
 +  /* Enable/disable SASL initial response */
 +  CINIT(SASL_IR, LONG, 218),
 +
 +  /* Function that will be called instead of the internal progress display
 +   * function. This function should be defined as the curl_xferinfo_callback
 +   * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
 +  CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
 +
 +  /* The XOAUTH2 bearer token */
 +  CINIT(XOAUTH2_BEARER, STRINGPOINT, 220),
 +
 +  /* Set the interface string to use as outgoing network
 +   * interface for DNS requests.
 +   * Only supported by the c-ares DNS backend */
 +  CINIT(DNS_INTERFACE, STRINGPOINT, 221),
 +
 +  /* Set the local IPv4 address to use for outgoing DNS requests.
 +   * Only supported by the c-ares DNS backend */
 +  CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222),
 +
 +  /* Set the local IPv6 address to use for outgoing DNS requests.
 +   * Only supported by the c-ares DNS backend */
 +  CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223),
 +
 +  /* Set authentication options directly */
 +  CINIT(LOGIN_OPTIONS, STRINGPOINT, 224),
 +
 +  /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
 +  CINIT(SSL_ENABLE_NPN, LONG, 225),
 +
 +  /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
 +  CINIT(SSL_ENABLE_ALPN, LONG, 226),
 +
 +  /* Time to wait for a response to a HTTP request containing an
 +   * Expect: 100-continue header before sending the data anyway. */
 +  CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
 +
 +  /* This points to a linked list of headers used for proxy requests only,
 +     struct curl_slist kind */
 +  CINIT(PROXYHEADER, OBJECTPOINT, 228),
 +
 +  /* Pass in a bitmask of "header options" */
 +  CINIT(HEADEROPT, LONG, 229),
 +
 +  /* The public key in DER form used to validate the peer public key
 +     this option is used only if SSL_VERIFYPEER is true */
 +  CINIT(PINNEDPUBLICKEY, STRINGPOINT, 230),
 +
 +  /* Path to Unix domain socket */
 +  CINIT(UNIX_SOCKET_PATH, STRINGPOINT, 231),
 +
 +  /* Set if we should verify the certificate status. */
 +  CINIT(SSL_VERIFYSTATUS, LONG, 232),
 +
 +  /* Set if we should enable TLS false start. */
 +  CINIT(SSL_FALSESTART, LONG, 233),
 +
 +  /* Do not squash dot-dot sequences */
 +  CINIT(PATH_AS_IS, LONG, 234),
 +
 +  /* Proxy Service Name */
 +  CINIT(PROXY_SERVICE_NAME, STRINGPOINT, 235),
 +
 +  /* Service Name */
 +  CINIT(SERVICE_NAME, STRINGPOINT, 236),
 +
 +  /* Wait/don't wait for pipe/mutex to clarify */
 +  CINIT(PIPEWAIT, LONG, 237),
 +
 +  /* Set the protocol used when curl is given a URL without a protocol */
 +  CINIT(DEFAULT_PROTOCOL, STRINGPOINT, 238),
 +
 +  /* Set stream weight, 1 - 256 (default is 16) */
 +  CINIT(STREAM_WEIGHT, LONG, 239),
 +
 +  /* Set stream dependency on another CURL handle */
 +  CINIT(STREAM_DEPENDS, OBJECTPOINT, 240),
 +
 +  /* Set E-xclusive stream dependency on another CURL handle */
 +  CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241),
 +
 +  /* Do not send any tftp option requests to the server */
 +  CINIT(TFTP_NO_OPTIONS, LONG, 242),
 +
 +  /* Linked-list of host:port:connect-to-host:connect-to-port,
 +     overrides the URL's host:port (only for the network layer) */
 +  CINIT(CONNECT_TO, OBJECTPOINT, 243),
 +
 +  /* Set TCP Fast Open */
 +  CINIT(TCP_FASTOPEN, LONG, 244),
 +
 +  /* Continue to send data if the server responds early with an
 +   * HTTP status code >= 300 */
 +  CINIT(KEEP_SENDING_ON_ERROR, LONG, 245),
 +
 +  /* The CApath or CAfile used to validate the proxy certificate
 +     this option is used only if PROXY_SSL_VERIFYPEER is true */
 +  CINIT(PROXY_CAINFO, STRINGPOINT, 246),
 +
 +  /* The CApath directory used to validate the proxy certificate
 +     this option is used only if PROXY_SSL_VERIFYPEER is true */
 +  CINIT(PROXY_CAPATH, STRINGPOINT, 247),
 +
 +  /* Set if we should verify the proxy in ssl handshake,
 +     set 1 to verify. */
 +  CINIT(PROXY_SSL_VERIFYPEER, LONG, 248),
 +
 +  /* Set if we should verify the Common name from the proxy certificate in ssl
 +   * handshake, set 1 to check existence, 2 to ensure that it matches
 +   * the provided hostname. */
 +  CINIT(PROXY_SSL_VERIFYHOST, LONG, 249),
 +
 +  /* What version to specifically try to use for proxy.
 +     See CURL_SSLVERSION defines below. */
 +  CINIT(PROXY_SSLVERSION, LONG, 250),
 +
 +  /* Set a username for authenticated TLS for proxy */
 +  CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251),
 +
 +  /* Set a password for authenticated TLS for proxy */
 +  CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252),
 +
 +  /* Set authentication type for authenticated TLS for proxy */
 +  CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253),
 +
 +  /* name of the file keeping your private SSL-certificate for proxy */
 +  CINIT(PROXY_SSLCERT, STRINGPOINT, 254),
 +
 +  /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for
 +     proxy */
 +  CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255),
 +
 +  /* name of the file keeping your private SSL-key for proxy */
 +  CINIT(PROXY_SSLKEY, STRINGPOINT, 256),
 +
 +  /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for
 +     proxy */
 +  CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257),
 +
 +  /* password for the SSL private key for proxy */
 +  CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258),
 +
 +  /* Specify which SSL ciphers to use for proxy */
 +  CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259),
 +
 +  /* CRL file for proxy */
 +  CINIT(PROXY_CRLFILE, STRINGPOINT, 260),
 +
 +  /* Enable/disable specific SSL features with a bitmask for proxy, see
 +     CURLSSLOPT_* */
 +  CINIT(PROXY_SSL_OPTIONS, LONG, 261),
 +
 +  /* Name of pre proxy to use. */
 +  CINIT(PRE_PROXY, STRINGPOINT, 262),
 +
 +  /* The public key in DER form used to validate the proxy public key
 +     this option is used only if PROXY_SSL_VERIFYPEER is true */
 +  CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263),
 +
 +  /* Path to an abstract Unix domain socket */
 +  CINIT(ABSTRACT_UNIX_SOCKET, STRINGPOINT, 264),
 +
 +  /* Suppress proxy CONNECT response headers from user callbacks */
 +  CINIT(SUPPRESS_CONNECT_HEADERS, LONG, 265),
 +
 +  /* The request target, instead of extracted from the URL */
 +  CINIT(REQUEST_TARGET, STRINGPOINT, 266),
 +
 +  /* bitmask of allowed auth methods for connections to SOCKS5 proxies */
 +  CINIT(SOCKS5_AUTH, LONG, 267),
 +
 +  /* Enable/disable SSH compression */
 +  CINIT(SSH_COMPRESSION, LONG, 268),
 +
 +  /* Post MIME data. */
 +  CINIT(MIMEPOST, OBJECTPOINT, 269),
 +
 +  /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of
 +     seconds since 1 Jan 1970. */
 +  CINIT(TIMEVALUE_LARGE, OFF_T, 270),
 +
 +  /* Head start in milliseconds to give happy eyeballs. */
 +  CINIT(HAPPY_EYEBALLS_TIMEOUT_MS, LONG, 271),
 +
 +  /* Function that will be called before a resolver request is made */
 +  CINIT(RESOLVER_START_FUNCTION, FUNCTIONPOINT, 272),
 +
 +  /* User data to pass to the resolver start callback. */
 +  CINIT(RESOLVER_START_DATA, OBJECTPOINT, 273),
 +
 +  /* send HAProxy PROXY protocol header? */
 +  CINIT(HAPROXYPROTOCOL, LONG, 274),
 +
 +  /* shuffle addresses before use when DNS returns multiple */
 +  CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275),
 +
 +  /* Specify which TLS 1.3 ciphers suites to use */
 +  CINIT(TLS13_CIPHERS, STRINGPOINT, 276),
 +  CINIT(PROXY_TLS13_CIPHERS, STRINGPOINT, 277),
 +
 +  /* Disallow specifying username/login in URL. */
 +  CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278),
 +
 +  /* DNS-over-HTTPS URL */
 +  CINIT(DOH_URL, STRINGPOINT, 279),
 +
 +  /* Preferred buffer size to use for uploads */
 +  CINIT(UPLOAD_BUFFERSIZE, LONG, 280),
 +
 +  /* Time in ms between connection upkeep calls for long-lived connections. */
 +  CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
 +
++  /* Specify URL using CURL URL API. */
++  CINIT(CURLU, OBJECTPOINT, 282),
++
++  /* add trailing data just after no more data is available */
++  CINIT(TRAILERFUNCTION, FUNCTIONPOINT, 283),
++
++  /* pointer to be passed to HTTP_TRAILER_FUNCTION */
++  CINIT(TRAILERDATA, OBJECTPOINT, 284),
++
++  /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */
++  CINIT(HTTP09_ALLOWED, LONG, 285),
++
++  /* alt-svc control bitmask */
++  CINIT(ALTSVC_CTRL, LONG, 286),
++
++  /* alt-svc cache file name to possibly read from/write to */
++  CINIT(ALTSVC, STRINGPOINT, 287),
++
++  /* maximum age of a connection to consider it for reuse (in seconds) */
++  CINIT(MAXAGE_CONN, LONG, 288),
++
 +  CURLOPT_LASTENTRY /* the last unused */
 +} CURLoption;
 +
 +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
 +                          the obsolete stuff removed! */
 +
 +/* Backwards compatibility with older names */
 +/* These are scheduled to disappear by 2011 */
 +
 +/* This was added in version 7.19.1 */
 +#define CURLOPT_POST301 CURLOPT_POSTREDIR
 +
 +/* These are scheduled to disappear by 2009 */
 +
 +/* The following were added in 7.17.0 */
 +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD
 +#define CURLOPT_FTPAPPEND CURLOPT_APPEND
 +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY
 +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL
 +
 +/* The following were added earlier */
 +
 +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
 +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
 +
 +#else
 +/* This is set if CURL_NO_OLDIES is defined at compile-time */
 +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
 +#endif
 +
 +
 +  /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
 +     name resolves addresses using more than one IP protocol version, this
 +     option might be handy to force libcurl to use a specific IP version. */
 +#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
 +                                     versions that your system allows */
 +#define CURL_IPRESOLVE_V4       1 /* resolve to IPv4 addresses */
 +#define CURL_IPRESOLVE_V6       2 /* resolve to IPv6 addresses */
 +
 +  /* three convenient "aliases" that follow the name scheme better */
 +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
 +
 +  /* These enums are for use with the CURLOPT_HTTP_VERSION option. */
 +enum {
 +  CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
 +                             like the library to choose the best possible
 +                             for us! */
 +  CURL_HTTP_VERSION_1_0,  /* please use HTTP 1.0 in the request */
 +  CURL_HTTP_VERSION_1_1,  /* please use HTTP 1.1 in the request */
 +  CURL_HTTP_VERSION_2_0,  /* please use HTTP 2 in the request */
 +  CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */
 +  CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE,  /* please use HTTP 2 without HTTP/1.1
 +                                           Upgrade */
 +
 +  CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
 +};
 +
 +/* Convenience definition simple because the name of the version is HTTP/2 and
 +   not 2.0. The 2_0 version of the enum name was set while the version was
 +   still planned to be 2.0 and we stick to it for compatibility. */
 +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0
 +
 +/*
 + * Public API enums for RTSP requests
 + */
 +enum {
 +    CURL_RTSPREQ_NONE, /* first in list */
 +    CURL_RTSPREQ_OPTIONS,
 +    CURL_RTSPREQ_DESCRIBE,
 +    CURL_RTSPREQ_ANNOUNCE,
 +    CURL_RTSPREQ_SETUP,
 +    CURL_RTSPREQ_PLAY,
 +    CURL_RTSPREQ_PAUSE,
 +    CURL_RTSPREQ_TEARDOWN,
 +    CURL_RTSPREQ_GET_PARAMETER,
 +    CURL_RTSPREQ_SET_PARAMETER,
 +    CURL_RTSPREQ_RECORD,
 +    CURL_RTSPREQ_RECEIVE,
 +    CURL_RTSPREQ_LAST /* last in list */
 +};
 +
 +  /* These enums are for use with the CURLOPT_NETRC option. */
 +enum CURL_NETRC_OPTION {
 +  CURL_NETRC_IGNORED,     /* The .netrc will never be read.
 +                           * This is the default. */
 +  CURL_NETRC_OPTIONAL,    /* A user:password in the URL will be preferred
 +                           * to one in the .netrc. */
 +  CURL_NETRC_REQUIRED,    /* A user:password in the URL will be ignored.
 +                           * Unless one is set programmatically, the .netrc
 +                           * will be queried. */
 +  CURL_NETRC_LAST
 +};
 +
 +enum {
 +  CURL_SSLVERSION_DEFAULT,
 +  CURL_SSLVERSION_TLSv1, /* TLS 1.x */
 +  CURL_SSLVERSION_SSLv2,
 +  CURL_SSLVERSION_SSLv3,
 +  CURL_SSLVERSION_TLSv1_0,
 +  CURL_SSLVERSION_TLSv1_1,
 +  CURL_SSLVERSION_TLSv1_2,
 +  CURL_SSLVERSION_TLSv1_3,
 +
 +  CURL_SSLVERSION_LAST /* never use, keep last */
 +};
 +
 +enum {
 +  CURL_SSLVERSION_MAX_NONE =     0,
 +  CURL_SSLVERSION_MAX_DEFAULT =  (CURL_SSLVERSION_TLSv1   << 16),
 +  CURL_SSLVERSION_MAX_TLSv1_0 =  (CURL_SSLVERSION_TLSv1_0 << 16),
 +  CURL_SSLVERSION_MAX_TLSv1_1 =  (CURL_SSLVERSION_TLSv1_1 << 16),
 +  CURL_SSLVERSION_MAX_TLSv1_2 =  (CURL_SSLVERSION_TLSv1_2 << 16),
 +  CURL_SSLVERSION_MAX_TLSv1_3 =  (CURL_SSLVERSION_TLSv1_3 << 16),
 +
 +  /* never use, keep last */
 +  CURL_SSLVERSION_MAX_LAST =     (CURL_SSLVERSION_LAST    << 16)
 +};
 +
 +enum CURL_TLSAUTH {
 +  CURL_TLSAUTH_NONE,
 +  CURL_TLSAUTH_SRP,
 +  CURL_TLSAUTH_LAST /* never use, keep last */
 +};
 +
 +/* symbols to use with CURLOPT_POSTREDIR.
 +   CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303
 +   can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302
 +   | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */
 +
 +#define CURL_REDIR_GET_ALL  0
 +#define CURL_REDIR_POST_301 1
 +#define CURL_REDIR_POST_302 2
 +#define CURL_REDIR_POST_303 4
 +#define CURL_REDIR_POST_ALL \
 +    (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
 +
 +typedef enum {
 +  CURL_TIMECOND_NONE,
 +
 +  CURL_TIMECOND_IFMODSINCE,
 +  CURL_TIMECOND_IFUNMODSINCE,
 +  CURL_TIMECOND_LASTMOD,
 +
 +  CURL_TIMECOND_LAST
 +} curl_TimeCond;
 +
 +/* Special size_t value signaling a zero-terminated string. */
 +#define CURL_ZERO_TERMINATED ((size_t) -1)
 +
 +/* curl_strequal() and curl_strnequal() are subject for removal in a future
 +   release */
 +CURL_EXTERN int curl_strequal(const char *s1, const char *s2);
 +CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n);
 +
 +/* Mime/form handling support. */
 +typedef struct curl_mime_s      curl_mime;      /* Mime context. */
 +typedef struct curl_mimepart_s  curl_mimepart;  /* Mime part context. */
 +
 +/*
 + * NAME curl_mime_init()
 + *
 + * DESCRIPTION
 + *
 + * Create a mime context and return its handle. The easy parameter is the
 + * target handle.
 + */
 +CURL_EXTERN curl_mime *curl_mime_init(CURL *easy);
 +
 +/*
 + * NAME curl_mime_free()
 + *
 + * DESCRIPTION
 + *
 + * release a mime handle and its substructures.
 + */
 +CURL_EXTERN void curl_mime_free(curl_mime *mime);
 +
 +/*
 + * NAME curl_mime_addpart()
 + *
 + * DESCRIPTION
 + *
 + * Append a new empty part to the given mime context and return a handle to
 + * the created part.
 + */
 +CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime);
 +
 +/*
 + * NAME curl_mime_name()
 + *
 + * DESCRIPTION
 + *
 + * Set mime/form part name.
 + */
 +CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name);
 +
 +/*
 + * NAME curl_mime_filename()
 + *
 + * DESCRIPTION
 + *
 + * Set mime part remote file name.
 + */
 +CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part,
 +                                        const char *filename);
 +
 +/*
 + * NAME curl_mime_type()
 + *
 + * DESCRIPTION
 + *
 + * Set mime part type.
 + */
 +CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype);
 +
 +/*
 + * NAME curl_mime_encoder()
 + *
 + * DESCRIPTION
 + *
 + * Set mime data transfer encoder.
 + */
 +CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part,
 +                                       const char *encoding);
 +
 +/*
 + * NAME curl_mime_data()
 + *
 + * DESCRIPTION
 + *
 + * Set mime part data source from memory data,
 + */
 +CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part,
 +                                    const char *data, size_t datasize);
 +
 +/*
 + * NAME curl_mime_filedata()
 + *
 + * DESCRIPTION
 + *
 + * Set mime part data source from named file.
 + */
 +CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part,
 +                                        const char *filename);
 +
 +/*
 + * NAME curl_mime_data_cb()
 + *
 + * DESCRIPTION
 + *
 + * Set mime part data source from callback function.
 + */
 +CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part,
 +                                       curl_off_t datasize,
 +                                       curl_read_callback readfunc,
 +                                       curl_seek_callback seekfunc,
 +                                       curl_free_callback freefunc,
 +                                       void *arg);
 +
 +/*
 + * NAME curl_mime_subparts()
 + *
 + * DESCRIPTION
 + *
 + * Set mime part data source from subparts.
 + */
 +CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part,
 +                                        curl_mime *subparts);
 +/*
 + * NAME curl_mime_headers()
 + *
 + * DESCRIPTION
 + *
 + * Set mime part headers.
 + */
 +CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part,
 +                                       struct curl_slist *headers,
 +                                       int take_ownership);
 +
 +/* Old form API. */
 +/* name is uppercase CURLFORM_<name> */
 +#ifdef CFINIT
 +#undef CFINIT
 +#endif
 +
 +#ifdef CURL_ISOCPP
 +#define CFINIT(name) CURLFORM_ ## name
 +#else
 +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
 +#define CFINIT(name) CURLFORM_/**/name
 +#endif
 +
 +typedef enum {
 +  CFINIT(NOTHING),        /********* the first one is unused ************/
 +
 +  /*  */
 +  CFINIT(COPYNAME),
 +  CFINIT(PTRNAME),
 +  CFINIT(NAMELENGTH),
 +  CFINIT(COPYCONTENTS),
 +  CFINIT(PTRCONTENTS),
 +  CFINIT(CONTENTSLENGTH),
 +  CFINIT(FILECONTENT),
 +  CFINIT(ARRAY),
 +  CFINIT(OBSOLETE),
 +  CFINIT(FILE),
 +
 +  CFINIT(BUFFER),
 +  CFINIT(BUFFERPTR),
 +  CFINIT(BUFFERLENGTH),
 +
 +  CFINIT(CONTENTTYPE),
 +  CFINIT(CONTENTHEADER),
 +  CFINIT(FILENAME),
 +  CFINIT(END),
 +  CFINIT(OBSOLETE2),
 +
 +  CFINIT(STREAM),
 +  CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */
 +
 +  CURLFORM_LASTENTRY /* the last unused */
 +} CURLformoption;
 +
 +#undef CFINIT /* done */
 +
 +/* structure to be used as parameter for CURLFORM_ARRAY */
 +struct curl_forms {
 +  CURLformoption option;
 +  const char     *value;
 +};
 +
 +/* use this for multipart formpost building */
 +/* Returns code for curl_formadd()
 + *
 + * Returns:
 + * CURL_FORMADD_OK             on success
 + * CURL_FORMADD_MEMORY         if the FormInfo allocation fails
 + * CURL_FORMADD_OPTION_TWICE   if one option is given twice for one Form
 + * CURL_FORMADD_NULL           if a null pointer was given for a char
 + * CURL_FORMADD_MEMORY         if the allocation of a FormInfo struct failed
 + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
 + * CURL_FORMADD_INCOMPLETE     if the some FormInfo is not complete (or error)
 + * CURL_FORMADD_MEMORY         if a curl_httppost struct cannot be allocated
 + * CURL_FORMADD_MEMORY         if some allocation for string copying failed.
 + * CURL_FORMADD_ILLEGAL_ARRAY  if an illegal option is used in an array
 + *
 + ***************************************************************************/
 +typedef enum {
 +  CURL_FORMADD_OK, /* first, no error */
 +
 +  CURL_FORMADD_MEMORY,
 +  CURL_FORMADD_OPTION_TWICE,
 +  CURL_FORMADD_NULL,
 +  CURL_FORMADD_UNKNOWN_OPTION,
 +  CURL_FORMADD_INCOMPLETE,
 +  CURL_FORMADD_ILLEGAL_ARRAY,
 +  CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
 +
 +  CURL_FORMADD_LAST /* last */
 +} CURLFORMcode;
 +
 +/*
 + * NAME curl_formadd()
 + *
 + * DESCRIPTION
 + *
 + * Pretty advanced function for building multi-part formposts. Each invoke
 + * adds one part that together construct a full post. Then use
 + * CURLOPT_HTTPPOST to send it off to libcurl.
 + */
 +CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
 +                                      struct curl_httppost **last_post,
 +                                      ...);
 +
 +/*
 + * callback function for curl_formget()
 + * The void *arg pointer will be the one passed as second argument to
 + *   curl_formget().
 + * The character buffer passed to it must not be freed.
 + * Should return the buffer length passed to it as the argument "len" on
 + *   success.
 + */
 +typedef size_t (*curl_formget_callback)(void *arg, const char *buf,
 +                                        size_t len);
 +
 +/*
 + * NAME curl_formget()
 + *
 + * DESCRIPTION
 + *
 + * Serialize a curl_httppost struct built with curl_formadd().
 + * Accepts a void pointer as second argument which will be passed to
 + * the curl_formget_callback function.
 + * Returns 0 on success.
 + */
 +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
 +                             curl_formget_callback append);
 +/*
 + * NAME curl_formfree()
 + *
 + * DESCRIPTION
 + *
 + * Free a multipart formpost previously built with curl_formadd().
 + */
 +CURL_EXTERN void curl_formfree(struct curl_httppost *form);
 +
 +/*
 + * NAME curl_getenv()
 + *
 + * DESCRIPTION
 + *
 + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is
 + * complete. DEPRECATED - see lib/README.curlx
 + */
 +CURL_EXTERN char *curl_getenv(const char *variable);
 +
 +/*
 + * NAME curl_version()
 + *
 + * DESCRIPTION
 + *
 + * Returns a static ascii string of the libcurl version.
 + */
 +CURL_EXTERN char *curl_version(void);
 +
 +/*
 + * NAME curl_easy_escape()
 + *
 + * DESCRIPTION
 + *
 + * Escapes URL strings (converts all letters consider illegal in URLs to their
 + * %XX versions). This function returns a new allocated string or NULL if an
 + * error occurred.
 + */
 +CURL_EXTERN char *curl_easy_escape(CURL *handle,
 +                                   const char *string,
 +                                   int length);
 +
 +/* the previous version: */
 +CURL_EXTERN char *curl_escape(const char *string,
 +                              int length);
 +
 +
 +/*
 + * NAME curl_easy_unescape()
 + *
 + * DESCRIPTION
 + *
 + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit
 + * versions). This function returns a new allocated string or NULL if an error
 + * occurred.
 + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are
 + * converted into the host encoding.
 + */
 +CURL_EXTERN char *curl_easy_unescape(CURL *handle,
 +                                     const char *string,
 +                                     int length,
 +                                     int *outlength);
 +
 +/* the previous version */
 +CURL_EXTERN char *curl_unescape(const char *string,
 +                                int length);
 +
 +/*
 + * NAME curl_free()
 + *
 + * DESCRIPTION
 + *
 + * Provided for de-allocation in the same translation unit that did the
 + * allocation. Added in libcurl 7.10
 + */
 +CURL_EXTERN void curl_free(void *p);
 +
 +/*
 + * NAME curl_global_init()
 + *
 + * DESCRIPTION
 + *
 + * curl_global_init() should be invoked exactly once for each application that
 + * uses libcurl and before any call of other libcurl functions.
 + *
 + * This function is not thread-safe!
 + */
 +CURL_EXTERN CURLcode curl_global_init(long flags);
 +
 +/*
 + * NAME curl_global_init_mem()
 + *
 + * DESCRIPTION
 + *
 + * curl_global_init() or curl_global_init_mem() should be invoked exactly once
 + * for each application that uses libcurl.  This function can be used to
 + * initialize libcurl and set user defined memory management callback
 + * functions.  Users can implement memory management routines to check for
 + * memory leaks, check for mis-use of the curl library etc.  User registered
 + * callback routines with be invoked by this library instead of the system
 + * memory management routines like malloc, free etc.
 + */
 +CURL_EXTERN CURLcode curl_global_init_mem(long flags,
 +                                          curl_malloc_callback m,
 +                                          curl_free_callback f,
 +                                          curl_realloc_callback r,
 +                                          curl_strdup_callback s,
 +                                          curl_calloc_callback c);
 +
 +/*
 + * NAME curl_global_cleanup()
 + *
 + * DESCRIPTION
 + *
 + * curl_global_cleanup() should be invoked exactly once for each application
 + * that uses libcurl
 + */
 +CURL_EXTERN void curl_global_cleanup(void);
 +
 +/* linked-list structure for the CURLOPT_QUOTE option (and other) */
 +struct curl_slist {
 +  char *data;
 +  struct curl_slist *next;
 +};
 +
 +/*
 + * NAME curl_global_sslset()
 + *
 + * DESCRIPTION
 + *
 + * When built with multiple SSL backends, curl_global_sslset() allows to
 + * choose one. This function can only be called once, and it must be called
 + * *before* curl_global_init().
 + *
 + * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The
 + * backend can also be specified via the name parameter (passing -1 as id).
 + * If both id and name are specified, the name will be ignored. If neither id
 + * nor name are specified, the function will fail with
 + * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the
 + * NULL-terminated list of available backends.
 + *
 + * Upon success, the function returns CURLSSLSET_OK.
 + *
 + * If the specified SSL backend is not available, the function returns
 + * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated
 + * list of available SSL backends.
 + *
 + * The SSL backend can be set only once. If it has already been set, a
 + * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE.
 + */
 +
 +typedef struct {
 +  curl_sslbackend id;
 +  const char *name;
 +} curl_ssl_backend;
 +
 +typedef enum {
 +  CURLSSLSET_OK = 0,
 +  CURLSSLSET_UNKNOWN_BACKEND,
 +  CURLSSLSET_TOO_LATE,
 +  CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */
 +} CURLsslset;
 +
 +CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
 +                                          const curl_ssl_backend ***avail);
 +
 +/*
 + * NAME curl_slist_append()
 + *
 + * DESCRIPTION
 + *
 + * Appends a string to a linked list. If no list exists, it will be created
 + * first. Returns the new list, after appending.
 + */
 +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
 +                                                 const char *);
 +
 +/*
 + * NAME curl_slist_free_all()
 + *
 + * DESCRIPTION
 + *
 + * free a previously built curl_slist.
 + */
 +CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
 +
 +/*
 + * NAME curl_getdate()
 + *
 + * DESCRIPTION
 + *
 + * Returns the time, in seconds since 1 Jan 1970 of the time string given in
 + * the first argument. The time argument in the second parameter is unused
 + * and should be set to NULL.
 + */
 +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
 +
 +/* info about the certificate chain, only for OpenSSL builds. Asked
 +   for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
 +struct curl_certinfo {
 +  int num_of_certs;             /* number of certificates with information */
 +  struct curl_slist **certinfo; /* for each index in this array, there's a
 +                                   linked list with textual information in the
 +                                   format "name: value" */
 +};
 +
 +/* Information about the SSL library used and the respective internal SSL
 +   handle, which can be used to obtain further information regarding the
 +   connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */
 +struct curl_tlssessioninfo {
 +  curl_sslbackend backend;
 +  void *internals;
 +};
 +
 +#define CURLINFO_STRING   0x100000
 +#define CURLINFO_LONG     0x200000
 +#define CURLINFO_DOUBLE   0x300000
 +#define CURLINFO_SLIST    0x400000
 +#define CURLINFO_PTR      0x400000 /* same as SLIST */
 +#define CURLINFO_SOCKET   0x500000
 +#define CURLINFO_OFF_T    0x600000
 +#define CURLINFO_MASK     0x0fffff
 +#define CURLINFO_TYPEMASK 0xf00000
 +
 +typedef enum {
 +  CURLINFO_NONE, /* first, never use this */
 +  CURLINFO_EFFECTIVE_URL    = CURLINFO_STRING + 1,
 +  CURLINFO_RESPONSE_CODE    = CURLINFO_LONG   + 2,
 +  CURLINFO_TOTAL_TIME       = CURLINFO_DOUBLE + 3,
 +  CURLINFO_NAMELOOKUP_TIME  = CURLINFO_DOUBLE + 4,
 +  CURLINFO_CONNECT_TIME     = CURLINFO_DOUBLE + 5,
 +  CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
 +  CURLINFO_SIZE_UPLOAD      = CURLINFO_DOUBLE + 7,
 +  CURLINFO_SIZE_UPLOAD_T    = CURLINFO_OFF_T  + 7,
 +  CURLINFO_SIZE_DOWNLOAD    = CURLINFO_DOUBLE + 8,
 +  CURLINFO_SIZE_DOWNLOAD_T  = CURLINFO_OFF_T  + 8,
 +  CURLINFO_SPEED_DOWNLOAD   = CURLINFO_DOUBLE + 9,
 +  CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T  + 9,
 +  CURLINFO_SPEED_UPLOAD     = CURLINFO_DOUBLE + 10,
 +  CURLINFO_SPEED_UPLOAD_T   = CURLINFO_OFF_T  + 10,
 +  CURLINFO_HEADER_SIZE      = CURLINFO_LONG   + 11,
 +  CURLINFO_REQUEST_SIZE     = CURLINFO_LONG   + 12,
 +  CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG   + 13,
 +  CURLINFO_FILETIME         = CURLINFO_LONG   + 14,
 +  CURLINFO_FILETIME_T       = CURLINFO_OFF_T  + 14,
 +  CURLINFO_CONTENT_LENGTH_DOWNLOAD   = CURLINFO_DOUBLE + 15,
 +  CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T  + 15,
 +  CURLINFO_CONTENT_LENGTH_UPLOAD     = CURLINFO_DOUBLE + 16,
 +  CURLINFO_CONTENT_LENGTH_UPLOAD_T   = CURLINFO_OFF_T  + 16,
 +  CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
 +  CURLINFO_CONTENT_TYPE     = CURLINFO_STRING + 18,
 +  CURLINFO_REDIRECT_TIME    = CURLINFO_DOUBLE + 19,
 +  CURLINFO_REDIRECT_COUNT   = CURLINFO_LONG   + 20,
 +  CURLINFO_PRIVATE          = CURLINFO_STRING + 21,
 +  CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG   + 22,
 +  CURLINFO_HTTPAUTH_AVAIL   = CURLINFO_LONG   + 23,
 +  CURLINFO_PROXYAUTH_AVAIL  = CURLINFO_LONG   + 24,
 +  CURLINFO_OS_ERRNO         = CURLINFO_LONG   + 25,
 +  CURLINFO_NUM_CONNECTS     = CURLINFO_LONG   + 26,
 +  CURLINFO_SSL_ENGINES      = CURLINFO_SLIST  + 27,
 +  CURLINFO_COOKIELIST       = CURLINFO_SLIST  + 28,
 +  CURLINFO_LASTSOCKET       = CURLINFO_LONG   + 29,
 +  CURLINFO_FTP_ENTRY_PATH   = CURLINFO_STRING + 30,
 +  CURLINFO_REDIRECT_URL     = CURLINFO_STRING + 31,
 +  CURLINFO_PRIMARY_IP       = CURLINFO_STRING + 32,
 +  CURLINFO_APPCONNECT_TIME  = CURLINFO_DOUBLE + 33,
 +  CURLINFO_CERTINFO         = CURLINFO_PTR    + 34,
 +  CURLINFO_CONDITION_UNMET  = CURLINFO_LONG   + 35,
 +  CURLINFO_RTSP_SESSION_ID  = CURLINFO_STRING + 36,
 +  CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG   + 37,
 +  CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG   + 38,
 +  CURLINFO_RTSP_CSEQ_RECV   = CURLINFO_LONG   + 39,
 +  CURLINFO_PRIMARY_PORT     = CURLINFO_LONG   + 40,
 +  CURLINFO_LOCAL_IP         = CURLINFO_STRING + 41,
 +  CURLINFO_LOCAL_PORT       = CURLINFO_LONG   + 42,
 +  CURLINFO_TLS_SESSION      = CURLINFO_PTR    + 43,
 +  CURLINFO_ACTIVESOCKET     = CURLINFO_SOCKET + 44,
 +  CURLINFO_TLS_SSL_PTR      = CURLINFO_PTR    + 45,
 +  CURLINFO_HTTP_VERSION     = CURLINFO_LONG   + 46,
 +  CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
 +  CURLINFO_PROTOCOL         = CURLINFO_LONG   + 48,
 +  CURLINFO_SCHEME           = CURLINFO_STRING + 49,
 +  /* Fill in new entries below here! */
 +
 +  /* Preferably these would be defined conditionally based on the
 +     sizeof curl_off_t being 64-bits */
 +  CURLINFO_TOTAL_TIME_T     = CURLINFO_OFF_T + 50,
 +  CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51,
 +  CURLINFO_CONNECT_TIME_T   = CURLINFO_OFF_T + 52,
 +  CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53,
 +  CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54,
 +  CURLINFO_REDIRECT_TIME_T  = CURLINFO_OFF_T + 55,
 +  CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
 +
 +  CURLINFO_LASTONE          = 56
 +} CURLINFO;
 +
 +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
 +   CURLINFO_HTTP_CODE */
 +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
 +
 +typedef enum {
 +  CURLCLOSEPOLICY_NONE, /* first, never use this */
 +
 +  CURLCLOSEPOLICY_OLDEST,
 +  CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
 +  CURLCLOSEPOLICY_LEAST_TRAFFIC,
 +  CURLCLOSEPOLICY_SLOWEST,
 +  CURLCLOSEPOLICY_CALLBACK,
 +
 +  CURLCLOSEPOLICY_LAST /* last, never use this */
 +} curl_closepolicy;
 +
 +#define CURL_GLOBAL_SSL (1<<0) /* no purpose since since 7.57.0 */
 +#define CURL_GLOBAL_WIN32 (1<<1)
 +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
 +#define CURL_GLOBAL_NOTHING 0
 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
 +#define CURL_GLOBAL_ACK_EINTR (1<<2)
 +
 +
 +/*****************************************************************************
 + * Setup defines, protos etc for the sharing stuff.
 + */
 +
 +/* Different data locks for a single share */
 +typedef enum {
 +  CURL_LOCK_DATA_NONE = 0,
 +  /*  CURL_LOCK_DATA_SHARE is used internally to say that
 +   *  the locking is just made to change the internal state of the share
 +   *  itself.
 +   */
 +  CURL_LOCK_DATA_SHARE,
 +  CURL_LOCK_DATA_COOKIE,
 +  CURL_LOCK_DATA_DNS,
 +  CURL_LOCK_DATA_SSL_SESSION,
 +  CURL_LOCK_DATA_CONNECT,
 +  CURL_LOCK_DATA_PSL,
 +  CURL_LOCK_DATA_LAST
 +} curl_lock_data;
 +
 +/* Different lock access types */
 +typedef enum {
 +  CURL_LOCK_ACCESS_NONE = 0,   /* unspecified action */
 +  CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
 +  CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
 +  CURL_LOCK_ACCESS_LAST        /* never use */
 +} curl_lock_access;
 +
 +typedef void (*curl_lock_function)(CURL *handle,
 +                                   curl_lock_data data,
 +                                   curl_lock_access locktype,
 +                                   void *userptr);
 +typedef void (*curl_unlock_function)(CURL *handle,
 +                                     curl_lock_data data,
 +                                     void *userptr);
 +
 +
 +typedef enum {
 +  CURLSHE_OK,  /* all is fine */
 +  CURLSHE_BAD_OPTION, /* 1 */
 +  CURLSHE_IN_USE,     /* 2 */
 +  CURLSHE_INVALID,    /* 3 */
 +  CURLSHE_NOMEM,      /* 4 out of memory */
 +  CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */
 +  CURLSHE_LAST        /* never use */
 +} CURLSHcode;
 +
 +typedef enum {
 +  CURLSHOPT_NONE,  /* don't use */
 +  CURLSHOPT_SHARE,   /* specify a data type to share */
 +  CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */
 +  CURLSHOPT_LOCKFUNC,   /* pass in a 'curl_lock_function' pointer */
 +  CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
 +  CURLSHOPT_USERDATA,   /* pass in a user data pointer used in the lock/unlock
 +                           callback functions */
 +  CURLSHOPT_LAST  /* never use */
 +} CURLSHoption;
 +
 +CURL_EXTERN CURLSH *curl_share_init(void);
 +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
 +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
 +
 +/****************************************************************************
 + * Structures for querying information about the curl library at runtime.
 + */
 +
 +typedef enum {
 +  CURLVERSION_FIRST,
 +  CURLVERSION_SECOND,
 +  CURLVERSION_THIRD,
 +  CURLVERSION_FOURTH,
 +  CURLVERSION_FIFTH,
 +  CURLVERSION_LAST /* never actually use this */
 +} CURLversion;
 +
 +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
 +   basically all programs ever that want to get version information. It is
 +   meant to be a built-in version number for what kind of struct the caller
 +   expects. If the struct ever changes, we redefine the NOW to another enum
 +   from above. */
 +#define CURLVERSION_NOW CURLVERSION_FIFTH
 +
 +typedef struct {
 +  CURLversion age;          /* age of the returned struct */
 +  const char *version;      /* LIBCURL_VERSION */
 +  unsigned int version_num; /* LIBCURL_VERSION_NUM */
 +  const char *host;         /* OS/host/cpu/machine when configured */
 +  int features;             /* bitmask, see defines below */
 +  const char *ssl_version;  /* human readable string */
 +  long ssl_version_num;     /* not used anymore, always 0 */
 +  const char *libz_version; /* human readable string */
 +  /* protocols is terminated by an entry with a NULL protoname */
 +  const char * const *protocols;
 +
 +  /* The fields below this were added in CURLVERSION_SECOND */
 +  const char *ares;
 +  int ares_num;
 +
 +  /* This field was added in CURLVERSION_THIRD */
 +  const char *libidn;
 +
 +  /* These field were added in CURLVERSION_FOURTH */
 +
 +  /* Same as '_libiconv_version' if built with HAVE_ICONV */
 +  int iconv_ver_num;
 +
 +  const char *libssh_version; /* human readable string */
 +
 +  /* These fields were added in CURLVERSION_FIFTH */
 +
 +  unsigned int brotli_ver_num; /* Numeric Brotli version
 +                                  (MAJOR << 24) | (MINOR << 12) | PATCH */
 +  const char *brotli_version; /* human readable string. */
 +
 +} curl_version_info_data;
 +
 +#define CURL_VERSION_IPV6         (1<<0)  /* IPv6-enabled */
 +#define CURL_VERSION_KERBEROS4    (1<<1)  /* Kerberos V4 auth is supported
 +                                             (deprecated) */
 +#define CURL_VERSION_SSL          (1<<2)  /* SSL options are present */
 +#define CURL_VERSION_LIBZ         (1<<3)  /* libz features are present */
 +#define CURL_VERSION_NTLM         (1<<4)  /* NTLM auth is supported */
 +#define CURL_VERSION_GSSNEGOTIATE (1<<5)  /* Negotiate auth is supported
 +                                             (deprecated) */
 +#define CURL_VERSION_DEBUG        (1<<6)  /* Built with debug capabilities */
 +#define CURL_VERSION_ASYNCHDNS    (1<<7)  /* Asynchronous DNS resolves */
 +#define CURL_VERSION_SPNEGO       (1<<8)  /* SPNEGO auth is supported */
 +#define CURL_VERSION_LARGEFILE    (1<<9)  /* Supports files larger than 2GB */
 +#define CURL_VERSION_IDN          (1<<10) /* Internationized Domain Names are
 +                                             supported */
 +#define CURL_VERSION_SSPI         (1<<11) /* Built against Windows SSPI */
 +#define CURL_VERSION_CONV         (1<<12) /* Character conversions supported */
 +#define CURL_VERSION_CURLDEBUG    (1<<13) /* Debug memory tracking supported */
 +#define CURL_VERSION_TLSAUTH_SRP  (1<<14) /* TLS-SRP auth is supported */
 +#define CURL_VERSION_NTLM_WB      (1<<15) /* NTLM delegation to winbind helper
 +                                             is supported */
 +#define CURL_VERSION_HTTP2        (1<<16) /* HTTP2 support built-in */
 +#define CURL_VERSION_GSSAPI       (1<<17) /* Built against a GSS-API library */
 +#define CURL_VERSION_KERBEROS5    (1<<18) /* Kerberos V5 auth is supported */
 +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
 +#define CURL_VERSION_PSL          (1<<20) /* Mozilla's Public Suffix List, used
 +                                             for cookie domain verification */
 +#define CURL_VERSION_HTTPS_PROXY  (1<<21) /* HTTPS-proxy support built-in */
 +#define CURL_VERSION_MULTI_SSL    (1<<22) /* Multiple SSL backends available */
 +#define CURL_VERSION_BROTLI       (1<<23) /* Brotli features are present. */
++#define CURL_VERSION_ALTSVC       (1<<24) /* Alt-Svc handling built-in */
 +
 + /*
 + * NAME curl_version_info()
 + *
 + * DESCRIPTION
 + *
 + * This function returns a pointer to a static copy of the version info
 + * struct. See above.
 + */
 +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
 +
 +/*
 + * NAME curl_easy_strerror()
 + *
 + * DESCRIPTION
 + *
 + * The curl_easy_strerror function may be used to turn a CURLcode value
 + * into the equivalent human readable error string.  This is useful
 + * for printing meaningful error messages.
 + */
 +CURL_EXTERN const char *curl_easy_strerror(CURLcode);
 +
 +/*
 + * NAME curl_share_strerror()
 + *
 + * DESCRIPTION
 + *
 + * The curl_share_strerror function may be used to turn a CURLSHcode value
 + * into the equivalent human readable error string.  This is useful
 + * for printing meaningful error messages.
 + */
 +CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
 +
 +/*
 + * NAME curl_easy_pause()
 + *
 + * DESCRIPTION
 + *
 + * The curl_easy_pause function pauses or unpauses transfers. Select the new
 + * state by setting the bitmask, use the convenience defines below.
 + *
 + */
 +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
 +
 +#define CURLPAUSE_RECV      (1<<0)
 +#define CURLPAUSE_RECV_CONT (0)
 +
 +#define CURLPAUSE_SEND      (1<<2)
 +#define CURLPAUSE_SEND_CONT (0)
 +
 +#define CURLPAUSE_ALL       (CURLPAUSE_RECV|CURLPAUSE_SEND)
 +#define CURLPAUSE_CONT      (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
 +
 +#ifdef  __cplusplus
 +}
 +#endif
 +
 +/* unfortunately, the easy.h and multi.h include files need options and info
 +  stuff before they can be included! */
 +#include "easy.h" /* nothing in curl is fun without the easy stuff */
 +#include "multi.h"
 +#include "urlapi.h"
 +
 +/* the typechecker doesn't work in C++ (yet) */
 +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
 +    ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \
 +    !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK)
 +#include "typecheck-gcc.h"
 +#else
 +#if defined(__STDC__) && (__STDC__ >= 1)
 +#if 0 /* Triggers clang -Wdisabled-macro-expansion, skip for CMake.  */
 +/* This preprocessor magic that replaces a call with the exact same call is
 +   only done to make sure application authors pass exactly three arguments
 +   to these functions. */
 +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param)
 +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg)
 +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
 +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
 +#endif
 +#endif /* __STDC__ >= 1 */
 +#endif /* gcc >= 4.3 && !__cplusplus */
 +
 +#endif /* __CURL_CURL_H */
diff --cc Utilities/cmcurl/include/curl/curlver.h
index 3d7b1fb,0000000..04efb93
mode 100644,000000..100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@@ -1,77 -1,0 +1,77 @@@
 +#ifndef __CURL_CURLVER_H
 +#define __CURL_CURLVER_H
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
-  * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
++ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
 + *
 + * This software is licensed as described in the file COPYING, which
 + * you should have received as part of this distribution. The terms
 + * are also available at https://curl.haxx.se/docs/copyright.html.
 + *
 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 + * copies of the Software, and permit persons to whom the Software is
 + * furnished to do so, under the terms of the COPYING file.
 + *
 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 + * KIND, either express or implied.
 + *
 + ***************************************************************************/
 +
 +/* This header file contains nothing but libcurl version info, generated by
 +   a script at release-time. This was made its own header file in 7.11.2 */
 +
 +/* This is the global package copyright */
- #define LIBCURL_COPYRIGHT "1996 - 2018 Daniel Stenberg, <daniel at haxx.se>."
++#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, <daniel at haxx.se>."
 +
 +/* This is the version number of the libcurl package from which this header
 +   file origins: */
- #define LIBCURL_VERSION "7.62.0"
++#define LIBCURL_VERSION "7.65.0"
 +
 +/* The numeric version number is also available "in parts" by using these
 +   defines: */
 +#define LIBCURL_VERSION_MAJOR 7
- #define LIBCURL_VERSION_MINOR 62
++#define LIBCURL_VERSION_MINOR 65
 +#define LIBCURL_VERSION_PATCH 0
 +
 +/* This is the numeric version of the libcurl version number, meant for easier
 +   parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
 +   always follow this syntax:
 +
 +         0xXXYYZZ
 +
 +   Where XX, YY and ZZ are the main version, release and patch numbers in
 +   hexadecimal (using 8 bits each). All three numbers are always represented
 +   using two digits.  1.2 would appear as "0x010200" while version 9.11.7
 +   appears as "0x090b07".
 +
 +   This 6-digit (24 bits) hexadecimal number does not show pre-release number,
 +   and it is always a greater number in a more recent release. It makes
 +   comparisons with greater than and less than work.
 +
 +   Note: This define is the full hex number and _does not_ use the
 +   CURL_VERSION_BITS() macro since curl's own configure script greps for it
 +   and needs it to contain the full number.
 +*/
- #define LIBCURL_VERSION_NUM 0x073E00
++#define LIBCURL_VERSION_NUM 0x074100
 +
 +/*
 + * This is the date and time when the full source package was created. The
 + * timestamp is not stored in git, as the timestamp is properly set in the
 + * tarballs by the maketgz script.
 + *
 + * The format of the date follows this template:
 + *
 + * "2007-11-23"
 + */
 +#define LIBCURL_TIMESTAMP "[unreleased]"
 +
- #define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
++#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
 +#define CURL_AT_LEAST_VERSION(x,y,z) \
 +  (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
 +
 +#endif /* __CURL_CURLVER_H */
diff --cc Utilities/cmcurl/lib/altsvc.c
index 0000000,85a4e01..85a4e01
mode 000000,100644..100644
--- a/Utilities/cmcurl/lib/altsvc.c
+++ b/Utilities/cmcurl/lib/altsvc.c
diff --cc Utilities/cmcurl/lib/altsvc.h
index 0000000,eefb45b..eefb45b
mode 000000,100644..100644
--- a/Utilities/cmcurl/lib/altsvc.h
+++ b/Utilities/cmcurl/lib/altsvc.h
diff --cc Utilities/cmcurl/lib/curl_config.h.cmake
index d5e3a90,0000000..b285c3f
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@@ -1,1018 -1,0 +1,1024 @@@
 +/* lib/curl_config.h.in.  Generated somehow by cmake.  */
 +
 +/* when building libcurl itself */
 +#cmakedefine BUILDING_LIBCURL 1
 +
 +/* to disable cookies support */
 +#cmakedefine CURL_DISABLE_COOKIES 1
 +
 +/* to disable cryptographic authentication */
 +#cmakedefine CURL_DISABLE_CRYPTO_AUTH 1
 +
 +/* to disable DICT */
 +#cmakedefine CURL_DISABLE_DICT 1
 +
 +/* to disable FILE */
 +#cmakedefine CURL_DISABLE_FILE 1
 +
 +/* to disable FTP */
 +#cmakedefine CURL_DISABLE_FTP 1
 +
 +/* to disable GOPHER */
 +#cmakedefine CURL_DISABLE_GOPHER 1
 +
 +/* to disable IMAP */
 +#cmakedefine CURL_DISABLE_IMAP 1
 +
 +/* to disable HTTP */
 +#cmakedefine CURL_DISABLE_HTTP 1
 +
 +/* to disable LDAP */
 +#cmakedefine CURL_DISABLE_LDAP 1
 +
 +/* to disable LDAPS */
 +#cmakedefine CURL_DISABLE_LDAPS 1
 +
 +/* to disable POP3 */
 +#cmakedefine CURL_DISABLE_POP3 1
 +
 +/* to disable proxies */
 +#cmakedefine CURL_DISABLE_PROXY 1
 +
 +/* to disable RTSP */
 +#cmakedefine CURL_DISABLE_RTSP 1
 +
 +/* to disable SMB */
 +#cmakedefine CURL_DISABLE_SMB 1
 +
 +/* to disable SMTP */
 +#cmakedefine CURL_DISABLE_SMTP 1
 +
 +/* to disable TELNET */
 +#cmakedefine CURL_DISABLE_TELNET 1
 +
 +/* to disable TFTP */
 +#cmakedefine CURL_DISABLE_TFTP 1
 +
 +/* to disable verbose strings */
 +#cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1
 +
 +/* to make a symbol visible */
 +#cmakedefine CURL_EXTERN_SYMBOL ${CURL_EXTERN_SYMBOL}
 +/* Ensure using CURL_EXTERN_SYMBOL is possible */
 +#ifndef CURL_EXTERN_SYMBOL
 +#define CURL_EXTERN_SYMBOL
 +#endif
 +
 +/* Use Windows LDAP implementation */
 +#cmakedefine USE_WIN32_LDAP 1
 +
 +/* when not building a shared library */
 +#cmakedefine CURL_STATICLIB 1
 +
 +/* your Entropy Gathering Daemon socket pathname */
 +#cmakedefine EGD_SOCKET ${EGD_SOCKET}
 +
 +/* Define if you want to enable IPv6 support */
 +#cmakedefine ENABLE_IPV6 1
 +
 +/* Define to the type qualifier of arg 1 for getnameinfo. */
 +#cmakedefine GETNAMEINFO_QUAL_ARG1 ${GETNAMEINFO_QUAL_ARG1}
 +
 +/* Define to the type of arg 1 for getnameinfo. */
 +#cmakedefine GETNAMEINFO_TYPE_ARG1 ${GETNAMEINFO_TYPE_ARG1}
 +
 +/* Define to the type of arg 2 for getnameinfo. */
 +#cmakedefine GETNAMEINFO_TYPE_ARG2 ${GETNAMEINFO_TYPE_ARG2}
 +
 +/* Define to the type of args 4 and 6 for getnameinfo. */
 +#cmakedefine GETNAMEINFO_TYPE_ARG46 ${GETNAMEINFO_TYPE_ARG46}
 +
 +/* Define to the type of arg 7 for getnameinfo. */
 +#cmakedefine GETNAMEINFO_TYPE_ARG7 ${GETNAMEINFO_TYPE_ARG7}
 +
 +/* Specifies the number of arguments to getservbyport_r */
 +#cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS}
 +
 +/* Specifies the size of the buffer to pass to getservbyport_r */
 +#cmakedefine GETSERVBYPORT_R_BUFSIZE ${GETSERVBYPORT_R_BUFSIZE}
 +
 +/* Define to 1 if you have the alarm function. */
 +#cmakedefine HAVE_ALARM 1
 +
 +/* Define to 1 if you have the <alloca.h> header file. */
 +#cmakedefine HAVE_ALLOCA_H 1
 +
 +/* Define to 1 if you have the <arpa/inet.h> header file. */
 +#cmakedefine HAVE_ARPA_INET_H 1
 +
 +/* Define to 1 if you have the <arpa/tftp.h> header file. */
 +#cmakedefine HAVE_ARPA_TFTP_H 1
 +
 +/* Define to 1 if you have the <assert.h> header file. */
 +#cmakedefine HAVE_ASSERT_H 1
 +
 +/* Define to 1 if you have the `basename' function. */
 +#cmakedefine HAVE_BASENAME 1
 +
 +/* Define to 1 if bool is an available type. */
 +#cmakedefine HAVE_BOOL_T 1
 +
 +/* Define to 1 if you have the __builtin_available function. */
 +#cmakedefine HAVE_BUILTIN_AVAILABLE 1
 +
 +/* Define to 1 if you have the clock_gettime function and monotonic timer. */
 +#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC 1
 +
 +/* Define to 1 if you have the `closesocket' function. */
 +#cmakedefine HAVE_CLOSESOCKET 1
 +
 +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
 +#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
 +
 +/* Define to 1 if you have the <crypto.h> header file. */
 +#cmakedefine HAVE_CRYPTO_H 1
 +
 +/* Define to 1 if you have the <des.h> header file. */
 +#cmakedefine HAVE_DES_H 1
 +
 +/* Define to 1 if you have the <dlfcn.h> header file. */
 +#cmakedefine HAVE_DLFCN_H 1
 +
 +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
 +#cmakedefine HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1
 +
 +/* Define to 1 if you have the <errno.h> header file. */
 +#cmakedefine HAVE_ERRNO_H 1
 +
 +/* Define to 1 if you have the <err.h> header file. */
 +#cmakedefine HAVE_ERR_H 1
 +
 +/* Define to 1 if you have the fcntl function. */
 +#cmakedefine HAVE_FCNTL 1
 +
 +/* Define to 1 if you have the <fcntl.h> header file. */
 +#cmakedefine HAVE_FCNTL_H 1
 +
 +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
 +#cmakedefine HAVE_FCNTL_O_NONBLOCK 1
 +
 +/* Define to 1 if you have the fdopen function. */
 +#cmakedefine HAVE_FDOPEN 1
 +
 +/* Define to 1 if you have the `fork' function. */
 +#cmakedefine HAVE_FORK 1
 +
 +/* Define to 1 if you have the freeaddrinfo function. */
 +#cmakedefine HAVE_FREEADDRINFO 1
 +
 +/* Define to 1 if you have the freeifaddrs function. */
 +#cmakedefine HAVE_FREEIFADDRS 1
 +
 +/* Define to 1 if you have the ftruncate function. */
 +#cmakedefine HAVE_FTRUNCATE 1
 +
 +/* Define to 1 if you have a working getaddrinfo function. */
 +#cmakedefine HAVE_GETADDRINFO 1
 +
 +/* Define to 1 if you have the `geteuid' function. */
 +#cmakedefine HAVE_GETEUID 1
 +
 +/* Define to 1 if you have the gethostbyaddr function. */
 +#cmakedefine HAVE_GETHOSTBYADDR 1
 +
 +/* Define to 1 if you have the gethostbyaddr_r function. */
 +#cmakedefine HAVE_GETHOSTBYADDR_R 1
 +
 +/* gethostbyaddr_r() takes 5 args */
 +#cmakedefine HAVE_GETHOSTBYADDR_R_5 1
 +
 +/* gethostbyaddr_r() takes 7 args */
 +#cmakedefine HAVE_GETHOSTBYADDR_R_7 1
 +
 +/* gethostbyaddr_r() takes 8 args */
 +#cmakedefine HAVE_GETHOSTBYADDR_R_8 1
 +
 +/* Define to 1 if you have the gethostbyname function. */
 +#cmakedefine HAVE_GETHOSTBYNAME 1
 +
 +/* Define to 1 if you have the gethostbyname_r function. */
 +#cmakedefine HAVE_GETHOSTBYNAME_R 1
 +
 +/* gethostbyname_r() takes 3 args */
 +#cmakedefine HAVE_GETHOSTBYNAME_R_3 1
 +
 +/* gethostbyname_r() takes 5 args */
 +#cmakedefine HAVE_GETHOSTBYNAME_R_5 1
 +
 +/* gethostbyname_r() takes 6 args */
 +#cmakedefine HAVE_GETHOSTBYNAME_R_6 1
 +
 +/* Define to 1 if you have the gethostname function. */
 +#cmakedefine HAVE_GETHOSTNAME 1
 +
 +/* Define to 1 if you have a working getifaddrs function. */
 +#cmakedefine HAVE_GETIFADDRS 1
 +
 +/* Define to 1 if you have the getnameinfo function. */
 +#cmakedefine HAVE_GETNAMEINFO 1
 +
 +/* Define to 1 if you have the `getpass_r' function. */
 +#cmakedefine HAVE_GETPASS_R 1
 +
 +/* Define to 1 if you have the `getppid' function. */
 +#cmakedefine HAVE_GETPPID 1
 +
 +/* Define to 1 if you have the `getprotobyname' function. */
 +#cmakedefine HAVE_GETPROTOBYNAME 1
 +
++/* Define to 1 if you have the `getpeername' function. */
++#cmakedefine HAVE_GETPEERNAME 1
++
++/* Define to 1 if you have the `getsockname' function. */
++#cmakedefine HAVE_GETSOCKNAME 1
++
 +/* Define to 1 if you have the `getpwuid' function. */
 +#cmakedefine HAVE_GETPWUID 1
 +
 +/* Define to 1 if you have the `getpwuid_r' function. */
 +#cmakedefine HAVE_GETPWUID_R 1
 +
 +/* Define to 1 if you have the `getrlimit' function. */
 +#cmakedefine HAVE_GETRLIMIT 1
 +
 +/* Define to 1 if you have the getservbyport_r function. */
 +#cmakedefine HAVE_GETSERVBYPORT_R 1
 +
 +/* Define to 1 if you have the `gettimeofday' function. */
 +#cmakedefine HAVE_GETTIMEOFDAY 1
 +
 +/* Define to 1 if you have a working glibc-style strerror_r function. */
 +#cmakedefine HAVE_GLIBC_STRERROR_R 1
 +
 +/* Define to 1 if you have a working gmtime_r function. */
 +#cmakedefine HAVE_GMTIME_R 1
 +
 +/* if you have the gssapi libraries */
 +#cmakedefine HAVE_GSSAPI 1
 +
 +/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
 +#cmakedefine HAVE_GSSAPI_GSSAPI_GENERIC_H 1
 +
 +/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
 +#cmakedefine HAVE_GSSAPI_GSSAPI_H 1
 +
 +/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
 +#cmakedefine HAVE_GSSAPI_GSSAPI_KRB5_H 1
 +
 +/* if you have the GNU gssapi libraries */
 +#cmakedefine HAVE_GSSGNU 1
 +
 +/* if you have the Heimdal gssapi libraries */
 +#cmakedefine HAVE_GSSHEIMDAL 1
 +
 +/* if you have the MIT gssapi libraries */
 +#cmakedefine HAVE_GSSMIT 1
 +
 +/* Define to 1 if you have the `idna_strerror' function. */
 +#cmakedefine HAVE_IDNA_STRERROR 1
 +
 +/* Define to 1 if you have the `idn_free' function. */
 +#cmakedefine HAVE_IDN_FREE 1
 +
 +/* Define to 1 if you have the <idn-free.h> header file. */
 +#cmakedefine HAVE_IDN_FREE_H 1
 +
 +/* Define to 1 if you have the <ifaddrs.h> header file. */
 +#cmakedefine HAVE_IFADDRS_H 1
 +
 +/* Define to 1 if you have the `inet_addr' function. */
 +#cmakedefine HAVE_INET_ADDR 1
 +
 +/* Define to 1 if you have the inet_ntoa_r function. */
 +#cmakedefine HAVE_INET_NTOA_R 1
 +
 +/* inet_ntoa_r() takes 2 args */
 +#cmakedefine HAVE_INET_NTOA_R_2 1
 +
 +/* inet_ntoa_r() takes 3 args */
 +#cmakedefine HAVE_INET_NTOA_R_3 1
 +
 +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
 +#cmakedefine HAVE_INET_NTOP 1
 +
 +/* Define to 1 if you have a IPv6 capable working inet_pton function. */
 +#cmakedefine HAVE_INET_PTON 1
 +
 +/* Define to 1 if you have the <inttypes.h> header file. */
 +#cmakedefine HAVE_INTTYPES_H 1
 +
 +/* Define to 1 if you have the ioctl function. */
 +#cmakedefine HAVE_IOCTL 1
 +
 +/* Define to 1 if you have the ioctlsocket function. */
 +#cmakedefine HAVE_IOCTLSOCKET 1
 +
 +/* Define to 1 if you have the IoctlSocket camel case function. */
 +#cmakedefine HAVE_IOCTLSOCKET_CAMEL 1
 +
 +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
 +   */
 +#cmakedefine HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1
 +
 +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
 +#cmakedefine HAVE_IOCTLSOCKET_FIONBIO 1
 +
 +/* Define to 1 if you have a working ioctl FIONBIO function. */
 +#cmakedefine HAVE_IOCTL_FIONBIO 1
 +
 +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
 +#cmakedefine HAVE_IOCTL_SIOCGIFADDR 1
 +
 +/* Define to 1 if you have the <io.h> header file. */
 +#cmakedefine HAVE_IO_H 1
 +
 +/* if you have the Kerberos4 libraries (including -ldes) */
 +#cmakedefine HAVE_KRB4 1
 +
 +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
 +#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM 1
 +
 +/* Define to 1 if you have the <krb.h> header file. */
 +#cmakedefine HAVE_KRB_H 1
 +
 +/* Define to 1 if you have the lber.h header file. */
 +#cmakedefine HAVE_LBER_H 1
 +
 +/* Define to 1 if you have the ldapssl.h header file. */
 +#cmakedefine HAVE_LDAPSSL_H 1
 +
 +/* Define to 1 if you have the ldap.h header file. */
 +#cmakedefine HAVE_LDAP_H 1
 +
 +/* Use LDAPS implementation */
 +#cmakedefine HAVE_LDAP_SSL 1
 +
 +/* Define to 1 if you have the ldap_ssl.h header file. */
 +#cmakedefine HAVE_LDAP_SSL_H 1
 +
 +/* Define to 1 if you have the `ldap_url_parse' function. */
 +#cmakedefine HAVE_LDAP_URL_PARSE 1
 +
 +/* Define to 1 if you have the <libgen.h> header file. */
 +#cmakedefine HAVE_LIBGEN_H 1
 +
 +/* Define to 1 if you have the `idn' library (-lidn). */
 +#cmakedefine HAVE_LIBIDN 1
 +
 +/* Define to 1 if you have the `resolv' library (-lresolv). */
 +#cmakedefine HAVE_LIBRESOLV 1
 +
 +/* Define to 1 if you have the `resolve' library (-lresolve). */
 +#cmakedefine HAVE_LIBRESOLVE 1
 +
 +/* Define to 1 if you have the `socket' library (-lsocket). */
 +#cmakedefine HAVE_LIBSOCKET 1
 +
 +/* Define to 1 if you have the `ssh2' library (-lssh2). */
 +#cmakedefine HAVE_LIBSSH2 1
 +
 +/* Define to 1 if libssh2 provides `libssh2_version'. */
 +#cmakedefine HAVE_LIBSSH2_VERSION 1
 +
 +/* Define to 1 if libssh2 provides `libssh2_init'. */
 +#cmakedefine HAVE_LIBSSH2_INIT 1
 +
 +/* Define to 1 if libssh2 provides `libssh2_exit'. */
 +#cmakedefine HAVE_LIBSSH2_EXIT 1
 +
 +/* Define to 1 if libssh2 provides `libssh2_scp_send64'. */
 +#cmakedefine HAVE_LIBSSH2_SCP_SEND64 1
 +
 +/* Define to 1 if libssh2 provides `libssh2_session_handshake'. */
 +#cmakedefine HAVE_LIBSSH2_SESSION_HANDSHAKE 1
 +
 +/* Define to 1 if you have the <libssh2.h> header file. */
 +#cmakedefine HAVE_LIBSSH2_H 1
 +
 +/* Define to 1 if you have the `ssl' library (-lssl). */
 +#cmakedefine HAVE_LIBSSL 1
 +
 +/* if zlib is available */
 +#cmakedefine HAVE_LIBZ 1
 +
 +/* if brotli is available */
 +#cmakedefine HAVE_BROTLI 1
 +
 +/* if your compiler supports LL */
 +#cmakedefine HAVE_LL 1
 +
 +/* Define to 1 if you have the <locale.h> header file. */
 +#cmakedefine HAVE_LOCALE_H 1
 +
 +/* Define to 1 if you have a working localtime_r function. */
 +#cmakedefine HAVE_LOCALTIME_R 1
 +
 +/* Define to 1 if the compiler supports the 'long long' data type. */
 +#cmakedefine HAVE_LONGLONG 1
 +
 +/* Define to 1 if you have the malloc.h header file. */
 +#cmakedefine HAVE_MALLOC_H 1
 +
 +/* Define to 1 if you have the <memory.h> header file. */
 +#cmakedefine HAVE_MEMORY_H 1
 +
 +/* Define to 1 if you have the MSG_NOSIGNAL flag. */
 +#cmakedefine HAVE_MSG_NOSIGNAL 1
 +
 +/* Define to 1 if you have the <netdb.h> header file. */
 +#cmakedefine HAVE_NETDB_H 1
 +
 +/* Define to 1 if you have the <netinet/in.h> header file. */
 +#cmakedefine HAVE_NETINET_IN_H 1
 +
 +/* Define to 1 if you have the <netinet/tcp.h> header file. */
 +#cmakedefine HAVE_NETINET_TCP_H 1
 +
 +/* Define to 1 if you have the <net/if.h> header file. */
 +#cmakedefine HAVE_NET_IF_H 1
 +
 +/* Define to 1 if NI_WITHSCOPEID exists and works. */
 +#cmakedefine HAVE_NI_WITHSCOPEID 1
 +
 +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE */
 +#cmakedefine HAVE_OLD_GSSMIT 1
 +
 +/* Define to 1 if you have the <openssl/crypto.h> header file. */
 +#cmakedefine HAVE_OPENSSL_CRYPTO_H 1
 +
 +/* Define to 1 if you have the <openssl/engine.h> header file. */
 +#cmakedefine HAVE_OPENSSL_ENGINE_H 1
 +
 +/* Define to 1 if you have the <openssl/err.h> header file. */
 +#cmakedefine HAVE_OPENSSL_ERR_H 1
 +
 +/* Define to 1 if you have the <openssl/pem.h> header file. */
 +#cmakedefine HAVE_OPENSSL_PEM_H 1
 +
 +/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
 +#cmakedefine HAVE_OPENSSL_PKCS12_H 1
 +
 +/* Define to 1 if you have the <openssl/rsa.h> header file. */
 +#cmakedefine HAVE_OPENSSL_RSA_H 1
 +
 +/* Define to 1 if you have the <openssl/ssl.h> header file. */
 +#cmakedefine HAVE_OPENSSL_SSL_H 1
 +
 +/* Define to 1 if you have the <openssl/x509.h> header file. */
 +#cmakedefine HAVE_OPENSSL_X509_H 1
 +
 +/* Define to 1 if you have the <pem.h> header file. */
 +#cmakedefine HAVE_PEM_H 1
 +
 +/* Define to 1 if you have the `perror' function. */
 +#cmakedefine HAVE_PERROR 1
 +
 +/* Define to 1 if you have the `pipe' function. */
 +#cmakedefine HAVE_PIPE 1
 +
 +/* Define to 1 if you have a working poll function. */
 +#cmakedefine HAVE_POLL 1
 +
 +/* If you have a fine poll */
 +#cmakedefine HAVE_POLL_FINE 1
 +
 +/* Define to 1 if you have the <poll.h> header file. */
 +#cmakedefine HAVE_POLL_H 1
 +
 +/* Define to 1 if you have a working POSIX-style strerror_r function. */
 +#cmakedefine HAVE_POSIX_STRERROR_R 1
 +
 +/* Define to 1 if you have the <pthread.h> header file */
 +#cmakedefine HAVE_PTHREAD_H 1
 +
 +/* Define to 1 if you have the <pwd.h> header file. */
 +#cmakedefine HAVE_PWD_H 1
 +
 +/* Define to 1 if you have the `RAND_egd' function. */
 +#cmakedefine HAVE_RAND_EGD 1
 +
 +/* Define to 1 if you have the `RAND_screen' function. */
 +#cmakedefine HAVE_RAND_SCREEN 1
 +
 +/* Define to 1 if you have the `RAND_status' function. */
 +#cmakedefine HAVE_RAND_STATUS 1
 +
 +/* Define to 1 if you have the recv function. */
 +#cmakedefine HAVE_RECV 1
 +
 +/* Define to 1 if you have the recvfrom function. */
 +#cmakedefine HAVE_RECVFROM 1
 +
 +/* Define to 1 if you have the <rsa.h> header file. */
 +#cmakedefine HAVE_RSA_H 1
 +
 +/* Define to 1 if you have the select function. */
 +#cmakedefine HAVE_SELECT 1
 +
 +/* Define to 1 if you have the send function. */
 +#cmakedefine HAVE_SEND 1
 +
 +/* Define to 1 if you have the 'fsetxattr' function. */
 +#cmakedefine HAVE_FSETXATTR 1
 +
 +/* fsetxattr() takes 5 args */
 +#cmakedefine HAVE_FSETXATTR_5 1
 +
 +/* fsetxattr() takes 6 args */
 +#cmakedefine HAVE_FSETXATTR_6 1
 +
 +/* Define to 1 if you have the <setjmp.h> header file. */
 +#cmakedefine HAVE_SETJMP_H 1
 +
 +/* Define to 1 if you have the `setlocale' function. */
 +#cmakedefine HAVE_SETLOCALE 1
 +
 +/* Define to 1 if you have the `setmode' function. */
 +#cmakedefine HAVE_SETMODE 1
 +
 +/* Define to 1 if you have the `setrlimit' function. */
 +#cmakedefine HAVE_SETRLIMIT 1
 +
 +/* Define to 1 if you have the setsockopt function. */
 +#cmakedefine HAVE_SETSOCKOPT 1
 +
 +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
 +#cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1
 +
 +/* Define to 1 if you have the <sgtty.h> header file. */
 +#cmakedefine HAVE_SGTTY_H 1
 +
 +/* Define to 1 if you have the sigaction function. */
 +#cmakedefine HAVE_SIGACTION 1
 +
 +/* Define to 1 if you have the siginterrupt function. */
 +#cmakedefine HAVE_SIGINTERRUPT 1
 +
 +/* Define to 1 if you have the signal function. */
 +#cmakedefine HAVE_SIGNAL 1
 +
 +/* Define to 1 if you have the <signal.h> header file. */
 +#cmakedefine HAVE_SIGNAL_H 1
 +
 +/* Define to 1 if you have the sigsetjmp function or macro. */
 +#cmakedefine HAVE_SIGSETJMP 1
 +
 +/* Define to 1 if sig_atomic_t is an available typedef. */
 +#cmakedefine HAVE_SIG_ATOMIC_T 1
 +
 +/* Define to 1 if sig_atomic_t is already defined as volatile. */
 +#cmakedefine HAVE_SIG_ATOMIC_T_VOLATILE 1
 +
 +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
 +#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
 +
 +/* Define to 1 if you have the `socket' function. */
 +#cmakedefine HAVE_SOCKET 1
 +
 +/* Define to 1 if you have the `SSL_get_shutdown' function. */
 +#cmakedefine HAVE_SSL_GET_SHUTDOWN 1
 +
 +/* Define to 1 if you have the <ssl.h> header file. */
 +#cmakedefine HAVE_SSL_H 1
 +
 +/* Define to 1 if you have the <stdbool.h> header file. */
 +#cmakedefine HAVE_STDBOOL_H 1
 +
 +/* Define to 1 if you have the <stdint.h> header file. */
 +#cmakedefine HAVE_STDINT_H 1
 +
 +/* Define to 1 if you have the <stdio.h> header file. */
 +#cmakedefine HAVE_STDIO_H 1
 +
 +/* Define to 1 if you have the <stdlib.h> header file. */
 +#cmakedefine HAVE_STDLIB_H 1
 +
 +/* Define to 1 if you have the strcasecmp function. */
 +#cmakedefine HAVE_STRCASECMP 1
 +
 +/* Define to 1 if you have the strcasestr function. */
 +#cmakedefine HAVE_STRCASESTR 1
 +
 +/* Define to 1 if you have the strcmpi function. */
 +#cmakedefine HAVE_STRCMPI 1
 +
 +/* Define to 1 if you have the strdup function. */
 +#cmakedefine HAVE_STRDUP 1
 +
 +/* Define to 1 if you have the strerror_r function. */
 +#cmakedefine HAVE_STRERROR_R 1
 +
 +/* Define to 1 if you have the stricmp function. */
 +#cmakedefine HAVE_STRICMP 1
 +
 +/* Define to 1 if you have the <strings.h> header file. */
 +#cmakedefine HAVE_STRINGS_H 1
 +
 +/* Define to 1 if you have the <string.h> header file. */
 +#cmakedefine HAVE_STRING_H 1
 +
 +/* Define to 1 if you have the strlcat function. */
 +#cmakedefine HAVE_STRLCAT 1
 +
 +/* Define to 1 if you have the `strlcpy' function. */
 +#cmakedefine HAVE_STRLCPY 1
 +
 +/* Define to 1 if you have the strncasecmp function. */
 +#cmakedefine HAVE_STRNCASECMP 1
 +
 +/* Define to 1 if you have the strncmpi function. */
 +#cmakedefine HAVE_STRNCMPI 1
 +
 +/* Define to 1 if you have the strnicmp function. */
 +#cmakedefine HAVE_STRNICMP 1
 +
 +/* Define to 1 if you have the <stropts.h> header file. */
 +#cmakedefine HAVE_STROPTS_H 1
 +
 +/* Define to 1 if you have the strstr function. */
 +#cmakedefine HAVE_STRSTR 1
 +
 +/* Define to 1 if you have the strtok_r function. */
 +#cmakedefine HAVE_STRTOK_R 1
 +
 +/* Define to 1 if you have the strtoll function. */
 +#cmakedefine HAVE_STRTOLL 1
 +
 +/* if struct sockaddr_storage is defined */
 +#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE 1
 +
 +/* Define to 1 if you have the timeval struct. */
 +#cmakedefine HAVE_STRUCT_TIMEVAL 1
 +
 +/* Define to 1 if you have the <sys/filio.h> header file. */
 +#cmakedefine HAVE_SYS_FILIO_H 1
 +
 +/* Define to 1 if you have the <sys/ioctl.h> header file. */
 +#cmakedefine HAVE_SYS_IOCTL_H 1
 +
 +/* Define to 1 if you have the <sys/param.h> header file. */
 +#cmakedefine HAVE_SYS_PARAM_H 1
 +
 +/* Define to 1 if you have the <sys/poll.h> header file. */
 +#cmakedefine HAVE_SYS_POLL_H 1
 +
 +/* Define to 1 if you have the <sys/resource.h> header file. */
 +#cmakedefine HAVE_SYS_RESOURCE_H 1
 +
 +/* Define to 1 if you have the <sys/select.h> header file. */
 +#cmakedefine HAVE_SYS_SELECT_H 1
 +
 +/* Define to 1 if you have the <sys/socket.h> header file. */
 +#cmakedefine HAVE_SYS_SOCKET_H 1
 +
 +/* Define to 1 if you have the <sys/sockio.h> header file. */
 +#cmakedefine HAVE_SYS_SOCKIO_H 1
 +
 +/* Define to 1 if you have the <sys/stat.h> header file. */
 +#cmakedefine HAVE_SYS_STAT_H 1
 +
 +/* Define to 1 if you have the <sys/time.h> header file. */
 +#cmakedefine HAVE_SYS_TIME_H 1
 +
 +/* Define to 1 if you have the <sys/types.h> header file. */
 +#cmakedefine HAVE_SYS_TYPES_H 1
 +
 +/* Define to 1 if you have the <sys/uio.h> header file. */
 +#cmakedefine HAVE_SYS_UIO_H 1
 +
 +/* Define to 1 if you have the <sys/un.h> header file. */
 +#cmakedefine HAVE_SYS_UN_H 1
 +
 +/* Define to 1 if you have the <sys/utime.h> header file. */
 +#cmakedefine HAVE_SYS_UTIME_H 1
 +
 +/* Define to 1 if you have the <termios.h> header file. */
 +#cmakedefine HAVE_TERMIOS_H 1
 +
 +/* Define to 1 if you have the <termio.h> header file. */
 +#cmakedefine HAVE_TERMIO_H 1
 +
 +/* Define to 1 if you have the <time.h> header file. */
 +#cmakedefine HAVE_TIME_H 1
 +
 +/* Define to 1 if you have the <tld.h> header file. */
 +#cmakedefine HAVE_TLD_H 1
 +
 +/* Define to 1 if you have the `tld_strerror' function. */
 +#cmakedefine HAVE_TLD_STRERROR 1
 +
 +/* Define to 1 if you have the `uname' function. */
 +#cmakedefine HAVE_UNAME 1
 +
 +/* Define to 1 if you have the <unistd.h> header file. */
 +#cmakedefine HAVE_UNISTD_H 1
 +
 +/* Define to 1 if you have the `utime' function. */
 +#cmakedefine HAVE_UTIME 1
 +
 +/* Define to 1 if you have the <utime.h> header file. */
 +#cmakedefine HAVE_UTIME_H 1
 +
 +/* Define to 1 if compiler supports C99 variadic macro style. */
 +#cmakedefine HAVE_VARIADIC_MACROS_C99 1
 +
 +/* Define to 1 if compiler supports old gcc variadic macro style. */
 +#cmakedefine HAVE_VARIADIC_MACROS_GCC 1
 +
 +/* Define to 1 if you have the winber.h header file. */
 +#cmakedefine HAVE_WINBER_H 1
 +
 +/* Define to 1 if you have the windows.h header file. */
 +#cmakedefine HAVE_WINDOWS_H 1
 +
 +/* Define to 1 if you have the winldap.h header file. */
 +#cmakedefine HAVE_WINLDAP_H 1
 +
 +/* Define to 1 if you have the winsock2.h header file. */
 +#cmakedefine HAVE_WINSOCK2_H 1
 +
 +/* Define to 1 if you have the winsock.h header file. */
 +#cmakedefine HAVE_WINSOCK_H 1
 +
 +/* Define this symbol if your OS supports changing the contents of argv */
 +#cmakedefine HAVE_WRITABLE_ARGV 1
 +
 +/* Define to 1 if you have the writev function. */
 +#cmakedefine HAVE_WRITEV 1
 +
 +/* Define to 1 if you have the ws2tcpip.h header file. */
 +#cmakedefine HAVE_WS2TCPIP_H 1
 +
 +/* Define to 1 if you have the <x509.h> header file. */
 +#cmakedefine HAVE_X509_H 1
 +
 +/* Define if you have the <process.h> header file. */
 +#cmakedefine HAVE_PROCESS_H 1
 +
 +/* if you have the zlib.h header file */
 +#cmakedefine HAVE_ZLIB_H 1
 +
 +/* Define to the sub-directory in which libtool stores uninstalled libraries.
 +   */
 +#cmakedefine LT_OBJDIR ${LT_OBJDIR}
 +
 +/* If you lack a fine basename() prototype */
 +#cmakedefine NEED_BASENAME_PROTO 1
 +
 +/* Define to 1 if you need the lber.h header file even with ldap.h */
 +#cmakedefine NEED_LBER_H 1
 +
 +/* Define to 1 if you need the malloc.h header file even with stdlib.h */
 +#cmakedefine NEED_MALLOC_H 1
 +
 +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
 +#cmakedefine NEED_REENTRANT 1
 +
 +/* cpu-machine-OS */
 +#cmakedefine OS ${OS}
 +
 +/* Name of package */
 +#cmakedefine PACKAGE ${PACKAGE}
 +
 +/* Define to the address where bug reports for this package should be sent. */
 +#cmakedefine PACKAGE_BUGREPORT ${PACKAGE_BUGREPORT}
 +
 +/* Define to the full name of this package. */
 +#cmakedefine PACKAGE_NAME ${PACKAGE_NAME}
 +
 +/* Define to the full name and version of this package. */
 +#cmakedefine PACKAGE_STRING ${PACKAGE_STRING}
 +
 +/* Define to the one symbol short name of this package. */
 +#cmakedefine PACKAGE_TARNAME ${PACKAGE_TARNAME}
 +
 +/* Define to the version of this package. */
 +#cmakedefine PACKAGE_VERSION ${PACKAGE_VERSION}
 +
 +/* a suitable file to read random data from */
 +#cmakedefine RANDOM_FILE "${RANDOM_FILE}"
 +
 +/* Define to the type of arg 1 for recvfrom. */
 +#cmakedefine RECVFROM_TYPE_ARG1 ${RECVFROM_TYPE_ARG1}
 +
 +/* Define to the type pointed by arg 2 for recvfrom. */
 +#cmakedefine RECVFROM_TYPE_ARG2 ${RECVFROM_TYPE_ARG2}
 +
 +/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */
 +#cmakedefine RECVFROM_TYPE_ARG2_IS_VOID 1
 +
 +/* Define to the type of arg 3 for recvfrom. */
 +#cmakedefine RECVFROM_TYPE_ARG3 ${RECVFROM_TYPE_ARG3}
 +
 +/* Define to the type of arg 4 for recvfrom. */
 +#cmakedefine RECVFROM_TYPE_ARG4 ${RECVFROM_TYPE_ARG4}
 +
 +/* Define to the type pointed by arg 5 for recvfrom. */
 +#cmakedefine RECVFROM_TYPE_ARG5 ${RECVFROM_TYPE_ARG5}
 +
 +/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */
 +#cmakedefine RECVFROM_TYPE_ARG5_IS_VOID 1
 +
 +/* Define to the type pointed by arg 6 for recvfrom. */
 +#cmakedefine RECVFROM_TYPE_ARG6 ${RECVFROM_TYPE_ARG6}
 +
 +/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */
 +#cmakedefine RECVFROM_TYPE_ARG6_IS_VOID 1
 +
 +/* Define to the function return type for recvfrom. */
 +#cmakedefine RECVFROM_TYPE_RETV ${RECVFROM_TYPE_RETV}
 +
 +/* Define to the type of arg 1 for recv. */
 +#cmakedefine RECV_TYPE_ARG1 ${RECV_TYPE_ARG1}
 +
 +/* Define to the type of arg 2 for recv. */
 +#cmakedefine RECV_TYPE_ARG2 ${RECV_TYPE_ARG2}
 +
 +/* Define to the type of arg 3 for recv. */
 +#cmakedefine RECV_TYPE_ARG3 ${RECV_TYPE_ARG3}
 +
 +/* Define to the type of arg 4 for recv. */
 +#cmakedefine RECV_TYPE_ARG4 ${RECV_TYPE_ARG4}
 +
 +/* Define to the function return type for recv. */
 +#cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV}
 +
 +/* Define as the return type of signal handlers (`int' or `void'). */
 +#cmakedefine RETSIGTYPE ${RETSIGTYPE}
 +
 +/* Define to the type qualifier of arg 5 for select. */
 +#cmakedefine SELECT_QUAL_ARG5 ${SELECT_QUAL_ARG5}
 +
 +/* Define to the type of arg 1 for select. */
 +#cmakedefine SELECT_TYPE_ARG1 ${SELECT_TYPE_ARG1}
 +
 +/* Define to the type of args 2, 3 and 4 for select. */
 +#cmakedefine SELECT_TYPE_ARG234 ${SELECT_TYPE_ARG234}
 +
 +/* Define to the type of arg 5 for select. */
 +#cmakedefine SELECT_TYPE_ARG5 ${SELECT_TYPE_ARG5}
 +
 +/* Define to the function return type for select. */
 +#cmakedefine SELECT_TYPE_RETV ${SELECT_TYPE_RETV}
 +
 +/* Define to the type qualifier of arg 2 for send. */
 +#cmakedefine SEND_QUAL_ARG2 ${SEND_QUAL_ARG2}
 +
 +/* Define to the type of arg 1 for send. */
 +#cmakedefine SEND_TYPE_ARG1 ${SEND_TYPE_ARG1}
 +
 +/* Define to the type of arg 2 for send. */
 +#cmakedefine SEND_TYPE_ARG2 ${SEND_TYPE_ARG2}
 +
 +/* Define to the type of arg 3 for send. */
 +#cmakedefine SEND_TYPE_ARG3 ${SEND_TYPE_ARG3}
 +
 +/* Define to the type of arg 4 for send. */
 +#cmakedefine SEND_TYPE_ARG4 ${SEND_TYPE_ARG4}
 +
 +/* Define to the function return type for send. */
 +#cmakedefine SEND_TYPE_RETV ${SEND_TYPE_RETV}
 +
 +/* The size of `int', as computed by sizeof. */
 + at SIZEOF_INT_CODE@
 +
 +/* The size of `short', as computed by sizeof. */
 + at SIZEOF_SHORT_CODE@
 +
 +/* The size of `long', as computed by sizeof. */
 + at SIZEOF_LONG_CODE@
 +
 +/* The size of `long long', as computed by sizeof. */
 + at SIZEOF_LONG_LONG_CODE@
 +
 +/* The size of `__int64', as computed by sizeof. */
 + at SIZEOF___INT64_CODE@
 +
 +/* The size of `off_t', as computed by sizeof. */
 + at SIZEOF_OFF_T_CODE@
 +
 +/* The size of `curl_off_t', as computed by sizeof. */
 + at SIZEOF_CURL_OFF_T_CODE@
 +
 +/* The size of `size_t', as computed by sizeof. */
 + at SIZEOF_SIZE_T_CODE@
 +
 +/* The size of `ssize_t', as computed by sizeof. */
 + at SIZEOF_SSIZE_T_CODE@
 +
 +/* The size of `time_t', as computed by sizeof. */
 + at SIZEOF_TIME_T_CODE@
 +
 +/* Define to 1 if you have the ANSI C header files. */
 +#cmakedefine STDC_HEADERS 1
 +
 +/* Define to the type of arg 3 for strerror_r. */
 +#cmakedefine STRERROR_R_TYPE_ARG3 ${STRERROR_R_TYPE_ARG3}
 +
 +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
 +#cmakedefine TIME_WITH_SYS_TIME 1
 +
 +/* Define if you want to enable c-ares support */
 +#cmakedefine USE_ARES 1
 +
 +/* Define if you want to enable POSIX threaded DNS lookup */
 +#cmakedefine USE_THREADS_POSIX 1
 +
 +/* Define if you want to enable WIN32 threaded DNS lookup */
 +#cmakedefine USE_THREADS_WIN32 1
 +
 +/* Define to disable non-blocking sockets. */
 +#cmakedefine USE_BLOCKING_SOCKETS 1
 +
 +/* if GnuTLS is enabled */
 +#cmakedefine USE_GNUTLS 1
 +
 +/* if PolarSSL is enabled */
 +#cmakedefine USE_POLARSSL 1
 +
- /* if DarwinSSL is enabled */
- #cmakedefine USE_DARWINSSL 1
++/* if Secure Transport is enabled */
++#cmakedefine USE_SECTRANSP 1
 +
 +/* if mbedTLS is enabled */
 +#cmakedefine USE_MBEDTLS 1
 +
 +/* if libSSH2 is in use */
 +#cmakedefine USE_LIBSSH2 1
 +
 +/* If you want to build curl with the built-in manual */
 +#cmakedefine USE_MANUAL 1
 +
 +/* if NSS is enabled */
 +#cmakedefine USE_NSS 1
 +
 +/* if you want to use OpenLDAP code instead of legacy ldap implementation */
 +#cmakedefine USE_OPENLDAP 1
 +
 +/* if OpenSSL is in use */
 +#cmakedefine USE_OPENSSL 1
 +
 +/* to enable NGHTTP2  */
 +#cmakedefine USE_NGHTTP2 1
 +
 +/* if Unix domain sockets are enabled  */
 +#cmakedefine USE_UNIX_SOCKETS
 +
 +/* to enable SSPI support */
 +#cmakedefine USE_WINDOWS_SSPI 1
 +
 +/* to enable Windows SSL  */
 +#cmakedefine USE_SCHANNEL 1
 +
 +/* enable multiple SSL backends */
 +#cmakedefine CURL_WITH_MULTI_SSL 1
 +
 +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
 +#cmakedefine USE_YASSLEMUL 1
 +
 +/* Version number of package */
 +#cmakedefine VERSION ${VERSION}
 +
 +/* Define to 1 if OS is AIX. */
 +#ifndef _ALL_SOURCE
 +#  undef _ALL_SOURCE
 +#endif
 +
 +/* Number of bits in a file offset, on hosts where this is settable. */
 +#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
 +
 +/* Define for large files, on AIX-style hosts. */
 +#cmakedefine _LARGE_FILES ${_LARGE_FILES}
 +
 +/* define this if you need it to compile thread-safe code */
 +#cmakedefine _THREAD_SAFE ${_THREAD_SAFE}
 +
 +/* Define to empty if `const' does not conform to ANSI C. */
 +#cmakedefine const ${const}
 +
 +/* Type to use in place of in_addr_t when system does not provide it. */
 +#cmakedefine in_addr_t ${in_addr_t}
 +
 +/* Define to `__inline__' or `__inline' if that's what the C compiler
 +   calls it, or to nothing if 'inline' is not supported under any name.  */
 +#ifndef __cplusplus
 +#undef inline
 +#endif
 +
 +/* Define to `unsigned int' if <sys/types.h> does not define. */
 +#cmakedefine size_t ${size_t}
 +
 +/* the signed version of size_t */
 +#ifndef SIZEOF_SSIZE_T
 +# if SIZEOF_LONG == SIZEOF_SIZE_T
 +   typedef long ssize_t;
 +# elif SIZEOF_LONG_LONG == SIZEOF_SIZE_T
 +   typedef long long ssize_t;
 +# elif SIZEOF___INT64 == SIZEOF_SIZE_T
 +   typedef __int64 ssize_t;
 +# else
 +   typedef int ssize_t;
 +# endif
 +#endif
 +
 +/* Define to 1 if you have the mach_absolute_time function. */
 +#cmakedefine HAVE_MACH_ABSOLUTE_TIME 1
diff --cc Utilities/cmcurl/lib/curl_setup.h
index 5cdbc592,0000000..efba5dd
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@@ -1,834 -1,0 +1,845 @@@
 +#ifndef HEADER_CURL_SETUP_H
 +#define HEADER_CURL_SETUP_H
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
-  * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
++ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
 + *
 + * This software is licensed as described in the file COPYING, which
 + * you should have received as part of this distribution. The terms
 + * are also available at https://curl.haxx.se/docs/copyright.html.
 + *
 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 + * copies of the Software, and permit persons to whom the Software is
 + * furnished to do so, under the terms of the COPYING file.
 + *
 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 + * KIND, either express or implied.
 + *
 + ***************************************************************************/
 +
 +#if defined(BUILDING_LIBCURL) && !defined(CURL_NO_OLDIES)
 +#define CURL_NO_OLDIES
 +#endif
 +
 +/*
 + * Define WIN32 when build target is Win32 API
 + */
 +
 +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \
 +    !defined(__SYMBIAN32__)
 +#define WIN32
 +#endif
 +
 +#ifdef WIN32
 +/*
 + * Don't include unneeded stuff in Windows headers to avoid compiler
 + * warnings and macro clashes.
 + * Make sure to define this macro before including any Windows headers.
 + */
 +#  ifndef WIN32_LEAN_AND_MEAN
 +#    define WIN32_LEAN_AND_MEAN
 +#  endif
 +#  ifndef NOGDI
 +#    define NOGDI
 +#  endif
 +#endif
 +
 +/*
 + * Include configuration script results or hand-crafted
 + * configuration file for platforms which lack config tool.
 + */
 +
 +#ifdef HAVE_CONFIG_H
 +
 +#include "curl_config.h"
 +
 +#else /* HAVE_CONFIG_H */
 +
 +#ifdef _WIN32_WCE
 +#  include "config-win32ce.h"
 +#else
 +#  ifdef WIN32
 +#    include "config-win32.h"
 +#  endif
 +#endif
 +
 +#if defined(macintosh) && defined(__MRC__)
 +#  include "config-mac.h"
 +#endif
 +
 +#ifdef __riscos__
 +#  include "config-riscos.h"
 +#endif
 +
 +#ifdef __AMIGA__
 +#  include "config-amigaos.h"
 +#endif
 +
 +#ifdef __SYMBIAN32__
 +#  include "config-symbian.h"
 +#endif
 +
 +#ifdef __OS400__
 +#  include "config-os400.h"
 +#endif
 +
 +#ifdef TPF
 +#  include "config-tpf.h"
 +#endif
 +
 +#ifdef __VXWORKS__
 +#  include "config-vxworks.h"
 +#endif
 +
 +#endif /* HAVE_CONFIG_H */
 +
 +#if defined(_MSC_VER)
 +# pragma warning(push,1)
 +#endif
 +
 +/* ================================================================ */
 +/* Definition of preprocessor macros/symbols which modify compiler  */
 +/* behavior or generated code characteristics must be done here,   */
 +/* as appropriate, before any system header file is included. It is */
 +/* also possible to have them defined in the config file included   */
 +/* before this point. As a result of all this we frown inclusion of */
 +/* system header files in our config files, avoid this at any cost. */
 +/* ================================================================ */
 +
 +/*
 + * AIX 4.3 and newer needs _THREAD_SAFE defined to build
 + * proper reentrant code. Others may also need it.
 + */
 +
 +#ifdef NEED_THREAD_SAFE
 +#  ifndef _THREAD_SAFE
 +#    define _THREAD_SAFE
 +#  endif
 +#endif
 +
 +/*
 + * Tru64 needs _REENTRANT set for a few function prototypes and
 + * things to appear in the system header files. Unixware needs it
 + * to build proper reentrant code. Others may also need it.
 + */
 +
 +#ifdef NEED_REENTRANT
 +#  ifndef _REENTRANT
 +#    define _REENTRANT
 +#  endif
 +#endif
 +
 +/* Solaris needs this to get a POSIX-conformant getpwuid_r */
 +#if defined(sun) || defined(__sun)
 +#  ifndef _POSIX_PTHREAD_SEMANTICS
 +#    define _POSIX_PTHREAD_SEMANTICS 1
 +#  endif
 +#endif
 +
 +/* ================================================================ */
 +/*  If you need to include a system header file for your platform,  */
 +/*  please, do it beyond the point further indicated in this file.  */
 +/* ================================================================ */
 +
 +#include <curl/curl.h>
 +
 +#define CURL_SIZEOF_CURL_OFF_T SIZEOF_CURL_OFF_T
 +
 +/*
 + * Disable other protocols when http is the only one desired.
 + */
 +
 +#ifdef HTTP_ONLY
 +#  ifndef CURL_DISABLE_TFTP
 +#    define CURL_DISABLE_TFTP
 +#  endif
 +#  ifndef CURL_DISABLE_FTP
 +#    define CURL_DISABLE_FTP
 +#  endif
 +#  ifndef CURL_DISABLE_LDAP
 +#    define CURL_DISABLE_LDAP
 +#  endif
 +#  ifndef CURL_DISABLE_TELNET
 +#    define CURL_DISABLE_TELNET
 +#  endif
 +#  ifndef CURL_DISABLE_DICT
 +#    define CURL_DISABLE_DICT
 +#  endif
 +#  ifndef CURL_DISABLE_FILE
 +#    define CURL_DISABLE_FILE
 +#  endif
 +#  ifndef CURL_DISABLE_RTSP
 +#    define CURL_DISABLE_RTSP
 +#  endif
 +#  ifndef CURL_DISABLE_POP3
 +#    define CURL_DISABLE_POP3
 +#  endif
 +#  ifndef CURL_DISABLE_IMAP
 +#    define CURL_DISABLE_IMAP
 +#  endif
 +#  ifndef CURL_DISABLE_SMTP
 +#    define CURL_DISABLE_SMTP
 +#  endif
 +#  ifndef CURL_DISABLE_GOPHER
 +#    define CURL_DISABLE_GOPHER
 +#  endif
 +#  ifndef CURL_DISABLE_SMB
 +#    define CURL_DISABLE_SMB
 +#  endif
 +#endif
 +
 +/*
 + * When http is disabled rtsp is not supported.
 + */
 +
 +#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP)
 +#  define CURL_DISABLE_RTSP
 +#endif
 +
 +/* ================================================================ */
 +/* No system header file shall be included in this file before this */
 +/* point. The only allowed ones are those included from curl/system.h */
 +/* ================================================================ */
 +
 +/*
 + * OS/400 setup file includes some system headers.
 + */
 +
 +#ifdef __OS400__
 +#  include "setup-os400.h"
 +#endif
 +
 +/*
 + * VMS setup file includes some system headers.
 + */
 +
 +#ifdef __VMS
 +#  include "setup-vms.h"
 +#endif
 +
 +/*
 + * Use getaddrinfo to resolve the IPv4 address literal. If the current network
 + * interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
 + * performing this task will result in a synthesized IPv6 address.
 + */
 +#ifdef  __APPLE__
 +#define USE_RESOLVE_ON_IPS 1
 +#endif
 +
 +/*
 + * Include header files for windows builds before redefining anything.
 + * Use this preprocessor block only to include or exclude windows.h,
 + * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs
 + * to any other further and independent block.  Under Cygwin things work
 + * just as under linux (e.g. <sys/socket.h>) and the winsock headers should
 + * never be included when __CYGWIN__ is defined.  configure script takes
 + * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H,
 + * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined.
 + */
 +
 +#ifdef HAVE_WINDOWS_H
 +#  if defined(UNICODE) && !defined(_UNICODE)
 +#    define _UNICODE
 +#  endif
 +#  if defined(_UNICODE) && !defined(UNICODE)
 +#    define UNICODE
 +#  endif
 +#  include <winerror.h>
 +#  include <windows.h>
 +#  ifdef HAVE_WINSOCK2_H
 +#    include <winsock2.h>
 +#    ifdef HAVE_WS2TCPIP_H
 +#      include <ws2tcpip.h>
 +#    endif
 +#  else
 +#    ifdef HAVE_WINSOCK_H
 +#      include <winsock.h>
 +#    endif
 +#  endif
 +#  include <tchar.h>
 +#  ifdef UNICODE
 +     typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
 +#  endif
 +#endif
 +
 +/*
 + * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
 + * define USE_WINSOCK to 1 if we have and use WINSOCK  API, else
 + * undefine USE_WINSOCK.
 + */
 +
 +#undef USE_WINSOCK
 +
 +#ifdef HAVE_WINSOCK2_H
 +#  define USE_WINSOCK 2
 +#else
 +#  ifdef HAVE_WINSOCK_H
 +#    define USE_WINSOCK 1
 +#  endif
 +#endif
 +
 +#ifdef USE_LWIPSOCK
 +#  include <lwip/init.h>
 +#  include <lwip/sockets.h>
 +#  include <lwip/netdb.h>
 +#endif
 +
 +#ifdef HAVE_EXTRA_STRICMP_H
 +#  include <extra/stricmp.h>
 +#endif
 +
 +#ifdef HAVE_EXTRA_STRDUP_H
 +#  include <extra/strdup.h>
 +#endif
 +
 +#ifdef TPF
 +#  include <strings.h>    /* for bzero, strcasecmp, and strncasecmp */
 +#  include <string.h>     /* for strcpy and strlen */
 +#  include <stdlib.h>     /* for rand and srand */
 +#  include <sys/socket.h> /* for select and ioctl*/
 +#  include <netdb.h>      /* for in_addr_t definition */
 +#  include <tpf/sysapi.h> /* for tpf_process_signals */
 +   /* change which select is used for libcurl */
 +#  define select(a,b,c,d,e) tpf_select_libcurl(a,b,c,d,e)
 +#endif
 +
 +#ifdef __VXWORKS__
 +#  include <sockLib.h>    /* for generic BSD socket functions */
 +#  include <ioLib.h>      /* for basic I/O interface functions */
 +#endif
 +
 +#ifdef __AMIGA__
- #  ifndef __ixemul__
- #    include <exec/types.h>
- #    include <exec/execbase.h>
- #    include <proto/exec.h>
- #    include <proto/dos.h>
++#  include <exec/types.h>
++#  include <exec/execbase.h>
++#  include <proto/exec.h>
++#  include <proto/dos.h>
++#  ifdef HAVE_PROTO_BSDSOCKET_H
++#    include <proto/bsdsocket.h> /* ensure bsdsocket.library use */
 +#    define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
 +#  endif
 +#endif
 +
 +#include <stdio.h>
 +#ifdef HAVE_ASSERT_H
 +#include <assert.h>
 +#endif
 +
 +#ifdef __TANDEM /* for nsr-tandem-nsk systems */
 +#include <floss.h>
 +#endif
 +
 +#ifndef STDC_HEADERS /* no standard C headers! */
 +#include <curl/stdcheaders.h>
 +#endif
 +
 +#ifdef __POCC__
 +#  include <sys/types.h>
 +#  include <unistd.h>
 +#  define sys_nerr EILSEQ
 +#endif
 +
 +/*
 + * Salford-C kludge section (mostly borrowed from wxWidgets).
 + */
 +#ifdef __SALFORDC__
 +  #pragma suppress 353             /* Possible nested comments */
 +  #pragma suppress 593             /* Define not used */
 +  #pragma suppress 61              /* enum has no name */
 +  #pragma suppress 106             /* unnamed, unused parameter */
 +  #include <clib.h>
 +#endif
 +
 +/* Default Windows file API selection.  */
 +#ifdef _WIN32
 +# if defined(_MSC_VER) && (_INTEGRAL_MAX_BITS >= 64)
 +#  define USE_WIN32_LARGE_FILES
 +# elif defined(__MINGW32__)
 +#  define USE_WIN32_LARGE_FILES
 +# else
 +#  define USE_WIN32_SMALL_FILES
 +# endif
 +#endif
 +
 +/*
 + * Large file (>2Gb) support using WIN32 functions.
 + */
 +
 +#ifdef USE_WIN32_LARGE_FILES
 +#  include <io.h>
 +#  include <sys/types.h>
 +#  include <sys/stat.h>
 +#  undef  lseek
 +#  define lseek(fdes,offset,whence)  _lseeki64(fdes, offset, whence)
 +#  undef  fstat
 +#  define fstat(fdes,stp)            _fstati64(fdes, stp)
 +#  undef  stat
 +#  define stat(fname,stp)            _stati64(fname, stp)
 +#  define struct_stat                struct _stati64
 +#  define LSEEK_ERROR                (__int64)-1
 +#endif
 +
 +/*
 + * Small file (<2Gb) support using WIN32 functions.
 + */
 +
 +#ifdef USE_WIN32_SMALL_FILES
 +#  include <io.h>
 +#  include <sys/types.h>
 +#  include <sys/stat.h>
 +#  ifndef _WIN32_WCE
 +#    undef  lseek
 +#    define lseek(fdes,offset,whence)  _lseek(fdes, (long)offset, whence)
 +#    define fstat(fdes,stp)            _fstat(fdes, stp)
 +#    define stat(fname,stp)            _stat(fname, stp)
 +#    define struct_stat                struct _stat
 +#  endif
 +#  define LSEEK_ERROR                (long)-1
 +#endif
 +
 +#ifndef struct_stat
 +#  define struct_stat struct stat
 +#endif
 +
 +#ifndef LSEEK_ERROR
 +#  define LSEEK_ERROR (off_t)-1
 +#endif
 +
 +#ifndef SIZEOF_TIME_T
 +/* assume default size of time_t to be 32 bit */
 +#define SIZEOF_TIME_T 4
 +#endif
 +
 +/*
 + * Default sizeof(off_t) in case it hasn't been defined in config file.
 + */
 +
 +#ifndef SIZEOF_OFF_T
 +#  if defined(__VMS) && !defined(__VAX)
 +#    if defined(_LARGEFILE)
 +#      define SIZEOF_OFF_T 8
 +#    endif
 +#  elif defined(__OS400__) && defined(__ILEC400__)
 +#    if defined(_LARGE_FILES)
 +#      define SIZEOF_OFF_T 8
 +#    endif
 +#  elif defined(__MVS__) && defined(__IBMC__)
 +#    if defined(_LP64) || defined(_LARGE_FILES)
 +#      define SIZEOF_OFF_T 8
 +#    endif
 +#  elif defined(__370__) && defined(__IBMC__)
 +#    if defined(_LP64) || defined(_LARGE_FILES)
 +#      define SIZEOF_OFF_T 8
 +#    endif
 +#  endif
 +#  ifndef SIZEOF_OFF_T
 +#    define SIZEOF_OFF_T 4
 +#  endif
 +#endif
 +
 +#if (SIZEOF_CURL_OFF_T == 4)
 +#  define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF)
 +#else
 +   /* assume CURL_SIZEOF_CURL_OFF_T == 8 */
 +#  define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
 +#endif
 +#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
 +
 +#if (SIZEOF_TIME_T == 4)
 +#  ifdef HAVE_TIME_T_UNSIGNED
 +#  define TIME_T_MAX UINT_MAX
 +#  define TIME_T_MIN 0
 +#  else
 +#  define TIME_T_MAX INT_MAX
 +#  define TIME_T_MIN INT_MIN
 +#  endif
 +#else
 +#  ifdef HAVE_TIME_T_UNSIGNED
 +#  define TIME_T_MAX 0xFFFFFFFFFFFFFFFF
 +#  define TIME_T_MIN 0
 +#  else
 +#  define TIME_T_MAX 0x7FFFFFFFFFFFFFFF
 +#  define TIME_T_MIN (-TIME_T_MAX - 1)
 +#  endif
 +#endif
 +
 +#ifndef SIZE_T_MAX
 +/* some limits.h headers have this defined, some don't */
 +#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4)
 +#define SIZE_T_MAX 18446744073709551615U
 +#else
 +#define SIZE_T_MAX 4294967295U
 +#endif
 +#endif
 +
 +/*
 + * Arg 2 type for gethostname in case it hasn't been defined in config file.
 + */
 +
 +#ifndef GETHOSTNAME_TYPE_ARG2
 +#  ifdef USE_WINSOCK
 +#    define GETHOSTNAME_TYPE_ARG2 int
 +#  else
 +#    define GETHOSTNAME_TYPE_ARG2 size_t
 +#  endif
 +#endif
 +
 +/* Below we define some functions. They should
 +
 +   4. set the SIGALRM signal timeout
 +   5. set dir/file naming defines
 +   */
 +
 +#ifdef WIN32
 +
 +#  define DIR_CHAR      "\\"
 +#  define DOT_CHAR      "_"
 +
 +#else /* WIN32 */
 +
 +#  ifdef MSDOS  /* Watt-32 */
 +
 +#    include <sys/ioctl.h>
 +#    define select(n,r,w,x,t) select_s(n,r,w,x,t)
 +#    define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z))
 +#    include <tcp.h>
 +#    ifdef word
 +#      undef word
 +#    endif
 +#    ifdef byte
 +#      undef byte
 +#    endif
 +
 +#  endif /* MSDOS */
 +
 +#  ifdef __minix
 +     /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */
 +     extern char *strtok_r(char *s, const char *delim, char **last);
 +     extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp);
 +#  endif
 +
 +#  define DIR_CHAR      "/"
 +#  ifndef DOT_CHAR
 +#    define DOT_CHAR      "."
 +#  endif
 +
 +#  ifdef MSDOS
 +#    undef DOT_CHAR
 +#    define DOT_CHAR      "_"
 +#  endif
 +
 +#  ifndef fileno /* sunos 4 have this as a macro! */
 +     int fileno(FILE *stream);
 +#  endif
 +
 +#endif /* WIN32 */
 +
 +/*
 + * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN
 + * defined in ws2tcpip.h as well as to provide IPv6 support.
 + * Does not apply if lwIP is used.
 + */
 +
 +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK)
 +#  if !defined(HAVE_WS2TCPIP_H) || \
 +     ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN))
 +#    undef HAVE_GETADDRINFO_THREADSAFE
 +#    undef HAVE_FREEADDRINFO
 +#    undef HAVE_GETADDRINFO
 +#    undef HAVE_GETNAMEINFO
 +#    undef ENABLE_IPV6
 +#  endif
 +#endif
 +
 +/* ---------------------------------------------------------------- */
 +/*             resolver specialty compile-time defines              */
 +/*         CURLRES_* defines to use in the host*.c sources          */
 +/* ---------------------------------------------------------------- */
 +
 +/*
 + * lcc-win32 doesn't have _beginthreadex(), lacks threads support.
 + */
 +
 +#if defined(__LCC__) && defined(WIN32)
 +#  undef USE_THREADS_POSIX
 +#  undef USE_THREADS_WIN32
 +#endif
 +
 +/*
 + * MSVC threads support requires a multi-threaded runtime library.
 + * _beginthreadex() is not available in single-threaded ones.
 + */
 +
 +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT)
 +#  undef USE_THREADS_POSIX
 +#  undef USE_THREADS_WIN32
 +#endif
 +
 +/*
 + * Mutually exclusive CURLRES_* definitions.
 + */
 +
 +#ifdef USE_ARES
 +#  define CURLRES_ASYNCH
 +#  define CURLRES_ARES
 +/* now undef the stock libc functions just to avoid them being used */
 +#  undef HAVE_GETADDRINFO
 +#  undef HAVE_FREEADDRINFO
 +#  undef HAVE_GETHOSTBYNAME
 +#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
 +#  define CURLRES_ASYNCH
 +#  define CURLRES_THREADED
 +#else
 +#  define CURLRES_SYNCH
 +#endif
 +
 +#ifdef ENABLE_IPV6
 +#  define CURLRES_IPV6
 +#else
 +#  define CURLRES_IPV4
 +#endif
 +
 +/* ---------------------------------------------------------------- */
 +
 +/*
 + * When using WINSOCK, TELNET protocol requires WINSOCK2 API.
 + */
 +
 +#if defined(USE_WINSOCK) && (USE_WINSOCK != 2)
 +#  define CURL_DISABLE_TELNET 1
 +#endif
 +
 +/*
 + * msvc 6.0 does not have struct sockaddr_storage and
 + * does not define IPPROTO_ESP in winsock2.h. But both
 + * are available if PSDK is properly installed.
 + */
 +
 +#if defined(_MSC_VER) && !defined(__POCC__)
 +#  if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP))
 +#    undef HAVE_STRUCT_SOCKADDR_STORAGE
 +#  endif
 +#endif
 +
 +/*
 + * Intentionally fail to build when using msvc 6.0 without PSDK installed.
 + * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK
 + * in lib/config-win32.h although absolutely discouraged and unsupported.
 + */
 +
 +#if defined(_MSC_VER) && !defined(__POCC__)
 +#  if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_))
 +#    if !defined(ALLOW_MSVC6_WITHOUT_PSDK)
 +#      error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \
 +             "Windows Server 2003 PSDK"
 +#    else
 +#      define CURL_DISABLE_LDAP 1
 +#    endif
 +#  endif
 +#endif
 +
 +#ifdef NETWARE
 +int netware_init(void);
 +#ifndef __NOVELL_LIBC__
 +#include <sys/bsdskt.h>
 +#include <sys/timeval.h>
 +#endif
 +#endif
 +
 +#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN)
 +/* The lib and header are present */
 +#define USE_LIBIDN2
 +#endif
 +
 +#if defined(USE_LIBIDN2) && defined(USE_WIN32_IDN)
 +#error "Both libidn2 and WinIDN are enabled, choose one."
 +#endif
 +
 +#define LIBIDN_REQUIRED_VERSION "0.4.1"
 +
 +#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
-     defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_MBEDTLS) || \
++    defined(USE_POLARSSL) || defined(USE_MBEDTLS) || \
 +    defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
-     defined(USE_DARWINSSL) || defined(USE_GSKIT) || defined(USE_MESALINK)
++    defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK)
 +#define USE_SSL    /* SSL support has been enabled */
 +#endif
 +
 +/* Single point where USE_SPNEGO definition might be defined */
 +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
 +    (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
 +#define USE_SPNEGO
 +#endif
 +
 +/* Single point where USE_KERBEROS5 definition might be defined */
 +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
 +    (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
 +#define USE_KERBEROS5
 +#endif
 +
 +/* Single point where USE_NTLM definition might be defined */
 +#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
 +#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
-     defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \
++    defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
 +    defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
 +    defined(USE_MBEDTLS)
 +
 +#define USE_NTLM
 +
 +#  if defined(USE_MBEDTLS)
 +/* Get definition of MBEDTLS_MD4_C */
 +#  include <mbedtls/md4.h>
 +#  endif
 +
 +#endif
 +#endif
 +
 +#ifdef CURL_WANTS_CA_BUNDLE_ENV
 +#error "No longer supported. Set CURLOPT_CAINFO at runtime instead."
 +#endif
 +
++#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) || defined(USE_WOLFSSH)
++#define USE_SSH
++#endif
++
 +/*
 + * Provide a mechanism to silence picky compilers, such as gcc 4.6+.
 + * Parameters should of course normally not be unused, but for example when
 + * we have multiple implementations of the same interface it may happen.
 + */
 +
 +#if defined(__GNUC__) && ((__GNUC__ >= 3) || \
 +  ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7)))
 +#  define UNUSED_PARAM __attribute__((__unused__))
 +#  define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
 +#else
 +#  define UNUSED_PARAM /*NOTHING*/
 +#  define WARN_UNUSED_RESULT
 +#endif
 +
 +/*
 + * Include macros and defines that should only be processed once.
 + */
 +
 +#ifndef HEADER_CURL_SETUP_ONCE_H
 +#include "curl_setup_once.h"
 +#endif
 +
 +/*
 + * Definition of our NOP statement Object-like macro
 + */
 +
 +#ifndef Curl_nop_stmt
 +#  define Curl_nop_stmt do { } WHILE_FALSE
 +#endif
 +
 +/*
 + * Ensure that Winsock and lwIP TCP/IP stacks are not mixed.
 + */
 +
 +#if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)
 +#  if defined(SOCKET) || \
 +     defined(USE_WINSOCK) || \
 +     defined(HAVE_WINSOCK_H) || \
 +     defined(HAVE_WINSOCK2_H) || \
 +     defined(HAVE_WS2TCPIP_H)
 +#    error "Winsock and lwIP TCP/IP stack definitions shall not coexist!"
 +#  endif
 +#endif
 +
 +/*
 + * Portable symbolic names for Winsock shutdown() mode flags.
 + */
 +
 +#ifdef USE_WINSOCK
 +#  define SHUT_RD   0x00
 +#  define SHUT_WR   0x01
 +#  define SHUT_RDWR 0x02
 +#endif
 +
 +/* Define S_ISREG if not defined by system headers, f.e. MSVC */
 +#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
 +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
 +#endif
 +
 +/* Define S_ISDIR if not defined by system headers, f.e. MSVC */
 +#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
 +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
 +#endif
 +
 +/* In Windows the default file mode is text but an application can override it.
 +Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
 +*/
 +#if defined(WIN32) || defined(MSDOS)
 +#define FOPEN_READTEXT "rt"
 +#define FOPEN_WRITETEXT "wt"
 +#define FOPEN_APPENDTEXT "at"
 +#elif defined(__CYGWIN__)
 +/* Cygwin has specific behavior we need to address when WIN32 is not defined.
 +https://cygwin.com/cygwin-ug-net/using-textbinary.html
 +For write we want our output to have line endings of LF and be compatible with
 +other Cygwin utilities. For read we want to handle input that may have line
 +endings either CRLF or LF so 't' is appropriate.
 +*/
 +#define FOPEN_READTEXT "rt"
 +#define FOPEN_WRITETEXT "w"
 +#define FOPEN_APPENDTEXT "a"
 +#else
 +#define FOPEN_READTEXT "r"
 +#define FOPEN_WRITETEXT "w"
 +#define FOPEN_APPENDTEXT "a"
 +#endif
 +
 +/* WinSock destroys recv() buffer when send() failed.
 + * Enabled automatically for Windows and for Cygwin as Cygwin sockets are
 + * wrappers for WinSock sockets. https://github.com/curl/curl/issues/657
 + * Define DONT_USE_RECV_BEFORE_SEND_WORKAROUND to force disable workaround.
 + */
 +#if !defined(DONT_USE_RECV_BEFORE_SEND_WORKAROUND)
 +#  if defined(WIN32) || defined(__CYGWIN__)
 +#    define USE_RECV_BEFORE_SEND_WORKAROUND
 +#  endif
 +#else  /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
 +#  ifdef USE_RECV_BEFORE_SEND_WORKAROUND
 +#    undef USE_RECV_BEFORE_SEND_WORKAROUND
 +#  endif
 +#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
 +
 +/* Detect Windows App environment which has a restricted access
 + * to the Win32 APIs. */
 +# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
 +  defined(WINAPI_FAMILY)
 +#  include <winapifamily.h>
 +#  if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) &&  \
 +     !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
 +#    define CURL_WINDOWS_APP
 +#  endif
 +# endif
 +
 +/* for systems that don't detect this in configure, use a sensible default */
 +#ifndef CURL_SA_FAMILY_T
 +#define CURL_SA_FAMILY_T unsigned short
 +#endif
 +
 +/* Some convenience macros to get the larger/smaller value out of two given.
 +   We prefix with CURL to prevent name collisions. */
 +#define CURLMAX(x,y) ((x)>(y)?(x):(y))
 +#define CURLMIN(x,y) ((x)<(y)?(x):(y))
 +
 +/* Some versions of the Android SDK is missing the declaration */
 +#if defined(HAVE_GETPWUID_R) && defined(HAVE_DECL_GETPWUID_R_MISSING)
 +struct passwd;
 +int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
 +               size_t buflen, struct passwd **result);
 +#endif
 +
++#ifdef DEBUGBUILD
++#define UNITTEST
++#else
++#define UNITTEST static
++#endif
++
 +#endif /* HEADER_CURL_SETUP_H */
diff --cc Utilities/cmcurl/lib/ftp.c
index ce889ab,0000000..53510f8
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@@ -1,4452 -1,0 +1,4443 @@@
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
-  * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
++ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
 + *
 + * This software is licensed as described in the file COPYING, which
 + * you should have received as part of this distribution. The terms
 + * are also available at https://curl.haxx.se/docs/copyright.html.
 + *
 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 + * copies of the Software, and permit persons to whom the Software is
 + * furnished to do so, under the terms of the COPYING file.
 + *
 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 + * KIND, either express or implied.
 + *
 + ***************************************************************************/
 +
 +#include "curl_setup.h"
 +
 +#ifndef CURL_DISABLE_FTP
 +
 +#ifdef HAVE_NETINET_IN_H
 +#include <netinet/in.h>
 +#endif
 +#ifdef HAVE_ARPA_INET_H
 +#include <arpa/inet.h>
 +#endif
 +#ifdef HAVE_UTSNAME_H
 +#include <sys/utsname.h>
 +#endif
 +#ifdef HAVE_NETDB_H
 +#include <netdb.h>
 +#endif
 +#ifdef __VMS
 +#include <in.h>
 +#include <inet.h>
 +#endif
 +
 +#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
 +#undef in_addr_t
 +#define in_addr_t unsigned long
 +#endif
 +
 +#include <curl/curl.h>
 +#include "urldata.h"
 +#include "sendf.h"
 +#include "if2ip.h"
 +#include "hostip.h"
 +#include "progress.h"
 +#include "transfer.h"
 +#include "escape.h"
 +#include "http.h" /* for HTTP proxy tunnel stuff */
 +#include "socks.h"
 +#include "ftp.h"
 +#include "fileinfo.h"
 +#include "ftplistparser.h"
 +#include "curl_range.h"
 +#include "curl_sec.h"
 +#include "strtoofft.h"
 +#include "strcase.h"
 +#include "vtls/vtls.h"
 +#include "connect.h"
 +#include "strerror.h"
 +#include "inet_ntop.h"
 +#include "inet_pton.h"
 +#include "select.h"
 +#include "parsedate.h" /* for the week day and month names */
 +#include "sockaddr.h" /* required for Curl_sockaddr_storage */
 +#include "multiif.h"
 +#include "url.h"
 +#include "strcase.h"
 +#include "speedcheck.h"
 +#include "warnless.h"
 +#include "http_proxy.h"
 +#include "non-ascii.h"
 +/* The last 3 #include files should be in this order */
 +#include "curl_printf.h"
 +#include "curl_memory.h"
 +#include "memdebug.h"
 +
 +#ifndef NI_MAXHOST
 +#define NI_MAXHOST 1025
 +#endif
 +#ifndef INET_ADDRSTRLEN
 +#define INET_ADDRSTRLEN 16
 +#endif
 +
 +#ifdef CURL_DISABLE_VERBOSE_STRINGS
 +#define ftp_pasv_verbose(a,b,c,d)  Curl_nop_stmt
 +#endif
 +
 +/* Local API functions */
 +#ifndef DEBUGBUILD
 +static void _state(struct connectdata *conn,
 +                   ftpstate newstate);
 +#define state(x,y) _state(x,y)
 +#else
 +static void _state(struct connectdata *conn,
 +                   ftpstate newstate,
 +                   int lineno);
 +#define state(x,y) _state(x,y,__LINE__)
 +#endif
 +
 +static CURLcode ftp_sendquote(struct connectdata *conn,
 +                              struct curl_slist *quote);
 +static CURLcode ftp_quit(struct connectdata *conn);
 +static CURLcode ftp_parse_url_path(struct connectdata *conn);
 +static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done);
 +#ifndef CURL_DISABLE_VERBOSE_STRINGS
 +static void ftp_pasv_verbose(struct connectdata *conn,
 +                             Curl_addrinfo *ai,
 +                             char *newhost, /* ascii version */
 +                             int port);
 +#endif
 +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn);
 +static CURLcode ftp_state_mdtm(struct connectdata *conn);
 +static CURLcode ftp_state_quote(struct connectdata *conn,
 +                                bool init, ftpstate instate);
 +static CURLcode ftp_nb_type(struct connectdata *conn,
 +                            bool ascii, ftpstate newstate);
 +static int ftp_need_type(struct connectdata *conn,
 +                         bool ascii);
 +static CURLcode ftp_do(struct connectdata *conn, bool *done);
 +static CURLcode ftp_done(struct connectdata *conn,
 +                         CURLcode, bool premature);
 +static CURLcode ftp_connect(struct connectdata *conn, bool *done);
 +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection);
 +static CURLcode ftp_do_more(struct connectdata *conn, int *completed);
 +static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done);
 +static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks,
 +                       int numsocks);
 +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
 +                              int numsocks);
 +static CURLcode ftp_doing(struct connectdata *conn,
 +                          bool *dophase_done);
 +static CURLcode ftp_setup_connection(struct connectdata * conn);
 +
 +static CURLcode init_wc_data(struct connectdata *conn);
 +static CURLcode wc_statemach(struct connectdata *conn);
 +
 +static void wc_data_dtor(void *ptr);
 +
 +static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize);
 +
 +static CURLcode ftp_readresp(curl_socket_t sockfd,
 +                             struct pingpong *pp,
 +                             int *ftpcode,
 +                             size_t *size);
 +static CURLcode ftp_dophase_done(struct connectdata *conn,
 +                                 bool connected);
 +
 +/* easy-to-use macro: */
 +#define PPSENDF(x,y,z)  result = Curl_pp_sendf(x,y,z); \
 +                        if(result)                     \
 +                          return result
 +
 +
 +/*
 + * FTP protocol handler.
 + */
 +
 +const struct Curl_handler Curl_handler_ftp = {
 +  "FTP",                           /* scheme */
 +  ftp_setup_connection,            /* setup_connection */
 +  ftp_do,                          /* do_it */
 +  ftp_done,                        /* done */
 +  ftp_do_more,                     /* do_more */
 +  ftp_connect,                     /* connect_it */
 +  ftp_multi_statemach,             /* connecting */
 +  ftp_doing,                       /* doing */
 +  ftp_getsock,                     /* proto_getsock */
 +  ftp_getsock,                     /* doing_getsock */
 +  ftp_domore_getsock,              /* domore_getsock */
 +  ZERO_NULL,                       /* perform_getsock */
 +  ftp_disconnect,                  /* disconnect */
 +  ZERO_NULL,                       /* readwrite */
 +  ZERO_NULL,                       /* connection_check */
 +  PORT_FTP,                        /* defport */
 +  CURLPROTO_FTP,                   /* protocol */
 +  PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD |
 +  PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP |
 +  PROTOPT_WILDCARD /* flags */
 +};
 +
 +
 +#ifdef USE_SSL
 +/*
 + * FTPS protocol handler.
 + */
 +
 +const struct Curl_handler Curl_handler_ftps = {
 +  "FTPS",                          /* scheme */
 +  ftp_setup_connection,            /* setup_connection */
 +  ftp_do,                          /* do_it */
 +  ftp_done,                        /* done */
 +  ftp_do_more,                     /* do_more */
 +  ftp_connect,                     /* connect_it */
 +  ftp_multi_statemach,             /* connecting */
 +  ftp_doing,                       /* doing */
 +  ftp_getsock,                     /* proto_getsock */
 +  ftp_getsock,                     /* doing_getsock */
 +  ftp_domore_getsock,              /* domore_getsock */
 +  ZERO_NULL,                       /* perform_getsock */
 +  ftp_disconnect,                  /* disconnect */
 +  ZERO_NULL,                       /* readwrite */
 +  ZERO_NULL,                       /* connection_check */
 +  PORT_FTPS,                       /* defport */
 +  CURLPROTO_FTPS,                  /* protocol */
 +  PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
 +  PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */
 +};
 +#endif
 +
 +static void close_secondarysocket(struct connectdata *conn)
 +{
 +  if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
 +    Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
 +    conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
 +  }
 +  conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
 +}
 +
 +/*
 + * NOTE: back in the old days, we added code in the FTP code that made NOBODY
 + * requests on files respond with headers passed to the client/stdout that
 + * looked like HTTP ones.
 + *
 + * This approach is not very elegant, it causes confusion and is error-prone.
 + * It is subject for removal at the next (or at least a future) soname bump.
 + * Until then you can test the effects of the removal by undefining the
 + * following define named CURL_FTP_HTTPSTYLE_HEAD.
 + */
 +#define CURL_FTP_HTTPSTYLE_HEAD 1
 +
 +static void freedirs(struct ftp_conn *ftpc)
 +{
 +  if(ftpc->dirs) {
 +    int i;
 +    for(i = 0; i < ftpc->dirdepth; i++) {
 +      free(ftpc->dirs[i]);
 +      ftpc->dirs[i] = NULL;
 +    }
 +    free(ftpc->dirs);
 +    ftpc->dirs = NULL;
 +    ftpc->dirdepth = 0;
 +  }
 +  Curl_safefree(ftpc->file);
 +
 +  /* no longer of any use */
 +  Curl_safefree(ftpc->newhost);
 +}
 +
 +/* Returns non-zero if the given string contains CR (\r) or LF (\n),
 +   which are not allowed within RFC 959 <string>.
 +   Note: The input string is in the client's encoding which might
 +   not be ASCII, so escape sequences \r & \n must be used instead
 +   of hex values 0x0d & 0x0a.
 +*/
 +static bool isBadFtpString(const char *string)
 +{
 +  return ((NULL != strchr(string, '\r')) ||
 +          (NULL != strchr(string, '\n'))) ? TRUE : FALSE;
 +}
 +
 +/***********************************************************************
 + *
 + * AcceptServerConnect()
 + *
 + * After connection request is received from the server this function is
 + * called to accept the connection and close the listening socket
 + *
 + */
 +static CURLcode AcceptServerConnect(struct connectdata *conn)
 +{
 +  struct Curl_easy *data = conn->data;
 +  curl_socket_t sock = conn->sock[SECONDARYSOCKET];
 +  curl_socket_t s = CURL_SOCKET_BAD;
 +#ifdef ENABLE_IPV6
 +  struct Curl_sockaddr_storage add;
 +#else
 +  struct sockaddr_in add;
 +#endif
 +  curl_socklen_t size = (curl_socklen_t) sizeof(add);
 +
 +  if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) {
 +    size = sizeof(add);
 +
 +    s = accept(sock, (struct sockaddr *) &add, &size);
 +  }
 +  Curl_closesocket(conn, sock); /* close the first socket */
 +
 +  if(CURL_SOCKET_BAD == s) {
 +    failf(data, "Error accept()ing server connect");
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +  infof(data, "Connection accepted from server\n");
 +  /* when this happens within the DO state it is important that we mark us as
 +     not needing DO_MORE anymore */
 +  conn->bits.do_more = FALSE;
 +
 +  conn->sock[SECONDARYSOCKET] = s;
 +  (void)curlx_nonblock(s, TRUE); /* enable non-blocking */
 +  conn->sock_accepted[SECONDARYSOCKET] = TRUE;
 +
 +  if(data->set.fsockopt) {
 +    int error = 0;
 +
 +    /* activate callback for setting socket options */
 +    Curl_set_in_callback(data, true);
 +    error = data->set.fsockopt(data->set.sockopt_client,
 +                               s,
 +                               CURLSOCKTYPE_ACCEPT);
 +    Curl_set_in_callback(data, false);
 +
 +    if(error) {
 +      close_secondarysocket(conn);
 +      return CURLE_ABORTED_BY_CALLBACK;
 +    }
 +  }
 +
 +  return CURLE_OK;
 +
 +}
 +
 +/*
 + * ftp_timeleft_accept() returns the amount of milliseconds left allowed for
 + * waiting server to connect. If the value is negative, the timeout time has
 + * already elapsed.
 + *
 + * The start time is stored in progress.t_acceptdata - as set with
 + * Curl_pgrsTime(..., TIMER_STARTACCEPT);
 + *
 + */
 +static timediff_t ftp_timeleft_accept(struct Curl_easy *data)
 +{
 +  timediff_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
 +  timediff_t other;
 +  struct curltime now;
 +
 +  if(data->set.accepttimeout > 0)
 +    timeout_ms = data->set.accepttimeout;
 +
 +  now = Curl_now();
 +
 +  /* check if the generic timeout possibly is set shorter */
 +  other =  Curl_timeleft(data, &now, FALSE);
 +  if(other && (other < timeout_ms))
 +    /* note that this also works fine for when other happens to be negative
 +       due to it already having elapsed */
 +    timeout_ms = other;
 +  else {
 +    /* subtract elapsed time */
 +    timeout_ms -= Curl_timediff(now, data->progress.t_acceptdata);
 +    if(!timeout_ms)
 +      /* avoid returning 0 as that means no timeout! */
 +      return -1;
 +  }
 +
 +  return timeout_ms;
 +}
 +
 +
 +/***********************************************************************
 + *
 + * ReceivedServerConnect()
 + *
 + * After allowing server to connect to us from data port, this function
 + * checks both data connection for connection establishment and ctrl
 + * connection for a negative response regarding a failure in connecting
 + *
 + */
 +static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
 +{
 +  struct Curl_easy *data = conn->data;
 +  curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
 +  curl_socket_t data_sock = conn->sock[SECONDARYSOCKET];
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +  int result;
 +  time_t timeout_ms;
 +  ssize_t nread;
 +  int ftpcode;
 +
 +  *received = FALSE;
 +
 +  timeout_ms = ftp_timeleft_accept(data);
 +  infof(data, "Checking for server connect\n");
 +  if(timeout_ms < 0) {
 +    /* if a timeout was already reached, bail out */
 +    failf(data, "Accept timeout occurred while waiting server connect");
 +    return CURLE_FTP_ACCEPT_TIMEOUT;
 +  }
 +
 +  /* First check whether there is a cached response from server */
 +  if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
 +    /* Data connection could not be established, let's return */
 +    infof(data, "There is negative response in cache while serv connect\n");
 +    Curl_GetFTPResponse(&nread, conn, &ftpcode);
 +    return CURLE_FTP_ACCEPT_FAILED;
 +  }
 +
 +  result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
 +
 +  /* see if the connection request is already here */
 +  switch(result) {
 +  case -1: /* error */
 +    /* let's die here */
 +    failf(data, "Error while waiting for server connect");
 +    return CURLE_FTP_ACCEPT_FAILED;
 +  case 0:  /* Server connect is not received yet */
 +    break; /* loop */
 +  default:
 +
 +    if(result & CURL_CSELECT_IN2) {
 +      infof(data, "Ready to accept data connection from server\n");
 +      *received = TRUE;
 +    }
 +    else if(result & CURL_CSELECT_IN) {
 +      infof(data, "Ctrl conn has data while waiting for data conn\n");
 +      Curl_GetFTPResponse(&nread, conn, &ftpcode);
 +
 +      if(ftpcode/100 > 3)
 +        return CURLE_FTP_ACCEPT_FAILED;
 +
 +      return CURLE_WEIRD_SERVER_REPLY;
 +    }
 +
 +    break;
 +  } /* switch() */
 +
 +  return CURLE_OK;
 +}
 +
 +
 +/***********************************************************************
 + *
 + * InitiateTransfer()
 + *
 + * After connection from server is accepted this function is called to
 + * setup transfer parameters and initiate the data transfer.
 + *
 + */
 +static CURLcode InitiateTransfer(struct connectdata *conn)
 +{
 +  struct Curl_easy *data = conn->data;
-   struct FTP *ftp = data->req.protop;
 +  CURLcode result = CURLE_OK;
 +
 +  if(conn->bits.ftp_use_data_ssl) {
 +    /* since we only have a plaintext TCP connection here, we must now
 +     * do the TLS stuff */
 +    infof(data, "Doing the SSL/TLS handshake on the data stream\n");
 +    result = Curl_ssl_connect(conn, SECONDARYSOCKET);
 +    if(result)
 +      return result;
 +  }
 +
 +  if(conn->proto.ftpc.state_saved == FTP_STOR) {
-     *(ftp->bytecountp) = 0;
- 
 +    /* When we know we're uploading a specified file, we can get the file
 +       size prior to the actual upload. */
- 
 +    Curl_pgrsSetUploadSize(data, data->state.infilesize);
 +
 +    /* set the SO_SNDBUF for the secondary socket for those who need it */
 +    Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
 +
-     Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
-                         SECONDARYSOCKET, ftp->bytecountp);
++    Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET);
 +  }
 +  else {
 +    /* FTP download: */
-     Curl_setup_transfer(conn, SECONDARYSOCKET,
-                         conn->proto.ftpc.retr_size_saved, FALSE,
-                         ftp->bytecountp, -1, NULL); /* no upload here */
++    Curl_setup_transfer(data, SECONDARYSOCKET,
++                        conn->proto.ftpc.retr_size_saved, FALSE, -1);
 +  }
 +
 +  conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
 +  state(conn, FTP_STOP);
 +
 +  return CURLE_OK;
 +}
 +
 +/***********************************************************************
 + *
 + * AllowServerConnect()
 + *
 + * When we've issue the PORT command, we have told the server to connect to
 + * us. This function checks whether data connection is established if so it is
 + * accepted.
 + *
 + */
 +static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
 +{
 +  struct Curl_easy *data = conn->data;
 +  time_t timeout_ms;
 +  CURLcode result = CURLE_OK;
 +
 +  *connected = FALSE;
 +  infof(data, "Preparing for accepting server on data port\n");
 +
 +  /* Save the time we start accepting server connect */
 +  Curl_pgrsTime(data, TIMER_STARTACCEPT);
 +
 +  timeout_ms = ftp_timeleft_accept(data);
 +  if(timeout_ms < 0) {
 +    /* if a timeout was already reached, bail out */
 +    failf(data, "Accept timeout occurred while waiting server connect");
 +    return CURLE_FTP_ACCEPT_TIMEOUT;
 +  }
 +
 +  /* see if the connection request is already here */
 +  result = ReceivedServerConnect(conn, connected);
 +  if(result)
 +    return result;
 +
 +  if(*connected) {
 +    result = AcceptServerConnect(conn);
 +    if(result)
 +      return result;
 +
 +    result = InitiateTransfer(conn);
 +    if(result)
 +      return result;
 +  }
 +  else {
 +    /* Add timeout to multi handle and break out of the loop */
 +    if(!result && *connected == FALSE) {
 +      Curl_expire(data, data->set.accepttimeout > 0 ?
 +                  data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT, 0);
 +    }
 +  }
 +
 +  return result;
 +}
 +
 +/* macro to check for a three-digit ftp status code at the start of the
 +   given string */
 +#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) &&       \
 +                          ISDIGIT(line[2]))
 +
 +/* macro to check for the last line in an FTP server response */
 +#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3]))
 +
 +static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len,
 +                          int *code)
 +{
 +  (void)conn;
 +
 +  if((len > 3) && LASTLINE(line)) {
 +    *code = curlx_sltosi(strtol(line, NULL, 10));
 +    return TRUE;
 +  }
 +
 +  return FALSE;
 +}
 +
 +static CURLcode ftp_readresp(curl_socket_t sockfd,
 +                             struct pingpong *pp,
 +                             int *ftpcode, /* return the ftp-code if done */
 +                             size_t *size) /* size of the response */
 +{
 +  struct connectdata *conn = pp->conn;
 +  struct Curl_easy *data = conn->data;
 +#ifdef HAVE_GSSAPI
 +  char * const buf = data->state.buffer;
 +#endif
 +  CURLcode result = CURLE_OK;
 +  int code;
 +
 +  result = Curl_pp_readresp(sockfd, pp, &code, size);
 +
 +#if defined(HAVE_GSSAPI)
 +  /* handle the security-oriented responses 6xx ***/
-   /* FIXME: some errorchecking perhaps... ***/
 +  switch(code) {
 +  case 631:
 +    code = Curl_sec_read_msg(conn, buf, PROT_SAFE);
 +    break;
 +  case 632:
 +    code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE);
 +    break;
 +  case 633:
 +    code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL);
 +    break;
 +  default:
 +    /* normal ftp stuff we pass through! */
 +    break;
 +  }
 +#endif
 +
 +  /* store the latest code for later retrieval */
 +  data->info.httpcode = code;
 +
 +  if(ftpcode)
 +    *ftpcode = code;
 +
 +  if(421 == code) {
 +    /* 421 means "Service not available, closing control connection." and FTP
 +     * servers use it to signal that idle session timeout has been exceeded.
 +     * If we ignored the response, it could end up hanging in some cases.
 +     *
 +     * This response code can come at any point so having it treated
 +     * generically is a good idea.
 +     */
 +    infof(data, "We got a 421 - timeout!\n");
 +    state(conn, FTP_STOP);
 +    return CURLE_OPERATION_TIMEDOUT;
 +  }
 +
 +  return result;
 +}
 +
 +/* --- parse FTP server responses --- */
 +
 +/*
 + * Curl_GetFTPResponse() is a BLOCKING function to read the full response
 + * from a server after a command.
 + *
 + */
 +
 +CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
 +                             struct connectdata *conn,
 +                             int *ftpcode) /* return the ftp-code */
 +{
 +  /*
 +   * We cannot read just one byte per read() and then go back to select() as
 +   * the OpenSSL read() doesn't grok that properly.
 +   *
 +   * Alas, read as much as possible, split up into lines, use the ending
 +   * line in a response or continue reading.  */
 +
 +  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
 +  struct Curl_easy *data = conn->data;
 +  CURLcode result = CURLE_OK;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +  size_t nread;
 +  int cache_skip = 0;
 +  int value_to_be_ignored = 0;
 +
 +  if(ftpcode)
 +    *ftpcode = 0; /* 0 for errors */
 +  else
 +    /* make the pointer point to something for the rest of this function */
 +    ftpcode = &value_to_be_ignored;
 +
 +  *nreadp = 0;
 +
 +  while(!*ftpcode && !result) {
 +    /* check and reset timeout value every lap */
-     time_t timeout = Curl_pp_state_timeout(pp); /* timeout in milliseconds */
++    time_t timeout = Curl_pp_state_timeout(pp, FALSE);
 +    time_t interval_ms;
 +
 +    if(timeout <= 0) {
 +      failf(data, "FTP response timeout");
 +      return CURLE_OPERATION_TIMEDOUT; /* already too little time */
 +    }
 +
 +    interval_ms = 1000;  /* use 1 second timeout intervals */
 +    if(timeout < interval_ms)
 +      interval_ms = timeout;
 +
 +    /*
 +     * Since this function is blocking, we need to wait here for input on the
 +     * connection and only then we call the response reading function. We do
 +     * timeout at least every second to make the timeout check run.
 +     *
 +     * A caution here is that the ftp_readresp() function has a cache that may
 +     * contain pieces of a response from the previous invoke and we need to
 +     * make sure we don't just wait for input while there is unhandled data in
 +     * that cache. But also, if the cache is there, we call ftp_readresp() and
 +     * the cache wasn't good enough to continue we must not just busy-loop
 +     * around this function.
 +     *
 +     */
 +
 +    if(pp->cache && (cache_skip < 2)) {
 +      /*
 +       * There's a cache left since before. We then skipping the wait for
 +       * socket action, unless this is the same cache like the previous round
 +       * as then the cache was deemed not enough to act on and we then need to
 +       * wait for more data anyway.
 +       */
 +    }
 +    else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) {
 +      switch(SOCKET_READABLE(sockfd, interval_ms)) {
 +      case -1: /* select() error, stop reading */
 +        failf(data, "FTP response aborted due to select/poll error: %d",
 +              SOCKERRNO);
 +        return CURLE_RECV_ERROR;
 +
 +      case 0: /* timeout */
 +        if(Curl_pgrsUpdate(conn))
 +          return CURLE_ABORTED_BY_CALLBACK;
 +        continue; /* just continue in our loop for the timeout duration */
 +
 +      default: /* for clarity */
 +        break;
 +      }
 +    }
 +    result = ftp_readresp(sockfd, pp, ftpcode, &nread);
 +    if(result)
 +      break;
 +
 +    if(!nread && pp->cache)
 +      /* bump cache skip counter as on repeated skips we must wait for more
 +         data */
 +      cache_skip++;
 +    else
 +      /* when we got data or there is no cache left, we reset the cache skip
 +         counter */
 +      cache_skip = 0;
 +
 +    *nreadp += nread;
 +
 +  } /* while there's buffer left and loop is requested */
 +
 +  pp->pending_resp = FALSE;
 +
 +  return result;
 +}
 +
 +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
 +  /* for debug purposes */
 +static const char * const ftp_state_names[]={
 +  "STOP",
 +  "WAIT220",
 +  "AUTH",
 +  "USER",
 +  "PASS",
 +  "ACCT",
 +  "PBSZ",
 +  "PROT",
 +  "CCC",
 +  "PWD",
 +  "SYST",
 +  "NAMEFMT",
 +  "QUOTE",
 +  "RETR_PREQUOTE",
 +  "STOR_PREQUOTE",
 +  "POSTQUOTE",
 +  "CWD",
 +  "MKD",
 +  "MDTM",
 +  "TYPE",
 +  "LIST_TYPE",
 +  "RETR_TYPE",
 +  "STOR_TYPE",
 +  "SIZE",
 +  "RETR_SIZE",
 +  "STOR_SIZE",
 +  "REST",
 +  "RETR_REST",
 +  "PORT",
 +  "PRET",
 +  "PASV",
 +  "LIST",
 +  "RETR",
 +  "STOR",
 +  "QUIT"
 +};
 +#endif
 +
 +/* This is the ONLY way to change FTP state! */
 +static void _state(struct connectdata *conn,
 +                   ftpstate newstate
 +#ifdef DEBUGBUILD
 +                   , int lineno
 +#endif
 +  )
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +#if defined(DEBUGBUILD)
 +
 +#if defined(CURL_DISABLE_VERBOSE_STRINGS)
 +  (void) lineno;
 +#else
 +  if(ftpc->state != newstate)
 +    infof(conn->data, "FTP %p (line %d) state change from %s to %s\n",
 +          (void *)ftpc, lineno, ftp_state_names[ftpc->state],
 +          ftp_state_names[newstate]);
 +#endif
 +#endif
 +
 +  ftpc->state = newstate;
 +}
 +
 +static CURLcode ftp_state_user(struct connectdata *conn)
 +{
 +  CURLcode result;
 +  struct FTP *ftp = conn->data->req.protop;
 +  /* send USER */
 +  PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:"");
 +
 +  state(conn, FTP_USER);
 +  conn->data->state.ftp_trying_alternative = FALSE;
 +
 +  return CURLE_OK;
 +}
 +
 +static CURLcode ftp_state_pwd(struct connectdata *conn)
 +{
 +  CURLcode result;
 +
 +  /* send PWD to discover our entry point */
 +  PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD");
 +  state(conn, FTP_PWD);
 +
 +  return CURLE_OK;
 +}
 +
 +/* For the FTP "protocol connect" and "doing" phases only */
 +static int ftp_getsock(struct connectdata *conn,
 +                       curl_socket_t *socks,
 +                       int numsocks)
 +{
 +  return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
 +}
 +
 +/* For the FTP "DO_MORE" phase only */
 +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
 +                              int numsocks)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if(!numsocks)
 +    return GETSOCK_BLANK;
 +
 +  /* When in DO_MORE state, we could be either waiting for us to connect to a
 +   * remote site, or we could wait for that site to connect to us. Or just
 +   * handle ordinary commands.
 +   */
 +
 +  if(FTP_STOP == ftpc->state) {
 +    int bits = GETSOCK_READSOCK(0);
 +
 +    /* if stopped and still in this state, then we're also waiting for a
 +       connect on the secondary connection */
 +    socks[0] = conn->sock[FIRSTSOCKET];
 +
 +    if(!conn->data->set.ftp_use_port) {
 +      int s;
 +      int i;
 +      /* PORT is used to tell the server to connect to us, and during that we
 +         don't do happy eyeballs, but we do if we connect to the server */
 +      for(s = 1, i = 0; i<2; i++) {
 +        if(conn->tempsock[i] != CURL_SOCKET_BAD) {
 +          socks[s] = conn->tempsock[i];
 +          bits |= GETSOCK_WRITESOCK(s++);
 +        }
 +      }
 +    }
 +    else {
 +      socks[1] = conn->sock[SECONDARYSOCKET];
 +      bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
 +    }
 +
 +    return bits;
 +  }
 +  return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
 +}
 +
 +/* This is called after the FTP_QUOTE state is passed.
 +
 +   ftp_state_cwd() sends the range of CWD commands to the server to change to
 +   the correct directory. It may also need to send MKD commands to create
 +   missing ones, if that option is enabled.
 +*/
 +static CURLcode ftp_state_cwd(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if(ftpc->cwddone)
 +    /* already done and fine */
 +    result = ftp_state_mdtm(conn);
 +  else {
 +    ftpc->count2 = 0; /* count2 counts failed CWDs */
 +
 +    /* count3 is set to allow a MKD to fail once. In the case when first CWD
 +       fails and then MKD fails (due to another session raced it to create the
 +       dir) this then allows for a second try to CWD to it */
 +    ftpc->count3 = (conn->data->set.ftp_create_missing_dirs == 2)?1:0;
 +
 +    if((conn->data->set.ftp_filemethod == FTPFILE_NOCWD) && !ftpc->cwdcount)
 +      /* No CWD necessary */
 +      result = ftp_state_mdtm(conn);
 +    else if(conn->bits.reuse && ftpc->entrypath) {
 +      /* This is a re-used connection. Since we change directory to where the
 +         transfer is taking place, we must first get back to the original dir
 +         where we ended up after login: */
 +      ftpc->cwdcount = 0; /* we count this as the first path, then we add one
 +                             for all upcoming ones in the ftp->dirs[] array */
 +      PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath);
 +      state(conn, FTP_CWD);
 +    }
 +    else {
 +      if(ftpc->dirdepth) {
 +        ftpc->cwdcount = 1;
 +        /* issue the first CWD, the rest is sent when the CWD responses are
 +           received... */
 +        PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->cwdcount -1]);
 +        state(conn, FTP_CWD);
 +      }
 +      else {
 +        /* No CWD necessary */
 +        result = ftp_state_mdtm(conn);
 +      }
 +    }
 +  }
 +  return result;
 +}
 +
 +typedef enum {
 +  EPRT,
 +  PORT,
 +  DONE
 +} ftpport;
 +
 +static CURLcode ftp_state_use_port(struct connectdata *conn,
 +                                   ftpport fcmd) /* start with this */
 +
 +{
 +  CURLcode result = CURLE_OK;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct Curl_easy *data = conn->data;
 +  curl_socket_t portsock = CURL_SOCKET_BAD;
 +  char myhost[256] = "";
 +
 +  struct Curl_sockaddr_storage ss;
 +  Curl_addrinfo *res, *ai;
 +  curl_socklen_t sslen;
 +  char hbuf[NI_MAXHOST];
 +  struct sockaddr *sa = (struct sockaddr *)&ss;
 +  struct sockaddr_in * const sa4 = (void *)sa;
 +#ifdef ENABLE_IPV6
 +  struct sockaddr_in6 * const sa6 = (void *)sa;
 +#endif
 +  char tmp[1024];
 +  static const char mode[][5] = { "EPRT", "PORT" };
 +  int rc;
 +  int error;
 +  char *host = NULL;
 +  char *string_ftpport = data->set.str[STRING_FTPPORT];
 +  struct Curl_dns_entry *h = NULL;
 +  unsigned short port_min = 0;
 +  unsigned short port_max = 0;
 +  unsigned short port;
 +  bool possibly_non_local = TRUE;
- 
++  char buffer[STRERROR_LEN];
 +  char *addr = NULL;
 +
 +  /* Step 1, figure out what is requested,
 +   * accepted format :
 +   * (ipv4|ipv6|domain|interface)?(:port(-range)?)?
 +   */
 +
 +  if(data->set.str[STRING_FTPPORT] &&
 +     (strlen(data->set.str[STRING_FTPPORT]) > 1)) {
 +
 +#ifdef ENABLE_IPV6
 +    size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ?
 +      INET6_ADDRSTRLEN : strlen(string_ftpport);
 +#else
 +    size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ?
 +      INET_ADDRSTRLEN : strlen(string_ftpport);
 +#endif
 +    char *ip_start = string_ftpport;
 +    char *ip_end = NULL;
 +    char *port_start = NULL;
 +    char *port_sep = NULL;
 +
 +    addr = calloc(addrlen + 1, 1);
 +    if(!addr)
 +      return CURLE_OUT_OF_MEMORY;
 +
 +#ifdef ENABLE_IPV6
 +    if(*string_ftpport == '[') {
 +      /* [ipv6]:port(-range) */
 +      ip_start = string_ftpport + 1;
 +      ip_end = strchr(string_ftpport, ']');
 +      if(ip_end)
 +        strncpy(addr, ip_start, ip_end - ip_start);
 +    }
 +    else
 +#endif
 +      if(*string_ftpport == ':') {
 +        /* :port */
 +        ip_end = string_ftpport;
 +      }
 +      else {
 +        ip_end = strchr(string_ftpport, ':');
 +        if(ip_end) {
 +          /* either ipv6 or (ipv4|domain|interface):port(-range) */
 +#ifdef ENABLE_IPV6
 +          if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
 +            /* ipv6 */
 +            port_min = port_max = 0;
 +            strcpy(addr, string_ftpport);
 +            ip_end = NULL; /* this got no port ! */
 +          }
 +          else
 +#endif
 +            /* (ipv4|domain|interface):port(-range) */
 +            strncpy(addr, string_ftpport, ip_end - ip_start);
 +        }
 +        else
 +          /* ipv4|interface */
 +          strcpy(addr, string_ftpport);
 +      }
 +
 +    /* parse the port */
 +    if(ip_end != NULL) {
 +      port_start = strchr(ip_end, ':');
 +      if(port_start) {
 +        port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10));
 +        port_sep = strchr(port_start, '-');
 +        if(port_sep) {
 +          port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
 +        }
 +        else
 +          port_max = port_min;
 +      }
 +    }
 +
 +    /* correct errors like:
 +     *  :1234-1230
 +     *  :-4711,  in this case port_min is (unsigned)-1,
 +     *           therefore port_min > port_max for all cases
 +     *           but port_max = (unsigned)-1
 +     */
 +    if(port_min > port_max)
 +      port_min = port_max = 0;
 +
 +
 +    if(*addr != '\0') {
 +      /* attempt to get the address of the given interface name */
 +      switch(Curl_if2ip(conn->ip_addr->ai_family,
 +                        Curl_ipv6_scope(conn->ip_addr->ai_addr),
 +                        conn->scope_id, addr, hbuf, sizeof(hbuf))) {
 +        case IF2IP_NOT_FOUND:
 +          /* not an interface, use the given string as host name instead */
 +          host = addr;
 +          break;
 +        case IF2IP_AF_NOT_SUPPORTED:
 +          return CURLE_FTP_PORT_FAILED;
 +        case IF2IP_FOUND:
 +          host = hbuf; /* use the hbuf for host name */
 +      }
 +    }
 +    else
 +      /* there was only a port(-range) given, default the host */
 +      host = NULL;
 +  } /* data->set.ftpport */
 +
 +  if(!host) {
 +    /* not an interface and not a host name, get default by extracting
 +       the IP from the control connection */
- 
 +    sslen = sizeof(ss);
 +    if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
 +      failf(data, "getsockname() failed: %s",
-           Curl_strerror(conn, SOCKERRNO) );
++            Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
 +      free(addr);
 +      return CURLE_FTP_PORT_FAILED;
 +    }
 +    switch(sa->sa_family) {
 +#ifdef ENABLE_IPV6
 +    case AF_INET6:
 +      Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
 +      break;
 +#endif
 +    default:
 +      Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
 +      break;
 +    }
 +    host = hbuf; /* use this host name */
 +    possibly_non_local = FALSE; /* we know it is local now */
 +  }
 +
 +  /* resolv ip/host to ip */
-   rc = Curl_resolv(conn, host, 0, &h);
++  rc = Curl_resolv(conn, host, 0, FALSE, &h);
 +  if(rc == CURLRESOLV_PENDING)
 +    (void)Curl_resolver_wait_resolv(conn, &h);
 +  if(h) {
 +    res = h->addr;
 +    /* when we return from this function, we can forget about this entry
 +       to we can unlock it now already */
 +    Curl_resolv_unlock(data, h);
 +  } /* (h) */
 +  else
 +    res = NULL; /* failure! */
 +
 +  if(res == NULL) {
 +    failf(data, "failed to resolve the address provided to PORT: %s", host);
 +    free(addr);
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  free(addr);
 +  host = NULL;
 +
 +  /* step 2, create a socket for the requested address */
 +
 +  portsock = CURL_SOCKET_BAD;
 +  error = 0;
 +  for(ai = res; ai; ai = ai->ai_next) {
 +    result = Curl_socket(conn, ai, NULL, &portsock);
 +    if(result) {
 +      error = SOCKERRNO;
 +      continue;
 +    }
 +    break;
 +  }
 +  if(!ai) {
-     failf(data, "socket failure: %s", Curl_strerror(conn, error));
++    failf(data, "socket failure: %s",
++          Curl_strerror(error, buffer, sizeof(buffer)));
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* step 3, bind to a suitable local address */
 +
 +  memcpy(sa, ai->ai_addr, ai->ai_addrlen);
 +  sslen = ai->ai_addrlen;
 +
 +  for(port = port_min; port <= port_max;) {
 +    if(sa->sa_family == AF_INET)
 +      sa4->sin_port = htons(port);
 +#ifdef ENABLE_IPV6
 +    else
 +      sa6->sin6_port = htons(port);
 +#endif
 +    /* Try binding the given address. */
 +    if(bind(portsock, sa, sslen) ) {
 +      /* It failed. */
 +      error = SOCKERRNO;
 +      if(possibly_non_local && (error == EADDRNOTAVAIL)) {
 +        /* The requested bind address is not local.  Use the address used for
 +         * the control connection instead and restart the port loop
 +         */
- 
 +        infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
-               Curl_strerror(conn, error) );
++              Curl_strerror(error, buffer, sizeof(buffer)));
 +
 +        sslen = sizeof(ss);
 +        if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
 +          failf(data, "getsockname() failed: %s",
-                 Curl_strerror(conn, SOCKERRNO) );
++                Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
 +          Curl_closesocket(conn, portsock);
 +          return CURLE_FTP_PORT_FAILED;
 +        }
 +        port = port_min;
 +        possibly_non_local = FALSE; /* don't try this again */
 +        continue;
 +      }
 +      if(error != EADDRINUSE && error != EACCES) {
 +        failf(data, "bind(port=%hu) failed: %s", port,
-               Curl_strerror(conn, error) );
++              Curl_strerror(error, buffer, sizeof(buffer)));
 +        Curl_closesocket(conn, portsock);
 +        return CURLE_FTP_PORT_FAILED;
 +      }
 +    }
 +    else
 +      break;
 +
 +    port++;
 +  }
 +
 +  /* maybe all ports were in use already*/
 +  if(port > port_max) {
 +    failf(data, "bind() failed, we ran out of ports!");
 +    Curl_closesocket(conn, portsock);
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* get the name again after the bind() so that we can extract the
 +     port number it uses now */
 +  sslen = sizeof(ss);
 +  if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
 +    failf(data, "getsockname() failed: %s",
-           Curl_strerror(conn, SOCKERRNO) );
++          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
 +    Curl_closesocket(conn, portsock);
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* step 4, listen on the socket */
 +
 +  if(listen(portsock, 1)) {
-     failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO));
++    failf(data, "socket failure: %s",
++          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
 +    Curl_closesocket(conn, portsock);
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* step 5, send the proper FTP command */
 +
 +  /* get a plain printable version of the numerical address to work with
 +     below */
 +  Curl_printable_address(ai, myhost, sizeof(myhost));
 +
 +#ifdef ENABLE_IPV6
 +  if(!conn->bits.ftp_use_eprt && conn->bits.ipv6)
 +    /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the
 +       request and enable EPRT again! */
 +    conn->bits.ftp_use_eprt = TRUE;
 +#endif
 +
 +  for(; fcmd != DONE; fcmd++) {
 +
 +    if(!conn->bits.ftp_use_eprt && (EPRT == fcmd))
 +      /* if disabled, goto next */
 +      continue;
 +
 +    if((PORT == fcmd) && sa->sa_family != AF_INET)
 +      /* PORT is IPv4 only */
 +      continue;
 +
 +    switch(sa->sa_family) {
 +    case AF_INET:
 +      port = ntohs(sa4->sin_port);
 +      break;
 +#ifdef ENABLE_IPV6
 +    case AF_INET6:
 +      port = ntohs(sa6->sin6_port);
 +      break;
 +#endif
 +    default:
 +      continue; /* might as well skip this */
 +    }
 +
 +    if(EPRT == fcmd) {
 +      /*
 +       * Two fine examples from RFC2428;
 +       *
 +       * EPRT |1|132.235.1.2|6275|
 +       *
 +       * EPRT |2|1080::8:800:200C:417A|5282|
 +       */
 +
 +      result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
 +                             sa->sa_family == AF_INET?1:2,
 +                             myhost, port);
 +      if(result) {
 +        failf(data, "Failure sending EPRT command: %s",
 +              curl_easy_strerror(result));
 +        Curl_closesocket(conn, portsock);
 +        /* don't retry using PORT */
 +        ftpc->count1 = PORT;
 +        /* bail out */
 +        state(conn, FTP_STOP);
 +        return result;
 +      }
 +      break;
 +    }
 +    if(PORT == fcmd) {
 +      char *source = myhost;
 +      char *dest = tmp;
 +
 +      /* translate x.x.x.x to x,x,x,x */
 +      while(source && *source) {
 +        if(*source == '.')
 +          *dest = ',';
 +        else
 +          *dest = *source;
 +        dest++;
 +        source++;
 +      }
 +      *dest = 0;
-       snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
++      msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
 +
 +      result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
 +      if(result) {
 +        failf(data, "Failure sending PORT command: %s",
 +              curl_easy_strerror(result));
 +        Curl_closesocket(conn, portsock);
 +        /* bail out */
 +        state(conn, FTP_STOP);
 +        return result;
 +      }
 +      break;
 +    }
 +  }
 +
 +  /* store which command was sent */
 +  ftpc->count1 = fcmd;
 +
 +  close_secondarysocket(conn);
 +
 +  /* we set the secondary socket variable to this for now, it is only so that
 +     the cleanup function will close it in case we fail before the true
 +     secondary stuff is made */
 +  conn->sock[SECONDARYSOCKET] = portsock;
 +
 +  /* this tcpconnect assignment below is a hackish work-around to make the
 +     multi interface with active FTP work - as it will not wait for a
 +     (passive) connect in Curl_is_connected().
 +
 +     The *proper* fix is to make sure that the active connection from the
 +     server is done in a non-blocking way. Currently, it is still BLOCKING.
 +  */
 +  conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
 +
 +  state(conn, FTP_PORT);
 +  return result;
 +}
 +
 +static CURLcode ftp_state_use_pasv(struct connectdata *conn)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  CURLcode result = CURLE_OK;
 +  /*
 +    Here's the excecutive summary on what to do:
 +
 +    PASV is RFC959, expect:
 +    227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
 +
 +    LPSV is RFC1639, expect:
 +    228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2)
 +
 +    EPSV is RFC2428, expect:
 +    229 Entering Extended Passive Mode (|||port|)
 +
 +  */
 +
 +  static const char mode[][5] = { "EPSV", "PASV" };
 +  int modeoff;
 +
 +#ifdef PF_INET6
 +  if(!conn->bits.ftp_use_epsv && conn->bits.ipv6)
 +    /* EPSV is disabled but we are connected to a IPv6 host, so we ignore the
 +       request and enable EPSV again! */
 +    conn->bits.ftp_use_epsv = TRUE;
 +#endif
 +
 +  modeoff = conn->bits.ftp_use_epsv?0:1;
 +
 +  PPSENDF(&ftpc->pp, "%s", mode[modeoff]);
 +
 +  ftpc->count1 = modeoff;
 +  state(conn, FTP_PASV);
 +  infof(conn->data, "Connect data stream passively\n");
 +
 +  return result;
 +}
 +
 +/*
 + * ftp_state_prepare_transfer() starts PORT, PASV or PRET etc.
 + *
 + * REST is the last command in the chain of commands when a "head"-like
 + * request is made. Thus, if an actual transfer is to be made this is where we
 + * take off for real.
 + */
 +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct Curl_easy *data = conn->data;
 +
 +  if(ftp->transfer != FTPTRANSFER_BODY) {
 +    /* doesn't transfer any data */
 +
 +    /* still possibly do PRE QUOTE jobs */
 +    state(conn, FTP_RETR_PREQUOTE);
 +    result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
 +  }
 +  else if(data->set.ftp_use_port) {
 +    /* We have chosen to use the PORT (or similar) command */
 +    result = ftp_state_use_port(conn, EPRT);
 +  }
 +  else {
 +    /* We have chosen (this is default) to use the PASV (or similar) command */
 +    if(data->set.ftp_use_pret) {
 +      /* The user has requested that we send a PRET command
 +         to prepare the server for the upcoming PASV */
 +      if(!conn->proto.ftpc.file) {
 +        PPSENDF(&conn->proto.ftpc.pp, "PRET %s",
 +                data->set.str[STRING_CUSTOMREQUEST]?
 +                data->set.str[STRING_CUSTOMREQUEST]:
 +                (data->set.ftp_list_only?"NLST":"LIST"));
 +      }
 +      else if(data->set.upload) {
 +        PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file);
 +      }
 +      else {
 +        PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file);
 +      }
 +      state(conn, FTP_PRET);
 +    }
 +    else {
 +      result = ftp_state_use_pasv(conn);
 +    }
 +  }
 +  return result;
 +}
 +
 +static CURLcode ftp_state_rest(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) {
 +    /* if a "head"-like request is being made (on a file) */
 +
 +    /* Determine if server can respond to REST command and therefore
 +       whether it supports range */
 +    PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0);
 +
 +    state(conn, FTP_REST);
 +  }
 +  else
 +    result = ftp_state_prepare_transfer(conn);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_size(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) {
 +    /* if a "head"-like request is being made (on a file) */
 +
 +    /* we know ftpc->file is a valid pointer to a file name */
 +    PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
 +
 +    state(conn, FTP_SIZE);
 +  }
 +  else
 +    result = ftp_state_rest(conn);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_list(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +
 +  /* If this output is to be machine-parsed, the NLST command might be better
 +     to use, since the LIST command output is not specified or standard in any
 +     way. It has turned out that the NLST list output is not the same on all
 +     servers either... */
 +
 +  /*
 +     if FTPFILE_NOCWD was specified, we are currently in
 +     the user's home directory, so we should add the path
 +     as argument for the LIST / NLST / or custom command.
 +     Whether the server will support this, is uncertain.
 +
 +     The other ftp_filemethods will CWD into dir/dir/ first and
 +     then just do LIST (in that case: nothing to do here)
 +  */
 +  char *cmd, *lstArg, *slashPos;
 +  const char *inpath = ftp->path;
 +
 +  lstArg = NULL;
 +  if((data->set.ftp_filemethod == FTPFILE_NOCWD) &&
 +     inpath && inpath[0] && strchr(inpath, '/')) {
 +    size_t n = strlen(inpath);
 +
 +    /* Check if path does not end with /, as then we cut off the file part */
 +    if(inpath[n - 1] != '/') {
 +      /* chop off the file part if format is dir/dir/file */
 +      slashPos = strrchr(inpath, '/');
 +      n = slashPos - inpath;
 +    }
 +    result = Curl_urldecode(data, inpath, n, &lstArg, NULL, TRUE);
 +    if(result)
 +      return result;
 +  }
 +
 +  cmd = aprintf("%s%s%s",
 +                data->set.str[STRING_CUSTOMREQUEST]?
 +                data->set.str[STRING_CUSTOMREQUEST]:
 +                (data->set.ftp_list_only?"NLST":"LIST"),
 +                lstArg? " ": "",
 +                lstArg? lstArg: "");
 +
 +  if(!cmd) {
 +    free(lstArg);
 +    return CURLE_OUT_OF_MEMORY;
 +  }
 +
 +  result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd);
 +
 +  free(lstArg);
 +  free(cmd);
 +
 +  if(result)
 +    return result;
 +
 +  state(conn, FTP_LIST);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_retr_prequote(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +
 +  /* We've sent the TYPE, now we must send the list of prequote strings */
 +
 +  result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +
 +  /* We've sent the TYPE, now we must send the list of prequote strings */
 +
 +  result = ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_type(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  /* If we have selected NOBODY and HEADER, it means that we only want file
 +     information. Which in FTP can't be much more than the file size and
 +     date. */
 +  if(data->set.opt_no_body && ftpc->file &&
 +     ftp_need_type(conn, data->set.prefer_ascii)) {
 +    /* The SIZE command is _not_ RFC 959 specified, and therefore many servers
 +       may not support it! It is however the only way we have to get a file's
 +       size! */
 +
 +    ftp->transfer = FTPTRANSFER_INFO;
 +    /* this means no actual transfer will be made */
 +
 +    /* Some servers return different sizes for different modes, and thus we
 +       must set the proper type before we check the size */
 +    result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE);
 +    if(result)
 +      return result;
 +  }
 +  else
 +    result = ftp_state_size(conn);
 +
 +  return result;
 +}
 +
 +/* This is called after the CWD commands have been done in the beginning of
 +   the DO phase */
 +static CURLcode ftp_state_mdtm(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  /* Requested time of file or time-depended transfer? */
 +  if((data->set.get_filetime || data->set.timecondition) && ftpc->file) {
 +
 +    /* we have requested to get the modified-time of the file, this is a white
 +       spot as the MDTM is not mentioned in RFC959 */
 +    PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file);
 +
 +    state(conn, FTP_MDTM);
 +  }
 +  else
 +    result = ftp_state_type(conn);
 +
 +  return result;
 +}
 +
 +
 +/* This is called after the TYPE and possible quote commands have been sent */
 +static CURLcode ftp_state_ul_setup(struct connectdata *conn,
 +                                   bool sizechecked)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if((data->state.resume_from && !sizechecked) ||
 +     ((data->state.resume_from > 0) && sizechecked)) {
 +    /* we're about to continue the uploading of a file */
 +    /* 1. get already existing file's size. We use the SIZE command for this
 +       which may not exist in the server!  The SIZE command is not in
 +       RFC959. */
 +
 +    /* 2. This used to set REST. But since we can do append, we
 +       don't another ftp command. We just skip the source file
 +       offset and then we APPEND the rest on the file instead */
 +
 +    /* 3. pass file-size number of bytes in the source file */
 +    /* 4. lower the infilesize counter */
 +    /* => transfer as usual */
 +    int seekerr = CURL_SEEKFUNC_OK;
 +
 +    if(data->state.resume_from < 0) {
 +      /* Got no given size to start from, figure it out */
 +      PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
 +      state(conn, FTP_STOR_SIZE);
 +      return result;
 +    }
 +
 +    /* enable append */
 +    data->set.ftp_append = TRUE;
 +
 +    /* Let's read off the proper amount of bytes from the input. */
 +    if(conn->seek_func) {
 +      Curl_set_in_callback(data, true);
 +      seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
 +                                SEEK_SET);
 +      Curl_set_in_callback(data, false);
 +    }
 +
 +    if(seekerr != CURL_SEEKFUNC_OK) {
 +      curl_off_t passed = 0;
 +      if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
 +        failf(data, "Could not seek stream");
 +        return CURLE_FTP_COULDNT_USE_REST;
 +      }
 +      /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
 +      do {
 +        size_t readthisamountnow =
 +          (data->state.resume_from - passed > data->set.buffer_size) ?
 +          (size_t)data->set.buffer_size :
 +          curlx_sotouz(data->state.resume_from - passed);
 +
 +        size_t actuallyread =
 +          data->state.fread_func(data->state.buffer, 1, readthisamountnow,
 +                                 data->state.in);
 +
 +        passed += actuallyread;
 +        if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
 +          /* this checks for greater-than only to make sure that the
 +             CURL_READFUNC_ABORT return code still aborts */
 +          failf(data, "Failed to read data");
 +          return CURLE_FTP_COULDNT_USE_REST;
 +        }
 +      } while(passed < data->state.resume_from);
 +    }
 +    /* now, decrease the size of the read */
 +    if(data->state.infilesize>0) {
 +      data->state.infilesize -= data->state.resume_from;
 +
 +      if(data->state.infilesize <= 0) {
 +        infof(data, "File already completely uploaded\n");
 +
 +        /* no data to transfer */
-         Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
++        Curl_setup_transfer(data, -1, -1, FALSE, -1);
 +
 +        /* Set ->transfer so that we won't get any error in
 +         * ftp_done() because we didn't transfer anything! */
 +        ftp->transfer = FTPTRANSFER_NONE;
 +
 +        state(conn, FTP_STOP);
 +        return CURLE_OK;
 +      }
 +    }
 +    /* we've passed, proceed as normal */
 +  } /* resume_from */
 +
 +  PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s",
 +          ftpc->file);
 +
 +  state(conn, FTP_STOR);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_quote(struct connectdata *conn,
 +                                bool init,
 +                                ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  bool quote = FALSE;
 +  struct curl_slist *item;
 +
 +  switch(instate) {
 +  case FTP_QUOTE:
 +  default:
 +    item = data->set.quote;
 +    break;
 +  case FTP_RETR_PREQUOTE:
 +  case FTP_STOR_PREQUOTE:
 +    item = data->set.prequote;
 +    break;
 +  case FTP_POSTQUOTE:
 +    item = data->set.postquote;
 +    break;
 +  }
 +
 +  /*
 +   * This state uses:
 +   * 'count1' to iterate over the commands to send
 +   * 'count2' to store whether to allow commands to fail
 +   */
 +
 +  if(init)
 +    ftpc->count1 = 0;
 +  else
 +    ftpc->count1++;
 +
 +  if(item) {
 +    int i = 0;
 +
 +    /* Skip count1 items in the linked list */
 +    while((i< ftpc->count1) && item) {
 +      item = item->next;
 +      i++;
 +    }
 +    if(item) {
 +      char *cmd = item->data;
 +      if(cmd[0] == '*') {
 +        cmd++;
 +        ftpc->count2 = 1; /* the sent command is allowed to fail */
 +      }
 +      else
 +        ftpc->count2 = 0; /* failure means cancel operation */
 +
 +      PPSENDF(&ftpc->pp, "%s", cmd);
 +      state(conn, instate);
 +      quote = TRUE;
 +    }
 +  }
 +
 +  if(!quote) {
 +    /* No more quote to send, continue to ... */
 +    switch(instate) {
 +    case FTP_QUOTE:
 +    default:
 +      result = ftp_state_cwd(conn);
 +      break;
 +    case FTP_RETR_PREQUOTE:
 +      if(ftp->transfer != FTPTRANSFER_BODY)
 +        state(conn, FTP_STOP);
 +      else {
 +        if(ftpc->known_filesize != -1) {
 +          Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
 +          result = ftp_state_retr(conn, ftpc->known_filesize);
 +        }
 +        else {
 +          if(data->set.ignorecl) {
 +            /* This code is to support download of growing files.  It prevents
 +               the state machine from requesting the file size from the
 +               server.  With an unknown file size the download continues until
 +               the server terminates it, otherwise the client stops if the
 +               received byte count exceeds the reported file size.  Set option
 +               CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/
 +            PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
 +            state(conn, FTP_RETR);
 +          }
 +          else {
 +            PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
 +            state(conn, FTP_RETR_SIZE);
 +          }
 +        }
 +      }
 +      break;
 +    case FTP_STOR_PREQUOTE:
 +      result = ftp_state_ul_setup(conn, FALSE);
 +      break;
 +    case FTP_POSTQUOTE:
 +      break;
 +    }
 +  }
 +
 +  return result;
 +}
 +
 +/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV
 +   problems */
 +static CURLcode ftp_epsv_disable(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +
 +  if(conn->bits.ipv6 && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)) {
 +    /* We can't disable EPSV when doing IPv6, so this is instead a fail */
 +    failf(conn->data, "Failed EPSV attempt, exiting\n");
 +    return CURLE_WEIRD_SERVER_REPLY;
 +  }
 +
 +  infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n");
 +  /* disable it for next transfer */
 +  conn->bits.ftp_use_epsv = FALSE;
 +  conn->data->state.errorbuf = FALSE; /* allow error message to get
 +                                         rewritten */
 +  PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV");
 +  conn->proto.ftpc.count1++;
 +  /* remain in/go to the FTP_PASV state */
 +  state(conn, FTP_PASV);
 +  return result;
 +}
 +
 +
 +static char *control_address(struct connectdata *conn)
 +{
 +  /* Returns the control connection IP address.
 +     If a proxy tunnel is used, returns the original host name instead, because
 +     the effective control connection address is the proxy address,
 +     not the ftp host. */
 +  if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
 +    return conn->host.name;
 +
 +  return conn->ip_addr_str;
 +}
 +
 +static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
 +                                    int ftpcode)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  CURLcode result;
 +  struct Curl_easy *data = conn->data;
 +  struct Curl_dns_entry *addr = NULL;
 +  int rc;
 +  unsigned short connectport; /* the local port connect() should use! */
 +  char *str = &data->state.buffer[4];  /* start on the first letter */
 +
 +  /* if we come here again, make sure the former name is cleared */
 +  Curl_safefree(ftpc->newhost);
 +
 +  if((ftpc->count1 == 0) &&
 +     (ftpcode == 229)) {
 +    /* positive EPSV response */
 +    char *ptr = strchr(str, '(');
 +    if(ptr) {
 +      unsigned int num;
 +      char separator[4];
 +      ptr++;
 +      if(5 == sscanf(ptr, "%c%c%c%u%c",
 +                     &separator[0],
 +                     &separator[1],
 +                     &separator[2],
 +                     &num,
 +                     &separator[3])) {
 +        const char sep1 = separator[0];
 +        int i;
 +
 +        /* The four separators should be identical, or else this is an oddly
 +           formatted reply and we bail out immediately. */
 +        for(i = 1; i<4; i++) {
 +          if(separator[i] != sep1) {
 +            ptr = NULL; /* set to NULL to signal error */
 +            break;
 +          }
 +        }
 +        if(num > 0xffff) {
 +          failf(data, "Illegal port number in EPSV reply");
 +          return CURLE_FTP_WEIRD_PASV_REPLY;
 +        }
 +        if(ptr) {
 +          ftpc->newport = (unsigned short)(num & 0xffff);
 +          ftpc->newhost = strdup(control_address(conn));
 +          if(!ftpc->newhost)
 +            return CURLE_OUT_OF_MEMORY;
 +        }
 +      }
 +      else
 +        ptr = NULL;
 +    }
 +    if(!ptr) {
 +      failf(data, "Weirdly formatted EPSV reply");
 +      return CURLE_FTP_WEIRD_PASV_REPLY;
 +    }
 +  }
 +  else if((ftpc->count1 == 1) &&
 +          (ftpcode == 227)) {
 +    /* positive PASV response */
 +    unsigned int ip[4];
 +    unsigned int port[2];
 +
 +    /*
 +     * Scan for a sequence of six comma-separated numbers and use them as
 +     * IP+port indicators.
 +     *
 +     * Found reply-strings include:
 +     * "227 Entering Passive Mode (127,0,0,1,4,51)"
 +     * "227 Data transfer will passively listen to 127,0,0,1,4,51"
 +     * "227 Entering passive mode. 127,0,0,1,4,51"
 +     */
 +    while(*str) {
 +      if(6 == sscanf(str, "%u,%u,%u,%u,%u,%u",
 +                     &ip[0], &ip[1], &ip[2], &ip[3],
 +                     &port[0], &port[1]))
 +        break;
 +      str++;
 +    }
 +
 +    if(!*str || (ip[0] > 255) || (ip[1] > 255)  || (ip[2] > 255)  ||
 +       (ip[3] > 255) || (port[0] > 255)  || (port[1] > 255) ) {
 +      failf(data, "Couldn't interpret the 227-response");
 +      return CURLE_FTP_WEIRD_227_FORMAT;
 +    }
 +
 +    /* we got OK from server */
 +    if(data->set.ftp_skip_ip) {
 +      /* told to ignore the remotely given IP but instead use the host we used
 +         for the control connection */
 +      infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead\n",
 +            ip[0], ip[1], ip[2], ip[3],
 +            conn->host.name);
 +      ftpc->newhost = strdup(control_address(conn));
 +    }
 +    else
 +      ftpc->newhost = aprintf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
 +
 +    if(!ftpc->newhost)
 +      return CURLE_OUT_OF_MEMORY;
 +
 +    ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff);
 +  }
 +  else if(ftpc->count1 == 0) {
 +    /* EPSV failed, move on to PASV */
 +    return ftp_epsv_disable(conn);
 +  }
 +  else {
 +    failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
 +    return CURLE_FTP_WEIRD_PASV_REPLY;
 +  }
 +
 +  if(conn->bits.proxy) {
 +    /*
 +     * This connection uses a proxy and we need to connect to the proxy again
 +     * here. We don't want to rely on a former host lookup that might've
 +     * expired now, instead we remake the lookup here and now!
 +     */
 +    const char * const host_name = conn->bits.socksproxy ?
 +      conn->socks_proxy.host.name : conn->http_proxy.host.name;
-     rc = Curl_resolv(conn, host_name, (int)conn->port, &addr);
++    rc = Curl_resolv(conn, host_name, (int)conn->port, FALSE, &addr);
 +    if(rc == CURLRESOLV_PENDING)
 +      /* BLOCKING, ignores the return code but 'addr' will be NULL in
 +         case of failure */
 +      (void)Curl_resolver_wait_resolv(conn, &addr);
 +
 +    connectport =
 +      (unsigned short)conn->port; /* we connect to the proxy's port */
 +
 +    if(!addr) {
 +      failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
 +      return CURLE_COULDNT_RESOLVE_PROXY;
 +    }
 +  }
 +  else {
 +    /* normal, direct, ftp connection */
-     rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr);
++    rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr);
 +    if(rc == CURLRESOLV_PENDING)
 +      /* BLOCKING */
 +      (void)Curl_resolver_wait_resolv(conn, &addr);
 +
 +    connectport = ftpc->newport; /* we connect to the remote port */
 +
 +    if(!addr) {
 +      failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport);
 +      return CURLE_FTP_CANT_GET_HOST;
 +    }
 +  }
 +
 +  conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
 +  result = Curl_connecthost(conn, addr);
 +
 +  if(result) {
 +    Curl_resolv_unlock(data, addr); /* we're done using this address */
 +    if(ftpc->count1 == 0 && ftpcode == 229)
 +      return ftp_epsv_disable(conn);
 +
 +    return result;
 +  }
 +
 +
 +  /*
 +   * When this is used from the multi interface, this might've returned with
 +   * the 'connected' set to FALSE and thus we are now awaiting a non-blocking
 +   * connect to connect.
 +   */
 +
 +  if(data->set.verbose)
 +    /* this just dumps information about this second connection */
 +    ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
 +
 +  Curl_resolv_unlock(data, addr); /* we're done using this address */
 +
 +  Curl_safefree(conn->secondaryhostname);
 +  conn->secondary_port = ftpc->newport;
 +  conn->secondaryhostname = strdup(ftpc->newhost);
 +  if(!conn->secondaryhostname)
 +    return CURLE_OUT_OF_MEMORY;
 +
 +  conn->bits.do_more = TRUE;
 +  state(conn, FTP_STOP); /* this phase is completed */
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_port_resp(struct connectdata *conn,
 +                                    int ftpcode)
 +{
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  ftpport fcmd = (ftpport)ftpc->count1;
 +  CURLcode result = CURLE_OK;
 +
 +  /* The FTP spec tells a positive response should have code 200.
 +     Be more permissive here to tolerate deviant servers. */
 +  if(ftpcode / 100 != 2) {
 +    /* the command failed */
 +
 +    if(EPRT == fcmd) {
 +      infof(data, "disabling EPRT usage\n");
 +      conn->bits.ftp_use_eprt = FALSE;
 +    }
 +    fcmd++;
 +
 +    if(fcmd == DONE) {
 +      failf(data, "Failed to do PORT");
 +      result = CURLE_FTP_PORT_FAILED;
 +    }
 +    else
 +      /* try next */
 +      result = ftp_state_use_port(conn, fcmd);
 +  }
 +  else {
 +    infof(data, "Connect data stream actively\n");
 +    state(conn, FTP_STOP); /* end of DO phase */
 +    result = ftp_dophase_done(conn, FALSE);
 +  }
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
 +                                    int ftpcode)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  switch(ftpcode) {
 +  case 213:
 +    {
 +      /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
 +         last .sss part is optional and means fractions of a second */
 +      int year, month, day, hour, minute, second;
 +      if(6 == sscanf(&data->state.buffer[4], "%04d%02d%02d%02d%02d%02d",
 +                     &year, &month, &day, &hour, &minute, &second)) {
 +        /* we have a time, reformat it */
 +        char timebuf[24];
 +        time_t secs = time(NULL);
 +
-         snprintf(timebuf, sizeof(timebuf),
-                  "%04d%02d%02d %02d:%02d:%02d GMT",
-                  year, month, day, hour, minute, second);
++        msnprintf(timebuf, sizeof(timebuf),
++                  "%04d%02d%02d %02d:%02d:%02d GMT",
++                  year, month, day, hour, minute, second);
 +        /* now, convert this into a time() value: */
 +        data->info.filetime = curl_getdate(timebuf, &secs);
 +      }
 +
 +#ifdef CURL_FTP_HTTPSTYLE_HEAD
 +      /* If we asked for a time of the file and we actually got one as well,
 +         we "emulate" a HTTP-style header in our output. */
 +
 +      if(data->set.opt_no_body &&
 +         ftpc->file &&
 +         data->set.get_filetime &&
 +         (data->info.filetime >= 0) ) {
 +        char headerbuf[128];
 +        time_t filetime = data->info.filetime;
 +        struct tm buffer;
 +        const struct tm *tm = &buffer;
 +
 +        result = Curl_gmtime(filetime, &buffer);
 +        if(result)
 +          return result;
 +
 +        /* format: "Tue, 15 Nov 1994 12:45:26" */
-         snprintf(headerbuf, sizeof(headerbuf),
-                  "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
-                  Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-                  tm->tm_mday,
-                  Curl_month[tm->tm_mon],
-                  tm->tm_year + 1900,
-                  tm->tm_hour,
-                  tm->tm_min,
-                  tm->tm_sec);
++        msnprintf(headerbuf, sizeof(headerbuf),
++                  "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
++                  Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
++                  tm->tm_mday,
++                  Curl_month[tm->tm_mon],
++                  tm->tm_year + 1900,
++                  tm->tm_hour,
++                  tm->tm_min,
++                  tm->tm_sec);
 +        result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0);
 +        if(result)
 +          return result;
 +      } /* end of a ridiculous amount of conditionals */
 +#endif
 +    }
 +    break;
 +  default:
 +    infof(data, "unsupported MDTM reply format\n");
 +    break;
 +  case 550: /* "No such file or directory" */
 +    failf(data, "Given file does not exist");
 +    result = CURLE_FTP_COULDNT_RETR_FILE;
 +    break;
 +  }
 +
 +  if(data->set.timecondition) {
 +    if((data->info.filetime > 0) && (data->set.timevalue > 0)) {
 +      switch(data->set.timecondition) {
 +      case CURL_TIMECOND_IFMODSINCE:
 +      default:
 +        if(data->info.filetime <= data->set.timevalue) {
 +          infof(data, "The requested document is not new enough\n");
 +          ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
 +          data->info.timecond = TRUE;
 +          state(conn, FTP_STOP);
 +          return CURLE_OK;
 +        }
 +        break;
 +      case CURL_TIMECOND_IFUNMODSINCE:
 +        if(data->info.filetime > data->set.timevalue) {
 +          infof(data, "The requested document is not old enough\n");
 +          ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
 +          data->info.timecond = TRUE;
 +          state(conn, FTP_STOP);
 +          return CURLE_OK;
 +        }
 +        break;
 +      } /* switch */
 +    }
 +    else {
 +      infof(data, "Skipping time comparison\n");
 +    }
 +  }
 +
 +  if(!result)
 +    result = ftp_state_type(conn);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_type_resp(struct connectdata *conn,
 +                                    int ftpcode,
 +                                    ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +
 +  if(ftpcode/100 != 2) {
 +    /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
 +       successful 'TYPE I'. While that is not as RFC959 says, it is still a
 +       positive response code and we allow that. */
 +    failf(data, "Couldn't set desired mode");
 +    return CURLE_FTP_COULDNT_SET_TYPE;
 +  }
 +  if(ftpcode != 200)
 +    infof(data, "Got a %03d response code instead of the assumed 200\n",
 +          ftpcode);
 +
 +  if(instate == FTP_TYPE)
 +    result = ftp_state_size(conn);
 +  else if(instate == FTP_LIST_TYPE)
 +    result = ftp_state_list(conn);
 +  else if(instate == FTP_RETR_TYPE)
 +    result = ftp_state_retr_prequote(conn);
 +  else if(instate == FTP_STOR_TYPE)
 +    result = ftp_state_stor_prequote(conn);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_retr(struct connectdata *conn,
 +                                         curl_off_t filesize)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
 +    failf(data, "Maximum file size exceeded");
 +    return CURLE_FILESIZE_EXCEEDED;
 +  }
 +  ftp->downloadsize = filesize;
 +
 +  if(data->state.resume_from) {
 +    /* We always (attempt to) get the size of downloads, so it is done before
 +       this even when not doing resumes. */
 +    if(filesize == -1) {
 +      infof(data, "ftp server doesn't support SIZE\n");
 +      /* We couldn't get the size and therefore we can't know if there really
 +         is a part of the file left to get, although the server will just
 +         close the connection when we start the connection so it won't cause
 +         us any harm, just not make us exit as nicely. */
 +    }
 +    else {
 +      /* We got a file size report, so we check that there actually is a
 +         part of the file left to get, or else we go home.  */
 +      if(data->state.resume_from< 0) {
 +        /* We're supposed to download the last abs(from) bytes */
 +        if(filesize < -data->state.resume_from) {
 +          failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
 +                ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
 +                data->state.resume_from, filesize);
 +          return CURLE_BAD_DOWNLOAD_RESUME;
 +        }
 +        /* convert to size to download */
 +        ftp->downloadsize = -data->state.resume_from;
 +        /* download from where? */
 +        data->state.resume_from = filesize - ftp->downloadsize;
 +      }
 +      else {
 +        if(filesize < data->state.resume_from) {
 +          failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
 +                ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
 +                data->state.resume_from, filesize);
 +          return CURLE_BAD_DOWNLOAD_RESUME;
 +        }
 +        /* Now store the number of bytes we are expected to download */
 +        ftp->downloadsize = filesize-data->state.resume_from;
 +      }
 +    }
 +
 +    if(ftp->downloadsize == 0) {
 +      /* no data to transfer */
-       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
++      Curl_setup_transfer(data, -1, -1, FALSE, -1);
 +      infof(data, "File already completely downloaded\n");
 +
 +      /* Set ->transfer so that we won't get any error in ftp_done()
 +       * because we didn't transfer the any file */
 +      ftp->transfer = FTPTRANSFER_NONE;
 +      state(conn, FTP_STOP);
 +      return CURLE_OK;
 +    }
 +
 +    /* Set resume file transfer offset */
 +    infof(data, "Instructs server to resume from offset %"
 +          CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from);
 +
 +    PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
 +            data->state.resume_from);
 +
 +    state(conn, FTP_RETR_REST);
 +  }
 +  else {
 +    /* no resume */
 +    PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
 +    state(conn, FTP_RETR);
 +  }
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_size_resp(struct connectdata *conn,
 +                                    int ftpcode,
 +                                    ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  curl_off_t filesize = -1;
 +  char *buf = data->state.buffer;
 +
 +  /* get the size from the ascii string: */
 +  if(ftpcode == 213)
 +    /* ignores parsing errors, which will make the size remain unknown */
 +    (void)curlx_strtoofft(buf + 4, NULL, 0, &filesize);
 +
 +  if(instate == FTP_SIZE) {
 +#ifdef CURL_FTP_HTTPSTYLE_HEAD
 +    if(-1 != filesize) {
 +      char clbuf[128];
-       snprintf(clbuf, sizeof(clbuf),
-                "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
++      msnprintf(clbuf, sizeof(clbuf),
++                "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
 +      result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0);
 +      if(result)
 +        return result;
 +    }
 +#endif
 +    Curl_pgrsSetDownloadSize(data, filesize);
 +    result = ftp_state_rest(conn);
 +  }
 +  else if(instate == FTP_RETR_SIZE) {
 +    Curl_pgrsSetDownloadSize(data, filesize);
 +    result = ftp_state_retr(conn, filesize);
 +  }
 +  else if(instate == FTP_STOR_SIZE) {
 +    data->state.resume_from = filesize;
 +    result = ftp_state_ul_setup(conn, TRUE);
 +  }
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_rest_resp(struct connectdata *conn,
 +                                    int ftpcode,
 +                                    ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  switch(instate) {
 +  case FTP_REST:
 +  default:
 +#ifdef CURL_FTP_HTTPSTYLE_HEAD
 +    if(ftpcode == 350) {
 +      char buffer[24]= { "Accept-ranges: bytes\r\n" };
 +      result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0);
 +      if(result)
 +        return result;
 +    }
 +#endif
 +    result = ftp_state_prepare_transfer(conn);
 +    break;
 +
 +  case FTP_RETR_REST:
 +    if(ftpcode != 350) {
 +      failf(conn->data, "Couldn't use REST");
 +      result = CURLE_FTP_COULDNT_USE_REST;
 +    }
 +    else {
 +      PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
 +      state(conn, FTP_RETR);
 +    }
 +    break;
 +  }
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_stor_resp(struct connectdata *conn,
 +                                    int ftpcode, ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +
 +  if(ftpcode >= 400) {
 +    failf(data, "Failed FTP upload: %0d", ftpcode);
 +    state(conn, FTP_STOP);
 +    /* oops, we never close the sockets! */
 +    return CURLE_UPLOAD_FAILED;
 +  }
 +
 +  conn->proto.ftpc.state_saved = instate;
 +
 +  /* PORT means we are now awaiting the server to connect to us. */
 +  if(data->set.ftp_use_port) {
 +    bool connected;
 +
 +    state(conn, FTP_STOP); /* no longer in STOR state */
 +
 +    result = AllowServerConnect(conn, &connected);
 +    if(result)
 +      return result;
 +
 +    if(!connected) {
 +      struct ftp_conn *ftpc = &conn->proto.ftpc;
 +      infof(data, "Data conn was not available immediately\n");
 +      ftpc->wait_data_conn = TRUE;
 +    }
 +
 +    return CURLE_OK;
 +  }
 +  return InitiateTransfer(conn);
 +}
 +
 +/* for LIST and RETR responses */
 +static CURLcode ftp_state_get_resp(struct connectdata *conn,
 +                                    int ftpcode,
 +                                    ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +
 +  if((ftpcode == 150) || (ftpcode == 125)) {
 +
 +    /*
 +      A;
 +      150 Opening BINARY mode data connection for /etc/passwd (2241
 +      bytes).  (ok, the file is being transferred)
 +
 +      B:
 +      150 Opening ASCII mode data connection for /bin/ls
 +
 +      C:
 +      150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes).
 +
 +      D:
 +      150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes)
 +
 +      E:
 +      125 Data connection already open; Transfer starting. */
 +
 +    curl_off_t size = -1; /* default unknown size */
 +
 +
 +    /*
 +     * It appears that there are FTP-servers that return size 0 for files when
 +     * SIZE is used on the file while being in BINARY mode. To work around
 +     * that (stupid) behavior, we attempt to parse the RETR response even if
 +     * the SIZE returned size zero.
 +     *
 +     * Debugging help from Salvatore Sorrentino on February 26, 2003.
 +     */
 +
 +    if((instate != FTP_LIST) &&
 +       !data->set.prefer_ascii &&
 +       (ftp->downloadsize < 1)) {
 +      /*
 +       * It seems directory listings either don't show the size or very
 +       * often uses size 0 anyway. ASCII transfers may very well turn out
 +       * that the transferred amount of data is not the same as this line
 +       * tells, why using this number in those cases only confuses us.
 +       *
 +       * Example D above makes this parsing a little tricky */
 +      char *bytes;
 +      char *buf = data->state.buffer;
 +      bytes = strstr(buf, " bytes");
 +      if(bytes) {
 +        long in = (long)(--bytes-buf);
 +        /* this is a hint there is size information in there! ;-) */
 +        while(--in) {
 +          /* scan for the left parenthesis and break there */
 +          if('(' == *bytes)
 +            break;
 +          /* skip only digits */
 +          if(!ISDIGIT(*bytes)) {
 +            bytes = NULL;
 +            break;
 +          }
 +          /* one more estep backwards */
 +          bytes--;
 +        }
 +        /* if we have nothing but digits: */
 +        if(bytes++) {
 +          /* get the number! */
 +          (void)curlx_strtoofft(bytes, NULL, 0, &size);
 +        }
 +      }
 +    }
 +    else if(ftp->downloadsize > -1)
 +      size = ftp->downloadsize;
 +
 +    if(size > data->req.maxdownload && data->req.maxdownload > 0)
 +      size = data->req.size = data->req.maxdownload;
 +    else if((instate != FTP_LIST) && (data->set.prefer_ascii))
 +      size = -1; /* kludge for servers that understate ASCII mode file size */
 +
 +    infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n",
 +          data->req.maxdownload);
 +
 +    if(instate != FTP_LIST)
 +      infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T "\n",
 +            size);
 +
 +    /* FTP download: */
 +    conn->proto.ftpc.state_saved = instate;
 +    conn->proto.ftpc.retr_size_saved = size;
 +
 +    if(data->set.ftp_use_port) {
 +      bool connected;
 +
 +      result = AllowServerConnect(conn, &connected);
 +      if(result)
 +        return result;
 +
 +      if(!connected) {
 +        struct ftp_conn *ftpc = &conn->proto.ftpc;
 +        infof(data, "Data conn was not available immediately\n");
 +        state(conn, FTP_STOP);
 +        ftpc->wait_data_conn = TRUE;
 +      }
 +    }
 +    else
 +      return InitiateTransfer(conn);
 +  }
 +  else {
 +    if((instate == FTP_LIST) && (ftpcode == 450)) {
 +      /* simply no matching files in the dir listing */
 +      ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */
 +      state(conn, FTP_STOP); /* this phase is over */
 +    }
 +    else {
 +      failf(data, "RETR response: %03d", ftpcode);
 +      return instate == FTP_RETR && ftpcode == 550?
 +        CURLE_REMOTE_FILE_NOT_FOUND:
 +        CURLE_FTP_COULDNT_RETR_FILE;
 +    }
 +  }
 +
 +  return result;
 +}
 +
 +/* after USER, PASS and ACCT */
 +static CURLcode ftp_state_loggedin(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +
 +  if(conn->ssl[FIRSTSOCKET].use) {
 +    /* PBSZ = PROTECTION BUFFER SIZE.
 +
 +    The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says:
 +
 +    Specifically, the PROT command MUST be preceded by a PBSZ
 +    command and a PBSZ command MUST be preceded by a successful
 +    security data exchange (the TLS negotiation in this case)
 +
 +    ... (and on page 8):
 +
 +    Thus the PBSZ command must still be issued, but must have a
 +    parameter of '0' to indicate that no buffering is taking place
 +    and the data connection should not be encapsulated.
 +    */
 +    PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0);
 +    state(conn, FTP_PBSZ);
 +  }
 +  else {
 +    result = ftp_state_pwd(conn);
 +  }
 +  return result;
 +}
 +
 +/* for USER and PASS responses */
 +static CURLcode ftp_state_user_resp(struct connectdata *conn,
 +                                    int ftpcode,
 +                                    ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  (void)instate; /* no use for this yet */
 +
 +  /* some need password anyway, and others just return 2xx ignored */
 +  if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
 +    /* 331 Password required for ...
 +       (the server requires to send the user's password too) */
 +    PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:"");
 +    state(conn, FTP_PASS);
 +  }
 +  else if(ftpcode/100 == 2) {
 +    /* 230 User ... logged in.
 +       (the user logged in with or without password) */
 +    result = ftp_state_loggedin(conn);
 +  }
 +  else if(ftpcode == 332) {
 +    if(data->set.str[STRING_FTP_ACCOUNT]) {
 +      PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]);
 +      state(conn, FTP_ACCT);
 +    }
 +    else {
 +      failf(data, "ACCT requested but none available");
 +      result = CURLE_LOGIN_DENIED;
 +    }
 +  }
 +  else {
 +    /* All other response codes, like:
 +
 +    530 User ... access denied
 +    (the server denies to log the specified user) */
 +
 +    if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
 +        !conn->data->state.ftp_trying_alternative) {
 +      /* Ok, USER failed.  Let's try the supplied command. */
 +      PPSENDF(&conn->proto.ftpc.pp, "%s",
 +              conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
 +      conn->data->state.ftp_trying_alternative = TRUE;
 +      state(conn, FTP_USER);
 +      result = CURLE_OK;
 +    }
 +    else {
 +      failf(data, "Access denied: %03d", ftpcode);
 +      result = CURLE_LOGIN_DENIED;
 +    }
 +  }
 +  return result;
 +}
 +
 +/* for ACCT response */
 +static CURLcode ftp_state_acct_resp(struct connectdata *conn,
 +                                    int ftpcode)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  if(ftpcode != 230) {
 +    failf(data, "ACCT rejected by server: %03d", ftpcode);
 +    result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */
 +  }
 +  else
 +    result = ftp_state_loggedin(conn);
 +
 +  return result;
 +}
 +
 +
 +static CURLcode ftp_statemach_act(struct connectdata *conn)
 +{
 +  CURLcode result;
 +  curl_socket_t sock = conn->sock[FIRSTSOCKET];
 +  struct Curl_easy *data = conn->data;
 +  int ftpcode;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +  static const char ftpauth[][4]  = { "SSL", "TLS" };
 +  size_t nread = 0;
 +
 +  if(pp->sendleft)
 +    return Curl_pp_flushsend(pp);
 +
 +  result = ftp_readresp(sock, pp, &ftpcode, &nread);
 +  if(result)
 +    return result;
 +
 +  if(ftpcode) {
 +    /* we have now received a full FTP server response */
 +    switch(ftpc->state) {
 +    case FTP_WAIT220:
 +      if(ftpcode == 230)
 +        /* 230 User logged in - already! */
 +        return ftp_state_user_resp(conn, ftpcode, ftpc->state);
 +      else if(ftpcode != 220) {
 +        failf(data, "Got a %03d ftp-server response when 220 was expected",
 +              ftpcode);
 +        return CURLE_WEIRD_SERVER_REPLY;
 +      }
 +
 +      /* We have received a 220 response fine, now we proceed. */
 +#ifdef HAVE_GSSAPI
 +      if(data->set.krb) {
 +        /* If not anonymous login, try a secure login. Note that this
 +           procedure is still BLOCKING. */
 +
 +        Curl_sec_request_prot(conn, "private");
 +        /* We set private first as default, in case the line below fails to
 +           set a valid level */
 +        Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
 +
 +        if(Curl_sec_login(conn))
 +          infof(data, "Logging in with password in cleartext!\n");
 +        else
 +          infof(data, "Authentication successful\n");
 +      }
 +#endif
 +
 +      if(data->set.use_ssl &&
 +         (!conn->ssl[FIRSTSOCKET].use ||
 +          (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
 +           !conn->proxy_ssl[FIRSTSOCKET].use))) {
 +        /* We don't have a SSL/TLS connection yet, but FTPS is
 +           requested. Try a FTPS connection now */
 +
 +        ftpc->count3 = 0;
 +        switch(data->set.ftpsslauth) {
 +        case CURLFTPAUTH_DEFAULT:
 +        case CURLFTPAUTH_SSL:
 +          ftpc->count2 = 1; /* add one to get next */
 +          ftpc->count1 = 0;
 +          break;
 +        case CURLFTPAUTH_TLS:
 +          ftpc->count2 = -1; /* subtract one to get next */
 +          ftpc->count1 = 1;
 +          break;
 +        default:
 +          failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d",
 +                (int)data->set.ftpsslauth);
 +          return CURLE_UNKNOWN_OPTION; /* we don't know what to do */
 +        }
 +        PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
 +        state(conn, FTP_AUTH);
 +      }
 +      else {
 +        result = ftp_state_user(conn);
 +        if(result)
 +          return result;
 +      }
 +
 +      break;
 +
 +    case FTP_AUTH:
 +      /* we have gotten the response to a previous AUTH command */
 +
 +      /* RFC2228 (page 5) says:
 +       *
 +       * If the server is willing to accept the named security mechanism,
 +       * and does not require any security data, it must respond with
 +       * reply code 234/334.
 +       */
 +
 +      if((ftpcode == 234) || (ftpcode == 334)) {
 +        /* Curl_ssl_connect is BLOCKING */
 +        result = Curl_ssl_connect(conn, FIRSTSOCKET);
 +        if(!result) {
 +          conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
 +          result = ftp_state_user(conn);
 +        }
 +      }
 +      else if(ftpc->count3 < 1) {
 +        ftpc->count3++;
 +        ftpc->count1 += ftpc->count2; /* get next attempt */
 +        result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
 +        /* remain in this same state */
 +      }
 +      else {
 +        if(data->set.use_ssl > CURLUSESSL_TRY)
 +          /* we failed and CURLUSESSL_CONTROL or CURLUSESSL_ALL is set */
 +          result = CURLE_USE_SSL_FAILED;
 +        else
 +          /* ignore the failure and continue */
 +          result = ftp_state_user(conn);
 +      }
 +
 +      if(result)
 +        return result;
 +      break;
 +
 +    case FTP_USER:
 +    case FTP_PASS:
 +      result = ftp_state_user_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_ACCT:
 +      result = ftp_state_acct_resp(conn, ftpcode);
 +      break;
 +
 +    case FTP_PBSZ:
 +      PPSENDF(&ftpc->pp, "PROT %c",
 +              data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
 +      state(conn, FTP_PROT);
 +
 +      break;
 +
 +    case FTP_PROT:
 +      if(ftpcode/100 == 2)
 +        /* We have enabled SSL for the data connection! */
 +        conn->bits.ftp_use_data_ssl =
 +          (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
 +      /* FTP servers typically responds with 500 if they decide to reject
 +         our 'P' request */
 +      else if(data->set.use_ssl > CURLUSESSL_CONTROL)
 +        /* we failed and bails out */
 +        return CURLE_USE_SSL_FAILED;
 +
 +      if(data->set.ftp_ccc) {
 +        /* CCC - Clear Command Channel
 +         */
 +        PPSENDF(&ftpc->pp, "%s", "CCC");
 +        state(conn, FTP_CCC);
 +      }
 +      else {
 +        result = ftp_state_pwd(conn);
 +        if(result)
 +          return result;
 +      }
 +      break;
 +
 +    case FTP_CCC:
 +      if(ftpcode < 500) {
 +        /* First shut down the SSL layer (note: this call will block) */
 +        result = Curl_ssl_shutdown(conn, FIRSTSOCKET);
 +
 +        if(result) {
 +          failf(conn->data, "Failed to clear the command channel (CCC)");
 +          return result;
 +        }
 +      }
 +
 +      /* Then continue as normal */
 +      result = ftp_state_pwd(conn);
 +      if(result)
 +        return result;
 +      break;
 +
 +    case FTP_PWD:
 +      if(ftpcode == 257) {
 +        char *ptr = &data->state.buffer[4];  /* start on the first letter */
 +        const size_t buf_size = data->set.buffer_size;
 +        char *dir;
 +        bool entry_extracted = FALSE;
 +
 +        dir = malloc(nread + 1);
 +        if(!dir)
 +          return CURLE_OUT_OF_MEMORY;
 +
 +        /* Reply format is like
 +           257<space>[rubbish]"<directory-name>"<space><commentary> and the
 +           RFC959 says
 +
 +           The directory name can contain any character; embedded
 +           double-quotes should be escaped by double-quotes (the
 +           "quote-doubling" convention).
 +        */
 +
 +        /* scan for the first double-quote for non-standard responses */
 +        while(ptr < &data->state.buffer[buf_size]
 +              && *ptr != '\n' && *ptr != '\0' && *ptr != '"')
 +          ptr++;
 +
 +        if('\"' == *ptr) {
 +          /* it started good */
 +          char *store;
 +          ptr++;
 +          for(store = dir; *ptr;) {
 +            if('\"' == *ptr) {
 +              if('\"' == ptr[1]) {
 +                /* "quote-doubling" */
 +                *store = ptr[1];
 +                ptr++;
 +              }
 +              else {
 +                /* end of path */
 +                entry_extracted = TRUE;
 +                break; /* get out of this loop */
 +              }
 +            }
 +            else
 +              *store = *ptr;
 +            store++;
 +            ptr++;
 +          }
 +          *store = '\0'; /* zero terminate */
 +        }
 +        if(entry_extracted) {
 +          /* If the path name does not look like an absolute path (i.e.: it
 +             does not start with a '/'), we probably need some server-dependent
 +             adjustments. For example, this is the case when connecting to
 +             an OS400 FTP server: this server supports two name syntaxes,
 +             the default one being incompatible with standard paths. In
 +             addition, this server switches automatically to the regular path
 +             syntax when one is encountered in a command: this results in
 +             having an entrypath in the wrong syntax when later used in CWD.
 +               The method used here is to check the server OS: we do it only
 +             if the path name looks strange to minimize overhead on other
 +             systems. */
 +
 +          if(!ftpc->server_os && dir[0] != '/') {
 +
 +            result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST");
 +            if(result) {
 +              free(dir);
 +              return result;
 +            }
 +            Curl_safefree(ftpc->entrypath);
 +            ftpc->entrypath = dir; /* remember this */
 +            infof(data, "Entry path is '%s'\n", ftpc->entrypath);
 +            /* also save it where getinfo can access it: */
 +            data->state.most_recent_ftp_entrypath = ftpc->entrypath;
 +            state(conn, FTP_SYST);
 +            break;
 +          }
 +
 +          Curl_safefree(ftpc->entrypath);
 +          ftpc->entrypath = dir; /* remember this */
 +          infof(data, "Entry path is '%s'\n", ftpc->entrypath);
 +          /* also save it where getinfo can access it: */
 +          data->state.most_recent_ftp_entrypath = ftpc->entrypath;
 +        }
 +        else {
 +          /* couldn't get the path */
 +          free(dir);
 +          infof(data, "Failed to figure out path\n");
 +        }
 +      }
 +      state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
 +      DEBUGF(infof(data, "protocol connect phase DONE\n"));
 +      break;
 +
 +    case FTP_SYST:
 +      if(ftpcode == 215) {
 +        char *ptr = &data->state.buffer[4];  /* start on the first letter */
 +        char *os;
 +        char *store;
 +
 +        os = malloc(nread + 1);
 +        if(!os)
 +          return CURLE_OUT_OF_MEMORY;
 +
 +        /* Reply format is like
 +           215<space><OS-name><space><commentary>
 +        */
 +        while(*ptr == ' ')
 +          ptr++;
 +        for(store = os; *ptr && *ptr != ' ';)
 +          *store++ = *ptr++;
 +        *store = '\0'; /* zero terminate */
 +
 +        /* Check for special servers here. */
 +
 +        if(strcasecompare(os, "OS/400")) {
 +          /* Force OS400 name format 1. */
 +          result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1");
 +          if(result) {
 +            free(os);
 +            return result;
 +          }
 +          /* remember target server OS */
 +          Curl_safefree(ftpc->server_os);
 +          ftpc->server_os = os;
 +          state(conn, FTP_NAMEFMT);
 +          break;
 +        }
 +        /* Nothing special for the target server. */
 +        /* remember target server OS */
 +        Curl_safefree(ftpc->server_os);
 +        ftpc->server_os = os;
 +      }
 +      else {
 +        /* Cannot identify server OS. Continue anyway and cross fingers. */
 +      }
 +
 +      state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
 +      DEBUGF(infof(data, "protocol connect phase DONE\n"));
 +      break;
 +
 +    case FTP_NAMEFMT:
 +      if(ftpcode == 250) {
 +        /* Name format change successful: reload initial path. */
 +        ftp_state_pwd(conn);
 +        break;
 +      }
 +
 +      state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
 +      DEBUGF(infof(data, "protocol connect phase DONE\n"));
 +      break;
 +
 +    case FTP_QUOTE:
 +    case FTP_POSTQUOTE:
 +    case FTP_RETR_PREQUOTE:
 +    case FTP_STOR_PREQUOTE:
 +      if((ftpcode >= 400) && !ftpc->count2) {
 +        /* failure response code, and not allowed to fail */
 +        failf(conn->data, "QUOT command failed with %03d", ftpcode);
 +        return CURLE_QUOTE_ERROR;
 +      }
 +      result = ftp_state_quote(conn, FALSE, ftpc->state);
 +      if(result)
 +        return result;
 +
 +      break;
 +
 +    case FTP_CWD:
 +      if(ftpcode/100 != 2) {
 +        /* failure to CWD there */
 +        if(conn->data->set.ftp_create_missing_dirs &&
 +           ftpc->cwdcount && !ftpc->count2) {
 +          /* try making it */
 +          ftpc->count2++; /* counter to prevent CWD-MKD loops */
 +          PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->cwdcount - 1]);
 +          state(conn, FTP_MKD);
 +        }
 +        else {
 +          /* return failure */
 +          failf(data, "Server denied you to change to the given directory");
 +          ftpc->cwdfail = TRUE; /* don't remember this path as we failed
 +                                   to enter it */
 +          return CURLE_REMOTE_ACCESS_DENIED;
 +        }
 +      }
 +      else {
 +        /* success */
 +        ftpc->count2 = 0;
 +        if(++ftpc->cwdcount <= ftpc->dirdepth) {
 +          /* send next CWD */
 +          PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]);
 +        }
 +        else {
 +          result = ftp_state_mdtm(conn);
 +          if(result)
 +            return result;
 +        }
 +      }
 +      break;
 +
 +    case FTP_MKD:
 +      if((ftpcode/100 != 2) && !ftpc->count3--) {
 +        /* failure to MKD the dir */
 +        failf(data, "Failed to MKD dir: %03d", ftpcode);
 +        return CURLE_REMOTE_ACCESS_DENIED;
 +      }
 +      state(conn, FTP_CWD);
 +      /* send CWD */
 +      PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]);
 +      break;
 +
 +    case FTP_MDTM:
 +      result = ftp_state_mdtm_resp(conn, ftpcode);
 +      break;
 +
 +    case FTP_TYPE:
 +    case FTP_LIST_TYPE:
 +    case FTP_RETR_TYPE:
 +    case FTP_STOR_TYPE:
 +      result = ftp_state_type_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_SIZE:
 +    case FTP_RETR_SIZE:
 +    case FTP_STOR_SIZE:
 +      result = ftp_state_size_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_REST:
 +    case FTP_RETR_REST:
 +      result = ftp_state_rest_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_PRET:
 +      if(ftpcode != 200) {
 +        /* there only is this one standard OK return code. */
 +        failf(data, "PRET command not accepted: %03d", ftpcode);
 +        return CURLE_FTP_PRET_FAILED;
 +      }
 +      result = ftp_state_use_pasv(conn);
 +      break;
 +
 +    case FTP_PASV:
 +      result = ftp_state_pasv_resp(conn, ftpcode);
 +      break;
 +
 +    case FTP_PORT:
 +      result = ftp_state_port_resp(conn, ftpcode);
 +      break;
 +
 +    case FTP_LIST:
 +    case FTP_RETR:
 +      result = ftp_state_get_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_STOR:
 +      result = ftp_state_stor_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_QUIT:
 +      /* fallthrough, just stop! */
 +    default:
 +      /* internal error */
 +      state(conn, FTP_STOP);
 +      break;
 +    }
 +  } /* if(ftpcode) */
 +
 +  return result;
 +}
 +
 +
 +/* called repeatedly until done from multi.c */
 +static CURLcode ftp_multi_statemach(struct connectdata *conn,
 +                                    bool *done)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
-   CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE);
++  CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE, FALSE);
 +
 +  /* Check for the state outside of the Curl_socket_check() return code checks
 +     since at times we are in fact already in this state when this function
 +     gets called. */
 +  *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE;
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_block_statemach(struct connectdata *conn)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +  CURLcode result = CURLE_OK;
 +
 +  while(ftpc->state != FTP_STOP) {
-     result = Curl_pp_statemach(pp, TRUE);
++    result = Curl_pp_statemach(pp, TRUE, TRUE /* disconnecting */);
 +    if(result)
 +      break;
 +  }
 +
 +  return result;
 +}
 +
 +/*
 + * ftp_connect() should do everything that is to be considered a part of
 + * the connection phase.
 + *
 + * The variable 'done' points to will be TRUE if the protocol-layer connect
 + * phase is done when this function returns, or FALSE if not.
 + *
 + */
 +static CURLcode ftp_connect(struct connectdata *conn,
 +                                 bool *done) /* see description above */
 +{
 +  CURLcode result;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +
 +  *done = FALSE; /* default to not done yet */
 +
 +  /* We always support persistent connections on ftp */
 +  connkeep(conn, "FTP default");
 +
 +  pp->response_time = RESP_TIMEOUT; /* set default response time-out */
 +  pp->statemach_act = ftp_statemach_act;
 +  pp->endofresp = ftp_endofresp;
 +  pp->conn = conn;
 +
 +  if(conn->handler->flags & PROTOPT_SSL) {
 +    /* BLOCKING */
 +    result = Curl_ssl_connect(conn, FIRSTSOCKET);
 +    if(result)
 +      return result;
 +  }
 +
 +  Curl_pp_init(pp); /* init the generic pingpong data */
 +
 +  /* When we connect, we start in the state where we await the 220
 +     response */
 +  state(conn, FTP_WAIT220);
 +
 +  result = ftp_multi_statemach(conn, done);
 +
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_done()
 + *
 + * The DONE function. This does what needs to be done after a single DO has
 + * performed.
 + *
 + * Input argument is already checked for validity.
 + */
 +static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
 +                         bool premature)
 +{
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +  ssize_t nread;
 +  int ftpcode;
 +  CURLcode result = CURLE_OK;
 +  char *path = NULL;
 +
 +  if(!ftp)
 +    return CURLE_OK;
 +
 +  switch(status) {
 +  case CURLE_BAD_DOWNLOAD_RESUME:
 +  case CURLE_FTP_WEIRD_PASV_REPLY:
 +  case CURLE_FTP_PORT_FAILED:
 +  case CURLE_FTP_ACCEPT_FAILED:
 +  case CURLE_FTP_ACCEPT_TIMEOUT:
 +  case CURLE_FTP_COULDNT_SET_TYPE:
 +  case CURLE_FTP_COULDNT_RETR_FILE:
 +  case CURLE_PARTIAL_FILE:
 +  case CURLE_UPLOAD_FAILED:
 +  case CURLE_REMOTE_ACCESS_DENIED:
 +  case CURLE_FILESIZE_EXCEEDED:
 +  case CURLE_REMOTE_FILE_NOT_FOUND:
 +  case CURLE_WRITE_ERROR:
 +    /* the connection stays alive fine even though this happened */
 +    /* fall-through */
 +  case CURLE_OK: /* doesn't affect the control connection's status */
 +    if(!premature)
 +      break;
 +
 +    /* until we cope better with prematurely ended requests, let them
 +     * fallback as if in complete failure */
 +    /* FALLTHROUGH */
 +  default:       /* by default, an error means the control connection is
 +                    wedged and should not be used anymore */
 +    ftpc->ctl_valid = FALSE;
 +    ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the
 +                             current path, as this connection is going */
 +    connclose(conn, "FTP ended with bad error code");
 +    result = status;      /* use the already set error code */
 +    break;
 +  }
 +
 +  /* now store a copy of the directory we are in */
 +  free(ftpc->prevpath);
 +
 +  if(data->state.wildcardmatch) {
 +    if(data->set.chunk_end && ftpc->file) {
 +      Curl_set_in_callback(data, true);
 +      data->set.chunk_end(data->wildcard.customptr);
 +      Curl_set_in_callback(data, false);
 +    }
 +    ftpc->known_filesize = -1;
 +  }
 +
 +  if(!result)
 +    /* get the "raw" path */
 +    result = Curl_urldecode(data, ftp->path, 0, &path, NULL, TRUE);
 +  if(result) {
 +    /* We can limp along anyway (and should try to since we may already be in
 +     * the error path) */
 +    ftpc->ctl_valid = FALSE; /* mark control connection as bad */
 +    connclose(conn, "FTP: out of memory!"); /* mark for connection closure */
 +    ftpc->prevpath = NULL; /* no path remembering */
 +  }
 +  else {
 +    size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */
 +    size_t dlen = strlen(path)-flen;
 +    if(!ftpc->cwdfail) {
 +      ftpc->prevmethod = data->set.ftp_filemethod;
 +      if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) {
 +        ftpc->prevpath = path;
 +        if(flen)
 +          /* if 'path' is not the whole string */
 +          ftpc->prevpath[dlen] = 0; /* terminate */
 +      }
 +      else {
 +        free(path);
 +        /* we never changed dir */
 +        ftpc->prevpath = strdup("");
 +        if(!ftpc->prevpath)
 +          return CURLE_OUT_OF_MEMORY;
 +      }
 +      if(ftpc->prevpath)
 +        infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath);
 +    }
 +    else {
 +      ftpc->prevpath = NULL; /* no path */
 +      free(path);
 +    }
 +  }
 +  /* free the dir tree and file parts */
 +  freedirs(ftpc);
 +
 +  /* shut down the socket to inform the server we're done */
 +
 +#ifdef _WIN32_WCE
 +  shutdown(conn->sock[SECONDARYSOCKET], 2);  /* SD_BOTH */
 +#endif
 +
 +  if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
 +    if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
 +      /* partial download completed */
 +      result = Curl_pp_sendf(pp, "%s", "ABOR");
 +      if(result) {
 +        failf(data, "Failure sending ABOR command: %s",
 +              curl_easy_strerror(result));
 +        ftpc->ctl_valid = FALSE; /* mark control connection as bad */
 +        connclose(conn, "ABOR command failed"); /* connection closure */
 +      }
 +    }
 +
 +    if(conn->ssl[SECONDARYSOCKET].use) {
 +      /* The secondary socket is using SSL so we must close down that part
 +         first before we close the socket for real */
 +      Curl_ssl_close(conn, SECONDARYSOCKET);
 +
 +      /* Note that we keep "use" set to TRUE since that (next) connection is
 +         still requested to use SSL */
 +    }
 +    close_secondarysocket(conn);
 +  }
 +
 +  if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid &&
 +     pp->pending_resp && !premature) {
 +    /*
 +     * Let's see what the server says about the transfer we just performed,
 +     * but lower the timeout as sometimes this connection has died while the
 +     * data has been transferred. This happens when doing through NATs etc that
 +     * abandon old silent connections.
 +     */
 +    long old_time = pp->response_time;
 +
 +    pp->response_time = 60*1000; /* give it only a minute for now */
 +    pp->response = Curl_now(); /* timeout relative now */
 +
 +    result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
 +
 +    pp->response_time = old_time; /* set this back to previous value */
 +
 +    if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) {
 +      failf(data, "control connection looks dead");
 +      ftpc->ctl_valid = FALSE; /* mark control connection as bad */
 +      connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */
 +    }
 +
 +    if(result)
 +      return result;
 +
 +    if(ftpc->dont_check && data->req.maxdownload > 0) {
 +      /* we have just sent ABOR and there is no reliable way to check if it was
 +       * successful or not; we have to close the connection now */
 +      infof(data, "partial download completed, closing connection\n");
 +      connclose(conn, "Partial download with no ability to check");
 +      return result;
 +    }
 +
 +    if(!ftpc->dont_check) {
 +      /* 226 Transfer complete, 250 Requested file action okay, completed. */
 +      if((ftpcode != 226) && (ftpcode != 250)) {
 +        failf(data, "server did not report OK, got %d", ftpcode);
 +        result = CURLE_PARTIAL_FILE;
 +      }
 +    }
 +  }
 +
 +  if(result || premature)
 +    /* the response code from the transfer showed an error already so no
 +       use checking further */
 +    ;
 +  else if(data->set.upload) {
 +    if((-1 != data->state.infilesize) &&
-        (data->state.infilesize != *ftp->bytecountp) &&
++       (data->state.infilesize != data->req.writebytecount) &&
 +       !data->set.crlf &&
 +       (ftp->transfer == FTPTRANSFER_BODY)) {
 +      failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
 +            " out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
-             *ftp->bytecountp, data->state.infilesize);
++            data->req.bytecount, data->state.infilesize);
 +      result = CURLE_PARTIAL_FILE;
 +    }
 +  }
 +  else {
 +    if((-1 != data->req.size) &&
-        (data->req.size != *ftp->bytecountp) &&
++       (data->req.size != data->req.bytecount) &&
 +#ifdef CURL_DO_LINEEND_CONV
 +       /* Most FTP servers don't adjust their file SIZE response for CRLFs, so
 +        * we'll check to see if the discrepancy can be explained by the number
 +        * of CRLFs we've changed to LFs.
 +        */
 +       ((data->req.size + data->state.crlf_conversions) !=
-         *ftp->bytecountp) &&
++        data->req.bytecount) &&
 +#endif /* CURL_DO_LINEEND_CONV */
-        (data->req.maxdownload != *ftp->bytecountp)) {
++       (data->req.maxdownload != data->req.bytecount)) {
 +      failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
-             " bytes", *ftp->bytecountp);
++            " bytes", data->req.bytecount);
 +      result = CURLE_PARTIAL_FILE;
 +    }
 +    else if(!ftpc->dont_check &&
-             !*ftp->bytecountp &&
++            !data->req.bytecount &&
 +            (data->req.size>0)) {
 +      failf(data, "No data was received!");
 +      result = CURLE_FTP_COULDNT_RETR_FILE;
 +    }
 +  }
 +
 +  /* clear these for next connection */
 +  ftp->transfer = FTPTRANSFER_BODY;
 +  ftpc->dont_check = FALSE;
 +
 +  /* Send any post-transfer QUOTE strings? */
 +  if(!status && !result && !premature && data->set.postquote)
 +    result = ftp_sendquote(conn, data->set.postquote);
 +  Curl_safefree(ftp->pathalloc);
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_sendquote()
 + *
 + * Where a 'quote' means a list of custom commands to send to the server.
 + * The quote list is passed as an argument.
 + *
 + * BLOCKING
 + */
 +
 +static
 +CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
 +{
 +  struct curl_slist *item;
 +  ssize_t nread;
 +  int ftpcode;
 +  CURLcode result;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +
 +  item = quote;
 +  while(item) {
 +    if(item->data) {
 +      char *cmd = item->data;
 +      bool acceptfail = FALSE;
 +
 +      /* if a command starts with an asterisk, which a legal FTP command never
 +         can, the command will be allowed to fail without it causing any
 +         aborts or cancels etc. It will cause libcurl to act as if the command
 +         is successful, whatever the server reponds. */
 +
 +      if(cmd[0] == '*') {
 +        cmd++;
 +        acceptfail = TRUE;
 +      }
 +
 +      PPSENDF(&conn->proto.ftpc.pp, "%s", cmd);
 +
 +      pp->response = Curl_now(); /* timeout relative now */
 +
 +      result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
 +      if(result)
 +        return result;
 +
 +      if(!acceptfail && (ftpcode >= 400)) {
 +        failf(conn->data, "QUOT string not accepted: %s", cmd);
 +        return CURLE_QUOTE_ERROR;
 +      }
 +    }
 +
 +    item = item->next;
 +  }
 +
 +  return CURLE_OK;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_need_type()
 + *
 + * Returns TRUE if we in the current situation should send TYPE
 + */
 +static int ftp_need_type(struct connectdata *conn,
 +                         bool ascii_wanted)
 +{
 +  return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I');
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_nb_type()
 + *
 + * Set TYPE. We only deal with ASCII or BINARY so this function
 + * sets one of them.
 + * If the transfer type is not sent, simulate on OK response in newstate
 + */
 +static CURLcode ftp_nb_type(struct connectdata *conn,
 +                            bool ascii, ftpstate newstate)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  CURLcode result;
 +  char want = (char)(ascii?'A':'I');
 +
 +  if(ftpc->transfertype == want) {
 +    state(conn, newstate);
 +    return ftp_state_type_resp(conn, 200, newstate);
 +  }
 +
 +  PPSENDF(&ftpc->pp, "TYPE %c", want);
 +  state(conn, newstate);
 +
 +  /* keep track of our current transfer type */
 +  ftpc->transfertype = want;
 +  return CURLE_OK;
 +}
 +
 +/***************************************************************************
 + *
 + * ftp_pasv_verbose()
 + *
 + * This function only outputs some informationals about this second connection
 + * when we've issued a PASV command before and thus we have connected to a
 + * possibly new IP address.
 + *
 + */
 +#ifndef CURL_DISABLE_VERBOSE_STRINGS
 +static void
 +ftp_pasv_verbose(struct connectdata *conn,
 +                 Curl_addrinfo *ai,
 +                 char *newhost, /* ascii version */
 +                 int port)
 +{
 +  char buf[256];
 +  Curl_printable_address(ai, buf, sizeof(buf));
 +  infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port);
 +}
 +#endif
 +
 +/*
 + * ftp_do_more()
 + *
 + * This function shall be called when the second FTP (data) connection is
 + * connected.
 + *
 + * 'complete' can return 0 for incomplete, 1 for done and -1 for go back
 + * (which basically is only for when PASV is being sent to retry a failed
 + * EPSV).
 + */
 +
 +static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
 +{
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  CURLcode result = CURLE_OK;
 +  bool connected = FALSE;
 +  bool complete = FALSE;
 +
 +  /* the ftp struct is inited in ftp_connect() */
 +  struct FTP *ftp = data->req.protop;
 +
 +  /* if the second connection isn't done yet, wait for it */
 +  if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
 +    if(Curl_connect_ongoing(conn)) {
 +      /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
-          aren't used so we blank their arguments. TODO: make this nicer */
++         aren't used so we blank their arguments. */
 +      result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
 +
 +      return result;
 +    }
 +
 +    result = Curl_is_connected(conn, SECONDARYSOCKET, &connected);
 +
 +    /* Ready to do more? */
 +    if(connected) {
 +      DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
 +    }
 +    else {
 +      if(result && (ftpc->count1 == 0)) {
 +        *completep = -1; /* go back to DOING please */
 +        /* this is a EPSV connect failing, try PASV instead */
 +        return ftp_epsv_disable(conn);
 +      }
 +      return result;
 +    }
 +  }
 +
 +  result = Curl_proxy_connect(conn, SECONDARYSOCKET);
 +  if(result)
 +    return result;
 +
 +  if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
 +    return result;
 +
 +  if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
 +     Curl_connect_ongoing(conn))
 +    return result;
 +
 +
 +  if(ftpc->state) {
 +    /* already in a state so skip the initial commands.
 +       They are only done to kickstart the do_more state */
 +    result = ftp_multi_statemach(conn, &complete);
 +
 +    *completep = (int)complete;
 +
 +    /* if we got an error or if we don't wait for a data connection return
 +       immediately */
 +    if(result || (ftpc->wait_data_conn != TRUE))
 +      return result;
 +
 +    if(ftpc->wait_data_conn)
 +      /* if we reach the end of the FTP state machine here, *complete will be
 +         TRUE but so is ftpc->wait_data_conn, which says we need to wait for
 +         the data connection and therefore we're not actually complete */
 +      *completep = 0;
 +  }
 +
 +  if(ftp->transfer <= FTPTRANSFER_INFO) {
 +    /* a transfer is about to take place, or if not a file name was given
 +       so we'll do a SIZE on it later and then we need the right TYPE first */
 +
 +    if(ftpc->wait_data_conn == TRUE) {
 +      bool serv_conned;
 +
 +      result = ReceivedServerConnect(conn, &serv_conned);
 +      if(result)
 +        return result; /* Failed to accept data connection */
 +
 +      if(serv_conned) {
 +        /* It looks data connection is established */
 +        result = AcceptServerConnect(conn);
 +        ftpc->wait_data_conn = FALSE;
 +        if(!result)
 +          result = InitiateTransfer(conn);
 +
 +        if(result)
 +          return result;
 +
 +        *completep = 1; /* this state is now complete when the server has
 +                           connected back to us */
 +      }
 +    }
 +    else if(data->set.upload) {
 +      result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE);
 +      if(result)
 +        return result;
 +
 +      result = ftp_multi_statemach(conn, &complete);
 +      if(ftpc->wait_data_conn)
 +        /* if we reach the end of the FTP state machine here, *complete will be
 +           TRUE but so is ftpc->wait_data_conn, which says we need to wait for
 +           the data connection and therefore we're not actually complete */
 +        *completep = 0;
 +      else
 +        *completep = (int)complete;
 +    }
 +    else {
 +      /* download */
 +      ftp->downloadsize = -1; /* unknown as of yet */
 +
 +      result = Curl_range(conn);
 +
 +      if(result == CURLE_OK && data->req.maxdownload >= 0) {
 +        /* Don't check for successful transfer */
 +        ftpc->dont_check = TRUE;
 +      }
 +
 +      if(result)
 +        ;
 +      else if(data->set.ftp_list_only || !ftpc->file) {
 +        /* The specified path ends with a slash, and therefore we think this
 +           is a directory that is requested, use LIST. But before that we
 +           need to set ASCII transfer mode. */
 +
 +        /* But only if a body transfer was requested. */
 +        if(ftp->transfer == FTPTRANSFER_BODY) {
 +          result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE);
 +          if(result)
 +            return result;
 +        }
 +        /* otherwise just fall through */
 +      }
 +      else {
 +        result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE);
 +        if(result)
 +          return result;
 +      }
 +
 +      result = ftp_multi_statemach(conn, &complete);
 +      *completep = (int)complete;
 +    }
 +    return result;
 +  }
 +
 +  if(!result && (ftp->transfer != FTPTRANSFER_BODY))
 +    /* no data to transfer. FIX: it feels like a kludge to have this here
 +       too! */
-     Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
++    Curl_setup_transfer(data, -1, -1, FALSE, -1);
 +
 +  if(!ftpc->wait_data_conn) {
 +    /* no waiting for the data connection so this is now complete */
 +    *completep = 1;
 +    DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result));
 +  }
 +
 +  return result;
 +}
 +
 +
 +
 +/***********************************************************************
 + *
 + * ftp_perform()
 + *
 + * This is the actual DO function for FTP. Get a file/directory according to
 + * the options previously setup.
 + */
 +
 +static
 +CURLcode ftp_perform(struct connectdata *conn,
 +                     bool *connected,  /* connect status after PASV / PORT */
 +                     bool *dophase_done)
 +{
 +  /* this is FTP and no proxy */
 +  CURLcode result = CURLE_OK;
 +
 +  DEBUGF(infof(conn->data, "DO phase starts\n"));
 +
 +  if(conn->data->set.opt_no_body) {
 +    /* requested no body means no transfer... */
 +    struct FTP *ftp = conn->data->req.protop;
 +    ftp->transfer = FTPTRANSFER_INFO;
 +  }
 +
 +  *dophase_done = FALSE; /* not done yet */
 +
 +  /* start the first command in the DO phase */
 +  result = ftp_state_quote(conn, TRUE, FTP_QUOTE);
 +  if(result)
 +    return result;
 +
 +  /* run the state-machine */
 +  result = ftp_multi_statemach(conn, dophase_done);
 +
 +  *connected = conn->bits.tcpconnect[SECONDARYSOCKET];
 +
 +  infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected);
 +
 +  if(*dophase_done) {
 +    DEBUGF(infof(conn->data, "DO phase is complete1\n"));
 +  }
 +
 +  return result;
 +}
 +
 +static void wc_data_dtor(void *ptr)
 +{
 +  struct ftp_wc *ftpwc = ptr;
 +  if(ftpwc && ftpwc->parser)
 +    Curl_ftp_parselist_data_free(&ftpwc->parser);
 +  free(ftpwc);
 +}
 +
 +static CURLcode init_wc_data(struct connectdata *conn)
 +{
 +  char *last_slash;
 +  struct FTP *ftp = conn->data->req.protop;
 +  char *path = ftp->path;
 +  struct WildcardData *wildcard = &(conn->data->wildcard);
 +  CURLcode result = CURLE_OK;
 +  struct ftp_wc *ftpwc = NULL;
 +
 +  last_slash = strrchr(ftp->path, '/');
 +  if(last_slash) {
 +    last_slash++;
 +    if(last_slash[0] == '\0') {
 +      wildcard->state = CURLWC_CLEAN;
 +      result = ftp_parse_url_path(conn);
 +      return result;
 +    }
 +    wildcard->pattern = strdup(last_slash);
 +    if(!wildcard->pattern)
 +      return CURLE_OUT_OF_MEMORY;
 +    last_slash[0] = '\0'; /* cut file from path */
 +  }
 +  else { /* there is only 'wildcard pattern' or nothing */
 +    if(path[0]) {
 +      wildcard->pattern = strdup(path);
 +      if(!wildcard->pattern)
 +        return CURLE_OUT_OF_MEMORY;
 +      path[0] = '\0';
 +    }
 +    else { /* only list */
 +      wildcard->state = CURLWC_CLEAN;
 +      result = ftp_parse_url_path(conn);
 +      return result;
 +    }
 +  }
 +
 +  /* program continues only if URL is not ending with slash, allocate needed
 +     resources for wildcard transfer */
 +
 +  /* allocate ftp protocol specific wildcard data */
 +  ftpwc = calloc(1, sizeof(struct ftp_wc));
 +  if(!ftpwc) {
 +    result = CURLE_OUT_OF_MEMORY;
 +    goto fail;
 +  }
 +
 +  /* INITIALIZE parselist structure */
 +  ftpwc->parser = Curl_ftp_parselist_data_alloc();
 +  if(!ftpwc->parser) {
 +    result = CURLE_OUT_OF_MEMORY;
 +    goto fail;
 +  }
 +
 +  wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */
 +  wildcard->dtor = wc_data_dtor;
 +
 +  /* wildcard does not support NOCWD option (assert it?) */
 +  if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD)
 +    conn->data->set.ftp_filemethod = FTPFILE_MULTICWD;
 +
 +  /* try to parse ftp url */
 +  result = ftp_parse_url_path(conn);
 +  if(result) {
 +    goto fail;
 +  }
 +
 +  wildcard->path = strdup(ftp->path);
 +  if(!wildcard->path) {
 +    result = CURLE_OUT_OF_MEMORY;
 +    goto fail;
 +  }
 +
 +  /* backup old write_function */
 +  ftpwc->backup.write_function = conn->data->set.fwrite_func;
 +  /* parsing write function */
 +  conn->data->set.fwrite_func = Curl_ftp_parselist;
 +  /* backup old file descriptor */
 +  ftpwc->backup.file_descriptor = conn->data->set.out;
 +  /* let the writefunc callback know what curl pointer is working with */
 +  conn->data->set.out = conn;
 +
 +  infof(conn->data, "Wildcard - Parsing started\n");
 +  return CURLE_OK;
 +
 +  fail:
 +  if(ftpwc) {
 +    Curl_ftp_parselist_data_free(&ftpwc->parser);
 +    free(ftpwc);
 +  }
 +  Curl_safefree(wildcard->pattern);
 +  wildcard->dtor = ZERO_NULL;
 +  wildcard->protdata = NULL;
 +  return result;
 +}
 +
 +/* This is called recursively */
 +static CURLcode wc_statemach(struct connectdata *conn)
 +{
 +  struct WildcardData * const wildcard = &(conn->data->wildcard);
 +  CURLcode result = CURLE_OK;
 +
 +  switch(wildcard->state) {
 +  case CURLWC_INIT:
 +    result = init_wc_data(conn);
 +    if(wildcard->state == CURLWC_CLEAN)
 +      /* only listing! */
 +      break;
 +    wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
 +    break;
 +
 +  case CURLWC_MATCHING: {
 +    /* In this state is LIST response successfully parsed, so lets restore
 +       previous WRITEFUNCTION callback and WRITEDATA pointer */
 +    struct ftp_wc *ftpwc = wildcard->protdata;
 +    conn->data->set.fwrite_func = ftpwc->backup.write_function;
 +    conn->data->set.out = ftpwc->backup.file_descriptor;
 +    ftpwc->backup.write_function = ZERO_NULL;
 +    ftpwc->backup.file_descriptor = NULL;
 +    wildcard->state = CURLWC_DOWNLOADING;
 +
 +    if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
 +      /* error found in LIST parsing */
 +      wildcard->state = CURLWC_CLEAN;
 +      return wc_statemach(conn);
 +    }
 +    if(wildcard->filelist.size == 0) {
 +      /* no corresponding file */
 +      wildcard->state = CURLWC_CLEAN;
 +      return CURLE_REMOTE_FILE_NOT_FOUND;
 +    }
 +    return wc_statemach(conn);
 +  }
 +
 +  case CURLWC_DOWNLOADING: {
 +    /* filelist has at least one file, lets get first one */
 +    struct ftp_conn *ftpc = &conn->proto.ftpc;
 +    struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
 +    struct FTP *ftp = conn->data->req.protop;
 +
 +    char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
 +    if(!tmp_path)
 +      return CURLE_OUT_OF_MEMORY;
 +
 +    /* switch default ftp->path and tmp_path */
 +    free(ftp->pathalloc);
 +    ftp->pathalloc = ftp->path = tmp_path;
 +
 +    infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
 +    if(conn->data->set.chunk_bgn) {
 +      long userresponse;
 +      Curl_set_in_callback(conn->data, true);
 +      userresponse = conn->data->set.chunk_bgn(
 +        finfo, wildcard->customptr, (int)wildcard->filelist.size);
 +      Curl_set_in_callback(conn->data, false);
 +      switch(userresponse) {
 +      case CURL_CHUNK_BGN_FUNC_SKIP:
 +        infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
 +              finfo->filename);
 +        wildcard->state = CURLWC_SKIP;
 +        return wc_statemach(conn);
 +      case CURL_CHUNK_BGN_FUNC_FAIL:
 +        return CURLE_CHUNK_FAILED;
 +      }
 +    }
 +
 +    if(finfo->filetype != CURLFILETYPE_FILE) {
 +      wildcard->state = CURLWC_SKIP;
 +      return wc_statemach(conn);
 +    }
 +
 +    if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
 +      ftpc->known_filesize = finfo->size;
 +
 +    result = ftp_parse_url_path(conn);
 +    if(result)
 +      return result;
 +
 +    /* we don't need the Curl_fileinfo of first file anymore */
 +    Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
 +
 +    if(wildcard->filelist.size == 0) { /* remains only one file to down. */
 +      wildcard->state = CURLWC_CLEAN;
 +      /* after that will be ftp_do called once again and no transfer
 +         will be done because of CURLWC_CLEAN state */
 +      return CURLE_OK;
 +    }
 +  } break;
 +
 +  case CURLWC_SKIP: {
 +    if(conn->data->set.chunk_end) {
 +      Curl_set_in_callback(conn->data, true);
 +      conn->data->set.chunk_end(conn->data->wildcard.customptr);
 +      Curl_set_in_callback(conn->data, false);
 +    }
 +    Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
 +    wildcard->state = (wildcard->filelist.size == 0) ?
 +                      CURLWC_CLEAN : CURLWC_DOWNLOADING;
 +    return wc_statemach(conn);
 +  }
 +
 +  case CURLWC_CLEAN: {
 +    struct ftp_wc *ftpwc = wildcard->protdata;
 +    result = CURLE_OK;
 +    if(ftpwc)
 +      result = Curl_ftp_parselist_geterror(ftpwc->parser);
 +
 +    wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
 +  } break;
 +
 +  case CURLWC_DONE:
 +  case CURLWC_ERROR:
 +  case CURLWC_CLEAR:
 +    if(wildcard->dtor)
 +      wildcard->dtor(wildcard->protdata);
 +    break;
 +  }
 +
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_do()
 + *
 + * This function is registered as 'curl_do' function. It decodes the path
 + * parts etc as a wrapper to the actual DO function (ftp_perform).
 + *
 + * The input argument is already checked for validity.
 + */
 +static CURLcode ftp_do(struct connectdata *conn, bool *done)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  *done = FALSE; /* default to false */
 +  ftpc->wait_data_conn = FALSE; /* default to no such wait */
 +
 +  if(conn->data->state.wildcardmatch) {
 +    result = wc_statemach(conn);
 +    if(conn->data->wildcard.state == CURLWC_SKIP ||
 +      conn->data->wildcard.state == CURLWC_DONE) {
 +      /* do not call ftp_regular_transfer */
 +      return CURLE_OK;
 +    }
 +    if(result) /* error, loop or skipping the file */
 +      return result;
 +  }
 +  else { /* no wildcard FSM needed */
 +    result = ftp_parse_url_path(conn);
 +    if(result)
 +      return result;
 +  }
 +
 +  result = ftp_regular_transfer(conn, done);
 +
 +  return result;
 +}
 +
 +
 +CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
 +{
 +  ssize_t bytes_written;
 +#define SBUF_SIZE 1024
 +  char s[SBUF_SIZE];
 +  size_t write_len;
 +  char *sptr = s;
 +  CURLcode result = CURLE_OK;
 +#ifdef HAVE_GSSAPI
 +  enum protection_level data_sec = conn->data_prot;
 +#endif
 +
 +  if(!cmd)
 +    return CURLE_BAD_FUNCTION_ARGUMENT;
 +
 +  write_len = strlen(cmd);
 +  if(!write_len || write_len > (sizeof(s) -3))
 +    return CURLE_BAD_FUNCTION_ARGUMENT;
 +
 +  memcpy(&s, cmd, write_len);
 +  strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
 +  write_len += 2;
 +  bytes_written = 0;
 +
 +  result = Curl_convert_to_network(conn->data, s, write_len);
 +  /* Curl_convert_to_network calls failf if unsuccessful */
 +  if(result)
 +    return result;
 +
 +  for(;;) {
 +#ifdef HAVE_GSSAPI
 +    conn->data_prot = PROT_CMD;
 +#endif
 +    result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
 +                        &bytes_written);
 +#ifdef HAVE_GSSAPI
 +    DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
 +    conn->data_prot = data_sec;
 +#endif
 +
 +    if(result)
 +      break;
 +
 +    if(conn->data->set.verbose)
 +      Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);
 +
 +    if(bytes_written != (ssize_t)write_len) {
 +      write_len -= bytes_written;
 +      sptr += bytes_written;
 +    }
 +    else
 +      break;
 +  }
 +
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_quit()
 + *
 + * This should be called before calling sclose() on an ftp control connection
 + * (not data connections). We should then wait for the response from the
 + * server before returning. The calling code should then try to close the
 + * connection.
 + *
 + */
 +static CURLcode ftp_quit(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +
 +  if(conn->proto.ftpc.ctl_valid) {
 +    result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT");
 +    if(result) {
 +      failf(conn->data, "Failure sending QUIT command: %s",
 +            curl_easy_strerror(result));
 +      conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */
 +      connclose(conn, "QUIT command failed"); /* mark for connection closure */
 +      state(conn, FTP_STOP);
 +      return result;
 +    }
 +
 +    state(conn, FTP_QUIT);
 +
 +    result = ftp_block_statemach(conn);
 +  }
 +
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_disconnect()
 + *
 + * Disconnect from an FTP server. Cleanup protocol-specific per-connection
 + * resources. BLOCKING.
 + */
 +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +
 +  /* We cannot send quit unconditionally. If this connection is stale or
 +     bad in any way, sending quit and waiting around here will make the
 +     disconnect wait in vain and cause more problems than we need to.
 +
 +     ftp_quit() will check the state of ftp->ctl_valid. If it's ok it
 +     will try to send the QUIT command, otherwise it will just return.
 +  */
 +  if(dead_connection)
 +    ftpc->ctl_valid = FALSE;
 +
 +  /* The FTP session may or may not have been allocated/setup at this point! */
 +  (void)ftp_quit(conn); /* ignore errors on the QUIT */
 +
 +  if(ftpc->entrypath) {
 +    struct Curl_easy *data = conn->data;
 +    if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
 +      data->state.most_recent_ftp_entrypath = NULL;
 +    }
 +    free(ftpc->entrypath);
 +    ftpc->entrypath = NULL;
 +  }
 +
 +  freedirs(ftpc);
 +  free(ftpc->prevpath);
 +  ftpc->prevpath = NULL;
 +  free(ftpc->server_os);
 +  ftpc->server_os = NULL;
 +
 +  Curl_pp_disconnect(pp);
 +
 +#ifdef HAVE_GSSAPI
 +  Curl_sec_end(conn);
 +#endif
 +
 +  return CURLE_OK;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_parse_url_path()
 + *
 + * Parse the URL path into separate path components.
 + *
 + */
 +static
 +CURLcode ftp_parse_url_path(struct connectdata *conn)
 +{
 +  struct Curl_easy *data = conn->data;
 +  /* the ftp struct is already inited in ftp_connect() */
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  const char *slash_pos;  /* position of the first '/' char in curpos */
 +  const char *path_to_use = ftp->path;
 +  const char *cur_pos;
 +  const char *filename = NULL;
 +
 +  cur_pos = path_to_use; /* current position in path. point at the begin of
 +                            next path component */
 +
 +  ftpc->ctl_valid = FALSE;
 +  ftpc->cwdfail = FALSE;
 +
 +  switch(data->set.ftp_filemethod) {
 +  case FTPFILE_NOCWD:
 +    /* fastest, but less standard-compliant */
 +
 +    /*
 +      The best time to check whether the path is a file or directory is right
 +      here. so:
 +
 +      the first condition in the if() right here, is there just in case
 +      someone decides to set path to NULL one day
 +   */
 +    if(path_to_use[0] &&
 +       (path_to_use[strlen(path_to_use) - 1] != '/') )
 +      filename = path_to_use;  /* this is a full file path */
 +    /*
 +      else {
 +        ftpc->file is not used anywhere other than for operations on a file.
 +        In other words, never for directory operations.
 +        So we can safely leave filename as NULL here and use it as a
 +        argument in dir/file decisions.
 +      }
 +    */
 +    break;
 +
 +  case FTPFILE_SINGLECWD:
 +    /* get the last slash */
 +    if(!path_to_use[0]) {
 +      /* no dir, no file */
 +      ftpc->dirdepth = 0;
 +      break;
 +    }
 +    slash_pos = strrchr(cur_pos, '/');
 +    if(slash_pos || !*cur_pos) {
 +      size_t dirlen = slash_pos-cur_pos;
 +      CURLcode result;
 +
 +      ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
 +      if(!ftpc->dirs)
 +        return CURLE_OUT_OF_MEMORY;
 +
 +      if(!dirlen)
 +        dirlen++;
 +
 +      result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/",
 +                              slash_pos ? dirlen : 1,
 +                              &ftpc->dirs[0], NULL,
 +                              TRUE);
 +      if(result) {
 +        freedirs(ftpc);
 +        return result;
 +      }
 +      ftpc->dirdepth = 1; /* we consider it to be a single dir */
 +      filename = slash_pos ? slash_pos + 1 : cur_pos; /* rest is file name */
 +    }
 +    else
 +      filename = cur_pos;  /* this is a file name only */
 +    break;
 +
 +  default: /* allow pretty much anything */
 +  case FTPFILE_MULTICWD:
 +    ftpc->dirdepth = 0;
 +    ftpc->diralloc = 5; /* default dir depth to allocate */
 +    ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0]));
 +    if(!ftpc->dirs)
 +      return CURLE_OUT_OF_MEMORY;
 +
 +    /* we have a special case for listing the root dir only */
 +    if(!strcmp(path_to_use, "/")) {
 +      cur_pos++; /* make it point to the zero byte */
 +      ftpc->dirs[0] = strdup("/");
 +      ftpc->dirdepth++;
 +    }
 +    else {
 +      /* parse the URL path into separate path components */
 +      while((slash_pos = strchr(cur_pos, '/')) != NULL) {
 +        /* 1 or 0 pointer offset to indicate absolute directory */
 +        ssize_t absolute_dir = ((cur_pos - ftp->path > 0) &&
 +                                (ftpc->dirdepth == 0))?1:0;
 +
 +        /* seek out the next path component */
 +        if(slash_pos-cur_pos) {
 +          /* we skip empty path components, like "x//y" since the FTP command
 +             CWD requires a parameter and a non-existent parameter a) doesn't
 +             work on many servers and b) has no effect on the others. */
 +          size_t len = slash_pos - cur_pos + absolute_dir;
 +          CURLcode result =
 +            Curl_urldecode(conn->data, cur_pos - absolute_dir, len,
 +                           &ftpc->dirs[ftpc->dirdepth], NULL,
 +                           TRUE);
 +          if(result) {
 +            freedirs(ftpc);
 +            return result;
 +          }
 +        }
 +        else {
 +          cur_pos = slash_pos + 1; /* jump to the rest of the string */
 +          if(!ftpc->dirdepth) {
 +            /* path starts with a slash, add that as a directory */
 +            ftpc->dirs[ftpc->dirdepth] = strdup("/");
 +            if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */
 +              failf(data, "no memory");
 +              freedirs(ftpc);
 +              return CURLE_OUT_OF_MEMORY;
 +            }
 +          }
 +          continue;
 +        }
 +
 +        cur_pos = slash_pos + 1; /* jump to the rest of the string */
 +        if(++ftpc->dirdepth >= ftpc->diralloc) {
 +          /* enlarge array */
 +          char **bigger;
 +          ftpc->diralloc *= 2; /* double the size each time */
 +          bigger = realloc(ftpc->dirs, ftpc->diralloc * sizeof(ftpc->dirs[0]));
 +          if(!bigger) {
 +            freedirs(ftpc);
 +            return CURLE_OUT_OF_MEMORY;
 +          }
 +          ftpc->dirs = bigger;
 +        }
 +      }
 +    }
 +    filename = cur_pos;  /* the rest is the file name */
 +    break;
 +  } /* switch */
 +
 +  if(filename && *filename) {
 +    CURLcode result =
 +      Curl_urldecode(conn->data, filename, 0,  &ftpc->file, NULL, TRUE);
 +
 +    if(result) {
 +      freedirs(ftpc);
 +      return result;
 +    }
 +  }
 +  else
 +    ftpc->file = NULL; /* instead of point to a zero byte, we make it a NULL
 +                          pointer */
 +
 +  if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) {
 +    /* We need a file name when uploading. Return error! */
 +    failf(data, "Uploading to a URL without a file name!");
 +    return CURLE_URL_MALFORMAT;
 +  }
 +
 +  ftpc->cwddone = FALSE; /* default to not done */
 +
 +  if(ftpc->prevpath) {
 +    /* prevpath is "raw" so we convert the input path before we compare the
 +       strings */
 +    size_t dlen;
 +    char *path;
 +    CURLcode result =
 +      Curl_urldecode(conn->data, ftp->path, 0, &path, &dlen, TRUE);
 +    if(result) {
 +      freedirs(ftpc);
 +      return result;
 +    }
 +
 +    dlen -= ftpc->file?strlen(ftpc->file):0;
 +    if((dlen == strlen(ftpc->prevpath)) &&
 +       !strncmp(path, ftpc->prevpath, dlen) &&
 +       (ftpc->prevmethod == data->set.ftp_filemethod)) {
 +      infof(data, "Request has same path as previous transfer\n");
 +      ftpc->cwddone = TRUE;
 +    }
 +    free(path);
 +  }
 +
 +  return CURLE_OK;
 +}
 +
 +/* call this when the DO phase has completed */
 +static CURLcode ftp_dophase_done(struct connectdata *conn,
 +                                 bool connected)
 +{
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if(connected) {
 +    int completed;
 +    CURLcode result = ftp_do_more(conn, &completed);
 +
 +    if(result) {
 +      close_secondarysocket(conn);
 +      return result;
 +    }
 +  }
 +
 +  if(ftp->transfer != FTPTRANSFER_BODY)
 +    /* no data to transfer */
-     Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
++    Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
 +  else if(!connected)
 +    /* since we didn't connect now, we want do_more to get called */
 +    conn->bits.do_more = TRUE;
 +
 +  ftpc->ctl_valid = TRUE; /* seems good */
 +
 +  return CURLE_OK;
 +}
 +
 +/* called from multi.c while DOing */
 +static CURLcode ftp_doing(struct connectdata *conn,
 +                          bool *dophase_done)
 +{
 +  CURLcode result = ftp_multi_statemach(conn, dophase_done);
 +
 +  if(result)
 +    DEBUGF(infof(conn->data, "DO phase failed\n"));
 +  else if(*dophase_done) {
 +    result = ftp_dophase_done(conn, FALSE /* not connected */);
 +
 +    DEBUGF(infof(conn->data, "DO phase is complete2\n"));
 +  }
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_regular_transfer()
 + *
 + * The input argument is already checked for validity.
 + *
 + * Performs all commands done before a regular transfer between a local and a
 + * remote host.
 + *
 + * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
 + * ftp_done() function without finding any major problem.
 + */
 +static
 +CURLcode ftp_regular_transfer(struct connectdata *conn,
 +                              bool *dophase_done)
 +{
 +  CURLcode result = CURLE_OK;
 +  bool connected = FALSE;
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  data->req.size = -1; /* make sure this is unknown at this point */
 +
 +  Curl_pgrsSetUploadCounter(data, 0);
 +  Curl_pgrsSetDownloadCounter(data, 0);
 +  Curl_pgrsSetUploadSize(data, -1);
 +  Curl_pgrsSetDownloadSize(data, -1);
 +
 +  ftpc->ctl_valid = TRUE; /* starts good */
 +
 +  result = ftp_perform(conn,
 +                       &connected, /* have we connected after PASV/PORT */
 +                       dophase_done); /* all commands in the DO-phase done? */
 +
 +  if(!result) {
 +
 +    if(!*dophase_done)
 +      /* the DO phase has not completed yet */
 +      return CURLE_OK;
 +
 +    result = ftp_dophase_done(conn, connected);
 +
 +    if(result)
 +      return result;
 +  }
 +  else
 +    freedirs(ftpc);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_setup_connection(struct connectdata *conn)
 +{
 +  struct Curl_easy *data = conn->data;
 +  char *type;
 +  struct FTP *ftp;
 +
 +  conn->data->req.protop = ftp = calloc(sizeof(struct FTP), 1);
 +  if(NULL == ftp)
 +    return CURLE_OUT_OF_MEMORY;
 +
 +  ftp->path = &data->state.up.path[1]; /* don't include the initial slash */
-   data->state.slash_removed = TRUE; /* we've skipped the slash */
 +
 +  /* FTP URLs support an extension like ";type=<typecode>" that
 +   * we'll try to get now! */
 +  type = strstr(ftp->path, ";type=");
 +
 +  if(!type)
 +    type = strstr(conn->host.rawalloc, ";type=");
 +
 +  if(type) {
 +    char command;
 +    *type = 0;                     /* it was in the middle of the hostname */
 +    command = Curl_raw_toupper(type[6]);
 +    conn->bits.type_set = TRUE;
 +
 +    switch(command) {
 +    case 'A': /* ASCII mode */
 +      data->set.prefer_ascii = TRUE;
 +      break;
 +
 +    case 'D': /* directory mode */
 +      data->set.ftp_list_only = TRUE;
 +      break;
 +
 +    case 'I': /* binary mode */
 +    default:
 +      /* switch off ASCII */
 +      data->set.prefer_ascii = FALSE;
 +      break;
 +    }
 +  }
 +
 +  /* get some initial data into the ftp struct */
-   ftp->bytecountp = &conn->data->req.bytecount;
 +  ftp->transfer = FTPTRANSFER_BODY;
 +  ftp->downloadsize = 0;
 +
 +  /* No need to duplicate user+password, the connectdata struct won't change
 +     during a session, but we re-init them here since on subsequent inits
 +     since the conn struct may have changed or been replaced.
 +  */
 +  ftp->user = conn->user;
 +  ftp->passwd = conn->passwd;
 +  if(isBadFtpString(ftp->user))
 +    return CURLE_URL_MALFORMAT;
 +  if(isBadFtpString(ftp->passwd))
 +    return CURLE_URL_MALFORMAT;
 +
 +  conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
 +
 +  return CURLE_OK;
 +}
 +
 +#endif /* CURL_DISABLE_FTP */

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b26487c663ec29d972fd61adc2b14ac5880b78c7
commit b26487c663ec29d972fd61adc2b14ac5880b78c7
Author:     Curl Upstream <curl-library at cool.haxx.se>
AuthorDate: Wed May 22 07:48:44 2019 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed May 22 14:11:40 2019 -0400

    curl 2019-05-22 (885ce314)
    
    Code extracted from:
    
        https://github.com/curl/curl.git
    
    at commit 885ce31401b6789c959131754b1e5ae518964072 (curl-7_65_0).

diff --git a/CMake/CurlTests.c b/CMake/CurlTests.c
index 9388c83..07b516b 100644
--- a/CMake/CurlTests.c
+++ b/CMake/CurlTests.c
@@ -240,6 +240,7 @@ int main()
 #ifndef inet_ntoa_r
   func_type func;
   func = (func_type)inet_ntoa_r;
+  (void)func;
 #endif
   return 0;
 }
@@ -255,6 +256,7 @@ int main()
 #ifndef inet_ntoa_r
   func_type func;
   func = (func_type)&inet_ntoa_r;
+  (void)func;
 #endif
   return 0;
 }
@@ -553,8 +555,8 @@ main() {
 #include <time.h>
 int
 main() {
-  struct timespec ts = {0, 0}; 
-  clock_gettime(CLOCK_MONOTONIC, &ts); 
+  struct timespec ts = {0, 0};
+  clock_gettime(CLOCK_MONOTONIC, &ts);
   return 0;
 }
 #endif
@@ -565,3 +567,49 @@ main() {
   return 0;
 }
 #endif
+#ifdef HAVE_VARIADIC_MACROS_C99
+#define c99_vmacro3(first, ...) fun3(first, __VA_ARGS__)
+#define c99_vmacro2(first, ...) fun2(first, __VA_ARGS__)
+
+int fun3(int arg1, int arg2, int arg3);
+int fun2(int arg1, int arg2);
+
+int fun3(int arg1, int arg2, int arg3) {
+  return arg1 + arg2 + arg3;
+}
+int fun2(int arg1, int arg2) {
+  return arg1 + arg2;
+}
+
+int
+main() {
+  int res3 = c99_vmacro3(1, 2, 3);
+  int res2 = c99_vmacro2(1, 2);
+  (void)res3;
+  (void)res2;
+  return 0;
+}
+#endif
+#ifdef HAVE_VARIADIC_MACROS_GCC
+#define gcc_vmacro3(first, args...) fun3(first, args)
+#define gcc_vmacro2(first, args...) fun2(first, args)
+
+int fun3(int arg1, int arg2, int arg3);
+int fun2(int arg1, int arg2);
+
+int fun3(int arg1, int arg2, int arg3) {
+  return arg1 + arg2 + arg3;
+}
+int fun2(int arg1, int arg2) {
+  return arg1 + arg2;
+}
+
+int
+main() {
+  int res3 = gcc_vmacro3(1, 2, 3);
+  int res2 = gcc_vmacro2(1, 2);
+  (void)res3;
+  (void)res2;
+  return 0;
+}
+#endif
diff --git a/CMake/FindGSS.cmake b/CMake/FindGSS.cmake
index 7a637fc..8a28f2f 100644
--- a/CMake/FindGSS.cmake
+++ b/CMake/FindGSS.cmake
@@ -68,7 +68,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
       # should also work in an odd case when multiple directories are given
       string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
       string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
-      string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1"_GSS_CFLAGS "${_GSS_CFLAGS}")
+      string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}")
 
       foreach(_flag ${_GSS_CFLAGS})
         if(_flag MATCHES "^-I.*")
@@ -91,7 +91,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
       # this script gives us libraries and link directories. Blah. We have to deal with it.
       string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
       string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
-      string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1"_GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
+      string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
 
       foreach(_flag ${_GSS_LIB_FLAGS})
         if(_flag MATCHES "^-l.*")
diff --git a/CMake/OtherTests.cmake b/CMake/OtherTests.cmake
index ce6d3e1..c1c9aa3 100644
--- a/CMake/OtherTests.cmake
+++ b/CMake/OtherTests.cmake
@@ -24,6 +24,8 @@ else()
   add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
 endif()
 
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+
 check_c_source_compiles("${_source_epilogue}
 int main(void) {
     recv(0, 0, 0, 0);
@@ -177,23 +179,6 @@ int main(void) {
   return 0;
 }" HAVE_STRUCT_TIMEVAL)
 
-
-include(CheckCSourceRuns)
-# See HAVE_POLL in CMakeLists.txt for why poll is disabled on macOS
-if(NOT APPLE)
-  set(CMAKE_REQUIRED_FLAGS)
-  if(HAVE_SYS_POLL_H)
-    set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
-  endif()
-  check_c_source_runs("
-    #ifdef HAVE_SYS_POLL_H
-    #  include <sys/poll.h>
-    #endif
-    int main(void) {
-      return poll((void *)0, 0, 10 /*ms*/);
-    }" HAVE_POLL_FINE)
-endif()
-
 set(HAVE_SIG_ATOMIC_T 1)
 set(CMAKE_REQUIRED_FLAGS)
 if(HAVE_SIGNAL_H)
@@ -229,3 +214,51 @@ check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
 if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
   set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
 endif()
+
+unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
+
+if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
+  # if not cross-compilation...
+  include(CheckCSourceRuns)
+  set(CMAKE_REQUIRED_FLAGS "")
+  if(HAVE_SYS_POLL_H)
+    set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
+  elseif(HAVE_POLL_H)
+    set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H")
+  endif()
+  check_c_source_runs("
+    #include <stdlib.h>
+    #include <sys/time.h>
+
+    #ifdef HAVE_SYS_POLL_H
+    #  include <sys/poll.h>
+    #elif  HAVE_POLL_H
+    #  include <poll.h>
+    #endif
+
+    int main(void)
+    {
+        if(0 != poll(0, 0, 10)) {
+          return 1; /* fail */
+        }
+        else {
+          /* detect the 10.12 poll() breakage */
+          struct timeval before, after;
+          int rc;
+          size_t us;
+
+          gettimeofday(&before, NULL);
+          rc = poll(NULL, 0, 500);
+          gettimeofday(&after, NULL);
+
+          us = (after.tv_sec - before.tv_sec) * 1000000 +
+            (after.tv_usec - before.tv_usec);
+
+          if(us < 400000) {
+            return 1;
+          }
+        }
+        return 0;
+    }" HAVE_POLL_FINE)
+endif()
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a3c17c4..c8c77e1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -57,7 +57,6 @@ string(REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+"
   CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS})
 string(REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM})
 
-include_regular_expression("^.*$")    # Sukender: Is it necessary?
 
 # Setup package meta-data
 # SET(PACKAGE "curl")
@@ -70,7 +69,6 @@ message(STATUS "curl version=[${CURL_VERSION}]")
 set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
 set(OS "\"${CMAKE_SYSTEM_NAME}\"")
 
-include_directories(${PROJECT_BINARY_DIR}/include/curl)
 include_directories(${CURL_SOURCE_DIR}/include)
 
 option(CURL_WERROR "Turn compiler warnings into errors" OFF)
@@ -105,11 +103,7 @@ endif()
 
 if(ENABLE_DEBUG)
   # DEBUGBUILD will be defined only for Debug builds
-  if(NOT CMAKE_VERSION VERSION_LESS 3.0)
-    set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
-  else()
-    set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUGBUILD)
-  endif()
+  set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
   set(ENABLE_CURLDEBUG ON)
 endif()
 
@@ -247,7 +241,6 @@ include(CheckLibraryExists)
 include(CheckSymbolExists)
 include(CheckTypeSize)
 include(CheckCSourceCompiles)
-include(CMakeDependentOption)
 
 # On windows preload settings
 if(WIN32)
@@ -291,10 +284,10 @@ if(WIN32)
 endif()
 
 # check SSL libraries
-# TODO support GNUTLS, NSS, POLARSSL, AXTLS, CYASSL
+# TODO support GNUTLS, NSS, POLARSSL, CYASSL
 
 if(APPLE)
-  option(CMAKE_USE_DARWINSSL "enable Apple OS native SSL/TLS" OFF)
+  option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF)
 endif()
 if(WIN32)
   option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF)
@@ -304,14 +297,14 @@ endif()
 option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF)
 
 set(openssl_default ON)
-if(WIN32 OR CMAKE_USE_DARWINSSL OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
+if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
   set(openssl_default OFF)
 endif()
 option(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ${openssl_default})
 
 count_true(enabled_ssl_options_count
   CMAKE_USE_WINSSL
-  CMAKE_USE_DARWINSSL
+  CMAKE_USE_SECTRANSP
   CMAKE_USE_OPENSSL
   CMAKE_USE_MBEDTLS
 )
@@ -331,6 +324,10 @@ if(CURL_WINDOWS_SSPI)
 endif()
 
 if(CMAKE_USE_DARWINSSL)
+  message(FATAL_ERROR "The cmake option CMAKE_USE_DARWINSSL was renamed to CMAKE_USE_SECTRANSP.")
+endif()
+
+if(CMAKE_USE_SECTRANSP)
   find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation")
   if(NOT COREFOUNDATION_FRAMEWORK)
       message(FATAL_ERROR "CoreFoundation framework not found")
@@ -342,7 +339,7 @@ if(CMAKE_USE_DARWINSSL)
   endif()
 
   set(SSL_ENABLED ON)
-  set(USE_DARWINSSL ON)
+  set(USE_SECTRANSP ON)
   list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}")
 endif()
 
@@ -476,6 +473,7 @@ if(NOT CURL_DISABLE_LDAP)
         list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
       endif()
       check_c_source_compiles("${_SRC_STRING}" NOT_NEED_LBER_H)
+      unset(CMAKE_REQUIRED_LIBRARIES)
 
       if(NOT_NEED_LBER_H)
         set(NEED_LBER_H OFF)
@@ -571,6 +569,7 @@ if(CMAKE_USE_LIBSSH2)
     check_function_exists(libssh2_scp_send64        HAVE_LIBSSH2_SCP_SEND64)
     check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE)
     set(CMAKE_EXTRA_INCLUDE_FILES "")
+    unset(CMAKE_REQUIRED_LIBRARIES)
   endif()
 endif()
 
@@ -585,7 +584,7 @@ if(CMAKE_USE_GSSAPI)
 
     message(STATUS "Found ${GSS_FLAVOUR} GSSAPI version: \"${GSS_VERSION}\"")
 
-    list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIRECTORIES})
+    list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIR})
     check_include_file_concat("gssapi/gssapi.h"  HAVE_GSSAPI_GSSAPI_H)
     check_include_file_concat("gssapi/gssapi_generic.h" HAVE_GSSAPI_GSSAPI_GENERIC_H)
     check_include_file_concat("gssapi/gssapi_krb5.h" HAVE_GSSAPI_GSSAPI_KRB5_H)
@@ -618,10 +617,11 @@ if(CMAKE_USE_GSSAPI)
       if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE)
         set(HAVE_OLD_GSSMIT ON)
       endif()
+      unset(CMAKE_REQUIRED_LIBRARIES)
 
     endif()
 
-    include_directories(${GSS_INCLUDE_DIRECTORIES})
+    include_directories(${GSS_INCLUDE_DIR})
     link_directories(${GSS_LINK_DIRECTORIES})
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}")
     set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
@@ -828,12 +828,8 @@ endif()
 
 check_symbol_exists(basename      "${CURL_INCLUDES}" HAVE_BASENAME)
 check_symbol_exists(socket        "${CURL_INCLUDES}" HAVE_SOCKET)
-# poll on macOS is unreliable, it first did not exist, then was broken until
-# fixed in 10.9 only to break again in 10.12.
-if(NOT APPLE)
-  check_symbol_exists(poll        "${CURL_INCLUDES}" HAVE_POLL)
-endif()
 check_symbol_exists(select        "${CURL_INCLUDES}" HAVE_SELECT)
+check_symbol_exists(poll          "${CURL_INCLUDES}" HAVE_POLL)
 check_symbol_exists(strdup        "${CURL_INCLUDES}" HAVE_STRDUP)
 check_symbol_exists(strstr        "${CURL_INCLUDES}" HAVE_STRSTR)
 check_symbol_exists(strtok_r      "${CURL_INCLUDES}" HAVE_STRTOK_R)
@@ -889,6 +885,8 @@ check_symbol_exists(freeifaddrs    "${CURL_INCLUDES}" HAVE_FREEIFADDRS)
 check_symbol_exists(pipe           "${CURL_INCLUDES}" HAVE_PIPE)
 check_symbol_exists(ftruncate      "${CURL_INCLUDES}" HAVE_FTRUNCATE)
 check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
+check_symbol_exists(getpeername    "${CURL_INCLUDES}" HAVE_GETPEERNAME)
+check_symbol_exists(getsockname    "${CURL_INCLUDES}" HAVE_GETSOCKNAME)
 check_symbol_exists(getrlimit      "${CURL_INCLUDES}" HAVE_GETRLIMIT)
 check_symbol_exists(setlocale      "${CURL_INCLUDES}" HAVE_SETLOCALE)
 check_symbol_exists(setmode        "${CURL_INCLUDES}" HAVE_SETMODE)
@@ -972,6 +970,8 @@ foreach(CURL_TEST
     HAVE_INET_NTOA_R_DECL_REENTRANT
     HAVE_GETADDRINFO
     HAVE_FILE_OFFSET_BITS
+    HAVE_VARIADIC_MACROS_C99
+    HAVE_VARIADIC_MACROS_GCC
     )
   curl_internal_test(${CURL_TEST})
 endforeach()
@@ -1133,7 +1133,7 @@ if(CURL_WERROR)
 endif()
 
 # Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
-function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
+function(transform_makefile_inc INPUT_FILE OUTPUT_FILE)
   file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
   string(REPLACE "$(top_srcdir)"   "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
   string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
@@ -1182,10 +1182,7 @@ endfunction()
 
 # Clear list and try to detect available features
 set(_items)
-_add_if("WinSSL"        SSL_ENABLED AND USE_WINDOWS_SSPI)
-_add_if("OpenSSL"       SSL_ENABLED AND USE_OPENSSL)
-_add_if("DarwinSSL"     SSL_ENABLED AND USE_DARWINSSL)
-_add_if("mbedTLS"       SSL_ENABLED AND USE_MBEDTLS)
+_add_if("SSL"           SSL_ENABLED)
 _add_if("IPv6"          ENABLE_IPV6)
 _add_if("unix-sockets"  USE_UNIX_SOCKETS)
 _add_if("libz"          HAVE_LIBZ)
@@ -1203,7 +1200,7 @@ _add_if("Kerberos"      NOT CURL_DISABLE_CRYPTO_AUTH AND
                         (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
 # NTLM support requires crypto function adaptions from various SSL libs
 # TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
-if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_DARWINSSL OR USE_MBEDTLS))
+if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_SECTRANSP OR USE_MBEDTLS))
   _add_if("NTLM"        1)
   # TODO missing option (autoconf: --enable-ntlm-wb)
   _add_if("NTLM_WB"     NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
@@ -1242,10 +1239,24 @@ _add_if("SCP"           USE_LIBSSH2)
 _add_if("SFTP"          USE_LIBSSH2)
 _add_if("RTSP"          NOT CURL_DISABLE_RTSP)
 _add_if("RTMP"          USE_LIBRTMP)
-list(SORT _items)
+if(_items)
+  list(SORT _items)
+endif()
 string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
 message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
 
+# Clear list and collect SSL backends
+set(_items)
+_add_if("WinSSL"           SSL_ENABLED AND USE_WINDOWS_SSPI)
+_add_if("OpenSSL"          SSL_ENABLED AND USE_OPENSSL)
+_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
+_add_if("mbedTLS"          SSL_ENABLED AND USE_MBEDTLS)
+if(_items)
+  list(SORT _items)
+endif()
+string(REPLACE ";" " " SSL_BACKENDS "${_items}")
+message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
+
 # curl-config needs the following options to be set.
 set(CC                      "${CMAKE_C_COMPILER}")
 # TODO probably put a -D... options here?
diff --git a/COPYING b/COPYING
index 560a49d..3528bd7 100644
--- a/COPYING
+++ b/COPYING
@@ -1,6 +1,6 @@
 COPYRIGHT AND PERMISSION NOTICE
 
-Copyright (c) 1996 - 2018, Daniel Stenberg, <daniel at haxx.se>, and many
+Copyright (c) 1996 - 2019, Daniel Stenberg, <daniel at haxx.se>, and many
 contributors, see the THANKS file.
 
 All rights reserved.
diff --git a/include/curl/curl.h b/include/curl/curl.h
index cf6f01d..d83b217 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -91,6 +91,11 @@
 #include <support/SupportDefs.h>
 #endif
 
+/* Compatibility for non-Clang compilers */
+#ifndef __has_declspec_attribute
+#  define __has_declspec_attribute(x) 0
+#endif
+
 #ifdef  __cplusplus
 extern "C" {
 #endif
@@ -109,7 +114,9 @@ typedef void CURLSH;
 
 #ifdef CURL_STATICLIB
 #  define CURL_EXTERN
-#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)
+#elif defined(WIN32) || defined(__SYMBIAN32__) || \
+     (__has_declspec_attribute(dllexport) && \
+      __has_declspec_attribute(dllimport))
 #  if defined(BUILDING_LIBCURL)
 #    define CURL_EXTERN  __declspec(dllexport)
 #  else
@@ -144,8 +151,8 @@ typedef enum {
   CURLSSLBACKEND_POLARSSL = 6,
   CURLSSLBACKEND_WOLFSSL = 7,
   CURLSSLBACKEND_SCHANNEL = 8,
-  CURLSSLBACKEND_DARWINSSL = 9,
-  CURLSSLBACKEND_AXTLS = 10,
+  CURLSSLBACKEND_SECURETRANSPORT = 9,
+  CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */
   CURLSSLBACKEND_MBEDTLS = 11,
   CURLSSLBACKEND_MESALINK = 12
 } curl_sslbackend;
@@ -153,7 +160,10 @@ typedef enum {
 /* aliases for library clones and renames */
 #define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
 #define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
+
+/* deprecated names: */
 #define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
+#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT
 
 struct curl_httppost {
   struct curl_httppost *next;       /* next entry in the list */
@@ -280,7 +290,7 @@ typedef enum {
 struct curl_fileinfo {
   char *filename;
   curlfiletype filetype;
-  time_t time;
+  time_t time; /* always zero! */
   unsigned int perm;
   int uid;
   int gid;
@@ -355,11 +365,21 @@ typedef int (*curl_seek_callback)(void *instream,
    signal libcurl to pause sending data on the current transfer. */
 #define CURL_READFUNC_PAUSE 0x10000001
 
+/* Return code for when the trailing headers' callback has terminated
+   without any errors*/
+#define CURL_TRAILERFUNC_OK 0
+/* Return code for when was an error in the trailing header's list and we
+  want to abort the request */
+#define CURL_TRAILERFUNC_ABORT 1
+
 typedef size_t (*curl_read_callback)(char *buffer,
                                       size_t size,
                                       size_t nitems,
                                       void *instream);
 
+typedef int (*curl_trailer_callback)(struct curl_slist **list,
+                                      void *userdata);
+
 typedef enum {
   CURLSOCKTYPE_IPCXN,  /* socket created for a specific IP connection */
   CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
@@ -585,9 +605,6 @@ typedef enum {
   CURL_LAST /* never use! */
 } CURLcode;
 
-/* added in 7.62.0 */
-#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
-
 #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
                           the obsolete stuff removed! */
 
@@ -602,6 +619,9 @@ typedef enum {
 #define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
 #define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
 
+/* The following were added in 7.62.0 */
+#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
+
 /* The following were added in 7.21.5, April 2011 */
 #define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
 
@@ -861,6 +881,14 @@ typedef enum {
 #define CURLHEADER_UNIFIED  0
 #define CURLHEADER_SEPARATE (1<<0)
 
+/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */
+#define CURLALTSVC_IMMEDIATELY  (1<<0)
+#define CURLALTSVC_ALTUSED      (1<<1)
+#define CURLALTSVC_READONLYFILE (1<<2)
+#define CURLALTSVC_H1           (1<<3)
+#define CURLALTSVC_H2           (1<<4)
+#define CURLALTSVC_H3           (1<<5)
+
 /* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
 #define CURLPROTO_HTTP   (1<<0)
 #define CURLPROTO_HTTPS  (1<<1)
@@ -1872,6 +1900,27 @@ typedef enum {
   /* Time in ms between connection upkeep calls for long-lived connections. */
   CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
 
+  /* Specify URL using CURL URL API. */
+  CINIT(CURLU, OBJECTPOINT, 282),
+
+  /* add trailing data just after no more data is available */
+  CINIT(TRAILERFUNCTION, FUNCTIONPOINT, 283),
+
+  /* pointer to be passed to HTTP_TRAILER_FUNCTION */
+  CINIT(TRAILERDATA, OBJECTPOINT, 284),
+
+  /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */
+  CINIT(HTTP09_ALLOWED, LONG, 285),
+
+  /* alt-svc control bitmask */
+  CINIT(ALTSVC_CTRL, LONG, 286),
+
+  /* alt-svc cache file name to possibly read from/write to */
+  CINIT(ALTSVC, STRINGPOINT, 287),
+
+  /* maximum age of a connection to consider it for reuse (in seconds) */
+  CINIT(MAXAGE_CONN, LONG, 288),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
@@ -2734,6 +2783,7 @@ typedef struct {
 #define CURL_VERSION_HTTPS_PROXY  (1<<21) /* HTTPS-proxy support built-in */
 #define CURL_VERSION_MULTI_SSL    (1<<22) /* Multiple SSL backends available */
 #define CURL_VERSION_BROTLI       (1<<23) /* Brotli features are present. */
+#define CURL_VERSION_ALTSVC       (1<<24) /* Alt-Svc handling built-in */
 
  /*
  * NAME curl_version_info()
diff --git a/include/curl/curlver.h b/include/curl/curlver.h
index 6c111da..bca53cb 100644
--- a/include/curl/curlver.h
+++ b/include/curl/curlver.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -26,16 +26,16 @@
    a script at release-time. This was made its own header file in 7.11.2 */
 
 /* This is the global package copyright */
-#define LIBCURL_COPYRIGHT "1996 - 2018 Daniel Stenberg, <daniel at haxx.se>."
+#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, <daniel at haxx.se>."
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "7.62.0-DEV"
+#define LIBCURL_VERSION "7.65.0-DEV"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 62
+#define LIBCURL_VERSION_MINOR 65
 #define LIBCURL_VERSION_PATCH 0
 
 /* This is the numeric version of the libcurl version number, meant for easier
@@ -57,7 +57,7 @@
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    and needs it to contain the full number.
 */
-#define LIBCURL_VERSION_NUM 0x073E00
+#define LIBCURL_VERSION_NUM 0x074100
 
 /*
  * This is the date and time when the full source package was created. The
@@ -70,7 +70,7 @@
  */
 #define LIBCURL_TIMESTAMP "[unreleased]"
 
-#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
+#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
 #define CURL_AT_LEAST_VERSION(x,y,z) \
   (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
 
diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h
index 2443362..2d1de4d 100644
--- a/include/curl/typecheck-gcc.h
+++ b/include/curl/typecheck-gcc.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -113,7 +113,6 @@ __extension__ ({                                                              \
 })
 
 /* wraps curl_easy_getinfo() with typechecking */
-/* FIXME: don't allow const pointers */
 #define curl_easy_getinfo(handle, info, arg)                                  \
 __extension__ ({                                                              \
   __typeof__(info) _curl_info = info;                                         \
@@ -146,9 +145,8 @@ __extension__ ({                                                              \
   curl_easy_getinfo(handle, _curl_info, arg);                                 \
 })
 
-/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
- * for now just make sure that the functions are called with three
- * arguments
+/*
+ * For now, just make sure that the functions are called with three arguments
  */
 #define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
 #define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
@@ -256,6 +254,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
 #define _curl_is_string_option(option)                                        \
   ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET ||                                \
    (option) == CURLOPT_ACCEPT_ENCODING ||                                     \
+   (option) == CURLOPT_ALTSVC ||                                              \
    (option) == CURLOPT_CAINFO ||                                              \
    (option) == CURLOPT_CAPATH ||                                              \
    (option) == CURLOPT_COOKIE ||                                              \
@@ -363,6 +362,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
    (option) == CURLOPT_SSL_CTX_DATA ||                                        \
    (option) == CURLOPT_WRITEDATA ||                                           \
    (option) == CURLOPT_RESOLVER_START_DATA ||                                 \
+   (option) == CURLOPT_CURLU ||                                               \
    0)
 
 /* evaluates to true if option takes a POST data argument (void* or char*) */
@@ -504,10 +504,6 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
    _curl_is_arr((expr), char) ||                                              \
    _curl_is_arr((expr), unsigned char))
 
-/* FIXME: the whole callback checking is messy...
- * The idea is to tolerate char vs. void and const vs. not const
- * pointers in arguments at least
- */
 /* helper: __builtin_types_compatible_p distinguishes between functions and
  * function pointers, hide it */
 #define _curl_callback_compatible(func, type)                                 \
diff --git a/include/curl/urlapi.h b/include/curl/urlapi.h
index 90dd56c..58e89d8 100644
--- a/include/curl/urlapi.h
+++ b/include/curl/urlapi.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,8 @@
  *
  ***************************************************************************/
 
+#include "curl.h"
+
 #ifdef  __cplusplus
 extern "C" {
 #endif
@@ -58,7 +60,8 @@ typedef enum {
   CURLUPART_PORT,
   CURLUPART_PATH,
   CURLUPART_QUERY,
-  CURLUPART_FRAGMENT
+  CURLUPART_FRAGMENT,
+  CURLUPART_ZONEID /* added in 7.65.0 */
 } CURLUPart;
 
 #define CURLU_DEFAULT_PORT (1<<0)       /* return default port number */
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 4aa0422..235b82b 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -28,13 +28,13 @@ LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c         \
 LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
 
 LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c     \
-  vtls/polarssl.c vtls/polarssl_threadlock.c vtls/axtls.c               \
+  vtls/polarssl.c vtls/polarssl_threadlock.c                            \
   vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c                  \
-  vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c
+  vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c
 
 LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h                \
-  vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h vtls/axtls.h   \
-  vtls/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h           \
+  vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h                \
+  vtls/cyassl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h           \
   vtls/mbedtls.h vtls/mesalink.h
 
 LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
@@ -52,10 +52,10 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
   openldap.c curl_gethostname.c gopher.c idn_win32.c                    \
   http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c      \
   http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c        \
-  curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c          \
+  curl_multibyte.c hostcheck.c conncache.c dotdot.c                     \
   x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c      \
   mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c  \
-  doh.c urlapi.c
+  doh.c urlapi.c curl_get_line.c altsvc.c
 
 LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
   formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h         \
@@ -72,10 +72,11 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
   curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h           \
   http_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h             \
   curl_sasl.h curl_multibyte.h hostcheck.h conncache.h                  \
-  curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h       \
+  curl_setup_once.h multihandle.h setup-vms.h dotdot.h                  \
   x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h           \
   curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h     \
-  curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h
+  curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h        \
+  curl_get_line.h altsvc.h
 
 LIB_RCFILES = libcurl.rc
 
diff --git a/lib/altsvc.c b/lib/altsvc.c
new file mode 100644
index 0000000..85a4e01
--- /dev/null
+++ b/lib/altsvc.c
@@ -0,0 +1,569 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+ * The Alt-Svc: header is defined in RFC 7838:
+ * https://tools.ietf.org/html/rfc7838
+ */
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC)
+#include <curl/curl.h>
+#include "urldata.h"
+#include "altsvc.h"
+#include "curl_get_line.h"
+#include "strcase.h"
+#include "parsedate.h"
+#include "sendf.h"
+#include "warnless.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define MAX_ALTSVC_LINE 4095
+#define MAX_ALTSVC_DATELENSTR "64"
+#define MAX_ALTSVC_DATELEN 64
+#define MAX_ALTSVC_HOSTLENSTR "512"
+#define MAX_ALTSVC_HOSTLEN 512
+#define MAX_ALTSVC_ALPNLENSTR "10"
+#define MAX_ALTSVC_ALPNLEN 10
+
+static enum alpnid alpn2alpnid(char *name)
+{
+  if(strcasecompare(name, "h1"))
+    return ALPN_h1;
+  if(strcasecompare(name, "h2"))
+    return ALPN_h2;
+  if(strcasecompare(name, "h2c"))
+    return ALPN_h2c;
+  if(strcasecompare(name, "h3"))
+    return ALPN_h3;
+  return ALPN_none; /* unknown, probably rubbish input */
+}
+
+/* Given the ALPN ID, return the name */
+const char *Curl_alpnid2str(enum alpnid id)
+{
+  switch(id) {
+  case ALPN_h1:
+    return "h1";
+  case ALPN_h2:
+    return "h2";
+  case ALPN_h2c:
+    return "h2c";
+  case ALPN_h3:
+    return "h3";
+  default:
+    return ""; /* bad */
+  }
+}
+
+
+static void altsvc_free(struct altsvc *as)
+{
+  free(as->srchost);
+  free(as->dsthost);
+  free(as);
+}
+
+static struct altsvc *altsvc_createid(const char *srchost,
+                                      const char *dsthost,
+                                      enum alpnid srcalpnid,
+                                      enum alpnid dstalpnid,
+                                      unsigned int srcport,
+                                      unsigned int dstport)
+{
+  struct altsvc *as = calloc(sizeof(struct altsvc), 1);
+  if(!as)
+    return NULL;
+
+  as->srchost = strdup(srchost);
+  if(!as->srchost)
+    goto error;
+  as->dsthost = strdup(dsthost);
+  if(!as->dsthost)
+    goto error;
+
+  as->srcalpnid = srcalpnid;
+  as->dstalpnid = dstalpnid;
+  as->srcport = curlx_ultous(srcport);
+  as->dstport = curlx_ultous(dstport);
+
+  return as;
+  error:
+  altsvc_free(as);
+  return NULL;
+}
+
+static struct altsvc *altsvc_create(char *srchost,
+                                    char *dsthost,
+                                    char *srcalpn,
+                                    char *dstalpn,
+                                    unsigned int srcport,
+                                    unsigned int dstport)
+{
+  enum alpnid dstalpnid = alpn2alpnid(dstalpn);
+  enum alpnid srcalpnid = alpn2alpnid(srcalpn);
+  if(!srcalpnid || !dstalpnid)
+    return NULL;
+  return altsvc_createid(srchost, dsthost, srcalpnid, dstalpnid,
+                         srcport, dstport);
+}
+
+/* only returns SERIOUS errors */
+static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
+{
+  /* Example line:
+     h2 example.com 443 h3 shiny.example.com 8443 "20191231 10:00:00" 1
+   */
+  char srchost[MAX_ALTSVC_HOSTLEN + 1];
+  char dsthost[MAX_ALTSVC_HOSTLEN + 1];
+  char srcalpn[MAX_ALTSVC_ALPNLEN + 1];
+  char dstalpn[MAX_ALTSVC_ALPNLEN + 1];
+  char date[MAX_ALTSVC_DATELEN + 1];
+  unsigned int srcport;
+  unsigned int dstport;
+  unsigned int prio;
+  unsigned int persist;
+  int rc;
+
+  rc = sscanf(line,
+              "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
+              "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
+              "\"%" MAX_ALTSVC_DATELENSTR "[^\"]\" %u %u",
+              srcalpn, srchost, &srcport,
+              dstalpn, dsthost, &dstport,
+              date, &persist, &prio);
+  if(9 == rc) {
+    struct altsvc *as;
+    time_t expires = curl_getdate(date, NULL);
+    as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport);
+    if(as) {
+      as->expires = expires;
+      as->prio = prio;
+      as->persist = persist ? 1 : 0;
+      Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
+      asi->num++; /* one more entry */
+    }
+  }
+
+  return CURLE_OK;
+}
+
+/*
+ * Load alt-svc entries from the given file. The text based line-oriented file
+ * format is documented here:
+ * https://github.com/curl/curl/wiki/QUIC-implementation
+ *
+ * This function only returns error on major problems that prevents alt-svc
+ * handling to work completely. It will ignore individual syntactical errors
+ * etc.
+ */
+static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
+{
+  CURLcode result = CURLE_OK;
+  char *line = NULL;
+  FILE *fp = fopen(file, FOPEN_READTEXT);
+  if(fp) {
+    line = malloc(MAX_ALTSVC_LINE);
+    if(!line)
+      goto fail;
+    while(Curl_get_line(line, MAX_ALTSVC_LINE, fp)) {
+      char *lineptr = line;
+      while(*lineptr && ISBLANK(*lineptr))
+        lineptr++;
+      if(*lineptr == '#')
+        /* skip commented lines */
+        continue;
+
+      altsvc_add(asi, lineptr);
+    }
+    free(line); /* free the line buffer */
+    fclose(fp);
+  }
+  return result;
+
+  fail:
+  free(line);
+  fclose(fp);
+  return CURLE_OUT_OF_MEMORY;
+}
+
+/*
+ * Write this single altsvc entry to a single output line
+ */
+
+static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
+{
+  struct tm stamp;
+  CURLcode result = Curl_gmtime(as->expires, &stamp);
+  if(result)
+    return result;
+
+  fprintf(fp,
+          "%s %s %u "
+          "%s %s %u "
+          "\"%d%02d%02d "
+          "%02d:%02d:%02d\" "
+          "%u %d\n",
+          Curl_alpnid2str(as->srcalpnid), as->srchost, as->srcport,
+          Curl_alpnid2str(as->dstalpnid), as->dsthost, as->dstport,
+          stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
+          stamp.tm_hour, stamp.tm_min, stamp.tm_sec,
+          as->persist, as->prio);
+  return CURLE_OK;
+}
+
+/* ---- library-wide functions below ---- */
+
+/*
+ * Curl_altsvc_init() creates a new altsvc cache.
+ * It returns the new instance or NULL if something goes wrong.
+ */
+struct altsvcinfo *Curl_altsvc_init(void)
+{
+  struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1);
+  if(!asi)
+    return NULL;
+  Curl_llist_init(&asi->list, NULL);
+
+  /* set default behavior */
+  asi->flags = CURLALTSVC_H1
+#ifdef USE_NGHTTP2
+    | CURLALTSVC_H2
+#endif
+#ifdef USE_HTTP3
+    | CURLALTSVC_H3
+#endif
+    ;
+  return asi;
+}
+
+/*
+ * Curl_altsvc_load() loads alt-svc from file.
+ */
+CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file)
+{
+  CURLcode result;
+  DEBUGASSERT(asi);
+  result = altsvc_load(asi, file);
+  return result;
+}
+
+/*
+ * Curl_altsvc_ctrl() passes on the external bitmask.
+ */
+CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
+{
+  DEBUGASSERT(asi);
+  if(!ctrl)
+    /* unexpected */
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  asi->flags = ctrl;
+  return CURLE_OK;
+}
+
+/*
+ * Curl_altsvc_cleanup() frees an altsvc cache instance and all associated
+ * resources.
+ */
+void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  if(altsvc) {
+    for(e = altsvc->list.head; e; e = n) {
+      struct altsvc *as = e->ptr;
+      n = e->next;
+      altsvc_free(as);
+    }
+    free(altsvc);
+  }
+}
+
+/*
+ * Curl_altsvc_save() writes the altsvc cache to a file.
+ */
+CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  CURLcode result = CURLE_OK;
+  FILE *out;
+
+  if(!altsvc)
+    /* no cache activated */
+    return CURLE_OK;
+
+  if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file[0])
+    /* marked as read-only or zero length file name */
+    return CURLE_OK;
+  out = fopen(file, FOPEN_WRITETEXT);
+  if(!out)
+    return CURLE_WRITE_ERROR;
+  fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n"
+        "# This file was generated by libcurl! Edit at your own risk.\n",
+        out);
+  for(e = altsvc->list.head; e; e = n) {
+    struct altsvc *as = e->ptr;
+    n = e->next;
+    result = altsvc_out(as, out);
+    if(result)
+      break;
+  }
+  fclose(out);
+  return result;
+}
+
+static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen)
+{
+  size_t len;
+  const char *protop;
+  const char *p = *ptr;
+  while(*p && ISBLANK(*p))
+    p++;
+  protop = p;
+  while(*p && ISALNUM(*p))
+    p++;
+  len = p - protop;
+
+  if(!len || (len >= buflen))
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  memcpy(alpnbuf, protop, len);
+  alpnbuf[len] = 0;
+  *ptr = p;
+  return CURLE_OK;
+}
+
+/* altsvc_flush() removes all alternatives for this source origin from the
+   list */
+static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
+                         const char *srchost, unsigned short srcport)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  for(e = asi->list.head; e; e = n) {
+    struct altsvc *as = e->ptr;
+    n = e->next;
+    if((srcalpnid == as->srcalpnid) &&
+       (srcport == as->srcport) &&
+       strcasecompare(srchost, as->srchost)) {
+      Curl_llist_remove(&asi->list, e, NULL);
+      altsvc_free(as);
+      asi->num--;
+    }
+  }
+}
+
+#ifdef DEBUGBUILD
+/* to play well with debug builds, we can *set* a fixed time this will
+   return */
+static time_t debugtime(void *unused)
+{
+  char *timestr = getenv("CURL_TIME");
+  (void)unused;
+  if(timestr) {
+    unsigned long val = strtol(timestr, NULL, 10);
+    return (time_t)val;
+  }
+  return time(NULL);
+}
+#define time(x) debugtime(x)
+#endif
+
+/*
+ * Curl_altsvc_parse() takes an incoming alt-svc response header and stores
+ * the data correctly in the cache.
+ *
+ * 'value' points to the header *value*. That's contents to the right of the
+ * header name.
+ */
+CURLcode Curl_altsvc_parse(struct Curl_easy *data,
+                           struct altsvcinfo *asi, const char *value,
+                           enum alpnid srcalpnid, const char *srchost,
+                           unsigned short srcport)
+{
+  const char *p = value;
+  size_t len;
+  enum alpnid dstalpnid = srcalpnid; /* the same by default */
+  char namebuf[MAX_ALTSVC_HOSTLEN] = "";
+  char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
+  struct altsvc *as;
+  unsigned short dstport = srcport; /* the same by default */
+  const char *semip;
+  time_t maxage = 24 * 3600; /* default is 24 hours */
+  bool persist = FALSE;
+  CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
+  if(result)
+    return result;
+
+  DEBUGASSERT(asi);
+
+  /* Flush all cached alternatives for this source origin, if any */
+  altsvc_flush(asi, srcalpnid, srchost, srcport);
+
+  /* "clear" is a magic keyword */
+  if(strcasecompare(alpnbuf, "clear")) {
+    return CURLE_OK;
+  }
+
+  /* The 'ma' and 'persist' flags are annoyingly meant for all alternatives
+     but are set after the list on the line. Scan for the semicolons and get
+     those fields first! */
+  semip = p;
+  do {
+    semip = strchr(semip, ';');
+    if(semip) {
+      char option[32];
+      unsigned long num;
+      char *end_ptr;
+      semip++; /* pass the semicolon */
+      result = getalnum(&semip, option, sizeof(option));
+      if(result)
+        break;
+      while(*semip && ISBLANK(*semip))
+        semip++;
+      if(*semip != '=')
+        continue;
+      semip++;
+      num = strtoul(semip, &end_ptr, 10);
+      if(num < ULONG_MAX) {
+        if(strcasecompare("ma", option))
+          maxage = num;
+        else if(strcasecompare("persist", option) && (num == 1))
+          persist = TRUE;
+      }
+      semip = end_ptr;
+    }
+  } while(semip);
+
+  do {
+    if(*p == '=') {
+      /* [protocol]="[host][:port]" */
+      dstalpnid = alpn2alpnid(alpnbuf);
+      if(!dstalpnid) {
+        infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf);
+        return CURLE_OK;
+      }
+      p++;
+      if(*p == '\"') {
+        const char *dsthost;
+        p++;
+        if(*p != ':') {
+          /* host name starts here */
+          const char *hostp = p;
+          while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
+            p++;
+          len = p - hostp;
+          if(!len || (len >= MAX_ALTSVC_HOSTLEN))
+            return CURLE_BAD_FUNCTION_ARGUMENT;
+          memcpy(namebuf, hostp, len);
+          namebuf[len] = 0;
+          dsthost = namebuf;
+        }
+        else {
+          /* no destination name, use source host */
+          dsthost = srchost;
+        }
+        if(*p == ':') {
+          /* a port number */
+          char *end_ptr;
+          unsigned long port = strtoul(++p, &end_ptr, 10);
+          if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
+            infof(data, "Unknown alt-svc port number, ignoring...\n");
+            return CURLE_OK;
+          }
+          p = end_ptr;
+          dstport = curlx_ultous(port);
+        }
+        if(*p++ != '\"')
+          return CURLE_BAD_FUNCTION_ARGUMENT;
+        as = altsvc_createid(srchost, dsthost,
+                             srcalpnid, dstalpnid,
+                             srcport, dstport);
+        if(as) {
+          /* The expires time also needs to take the Age: value (if any) into
+             account. [See RFC 7838 section 3.1] */
+          as->expires = maxage + time(NULL);
+          as->persist = persist;
+          Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
+          asi->num++; /* one more entry */
+          infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
+                Curl_alpnid2str(dstalpnid));
+        }
+      }
+      /* after the double quote there can be a comma if there's another
+         string or a semicolon if no more */
+      if(*p == ',') {
+        /* comma means another alternative is presented */
+        p++;
+        result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
+        if(result)
+          /* failed to parse, but since we already did at least one host we
+             return OK */
+          return CURLE_OK;
+      }
+    }
+  } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));
+
+  return CURLE_OK;
+}
+
+/*
+ * Return TRUE on a match
+ */
+bool Curl_altsvc_lookup(struct altsvcinfo *asi,
+                        enum alpnid srcalpnid, const char *srchost,
+                        int srcport,
+                        enum alpnid *dstalpnid, const char **dsthost,
+                        int *dstport)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  time_t now = time(NULL);
+  DEBUGASSERT(asi);
+  DEBUGASSERT(srchost);
+  DEBUGASSERT(dsthost);
+
+  for(e = asi->list.head; e; e = n) {
+    struct altsvc *as = e->ptr;
+    n = e->next;
+    if(as->expires < now) {
+      /* an expired entry, remove */
+      altsvc_free(as);
+      continue;
+    }
+    if((as->srcalpnid == srcalpnid) &&
+       strcasecompare(as->srchost, srchost) &&
+       as->srcport == srcport) {
+      /* match */
+      *dstalpnid = as->dstalpnid;
+      *dsthost = as->dsthost;
+      *dstport = as->dstport;
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */
diff --git a/lib/altsvc.h b/lib/altsvc.h
new file mode 100644
index 0000000..eefb45b
--- /dev/null
+++ b/lib/altsvc.h
@@ -0,0 +1,77 @@
+#ifndef HEADER_CURL_ALTSVC_H
+#define HEADER_CURL_ALTSVC_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC)
+#include <curl/curl.h>
+#include "llist.h"
+
+enum alpnid {
+  ALPN_none,
+  ALPN_h1,
+  ALPN_h2,
+  ALPN_h2c,
+  ALPN_h3
+};
+
+struct altsvc {
+  char *srchost;
+  char *dsthost;
+  unsigned short srcport;
+  unsigned short dstport;
+  enum alpnid srcalpnid;
+  enum alpnid dstalpnid;
+  time_t expires;
+  bool persist;
+  int prio;
+  struct curl_llist_element node;
+};
+
+struct altsvcinfo {
+  char *filename;
+  struct curl_llist list; /* list of entries */
+  size_t num; /* number of alt-svc entries */
+  long flags; /* the publicly set bitmask */
+};
+
+const char *Curl_alpnid2str(enum alpnid id);
+struct altsvcinfo *Curl_altsvc_init(void);
+CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file);
+CURLcode Curl_altsvc_save(struct altsvcinfo *asi, const char *file);
+CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl);
+void Curl_altsvc_cleanup(struct altsvcinfo *altsvc);
+CURLcode Curl_altsvc_parse(struct Curl_easy *data,
+                           struct altsvcinfo *altsvc, const char *value,
+                           enum alpnid srcalpn, const char *srchost,
+                           unsigned short srcport);
+bool Curl_altsvc_lookup(struct altsvcinfo *asi,
+                        enum alpnid srcalpnid, const char *srchost,
+                        int srcport,
+                        enum alpnid *dstalpnid, const char **dsthost,
+                        int *dstport);
+#else
+/* disabled */
+#define Curl_altsvc_save(a,b)
+#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */
+#endif /* HEADER_CURL_ALTSVC_H */
diff --git a/lib/amigaos.c b/lib/amigaos.c
index 4f55b30..cf44bdc 100644
--- a/lib/amigaos.c
+++ b/lib/amigaos.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,17 +22,26 @@
 
 #include "curl_setup.h"
 
-#if defined(__AMIGA__) && !defined(__ixemul__)
-
-#include <amitcp/socketbasetags.h>
+#ifdef __AMIGA__
+#  include "amigaos.h"
+#  if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
+#    include <amitcp/socketbasetags.h>
+#  endif
+#  ifdef __libnix__
+#    include <stabs.h>
+#  endif
+#endif
 
-#include "amigaos.h"
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
 
+#ifdef __AMIGA__
+#if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
 struct Library *SocketBase = NULL;
 extern int errno, h_errno;
 
 #ifdef __libnix__
-#include <stabs.h>
 void __request(const char *msg);
 #else
 # define __request(msg)       Printf(msg "\n\a")
@@ -74,4 +83,13 @@ bool Curl_amiga_init()
 ADD2EXIT(Curl_amiga_cleanup, -50);
 #endif
 
-#endif /* __AMIGA__ && ! __ixemul__ */
+#endif /* HAVE_PROTO_BSDSOCKET_H */
+
+#ifdef USE_AMISSL
+void Curl_amiga_X509_free(X509 *a)
+{
+  X509_free(a);
+}
+#endif /* USE_AMISSL */
+#endif /* __AMIGA__ */
+
diff --git a/lib/amigaos.h b/lib/amigaos.h
index 7c0926c..c776c9c 100644
--- a/lib/amigaos.h
+++ b/lib/amigaos.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
-#if defined(__AMIGA__) && !defined(__ixemul__)
+#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL)
 
 bool Curl_amiga_init();
 void Curl_amiga_cleanup();
@@ -35,4 +35,10 @@ void Curl_amiga_cleanup();
 
 #endif
 
+#ifdef USE_AMISSL
+#include <openssl/x509v3.h>
+void Curl_amiga_X509_free(X509 *a);
+#endif /* USE_AMISSL */
+
 #endif /* HEADER_CURL_AMIGAOS_H */
+
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index 5cfb260..8561a47 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -68,7 +68,7 @@
 #include "progress.h"
 
 #  if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
-     (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
+     (defined(WIN32) || defined(__SYMBIAN32__))
 #    define CARES_STATICLIB
 #  endif
 #  include <ares.h>
@@ -89,8 +89,20 @@ struct ResolverResults {
   int num_pending; /* number of ares_gethostbyname() requests */
   Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */
   int last_status;
+  struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
 };
 
+/* How long we are willing to wait for additional parallel responses after
+   obtaining a "definitive" one.
+
+   This is intended to equal the c-ares default timeout.  cURL always uses that
+   default value.  Unfortunately, c-ares doesn't expose its default timeout in
+   its API, but it is officially documented as 5 seconds.
+
+   See query_completed_cb() for an explanation of how this is used.
+ */
+#define HAPPY_EYEBALLS_DNS_TIMEOUT 5000
+
 /*
  * Curl_resolver_global_init() - the generic low-level asynchronous name
  * resolve API.  Called from curl_global_init() to initialize global resolver
@@ -119,6 +131,17 @@ void Curl_resolver_global_cleanup(void)
 #endif
 }
 
+
+static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd,
+                                    int readable, int writable)
+{
+  struct Curl_easy *easy = data;
+  if(!readable && !writable) {
+    DEBUGASSERT(easy);
+    Curl_multi_closed(easy, socket_fd);
+  }
+}
+
 /*
  * Curl_resolver_init()
  *
@@ -126,9 +149,14 @@ void Curl_resolver_global_cleanup(void)
  * URL-state specific environment ('resolver' member of the UrlState
  * structure).  Fills the passed pointer by the initialized ares_channel.
  */
-CURLcode Curl_resolver_init(void **resolver)
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
 {
-  int status = ares_init((ares_channel*)resolver);
+  int status;
+  struct ares_options options;
+  int optmask = ARES_OPT_SOCK_STATE_CB;
+  options.sock_state_cb = Curl_ares_sock_state_cb;
+  options.sock_state_cb_data = easy;
+  status = ares_init_options((ares_channel*)resolver, &options, optmask);
   if(status != ARES_SUCCESS) {
     if(status == ARES_ENOMEM)
       return CURLE_OUT_OF_MEMORY;
@@ -159,12 +187,15 @@ void Curl_resolver_cleanup(void *resolver)
  * environment ('resolver' member of the UrlState structure).  Duplicates the
  * 'from' ares channel and passes the resulting channel to the 'to' pointer.
  */
-int Curl_resolver_duphandle(void **to, void *from)
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
 {
-  /* Clone the ares channel for the new handle */
-  if(ARES_SUCCESS != ares_dup((ares_channel*)to, (ares_channel)from))
-    return CURLE_FAILED_INIT;
-  return CURLE_OK;
+  (void)from;
+  /*
+   * it would be better to call ares_dup instead, but right now
+   * it is not possible to set 'sock_state_cb_data' outside of
+   * ares_init_options
+   */
+  return Curl_resolver_init(easy, to);
 }
 
 static void destroy_async_data(struct Curl_async *async);
@@ -180,6 +211,17 @@ void Curl_resolver_cancel(struct connectdata *conn)
 }
 
 /*
+ * We're equivalent to Curl_resolver_cancel() for the c-ares resolver.  We
+ * never block.
+ */
+void Curl_resolver_kill(struct connectdata *conn)
+{
+  /* We don't need to check the resolver state because we can be called safely
+     at any time and we always do the same thing. */
+  Curl_resolver_cancel(conn);
+}
+
+/*
  * destroy_async_data() cleans up async resolver data.
  */
 static void destroy_async_data(struct Curl_async *async)
@@ -289,9 +331,9 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
     /* move through the descriptors and ask for processing on them */
     for(i = 0; i < num; i++)
       ares_process_fd((ares_channel)data->state.resolver,
-                      pfd[i].revents & (POLLRDNORM|POLLIN)?
+                      (pfd[i].revents & (POLLRDNORM|POLLIN))?
                       pfd[i].fd:ARES_SOCKET_BAD,
-                      pfd[i].revents & (POLLWRNORM|POLLOUT)?
+                      (pfd[i].revents & (POLLWRNORM|POLLOUT))?
                       pfd[i].fd:ARES_SOCKET_BAD);
   }
   return nfds;
@@ -317,6 +359,29 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
 
   waitperform(conn, 0);
 
+  /* Now that we've checked for any last minute results above, see if there are
+     any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
+     expires. */
+  if(res
+     && res->num_pending
+     /* This is only set to non-zero if the timer was started. */
+     && (res->happy_eyeballs_dns_time.tv_sec
+         || res->happy_eyeballs_dns_time.tv_usec)
+     && (Curl_timediff(Curl_now(), res->happy_eyeballs_dns_time)
+         >= HAPPY_EYEBALLS_DNS_TIMEOUT)) {
+    /* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer
+       running. */
+    memset(
+      &res->happy_eyeballs_dns_time, 0, sizeof(res->happy_eyeballs_dns_time));
+
+    /* Cancel the raw c-ares request, which will fire query_completed_cb() with
+       ARES_ECANCELLED synchronously for all pending responses.  This will
+       leave us with res->num_pending == 0, which is perfect for the next
+       block. */
+    ares_cancel((ares_channel)data->state.resolver);
+    DEBUGASSERT(res->num_pending == 0);
+  }
+
   if(res && !res->num_pending) {
     if(dns) {
       (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
@@ -342,13 +407,13 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
 /*
  * Curl_resolver_wait_resolv()
  *
- * waits for a resolve to finish. This function should be avoided since using
+ * Waits for a resolve to finish. This function should be avoided since using
  * this risk getting the multi interface to "hang".
  *
  * If 'entry' is non-NULL, make it point to the resolved dns entry
  *
- * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
- * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
  */
 CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                    struct Curl_dns_entry **entry)
@@ -425,9 +490,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
 
   if(result)
     /* close the connection, since we can't return failure here without
-       cleaning up this connection properly.
-       TODO: remove this action from here, it is not a name resolver decision.
-    */
+       cleaning up this connection properly. */
     connclose(conn, "c-ares resolve failed");
 
   return result;
@@ -487,6 +550,66 @@ static void query_completed_cb(void *arg,  /* (struct connectdata *) */
     /* A successful result overwrites any previous error */
     if(res->last_status != ARES_SUCCESS)
       res->last_status = status;
+
+    /* If there are responses still pending, we presume they must be the
+       complementary IPv4 or IPv6 lookups that we started in parallel in
+       Curl_resolver_getaddrinfo() (for Happy Eyeballs).  If we've got a
+       "definitive" response from one of a set of parallel queries, we need to
+       think about how long we're willing to wait for more responses. */
+    if(res->num_pending
+       /* Only these c-ares status values count as "definitive" for these
+          purposes.  For example, ARES_ENODATA is what we expect when there is
+          no IPv6 entry for a domain name, and that's not a reason to get more
+          aggressive in our timeouts for the other response.  Other errors are
+          either a result of bad input (which should affect all parallel
+          requests), local or network conditions, non-definitive server
+          responses, or us cancelling the request. */
+       && (status == ARES_SUCCESS || status == ARES_ENOTFOUND)) {
+      /* Right now, there can only be up to two parallel queries, so don't
+         bother handling any other cases. */
+      DEBUGASSERT(res->num_pending == 1);
+
+      /* It's possible that one of these parallel queries could succeed
+         quickly, but the other could always fail or timeout (when we're
+         talking to a pool of DNS servers that can only successfully resolve
+         IPv4 address, for example).
+
+         It's also possible that the other request could always just take
+         longer because it needs more time or only the second DNS server can
+         fulfill it successfully.  But, to align with the philosophy of Happy
+         Eyeballs, we don't want to wait _too_ long or users will think
+         requests are slow when IPv6 lookups don't actually work (but IPv4 ones
+         do).
+
+         So, now that we have a usable answer (some IPv4 addresses, some IPv6
+         addresses, or "no such domain"), we start a timeout for the remaining
+         pending responses.  Even though it is typical that this resolved
+         request came back quickly, that needn't be the case.  It might be that
+         this completing request didn't get a result from the first DNS server
+         or even the first round of the whole DNS server pool.  So it could
+         already be quite some time after we issued the DNS queries in the
+         first place.  Without modifying c-ares, we can't know exactly where in
+         its retry cycle we are.  We could guess based on how much time has
+         gone by, but it doesn't really matter.  Happy Eyeballs tells us that,
+         given usable information in hand, we simply don't want to wait "too
+         much longer" after we get a result.
+
+         We simply wait an additional amount of time equal to the default
+         c-ares query timeout.  That is enough time for a typical parallel
+         response to arrive without being "too long".  Even on a network
+         where one of the two types of queries is failing or timing out
+         constantly, this will usually mean we wait a total of the default
+         c-ares timeout (5 seconds) plus the round trip time for the successful
+         request, which seems bearable.  The downside is that c-ares might race
+         with us to issue one more retry just before we give up, but it seems
+         better to "waste" that request instead of trying to guess the perfect
+         timeout to prevent it.  After all, we don't even know where in the
+         c-ares retry cycle each request is.
+      */
+      res->happy_eyeballs_dns_time = Curl_now();
+      Curl_expire(
+        conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS);
+    }
   }
 }
 
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 2a59294..55e0811 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -108,8 +108,9 @@ void Curl_resolver_global_cleanup(void)
  * URL-state specific environment ('resolver' member of the UrlState
  * structure).
  */
-CURLcode Curl_resolver_init(void **resolver)
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
 {
+  (void)easy;
   *resolver = calloc(1, sizeof(struct resdata));
   if(!*resolver)
     return CURLE_OUT_OF_MEMORY;
@@ -132,10 +133,10 @@ void Curl_resolver_cleanup(void *resolver)
  * Called from curl_easy_duphandle() to duplicate resolver URL state-specific
  * environment ('resolver' member of the UrlState structure).
  */
-int Curl_resolver_duphandle(void **to, void *from)
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
 {
   (void)from;
-  return Curl_resolver_init(to);
+  return Curl_resolver_init(easy, to);
 }
 
 static void destroy_async_data(struct Curl_async *);
@@ -276,7 +277,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
   char service[12];
   int rc;
 
-  snprintf(service, sizeof(service), "%d", tsd->port);
+  msnprintf(service, sizeof(service), "%d", tsd->port);
 
   rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
 
@@ -460,23 +461,15 @@ static CURLcode resolver_error(struct connectdata *conn)
   return result;
 }
 
-/*
- * Curl_resolver_wait_resolv()
- *
- * waits for a resolve to finish. This function should be avoided since using
- * this risk getting the multi interface to "hang".
- *
- * If 'entry' is non-NULL, make it point to the resolved dns entry
- *
- * This is the version for resolves-in-a-thread.
- */
-CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
-                                   struct Curl_dns_entry **entry)
+static CURLcode thread_wait_resolv(struct connectdata *conn,
+                                   struct Curl_dns_entry **entry,
+                                   bool report)
 {
   struct thread_data   *td = (struct thread_data*) conn->async.os_specific;
   CURLcode result = CURLE_OK;
 
   DEBUGASSERT(conn && td);
+  DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
 
   /* wait for the thread to resolve the name */
   if(Curl_thread_join(&td->thread_hnd)) {
@@ -491,18 +484,55 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
   if(entry)
     *entry = conn->async.dns;
 
-  if(!conn->async.dns)
+  if(!conn->async.dns && report)
     /* a name was not resolved, report error */
     result = resolver_error(conn);
 
   destroy_async_data(&conn->async);
 
-  if(!conn->async.dns)
+  if(!conn->async.dns && report)
     connclose(conn, "asynch resolve failed");
 
   return result;
 }
 
+
+/*
+ * Until we gain a way to signal the resolver threads to stop early, we must
+ * simply wait for them and ignore their results.
+ */
+void Curl_resolver_kill(struct connectdata *conn)
+{
+  struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+
+  /* If we're still resolving, we must wait for the threads to fully clean up,
+     unfortunately.  Otherwise, we can simply cancel to clean up any resolver
+     data. */
+  if(td && td->thread_hnd != curl_thread_t_null)
+    (void)thread_wait_resolv(conn, NULL, FALSE);
+  else
+    Curl_resolver_cancel(conn);
+}
+
+/*
+ * Curl_resolver_wait_resolv()
+ *
+ * Waits for a resolve to finish. This function should be avoided since using
+ * this risk getting the multi interface to "hang".
+ *
+ * If 'entry' is non-NULL, make it point to the resolved dns entry
+ *
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
+ *
+ * This is the version for resolves-in-a-thread.
+ */
+CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+                                   struct Curl_dns_entry **entry)
+{
+  return thread_wait_resolv(conn, entry, TRUE);
+}
+
 /*
  * Curl_resolver_is_resolved() is called repeatedly to check if a previous
  * name resolve request has completed. It should also make sure to time-out if
@@ -678,7 +708,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
   hints.ai_family = pf;
   hints.ai_socktype = conn->socktype;
 
-  snprintf(sbuf, sizeof(sbuf), "%d", port);
+  msnprintf(sbuf, sizeof(sbuf), "%d", port);
 
   reslv->start = Curl_now();
   /* fire up a new resolver thread! */
diff --git a/lib/asyn.h b/lib/asyn.h
index 3adc366..ccd4b1f 100644
--- a/lib/asyn.h
+++ b/lib/asyn.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -60,7 +60,7 @@ void Curl_resolver_global_cleanup(void);
  * Returning anything else than CURLE_OK fails curl_easy_init() with the
  * correspondent code.
  */
-CURLcode Curl_resolver_init(void **resolver);
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver);
 
 /*
  * Curl_resolver_cleanup()
@@ -79,17 +79,33 @@ void Curl_resolver_cleanup(void *resolver);
  * pointer.  Returning anything else than CURLE_OK causes failed
  * curl_easy_duphandle() call.
  */
-int Curl_resolver_duphandle(void **to, void *from);
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to,
+                                 void *from);
 
 /*
  * Curl_resolver_cancel().
  *
  * It is called from inside other functions to cancel currently performing
  * resolver request. Should also free any temporary resources allocated to
- * perform a request.
+ * perform a request.  This never waits for resolver threads to complete.
+ *
+ * It is safe to call this when conn is in any state.
  */
 void Curl_resolver_cancel(struct connectdata *conn);
 
+/*
+ * Curl_resolver_kill().
+ *
+ * This acts like Curl_resolver_cancel() except it will block until any threads
+ * associated with the resolver are complete.  This never blocks for resolvers
+ * that do not use threads.  This is intended to be the "last chance" function
+ * that cleans up an in-progress resolver completely (before its owner is about
+ * to die).
+ *
+ * It is safe to call this when conn is in any state.
+ */
+void Curl_resolver_kill(struct connectdata *conn);
+
 /* Curl_resolver_getsock()
  *
  * This function is called from the multi_getsock() function.  'sock' is a
@@ -116,14 +132,13 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
 /*
  * Curl_resolver_wait_resolv()
  *
- * waits for a resolve to finish. This function should be avoided since using
+ * Waits for a resolve to finish. This function should be avoided since using
  * this risk getting the multi interface to "hang".
  *
  * If 'entry' is non-NULL, make it point to the resolved dns entry
  *
- * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
- * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
-
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
  */
 CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                    struct Curl_dns_entry **dnsentry);
@@ -147,11 +162,12 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
 #ifndef CURLRES_ASYNCH
 /* convert these functions if an asynch resolver isn't used */
 #define Curl_resolver_cancel(x) Curl_nop_stmt
+#define Curl_resolver_kill(x) Curl_nop_stmt
 #define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
 #define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
 #define Curl_resolver_getsock(x,y,z) 0
-#define Curl_resolver_duphandle(x,y) CURLE_OK
-#define Curl_resolver_init(x) CURLE_OK
+#define Curl_resolver_duphandle(x,y,z) CURLE_OK
+#define Curl_resolver_init(x,y) CURLE_OK
 #define Curl_resolver_global_init() CURLE_OK
 #define Curl_resolver_global_cleanup() Curl_nop_stmt
 #define Curl_resolver_cleanup(x) Curl_nop_stmt
diff --git a/lib/base64.c b/lib/base64.c
index 6370e4c..fb081a6 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,6 +23,11 @@
 /* Base64 encoding/decoding */
 
 #include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_LIBSSH2) || \
+  defined(USE_LIBSSH) || !defined(CURL_DISABLE_LDAP) || \
+  !defined(CURL_DISABLE_DOH) || defined(USE_SSL)
+
 #include "urldata.h" /* for the Curl_easy definition */
 #include "warnless.h"
 #include "curl_base64.h"
@@ -233,24 +238,24 @@ static CURLcode base64_encode(const char *table64,
 
     switch(inputparts) {
     case 1: /* only one byte read */
-      snprintf(output, 5, "%c%c==",
-               table64[obuf[0]],
-               table64[obuf[1]]);
+      msnprintf(output, 5, "%c%c==",
+                table64[obuf[0]],
+                table64[obuf[1]]);
       break;
 
     case 2: /* two bytes read */
-      snprintf(output, 5, "%c%c%c=",
-               table64[obuf[0]],
-               table64[obuf[1]],
-               table64[obuf[2]]);
+      msnprintf(output, 5, "%c%c%c=",
+                table64[obuf[0]],
+                table64[obuf[1]],
+                table64[obuf[2]]);
       break;
 
     default:
-      snprintf(output, 5, "%c%c%c%c",
-               table64[obuf[0]],
-               table64[obuf[1]],
-               table64[obuf[2]],
-               table64[obuf[3]]);
+      msnprintf(output, 5, "%c%c%c%c",
+                table64[obuf[0]],
+                table64[obuf[1]],
+                table64[obuf[2]],
+                table64[obuf[3]]);
       break;
     }
     output += 4;
@@ -317,3 +322,5 @@ CURLcode Curl_base64url_encode(struct Curl_easy *data,
 {
   return base64_encode(base64url, data, inputbuff, insize, outptr, outlen);
 }
+
+#endif /* no users so disabled */
diff --git a/lib/conncache.c b/lib/conncache.c
index 6fbf3b1..5350919 100644
--- a/lib/conncache.c
+++ b/lib/conncache.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus at haxx.se>
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -175,12 +175,12 @@ static void hashkey(struct connectdata *conn, char *buf,
   DEBUGASSERT(len > 32);
 
   /* put the number first so that the hostname gets cut off if too long */
-  snprintf(buf, len, "%ld%s", conn->port, hostname);
+  msnprintf(buf, len, "%ld%s", conn->port, hostname);
 }
 
-void Curl_conncache_unlock(struct connectdata *conn)
+void Curl_conncache_unlock(struct Curl_easy *data)
 {
-  CONN_UNLOCK(conn->data);
+  CONN_UNLOCK(data);
 }
 
 /* Returns number of connections currently held in the connection cache.
@@ -302,9 +302,14 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
   return result;
 }
 
-void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
+/*
+ * Removes the connectdata object from the connection cache *and* clears the
+ * ->data pointer association. Pass TRUE/FALSE in the 'lock' argument
+ * depending on if the parent function already holds the lock or not.
+ */
+void Curl_conncache_remove_conn(struct Curl_easy *data,
+                                struct connectdata *conn, bool lock)
 {
-  struct Curl_easy *data = conn->data;
   struct connectbundle *bundle = conn->bundle;
   struct conncache *connc = data->state.conn_cache;
 
@@ -323,6 +328,7 @@ void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
       DEBUGF(infof(data, "The cache now contains %zu members\n",
                    connc->num_conn));
     }
+    conn->data = NULL; /* clear the association */
     if(lock) {
       CONN_UNLOCK(data);
     }
@@ -386,8 +392,8 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
    NOTE: no locking is done here as this is presumably only done when cleaning
    up a cache!
 */
-struct connectdata *
-Curl_conncache_find_first_connection(struct conncache *connc)
+static struct connectdata *
+conncache_find_first_connection(struct conncache *connc)
 {
   struct curl_hash_iterator iter;
   struct curl_hash_element *he;
@@ -427,6 +433,8 @@ bool Curl_conncache_return_conn(struct connectdata *conn)
     data->multi->maxconnects;
   struct connectdata *conn_candidate = NULL;
 
+  conn->data = NULL; /* no owner anymore */
+  conn->lastused = Curl_now(); /* it was used up until now */
   if(maxconnects > 0 &&
      Curl_conncache_size(data) > maxconnects) {
     infof(data, "Connection cache is full, closing the oldest one.\n");
@@ -470,9 +478,9 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
   while(curr) {
     conn = curr->ptr;
 
-    if(!CONN_INUSE(conn)) {
+    if(!CONN_INUSE(conn) && !conn->data) {
       /* Set higher score for the age passed since the connection was used */
-      score = Curl_timediff(now, conn->now);
+      score = Curl_timediff(now, conn->lastused);
 
       if(score > highscore) {
         highscore = score;
@@ -528,9 +536,9 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
     while(curr) {
       conn = curr->ptr;
 
-      if(!CONN_INUSE(conn)) {
+      if(!CONN_INUSE(conn) && !conn->data) {
         /* Set higher score for the age passed since the connection was used */
-        score = Curl_timediff(now, conn->now);
+        score = Curl_timediff(now, conn->lastused);
 
         if(score > highscore) {
           highscore = score;
@@ -560,20 +568,18 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
 {
   struct connectdata *conn;
 
-  conn = Curl_conncache_find_first_connection(connc);
+  conn = conncache_find_first_connection(connc);
   while(conn) {
     SIGPIPE_VARIABLE(pipe_st);
     conn->data = connc->closure_handle;
 
     sigpipe_ignore(conn->data, &pipe_st);
-    conn->data->easy_conn = NULL; /* clear the easy handle's connection
-                                     pointer */
     /* This will remove the connection from the cache */
     connclose(conn, "kill all");
     (void)Curl_disconnect(connc->closure_handle, conn, FALSE);
     sigpipe_restore(&pipe_st);
 
-    conn = Curl_conncache_find_first_connection(connc);
+    conn = conncache_find_first_connection(connc);
   }
 
   if(connc->closure_handle) {
diff --git a/lib/conncache.h b/lib/conncache.h
index eedd7a8..35be9e0 100644
--- a/lib/conncache.h
+++ b/lib/conncache.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2015 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2015 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus at haxx.se>
  *
  * This software is licensed as described in the file COPYING, which
@@ -40,7 +40,6 @@ struct conncache {
 
 #define BUNDLE_NO_MULTIUSE -1
 #define BUNDLE_UNKNOWN     0  /* initial value */
-#define BUNDLE_PIPELINING  1
 #define BUNDLE_MULTIPLEX   2
 
 struct connectbundle {
@@ -56,7 +55,7 @@ void Curl_conncache_destroy(struct conncache *connc);
 /* return the correct bundle, to a host or a proxy */
 struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
                                                  struct conncache *connc);
-void Curl_conncache_unlock(struct connectdata *conn);
+void Curl_conncache_unlock(struct Curl_easy *data);
 /* returns number of connections currently held in the connection cache */
 size_t Curl_conncache_size(struct Curl_easy *data);
 size_t Curl_conncache_bundle_size(struct connectdata *conn);
@@ -64,7 +63,8 @@ size_t Curl_conncache_bundle_size(struct connectdata *conn);
 bool Curl_conncache_return_conn(struct connectdata *conn);
 CURLcode Curl_conncache_add_conn(struct conncache *connc,
                                  struct connectdata *conn) WARN_UNUSED_RESULT;
-void Curl_conncache_remove_conn(struct connectdata *conn,
+void Curl_conncache_remove_conn(struct Curl_easy *data,
+                                struct connectdata *conn,
                                 bool lock);
 bool Curl_conncache_foreach(struct Curl_easy *data,
                             struct conncache *connc,
diff --git a/lib/connect.c b/lib/connect.c
index 41f2202..002535b 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -357,7 +357,7 @@ static CURLcode bindlocal(struct connectdata *conn,
         conn->ip_version = CURL_IPRESOLVE_V6;
 #endif
 
-      rc = Curl_resolv(conn, dev, 0, &h);
+      rc = Curl_resolv(conn, dev, 0, FALSE, &h);
       if(rc == CURLRESOLV_PENDING)
         (void)Curl_resolver_wait_resolv(conn, &h);
       conn->ip_version = ipver;
@@ -446,9 +446,10 @@ static CURLcode bindlocal(struct connectdata *conn,
       curl_socklen_t size = sizeof(add);
       memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
       if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
+        char buffer[STRERROR_LEN];
         data->state.os_errno = error = SOCKERRNO;
         failf(data, "getsockname() failed with errno %d: %s",
-              error, Curl_strerror(conn, error));
+              error, Curl_strerror(error, buffer, sizeof(buffer)));
         return CURLE_INTERFACE_FAILED;
       }
       infof(data, "Local port: %hu\n", port);
@@ -470,10 +471,12 @@ static CURLcode bindlocal(struct connectdata *conn,
     else
       break;
   }
-
-  data->state.os_errno = error = SOCKERRNO;
-  failf(data, "bind failed with errno %d: %s",
-        error, Curl_strerror(conn, error));
+  {
+    char buffer[STRERROR_LEN];
+    data->state.os_errno = error = SOCKERRNO;
+    failf(data, "bind failed with errno %d: %s",
+          error, Curl_strerror(error, buffer, sizeof(buffer)));
+  }
 
   return CURLE_INTERFACE_FAILED;
 }
@@ -522,7 +525,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
     err = 0;
   }
 #endif
-#ifdef __minix
+#if defined(EBADIOCTL) && defined(__minix)
   /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
   if(EBADIOCTL == err) {
     SET_SOCKERRNO(0);
@@ -617,12 +620,14 @@ void Curl_persistconninfo(struct connectdata *conn)
   conn->data->info.conn_local_port = conn->local_port;
 }
 
+UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
+                             long *port);
+
 /* retrieves ip address and port from a sockaddr structure.
    note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
-bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
-                         long *port)
+UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
+                             long *port)
 {
-  unsigned short us_port;
   struct sockaddr_in *si = NULL;
 #ifdef ENABLE_IPV6
   struct sockaddr_in6 *si6 = NULL;
@@ -636,7 +641,7 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
       si = (struct sockaddr_in *)(void *) sa;
       if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
                         addr, MAX_IPADR_LEN)) {
-        us_port = ntohs(si->sin_port);
+        unsigned short us_port = ntohs(si->sin_port);
         *port = us_port;
         return TRUE;
       }
@@ -646,7 +651,7 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
       si6 = (struct sockaddr_in6 *)(void *) sa;
       if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
                         addr, MAX_IPADR_LEN)) {
-        us_port = ntohs(si6->sin6_port);
+        unsigned short us_port = ntohs(si6->sin6_port);
         *port = us_port;
         return TRUE;
       }
@@ -655,7 +660,7 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
     case AF_UNIX:
       su = (struct sockaddr_un*)sa;
-      snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
+      msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
       *port = 0;
       return TRUE;
 #endif
@@ -673,49 +678,57 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
    connection */
 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
 {
-  curl_socklen_t len;
-  struct Curl_sockaddr_storage ssrem;
-  struct Curl_sockaddr_storage ssloc;
-  struct Curl_easy *data = conn->data;
-
   if(conn->socktype == SOCK_DGRAM)
     /* there's no connection! */
     return;
 
+#if defined(HAVE_GETPEERNAME) || defined(HAVE_GETSOCKNAME)
   if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
+    struct Curl_easy *data = conn->data;
+    char buffer[STRERROR_LEN];
+    struct Curl_sockaddr_storage ssrem;
+    struct Curl_sockaddr_storage ssloc;
+    curl_socklen_t len;
+#ifdef HAVE_GETPEERNAME
     len = sizeof(struct Curl_sockaddr_storage);
     if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
       int error = SOCKERRNO;
       failf(data, "getpeername() failed with errno %d: %s",
-            error, Curl_strerror(conn, error));
+            error, Curl_strerror(error, buffer, sizeof(buffer)));
       return;
     }
-
+#endif
+#ifdef HAVE_GETSOCKNAME
     len = sizeof(struct Curl_sockaddr_storage);
     memset(&ssloc, 0, sizeof(ssloc));
     if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
       int error = SOCKERRNO;
       failf(data, "getsockname() failed with errno %d: %s",
-            error, Curl_strerror(conn, error));
+            error, Curl_strerror(error, buffer, sizeof(buffer)));
       return;
     }
-
-    if(!Curl_getaddressinfo((struct sockaddr*)&ssrem,
-                            conn->primary_ip, &conn->primary_port)) {
+#endif
+#ifdef HAVE_GETPEERNAME
+    if(!getaddressinfo((struct sockaddr*)&ssrem,
+                       conn->primary_ip, &conn->primary_port)) {
       failf(data, "ssrem inet_ntop() failed with errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       return;
     }
     memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
-
-    if(!Curl_getaddressinfo((struct sockaddr*)&ssloc,
-                            conn->local_ip, &conn->local_port)) {
+#endif
+#ifdef HAVE_GETSOCKNAME
+    if(!getaddressinfo((struct sockaddr*)&ssloc,
+                       conn->local_ip, &conn->local_port)) {
       failf(data, "ssloc inet_ntop() failed with errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       return;
     }
-
+#endif
   }
+#else /* !HAVE_GETSOCKNAME && !HAVE_GETPEERNAME */
+  (void)sockfd; /* unused */
+#endif
 
   /* persist connection info in session handle */
   Curl_persistconninfo(conn);
@@ -836,9 +849,11 @@ CURLcode Curl_is_connected(struct connectdata *conn,
       if(conn->tempaddr[i]) {
         CURLcode status;
         char ipaddress[MAX_IPADR_LEN];
+        char buffer[STRERROR_LEN];
         Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
         infof(data, "connect to %s port %ld failed: %s\n",
-              ipaddress, conn->port, Curl_strerror(conn, error));
+              ipaddress, conn->port,
+              Curl_strerror(error, buffer, sizeof(buffer)));
 
         conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
                                    allow : allow / 2;
@@ -854,8 +869,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 
   if(result) {
     /* no more addresses to try */
-
     const char *hostname;
+    char buffer[STRERROR_LEN];
 
     /* if the first address family runs out of addresses to try before
        the happy eyeball timeout, go ahead and try the next family now */
@@ -875,13 +890,14 @@ CURLcode Curl_is_connected(struct connectdata *conn,
       hostname = conn->host.name;
 
     failf(data, "Failed to connect to %s port %ld: %s",
-        hostname, conn->port, Curl_strerror(conn, error));
+          hostname, conn->port,
+          Curl_strerror(error, buffer, sizeof(buffer)));
   }
 
   return result;
 }
 
-void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
+static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
 {
 #if defined(TCP_NODELAY)
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -889,6 +905,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
 #endif
   curl_socklen_t onoff = (curl_socklen_t) 1;
   int level = IPPROTO_TCP;
+  char buffer[STRERROR_LEN];
 
 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
   (void) conn;
@@ -897,7 +914,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
   if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
                 sizeof(onoff)) < 0)
     infof(data, "Could not set TCP_NODELAY: %s\n",
-          Curl_strerror(conn, SOCKERRNO));
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
   else
     infof(data, "TCP_NODELAY set\n");
 #else
@@ -917,9 +934,11 @@ static void nosigpipe(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   int onoff = 1;
   if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
-                sizeof(onoff)) < 0)
+                sizeof(onoff)) < 0) {
+    char buffer[STRERROR_LEN];
     infof(data, "Could not set SO_NOSIGPIPE: %s\n",
-          Curl_strerror(conn, SOCKERRNO));
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
+  }
 }
 #else
 #define nosigpipe(x,y) Curl_nop_stmt
@@ -995,6 +1014,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
 #ifdef TCP_FASTOPEN_CONNECT
   int optval = 1;
 #endif
+  char buffer[STRERROR_LEN];
 
   *sockp = CURL_SOCKET_BAD;
 
@@ -1006,15 +1026,15 @@ static CURLcode singleipconnect(struct connectdata *conn,
     return CURLE_OK;
 
   /* store remote address and port used in this connection attempt */
-  if(!Curl_getaddressinfo((struct sockaddr*)&addr.sa_addr,
-                          ipaddress, &port)) {
+  if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
+                     ipaddress, &port)) {
     /* malformed address or bug in inet_ntop, try next address */
     failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     Curl_closesocket(conn, sockfd);
     return CURLE_OK;
   }
-  infof(data, "  Trying %s...\n", ipaddress);
+  infof(data, "  Trying %s:%ld...\n", ipaddress, port);
 
 #ifdef ENABLE_IPV6
   is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
@@ -1023,7 +1043,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
   is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
 #endif
   if(is_tcp && data->set.tcp_nodelay)
-    Curl_tcpnodelay(conn, sockfd);
+    tcpnodelay(conn, sockfd);
 
   nosigpipe(conn, sockfd);
 
@@ -1146,7 +1166,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
     default:
       /* unknown error, fallthrough and try another address! */
       infof(data, "Immediate connect fail for %s: %s\n",
-            ipaddress, Curl_strerror(conn, error));
+            ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
       data->state.os_errno = error;
 
       /* connect failed */
@@ -1314,7 +1334,7 @@ int Curl_closesocket(struct connectdata *conn,
       conn->sock_accepted[SECONDARYSOCKET] = FALSE;
     else {
       int rc;
-      Curl_multi_closed(conn, sock);
+      Curl_multi_closed(conn->data, sock);
       Curl_set_in_callback(conn->data, true);
       rc = conn->fclosesocket(conn->closesocket_client, sock);
       Curl_set_in_callback(conn->data, false);
@@ -1324,7 +1344,7 @@ int Curl_closesocket(struct connectdata *conn,
 
   if(conn)
     /* tell the multi-socket code about this */
-    Curl_multi_closed(conn, sock);
+    Curl_multi_closed(conn->data, sock);
 
   sclose(sock);
 
@@ -1420,7 +1440,7 @@ void Curl_conncontrol(struct connectdata *conn,
   if((ctrl == CONNCTRL_STREAM) &&
      (conn->handler->flags & PROTOPT_STREAM))
     DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
-  else if(closeit != conn->bits.close) {
+  else if((bit)closeit != conn->bits.close) {
     DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
                  closeit?"closure":"keep alive", reason));
     conn->bits.close = closeit; /* the only place in the source code that
diff --git a/lib/connect.h b/lib/connect.h
index 193dc63..6a5c755 100644
--- a/lib/connect.h
+++ b/lib/connect.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -76,11 +76,6 @@ void Curl_persistconninfo(struct connectdata *conn);
 int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
 
 /*
- * Get presentation format IP address and port from a sockaddr.
- */
-bool Curl_getaddressinfo(struct sockaddr *sa, char *addr, long *port);
-
-/*
  * The Curl_sockaddr_ex structure is basically libcurl's external API
  * curl_sockaddr structure with enough space available to directly hold any
  * protocol-specific address structures. The variable declared here will be
@@ -111,8 +106,6 @@ CURLcode Curl_socket(struct connectdata *conn,
                      struct Curl_sockaddr_ex *addr,
                      curl_socket_t *sockfd);
 
-void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd);
-
 /*
  * Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
  * argument specifies if it is the end of a connection or a stream.
diff --git a/lib/cookie.c b/lib/cookie.c
index a342c61..9a9e14d 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -93,6 +93,7 @@ Example set of cookies:
 #include "share.h"
 #include "strtoofft.h"
 #include "strcase.h"
+#include "curl_get_line.h"
 #include "curl_memrchr.h"
 #include "inet_pton.h"
 
@@ -223,7 +224,7 @@ static bool pathmatch(const char *cookie_path, const char *request_uri)
     goto pathmatched;
   }
 
-  /* here, cookie_path_len < url_path_len */
+  /* here, cookie_path_len < uri_path_len */
   if(uri_path[cookie_path_len] == '/') {
     ret = TRUE;
     goto pathmatched;
@@ -433,9 +434,10 @@ Curl_cookie_add(struct Curl_easy *data,
                 bool noexpire, /* if TRUE, skip remove_expired() */
                 char *lineptr,   /* first character of the line */
                 const char *domain, /* default domain */
-                const char *path)   /* full path used when this cookie is set,
+                const char *path,   /* full path used when this cookie is set,
                                        used to get default path for the cookie
                                        unless set */
+                bool secure)  /* TRUE if connection is over secure origin */
 {
   struct Cookie *clist;
   struct Cookie *co;
@@ -527,6 +529,19 @@ Curl_cookie_add(struct Curl_easy *data,
         while(*whatptr && ISBLANK(*whatptr))
           whatptr++;
 
+        /*
+         * Check if we have a reserved prefix set before anything else, as we
+         * otherwise have to test for the prefix in both the cookie name and
+         * "the rest". Prefixes must start with '__' and end with a '-', so
+         * only test for names where that can possibly be true.
+         */
+        if(nlen > 3 && name[0] == '_' && name[1] == '_') {
+          if(strncasecompare("__Secure-", name, 9))
+            co->prefix |= COOKIE_PREFIX__SECURE;
+          else if(strncasecompare("__Host-", name, 7))
+            co->prefix |= COOKIE_PREFIX__HOST;
+        }
+
         if(!co->name) {
           /* The very first name/value pair is the actual cookie name */
           if(!sep) {
@@ -546,8 +561,20 @@ Curl_cookie_add(struct Curl_easy *data,
           /* this was a "<name>=" with no content, and we must allow
              'secure' and 'httponly' specified this weirdly */
           done = TRUE;
-          if(strcasecompare("secure", name))
-            co->secure = TRUE;
+          /*
+           * secure cookies are only allowed to be set when the connection is
+           * using a secure protocol, or when the cookie is being set by
+           * reading from file
+           */
+          if(strcasecompare("secure", name)) {
+            if(secure || !c->running) {
+              co->secure = TRUE;
+            }
+            else {
+              badcookie = TRUE;
+              break;
+            }
+          }
           else if(strcasecompare("httponly", name))
             co->httponly = TRUE;
           else if(sep)
@@ -675,7 +702,10 @@ Curl_cookie_add(struct Curl_easy *data,
         /* overflow, used max value */
         co->expires = CURL_OFF_T_MAX;
       else if(!offt) {
-        if(CURL_OFF_T_MAX - now < co->expires)
+        if(!co->expires)
+          /* already expired */
+          co->expires = 1;
+        else if(CURL_OFF_T_MAX - now < co->expires)
           /* would overflow */
           co->expires = CURL_OFF_T_MAX;
         else
@@ -828,7 +858,13 @@ Curl_cookie_add(struct Curl_easy *data,
         fields++; /* add a field and fall down to secure */
         /* FALLTHROUGH */
       case 3:
-        co->secure = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
+        co->secure = FALSE;
+        if(strcasecompare(ptr, "TRUE")) {
+          if(secure || c->running)
+            co->secure = TRUE;
+          else
+            badcookie = TRUE;
+        }
         break;
       case 4:
         if(curlx_strtoofft(ptr, NULL, 10, &co->expires))
@@ -838,6 +874,13 @@ Curl_cookie_add(struct Curl_easy *data,
         co->name = strdup(ptr);
         if(!co->name)
           badcookie = TRUE;
+        else {
+          /* For Netscape file format cookies we check prefix on the name */
+          if(strncasecompare("__Secure-", co->name, 9))
+            co->prefix |= COOKIE_PREFIX__SECURE;
+          else if(strncasecompare("__Host-", co->name, 7))
+            co->prefix |= COOKIE_PREFIX__HOST;
+        }
         break;
       case 6:
         co->value = strdup(ptr);
@@ -866,6 +909,26 @@ Curl_cookie_add(struct Curl_easy *data,
 
   }
 
+  if(co->prefix & COOKIE_PREFIX__SECURE) {
+    /* The __Secure- prefix only requires that the cookie be set secure */
+    if(!co->secure) {
+      freecookie(co);
+      return NULL;
+    }
+  }
+  if(co->prefix & COOKIE_PREFIX__HOST) {
+    /*
+     * The __Host- prefix requires the cookie to be secure, have a "/" path
+     * and not have a domain set.
+     */
+    if(co->secure && co->path && strcmp(co->path, "/") == 0 && !co->tailmatch)
+      ;
+    else {
+      freecookie(co);
+      return NULL;
+    }
+  }
+
   if(!c->running &&    /* read from a file */
      c->newsession &&  /* clean session cookies */
      !co->expires) {   /* this is a session cookie since it doesn't expire! */
@@ -926,9 +989,31 @@ Curl_cookie_add(struct Curl_easy *data,
         /* the domains were identical */
 
         if(clist->spath && co->spath) {
-          if(strcasecompare(clist->spath, co->spath)) {
-            replace_old = TRUE;
+          if(clist->secure && !co->secure && !secure) {
+            size_t cllen;
+            const char *sep;
+
+            /*
+             * A non-secure cookie may not overlay an existing secure cookie.
+             * For an existing cookie "a" with path "/login", refuse a new
+             * cookie "a" with for example path "/login/en", while the path
+             * "/loginhelper" is ok.
+             */
+
+            sep = strchr(clist->spath + 1, '/');
+
+            if(sep)
+              cllen = sep - clist->spath;
+            else
+              cllen = strlen(clist->spath);
+
+            if(strncasecompare(clist->spath, co->spath, cllen)) {
+              freecookie(co);
+              return NULL;
+            }
           }
+          else if(strcasecompare(clist->spath, co->spath))
+            replace_old = TRUE;
           else
             replace_old = FALSE;
         }
@@ -1003,33 +1088,6 @@ Curl_cookie_add(struct Curl_easy *data,
   return co;
 }
 
-/*
- * get_line() makes sure to only return complete whole lines that fit in 'len'
- * bytes and end with a newline.
- */
-static char *get_line(char *buf, int len, FILE *input)
-{
-  bool partial = FALSE;
-  while(1) {
-    char *b = fgets(buf, len, input);
-    if(b) {
-      size_t rlen = strlen(b);
-      if(rlen && (b[rlen-1] == '\n')) {
-        if(partial) {
-          partial = FALSE;
-          continue;
-        }
-        return b;
-      }
-      /* read a partial, discard the next piece that ends with newline */
-      partial = TRUE;
-    }
-    else
-      break;
-  }
-  return NULL;
-}
-
 
 /*****************************************************************************
  *
@@ -1087,7 +1145,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
     line = malloc(MAX_COOKIE_LINE);
     if(!line)
       goto fail;
-    while(get_line(line, MAX_COOKIE_LINE, fp)) {
+    while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) {
       if(checkprefix("Set-Cookie:", line)) {
         /* This is a cookie line, get it! */
         lineptr = &line[11];
@@ -1100,7 +1158,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
       while(*lineptr && ISBLANK(*lineptr))
         lineptr++;
 
-      Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL);
+      Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
     }
     free(line); /* free the line buffer */
     remove_expired(c); /* run this once, not on every cookie */
@@ -1451,27 +1509,14 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
   struct Cookie *co;
   FILE *out;
   bool use_stdout = FALSE;
-  char *format_ptr;
-  unsigned int i;
-  unsigned int j;
-  struct Cookie **array;
 
-  if((NULL == c) || (0 == c->numcookies))
-    /* If there are no known cookies, we don't write or even create any
-       destination file */
+  if(!c)
+    /* no cookie engine alive */
     return 0;
 
   /* at first, remove expired cookies */
   remove_expired(c);
 
-  /* make sure we still have cookies after expiration */
-  if(0 == c->numcookies)
-    return 0;
-
-  array = malloc(sizeof(struct Cookie *) * c->numcookies);
-  if(!array)
-    return 1;
-
   if(!strcmp("-", dumphere)) {
     /* use stdout */
     out = stdout;
@@ -1480,7 +1525,6 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
   else {
     out = fopen(dumphere, FOPEN_WRITETEXT);
     if(!out) {
-      free(array);
       return 1; /* failure */
     }
   }
@@ -1490,32 +1534,44 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
         "# This file was generated by libcurl! Edit at your own risk.\n\n",
         out);
 
-  j = 0;
-  for(i = 0; i < COOKIE_HASH_SIZE; i++) {
-    for(co = c->cookies[i]; co; co = co->next) {
-      if(!co->domain)
-        continue;
-      array[j++] = co;
-    }
-  }
-
-  qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
+  if(c->numcookies) {
+    unsigned int i;
+    unsigned int j;
+    struct Cookie **array;
 
-  for(i = 0; i < j; i++) {
-    format_ptr = get_netscape_format(array[i]);
-    if(format_ptr == NULL) {
-      fprintf(out, "#\n# Fatal libcurl error\n");
-      free(array);
+    array = malloc(sizeof(struct Cookie *) * c->numcookies);
+    if(!array) {
       if(!use_stdout)
         fclose(out);
       return 1;
     }
-    fprintf(out, "%s\n", format_ptr);
-    free(format_ptr);
-  }
 
-  free(array);
+    j = 0;
+    for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+      for(co = c->cookies[i]; co; co = co->next) {
+        if(!co->domain)
+          continue;
+        array[j++] = co;
+      }
+    }
+
+    qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
 
+    for(i = 0; i < j; i++) {
+      char *format_ptr = get_netscape_format(array[i]);
+      if(format_ptr == NULL) {
+        fprintf(out, "#\n# Fatal libcurl error\n");
+        free(array);
+        if(!use_stdout)
+          fclose(out);
+        return 1;
+      }
+      fprintf(out, "%s\n", format_ptr);
+      free(format_ptr);
+    }
+
+    free(array);
+  }
   if(!use_stdout)
     fclose(out);
 
diff --git a/lib/cookie.h b/lib/cookie.h
index a9f90ca..b2730cf 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -44,8 +44,16 @@ struct Cookie {
   bool livecookie;   /* updated from a server, not a stored file */
   bool httponly;     /* true if the httponly directive is present */
   int creationtime;  /* time when the cookie was written */
+  unsigned char prefix; /* bitmap fields indicating which prefix are set */
 };
 
+/*
+ * Available cookie prefixes, as defined in
+ * draft-ietf-httpbis-rfc6265bis-02
+ */
+#define COOKIE_PREFIX__SECURE (1<<0)
+#define COOKIE_PREFIX__HOST (1<<1)
+
 #define COOKIE_HASH_SIZE 256
 
 struct CookieInfo {
@@ -85,7 +93,8 @@ struct Curl_easy;
 struct Cookie *Curl_cookie_add(struct Curl_easy *data,
                                struct CookieInfo *, bool header, bool noexpiry,
                                char *lineptr,
-                               const char *domain, const char *path);
+                               const char *domain, const char *path,
+                               bool secure);
 
 struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
                                    const char *, bool);
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
index fd49679..16c4779 100644
--- a/lib/curl_addrinfo.c
+++ b/lib/curl_addrinfo.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -539,7 +539,7 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) &&  \
   defined(HAVE_FREEADDRINFO)
 /*
- * curl_dofreeaddrinfo()
+ * curl_dbg_freeaddrinfo()
  *
  * This is strictly for memory tracing and are using the same style as the
  * family otherwise present in memdebug.c. I put these ones here since they
@@ -547,23 +547,23 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
  */
 
 void
-curl_dofreeaddrinfo(struct addrinfo *freethis,
-                    int line, const char *source)
+curl_dbg_freeaddrinfo(struct addrinfo *freethis,
+                      int line, const char *source)
 {
+  curl_dbg_log("ADDR %s:%d freeaddrinfo(%p)\n",
+               source, line, (void *)freethis);
 #ifdef USE_LWIPSOCK
   lwip_freeaddrinfo(freethis);
 #else
   (freeaddrinfo)(freethis);
 #endif
-  curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n",
-              source, line, (void *)freethis);
 }
 #endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */
 
 
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
 /*
- * curl_dogetaddrinfo()
+ * curl_dbg_getaddrinfo()
  *
  * This is strictly for memory tracing and are using the same style as the
  * family otherwise present in memdebug.c. I put these ones here since they
@@ -571,11 +571,11 @@ curl_dofreeaddrinfo(struct addrinfo *freethis,
  */
 
 int
-curl_dogetaddrinfo(const char *hostname,
-                   const char *service,
-                   const struct addrinfo *hints,
-                   struct addrinfo **result,
-                   int line, const char *source)
+curl_dbg_getaddrinfo(const char *hostname,
+                    const char *service,
+                    const struct addrinfo *hints,
+                    struct addrinfo **result,
+                    int line, const char *source)
 {
 #ifdef USE_LWIPSOCK
   int res = lwip_getaddrinfo(hostname, service, hints, result);
@@ -584,11 +584,11 @@ curl_dogetaddrinfo(const char *hostname,
 #endif
   if(0 == res)
     /* success */
-    curl_memlog("ADDR %s:%d getaddrinfo() = %p\n",
-                source, line, (void *)*result);
+    curl_dbg_log("ADDR %s:%d getaddrinfo() = %p\n",
+                 source, line, (void *)*result);
   else
-    curl_memlog("ADDR %s:%d getaddrinfo() failed\n",
-                source, line);
+    curl_dbg_log("ADDR %s:%d getaddrinfo() failed\n",
+                 source, line);
   return res;
 }
 #endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */
diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h
index 8f6f3d1..205e121 100644
--- a/lib/curl_addrinfo.h
+++ b/lib/curl_addrinfo.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -86,17 +86,14 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract);
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
     defined(HAVE_FREEADDRINFO)
 void
-curl_dofreeaddrinfo(struct addrinfo *freethis,
-                    int line, const char *source);
+curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line, const char *source);
 #endif
 
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
 int
-curl_dogetaddrinfo(const char *hostname,
-                   const char *service,
-                   const struct addrinfo *hints,
-                   struct addrinfo **result,
-                   int line, const char *source);
+curl_dbg_getaddrinfo(const char *hostname, const char *service,
+                     const struct addrinfo *hints, struct addrinfo **result,
+                     int line, const char *source);
 #endif
 
 #ifdef HAVE_GETADDRINFO
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index 5308eb5..9ac64f6 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -235,6 +235,12 @@
 /* Define to 1 if you have the `getprotobyname' function. */
 #cmakedefine HAVE_GETPROTOBYNAME 1
 
+/* Define to 1 if you have the `getpeername' function. */
+#cmakedefine HAVE_GETPEERNAME 1
+
+/* Define to 1 if you have the `getsockname' function. */
+#cmakedefine HAVE_GETSOCKNAME 1
+
 /* Define to 1 if you have the `getpwuid' function. */
 #cmakedefine HAVE_GETPWUID 1
 
@@ -930,8 +936,8 @@
 /* if PolarSSL is enabled */
 #cmakedefine USE_POLARSSL 1
 
-/* if DarwinSSL is enabled */
-#cmakedefine USE_DARWINSSL 1
+/* if Secure Transport is enabled */
+#cmakedefine USE_SECTRANSP 1
 
 /* if mbedTLS is enabled */
 #cmakedefine USE_MBEDTLS 1
diff --git a/lib/curl_endian.c b/lib/curl_endian.c
index c25db49..b7563b3 100644
--- a/lib/curl_endian.c
+++ b/lib/curl_endian.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -82,7 +82,7 @@ unsigned short Curl_read16_be(const unsigned char *buf)
 }
 
 /*
- * Curl_write32_le()
+ * write32_le()
  *
  * This function converts a 32-bit integer from the native endian format,
  * to little endian format ready for sending down the wire.
@@ -92,7 +92,7 @@ unsigned short Curl_read16_be(const unsigned char *buf)
  * value    [in]     - The 32-bit integer value.
  * buffer   [in]     - A pointer to the output buffer.
  */
-void Curl_write32_le(const int value, unsigned char *buffer)
+static void write32_le(const int value, unsigned char *buffer)
 {
   buffer[0] = (char)(value & 0x000000FF);
   buffer[1] = (char)((value & 0x0000FF00) >> 8);
@@ -118,7 +118,7 @@ void Curl_write64_le(const long long value, unsigned char *buffer)
 void Curl_write64_le(const __int64 value, unsigned char *buffer)
 #endif
 {
-  Curl_write32_le((int)value, buffer);
-  Curl_write32_le((int)(value >> 32), buffer + 4);
+  write32_le((int)value, buffer);
+  write32_le((int)(value >> 32), buffer + 4);
 }
 #endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c
index fbfd85c..ab3e742 100644
--- a/lib/curl_fnmatch.c
+++ b/lib/curl_fnmatch.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
  ***************************************************************************/
 
 #include "curl_setup.h"
-
+#ifndef CURL_DISABLE_FTP
 #include <curl/curl.h>
 
 #include "curl_fnmatch.h"
@@ -32,15 +32,6 @@
 
 #ifndef HAVE_FNMATCH
 
-/*
- * TODO:
- *
- * Make this function match POSIX. Test 1307 includes a set of test patterns
- * that returns different results with a POSIX fnmatch() than with this
- * implementation and this is considered a bug where POSIX is the guiding
- * light.
- */
-
 #define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
 #define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
 
@@ -394,3 +385,5 @@ int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
 }
 
 #endif
+
+#endif /* if FTP is disabled */
diff --git a/lib/fileinfo.c b/lib/curl_get_line.c
similarity index 61%
copy from lib/fileinfo.c
copy to lib/curl_get_line.c
index 4e72e1e..c419485 100644
--- a/lib/fileinfo.c
+++ b/lib/curl_get_line.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,22 +22,34 @@
 
 #include "curl_setup.h"
 
-#include "strdup.h"
-#include "fileinfo.h"
+#include "curl_get_line.h"
 #include "curl_memory.h"
 /* The last #include file should be: */
 #include "memdebug.h"
 
-struct fileinfo *Curl_fileinfo_alloc(void)
+/*
+ * get_line() makes sure to only return complete whole lines that fit in 'len'
+ * bytes and end with a newline.
+ */
+char *Curl_get_line(char *buf, int len, FILE *input)
 {
-  return calloc(1, sizeof(struct fileinfo));
-}
-
-void Curl_fileinfo_cleanup(struct fileinfo *finfo)
-{
-  if(!finfo)
-    return;
-
-  Curl_safefree(finfo->info.b_data);
-  free(finfo);
+  bool partial = FALSE;
+  while(1) {
+    char *b = fgets(buf, len, input);
+    if(b) {
+      size_t rlen = strlen(b);
+      if(rlen && (b[rlen-1] == '\n')) {
+        if(partial) {
+          partial = FALSE;
+          continue;
+        }
+        return b;
+      }
+      /* read a partial, discard the next piece that ends with newline */
+      partial = TRUE;
+    }
+    else
+      break;
+  }
+  return NULL;
 }
diff --git a/lib/vtls/axtls.h b/lib/curl_get_line.h
similarity index 73%
rename from lib/vtls/axtls.h
rename to lib/curl_get_line.h
index cb81872..532ab08 100644
--- a/lib/vtls/axtls.h
+++ b/lib/curl_get_line.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_AXTLS_H
-#define HEADER_CURL_AXTLS_H
+#ifndef HEADER_CURL_GET_LINE_H
+#define HEADER_CURL_GET_LINE_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,8 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2010, DirecTV, Contact: Eric Hu <ehu at directv.com>
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,11 +22,8 @@
  *
  ***************************************************************************/
 
-#ifdef USE_AXTLS
-#include "curl/curl.h"
-#include "urldata.h"
+/* get_line() makes sure to only return complete whole lines that fit in 'len'
+ * bytes and end with a newline. */
+char *Curl_get_line(char *buf, int len, FILE *input);
 
-extern const struct Curl_ssl Curl_ssl_axtls;
-
-#endif /* USE_AXTLS */
-#endif /* HEADER_CURL_AXTLS_H */
+#endif /* HEADER_CURL_GET_LINE_H */
diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c
index f007986..d854ab0 100644
--- a/lib/curl_gssapi.c
+++ b/lib/curl_gssapi.c
@@ -97,9 +97,9 @@ static size_t display_gss_error(OM_uint32 status, int type,
                                   &msg_ctx,
                                   &status_string);
     if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
-      len += snprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
-                      "%.*s. ", (int)status_string.length,
-                      (char *)status_string.value);
+      len += msnprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
+                       "%.*s. ", (int)status_string.length,
+                       (char *)status_string.value);
     }
     gss_release_buffer(&min_stat, &status_string);
   } while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
diff --git a/lib/curl_gssapi.h b/lib/curl_gssapi.h
index 9700a28..88f68db 100644
--- a/lib/curl_gssapi.h
+++ b/lib/curl_gssapi.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2011 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2011 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -26,19 +26,6 @@
 #include "urldata.h"
 
 #ifdef HAVE_GSSAPI
-
-#ifdef HAVE_GSSGNU
-#  include <gss.h>
-#elif defined HAVE_GSSMIT
-   /* MIT style */
-#  include <gssapi/gssapi.h>
-#  include <gssapi/gssapi_generic.h>
-#  include <gssapi/gssapi_krb5.h>
-#else
-   /* Heimdal-style */
-#  include <gssapi.h>
-#endif
-
 extern gss_OID_desc Curl_spnego_mech_oid;
 extern gss_OID_desc Curl_krb5_mech_oid;
 
@@ -71,5 +58,4 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
 #define GSSAUTH_P_PRIVACY   4
 
 #endif /* HAVE_GSSAPI */
-
 #endif /* HEADER_CURL_GSSAPI_H */
diff --git a/lib/curl_md4.h b/lib/curl_md4.h
index e069041..392203f 100644
--- a/lib/curl_md4.h
+++ b/lib/curl_md4.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -25,11 +25,13 @@
 #include "curl_setup.h"
 
 #if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
 
 void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
 
 #endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) ||
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
 
 #endif /* HEADER_CURL_MD4_H */
diff --git a/lib/curl_md5.h b/lib/curl_md5.h
index 5f70c96..aaf25f6 100644
--- a/lib/curl_md5.h
+++ b/lib/curl_md5.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -53,10 +53,10 @@ void Curl_md5it(unsigned char *output,
                 const unsigned char *input);
 
 MD5_context * Curl_MD5_init(const MD5_params *md5params);
-int Curl_MD5_update(MD5_context *context,
-                    const unsigned char *data,
-                    unsigned int len);
-int Curl_MD5_final(MD5_context *context, unsigned char *result);
+CURLcode Curl_MD5_update(MD5_context *context,
+                         const unsigned char *data,
+                         unsigned int len);
+CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result);
 
 #endif
 
diff --git a/lib/curl_memory.h b/lib/curl_memory.h
index fccf468..ce38a08 100644
--- a/lib/curl_memory.h
+++ b/lib/curl_memory.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -39,7 +39,7 @@
  *
  * File lib/strdup.c is an exception, given that it provides a strdup
  * clone implementation while using malloc. Extra care needed inside
- * this one. TODO: revisit this paragraph and related code.
+ * this one.
  *
  * The need for curl_memory.h inclusion is due to libcurl's feature
  * of allowing library user to provide memory replacement functions,
diff --git a/lib/curl_multibyte.c b/lib/curl_multibyte.c
index e78bb50..e48334f 100644
--- a/lib/curl_multibyte.c
+++ b/lib/curl_multibyte.c
@@ -64,13 +64,13 @@ char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
   char *str_utf8 = NULL;
 
   if(str_w) {
-    int str_utf8_len = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL,
-                                           0, NULL, NULL);
-    if(str_utf8_len > 0) {
-      str_utf8 = malloc(str_utf8_len * sizeof(wchar_t));
+    int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, -1,
+                                    NULL, 0, NULL, NULL);
+    if(bytes > 0) {
+      str_utf8 = malloc(bytes);
       if(str_utf8) {
-        if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len,
-                               NULL, FALSE) == 0) {
+        if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, bytes,
+                               NULL, NULL) == 0) {
           free(str_utf8);
           return NULL;
         }
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
index 922e85a..b6df38f 100644
--- a/lib/curl_ntlm_core.c
+++ b/lib/curl_ntlm_core.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -38,7 +38,7 @@
    3. USE_GNUTLS
    4. USE_NSS
    5. USE_MBEDTLS
-   6. USE_DARWINSSL
+   6. USE_SECTRANSP
    7. USE_OS400CRYPTO
    8. USE_WIN32_CRYPTO
 
@@ -54,23 +54,15 @@
 
 #ifdef USE_OPENSSL
 
-#  ifdef USE_OPENSSL
-#    include <openssl/des.h>
-#    ifndef OPENSSL_NO_MD4
-#      include <openssl/md4.h>
-#    endif
-#    include <openssl/md5.h>
-#    include <openssl/ssl.h>
-#    include <openssl/rand.h>
+#  include <openssl/des.h>
+#  ifndef OPENSSL_NO_MD4
+#    include <openssl/md4.h>
 #  else
-#    include <des.h>
-#    ifndef OPENSSL_NO_MD4
-#      include <md4.h>
-#    endif
-#    include <md5.h>
-#    include <ssl.h>
-#    include <rand.h>
+#    include "curl_md4.h"
 #  endif
+#  include <openssl/md5.h>
+#  include <openssl/ssl.h>
+#  include <openssl/rand.h>
 #  if (OPENSSL_VERSION_NUMBER < 0x00907001L)
 #    define DES_key_schedule des_key_schedule
 #    define DES_cblock des_cblock
@@ -111,7 +103,7 @@
 #    include "curl_md4.h"
 #  endif
 
-#elif defined(USE_DARWINSSL)
+#elif defined(USE_SECTRANSP)
 
 #  include <CommonCrypto/CommonCryptor.h>
 #  include <CommonCrypto/CommonDigest.h>
@@ -300,7 +292,7 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out,
   return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
 }
 
-#elif defined(USE_DARWINSSL)
+#elif defined(USE_SECTRANSP)
 
 static bool encrypt_des(const unsigned char *in, unsigned char *out,
                         const unsigned char *key_56)
@@ -447,7 +439,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
   setup_des_key(keys + 14, &des);
   gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
   gcry_cipher_close(des);
-#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \
+#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
   encrypt_des(plaintext, results, keys);
   encrypt_des(plaintext, results + 8, keys + 7);
@@ -511,7 +503,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
     setup_des_key(pw + 7, &des);
     gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
     gcry_cipher_close(des);
-#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \
+#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
     encrypt_des(magic, lmbuffer, pw);
     encrypt_des(magic, lmbuffer + 8, pw + 7);
@@ -578,10 +570,14 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
   {
     /* Create NT hashed password. */
 #ifdef USE_OPENSSL
+#if !defined(OPENSSL_NO_MD4)
     MD4_CTX MD4pw;
     MD4_Init(&MD4pw);
     MD4_Update(&MD4pw, pw, 2 * len);
     MD4_Final(ntbuffer, &MD4pw);
+#else
+    Curl_md4it(ntbuffer, pw, 2 * len);
+#endif
 #elif defined(USE_GNUTLS_NETTLE)
     struct md4_ctx MD4pw;
     md4_init(&MD4pw);
@@ -601,7 +597,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
 #else
     Curl_md4it(ntbuffer, pw, 2 * len);
 #endif
-#elif defined(USE_DARWINSSL)
+#elif defined(USE_SECTRANSP)
     (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
 #elif defined(USE_OS400CRYPTO)
     Curl_md4it(ntbuffer, pw, 2 * len);
@@ -631,9 +627,9 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
 #if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
 
 /* This returns the HMAC MD5 digest */
-CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
-                       const unsigned char *data, unsigned int datalen,
-                       unsigned char *output)
+static CURLcode hmac_md5(const unsigned char *key, unsigned int keylen,
+                         const unsigned char *data, unsigned int datalen,
+                         unsigned char *output)
 {
   HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen);
 
@@ -678,9 +674,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
   ascii_uppercase_to_unicode_le(identity, user, userlen);
   ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
 
-  result = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
-                         ntlmv2hash);
-
+  result = hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
+                    ntlmv2hash);
   free(identity);
 
   return result;
@@ -753,12 +748,12 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
     return CURLE_OUT_OF_MEMORY;
 
   /* Create the BLOB structure */
-  snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
-           "%c%c%c%c"   /* NTLMv2_BLOB_SIGNATURE */
-           "%c%c%c%c",  /* Reserved = 0 */
-           NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
-           NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
-           0, 0, 0, 0);
+  msnprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
+            "%c%c%c%c"   /* NTLMv2_BLOB_SIGNATURE */
+            "%c%c%c%c",  /* Reserved = 0 */
+            NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
+            NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
+            0, 0, 0, 0);
 
   Curl_write64_le(tw, ptr + 24);
   memcpy(ptr + 32, challenge_client, 8);
@@ -766,8 +761,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
 
   /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
   memcpy(ptr + 8, &ntlm->nonce[0], 8);
-  result = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
-                         NTLMv2_BLOB_LEN + 8, hmac_output);
+  result = hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
+                    NTLMv2_BLOB_LEN + 8, hmac_output);
   if(result) {
     free(ptr);
     return result;
@@ -809,7 +804,7 @@ CURLcode  Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
   memcpy(&data[0], challenge_server, 8);
   memcpy(&data[8], challenge_client, 8);
 
-  result = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
+  result = hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
   if(result)
     return result;
 
diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h
index 07ef5de..3b4b805 100644
--- a/lib/curl_ntlm_core.h
+++ b/lib/curl_ntlm_core.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -43,9 +43,7 @@
 
 /* Define USE_NTRESPONSES in order to make the type-3 message include
  * the NT response message. */
-#if !defined(USE_OPENSSL) || !defined(OPENSSL_NO_MD4)
 #define USE_NTRESPONSES
-#endif
 
 /* Define USE_NTLM2SESSION in order to make the type-3 message include the
    NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a
diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c
index a4791eb..80266e2 100644
--- a/lib/curl_ntlm_wb.c
+++ b/lib/curl_ntlm_wb.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -53,6 +53,8 @@
 #include "url.h"
 #include "strerror.h"
 #include "strdup.h"
+#include "strcase.h"
+
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -74,7 +76,7 @@
 #  define sclose_nolog(x)  close((x))
 #endif
 
-void Curl_ntlm_wb_cleanup(struct connectdata *conn)
+void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn)
 {
   if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
     sclose(conn->ntlm_auth_hlpr_socket);
@@ -124,6 +126,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
   struct passwd pw, *pw_res;
   char pwbuf[1024];
 #endif
+  char buffer[STRERROR_LEN];
 
   /* Return if communication with ntlm_auth already set up */
   if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
@@ -179,13 +182,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
 
   if(access(ntlm_auth, X_OK) != 0) {
     failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s",
-          ntlm_auth, errno, Curl_strerror(conn, errno));
+          ntlm_auth, errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
   }
 
   if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
     failf(conn->data, "Could not open socket pair. errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
   }
 
@@ -194,7 +197,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
     sclose(sockfds[0]);
     sclose(sockfds[1]);
     failf(conn->data, "Could not fork. errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
   }
   else if(!child_pid) {
@@ -206,13 +209,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
     sclose_nolog(sockfds[0]);
     if(dup2(sockfds[1], STDIN_FILENO) == -1) {
       failf(conn->data, "Could not redirect child stdin. errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       exit(1);
     }
 
     if(dup2(sockfds[1], STDOUT_FILENO) == -1) {
       failf(conn->data, "Could not redirect child stdout. errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       exit(1);
     }
 
@@ -232,7 +235,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
 
     sclose_nolog(sockfds[1]);
     failf(conn->data, "Could not execl(). errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     exit(1);
   }
 
@@ -332,6 +335,48 @@ done:
   return CURLE_REMOTE_ACCESS_DENIED;
 }
 
+CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
+                            bool proxy,
+                            const char *header)
+{
+  curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
+
+  if(!checkprefix("NTLM", header))
+    return CURLE_BAD_CONTENT_ENCODING;
+
+  header += strlen("NTLM");
+  while(*header && ISSPACE(*header))
+    header++;
+
+  if(*header) {
+    conn->challenge_header = strdup(header);
+    if(!conn->challenge_header)
+      return CURLE_OUT_OF_MEMORY;
+
+    *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
+  }
+  else {
+    if(*state == NTLMSTATE_LAST) {
+      infof(conn->data, "NTLM auth restarted\n");
+      Curl_http_auth_cleanup_ntlm_wb(conn);
+    }
+    else if(*state == NTLMSTATE_TYPE3) {
+      infof(conn->data, "NTLM handshake rejected\n");
+      Curl_http_auth_cleanup_ntlm_wb(conn);
+      *state = NTLMSTATE_NONE;
+      return CURLE_REMOTE_ACCESS_DENIED;
+    }
+    else if(*state >= NTLMSTATE_TYPE1) {
+      infof(conn->data, "NTLM handshake failure (internal error)\n");
+      return CURLE_REMOTE_ACCESS_DENIED;
+    }
+
+    *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
+  }
+
+  return CURLE_OK;
+}
+
 /*
  * This is for creating ntlm header output by delegating challenge/response
  * to Samba's winbind daemon helper ntlm_auth.
@@ -344,8 +389,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   char **allocuserpwd;
   /* point to the name and password for this */
   const char *userp;
-  /* point to the correct struct with this */
-  struct ntlmdata *ntlm;
+  curlntlm *state;
   struct auth *authp;
 
   CURLcode res = CURLE_OK;
@@ -357,13 +401,13 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   if(proxy) {
     allocuserpwd = &conn->allocptr.proxyuserpwd;
     userp = conn->http_proxy.user;
-    ntlm = &conn->proxyntlm;
+    state = &conn->proxy_ntlm_state;
     authp = &conn->data->state.authproxy;
   }
   else {
     allocuserpwd = &conn->allocptr.userpwd;
     userp = conn->user;
-    ntlm = &conn->ntlm;
+    state = &conn->http_ntlm_state;
     authp = &conn->data->state.authhost;
   }
   authp->done = FALSE;
@@ -372,7 +416,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   if(!userp)
     userp = "";
 
-  switch(ntlm->state) {
+  switch(*state) {
   case NTLMSTATE_TYPE1:
   default:
     /* Use Samba's 'winbind' daemon to support NTLM authentication,
@@ -391,7 +435,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
     res = ntlm_wb_init(conn, userp);
     if(res)
       return res;
-    res = ntlm_wb_response(conn, "YR\n", ntlm->state);
+    res = ntlm_wb_response(conn, "YR\n", *state);
     if(res)
       return res;
 
@@ -405,11 +449,12 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
       return CURLE_OUT_OF_MEMORY;
     conn->response_header = NULL;
     break;
+
   case NTLMSTATE_TYPE2:
     input = aprintf("TT %s\n", conn->challenge_header);
     if(!input)
       return CURLE_OUT_OF_MEMORY;
-    res = ntlm_wb_response(conn, input, ntlm->state);
+    res = ntlm_wb_response(conn, input, *state);
     free(input);
     input = NULL;
     if(res)
@@ -420,17 +465,20 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
                             proxy ? "Proxy-" : "",
                             conn->response_header);
     DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
-    ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
+    *state = NTLMSTATE_TYPE3; /* we sent a type-3 */
     authp->done = TRUE;
-    Curl_ntlm_wb_cleanup(conn);
+    Curl_http_auth_cleanup_ntlm_wb(conn);
     if(!*allocuserpwd)
       return CURLE_OUT_OF_MEMORY;
     break;
+
   case NTLMSTATE_TYPE3:
     /* connection is already authenticated,
      * don't send a header in future requests */
-    free(*allocuserpwd);
-    *allocuserpwd = NULL;
+    *state = NTLMSTATE_LAST;
+    /* FALLTHROUGH */
+  case NTLMSTATE_LAST:
+    Curl_safefree(*allocuserpwd);
     authp->done = TRUE;
     break;
   }
diff --git a/lib/curl_ntlm_wb.h b/lib/curl_ntlm_wb.h
index aba3d46..3cf841c 100644
--- a/lib/curl_ntlm_wb.h
+++ b/lib/curl_ntlm_wb.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -27,11 +27,14 @@
 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
     defined(NTLM_WB_ENABLED)
 
-/* this is for creating ntlm header output by delegating challenge/response
-   to Samba's winbind daemon helper ntlm_auth */
+/* this is for ntlm header input */
+CURLcode Curl_input_ntlm_wb(struct connectdata *conn, bool proxy,
+                            const char *header);
+
+/* this is for creating ntlm header output */
 CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy);
 
-void Curl_ntlm_wb_cleanup(struct connectdata *conn);
+void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn);
 
 #endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */
 
diff --git a/lib/curl_path.c b/lib/curl_path.c
index 68f3e44..85dddce 100644
--- a/lib/curl_path.c
+++ b/lib/curl_path.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,8 @@
 
 #include "curl_setup.h"
 
+#if defined(USE_SSH)
+
 #include <curl/curl.h>
 #include "curl_memory.h"
 #include "curl_path.h"
@@ -193,3 +195,5 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
   Curl_safefree(*path);
   return CURLE_QUOTE_ERROR;
 }
+
+#endif /* if SSH is used */
diff --git a/lib/curl_printf.h b/lib/curl_printf.h
index 49857cd..0d37b8e 100644
--- a/lib/curl_printf.h
+++ b/lib/curl_printf.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
 
 # undef printf
 # undef fprintf
-# undef snprintf
+# undef msnprintf
 # undef vprintf
 # undef vfprintf
 # undef vsnprintf
@@ -39,18 +39,10 @@
 # undef vaprintf
 # define printf curl_mprintf
 # define fprintf curl_mfprintf
-# define snprintf curl_msnprintf
+# define msnprintf curl_msnprintf
 # define vprintf curl_mvprintf
 # define vfprintf curl_mvfprintf
-# define vsnprintf curl_mvsnprintf
+# define mvsnprintf curl_mvsnprintf
 # define aprintf curl_maprintf
 # define vaprintf curl_mvaprintf
-
-/* We define away the sprintf functions unconditonally since we don't want
-   internal code to be using them, intentionally or by mistake!*/
-# undef sprintf
-# undef vsprintf
-# define sprintf sprintf_was_used
-# define vsprintf vsprintf_was_used
-
 #endif /* HEADER_CURL_PRINTF_H */
diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c
index f09f2f3..16b1de1 100644
--- a/lib/curl_rtmp.c
+++ b/lib/curl_rtmp.c
@@ -5,7 +5,7 @@
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  * Copyright (C) 2010, Howard Chu, <hyc at highlandsun.com>
  *
  * This software is licensed as described in the file COPYING, which
@@ -239,17 +239,18 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
 
 static CURLcode rtmp_do(struct connectdata *conn, bool *done)
 {
+  struct Curl_easy *data = conn->data;
   RTMP *r = conn->proto.generic;
 
   if(!RTMP_ConnectStream(r, 0))
     return CURLE_FAILED_INIT;
 
   if(conn->data->set.upload) {
-    Curl_pgrsSetUploadSize(conn->data, conn->data->state.infilesize);
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+    Curl_pgrsSetUploadSize(data, data->state.infilesize);
+    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
   }
   else
-    Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   *done = TRUE;
   return CURLE_OK;
 }
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index 354bc54..018e422 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -31,6 +31,9 @@
 
 #include "curl_setup.h"
 
+#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \
+  !defined(CURL_DISABLE_POP3)
+
 #include <curl/curl.h>
 #include "urldata.h"
 
@@ -83,14 +86,14 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
 #if defined(USE_KERBEROS5)
   /* Cleanup the gssapi structure */
   if(authused == SASL_MECH_GSSAPI) {
-    Curl_auth_gssapi_cleanup(&conn->krb5);
+    Curl_auth_cleanup_gssapi(&conn->krb5);
   }
 #endif
 
 #if defined(USE_NTLM)
   /* Cleanup the NTLM structure */
   if(authused == SASL_MECH_NTLM) {
-    Curl_auth_ntlm_cleanup(&conn->ntlm);
+    Curl_auth_cleanup_ntlm(&conn->ntlm);
   }
 #endif
 
@@ -290,7 +293,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
 #if defined(USE_KERBEROS5)
     if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() &&
        Curl_auth_user_contains_domain(conn->user)) {
-      sasl->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */
+      sasl->mutual_auth = FALSE;
       mech = SASL_MECH_STRING_GSSAPI;
       state1 = SASL_GSSAPI;
       state2 = SASL_GSSAPI_TOKEN;
@@ -300,8 +303,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
         result = Curl_auth_create_gssapi_user_message(data, conn->user,
                                                       conn->passwd,
                                                       service,
-                                                      data->easy_conn->
-                                                            host.name,
+                                                      data->conn->host.name,
                                                       sasl->mutual_auth,
                                                       NULL, &conn->krb5,
                                                       &resp, &len);
@@ -358,10 +360,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
       sasl->authused = SASL_MECH_XOAUTH2;
 
       if(force_ir || data->set.sasl_ir)
-        result = Curl_auth_create_oauth_bearer_message(data, conn->user,
-                                                       NULL, 0,
-                                                       conn->oauth_bearer,
-                                                       &resp, &len);
+        result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
+                                                        conn->oauth_bearer,
+                                                        &resp, &len);
     }
     else if(enabledmechs & SASL_MECH_PLAIN) {
       mech = SASL_MECH_STRING_PLAIN;
@@ -369,8 +370,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
       sasl->authused = SASL_MECH_PLAIN;
 
       if(force_ir || data->set.sasl_ir)
-        result = Curl_auth_create_plain_message(data, conn->user, conn->passwd,
-                                                &resp, &len);
+        result = Curl_auth_create_plain_message(data, NULL, conn->user,
+                                                conn->passwd, &resp, &len);
     }
     else if(enabledmechs & SASL_MECH_LOGIN) {
       mech = SASL_MECH_STRING_LOGIN;
@@ -452,9 +453,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
     *progress = SASL_DONE;
     return result;
   case SASL_PLAIN:
-    result = Curl_auth_create_plain_message(data, conn->user, conn->passwd,
-                                            &resp,
-                                            &len);
+    result = Curl_auth_create_plain_message(data, NULL, conn->user,
+                                            conn->passwd, &resp, &len);
     break;
   case SASL_LOGIN:
     result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
@@ -517,7 +517,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
     result = Curl_auth_create_gssapi_user_message(data, conn->user,
                                                   conn->passwd,
                                                   service,
-                                                  data->easy_conn->host.name,
+                                                  data->conn->host.name,
                                                   sasl->mutual_auth, NULL,
                                                   &conn->krb5,
                                                   &resp, &len);
@@ -563,10 +563,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
       newstate = SASL_OAUTH2_RESP;
     }
     else
-      result = Curl_auth_create_oauth_bearer_message(data, conn->user,
-                                                     NULL, 0,
-                                                     conn->oauth_bearer,
-                                                     &resp, &len);
+      result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
+                                                      conn->oauth_bearer,
+                                                      &resp, &len);
     break;
 
   case SASL_OAUTH2_RESP:
@@ -627,3 +626,4 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
 
   return result;
 }
+#endif /* protocols are enabled that use SASL */
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index b845015..e5b5c86 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -310,11 +310,12 @@
 #endif
 
 #ifdef __AMIGA__
-#  ifndef __ixemul__
-#    include <exec/types.h>
-#    include <exec/execbase.h>
-#    include <proto/exec.h>
-#    include <proto/dos.h>
+#  include <exec/types.h>
+#  include <exec/execbase.h>
+#  include <proto/exec.h>
+#  include <proto/dos.h>
+#  ifdef HAVE_PROTO_BSDSOCKET_H
+#    include <proto/bsdsocket.h> /* ensure bsdsocket.library use */
 #    define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
 #  endif
 #endif
@@ -646,9 +647,9 @@ int netware_init(void);
 #define LIBIDN_REQUIRED_VERSION "0.4.1"
 
 #if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
-    defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_MBEDTLS) || \
+    defined(USE_POLARSSL) || defined(USE_MBEDTLS) || \
     defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
-    defined(USE_DARWINSSL) || defined(USE_GSKIT) || defined(USE_MESALINK)
+    defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK)
 #define USE_SSL    /* SSL support has been enabled */
 #endif
 
@@ -667,7 +668,7 @@ int netware_init(void);
 /* Single point where USE_NTLM definition might be defined */
 #if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
 #if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
-    defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \
+    defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
     defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
     defined(USE_MBEDTLS)
 
@@ -685,6 +686,10 @@ int netware_init(void);
 #error "No longer supported. Set CURLOPT_CAINFO at runtime instead."
 #endif
 
+#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) || defined(USE_WOLFSSH)
+#define USE_SSH
+#endif
+
 /*
  * Provide a mechanism to silence picky compilers, such as gcc 4.6+.
  * Parameters should of course normally not be unused, but for example when
@@ -816,4 +821,10 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
                size_t buflen, struct passwd **result);
 #endif
 
+#ifdef DEBUGBUILD
+#define UNITTEST
+#else
+#define UNITTEST static
+#endif
+
 #endif /* HEADER_CURL_SETUP_H */
diff --git a/lib/curlx.h b/lib/curlx.h
index 4c77d4f..3e9b516 100644
--- a/lib/curlx.h
+++ b/lib/curlx.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -81,22 +81,21 @@
 # undef printf
 # undef fprintf
 # undef sprintf
-# undef snprintf
+# undef msnprintf
 # undef vprintf
 # undef vfprintf
 # undef vsprintf
-# undef vsnprintf
+# undef mvsnprintf
 # undef aprintf
 # undef vaprintf
 
 # define printf curlx_mprintf
 # define fprintf curlx_mfprintf
 # define sprintf curlx_msprintf
-# define snprintf curlx_msnprintf
+# define msnprintf curlx_msnprintf
 # define vprintf curlx_mvprintf
 # define vfprintf curlx_mvfprintf
-# define vsprintf curlx_mvsprintf
-# define vsnprintf curlx_mvsnprintf
+# define mvsnprintf curlx_mvsnprintf
 # define aprintf curlx_maprintf
 # define vaprintf curlx_mvaprintf
 #endif /* ENABLE_CURLX_PRINTF */
diff --git a/lib/dict.c b/lib/dict.c
index 78ef046..208a233 100644
--- a/lib/dict.c
+++ b/lib/dict.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -137,7 +137,6 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
 
   char *path = data->state.up.path;
-  curl_off_t *bytecount = &data->req.bytecount;
 
   *done = TRUE; /* unconditionally */
 
@@ -200,8 +199,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
       failf(data, "Failed sending DICT request");
       return result;
     }
-    Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-                        -1, NULL); /* no upload */
+    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */
   }
   else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
           strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
@@ -247,8 +245,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
       failf(data, "Failed sending DICT request");
       return result;
     }
-    Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-                        -1, NULL); /* no upload */
+    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   }
   else {
 
@@ -270,7 +267,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
         return result;
       }
 
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
     }
   }
 
diff --git a/lib/doh.c b/lib/doh.c
index ef6013d..6d1f330 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,17 +22,19 @@
 
 #include "curl_setup.h"
 
+#ifndef CURL_DISABLE_DOH
+
 #include "urldata.h"
 #include "curl_addrinfo.h"
 #include "doh.h"
 
-#ifdef USE_NGHTTP2
 #include "sendf.h"
 #include "multiif.h"
 #include "url.h"
 #include "share.h"
 #include "curl_base64.h"
 #include "connect.h"
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -143,8 +145,8 @@ doh_write_cb(void *contents, size_t size, size_t nmemb, void *userp)
     /* suspiciously much for us */
     return 0;
 
-  mem->memory = realloc(mem->memory, mem->size + realsize);
-  if(mem->memory == NULL)
+  mem->memory = Curl_saferealloc(mem->memory, mem->size + realsize);
+  if(!mem->memory)
     /* out of memory! */
     return 0;
 
@@ -160,7 +162,7 @@ static int Curl_doh_done(struct Curl_easy *doh, CURLcode result)
   struct Curl_easy *data = doh->set.dohfor;
   /* so one of the DOH request done for the 'data' transfer is now complete! */
   data->req.doh.pending--;
-  infof(data, "a DOH request is completed, %d to go\n", data->req.doh.pending);
+  infof(data, "a DOH request is completed, %u to go\n", data->req.doh.pending);
   if(result)
     infof(data, "DOH request %s\n", curl_easy_strerror(result));
 
@@ -173,8 +175,12 @@ static int Curl_doh_done(struct Curl_easy *doh, CURLcode result)
   return 0;
 }
 
-#define ERROR_CHECK_SETOPT(x,y) result = curl_easy_setopt(doh, x, y);   \
-  if(result) goto error
+#define ERROR_CHECK_SETOPT(x,y) \
+do {                                      \
+  result = curl_easy_setopt(doh, x, y);   \
+  if(result)                              \
+    goto error;                           \
+} WHILE_FALSE
 
 static CURLcode dohprobe(struct Curl_easy *data,
                          struct dnsprobe *p, DNStype dnstype,
@@ -234,13 +240,76 @@ static CURLcode dohprobe(struct Curl_easy *data,
       ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen);
     }
     ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
+#ifdef USE_NGHTTP2
     ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
+#endif
 #ifndef CURLDEBUG
     /* enforce HTTPS if not debug */
     ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
 #endif
     ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
-    ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
+    if(data->set.verbose)
+      ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
+    if(data->set.no_signal)
+      ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L);
+
+    /* Inherit *some* SSL options from the user's transfer. This is a
+       best-guess as to which options are needed for compatibility. #3661 */
+    if(data->set.ssl.falsestart)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L);
+    if(data->set.ssl.primary.verifyhost)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, 2L);
+    if(data->set.proxy_ssl.primary.verifyhost)
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYHOST, 2L);
+    if(data->set.ssl.primary.verifypeer)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L);
+    if(data->set.proxy_ssl.primary.verifypeer)
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
+    if(data->set.ssl.primary.verifystatus)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L);
+    if(data->set.str[STRING_SSL_CAFILE_ORIG]) {
+      ERROR_CHECK_SETOPT(CURLOPT_CAINFO,
+        data->set.str[STRING_SSL_CAFILE_ORIG]);
+    }
+    if(data->set.str[STRING_SSL_CAFILE_PROXY]) {
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO,
+        data->set.str[STRING_SSL_CAFILE_PROXY]);
+    }
+    if(data->set.str[STRING_SSL_CAPATH_ORIG]) {
+      ERROR_CHECK_SETOPT(CURLOPT_CAPATH,
+        data->set.str[STRING_SSL_CAPATH_ORIG]);
+    }
+    if(data->set.str[STRING_SSL_CAPATH_PROXY]) {
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH,
+        data->set.str[STRING_SSL_CAPATH_PROXY]);
+    }
+    if(data->set.str[STRING_SSL_CRLFILE_ORIG]) {
+      ERROR_CHECK_SETOPT(CURLOPT_CRLFILE,
+        data->set.str[STRING_SSL_CRLFILE_ORIG]);
+    }
+    if(data->set.str[STRING_SSL_CRLFILE_PROXY]) {
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE,
+        data->set.str[STRING_SSL_CRLFILE_PROXY]);
+    }
+    if(data->set.ssl.certinfo)
+      ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L);
+    if(data->set.str[STRING_SSL_RANDOM_FILE]) {
+      ERROR_CHECK_SETOPT(CURLOPT_RANDOM_FILE,
+        data->set.str[STRING_SSL_RANDOM_FILE]);
+    }
+    if(data->set.str[STRING_SSL_EGDSOCKET]) {
+      ERROR_CHECK_SETOPT(CURLOPT_EGDSOCKET,
+        data->set.str[STRING_SSL_EGDSOCKET]);
+    }
+    if(data->set.ssl.no_revoke)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+    if(data->set.proxy_ssl.no_revoke)
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+    if(data->set.ssl.fsslctx)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
+    if(data->set.ssl.fsslctxp)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
+
     doh->set.fmultidone = Curl_doh_done;
     doh->set.dohfor = data; /* identify for which transfer this is done */
     p->easy = doh;
@@ -515,7 +584,6 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
   unsigned short qdcount;
   unsigned short ancount;
   unsigned short type = 0;
-  unsigned short class;
   unsigned short rdlength;
   unsigned short nscount;
   unsigned short arcount;
@@ -524,7 +592,7 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
 
   if(dohlen < 12)
     return DOH_TOO_SMALL_BUFFER; /* too small */
-  if(doh[0] || doh[1])
+  if(!doh || doh[0] || doh[1])
     return DOH_DNS_BAD_ID; /* bad ID */
   rcode = doh[3] & 0x0f;
   if(rcode)
@@ -543,6 +611,7 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
 
   ancount = get16bit(doh, 6);
   while(ancount) {
+    unsigned short class;
     unsigned int ttl;
 
     rc = skipqname(doh, dohlen, &index);
@@ -660,13 +729,13 @@ static void showdoh(struct Curl_easy *data,
       char buffer[128];
       char *ptr;
       size_t len;
-      snprintf(buffer, 128, "DOH AAAA: ");
+      msnprintf(buffer, 128, "DOH AAAA: ");
       ptr = &buffer[10];
       len = 118;
       for(j = 0; j < 16; j += 2) {
         size_t l;
-        snprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
-                 d->addr[i].ip.v6[j + 1]);
+        msnprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
+                  d->addr[i].ip.v6[j + 1]);
         l = strlen(ptr);
         len -= l;
         ptr += l;
@@ -827,8 +896,6 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
     DOHcode rc;
     DOHcode rc2;
     struct dohentry de;
-    struct Curl_dns_entry *dns;
-    struct Curl_addrinfo *ai;
     /* remove DOH handles from multi handle and close them */
     curl_multi_remove_handle(data->multi, data->req.doh.probe[0].easy);
     Curl_close(data->req.doh.probe[0].easy);
@@ -853,11 +920,14 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
                      &de);
     free(data->req.doh.probe[1].serverdoh.memory);
     if(rc2) {
-      infof(data, "DOG: %s type %s for %s\n", doh_strerror(rc2),
+      infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc2),
             type2name(data->req.doh.probe[1].dnstype),
             data->req.doh.host);
     }
     if(!rc || !rc2) {
+      struct Curl_dns_entry *dns;
+      struct Curl_addrinfo *ai;
+
       infof(data, "DOH Host name: %s\n", data->req.doh.host);
       showdoh(data, &de);
 
@@ -894,27 +964,4 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
   return CURLE_OK;
 }
 
-#else /* !USE_NGHTTP2 */
-/*
- */
-Curl_addrinfo *Curl_doh(struct connectdata *conn,
-                        const char *hostname,
-                        int port,
-                        int *waitp)
-{
-  (void)conn;
-  (void)hostname;
-  (void)port;
-  (void)waitp;
-  return NULL;
-}
-
-CURLcode Curl_doh_is_resolved(struct connectdata *conn,
-                              struct Curl_dns_entry **dnsp)
-{
-  (void)conn;
-  (void)dnsp;
-  return CURLE_NOT_BUILT_IN;
-}
-
-#endif /* USE_NGHTTP2 */
+#endif /* CURL_DISABLE_DOH */
diff --git a/lib/doh.h b/lib/doh.h
index 83c79bc..34bfa6f 100644
--- a/lib/doh.h
+++ b/lib/doh.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -25,6 +25,8 @@
 #include "urldata.h"
 #include "curl_addrinfo.h"
 
+#ifndef CURL_DISABLE_DOH
+
 /*
  * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name
  * and returns a 'Curl_addrinfo *' with the address information.
@@ -102,4 +104,10 @@ DOHcode doh_decode(unsigned char *doh,
                    struct dohentry *d);
 void de_cleanup(struct dohentry *d);
 #endif
+
+#else /* if DOH is disabled */
+#define Curl_doh(a,b,c,d) NULL
+#define Curl_doh_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
+#endif
+
 #endif /* HEADER_CURL_DOH_H */
diff --git a/lib/easy.c b/lib/easy.c
index 4de4e65..4a6f965 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -75,6 +75,7 @@
 #include "ssh.h"
 #include "setopt.h"
 #include "http_digest.h"
+#include "system_win32.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -83,70 +84,6 @@
 
 void Curl_version_init(void);
 
-/* win32_cleanup() is for win32 socket cleanup functionality, the opposite
-   of win32_init() */
-static void win32_cleanup(void)
-{
-#ifdef USE_WINSOCK
-  WSACleanup();
-#endif
-#ifdef USE_WINDOWS_SSPI
-  Curl_sspi_global_cleanup();
-#endif
-}
-
-/* win32_init() performs win32 socket initialization to properly setup the
-   stack to allow networking */
-static CURLcode win32_init(void)
-{
-#ifdef USE_WINSOCK
-  WORD wVersionRequested;
-  WSADATA wsaData;
-  int res;
-
-#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
-  Error IPV6_requires_winsock2
-#endif
-
-  wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
-
-  res = WSAStartup(wVersionRequested, &wsaData);
-
-  if(res != 0)
-    /* Tell the user that we couldn't find a usable */
-    /* winsock.dll.     */
-    return CURLE_FAILED_INIT;
-
-  /* Confirm that the Windows Sockets DLL supports what we need.*/
-  /* Note that if the DLL supports versions greater */
-  /* than wVersionRequested, it will still return */
-  /* wVersionRequested in wVersion. wHighVersion contains the */
-  /* highest supported version. */
-
-  if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
-     HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
-    /* Tell the user that we couldn't find a usable */
-
-    /* winsock.dll. */
-    WSACleanup();
-    return CURLE_FAILED_INIT;
-  }
-  /* The Windows Sockets DLL is acceptable. Proceed. */
-#elif defined(USE_LWIPSOCK)
-  lwip_init();
-#endif
-
-#ifdef USE_WINDOWS_SSPI
-  {
-    CURLcode result = Curl_sspi_global_init();
-    if(result)
-      return result;
-  }
-#endif
-
-  return CURLE_OK;
-}
-
 /* true globals -- for curl_global_init() and curl_global_cleanup() */
 static unsigned int  initialized;
 static long          init_flags;
@@ -223,11 +160,12 @@ static CURLcode global_init(long flags, bool memoryfuncs)
     return CURLE_FAILED_INIT;
   }
 
-  if(flags & CURL_GLOBAL_WIN32)
-    if(win32_init()) {
-      DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
-      return CURLE_FAILED_INIT;
-    }
+#ifdef WIN32
+  if(Curl_win32_init(flags)) {
+    DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
+    return CURLE_FAILED_INIT;
+  }
+#endif
 
 #ifdef __AMIGA__
   if(!Curl_amiga_init()) {
@@ -327,12 +265,12 @@ void curl_global_cleanup(void)
   if(--initialized)
     return;
 
-  Curl_global_host_cache_dtor();
   Curl_ssl_cleanup();
   Curl_resolver_global_cleanup();
 
-  if(init_flags & CURL_GLOBAL_WIN32)
-    win32_cleanup();
+#ifdef WIN32
+  Curl_win32_cleanup(init_flags);
+#endif
 
   Curl_amiga_cleanup();
 
@@ -489,8 +427,8 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
            mask. Convert from libcurl bitmask to the poll one. */
         m->socket.events = socketcb2poll(what);
         infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
-              what&CURL_POLL_IN?"IN":"",
-              what&CURL_POLL_OUT?"OUT":"");
+              (what&CURL_POLL_IN)?"IN":"",
+              (what&CURL_POLL_OUT)?"OUT":"");
       }
       break;
     }
@@ -513,8 +451,8 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
         m->socket.revents = 0;
         ev->list = m;
         infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
-              what&CURL_POLL_IN?"IN":"",
-              what&CURL_POLL_OUT?"OUT":"");
+              (what&CURL_POLL_IN)?"IN":"",
+              (what&CURL_POLL_OUT)?"OUT":"");
       }
       else
         return CURLE_OUT_OF_MEMORY;
@@ -621,7 +559,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
       return CURLE_RECV_ERROR;
 
     if(mcode)
-      return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */
+      return CURLE_URL_MALFORMAT;
 
     /* we don't really care about the "msgs_in_queue" value returned in the
        second argument */
@@ -664,12 +602,12 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
 
   while(!done && !mcode) {
     int still_running = 0;
-    int rc;
+    bool gotsocket = FALSE;
 
-    mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc);
+    mcode = Curl_multi_wait(multi, NULL, 0, 1000, NULL, &gotsocket);
 
     if(!mcode) {
-      if(!rc) {
+      if(!gotsocket) {
         long sleep_ms;
 
         /* If it returns without any filedescriptor instantly, we need to
@@ -688,6 +626,7 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
 
     /* only read 'still_running' if curl_multi_perform() return OK */
     if(!mcode && !still_running) {
+      int rc;
       CURLMsg *msg = curl_multi_info_read(multi, &rc);
       if(msg) {
         result = msg->data.result;
@@ -966,7 +905,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
   }
 
   /* Clone the resolver handle, if present, for the new handle */
-  if(Curl_resolver_duphandle(&outcurl->state.resolver,
+  if(Curl_resolver_duphandle(outcurl,
+                             &outcurl->state.resolver,
                              data->state.resolver))
     goto fail;
 
@@ -1021,7 +961,10 @@ void curl_easy_reset(struct Curl_easy *data)
   /* zero out authentication data: */
   memset(&data->state.authhost, 0, sizeof(struct auth));
   memset(&data->state.authproxy, 0, sizeof(struct auth));
-  Curl_digest_cleanup(data);
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+  Curl_http_auth_cleanup_digest(data);
+#endif
 }
 
 /*
@@ -1058,7 +1001,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
     unsigned int i;
     unsigned int count = data->state.tempcount;
     struct tempbuf writebuf[3]; /* there can only be three */
-    struct connectdata *conn = data->easy_conn;
+    struct connectdata *conn = data->conn;
     struct Curl_easy *saved_data = NULL;
 
     /* copy the structs to allow for immediate re-pausing */
diff --git a/lib/escape.c b/lib/escape.c
index afd3899..7121db3 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -122,7 +122,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
         return NULL;
       }
 
-      snprintf(&ns[strindex], 4, "%%%02X", in);
+      msnprintf(&ns[strindex], 4, "%%%02X", in);
 
       strindex += 3;
     }
diff --git a/lib/file.c b/lib/file.c
index 722b55e..d349cd9 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -311,7 +311,7 @@ static CURLcode file_upload(struct connectdata *conn)
     if(result)
       break;
 
-    if(readcount <= 0)  /* fix questionable compare error. curlvms */
+    if(!readcount)
       break;
 
     nread = readcount;
@@ -417,8 +417,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
     struct tm buffer;
     const struct tm *tm = &buffer;
     char header[80];
-    snprintf(header, sizeof(header),
-             "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
+    msnprintf(header, sizeof(header),
+              "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
+              expected_size);
     result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
     if(result)
       return result;
@@ -434,16 +435,16 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
       return result;
 
     /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
-    snprintf(header, sizeof(header),
-             "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
-             Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-             tm->tm_mday,
-             Curl_month[tm->tm_mon],
-             tm->tm_year + 1900,
-             tm->tm_hour,
-             tm->tm_min,
-             tm->tm_sec,
-             data->set.opt_no_body ? "": "\r\n");
+    msnprintf(header, sizeof(header),
+              "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
+              Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+              tm->tm_mday,
+              Curl_month[tm->tm_mon],
+              tm->tm_year + 1900,
+              tm->tm_hour,
+              tm->tm_min,
+              tm->tm_sec,
+              data->set.opt_no_body ? "": "\r\n");
     result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
     if(result)
       return result;
diff --git a/lib/fileinfo.c b/lib/fileinfo.c
index 4e72e1e..2630c9e 100644
--- a/lib/fileinfo.c
+++ b/lib/fileinfo.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2010 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
  ***************************************************************************/
 
 #include "curl_setup.h"
-
+#ifndef CURL_DISABLE_FTP
 #include "strdup.h"
 #include "fileinfo.h"
 #include "curl_memory.h"
@@ -41,3 +41,4 @@ void Curl_fileinfo_cleanup(struct fileinfo *finfo)
   Curl_safefree(finfo->info.b_data);
   free(finfo);
 }
+#endif
diff --git a/lib/formdata.c b/lib/formdata.c
index 202d930..429d479 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -24,14 +24,14 @@
 
 #include <curl/curl.h>
 
-#ifndef CURL_DISABLE_HTTP
+#include "formdata.h"
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)
 
 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
 #include <libgen.h>
 #endif
 
 #include "urldata.h" /* for struct Curl_easy */
-#include "formdata.h"
 #include "mime.h"
 #include "non-ascii.h"
 #include "vtls/vtls.h"
@@ -569,7 +569,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       if(((form->flags & HTTPPOST_FILENAME) ||
           (form->flags & HTTPPOST_BUFFER)) &&
          !form->contenttype) {
-        char *f = form->flags & HTTPPOST_BUFFER?
+        char *f = (form->flags & HTTPPOST_BUFFER)?
           form->showfilename : form->value;
         char const *type;
         type = Curl_mime_contenttype(f);
@@ -921,7 +921,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
   return result;
 }
 
-#else  /* CURL_DISABLE_HTTP */
+#else
+/* if disabled */
 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
                           struct curl_httppost **last_post,
                           ...)
@@ -946,5 +947,4 @@ void curl_formfree(struct curl_httppost *form)
   /* does nothing HTTP is disabled */
 }
 
-
-#endif  /* !defined(CURL_DISABLE_HTTP) */
+#endif  /* if disabled */
diff --git a/lib/formdata.h b/lib/formdata.h
index 1246c2b..cb20805 100644
--- a/lib/formdata.h
+++ b/lib/formdata.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,10 @@
  *
  ***************************************************************************/
 
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_MIME
+
 /* used by FormAdd for temporary storage */
 typedef struct FormInfo {
   char *name;
@@ -47,5 +51,10 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
                           curl_mimepart *,
                           struct curl_httppost *post,
                           curl_read_callback fread_func);
+#else
+/* disabled */
+#define Curl_getformdata(a,b,c,d) CURLE_NOT_BUILT_IN
+#endif
+
 
 #endif /* HEADER_CURL_FORMDATA_H */
diff --git a/lib/ftp.c b/lib/ftp.c
index 793d991..d6343fd 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -448,7 +448,6 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
 static CURLcode InitiateTransfer(struct connectdata *conn)
 {
   struct Curl_easy *data = conn->data;
-  struct FTP *ftp = data->req.protop;
   CURLcode result = CURLE_OK;
 
   if(conn->bits.ftp_use_data_ssl) {
@@ -461,24 +460,19 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
   }
 
   if(conn->proto.ftpc.state_saved == FTP_STOR) {
-    *(ftp->bytecountp) = 0;
-
     /* When we know we're uploading a specified file, we can get the file
        size prior to the actual upload. */
-
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
 
     /* set the SO_SNDBUF for the secondary socket for those who need it */
     Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
 
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
-                        SECONDARYSOCKET, ftp->bytecountp);
+    Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET);
   }
   else {
     /* FTP download: */
-    Curl_setup_transfer(conn, SECONDARYSOCKET,
-                        conn->proto.ftpc.retr_size_saved, FALSE,
-                        ftp->bytecountp, -1, NULL); /* no upload here */
+    Curl_setup_transfer(data, SECONDARYSOCKET,
+                        conn->proto.ftpc.retr_size_saved, FALSE, -1);
   }
 
   conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
@@ -578,7 +572,6 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
 
 #if defined(HAVE_GSSAPI)
   /* handle the security-oriented responses 6xx ***/
-  /* FIXME: some errorchecking perhaps... ***/
   switch(code) {
   case 631:
     code = Curl_sec_read_msg(conn, buf, PROT_SAFE);
@@ -655,7 +648,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
 
   while(!*ftpcode && !result) {
     /* check and reset timeout value every lap */
-    time_t timeout = Curl_pp_state_timeout(pp); /* timeout in milliseconds */
+    time_t timeout = Curl_pp_state_timeout(pp, FALSE);
     time_t interval_ms;
 
     if(timeout <= 0) {
@@ -955,7 +948,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   unsigned short port_max = 0;
   unsigned short port;
   bool possibly_non_local = TRUE;
-
+  char buffer[STRERROR_LEN];
   char *addr = NULL;
 
   /* Step 1, figure out what is requested,
@@ -1064,11 +1057,10 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   if(!host) {
     /* not an interface and not a host name, get default by extracting
        the IP from the control connection */
-
     sslen = sizeof(ss);
     if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
       failf(data, "getsockname() failed: %s",
-          Curl_strerror(conn, SOCKERRNO) );
+            Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
       free(addr);
       return CURLE_FTP_PORT_FAILED;
     }
@@ -1087,7 +1079,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   }
 
   /* resolv ip/host to ip */
-  rc = Curl_resolv(conn, host, 0, &h);
+  rc = Curl_resolv(conn, host, 0, FALSE, &h);
   if(rc == CURLRESOLV_PENDING)
     (void)Curl_resolver_wait_resolv(conn, &h);
   if(h) {
@@ -1121,7 +1113,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
     break;
   }
   if(!ai) {
-    failf(data, "socket failure: %s", Curl_strerror(conn, error));
+    failf(data, "socket failure: %s",
+          Curl_strerror(error, buffer, sizeof(buffer)));
     return CURLE_FTP_PORT_FAILED;
   }
 
@@ -1145,14 +1138,13 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
         /* The requested bind address is not local.  Use the address used for
          * the control connection instead and restart the port loop
          */
-
         infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
-              Curl_strerror(conn, error) );
+              Curl_strerror(error, buffer, sizeof(buffer)));
 
         sslen = sizeof(ss);
         if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
           failf(data, "getsockname() failed: %s",
-                Curl_strerror(conn, SOCKERRNO) );
+                Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
           Curl_closesocket(conn, portsock);
           return CURLE_FTP_PORT_FAILED;
         }
@@ -1162,7 +1154,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
       }
       if(error != EADDRINUSE && error != EACCES) {
         failf(data, "bind(port=%hu) failed: %s", port,
-              Curl_strerror(conn, error) );
+              Curl_strerror(error, buffer, sizeof(buffer)));
         Curl_closesocket(conn, portsock);
         return CURLE_FTP_PORT_FAILED;
       }
@@ -1185,7 +1177,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   sslen = sizeof(ss);
   if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
     failf(data, "getsockname() failed: %s",
-          Curl_strerror(conn, SOCKERRNO) );
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
     Curl_closesocket(conn, portsock);
     return CURLE_FTP_PORT_FAILED;
   }
@@ -1193,7 +1185,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   /* step 4, listen on the socket */
 
   if(listen(portsock, 1)) {
-    failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO));
+    failf(data, "socket failure: %s",
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
     Curl_closesocket(conn, portsock);
     return CURLE_FTP_PORT_FAILED;
   }
@@ -1272,7 +1265,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
         source++;
       }
       *dest = 0;
-      snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
+      msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
 
       result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
       if(result) {
@@ -1658,7 +1651,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
         infof(data, "File already completely uploaded\n");
 
         /* no data to transfer */
-        Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+        Curl_setup_transfer(data, -1, -1, FALSE, -1);
 
         /* Set ->transfer so that we won't get any error in
          * ftp_done() because we didn't transfer anything! */
@@ -1940,7 +1933,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
      */
     const char * const host_name = conn->bits.socksproxy ?
       conn->socks_proxy.host.name : conn->http_proxy.host.name;
-    rc = Curl_resolv(conn, host_name, (int)conn->port, &addr);
+    rc = Curl_resolv(conn, host_name, (int)conn->port, FALSE, &addr);
     if(rc == CURLRESOLV_PENDING)
       /* BLOCKING, ignores the return code but 'addr' will be NULL in
          case of failure */
@@ -1956,7 +1949,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
   }
   else {
     /* normal, direct, ftp connection */
-    rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr);
+    rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr);
     if(rc == CURLRESOLV_PENDING)
       /* BLOCKING */
       (void)Curl_resolver_wait_resolv(conn, &addr);
@@ -2061,9 +2054,9 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
         char timebuf[24];
         time_t secs = time(NULL);
 
-        snprintf(timebuf, sizeof(timebuf),
-                 "%04d%02d%02d %02d:%02d:%02d GMT",
-                 year, month, day, hour, minute, second);
+        msnprintf(timebuf, sizeof(timebuf),
+                  "%04d%02d%02d %02d:%02d:%02d GMT",
+                  year, month, day, hour, minute, second);
         /* now, convert this into a time() value: */
         data->info.filetime = curl_getdate(timebuf, &secs);
       }
@@ -2086,15 +2079,15 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
           return result;
 
         /* format: "Tue, 15 Nov 1994 12:45:26" */
-        snprintf(headerbuf, sizeof(headerbuf),
-                 "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
-                 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-                 tm->tm_mday,
-                 Curl_month[tm->tm_mon],
-                 tm->tm_year + 1900,
-                 tm->tm_hour,
-                 tm->tm_min,
-                 tm->tm_sec);
+        msnprintf(headerbuf, sizeof(headerbuf),
+                  "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+                  Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+                  tm->tm_mday,
+                  Curl_month[tm->tm_mon],
+                  tm->tm_year + 1900,
+                  tm->tm_hour,
+                  tm->tm_min,
+                  tm->tm_sec);
         result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0);
         if(result)
           return result;
@@ -2230,7 +2223,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
 
     if(ftp->downloadsize == 0) {
       /* no data to transfer */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
       infof(data, "File already completely downloaded\n");
 
       /* Set ->transfer so that we won't get any error in ftp_done()
@@ -2276,8 +2269,8 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
 #ifdef CURL_FTP_HTTPSTYLE_HEAD
     if(-1 != filesize) {
       char clbuf[128];
-      snprintf(clbuf, sizeof(clbuf),
-               "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
+      msnprintf(clbuf, sizeof(clbuf),
+                "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
       result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0);
       if(result)
         return result;
@@ -3054,7 +3047,7 @@ static CURLcode ftp_multi_statemach(struct connectdata *conn,
                                     bool *done)
 {
   struct ftp_conn *ftpc = &conn->proto.ftpc;
-  CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE);
+  CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE, FALSE);
 
   /* Check for the state outside of the Curl_socket_check() return code checks
      since at times we are in fact already in this state when this function
@@ -3071,7 +3064,7 @@ static CURLcode ftp_block_statemach(struct connectdata *conn)
   CURLcode result = CURLE_OK;
 
   while(ftpc->state != FTP_STOP) {
-    result = Curl_pp_statemach(pp, TRUE);
+    result = Curl_pp_statemach(pp, TRUE, TRUE /* disconnecting */);
     if(result)
       break;
   }
@@ -3308,33 +3301,33 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
     ;
   else if(data->set.upload) {
     if((-1 != data->state.infilesize) &&
-       (data->state.infilesize != *ftp->bytecountp) &&
+       (data->state.infilesize != data->req.writebytecount) &&
        !data->set.crlf &&
        (ftp->transfer == FTPTRANSFER_BODY)) {
       failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
             " out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
-            *ftp->bytecountp, data->state.infilesize);
+            data->req.bytecount, data->state.infilesize);
       result = CURLE_PARTIAL_FILE;
     }
   }
   else {
     if((-1 != data->req.size) &&
-       (data->req.size != *ftp->bytecountp) &&
+       (data->req.size != data->req.bytecount) &&
 #ifdef CURL_DO_LINEEND_CONV
        /* Most FTP servers don't adjust their file SIZE response for CRLFs, so
         * we'll check to see if the discrepancy can be explained by the number
         * of CRLFs we've changed to LFs.
         */
        ((data->req.size + data->state.crlf_conversions) !=
-        *ftp->bytecountp) &&
+        data->req.bytecount) &&
 #endif /* CURL_DO_LINEEND_CONV */
-       (data->req.maxdownload != *ftp->bytecountp)) {
+       (data->req.maxdownload != data->req.bytecount)) {
       failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
-            " bytes", *ftp->bytecountp);
+            " bytes", data->req.bytecount);
       result = CURLE_PARTIAL_FILE;
     }
     else if(!ftpc->dont_check &&
-            !*ftp->bytecountp &&
+            !data->req.bytecount &&
             (data->req.size>0)) {
       failf(data, "No data was received!");
       result = CURLE_FTP_COULDNT_RETR_FILE;
@@ -3496,7 +3489,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
   if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
     if(Curl_connect_ongoing(conn)) {
       /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
-         aren't used so we blank their arguments. TODO: make this nicer */
+         aren't used so we blank their arguments. */
       result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
 
       return result;
@@ -3629,7 +3622,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
   if(!result && (ftp->transfer != FTPTRANSFER_BODY))
     /* no data to transfer. FIX: it feels like a kludge to have this here
        too! */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(data, -1, -1, FALSE, -1);
 
   if(!ftpc->wait_data_conn) {
     /* no waiting for the data connection so this is now complete */
@@ -4308,7 +4301,7 @@ static CURLcode ftp_dophase_done(struct connectdata *conn,
 
   if(ftp->transfer != FTPTRANSFER_BODY)
     /* no data to transfer */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
   else if(!connected)
     /* since we didn't connect now, we want do_more to get called */
     conn->bits.do_more = TRUE;
@@ -4395,7 +4388,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
     return CURLE_OUT_OF_MEMORY;
 
   ftp->path = &data->state.up.path[1]; /* don't include the initial slash */
-  data->state.slash_removed = TRUE; /* we've skipped the slash */
 
   /* FTP URLs support an extension like ";type=<typecode>" that
    * we'll try to get now! */
@@ -4428,7 +4420,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
   }
 
   /* get some initial data into the ftp struct */
-  ftp->bytecountp = &conn->data->req.bytecount;
   ftp->transfer = FTPTRANSFER_BODY;
   ftp->downloadsize = 0;
 
diff --git a/lib/ftp.h b/lib/ftp.h
index 38d0322..828d69a 100644
--- a/lib/ftp.h
+++ b/lib/ftp.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -102,7 +102,6 @@ typedef enum {
    perhaps the Curl_easy is changed between the times the connection is
    used. */
 struct FTP {
-  curl_off_t *bytecountp;
   char *user;    /* user name string */
   char *passwd;  /* password string */
   char *path;    /* points to the urlpieces struct field */
diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c
index 249fe09..c4eb437 100644
--- a/lib/ftplistparser.c
+++ b/lib/ftplistparser.c
@@ -405,7 +405,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.UNIX.main = PL_UNIX_FILETYPE;
             /* start FSM again not considering size of directory */
             finfo->b_used = 0;
-            i--;
+            continue;
           }
           break;
         case PL_UNIX_TOTALSIZE_READING:
@@ -914,10 +914,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
       case PL_WINNT_DIRORSIZE:
         switch(parser->state.NT.sub.dirorsize) {
         case PL_WINNT_DIRORSIZE_PRESPACE:
-          if(c == ' ') {
-
-          }
-          else {
+          if(c != ' ') {
             parser->item_offset = finfo->b_used - 1;
             parser->item_length = 1;
             parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
diff --git a/lib/getinfo.c b/lib/getinfo.c
index 54c2c2f..e118da8 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -163,10 +163,10 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
       *param_longp = (long)data->info.filetime;
     break;
   case CURLINFO_HEADER_SIZE:
-    *param_longp = data->info.header_size;
+    *param_longp = (long)data->info.header_size;
     break;
   case CURLINFO_REQUEST_SIZE:
-    *param_longp = data->info.request_size;
+    *param_longp = (long)data->info.request_size;
     break;
   case CURLINFO_SSL_VERIFYRESULT:
     *param_longp = data->set.ssl.certverifyresult;
@@ -390,7 +390,7 @@ static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
                                           param_slistp;
       struct curl_tlssessioninfo *tsi = &data->tsi;
 #ifdef USE_SSL
-      struct connectdata *conn = data->easy_conn;
+      struct connectdata *conn = data->conn;
 #endif
 
       *tsip = tsi;
diff --git a/lib/gopher.c b/lib/gopher.c
index b441a64..b296c62 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -31,9 +31,11 @@
 #include "progress.h"
 #include "gopher.h"
 #include "select.h"
+#include "strdup.h"
 #include "url.h"
 #include "escape.h"
 #include "warnless.h"
+#include "curl_printf.h"
 #include "curl_memory.h"
 /* The last #include file should be: */
 #include "memdebug.h"
@@ -76,9 +78,9 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
-
-  curl_off_t *bytecount = &data->req.bytecount;
+  char *gopherpath;
   char *path = data->state.up.path;
+  char *query = data->state.up.query;
   char *sel = NULL;
   char *sel_org = NULL;
   ssize_t amount, k;
@@ -86,20 +88,33 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
 
   *done = TRUE; /* unconditionally */
 
+  /* path is guaranteed non-NULL */
+  DEBUGASSERT(path);
+
+  if(query)
+    gopherpath = aprintf("%s?%s", path, query);
+  else
+    gopherpath = strdup(path);
+
+  if(!gopherpath)
+    return CURLE_OUT_OF_MEMORY;
+
   /* Create selector. Degenerate cases: / and /1 => convert to "" */
-  if(strlen(path) <= 2) {
+  if(strlen(gopherpath) <= 2) {
     sel = (char *)"";
     len = strlen(sel);
+    free(gopherpath);
   }
   else {
     char *newp;
 
     /* Otherwise, drop / and the first character (i.e., item type) ... */
-    newp = path;
+    newp = gopherpath;
     newp += 2;
 
     /* ... and finally unescape */
     result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
+    free(gopherpath);
     if(result)
       return result;
     sel_org = sel;
@@ -153,8 +168,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
   if(result)
     return result;
 
-  Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-                      -1, NULL); /* no upload */
+  Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   return CURLE_OK;
 }
 #endif /*CURL_DISABLE_GOPHER*/
diff --git a/lib/hostasyn.c b/lib/hostasyn.c
index 6ff60ba..99d872b 100644
--- a/lib/hostasyn.c
+++ b/lib/hostasyn.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -85,14 +85,14 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
       dns = Curl_cache_addr(data, ai,
                             conn->async.hostname,
                             conn->async.port);
+      if(data->share)
+        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
       if(!dns) {
         /* failed to store, cleanup and return error */
         Curl_freeaddrinfo(ai);
         result = CURLE_OUT_OF_MEMORY;
       }
-
-      if(data->share)
-        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
     }
     else {
       result = CURLE_OUT_OF_MEMORY;
diff --git a/lib/hostcheck.c b/lib/hostcheck.c
index c9d8112..115d24b 100644
--- a/lib/hostcheck.c
+++ b/lib/hostcheck.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,7 +23,6 @@
 #include "curl_setup.h"
 
 #if defined(USE_OPENSSL)                                \
-  || defined(USE_AXTLS)                                 \
   || defined(USE_GSKIT)                                 \
   || defined(USE_SCHANNEL)
 /* these backends use functions from this file */
@@ -128,16 +127,14 @@ static int hostmatch(char *hostname, char *pattern)
 
 int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
 {
-  char *matchp;
-  char *hostp;
   int res = 0;
   if(!match_pattern || !*match_pattern ||
       !hostname || !*hostname) /* sanity check */
     ;
   else {
-    matchp = strdup(match_pattern);
+    char *matchp = strdup(match_pattern);
     if(matchp) {
-      hostp = strdup(hostname);
+      char *hostp = strdup(hostname);
       if(hostp) {
         if(hostmatch(hostp, matchp) == CURL_HOST_MATCH)
           res = 1;
@@ -150,4 +147,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
   return res;
 }
 
-#endif /* OPENSSL, AXTLS, GSKIT or schannel+wince */
+#endif /* OPENSSL, GSKIT or schannel+wince */
diff --git a/lib/hostip.c b/lib/hostip.c
index f589a0b..cf33ed8 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -73,6 +73,8 @@
 #define USE_ALARM_TIMEOUT
 #endif
 
+#define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */
+
 /*
  * hostip.c explained
  * ==================
@@ -112,43 +114,9 @@
  * CURLRES_* defines based on the config*.h and curl_setup.h defines.
  */
 
-/* These two symbols are for the global DNS cache */
-static struct curl_hash hostname_cache;
-static int host_cache_initialized;
-
 static void freednsentry(void *freethis);
 
 /*
- * Curl_global_host_cache_init() initializes and sets up a global DNS cache.
- * Global DNS cache is general badness. Do not use. This will be removed in
- * a future version. Use the share interface instead!
- *
- * Returns a struct curl_hash pointer on success, NULL on failure.
- */
-struct curl_hash *Curl_global_host_cache_init(void)
-{
-  int rc = 0;
-  if(!host_cache_initialized) {
-    rc = Curl_hash_init(&hostname_cache, 7, Curl_hash_str,
-                        Curl_str_key_compare, freednsentry);
-    if(!rc)
-      host_cache_initialized = 1;
-  }
-  return rc?NULL:&hostname_cache;
-}
-
-/*
- * Destroy and cleanup the global DNS cache
- */
-void Curl_global_host_cache_dtor(void)
-{
-  if(host_cache_initialized) {
-    Curl_hash_destroy(&hostname_cache);
-    host_cache_initialized = 0;
-  }
-}
-
-/*
  * Return # of addresses in a Curl_addrinfo struct
  */
 int Curl_num_addresses(const Curl_addrinfo *addr)
@@ -198,23 +166,19 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
 }
 
 /*
- * Return a hostcache id string for the provided host + port, to be used by
- * the DNS caching.
+ * Create a hostcache id string for the provided host + port, to be used by
+ * the DNS caching. Without alloc.
  */
-static char *
-create_hostcache_id(const char *name, int port)
+static void
+create_hostcache_id(const char *name, int port, char *ptr, size_t buflen)
 {
-  /* create and return the new allocated entry */
-  char *id = aprintf("%s:%d", name, port);
-  char *ptr = id;
-  if(ptr) {
-    /* lower case the name part */
-    while(*ptr && (*ptr != ':')) {
-      *ptr = (char)TOLOWER(*ptr);
-      ptr++;
-    }
-  }
-  return id;
+  size_t len = strlen(name);
+  if(len > (buflen - 7))
+    len = buflen - 7;
+  /* store and lower case the name */
+  while(len--)
+    *ptr++ = (char)TOLOWER(*name++);
+  msnprintf(ptr, 7, ":%u", port);
 }
 
 struct hostcache_prune_data {
@@ -296,22 +260,27 @@ fetch_addr(struct connectdata *conn,
                 const char *hostname,
                 int port)
 {
-  char *entry_id = NULL;
   struct Curl_dns_entry *dns = NULL;
   size_t entry_len;
   struct Curl_easy *data = conn->data;
+  char entry_id[MAX_HOSTCACHE_LEN];
 
   /* Create an entry id, based upon the hostname and port */
-  entry_id = create_hostcache_id(hostname, port);
-  /* If we can't create the entry id, fail */
-  if(!entry_id)
-    return dns;
-
+  create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
   entry_len = strlen(entry_id);
 
   /* See if its already in our dns cache */
   dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
 
+  /* No entry found in cache, check if we might have a wildcard entry */
+  if(!dns && data->change.wildcard_resolve) {
+    create_hostcache_id("*", port, entry_id, sizeof(entry_id));
+    entry_len = strlen(entry_id);
+
+    /* See if it's already in our dns cache */
+    dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
+  }
+
   if(dns && (data->set.dns_cache_timeout != -1)) {
     /* See whether the returned entry is stale. Done before we release lock */
     struct hostcache_prune_data user;
@@ -326,9 +295,6 @@ fetch_addr(struct connectdata *conn,
     }
   }
 
-  /* free the allocated entry_id again */
-  free(entry_id);
-
   return dns;
 }
 
@@ -368,6 +334,9 @@ Curl_fetch_addr(struct connectdata *conn,
   return dns;
 }
 
+#ifndef CURL_DISABLE_SHUFFLE_DNS
+UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
+                                    Curl_addrinfo **addr);
 /*
  * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
  * struct by re-linking its linked list.
@@ -380,7 +349,8 @@ Curl_fetch_addr(struct connectdata *conn,
  *
  * @unittest: 1608
  */
-CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr)
+UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
+                                    Curl_addrinfo **addr)
 {
   CURLcode result = CURLE_OK;
   const int num_addrs = Curl_num_addresses(*addr);
@@ -431,6 +401,7 @@ CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr)
   }
   return result;
 }
+#endif
 
 /*
  * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
@@ -447,32 +418,30 @@ Curl_cache_addr(struct Curl_easy *data,
                 const char *hostname,
                 int port)
 {
-  char *entry_id;
+  char entry_id[MAX_HOSTCACHE_LEN];
   size_t entry_len;
   struct Curl_dns_entry *dns;
   struct Curl_dns_entry *dns2;
 
+#ifndef CURL_DISABLE_SHUFFLE_DNS
   /* shuffle addresses if requested */
   if(data->set.dns_shuffle_addresses) {
     CURLcode result = Curl_shuffle_addr(data, &addr);
     if(result)
       return NULL;
   }
-
-  /* Create an entry id, based upon the hostname and port */
-  entry_id = create_hostcache_id(hostname, port);
-  /* If we can't create the entry id, fail */
-  if(!entry_id)
-    return NULL;
-  entry_len = strlen(entry_id);
+#endif
 
   /* Create a new cache entry */
   dns = calloc(1, sizeof(struct Curl_dns_entry));
   if(!dns) {
-    free(entry_id);
     return NULL;
   }
 
+  /* Create an entry id, based upon the hostname and port */
+  create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
+  entry_len = strlen(entry_id);
+
   dns->inuse = 1;   /* the cache has the first reference */
   dns->addr = addr; /* this is the address(es) */
   time(&dns->timestamp);
@@ -484,16 +453,11 @@ Curl_cache_addr(struct Curl_easy *data,
                        (void *)dns);
   if(!dns2) {
     free(dns);
-    free(entry_id);
     return NULL;
   }
 
   dns = dns2;
   dns->inuse++;         /* mark entry as in-use */
-
-  /* free the allocated entry_id */
-  free(entry_id);
-
   return dns;
 }
 
@@ -521,6 +485,7 @@ Curl_cache_addr(struct Curl_easy *data,
 int Curl_resolv(struct connectdata *conn,
                 const char *hostname,
                 int port,
+                bool allowDOH,
                 struct Curl_dns_entry **entry)
 {
   struct Curl_dns_entry *dns = NULL;
@@ -548,7 +513,7 @@ int Curl_resolv(struct connectdata *conn,
     /* The entry was not in the cache. Resolve it to IP address */
 
     Curl_addrinfo *addr;
-    int respwait;
+    int respwait = 0;
 
     /* Check what IP specifics the app has requested and if we can provide it.
      * If not, bail out. */
@@ -566,7 +531,7 @@ int Curl_resolv(struct connectdata *conn,
         return CURLRESOLV_ERROR;
     }
 
-    if(data->set.doh) {
+    if(allowDOH && data->set.doh) {
       addr = Curl_doh(conn, hostname, port, &respwait);
     }
     else {
@@ -692,7 +657,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
 
   if(!timeout)
     /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
-    return Curl_resolv(conn, hostname, port, entry);
+    return Curl_resolv(conn, hostname, port, TRUE, entry);
 
   if(timeout < 1000) {
     /* The alarm() function only provides integer second resolution, so if
@@ -754,7 +719,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
   /* Perform the actual name resolution. This might be interrupted by an
    * alarm if it takes too long.
    */
-  rc = Curl_resolv(conn, hostname, port, entry);
+  rc = Curl_resolv(conn, hostname, port, TRUE, entry);
 
 #ifdef USE_ALARM_TIMEOUT
 clean_up:
@@ -872,11 +837,14 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
   char hostname[256];
   int port = 0;
 
+  /* Default is no wildcard found */
+  data->change.wildcard_resolve = false;
+
   for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
+    char entry_id[MAX_HOSTCACHE_LEN];
     if(!hostp->data)
       continue;
     if(hostp->data[0] == '-') {
-      char *entry_id;
       size_t entry_len;
 
       if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) {
@@ -886,12 +854,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       }
 
       /* Create an entry id, based upon the hostname and port */
-      entry_id = create_hostcache_id(hostname, port);
-      /* If we can't create the entry id, fail */
-      if(!entry_id) {
-        return CURLE_OUT_OF_MEMORY;
-      }
-
+      create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
       entry_len = strlen(entry_id);
 
       if(data->share)
@@ -902,14 +865,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
 
       if(data->share)
         Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
-
-      /* free the allocated entry_id again */
-      free(entry_id);
     }
     else {
       struct Curl_dns_entry *dns;
       Curl_addrinfo *head = NULL, *tail = NULL;
-      char *entry_id;
       size_t entry_len;
       char address[64];
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -1005,12 +964,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       }
 
       /* Create an entry id, based upon the hostname and port */
-      entry_id = create_hostcache_id(hostname, port);
-      /* If we can't create the entry id, fail */
-      if(!entry_id) {
-        Curl_freeaddrinfo(head);
-        return CURLE_OUT_OF_MEMORY;
-      }
+      create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
       entry_len = strlen(entry_id);
 
       if(data->share)
@@ -1031,8 +985,6 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
 
         Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
       }
-      /* free the allocated entry_id again */
-      free(entry_id);
 
       /* put this new host in the cache */
       dns = Curl_cache_addr(data, head, hostname, port);
@@ -1052,6 +1004,13 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       }
       infof(data, "Added %s:%d:%s to DNS cache\n",
             hostname, port, addresses);
+
+      /* Wildcard hostname */
+      if(hostname[0] == '*' && hostname[1] == '\0') {
+        infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n",
+              hostname, port);
+        data->change.wildcard_resolve = true;
+      }
     }
   }
   data->change.resolve = NULL; /* dealt with now */
diff --git a/lib/hostip.h b/lib/hostip.h
index 29fd1ef..9dc0d5a 100644
--- a/lib/hostip.h
+++ b/lib/hostip.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -83,8 +83,11 @@ struct Curl_dns_entry {
 #define CURLRESOLV_ERROR    -1
 #define CURLRESOLV_RESOLVED  0
 #define CURLRESOLV_PENDING   1
-int Curl_resolv(struct connectdata *conn, const char *hostname,
-                int port, struct Curl_dns_entry **dnsentry);
+int Curl_resolv(struct connectdata *conn,
+                const char *hostname,
+                int port,
+                bool allowDOH,
+                struct Curl_dns_entry **dnsentry);
 int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
                         int port, struct Curl_dns_entry **dnsentry,
                         time_t timeoutms);
@@ -179,16 +182,6 @@ Curl_fetch_addr(struct connectdata *conn,
                 int port);
 
 /*
- * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
- * struct by re-linking its linked list.
- *
- * The addr argument should be the address of a pointer to the head node of a
- * `Curl_addrinfo` list and it will be modified to point to the new head after
- * shuffling.
- */
-CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr);
-
-/*
  * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
  *
  * Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
diff --git a/lib/hostip4.c b/lib/hostip4.c
index 9d6f115..e6ba710 100644
--- a/lib/hostip4.c
+++ b/lib/hostip4.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -145,7 +145,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
     hints.ai_family = PF_INET;
     hints.ai_socktype = SOCK_STREAM;
     if(port) {
-      snprintf(sbuf, sizeof(sbuf), "%d", port);
+      msnprintf(sbuf, sizeof(sbuf), "%d", port);
       sbufptr = sbuf;
     }
 
diff --git a/lib/hostip6.c b/lib/hostip6.c
index 3bf47b4..5511f1a 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -101,14 +101,16 @@ static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
 {
   printf("dump_addrinfo:\n");
   for(; ai; ai = ai->ai_next) {
-    char  buf[INET6_ADDRSTRLEN];
-
+    char buf[INET6_ADDRSTRLEN];
     printf("    fam %2d, CNAME %s, ",
            ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
     if(Curl_printable_address(ai, buf, sizeof(buf)))
       printf("%s\n", buf);
-    else
-      printf("failed; %s\n", Curl_strerror(conn, SOCKERRNO));
+    else {
+      char buffer[STRERROR_LEN];
+      printf("failed; %s\n",
+             Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
+    }
   }
 }
 #else
@@ -178,7 +180,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
 #endif
 
   if(port) {
-    snprintf(sbuf, sizeof(sbuf), "%d", port);
+    msnprintf(sbuf, sizeof(sbuf), "%d", port);
     sbufptr = sbuf;
   }
 
diff --git a/lib/http.c b/lib/http.c
index 46ac15a..338c59a 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -73,10 +73,10 @@
 #include "http_proxy.h"
 #include "warnless.h"
 #include "non-ascii.h"
-#include "pipeline.h"
 #include "http2.h"
 #include "connect.h"
 #include "strdup.h"
+#include "altsvc.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -92,7 +92,9 @@ static int http_getsock_do(struct connectdata *conn,
                            int numsocks);
 static int http_should_fail(struct connectdata *conn);
 
+#ifndef CURL_DISABLE_PROXY
 static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
+#endif
 
 #ifdef USE_SSL
 static CURLcode https_connecting(struct connectdata *conn, bool *done);
@@ -102,13 +104,14 @@ static int https_getsock(struct connectdata *conn,
 #else
 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
 #endif
+static CURLcode http_setup_conn(struct connectdata *conn);
 
 /*
  * HTTP handler interface.
  */
 const struct Curl_handler Curl_handler_http = {
   "HTTP",                               /* scheme */
-  Curl_http_setup_conn,                 /* setup_connection */
+  http_setup_conn,                      /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -133,7 +136,7 @@ const struct Curl_handler Curl_handler_http = {
  */
 const struct Curl_handler Curl_handler_https = {
   "HTTPS",                              /* scheme */
-  Curl_http_setup_conn,                 /* setup_connection */
+  http_setup_conn,                      /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
@@ -153,7 +156,7 @@ const struct Curl_handler Curl_handler_https = {
 };
 #endif
 
-CURLcode Curl_http_setup_conn(struct connectdata *conn)
+static CURLcode http_setup_conn(struct connectdata *conn)
 {
   /* allocate the HTTP-specific struct for the Curl_easy, only to survive
      during this request */
@@ -175,7 +178,7 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
   return CURLE_OK;
 }
 
-
+#ifndef CURL_DISABLE_PROXY
 /*
  * checkProxyHeaders() checks the linked list of custom proxy headers
  * if proxy headers are not available, then it will lookup into http header
@@ -202,6 +205,10 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
 
   return NULL;
 }
+#else
+/* disabled */
+#define Curl_checkProxyheaders(x,y) NULL
+#endif
 
 /*
  * Strip off leading and trailing whitespace from the value in the
@@ -256,6 +263,7 @@ char *Curl_copy_header_value(const char *header)
   return value;
 }
 
+#ifndef CURL_DISABLE_HTTP_AUTH
 /*
  * http_output_basic() sets up an Authorization: header (or the proxy version)
  * for HTTP Basic authentication.
@@ -337,6 +345,8 @@ static CURLcode http_output_bearer(struct connectdata *conn)
   return result;
 }
 
+#endif
+
 /* pickoneauth() selects the most favourable authentication method from the
  * ones available and the ones we want.
  *
@@ -415,7 +425,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
     break;
   }
 
-  bytessent = http->writebytecount;
+  bytessent = data->req.writebytecount;
 
   if(conn->bits.authneg) {
     /* This is a state where we are known to be negotiating and we don't send
@@ -456,8 +466,8 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
        (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
        (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
       if(((expectsend - bytessent) < 2000) ||
-         (conn->ntlm.state != NTLMSTATE_NONE) ||
-         (conn->proxyntlm.state != NTLMSTATE_NONE)) {
+         (conn->http_ntlm_state != NTLMSTATE_NONE) ||
+         (conn->proxy_ntlm_state != NTLMSTATE_NONE)) {
         /* The NTLM-negotiation has started *OR* there is just a little (<2K)
            data left to send, keep on sending. */
 
@@ -479,8 +489,36 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
             (curl_off_t)(expectsend - bytessent));
     }
 #endif
+#if defined(USE_SPNEGO)
+    /* There is still data left to send */
+    if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) ||
+       (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) {
+      if(((expectsend - bytessent) < 2000) ||
+         (conn->http_negotiate_state != GSS_AUTHNONE) ||
+         (conn->proxy_negotiate_state != GSS_AUTHNONE)) {
+        /* The NEGOTIATE-negotiation has started *OR*
+        there is just a little (<2K) data left to send, keep on sending. */
+
+        /* rewind data when completely done sending! */
+        if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
+          conn->bits.rewindaftersend = TRUE;
+          infof(data, "Rewind stream after send\n");
+        }
+
+        return CURLE_OK;
+      }
 
-    /* This is not NTLM or many bytes left to send: close */
+      if(conn->bits.close)
+        /* this is already marked to get closed */
+        return CURLE_OK;
+
+      infof(data, "NEGOTIATE send, close instead of sending %"
+        CURL_FORMAT_CURL_OFF_T " bytes\n",
+        (curl_off_t)(expectsend - bytessent));
+    }
+#endif
+
+    /* This is not NEGOTIATE/NTLM or many bytes left to send: close */
     streamclose(conn, "Mid-auth HTTP and much data left to send");
     data->req.size = 0; /* don't download any more than 0 bytes */
 
@@ -526,6 +564,12 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
     pickhost = pickoneauth(&data->state.authhost, authmask);
     if(!pickhost)
       data->state.authproblem = TRUE;
+    if(data->state.authhost.picked == CURLAUTH_NTLM &&
+       conn->httpversion > 11) {
+      infof(data, "Forcing HTTP/1.1 for NTLM");
+      connclose(conn, "Force HTTP/1.1 connection");
+      conn->data->set.httpversion = CURL_HTTP_VERSION_1_1;
+    }
   }
   if(conn->bits.proxy_user_passwd &&
      ((data->req.httpcode == 407) ||
@@ -576,6 +620,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
   return result;
 }
 
+#ifndef CURL_DISABLE_HTTP_AUTH
 /*
  * Output the correct authentication header depending on the auth type
  * and whether or not it is to a proxy.
@@ -592,10 +637,6 @@ output_auth_headers(struct connectdata *conn,
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO)
   struct Curl_easy *data = conn->data;
 #endif
-#ifdef USE_SPNEGO
-  struct negotiatedata *negdata = proxy ?
-    &data->state.proxyneg : &data->state.negotiate;
-#endif
 
 #ifdef CURL_DISABLE_CRYPTO_AUTH
   (void)request;
@@ -603,15 +644,11 @@ output_auth_headers(struct connectdata *conn,
 #endif
 
 #ifdef USE_SPNEGO
-  negdata->state = GSS_AUTHNONE;
-  if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
-     negdata->context && !GSS_ERROR(negdata->status)) {
+  if((authstatus->picked == CURLAUTH_NEGOTIATE)) {
     auth = "Negotiate";
     result = Curl_output_negotiate(conn, proxy);
     if(result)
       return result;
-    authstatus->done = TRUE;
-    negdata->state = GSS_AUTHSENT;
   }
   else
 #endif
@@ -697,7 +734,7 @@ output_auth_headers(struct connectdata *conn,
  *
  * @param conn all information about the current connection
  * @param request pointer to the request keyword
- * @param path pointer to the requested path
+ * @param path pointer to the requested path; should include query part
  * @param proxytunnel boolean if this is the request setting up a "proxy
  * tunnel"
  *
@@ -744,7 +781,7 @@ Curl_http_output_auth(struct connectdata *conn,
 #ifndef CURL_DISABLE_PROXY
   /* Send proxy authentication header if needed */
   if(conn->bits.httpproxy &&
-      (conn->bits.tunnel_proxy == proxytunnel)) {
+     (conn->bits.tunnel_proxy == (bit)proxytunnel)) {
     result = output_auth_headers(conn, authproxy, request, path, TRUE);
     if(result)
       return result;
@@ -772,6 +809,22 @@ Curl_http_output_auth(struct connectdata *conn,
   return result;
 }
 
+#else
+/* when disabled */
+CURLcode
+Curl_http_output_auth(struct connectdata *conn,
+                      const char *request,
+                      const char *path,
+                      bool proxytunnel)
+{
+  (void)conn;
+  (void)request;
+  (void)path;
+  (void)proxytunnel;
+  return CURLE_OK;
+}
+#endif
+
 /*
  * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
  * headers. They are dealt with both in the transfer.c main loop and in the
@@ -787,8 +840,8 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
   struct Curl_easy *data = conn->data;
 
 #ifdef USE_SPNEGO
-  struct negotiatedata *negdata = proxy?
-    &data->state.proxyneg:&data->state.negotiate;
+  curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
+                                    &conn->http_negotiate_state;
 #endif
   unsigned long *availp;
   struct auth *authp;
@@ -827,21 +880,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
         authp->avail |= CURLAUTH_NEGOTIATE;
 
         if(authp->picked == CURLAUTH_NEGOTIATE) {
-          if(negdata->state == GSS_AUTHSENT ||
-             negdata->state == GSS_AUTHNONE) {
-            CURLcode result = Curl_input_negotiate(conn, proxy, auth);
-            if(!result) {
-              DEBUGASSERT(!data->req.newurl);
-              data->req.newurl = strdup(data->change.url);
-              if(!data->req.newurl)
-                return CURLE_OUT_OF_MEMORY;
-              data->state.authproblem = FALSE;
-              /* we received a GSS auth token and we dealt with it fine */
-              negdata->state = GSS_AUTHRECV;
-            }
-            else
-              data->state.authproblem = TRUE;
+          CURLcode result = Curl_input_negotiate(conn, proxy, auth);
+          if(!result) {
+            DEBUGASSERT(!data->req.newurl);
+            data->req.newurl = strdup(data->change.url);
+            if(!data->req.newurl)
+              return CURLE_OUT_OF_MEMORY;
+            data->state.authproblem = FALSE;
+            /* we received a GSS auth token and we dealt with it fine */
+            *negstate = GSS_AUTHRECV;
           }
+          else
+            data->state.authproblem = TRUE;
         }
       }
     }
@@ -869,19 +919,10 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
                 *availp |= CURLAUTH_NTLM_WB;
                 authp->avail |= CURLAUTH_NTLM_WB;
 
-                /* Get the challenge-message which will be passed to
-                 * ntlm_auth for generating the type 3 message later */
-                while(*auth && ISSPACE(*auth))
-                  auth++;
-                if(checkprefix("NTLM", auth)) {
-                  auth += strlen("NTLM");
-                  while(*auth && ISSPACE(*auth))
-                    auth++;
-                  if(*auth) {
-                    conn->challenge_header = strdup(auth);
-                    if(!conn->challenge_header)
-                      return CURLE_OUT_OF_MEMORY;
-                  }
+                result = Curl_input_ntlm_wb(conn, proxy, auth);
+                if(result) {
+                  infof(data, "Authentication problem. Ignoring this.\n");
+                  data->state.authproblem = TRUE;
                 }
               }
 #endif
@@ -1111,14 +1152,13 @@ void Curl_add_buffer_free(Curl_send_buffer **inp)
 CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
                               struct connectdata *conn,
 
-                               /* add the number of sent bytes to this
-                                  counter */
-                              long *bytes_written,
+                              /* add the number of sent bytes to this
+                                 counter */
+                              curl_off_t *bytes_written,
 
-                               /* how much of the buffer contains body data */
+                              /* how much of the buffer contains body data */
                               size_t included_body_bytes,
                               int socketindex)
-
 {
   ssize_t amount;
   CURLcode result;
@@ -1214,7 +1254,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
     if(http) {
       /* if we sent a piece of the body here, up the byte counter for it
          accordingly */
-      http->writebytecount += bodylen;
+      data->req.writebytecount += bodylen;
+      Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
 
       if((size_t)amount != size) {
         /* The whole request could not be sent in one system call. We must
@@ -1255,7 +1296,6 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
            This needs FIXing.
         */
         return CURLE_SEND_ERROR;
-      Curl_pipeline_leave_write(conn);
     }
   }
   Curl_add_buffer_free(&in);
@@ -1432,12 +1472,14 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
     /* nothing else to do except wait right now - we're not done here. */
     return CURLE_OK;
 
+#ifndef CURL_DISABLE_PROXY
   if(conn->data->set.haproxyprotocol) {
     /* add HAProxy PROXY protocol header */
     result = add_haproxy_protocol_header(conn);
     if(result)
       return result;
   }
+#endif
 
   if(conn->given->protocol & CURLPROTO_HTTPS) {
     /* perform SSL initialization */
@@ -1464,6 +1506,7 @@ static int http_getsock_do(struct connectdata *conn,
   return GETSOCK_WRITESOCK(0);
 }
 
+#ifndef CURL_DISABLE_PROXY
 static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
 {
   char proxy_header[128];
@@ -1479,14 +1522,14 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
     strcpy(tcp_version, "TCP4");
   }
 
-  snprintf(proxy_header,
-           sizeof(proxy_header),
-           "PROXY %s %s %s %li %li\r\n",
-           tcp_version,
-           conn->data->info.conn_local_ip,
-           conn->data->info.conn_primary_ip,
-           conn->data->info.conn_local_port,
-           conn->data->info.conn_primary_port);
+  msnprintf(proxy_header,
+            sizeof(proxy_header),
+            "PROXY %s %s %s %li %li\r\n",
+            tcp_version,
+            conn->data->info.conn_local_ip,
+            conn->data->info.conn_primary_ip,
+            conn->data->info.conn_local_port,
+            conn->data->info.conn_primary_port);
 
   req_buffer = Curl_add_buffer_init();
   if(!req_buffer)
@@ -1504,6 +1547,7 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
 
   return result;
 }
+#endif
 
 #ifdef USE_SSL
 static CURLcode https_connecting(struct connectdata *conn, bool *done)
@@ -1547,20 +1591,6 @@ CURLcode Curl_http_done(struct connectdata *conn,
 
   Curl_unencode_cleanup(conn);
 
-#ifdef USE_SPNEGO
-  if(data->state.proxyneg.state == GSS_AUTHSENT ||
-     data->state.negotiate.state == GSS_AUTHSENT) {
-    /* add forbid re-use if http-code != 401/407 as a WA only needed for
-     * 401/407 that signal auth failure (empty) otherwise state will be RECV
-     * with current code.
-     * Do not close CONNECT_ONLY connections. */
-    if((data->req.httpcode != 401) && (data->req.httpcode != 407) &&
-       !data->set.connect_only)
-      streamclose(conn, "Negotiate transfer completed");
-    Curl_cleanup_negotiate(data);
-  }
-#endif
-
   /* set the proper values (possibly modified on POST) */
   conn->seek_func = data->set.seek_func; /* restore */
   conn->seek_client = data->set.seek_client; /* restore */
@@ -1576,16 +1606,6 @@ CURLcode Curl_http_done(struct connectdata *conn,
 
   Curl_mime_cleanpart(&http->form);
 
-  switch(data->set.httpreq) {
-  case HTTPREQ_PUT:
-  case HTTPREQ_POST_FORM:
-  case HTTPREQ_POST_MIME:
-    data->req.bytecount = http->readbytecount + http->writebytecount;
-    break;
-  default:
-    break;
-  }
-
   if(status)
     return status;
 
@@ -1593,7 +1613,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
                       entire operation is complete */
      !conn->bits.retry &&
      !data->set.connect_only &&
-     (http->readbytecount +
+     (data->req.bytecount +
       data->req.headerbytecount -
       data->req.deductheadercount) <= 0) {
     /* If this connection isn't simply closed to be retried, AND nothing was
@@ -1676,6 +1696,50 @@ enum proxy_use {
   HEADER_CONNECT  /* sending CONNECT to a proxy */
 };
 
+/* used to compile the provided trailers into one buffer
+   will return an error code if one of the headers is
+   not formatted correctly */
+CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
+                                    Curl_send_buffer *buffer,
+                                    struct Curl_easy *handle)
+{
+  char *ptr = NULL;
+  CURLcode result = CURLE_OK;
+  const char *endofline_native = NULL;
+  const char *endofline_network = NULL;
+
+  if(
+#ifdef CURL_DO_LINEEND_CONV
+     (handle->set.prefer_ascii) ||
+#endif
+     (handle->set.crlf)) {
+    /* \n will become \r\n later on */
+    endofline_native  = "\n";
+    endofline_network = "\x0a";
+  }
+  else {
+    endofline_native  = "\r\n";
+    endofline_network = "\x0d\x0a";
+  }
+
+  while(trailers) {
+    /* only add correctly formatted trailers */
+    ptr = strchr(trailers->data, ':');
+    if(ptr && *(ptr + 1) == ' ') {
+      result = Curl_add_bufferf(&buffer, "%s%s", trailers->data,
+                                endofline_native);
+      if(result)
+        return result;
+    }
+    else
+      infof(handle, "Malformatted trailing header ! Skipping trailer.");
+    trailers = trailers->next;
+  }
+  result = Curl_add_buffer(&buffer, endofline_network,
+                           strlen(endofline_network));
+  return result;
+}
+
 CURLcode Curl_add_custom_headers(struct connectdata *conn,
                                  bool is_connect,
                                  Curl_send_buffer *req_buffer)
@@ -1737,9 +1801,16 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
           }
           else {
             if(*(--ptr) == ';') {
-              /* send no-value custom header if terminated by semicolon */
-              *ptr = ':';
-              semicolonp = ptr;
+              /* copy the source */
+              semicolonp = strdup(headers->data);
+              if(!semicolonp) {
+                Curl_add_buffer_free(&req_buffer);
+                return CURLE_OUT_OF_MEMORY;
+              }
+              /* put a colon where the semicolon is */
+              semicolonp[ptr - headers->data] = ':';
+              /* point at the colon */
+              optr = &semicolonp [ptr - headers->data];
             }
           }
           ptr = optr;
@@ -1755,35 +1826,37 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
         if(*ptr || semicolonp) {
           /* only send this if the contents was non-blank or done special */
           CURLcode result = CURLE_OK;
+          char *compare = semicolonp ? semicolonp : headers->data;
 
           if(conn->allocptr.host &&
              /* a Host: header was sent already, don't pass on any custom Host:
                 header as that will produce *two* in the same request! */
-             checkprefix("Host:", headers->data))
+             checkprefix("Host:", compare))
             ;
           else if(data->set.httpreq == HTTPREQ_POST_FORM &&
                   /* this header (extended by formdata.c) is sent later */
-                  checkprefix("Content-Type:", headers->data))
+                  checkprefix("Content-Type:", compare))
             ;
           else if(data->set.httpreq == HTTPREQ_POST_MIME &&
                   /* this header is sent later */
-                  checkprefix("Content-Type:", headers->data))
+                  checkprefix("Content-Type:", compare))
             ;
           else if(conn->bits.authneg &&
                   /* while doing auth neg, don't allow the custom length since
                      we will force length zero then */
-                  checkprefix("Content-Length:", headers->data))
+                  checkprefix("Content-Length:", compare))
             ;
           else if(conn->allocptr.te &&
                   /* when asking for Transfer-Encoding, don't pass on a custom
                      Connection: */
-                  checkprefix("Connection:", headers->data))
+                  checkprefix("Connection:", compare))
             ;
           else if((conn->httpversion == 20) &&
-                  checkprefix("Transfer-Encoding:", headers->data))
+                  checkprefix("Transfer-Encoding:", compare))
             /* HTTP/2 doesn't support chunked requests */
             ;
-          else if(checkprefix("Authorization:", headers->data) &&
+          else if((checkprefix("Authorization:", compare) ||
+                   checkprefix("Cookie:", compare)) &&
                   /* be careful of sending this potentially sensitive header to
                      other hosts */
                   (data->state.this_is_a_follow &&
@@ -1792,10 +1865,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
                    !strcasecompare(data->state.first_host, conn->host.name)))
             ;
           else {
-            result = Curl_add_bufferf(&req_buffer, "%s\r\n", headers->data);
+            result = Curl_add_bufferf(&req_buffer, "%s\r\n", compare);
           }
           if(semicolonp)
-            *semicolonp = ';'; /* put back the semicolon */
+            free(semicolonp);
           if(result)
             return result;
         }
@@ -1807,6 +1880,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
   return CURLE_OK;
 }
 
+#ifndef CURL_DISABLE_PARSEDATE
 CURLcode Curl_add_timecondition(struct Curl_easy *data,
                                 Curl_send_buffer *req_buffer)
 {
@@ -1850,21 +1924,31 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
    */
 
   /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
-  snprintf(datestr, sizeof(datestr),
-           "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
-           condp,
-           Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-           tm->tm_mday,
-           Curl_month[tm->tm_mon],
-           tm->tm_year + 1900,
-           tm->tm_hour,
-           tm->tm_min,
-           tm->tm_sec);
+  msnprintf(datestr, sizeof(datestr),
+            "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+            condp,
+            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+            tm->tm_mday,
+            Curl_month[tm->tm_mon],
+            tm->tm_year + 1900,
+            tm->tm_hour,
+            tm->tm_min,
+            tm->tm_sec);
 
   result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr));
 
   return result;
 }
+#else
+/* disabled */
+CURLcode Curl_add_timecondition(struct Curl_easy *data,
+                                Curl_send_buffer *req_buffer)
+{
+  (void)data;
+  (void)req_buffer;
+  return CURLE_OK;
+}
+#endif
 
 /*
  * Curl_http() gets called from the generic multi_do() function when a HTTP
@@ -1916,6 +2000,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 #ifdef USE_NGHTTP2
       if(conn->data->set.httpversion ==
          CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+        if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
+          /* We don't support HTTP/2 proxies yet. Also it's debatable whether
+             or not this setting should apply to HTTP/2 proxies. */
+          infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
+          break;
+        }
+
         DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
         conn->httpversion = 20;
 
@@ -1947,7 +2038,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 
     data->state.first_remote_port = conn->remote_port;
   }
-  http->writebytecount = http->readbytecount = 0;
 
   if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
      data->set.upload) {
@@ -1995,11 +2085,21 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   }
 
   /* setup the authentication headers */
-  result = Curl_http_output_auth(conn, request, path, FALSE);
-  if(result)
-    return result;
+  {
+    char *pq = NULL;
+    if(query && *query) {
+      pq = aprintf("%s?%s", path, query);
+      if(!pq)
+        return CURLE_OUT_OF_MEMORY;
+    }
+    result = Curl_http_output_auth(conn, request, (pq ? pq : path), FALSE);
+    free(pq);
+    if(result)
+      return result;
+  }
 
-  if((data->state.authhost.multipass || data->state.authproxy.multipass) &&
+  if(((data->state.authhost.multipass && !data->state.authhost.done)
+      || (data->state.authproxy.multipass && !data->state.authproxy.done)) &&
      (httpreq != HTTPREQ_GET) &&
      (httpreq != HTTPREQ_HEAD)) {
     /* Auth is required and we are not authenticated yet. Make a PUT or POST
@@ -2084,6 +2184,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     http->sendit = NULL;
   }
 
+#ifndef CURL_DISABLE_MIME
   if(http->sendit) {
     const char *cthdr = Curl_checkheaders(conn, "Content-Type");
 
@@ -2108,6 +2209,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       return result;
     http->postsize = Curl_mime_size(http->sendit);
   }
+#endif
 
   ptr = Curl_checkheaders(conn, "Transfer-Encoding");
   if(ptr) {
@@ -2293,8 +2395,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
           if(!*data->state.up.path && path[strlen(path) - 1] != '/') {
             *p++ = '/';
           }
-          snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
-                   data->set.prefer_ascii ? 'a' : 'i');
+          msnprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
+                    data->set.prefer_ascii ? 'a' : 'i');
         }
       }
       if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
@@ -2635,9 +2737,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       failf(data, "Failed sending PUT request");
     else
       /* prepare for transfer */
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
-                          &http->readbytecount, postsize?FIRSTSOCKET:-1,
-                          postsize?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          postsize?FIRSTSOCKET:-1);
     if(result)
       return result;
     break;
@@ -2657,12 +2758,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
         failf(data, "Failed sending POST request");
       else
         /* setup variables for the upcoming transfer */
-        Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
-                            -1, NULL);
+        Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
       break;
     }
 
-    postsize = http->postsize;
+    data->state.infilesize = postsize = http->postsize;
 
     /* We only set Content-Length and allow a custom Content-Length if
        we don't upload data chunked, as RFC2616 forbids us to set both
@@ -2678,6 +2778,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
         return result;
     }
 
+#ifndef CURL_DISABLE_MIME
     /* Output mime-generated headers. */
     {
       struct curl_slist *hdr;
@@ -2688,6 +2789,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
           return result;
       }
     }
+#endif
 
     /* For really small posts we don't use Expect: headers at all, and for
        the somewhat bigger ones we allow the app to disable it. Just make
@@ -2726,9 +2828,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       failf(data, "Failed sending POST request");
     else
       /* prepare for transfer */
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
-                          &http->readbytecount, postsize?FIRSTSOCKET:-1,
-                          postsize?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          postsize?FIRSTSOCKET:-1);
     if(result)
       return result;
 
@@ -2882,9 +2983,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     if(result)
       failf(data, "Failed sending HTTP POST request");
     else
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
-                          &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
-                          http->postdata?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          http->postdata?FIRSTSOCKET:-1);
     break;
 
   default:
@@ -2900,33 +3000,30 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       failf(data, "Failed sending HTTP request");
     else
       /* HTTP GET/HEAD download: */
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
-                          http->postdata?FIRSTSOCKET:-1,
-                          http->postdata?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          http->postdata?FIRSTSOCKET:-1);
   }
   if(result)
     return result;
 
-  if(http->writebytecount) {
+  if(data->req.writebytecount) {
     /* if a request-body has been sent off, we make sure this progress is noted
        properly */
-    Curl_pgrsSetUploadCounter(data, http->writebytecount);
+    Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
     if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
 
-    if(http->writebytecount >= postsize) {
+    if(data->req.writebytecount >= postsize) {
       /* already sent the entire request body, mark the "upload" as
          complete */
       infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
             " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
-            http->writebytecount, postsize);
+            data->req.writebytecount, postsize);
       data->req.upload_done = TRUE;
       data->req.keepon &= ~KEEP_SEND; /* we're done writing */
       data->req.exp100 = EXP100_SEND_DATA; /* already sent */
       Curl_expire_done(data, EXPIRE_100_TIMEOUT);
     }
-    else
-      data->req.writebytecount = http->writebytecount;
   }
 
   if((conn->httpversion == 20) && data->req.upload_chunky)
@@ -3161,6 +3258,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
           k->header = FALSE;
           k->badheader = HEADER_ALLBAD;
           streamclose(conn, "bad HTTP: No end-of-message indicator");
+          if(!data->set.http09_allowed) {
+            failf(data, "Received HTTP/0.9 when not allowed\n");
+            return CURLE_UNSUPPORTED_PROTOCOL;
+          }
           break;
         }
       }
@@ -3194,6 +3295,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
       if(st == STATUS_BAD) {
         streamclose(conn, "bad HTTP: No end-of-message indicator");
         /* this is not the beginning of a protocol first header line */
+        if(!data->set.http09_allowed) {
+          failf(data, "Received HTTP/0.9 when not allowed\n");
+          return CURLE_UNSUPPORTED_PROTOCOL;
+        }
         k->header = FALSE;
         if(*nread)
           /* since there's more, this is a partial bad header */
@@ -3306,14 +3411,31 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
 #if defined(USE_NTLM)
       if(conn->bits.close &&
          (((data->req.httpcode == 401) &&
-           (conn->ntlm.state == NTLMSTATE_TYPE2)) ||
+           (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
           ((data->req.httpcode == 407) &&
-           (conn->proxyntlm.state == NTLMSTATE_TYPE2)))) {
+           (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
         infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
         data->state.authproblem = TRUE;
       }
 #endif
-
+#if defined(USE_SPNEGO)
+      if(conn->bits.close &&
+        (((data->req.httpcode == 401) &&
+          (conn->http_negotiate_state == GSS_AUTHRECV)) ||
+         ((data->req.httpcode == 407) &&
+          (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
+        infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
+        data->state.authproblem = TRUE;
+      }
+      if((conn->http_negotiate_state == GSS_AUTHDONE) &&
+         (data->req.httpcode != 401)) {
+        conn->http_negotiate_state = GSS_AUTHSUCC;
+      }
+      if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
+         (data->req.httpcode != 407)) {
+        conn->proxy_negotiate_state = GSS_AUTHSUCC;
+      }
+#endif
       /*
        * When all the headers have been parsed, see if we should give
        * up and return an error.
@@ -3549,6 +3671,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
             if(conn->httpversion != 20)
               infof(data, "Lying server, not serving HTTP/2\n");
           }
+          if(conn->httpversion < 20) {
+            conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
+            infof(data, "Mark bundle as not supporting multiuse\n");
+          }
         }
         else if(!nc) {
           /* this is the real world, not a Nirvana
@@ -3586,7 +3712,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
           conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
         }
         else {
-          /* TODO: do we care about the other cases here? */
           nc = 0;
         }
       }
@@ -3639,26 +3764,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         }
         else if(conn->httpversion >= 11 &&
                 !conn->bits.close) {
-          /* If HTTP version is >= 1.1 and connection is persistent
-             server supports pipelining. */
+          /* If HTTP version is >= 1.1 and connection is persistent */
           DEBUGF(infof(data,
-                       "HTTP 1.1 or later with persistent connection, "
-                       "pipelining supported\n"));
-          /* Activate pipelining if needed */
-          if(conn->bundle) {
-            if(!Curl_pipeline_site_blacklisted(data, conn))
-              conn->bundle->multiuse = BUNDLE_PIPELINING;
-          }
+                       "HTTP 1.1 or later with persistent connection\n"));
         }
 
         switch(k->httpcode) {
-        case 204:
-          /* (quote from RFC2616, section 10.2.5): The server has
-           * fulfilled the request but does not need to return an
-           * entity-body ... The 204 response MUST NOT include a
-           * message-body, and thus is always terminated by the first
-           * empty line after the header fields. */
-          /* FALLTHROUGH */
         case 304:
           /* (quote from RFC2616, section 10.3.5): The 304 response
            * MUST NOT contain a message-body, and thus is always
@@ -3666,6 +3777,13 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
            * fields.  */
           if(data->set.timecondition)
             data->info.timecond = TRUE;
+          /* FALLTHROUGH */
+        case 204:
+          /* (quote from RFC2616, section 10.2.5): The server has
+           * fulfilled the request but does not need to return an
+           * entity-body ... The 204 response MUST NOT include a
+           * message-body, and thus is always terminated by the first
+           * empty line after the header fields. */
           k->size = 0;
           k->maxdownload = 0;
           k->ignorecl = TRUE; /* ignore Content-Length headers */
@@ -3733,19 +3851,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         data->info.contenttype = contenttype;
       }
     }
-    else if(checkprefix("Server:", k->p)) {
-      if(conn->httpversion < 20) {
-        /* only do this for non-h2 servers */
-        char *server_name = Curl_copy_header_value(k->p);
-
-        /* Turn off pipelining if the server version is blacklisted  */
-        if(conn->bundle && (conn->bundle->multiuse == BUNDLE_PIPELINING)) {
-          if(Curl_pipeline_server_blacklisted(data, server_name))
-            conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
-        }
-        free(server_name);
-      }
-    }
     else if((conn->httpversion == 10) &&
             conn->bits.httpproxy &&
             Curl_compareheader(k->p,
@@ -3859,7 +3964,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
                          here, or else use real peer host name. */
                       conn->allocptr.cookiehost?
                       conn->allocptr.cookiehost:conn->host.name,
-                      data->state.up.path);
+                      data->state.up.path,
+                      (conn->handler->protocol&CURLPROTO_HTTPS)?
+                      TRUE:FALSE);
       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
     }
 #endif
@@ -3888,6 +3995,22 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
       if(result)
         return result;
     }
+  #ifdef USE_SPNEGO
+    else if(checkprefix("Persistent-Auth", k->p)) {
+      struct negotiatedata *negdata = &conn->negotiate;
+      struct auth *authp = &data->state.authhost;
+      if(authp->picked == CURLAUTH_NEGOTIATE) {
+        char *persistentauth = Curl_copy_header_value(k->p);
+        if(!persistentauth)
+          return CURLE_OUT_OF_MEMORY;
+        negdata->noauthpersist = checkprefix("false", persistentauth);
+        negdata->havenoauthpersist = TRUE;
+        infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
+          negdata->noauthpersist, persistentauth);
+        free(persistentauth);
+      }
+    }
+  #endif
     else if((k->httpcode >= 300 && k->httpcode < 400) &&
             checkprefix("Location:", k->p) &&
             !data->req.location) {
@@ -3915,6 +4038,27 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         }
       }
     }
+#ifdef USE_ALTSVC
+    /* If enabled, the header is incoming and this is over HTTPS */
+    else if(data->asi && checkprefix("Alt-Svc:", k->p) &&
+            ((conn->handler->flags & PROTOPT_SSL) ||
+#ifdef CURLDEBUG
+             /* allow debug builds to circumvent the HTTPS restriction */
+             getenv("CURL_ALTSVC_HTTP")
+#else
+             0
+#endif
+              )) {
+      /* the ALPN of the current request */
+      enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
+      result = Curl_altsvc_parse(data, data->asi,
+                                 &k->p[ strlen("Alt-Svc:") ],
+                                 id, conn->host.name,
+                                 curlx_uitous(conn->remote_port));
+      if(result)
+        return result;
+    }
+#endif
     else if(conn->handler->protocol & CURLPROTO_RTSP) {
       result = Curl_rtsp_parseheader(conn, k->p);
       if(result)
diff --git a/lib/http.h b/lib/http.h
index 21fa701..a59fe7a 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -65,7 +65,7 @@ CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
                          size_t size) WARN_UNUSED_RESULT;
 CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
                               struct connectdata *conn,
-                              long *bytes_written,
+                              curl_off_t *bytes_written,
                               size_t included_body_bytes,
                               int socketindex);
 
@@ -74,6 +74,9 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
 CURLcode Curl_add_custom_headers(struct connectdata *conn,
                                  bool is_connect,
                                  Curl_send_buffer *req_buffer);
+CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
+                                    Curl_send_buffer *buffer,
+                                    struct Curl_easy *handle);
 
 /* protocol-specific functions set up to be called by the main engine */
 CURLcode Curl_http(struct connectdata *conn, bool *done);
@@ -136,8 +139,6 @@ struct HTTP {
 
   const char *p_pragma;      /* Pragma: string */
   const char *p_accept;      /* Accept: string */
-  curl_off_t readbytecount;
-  curl_off_t writebytecount;
 
   /* For FORM posting */
   curl_mimepart form;
diff --git a/lib/http2.c b/lib/http2.c
index 0c5f6db..8e7bc21 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -111,8 +111,6 @@ static int http2_perform_getsock(const struct connectdata *conn,
   int bitmap = GETSOCK_BLANK;
   (void)numsocks;
 
-  /* TODO We should check underlying socket state if it is SSL socket
-     because of renegotiation. */
   sock[0] = conn->sock[FIRSTSOCKET];
 
   /* in a HTTP/2 connection we can basically always get a frame so we should
@@ -350,14 +348,14 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
 int Curl_http2_ver(char *p, size_t len)
 {
   nghttp2_info *h2 = nghttp2_version(0);
-  return snprintf(p, len, " nghttp2/%s", h2->version_str);
+  return msnprintf(p, len, " nghttp2/%s", h2->version_str);
 }
 
 /* HTTP/2 error code to name based on the Error Code Registry.
 https://tools.ietf.org/html/rfc7540#page-77
 nghttp2_error_code enums are identical.
 */
-const char *Curl_http2_strerror(uint32_t err)
+static const char *http2_strerror(uint32_t err)
 {
 #ifndef NGHTTP2_HAS_HTTP2_STRERROR
   const char *str[] = {
@@ -618,6 +616,18 @@ static int push_promise(struct Curl_easy *data,
   return rv;
 }
 
+/*
+ * multi_connchanged() is called to tell that there is a connection in
+ * this multi handle that has changed state (multiplexing become possible, the
+ * number of allowed streams changed or similar), and a subsequent use of this
+ * multi handle should move CONNECT_PEND handles back to CONNECT to have them
+ * retry.
+ */
+static void multi_connchanged(struct Curl_multi *multi)
+{
+  multi->recheckstate = TRUE;
+}
+
 static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
                          void *userp)
 {
@@ -650,7 +660,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
         infof(conn->data,
               "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
               httpc->settings.max_concurrent_streams);
-        Curl_multi_connchanged(conn->data->multi);
+        multi_connchanged(conn->data->multi);
       }
     }
     return 0;
@@ -800,7 +810,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
     H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
                  ", stream %u\n",
                  len - nread, stream_id));
-    data_s->easy_conn->proto.httpc.pause_stream_id = stream_id;
+    data_s->conn->proto.httpc.pause_stream_id = stream_id;
 
     return NGHTTP2_ERR_PAUSE;
   }
@@ -808,7 +818,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
   /* pause execution of nghttp2 if we received data for another handle
      in order to process them first. */
   if(conn->data != data_s) {
-    data_s->easy_conn->proto.httpc.pause_stream_id = stream_id;
+    data_s->conn->proto.httpc.pause_stream_id = stream_id;
 
     return NGHTTP2_ERR_PAUSE;
   }
@@ -837,7 +847,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
       return 0;
     }
     H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
-                 Curl_http2_strerror(error_code), error_code, stream_id));
+                 http2_strerror(error_code), error_code, stream_id));
     stream = data_s->req.protop;
     if(!stream)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -854,6 +864,10 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
             stream_id);
       DEBUGASSERT(0);
     }
+    if(stream_id == httpc->pause_stream_id) {
+      H2BUGF(infof(data_s, "Stopped the pause stream!\n"));
+      httpc->pause_stream_id = 0;
+    }
     H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
     stream->stream_id = 0; /* cleared */
   }
@@ -953,6 +967,28 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
   if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
     char *h;
 
+    if(!strcmp(":authority", (const char *)name)) {
+      /* pseudo headers are lower case */
+      int rc = 0;
+      char *check = aprintf("%s:%d", conn->host.name, conn->remote_port);
+      if(!check)
+        /* no memory */
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
+      if(!Curl_strcasecompare(check, (const char *)value)) {
+        /* This is push is not for the same authority that was asked for in
+         * the URL. RFC 7540 section 8.2 says: "A client MUST treat a
+         * PUSH_PROMISE for which the server is not authoritative as a stream
+         * error of type PROTOCOL_ERROR."
+         */
+        (void)nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+                                        stream_id, NGHTTP2_PROTOCOL_ERROR);
+        rc = NGHTTP2_ERR_CALLBACK_FAILURE;
+      }
+      free(check);
+      if(rc)
+        return rc;
+    }
+
     if(!stream->push_headers) {
       stream->push_headers_alloc = 10;
       stream->push_headers = malloc(stream->push_headers_alloc *
@@ -1193,7 +1229,7 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
 /*
  * Initialize nghttp2 for a Curl connection
  */
-CURLcode Curl_http2_init(struct connectdata *conn)
+static CURLcode http2_init(struct connectdata *conn)
 {
   if(!conn->proto.httpc.h2) {
     int rc;
@@ -1427,7 +1463,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
   }
   else if(httpc->error_code != NGHTTP2_NO_ERROR) {
     failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
-          stream->stream_id, Curl_http2_strerror(httpc->error_code),
+          stream->stream_id, http2_strerror(httpc->error_code),
           httpc->error_code);
     *err = CURLE_HTTP2_STREAM;
     return -1;
@@ -1809,9 +1845,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
                           const void *mem, size_t len, CURLcode *err)
 {
   /*
-   * BIG TODO: Currently, we send request in this function, but this
-   * function is also used to send request body. It would be nice to
-   * add dedicated function for request.
+   * Currently, we send request in this function, but this function is also
+   * used to send request body. It would be nice to add dedicated function for
+   * request.
    */
   int rv;
   struct http_conn *httpc = &conn->proto.httpc;
@@ -2137,7 +2173,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
   else
     conn->handler = &Curl_handler_http2;
 
-  result = Curl_http2_init(conn);
+  result = http2_init(conn);
   if(result) {
     Curl_add_buffer_free(&stream->header_recvbuf);
     return result;
@@ -2159,7 +2195,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
   conn->bundle->multiuse = BUNDLE_MULTIPLEX;
 
   infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n");
-  Curl_multi_connchanged(conn->data->multi);
+  multi_connchanged(conn->data->multi);
 
   return CURLE_OK;
 }
@@ -2367,6 +2403,14 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
     Curl_http2_remove_child(data->set.stream_depends_on, data);
 }
 
+/* Only call this function for a transfer that already got a HTTP/2
+   CURLE_HTTP2_STREAM error! */
+bool Curl_h2_http_1_1_error(struct connectdata *conn)
+{
+  struct http_conn *httpc = &conn->proto.httpc;
+  return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED);
+}
+
 #else /* !USE_NGHTTP2 */
 
 /* Satisfy external references even if http2 is not compiled in. */
diff --git a/lib/http2.h b/lib/http2.h
index 4492ec2..db6217b 100644
--- a/lib/http2.h
+++ b/lib/http2.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -59,8 +59,10 @@ CURLcode Curl_http2_add_child(struct Curl_easy *parent,
 void Curl_http2_remove_child(struct Curl_easy *parent,
                              struct Curl_easy *child);
 void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
+
+/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
+bool Curl_h2_http_1_1_error(struct connectdata *conn);
 #else /* USE_NGHTTP2 */
-#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
@@ -74,6 +76,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
 #define Curl_http2_add_child(x, y, z)
 #define Curl_http2_remove_child(x, y)
 #define Curl_http2_cleanup_dependencies(x)
+#define Curl_h2_http_1_1_error(x) 0
 #endif
 
 #endif /* HEADER_CURL_HTTP2_H */
diff --git a/lib/http_digest.c b/lib/http_digest.c
index e2d865b..9616c30 100644
--- a/lib/http_digest.c
+++ b/lib/http_digest.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
 #include "strcase.h"
 #include "vauth/vauth.h"
 #include "http_digest.h"
+
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -171,7 +172,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
   return CURLE_OK;
 }
 
-void Curl_digest_cleanup(struct Curl_easy *data)
+void Curl_http_auth_cleanup_digest(struct Curl_easy *data)
 {
   Curl_auth_digest_cleanup(&data->state.digest);
   Curl_auth_digest_cleanup(&data->state.proxydigest);
diff --git a/lib/http_digest.h b/lib/http_digest.h
index fd225c7..73410ae 100644
--- a/lib/http_digest.h
+++ b/lib/http_digest.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,6 +23,8 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+
 /* this is for digest header input */
 CURLcode Curl_input_digest(struct connectdata *conn,
                            bool proxy, const char *header);
@@ -33,10 +35,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
                             const unsigned char *request,
                             const unsigned char *uripath);
 
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
-void Curl_digest_cleanup(struct Curl_easy *data);
-#else
-#define Curl_digest_cleanup(x) Curl_nop_stmt
-#endif
+void Curl_http_auth_cleanup_digest(struct Curl_easy *data);
+
+#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_CRYPTO_AUTH */
 
 #endif /* HEADER_CURL_HTTP_DIGEST_H */
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index ddcd65b..c8f4064 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -49,6 +49,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
 
   /* Point to the correct struct with this */
   struct negotiatedata *neg_ctx;
+  curlnegotiate state;
 
   if(proxy) {
     userp = conn->http_proxy.user;
@@ -56,7 +57,8 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
               data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
     host = conn->http_proxy.host.name;
-    neg_ctx = &data->state.proxyneg;
+    neg_ctx = &conn->proxyneg;
+    state = conn->proxy_negotiate_state;
   }
   else {
     userp = conn->user;
@@ -64,7 +66,8 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     service = data->set.str[STRING_SERVICE_NAME] ?
               data->set.str[STRING_SERVICE_NAME] : "HTTP";
     host = conn->host.name;
-    neg_ctx = &data->state.negotiate;
+    neg_ctx = &conn->negotiate;
+    state = conn->http_negotiate_state;
   }
 
   /* Not set means empty */
@@ -80,59 +83,138 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     header++;
 
   len = strlen(header);
+  neg_ctx->havenegdata = len != 0;
   if(!len) {
-    /* Is this the first call in a new negotiation? */
-    if(neg_ctx->context) {
-      /* The server rejected our authentication and hasn't suppled any more
+    if(state == GSS_AUTHSUCC) {
+      infof(conn->data, "Negotiate auth restarted\n");
+      Curl_http_auth_cleanup_negotiate(conn);
+    }
+    else if(state != GSS_AUTHNONE) {
+      /* The server rejected our authentication and hasn't supplied any more
       negotiation mechanisms */
+      Curl_http_auth_cleanup_negotiate(conn);
       return CURLE_LOGIN_DENIED;
     }
   }
 
+  /* Supports SSL channel binding for Windows ISS extended protection */
+#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS)
+  neg_ctx->sslContext = conn->sslContext;
+#endif
+
   /* Initialize the security context and decode our challenge */
   result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
                                            host, header, neg_ctx);
 
   if(result)
-    Curl_auth_spnego_cleanup(neg_ctx);
+    Curl_http_auth_cleanup_negotiate(conn);
 
   return result;
 }
 
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
 {
-  struct negotiatedata *neg_ctx = proxy ? &conn->data->state.proxyneg :
-    &conn->data->state.negotiate;
+  struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg :
+    &conn->negotiate;
+  struct auth *authp = proxy ? &conn->data->state.authproxy :
+    &conn->data->state.authhost;
+  curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
+                                 &conn->http_negotiate_state;
   char *base64 = NULL;
   size_t len = 0;
   char *userp;
   CURLcode result;
 
-  result = Curl_auth_create_spnego_message(conn->data, neg_ctx, &base64, &len);
-  if(result)
-    return result;
+  authp->done = FALSE;
 
-  userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
-                  base64);
+  if(*state == GSS_AUTHRECV) {
+    if(neg_ctx->havenegdata) {
+      neg_ctx->havemultiplerequests = TRUE;
+    }
+  }
+  else if(*state == GSS_AUTHSUCC) {
+    if(!neg_ctx->havenoauthpersist) {
+      neg_ctx->noauthpersist = !neg_ctx->havemultiplerequests;
+    }
+  }
 
-  if(proxy) {
-    Curl_safefree(conn->allocptr.proxyuserpwd);
-    conn->allocptr.proxyuserpwd = userp;
+  if(neg_ctx->noauthpersist ||
+    (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) {
+
+    if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) {
+      infof(conn->data, "Curl_output_negotiate, "
+       "no persistent authentication: cleanup existing context");
+      Curl_http_auth_cleanup_negotiate(conn);
+    }
+    if(!neg_ctx->context) {
+      result = Curl_input_negotiate(conn, proxy, "Negotiate");
+      if(result == CURLE_LOGIN_DENIED) {
+        /* negotiate auth failed, let's continue unauthenticated to stay
+         * compatible with the behavior before curl-7_64_0-158-g6c6035532 */
+        conn->data->state.authproblem = TRUE;
+        return CURLE_OK;
+      }
+      else if(result)
+        return result;
+    }
+
+    result = Curl_auth_create_spnego_message(conn->data,
+      neg_ctx, &base64, &len);
+    if(result)
+      return result;
+
+    userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
+      base64);
+
+    if(proxy) {
+      Curl_safefree(conn->allocptr.proxyuserpwd);
+      conn->allocptr.proxyuserpwd = userp;
+    }
+    else {
+      Curl_safefree(conn->allocptr.userpwd);
+      conn->allocptr.userpwd = userp;
+    }
+
+    free(base64);
+
+    if(userp == NULL) {
+      return CURLE_OUT_OF_MEMORY;
+    }
+
+    *state = GSS_AUTHSENT;
+  #ifdef HAVE_GSSAPI
+    if(neg_ctx->status == GSS_S_COMPLETE ||
+       neg_ctx->status == GSS_S_CONTINUE_NEEDED) {
+      *state = GSS_AUTHDONE;
+    }
+  #else
+  #ifdef USE_WINDOWS_SSPI
+    if(neg_ctx->status == SEC_E_OK ||
+       neg_ctx->status == SEC_I_CONTINUE_NEEDED) {
+      *state = GSS_AUTHDONE;
+    }
+  #endif
+  #endif
   }
-  else {
-    Curl_safefree(conn->allocptr.userpwd);
-    conn->allocptr.userpwd = userp;
+
+  if(*state == GSS_AUTHDONE || *state == GSS_AUTHSUCC) {
+    /* connection is already authenticated,
+     * don't send a header in future requests */
+    authp->done = TRUE;
   }
 
-  free(base64);
+  neg_ctx->havenegdata = FALSE;
 
-  return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
+  return CURLE_OK;
 }
 
-void Curl_cleanup_negotiate(struct Curl_easy *data)
+void Curl_http_auth_cleanup_negotiate(struct connectdata *conn)
 {
-  Curl_auth_spnego_cleanup(&data->state.negotiate);
-  Curl_auth_spnego_cleanup(&data->state.proxyneg);
+  conn->http_negotiate_state = GSS_AUTHNONE;
+  conn->proxy_negotiate_state = GSS_AUTHNONE;
+
+  Curl_auth_cleanup_spnego(&conn->negotiate);
+  Curl_auth_cleanup_spnego(&conn->proxyneg);
 }
 
 #endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
diff --git a/lib/http_negotiate.h b/lib/http_negotiate.h
index c64e548..4f0ac16 100644
--- a/lib/http_negotiate.h
+++ b/lib/http_negotiate.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
  *
  ***************************************************************************/
 
-#ifdef USE_SPNEGO
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
 
 /* this is for Negotiate header input */
 CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
@@ -31,8 +31,8 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
 /* this is for creating Negotiate header output */
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
 
-void Curl_cleanup_negotiate(struct Curl_easy *data);
+void Curl_http_auth_cleanup_negotiate(struct connectdata *conn);
 
-#endif /* USE_SPNEGO */
+#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
 
 #endif /* HEADER_CURL_HTTP_NEGOTIATE_H */
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
index a9b33f9..e4a4fe0 100644
--- a/lib/http_ntlm.c
+++ b/lib/http_ntlm.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -68,9 +68,11 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
 {
   /* point to the correct struct with this */
   struct ntlmdata *ntlm;
+  curlntlm *state;
   CURLcode result = CURLE_OK;
 
   ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
+  state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
 
   if(checkprefix("NTLM", header)) {
     header += strlen("NTLM");
@@ -83,25 +85,25 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
       if(result)
         return result;
 
-      ntlm->state = NTLMSTATE_TYPE2; /* We got a type-2 message */
+      *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
     }
     else {
-      if(ntlm->state == NTLMSTATE_LAST) {
+      if(*state == NTLMSTATE_LAST) {
         infof(conn->data, "NTLM auth restarted\n");
-        Curl_http_ntlm_cleanup(conn);
+        Curl_http_auth_cleanup_ntlm(conn);
       }
-      else if(ntlm->state == NTLMSTATE_TYPE3) {
+      else if(*state == NTLMSTATE_TYPE3) {
         infof(conn->data, "NTLM handshake rejected\n");
-        Curl_http_ntlm_cleanup(conn);
-        ntlm->state = NTLMSTATE_NONE;
+        Curl_http_auth_cleanup_ntlm(conn);
+        *state = NTLMSTATE_NONE;
         return CURLE_REMOTE_ACCESS_DENIED;
       }
-      else if(ntlm->state >= NTLMSTATE_TYPE1) {
+      else if(*state >= NTLMSTATE_TYPE1) {
         infof(conn->data, "NTLM handshake failure (internal error)\n");
         return CURLE_REMOTE_ACCESS_DENIED;
       }
 
-      ntlm->state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
+      *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
     }
   }
 
@@ -129,6 +131,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
 
   /* point to the correct struct with this */
   struct ntlmdata *ntlm;
+  curlntlm *state;
   struct auth *authp;
 
   DEBUGASSERT(conn);
@@ -147,6 +150,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
               conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
     hostname = conn->http_proxy.host.name;
     ntlm = &conn->proxyntlm;
+    state = &conn->proxy_ntlm_state;
     authp = &conn->data->state.authproxy;
   }
   else {
@@ -157,6 +161,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
               conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
     hostname = conn->host.name;
     ntlm = &conn->ntlm;
+    state = &conn->http_ntlm_state;
     authp = &conn->data->state.authhost;
   }
   authp->done = FALSE;
@@ -175,9 +180,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
     if(s_hSecDll == NULL)
       return err;
   }
+#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
+  ntlm->sslContext = conn->sslContext;
+#endif
 #endif
 
-  switch(ntlm->state) {
+  switch(*state) {
   case NTLMSTATE_TYPE1:
   default: /* for the weird cases we (re)start here */
     /* Create a type-1 message */
@@ -219,7 +227,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
 
       DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
 
-      ntlm->state = NTLMSTATE_TYPE3; /* we send a type-3 */
+      *state = NTLMSTATE_TYPE3; /* we send a type-3 */
       authp->done = TRUE;
     }
     break;
@@ -227,7 +235,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
   case NTLMSTATE_TYPE3:
     /* connection is already authenticated,
      * don't send a header in future requests */
-    ntlm->state = NTLMSTATE_LAST;
+    *state = NTLMSTATE_LAST;
     /* FALLTHROUGH */
   case NTLMSTATE_LAST:
     Curl_safefree(*allocuserpwd);
@@ -238,13 +246,13 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
   return CURLE_OK;
 }
 
-void Curl_http_ntlm_cleanup(struct connectdata *conn)
+void Curl_http_auth_cleanup_ntlm(struct connectdata *conn)
 {
-  Curl_auth_ntlm_cleanup(&conn->ntlm);
-  Curl_auth_ntlm_cleanup(&conn->proxyntlm);
+  Curl_auth_cleanup_ntlm(&conn->ntlm);
+  Curl_auth_cleanup_ntlm(&conn->proxyntlm);
 
 #if defined(NTLM_WB_ENABLED)
-  Curl_ntlm_wb_cleanup(conn);
+  Curl_http_auth_cleanup_ntlm_wb(conn);
 #endif
 }
 
diff --git a/lib/http_ntlm.h b/lib/http_ntlm.h
index d186bbe..003714d 100644
--- a/lib/http_ntlm.h
+++ b/lib/http_ntlm.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_NTLM_H
-#define HEADER_CURL_NTLM_H
+#ifndef HEADER_CURL_HTTP_NTLM_H
+#define HEADER_CURL_HTTP_NTLM_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -33,8 +33,8 @@ CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy,
 /* this is for creating ntlm header output */
 CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
 
-void Curl_http_ntlm_cleanup(struct connectdata *conn);
+void Curl_http_auth_cleanup_ntlm(struct connectdata *conn);
 
 #endif /* !CURL_DISABLE_HTTP && USE_NTLM */
 
-#endif /* HEADER_CURL_NTLM_H */
+#endif /* HEADER_CURL_HTTP_NTLM_H */
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index 2e0d92e..d7ed117 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -643,7 +643,7 @@ static CURLcode CONNECT(struct connectdata *conn,
 
 void Curl_connect_free(struct Curl_easy *data)
 {
-  struct connectdata *conn = data->easy_conn;
+  struct connectdata *conn = data->conn;
   struct http_connect_state *s = conn->connect_state;
   if(s) {
     free(s);
diff --git a/lib/if2ip.c b/lib/if2ip.c
index ce38ea1..d003de6 100644
--- a/lib/if2ip.c
+++ b/lib/if2ip.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -96,26 +96,8 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
 
 #if defined(HAVE_GETIFADDRS)
 
-bool Curl_if_is_interface_name(const char *interf)
-{
-  bool result = FALSE;
-
-  struct ifaddrs *iface, *head;
-
-  if(getifaddrs(&head) >= 0) {
-    for(iface = head; iface != NULL; iface = iface->ifa_next) {
-      if(strcasecompare(iface->ifa_name, interf)) {
-        result = TRUE;
-        break;
-      }
-    }
-    freeifaddrs(head);
-  }
-  return result;
-}
-
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size)
 {
   struct ifaddrs *iface, *head;
@@ -127,7 +109,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 
 #if !defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) || \
     !defined(ENABLE_IPV6)
-  (void) remote_scope_id;
+  (void) local_scope_id;
 #endif
 
   if(getifaddrs(&head) >= 0) {
@@ -141,7 +123,9 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
             char ipstr[64];
 #ifdef ENABLE_IPV6
             if(af == AF_INET6) {
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
               unsigned int scopeid = 0;
+#endif
               unsigned int ifscope = Curl_ipv6_scope(iface->ifa_addr);
 
               if(ifscope != remote_scope) {
@@ -161,15 +145,16 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
                             ->sin6_scope_id;
 
               /* If given, scope id should match. */
-              if(remote_scope_id && scopeid != remote_scope_id) {
+              if(local_scope_id && scopeid != local_scope_id) {
                 if(res == IF2IP_NOT_FOUND)
                   res = IF2IP_AF_NOT_SUPPORTED;
 
                 continue;
               }
-#endif
+
               if(scopeid)
-                snprintf(scope, sizeof(scope), "%%%u", scopeid);
+                  msnprintf(scope, sizeof(scope), "%%%u", scopeid);
+#endif
             }
             else
 #endif
@@ -177,7 +162,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
                   &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
             res = IF2IP_FOUND;
             ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
-            snprintf(buf, buf_size, "%s%s", ip, scope);
+            msnprintf(buf, buf_size, "%s%s", ip, scope);
             break;
           }
         }
@@ -196,17 +181,8 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 
 #elif defined(HAVE_IOCTL_SIOCGIFADDR)
 
-bool Curl_if_is_interface_name(const char *interf)
-{
-  /* This is here just to support the old interfaces */
-  char buf[256];
-
-  return (Curl_if2ip(AF_INET, 0 /* unused */, 0, interf, buf, sizeof(buf)) ==
-          IF2IP_NOT_FOUND) ? FALSE : TRUE;
-}
-
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size)
 {
   struct ifreq req;
@@ -216,7 +192,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
   size_t len;
 
   (void)remote_scope;
-  (void)remote_scope_id;
+  (void)local_scope_id;
 
   if(!interf || (af != AF_INET))
     return IF2IP_NOT_FOUND;
@@ -251,20 +227,13 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 
 #else
 
-bool Curl_if_is_interface_name(const char *interf)
-{
-  (void) interf;
-
-  return FALSE;
-}
-
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size)
 {
     (void) af;
     (void) remote_scope;
-    (void) remote_scope_id;
+    (void) local_scope_id;
     (void) interf;
     (void) buf;
     (void) buf_size;
diff --git a/lib/if2ip.h b/lib/if2ip.h
index a90e662..f193d42 100644
--- a/lib/if2ip.h
+++ b/lib/if2ip.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -32,8 +32,6 @@
 
 unsigned int Curl_ipv6_scope(const struct sockaddr *sa);
 
-bool Curl_if_is_interface_name(const char *interf);
-
 typedef enum {
   IF2IP_NOT_FOUND = 0, /* Interface not found */
   IF2IP_AF_NOT_SUPPORTED = 1, /* Int. exists but has no address for this af */
@@ -41,7 +39,7 @@ typedef enum {
 } if2ip_result_t;
 
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size);
 
 #ifdef __INTERIX
diff --git a/lib/imap.c b/lib/imap.c
index 3ef8909..bdcc69c 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
  * RFC4959 IMAP Extension for SASL Initial Client Response
  * RFC5092 IMAP URL Scheme
  * RFC6749 OAuth 2.0 Authorization Framework
+ * RFC8314 Use of TLS for Email Submission and Access
  * Draft   LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
  *
  ***************************************************************************/
@@ -316,7 +317,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
      a space and optionally some text as per RFC-3501 for the AUTHENTICATE and
      APPEND commands and as outlined in Section 4. Examples of RFC-4959 but
      some e-mail servers ignore this and only send a single + instead. */
-  if(imap && !imap->custom && ((len == 3 && !memcmp("+", line, 1)) ||
+  if(imap && !imap->custom && ((len == 3 && line[0] == '+') ||
      (len >= 2 && !memcmp("+ ", line, 2)))) {
     switch(imapc->state) {
       /* States which are interested in continuation responses */
@@ -1042,7 +1043,7 @@ static CURLcode imap_state_listsearch_resp(struct connectdata *conn,
     line[len] = '\0';
   }
   else if(imapcode != IMAP_RESP_OK)
-    result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
+    result = CURLE_QUOTE_ERROR;
   else
     /* End of DO phase */
     state(conn, IMAP_STOP);
@@ -1114,7 +1115,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
   if(imapcode != '*') {
     Curl_pgrsSetDownloadSize(data, -1);
     state(conn, IMAP_STOP);
-    return CURLE_REMOTE_FILE_NOT_FOUND; /* TODO: Fix error code */
+    return CURLE_REMOTE_FILE_NOT_FOUND;
   }
 
   /* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse
@@ -1177,11 +1178,11 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
 
     if(data->req.bytecount == size)
       /* The entire data is already transferred! */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
     else {
       /* IMAP download */
       data->req.maxdownload = size;
-      Curl_setup_transfer(conn, FIRSTSOCKET, size, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1);
     }
   }
   else {
@@ -1231,7 +1232,7 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode,
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
 
     /* IMAP upload */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
 
     /* End of DO phase */
     state(conn, IMAP_STOP);
@@ -1362,19 +1363,20 @@ static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
       return result;
   }
 
-  result = Curl_pp_statemach(&imapc->pp, FALSE);
+  result = Curl_pp_statemach(&imapc->pp, FALSE, FALSE);
   *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
 
   return result;
 }
 
-static CURLcode imap_block_statemach(struct connectdata *conn)
+static CURLcode imap_block_statemach(struct connectdata *conn,
+                                     bool disconnecting)
 {
   CURLcode result = CURLE_OK;
   struct imap_conn *imapc = &conn->proto.imapc;
 
   while(imapc->state != IMAP_STOP && !result)
-    result = Curl_pp_statemach(&imapc->pp, TRUE);
+    result = Curl_pp_statemach(&imapc->pp, TRUE, disconnecting);
 
   return result;
 }
@@ -1490,14 +1492,9 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
         state(conn, IMAP_APPEND_FINAL);
     }
 
-    /* Run the state-machine
-
-       TODO: when the multi interface is used, this _really_ should be using
-       the imap_multi_statemach function but we have no general support for
-       non-blocking DONE operations!
-    */
+    /* Run the state-machine */
     if(!result)
-      result = imap_block_statemach(conn);
+      result = imap_block_statemach(conn, FALSE);
   }
 
   /* Cleanup our per-request based variables */
@@ -1635,7 +1632,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
      point! */
   if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart)
     if(!imap_perform_logout(conn))
-      (void)imap_block_statemach(conn); /* ignore errors on LOGOUT */
+      (void)imap_block_statemach(conn, TRUE); /* ignore errors on LOGOUT */
 
   /* Disconnect from the server */
   Curl_pp_disconnect(&imapc->pp);
@@ -1659,7 +1656,7 @@ static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
 
   if(imap->transfer != FTPTRANSFER_BODY)
     /* no data to transfer */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
 
   return CURLE_OK;
 }
@@ -1749,8 +1746,8 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
   imapc->cmdid = (imapc->cmdid + 1) % 1000;
 
   /* Calculate the tag based on the connection ID and command ID */
-  snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
-           'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
+  msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
+            'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
 
   /* Prefix the format with the tag */
   taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
@@ -1793,7 +1790,7 @@ static char *imap_atom(const char *str, bool escape_only)
     return NULL;
 
   /* Look for "atom-specials", counting the backslash and quote characters as
-     these will need escapping */
+     these will need escaping */
   p1 = str;
   while(*p1) {
     if(*p1 == '\\')
diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c
index ac5d2d4..855981c 100644
--- a/lib/inet_ntop.c
+++ b/lib/inet_ntop.c
@@ -55,11 +55,11 @@ static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
   DEBUGASSERT(size >= 16);
 
   tmp[0] = '\0';
-  (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
-                 ((int)((unsigned char)src[0])) & 0xff,
-                 ((int)((unsigned char)src[1])) & 0xff,
-                 ((int)((unsigned char)src[2])) & 0xff,
-                 ((int)((unsigned char)src[3])) & 0xff);
+  (void)msnprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
+                  ((int)((unsigned char)src[0])) & 0xff,
+                  ((int)((unsigned char)src[1])) & 0xff,
+                  ((int)((unsigned char)src[2])) & 0xff,
+                  ((int)((unsigned char)src[3])) & 0xff);
 
   len = strlen(tmp);
   if(len == 0 || len >= size) {
@@ -148,7 +148,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
       tp += strlen(tp);
       break;
     }
-    tp += snprintf(tp, 5, "%lx", words[i]);
+    tp += msnprintf(tp, 5, "%lx", words[i]);
   }
 
   /* Was it a trailing run of 0x00's?
diff --git a/lib/inet_pton.c b/lib/inet_pton.c
index fef9610..0d65ae0 100644
--- a/lib/inet_pton.c
+++ b/lib/inet_pton.c
@@ -153,7 +153,7 @@ inet_pton6(const char *src, unsigned char *dst)
   static const char xdigits_l[] = "0123456789abcdef",
     xdigits_u[] = "0123456789ABCDEF";
   unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
-  const char *xdigits, *curtok;
+  const char *curtok;
   int ch, saw_xdigit;
   size_t val;
 
@@ -168,6 +168,7 @@ inet_pton6(const char *src, unsigned char *dst)
   saw_xdigit = 0;
   val = 0;
   while((ch = *src++) != '\0') {
+    const char *xdigits;
     const char *pch;
 
     pch = strchr((xdigits = xdigits_l), ch);
diff --git a/lib/ldap.c b/lib/ldap.c
index ceaa71d..fd31faa 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -5,7 +5,7 @@
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -744,7 +744,7 @@ quit:
 #endif
 
   /* no data to transfer */
-  Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+  Curl_setup_transfer(data, -1, -1, FALSE, -1);
   connclose(conn, "LDAP connection always disable re-use");
 
   return result;
@@ -839,6 +839,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 {
   int rc = LDAP_SUCCESS;
   char *path;
+  char *query;
   char *p;
   char *q;
   size_t i;
@@ -846,7 +847,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
   if(!conn->data ||
      !conn->data->state.up.path ||
      conn->data->state.up.path[0] != '/' ||
-     !strcasecompare("LDAP", conn->data->state.up.scheme))
+     !strncasecompare("LDAP", conn->data->state.up.scheme, 4))
     return LDAP_INVALID_SYNTAX;
 
   ludp->lud_scope = LDAP_SCOPE_BASE;
@@ -858,11 +859,14 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
   if(!path)
     return LDAP_NO_MEMORY;
 
-  /* Parse the DN (Distinguished Name) */
-  q = strchr(p, '?');
-  if(q)
-    *q++ = '\0';
+  /* Duplicate the query */
+  q = query = strdup(conn->data->state.up.query);
+  if(!query) {
+    free(path);
+    return LDAP_NO_MEMORY;
+  }
 
+  /* Parse the DN (Distinguished Name) */
   if(*p) {
     char *dn = p;
     char *unescaped;
@@ -1039,6 +1043,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 
 quit:
   free(path);
+  free(query);
 
   return rc;
 }
@@ -1064,8 +1069,6 @@ static int _ldap_url_parse(const struct connectdata *conn,
 
 static void _ldap_free_urldesc(LDAPURLDesc *ludp)
 {
-  size_t i;
-
   if(!ludp)
     return;
 
@@ -1073,6 +1076,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp)
   free(ludp->lud_filter);
 
   if(ludp->lud_attrs) {
+    size_t i;
     for(i = 0; i < ludp->lud_attrs_dups; i++)
       free(ludp->lud_attrs[i]);
     free(ludp->lud_attrs);
diff --git a/lib/libcurl.rc b/lib/libcurl.rc
index 3316fba..4839d0a 100644
--- a/lib/libcurl.rc
+++ b/lib/libcurl.rc
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,22 +22,22 @@
 #include <winver.h>
 #include "../include/curl/curlver.h"
 
-LANGUAGE  0x09,0x01
+LANGUAGE  0, 0
 
 #define RC_VERSION  LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0
 
 VS_VERSION_INFO VERSIONINFO
   FILEVERSION     RC_VERSION
   PRODUCTVERSION  RC_VERSION
-  FILEFLAGSMASK   0x3fL
+  FILEFLAGSMASK   VS_FFI_FILEFLAGSMASK
 #if defined(DEBUGBUILD) || defined(_DEBUG)
-  FILEFLAGS 1
+  FILEFLAGS VS_FF_DEBUG
 #else
-  FILEFLAGS 0
+  FILEFLAGS 0L
 #endif
   FILEOS      VOS__WINDOWS32
   FILETYPE    VFT_DLL
-  FILESUBTYPE 0x0L
+  FILESUBTYPE 0L
 
 BEGIN
   BLOCK "StringFileInfo"
diff --git a/lib/md4.c b/lib/md4.c
index d350602..e7c77bc 100644
--- a/lib/md4.c
+++ b/lib/md4.c
@@ -1,4 +1,5 @@
 /*
+ * !checksrc! disable COPYRIGHT
  * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
  * MD4 Message-Digest Algorithm (RFC 1320).
  *
@@ -37,9 +38,11 @@
 
 #include "curl_setup.h"
 
-/* The NSS, OS/400 and sometimes mbed TLS crypto libraries do not provide the
- * MD4 hash algorithm, so we have a local implementation of it */
+/* The NSS, OS/400, and when not included, OpenSSL and mbed TLS crypto
+ * libraries do not provide the MD4 hash algorithm, so we use this
+ * implementation of it */
 #if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
 
 #include "curl_md4.h"
@@ -112,7 +115,6 @@ static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
 {
   const unsigned char *ptr;
   MD4_u32plus a, b, c, d;
-  MD4_u32plus saved_a, saved_b, saved_c, saved_d;
 
   ptr = (const unsigned char *)data;
 
@@ -122,6 +124,8 @@ static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
   d = ctx->d;
 
   do {
+    MD4_u32plus saved_a, saved_b, saved_c, saved_d;
+
     saved_a = a;
     saved_b = b;
     saved_c = c;
@@ -129,59 +133,59 @@ static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
 
 /* Round 1 */
     STEP(F, a, b, c, d, SET(0), 3)
-      STEP(F, d, a, b, c, SET(1), 7)
-      STEP(F, c, d, a, b, SET(2), 11)
-      STEP(F, b, c, d, a, SET(3), 19)
-      STEP(F, a, b, c, d, SET(4), 3)
-      STEP(F, d, a, b, c, SET(5), 7)
-      STEP(F, c, d, a, b, SET(6), 11)
-      STEP(F, b, c, d, a, SET(7), 19)
-      STEP(F, a, b, c, d, SET(8), 3)
-      STEP(F, d, a, b, c, SET(9), 7)
-      STEP(F, c, d, a, b, SET(10), 11)
-      STEP(F, b, c, d, a, SET(11), 19)
-      STEP(F, a, b, c, d, SET(12), 3)
-      STEP(F, d, a, b, c, SET(13), 7)
-      STEP(F, c, d, a, b, SET(14), 11)
-      STEP(F, b, c, d, a, SET(15), 19)
+    STEP(F, d, a, b, c, SET(1), 7)
+    STEP(F, c, d, a, b, SET(2), 11)
+    STEP(F, b, c, d, a, SET(3), 19)
+    STEP(F, a, b, c, d, SET(4), 3)
+    STEP(F, d, a, b, c, SET(5), 7)
+    STEP(F, c, d, a, b, SET(6), 11)
+    STEP(F, b, c, d, a, SET(7), 19)
+    STEP(F, a, b, c, d, SET(8), 3)
+    STEP(F, d, a, b, c, SET(9), 7)
+    STEP(F, c, d, a, b, SET(10), 11)
+    STEP(F, b, c, d, a, SET(11), 19)
+    STEP(F, a, b, c, d, SET(12), 3)
+    STEP(F, d, a, b, c, SET(13), 7)
+    STEP(F, c, d, a, b, SET(14), 11)
+    STEP(F, b, c, d, a, SET(15), 19)
 
 /* Round 2 */
-      STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3)
-      STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5)
-      STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9)
-      STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13)
-      STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3)
-      STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5)
-      STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9)
-      STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13)
-      STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3)
-      STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5)
-      STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9)
-      STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13)
-      STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3)
-      STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5)
-      STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9)
-      STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13)
+    STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3)
+    STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5)
+    STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9)
+    STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13)
+    STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3)
+    STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5)
+    STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9)
+    STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13)
+    STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3)
+    STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5)
+    STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9)
+    STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13)
+    STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3)
+    STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5)
+    STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9)
+    STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13)
 
 /* Round 3 */
-      STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3)
-      STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9)
-      STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11)
-      STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15)
-      STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3)
-      STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9)
-      STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11)
-      STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15)
-      STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3)
-      STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9)
-      STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11)
-      STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15)
-      STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3)
-      STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9)
-      STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11)
-      STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15)
-
-      a += saved_a;
+    STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3)
+    STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9)
+    STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11)
+    STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15)
+    STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3)
+    STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9)
+    STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11)
+    STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15)
+    STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3)
+    STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9)
+    STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11)
+    STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15)
+    STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3)
+    STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9)
+    STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11)
+    STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15)
+
+    a += saved_a;
     b += saved_b;
     c += saved_c;
     d += saved_d;
@@ -211,7 +215,7 @@ static void MD4_Init(MD4_CTX *ctx)
 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
 {
   MD4_u32plus saved_lo;
-  unsigned long used, available;
+  unsigned long used;
 
   saved_lo = ctx->lo;
   ctx->lo = (saved_lo + size) & 0x1fffffff;
@@ -222,7 +226,7 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
   used = saved_lo & 0x3f;
 
   if(used) {
-    available = 64 - used;
+    unsigned long available = 64 - used;
 
     if(size < available) {
       memcpy(&ctx->buffer[used], data, size);
@@ -303,5 +307,7 @@ void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
   MD4_Update(&ctx, input, curlx_uztoui(len));
   MD4_Final(output, &ctx);
 }
+
 #endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) ||
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
diff --git a/lib/md5.c b/lib/md5.c
index 45f45bb..2b81ca4 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -39,19 +39,19 @@
 
 typedef struct md5_ctx MD5_CTX;
 
-static void MD5_Init(MD5_CTX * ctx)
+static void MD5_Init(MD5_CTX *ctx)
 {
   md5_init(ctx);
 }
 
-static void MD5_Update(MD5_CTX * ctx,
+static void MD5_Update(MD5_CTX *ctx,
                        const unsigned char *input,
                        unsigned int inputLen)
 {
   md5_update(ctx, inputLen, input);
 }
 
-static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
 {
   md5_digest(ctx, 16, digest);
 }
@@ -65,25 +65,25 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
 
 typedef gcry_md_hd_t MD5_CTX;
 
-static void MD5_Init(MD5_CTX * ctx)
+static void MD5_Init(MD5_CTX *ctx)
 {
   gcry_md_open(ctx, GCRY_MD_MD5, 0);
 }
 
-static void MD5_Update(MD5_CTX * ctx,
+static void MD5_Update(MD5_CTX *ctx,
                        const unsigned char *input,
                        unsigned int inputLen)
 {
   gcry_md_write(*ctx, input, inputLen);
 }
 
-static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
 {
   memcpy(digest, gcry_md_read(*ctx, 0), 16);
   gcry_md_close(*ctx);
 }
 
-#elif defined(USE_OPENSSL)
+#elif defined(USE_OPENSSL) && !defined(USE_AMISSL)
 /* When OpenSSL is available we use the MD5-function from OpenSSL */
 #include <openssl/md5.h>
 #include "curl_memory.h"
@@ -124,7 +124,7 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
   CC_MD5_Final(digest, ctx);
 }
 
-#elif defined(_WIN32) && !defined(CURL_WINDOWS_APP)
+#elif defined(WIN32) && !defined(CURL_WINDOWS_APP)
 
 #include <wincrypt.h>
 #include "curl_memory.h"
@@ -163,13 +163,6 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
     CryptReleaseContext(ctx->hCryptProv, 0);
 }
 
-#elif defined(USE_AXTLS)
-#include <axTLS/config.h>
-#include <axTLS/os_int.h>
-#include <axTLS/crypto.h>
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
 #else
 /* When no other crypto library is available we use this code segment */
 /*
@@ -282,7 +275,6 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
 {
   const unsigned char *ptr;
   MD5_u32plus a, b, c, d;
-  MD5_u32plus saved_a, saved_b, saved_c, saved_d;
 
   ptr = (const unsigned char *)data;
 
@@ -292,6 +284,8 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
   d = ctx->d;
 
   do {
+    MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+
     saved_a = a;
     saved_b = b;
     saved_c = c;
@@ -299,77 +293,77 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
 
 /* Round 1 */
     STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
-      STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
-      STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
-      STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
-      STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
-      STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
-      STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
-      STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
-      STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
-      STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
-      STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
-      STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
-      STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
-      STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
-      STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
-      STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
+    STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
+    STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
+    STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
+    STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
+    STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
+    STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
+    STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
+    STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
+    STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
+    STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
+    STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
+    STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
+    STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
+    STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
+    STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
 
 /* Round 2 */
-      STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
-      STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
-      STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
-      STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
-      STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
-      STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
-      STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
-      STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
-      STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
-      STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
-      STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
-      STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
-      STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
-      STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
-      STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
-      STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
+    STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
+    STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
+    STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
+    STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
+    STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
+    STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
+    STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
+    STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
+    STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
+    STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
+    STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
+    STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
+    STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
+    STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
+    STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
+    STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
 
 /* Round 3 */
-      STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
-      STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
-      STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
-      STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
-      STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
-      STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
-      STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
-      STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
-      STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
-      STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
-      STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
-      STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
-      STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
-      STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
-      STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
-      STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
+    STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
+    STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
+    STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
+    STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
+    STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
+    STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+    STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
+    STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
+    STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
+    STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
+    STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
+    STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
+    STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
+    STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
+    STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
+    STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
 
 /* Round 4 */
-      STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
-      STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
-      STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
-      STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
-      STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
-      STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
-      STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
-      STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
-      STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
-      STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
-      STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
-      STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
-      STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
-      STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
-      STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
-      STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
-
-      a += saved_a;
+    STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
+    STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
+    STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
+    STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
+    STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
+    STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
+    STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
+    STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
+    STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
+    STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
+    STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
+    STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
+    STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
+    STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
+    STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
+    STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
+
+    a += saved_a;
     b += saved_b;
     c += saved_c;
     d += saved_d;
@@ -399,7 +393,7 @@ static void MD5_Init(MD5_CTX *ctx)
 static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
 {
   MD5_u32plus saved_lo;
-  unsigned long used, available;
+  unsigned long used;
 
   saved_lo = ctx->lo;
   ctx->lo = (saved_lo + size) & 0x1fffffff;
@@ -410,7 +404,7 @@ static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
   used = saved_lo & 0x3f;
 
   if(used) {
-    available = 64 - used;
+    unsigned long available = 64 - used;
 
     if(size < available) {
       memcpy(&ctx->buffer[used], data, size);
@@ -552,23 +546,23 @@ MD5_context *Curl_MD5_init(const MD5_params *md5params)
   return ctxt;
 }
 
-int Curl_MD5_update(MD5_context *context,
-                    const unsigned char *data,
-                    unsigned int len)
+CURLcode Curl_MD5_update(MD5_context *context,
+                         const unsigned char *data,
+                         unsigned int len)
 {
   (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len);
 
-  return 0;
+  return CURLE_OK;
 }
 
-int Curl_MD5_final(MD5_context *context, unsigned char *result)
+CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result)
 {
   (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
 
   free(context->md5_hashctx);
   free(context);
 
-  return 0;
+  return CURLE_OK;
 }
 
 #endif /* CURL_DISABLE_CRYPTO_AUTH */
diff --git a/lib/memdebug.c b/lib/memdebug.c
index 2b81c26..ede6009 100644
--- a/lib/memdebug.c
+++ b/lib/memdebug.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -100,30 +100,29 @@ struct memdebug {
  * Don't use these with multithreaded test programs!
  */
 
-#define logfile curl_debuglogfile
-FILE *curl_debuglogfile = NULL;
+FILE *curl_dbg_logfile = NULL;
 static bool memlimit = FALSE; /* enable memory limit */
 static long memsize = 0;  /* set number of mallocs allowed */
 
 /* this sets the log file name */
-void curl_memdebug(const char *logname)
+void curl_dbg_memdebug(const char *logname)
 {
-  if(!logfile) {
+  if(!curl_dbg_logfile) {
     if(logname && *logname)
-      logfile = fopen(logname, FOPEN_WRITETEXT);
+      curl_dbg_logfile = fopen(logname, FOPEN_WRITETEXT);
     else
-      logfile = stderr;
+      curl_dbg_logfile = stderr;
 #ifdef MEMDEBUG_LOG_SYNC
     /* Flush the log file after every line so the log isn't lost in a crash */
-    if(logfile)
-      setbuf(logfile, (char *)NULL);
+    if(curl_dbg_logfile)
+      setbuf(curl_dbg_logfile, (char *)NULL);
 #endif
   }
 }
 
 /* This function sets the number of malloc() calls that should return
    successfully! */
-void curl_memlimit(long limit)
+void curl_dbg_memlimit(long limit)
 {
   if(!memlimit) {
     memlimit = TRUE;
@@ -140,12 +139,12 @@ static bool countcheck(const char *func, int line, const char *source)
     if(!memsize) {
       if(source) {
         /* log to file */
-        curl_memlog("LIMIT %s:%d %s reached memlimit\n",
-                    source, line, func);
+        curl_dbg_log("LIMIT %s:%d %s reached memlimit\n",
+                     source, line, func);
         /* log to stderr also */
         fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
                 source, line, func);
-        fflush(logfile); /* because it might crash now */
+        fflush(curl_dbg_logfile); /* because it might crash now */
       }
       errno = ENOMEM;
       return TRUE; /* RETURN ERROR! */
@@ -159,7 +158,7 @@ static bool countcheck(const char *func, int line, const char *source)
   return FALSE; /* allow this */
 }
 
-void *curl_domalloc(size_t wantedsize, int line, const char *source)
+void *curl_dbg_malloc(size_t wantedsize, int line, const char *source)
 {
   struct memdebug *mem;
   size_t size;
@@ -180,15 +179,15 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
   }
 
   if(source)
-    curl_memlog("MEM %s:%d malloc(%zu) = %p\n",
-                source, line, wantedsize,
-                mem ? (void *)mem->mem : (void *)0);
+    curl_dbg_log("MEM %s:%d malloc(%zu) = %p\n",
+                 source, line, wantedsize,
+                 mem ? (void *)mem->mem : (void *)0);
 
   return (mem ? mem->mem : NULL);
 }
 
-void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
-                    int line, const char *source)
+void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size,
+                      int line, const char *source)
 {
   struct memdebug *mem;
   size_t size, user_size;
@@ -208,14 +207,14 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
     mem->size = user_size;
 
   if(source)
-    curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n",
-                source, line, wanted_elements, wanted_size,
-                mem ? (void *)mem->mem : (void *)0);
+    curl_dbg_log("MEM %s:%d calloc(%zu,%zu) = %p\n",
+                 source, line, wanted_elements, wanted_size,
+                 mem ? (void *)mem->mem : (void *)0);
 
   return (mem ? mem->mem : NULL);
 }
 
-char *curl_dostrdup(const char *str, int line, const char *source)
+char *curl_dbg_strdup(const char *str, int line, const char *source)
 {
   char *mem;
   size_t len;
@@ -227,19 +226,19 @@ char *curl_dostrdup(const char *str, int line, const char *source)
 
   len = strlen(str) + 1;
 
-  mem = curl_domalloc(len, 0, NULL); /* NULL prevents logging */
+  mem = curl_dbg_malloc(len, 0, NULL); /* NULL prevents logging */
   if(mem)
     memcpy(mem, str, len);
 
   if(source)
-    curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
-                source, line, (const void *)str, len, (const void *)mem);
+    curl_dbg_log("MEM %s:%d strdup(%p) (%zu) = %p\n",
+                 source, line, (const void *)str, len, (const void *)mem);
 
   return mem;
 }
 
 #if defined(WIN32) && defined(UNICODE)
-wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
+wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source)
 {
   wchar_t *mem;
   size_t wsiz, bsiz;
@@ -252,12 +251,12 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
   wsiz = wcslen(str) + 1;
   bsiz = wsiz * sizeof(wchar_t);
 
-  mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */
+  mem = curl_dbg_malloc(bsiz, 0, NULL); /* NULL prevents logging */
   if(mem)
     memcpy(mem, str, bsiz);
 
   if(source)
-    curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
+    curl_dbg_log("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
                 source, line, (void *)str, bsiz, (void *)mem);
 
   return mem;
@@ -266,8 +265,8 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
 
 /* We provide a realloc() that accepts a NULL as pointer, which then
    performs a malloc(). In order to work with ares. */
-void *curl_dorealloc(void *ptr, size_t wantedsize,
-                     int line, const char *source)
+void *curl_dbg_realloc(void *ptr, size_t wantedsize,
+                      int line, const char *source)
 {
   struct memdebug *mem = NULL;
 
@@ -293,7 +292,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
 
   mem = (Curl_crealloc)(mem, size);
   if(source)
-    curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n",
+    curl_dbg_log("MEM %s:%d realloc(%p, %zu) = %p\n",
                 source, line, (void *)ptr, wantedsize,
                 mem ? (void *)mem->mem : (void *)0);
 
@@ -305,11 +304,10 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
   return NULL;
 }
 
-void curl_dofree(void *ptr, int line, const char *source)
+void curl_dbg_free(void *ptr, int line, const char *source)
 {
-  struct memdebug *mem;
-
   if(ptr) {
+    struct memdebug *mem;
 
 #ifdef __INTEL_COMPILER
 #  pragma warning(push)
@@ -331,11 +329,11 @@ void curl_dofree(void *ptr, int line, const char *source)
   }
 
   if(source)
-    curl_memlog("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
+    curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
 }
 
-curl_socket_t curl_socket(int domain, int type, int protocol,
-                          int line, const char *source)
+curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
+                             int line, const char *source)
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d socket() = %d\n" :
@@ -351,44 +349,44 @@ curl_socket_t curl_socket(int domain, int type, int protocol,
   sockfd = socket(domain, type, protocol);
 
   if(source && (sockfd != CURL_SOCKET_BAD))
-    curl_memlog(fmt, source, line, sockfd);
+    curl_dbg_log(fmt, source, line, sockfd);
 
   return sockfd;
 }
 
-SEND_TYPE_RETV curl_dosend(SEND_TYPE_ARG1 sockfd,
-                           SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
-                           SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line,
-                           const char *source)
+SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd,
+                            SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
+                            SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line,
+                            const char *source)
 {
   SEND_TYPE_RETV rc;
   if(countcheck("send", line, source))
     return -1;
   rc = send(sockfd, buf, len, flags);
   if(source)
-    curl_memlog("SEND %s:%d send(%lu) = %ld\n",
+    curl_dbg_log("SEND %s:%d send(%lu) = %ld\n",
                 source, line, (unsigned long)len, (long)rc);
   return rc;
 }
 
-RECV_TYPE_RETV curl_dorecv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf,
-                           RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line,
-                           const char *source)
+RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf,
+                            RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line,
+                            const char *source)
 {
   RECV_TYPE_RETV rc;
   if(countcheck("recv", line, source))
     return -1;
   rc = recv(sockfd, buf, len, flags);
   if(source)
-    curl_memlog("RECV %s:%d recv(%lu) = %ld\n",
+    curl_dbg_log("RECV %s:%d recv(%lu) = %ld\n",
                 source, line, (unsigned long)len, (long)rc);
   return rc;
 }
 
 #ifdef HAVE_SOCKETPAIR
-int curl_socketpair(int domain, int type, int protocol,
-                    curl_socket_t socket_vector[2],
-                    int line, const char *source)
+int curl_dbg_socketpair(int domain, int type, int protocol,
+                       curl_socket_t socket_vector[2],
+                       int line, const char *source)
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d socketpair() = %d %d\n" :
@@ -399,14 +397,14 @@ int curl_socketpair(int domain, int type, int protocol,
   int res = socketpair(domain, type, protocol, socket_vector);
 
   if(source && (0 == res))
-    curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]);
+    curl_dbg_log(fmt, source, line, socket_vector[0], socket_vector[1]);
 
   return res;
 }
 #endif
 
-curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
-                          int line, const char *source)
+curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen,
+                             int line, const char *source)
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d accept() = %d\n" :
@@ -420,13 +418,13 @@ curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
   curl_socket_t sockfd = accept(s, addr, addrlen);
 
   if(source && (sockfd != CURL_SOCKET_BAD))
-    curl_memlog(fmt, source, line, sockfd);
+    curl_dbg_log(fmt, source, line, sockfd);
 
   return sockfd;
 }
 
 /* separate function to allow libcurl to mark a "faked" close */
-void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source)
+void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source)
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d sclose(%d)\n":
@@ -435,54 +433,40 @@ void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source)
     "FD %s:%d sclose(%zd)\n";
 
   if(source)
-    curl_memlog(fmt, source, line, sockfd);
+    curl_dbg_log(fmt, source, line, sockfd);
 }
 
 /* this is our own defined way to close sockets on *ALL* platforms */
-int curl_sclose(curl_socket_t sockfd, int line, const char *source)
+int curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source)
 {
   int res = sclose(sockfd);
-  curl_mark_sclose(sockfd, line, source);
+  curl_dbg_mark_sclose(sockfd, line, source);
   return res;
 }
 
-FILE *curl_fopen(const char *file, const char *mode,
-                 int line, const char *source)
+FILE *curl_dbg_fopen(const char *file, const char *mode,
+                    int line, const char *source)
 {
   FILE *res = fopen(file, mode);
 
   if(source)
-    curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
+    curl_dbg_log("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
                 source, line, file, mode, (void *)res);
 
   return res;
 }
 
-#ifdef HAVE_FDOPEN
-FILE *curl_fdopen(int filedes, const char *mode,
-                  int line, const char *source)
-{
-  FILE *res = fdopen(filedes, mode);
-
-  if(source)
-    curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
-                source, line, filedes, mode, (void *)res);
-
-  return res;
-}
-#endif
-
-int curl_fclose(FILE *file, int line, const char *source)
+int curl_dbg_fclose(FILE *file, int line, const char *source)
 {
   int res;
 
   DEBUGASSERT(file != NULL);
 
-  res = fclose(file);
-
   if(source)
-    curl_memlog("FILE %s:%d fclose(%p)\n",
-                source, line, (void *)file);
+    curl_dbg_log("FILE %s:%d fclose(%p)\n",
+                 source, line, (void *)file);
+
+  res = fclose(file);
 
   return res;
 }
@@ -490,13 +474,13 @@ int curl_fclose(FILE *file, int line, const char *source)
 #define LOGLINE_BUFSIZE  1024
 
 /* this does the writing to the memory tracking log file */
-void curl_memlog(const char *format, ...)
+void curl_dbg_log(const char *format, ...)
 {
   char *buf;
   int nchars;
   va_list ap;
 
-  if(!logfile)
+  if(!curl_dbg_logfile)
     return;
 
   buf = (Curl_cmalloc)(LOGLINE_BUFSIZE);
@@ -504,14 +488,14 @@ void curl_memlog(const char *format, ...)
     return;
 
   va_start(ap, format);
-  nchars = vsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
+  nchars = mvsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
   va_end(ap);
 
   if(nchars > LOGLINE_BUFSIZE - 1)
     nchars = LOGLINE_BUFSIZE - 1;
 
   if(nchars > 0)
-    fwrite(buf, 1, (size_t)nchars, logfile);
+    fwrite(buf, 1, (size_t)nchars, curl_dbg_logfile);
 
   (Curl_cfree)(buf);
 }
diff --git a/lib/memdebug.h b/lib/memdebug.h
index 233de65..5236f60 100644
--- a/lib/memdebug.h
+++ b/lib/memdebug.h
@@ -8,7 +8,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -30,97 +30,92 @@
 
 #define CURL_MT_LOGFNAME_BUFSIZE 512
 
-#define logfile curl_debuglogfile
-
-extern FILE *logfile;
+extern FILE *curl_dbg_logfile;
 
 /* memory functions */
-CURL_EXTERN void *curl_domalloc(size_t size, int line, const char *source);
-CURL_EXTERN void *curl_docalloc(size_t elements, size_t size, int line,
-                                const char *source);
-CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line,
-                                 const char *source);
-CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source);
-CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source);
-#if defined(WIN32) && defined(UNICODE)
-CURL_EXTERN wchar_t *curl_dowcsdup(const wchar_t *str, int line,
+CURL_EXTERN void *curl_dbg_malloc(size_t size, int line, const char *source);
+CURL_EXTERN void *curl_dbg_calloc(size_t elements, size_t size, int line,
+                                  const char *source);
+CURL_EXTERN void *curl_dbg_realloc(void *ptr, size_t size, int line,
                                    const char *source);
+CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source);
+CURL_EXTERN char *curl_dbg_strdup(const char *str, int line, const char *src);
+#if defined(WIN32) && defined(UNICODE)
+CURL_EXTERN wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line,
+                                     const char *source);
 #endif
 
-CURL_EXTERN void curl_memdebug(const char *logname);
-CURL_EXTERN void curl_memlimit(long limit);
-CURL_EXTERN void curl_memlog(const char *format, ...);
+CURL_EXTERN void curl_dbg_memdebug(const char *logname);
+CURL_EXTERN void curl_dbg_memlimit(long limit);
+CURL_EXTERN void curl_dbg_log(const char *format, ...);
 
 /* file descriptor manipulators */
-CURL_EXTERN curl_socket_t curl_socket(int domain, int type, int protocol,
-                                      int line, const char *source);
-CURL_EXTERN void curl_mark_sclose(curl_socket_t sockfd,
-                                  int line, const char *source);
-CURL_EXTERN int curl_sclose(curl_socket_t sockfd,
-                            int line, const char *source);
-CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen,
+CURL_EXTERN curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
+                                          int line, const char *source);
+CURL_EXTERN void curl_dbg_mark_sclose(curl_socket_t sockfd,
                                       int line, const char *source);
-#ifdef HAVE_SOCKETPAIR
-CURL_EXTERN int curl_socketpair(int domain, int type, int protocol,
-                                curl_socket_t socket_vector[2],
+CURL_EXTERN int curl_dbg_sclose(curl_socket_t sockfd,
                                 int line, const char *source);
+CURL_EXTERN curl_socket_t curl_dbg_accept(curl_socket_t s, void *a, void *alen,
+                                          int line, const char *source);
+#ifdef HAVE_SOCKETPAIR
+CURL_EXTERN int curl_dbg_socketpair(int domain, int type, int protocol,
+                                    curl_socket_t socket_vector[2],
+                                    int line, const char *source);
 #endif
 
 /* send/receive sockets */
-CURL_EXTERN SEND_TYPE_RETV curl_dosend(SEND_TYPE_ARG1 sockfd,
-                                       SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
-                                       SEND_TYPE_ARG3 len,
-                                       SEND_TYPE_ARG4 flags, int line,
-                                       const char *source);
-CURL_EXTERN RECV_TYPE_RETV curl_dorecv(RECV_TYPE_ARG1 sockfd,
-                                       RECV_TYPE_ARG2 buf, RECV_TYPE_ARG3 len,
-                                       RECV_TYPE_ARG4 flags, int line,
-                                       const char *source);
+CURL_EXTERN SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd,
+                                         SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
+                                         SEND_TYPE_ARG3 len,
+                                         SEND_TYPE_ARG4 flags, int line,
+                                         const char *source);
+CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd,
+                                         RECV_TYPE_ARG2 buf,
+                                         RECV_TYPE_ARG3 len,
+                                         RECV_TYPE_ARG4 flags, int line,
+                                         const char *source);
 
 /* FILE functions */
-CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line,
-                             const char *source);
-#ifdef HAVE_FDOPEN
-CURL_EXTERN FILE *curl_fdopen(int filedes, const char *mode, int line,
-                              const char *source);
-#endif
-CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
+CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line,
+                                 const char *source);
+CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source);
 
 #ifndef MEMDEBUG_NODEFINES
 
 /* Set this symbol on the command-line, recompile all lib-sources */
 #undef strdup
-#define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
-#define malloc(size) curl_domalloc(size, __LINE__, __FILE__)
-#define calloc(nbelem,size) curl_docalloc(nbelem, size, __LINE__, __FILE__)
-#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
-#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
-#define send(a,b,c,d) curl_dosend(a,b,c,d, __LINE__, __FILE__)
-#define recv(a,b,c,d) curl_dorecv(a,b,c,d, __LINE__, __FILE__)
+#define strdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__)
+#define malloc(size) curl_dbg_malloc(size, __LINE__, __FILE__)
+#define calloc(nbelem,size) curl_dbg_calloc(nbelem, size, __LINE__, __FILE__)
+#define realloc(ptr,size) curl_dbg_realloc(ptr, size, __LINE__, __FILE__)
+#define free(ptr) curl_dbg_free(ptr, __LINE__, __FILE__)
+#define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__)
+#define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__)
 
 #ifdef WIN32
 #  ifdef UNICODE
 #    undef wcsdup
-#    define wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+#    define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
 #    undef _wcsdup
-#    define _wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+#    define _wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
 #    undef _tcsdup
-#    define _tcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+#    define _tcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
 #  else
 #    undef _tcsdup
-#    define _tcsdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
+#    define _tcsdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__)
 #  endif
 #endif
 
 #undef socket
 #define socket(domain,type,protocol)\
- curl_socket(domain, type, protocol, __LINE__, __FILE__)
+ curl_dbg_socket(domain, type, protocol, __LINE__, __FILE__)
 #undef accept /* for those with accept as a macro */
 #define accept(sock,addr,len)\
- curl_accept(sock, addr, len, __LINE__, __FILE__)
+ curl_dbg_accept(sock, addr, len, __LINE__, __FILE__)
 #ifdef HAVE_SOCKETPAIR
 #define socketpair(domain,type,protocol,socket_vector)\
- curl_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__)
+ curl_dbg_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__)
 #endif
 
 #ifdef HAVE_GETADDRINFO
@@ -129,31 +124,31 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
    our macro as for other platforms. Instead, we redefine the new name they
    define getaddrinfo to become! */
 #define ogetaddrinfo(host,serv,hint,res) \
-  curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
+  curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
 #else
 #undef getaddrinfo
 #define getaddrinfo(host,serv,hint,res) \
-  curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
+  curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
 #endif
 #endif /* HAVE_GETADDRINFO */
 
 #ifdef HAVE_FREEADDRINFO
 #undef freeaddrinfo
 #define freeaddrinfo(data) \
-  curl_dofreeaddrinfo(data, __LINE__, __FILE__)
+  curl_dbg_freeaddrinfo(data, __LINE__, __FILE__)
 #endif /* HAVE_FREEADDRINFO */
 
 /* sclose is probably already defined, redefine it! */
 #undef sclose
-#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)
+#define sclose(sockfd) curl_dbg_sclose(sockfd,__LINE__,__FILE__)
 
-#define fake_sclose(sockfd) curl_mark_sclose(sockfd,__LINE__,__FILE__)
+#define fake_sclose(sockfd) curl_dbg_mark_sclose(sockfd,__LINE__,__FILE__)
 
 #undef fopen
-#define fopen(file,mode) curl_fopen(file,mode,__LINE__,__FILE__)
+#define fopen(file,mode) curl_dbg_fopen(file,mode,__LINE__,__FILE__)
 #undef fdopen
-#define fdopen(file,mode) curl_fdopen(file,mode,__LINE__,__FILE__)
-#define fclose(file) curl_fclose(file,__LINE__,__FILE__)
+#define fdopen(file,mode) curl_dbg_fdopen(file,mode,__LINE__,__FILE__)
+#define fclose(file) curl_dbg_fclose(file,__LINE__,__FILE__)
 
 #endif /* MEMDEBUG_NODEFINES */
 
diff --git a/lib/mime.c b/lib/mime.c
index ca492d1..2135f72 100644
--- a/lib/mime.c
+++ b/lib/mime.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -29,8 +29,8 @@
 #include "urldata.h"
 #include "sendf.h"
 
-#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
-    !defined(CURL_DISABLE_IMAP)
+#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
+  !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
 
 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
 #include <libgen.h>
@@ -821,8 +821,10 @@ static size_t readback_part(curl_mimepart *part,
     struct curl_slist *hdr = (struct curl_slist *) part->state.ptr;
     switch(part->state.state) {
     case MIMESTATE_BEGIN:
-      mimesetstate(&part->state, part->flags & MIME_BODY_ONLY? MIMESTATE_BODY:
-                                 MIMESTATE_CURLHEADERS, part->curlheaders);
+      mimesetstate(&part->state,
+                   (part->flags & MIME_BODY_ONLY)?
+                     MIMESTATE_BODY: MIMESTATE_CURLHEADERS,
+                   part->curlheaders);
       break;
     case MIMESTATE_USERHEADERS:
       if(!hdr) {
@@ -1122,8 +1124,6 @@ void curl_mime_free(curl_mime *mime)
       Curl_mime_cleanpart(part);
       free(part);
     }
-
-    free(mime->boundary);
     free(mime);
   }
 }
@@ -1220,18 +1220,10 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
     mime->firstpart = NULL;
     mime->lastpart = NULL;
 
-    /* Get a part boundary. */
-    mime->boundary = malloc(24 + MIME_RAND_BOUNDARY_CHARS + 1);
-    if(!mime->boundary) {
-      free(mime);
-      return NULL;
-    }
-
     memset(mime->boundary, '-', 24);
-    if(Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24,
+    if(Curl_rand_hex(easy, (unsigned char *) &mime->boundary[24],
                      MIME_RAND_BOUNDARY_CHARS + 1)) {
       /* failed to get random separator, bail out */
-      free(mime->boundary);
       free(mime);
       return NULL;
     }
@@ -1909,72 +1901,4 @@ CURLcode curl_mime_headers(curl_mimepart *part,
   return CURLE_NOT_BUILT_IN;
 }
 
-void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
-{
-  (void) part;
-  (void) easy;
-}
-
-void Curl_mime_cleanpart(curl_mimepart *part)
-{
-  (void) part;
-}
-
-CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
-{
-  (void) dst;
-  (void) src;
-  return CURLE_OK;    /* Nothing to duplicate: always succeed. */
-}
-
-CURLcode Curl_mime_set_subparts(curl_mimepart *part,
-                                curl_mime *subparts, int take_ownership)
-{
-  (void) part;
-  (void) subparts;
-  (void) take_ownership;
-  return CURLE_NOT_BUILT_IN;
-}
-
-CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
-                                   const char *contenttype,
-                                   const char *disposition,
-                                   enum mimestrategy strategy)
-{
-  (void) part;
-  (void) contenttype;
-  (void) disposition;
-  (void) strategy;
-  return CURLE_NOT_BUILT_IN;
-}
-
-curl_off_t Curl_mime_size(curl_mimepart *part)
-{
-  (void) part;
-  return (curl_off_t) -1;
-}
-
-size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
-{
-  (void) buffer;
-  (void) size;
-  (void) nitems;
-  (void) instream;
-  return 0;
-}
-
-CURLcode Curl_mime_rewind(curl_mimepart *part)
-{
-  (void) part;
-  return CURLE_NOT_BUILT_IN;
-}
-
-/* VARARGS2 */
-CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
-{
-  (void) slp;
-  (void) fmt;
-  return CURLE_NOT_BUILT_IN;
-}
-
-#endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
+#endif /* if disabled */
diff --git a/lib/mime.h b/lib/mime.h
index 4d5c704..4c9a5fb 100644
--- a/lib/mime.h
+++ b/lib/mime.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,8 @@
  *
  ***************************************************************************/
 
+#include "curl_setup.h"
+
 #define MIME_RAND_BOUNDARY_CHARS        16  /* Nb. of random boundary chars. */
 #define MAX_ENCODED_LINE_LENGTH         76  /* Maximum encoded line length. */
 #define ENCODING_BUFFER_SIZE            256 /* Encoding temp buffers size. */
@@ -69,7 +71,7 @@ enum mimestrategy {
 typedef struct {
   const char *   name;          /* Encoding name. */
   size_t         (*encodefunc)(char *buffer, size_t size, bool ateof,
-                             curl_mimepart *part);  /* Encoded read. */
+                               curl_mimepart *part);  /* Encoded read. */
   curl_off_t     (*sizefunc)(curl_mimepart *part);  /* Encoded size. */
 }  mime_encoder;
 
@@ -88,13 +90,16 @@ typedef struct {
   size_t offset;              /* State-dependent offset. */
 }  mime_state;
 
+/* minimum buffer size for the boundary string */
+#define MIME_BOUNDARY_LEN (24 + MIME_RAND_BOUNDARY_CHARS + 1)
+
 /* A mime multipart. */
 struct curl_mime_s {
   struct Curl_easy *easy;          /* The associated easy handle. */
   curl_mimepart *parent;           /* Parent part. */
   curl_mimepart *firstpart;        /* First part. */
   curl_mimepart *lastpart;         /* Last part. */
-  char *boundary;                  /* The part boundary. */
+  char boundary[MIME_BOUNDARY_LEN]; /* The part boundary. */
   mime_state state;                /* Current readback state. */
 };
 
@@ -122,6 +127,8 @@ struct curl_mimepart_s {
   mime_encoder_state encstate;     /* Data encoder state. */
 };
 
+#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
+  !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
 
 /* Prototypes. */
 void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy);
@@ -140,4 +147,18 @@ CURLcode Curl_mime_rewind(curl_mimepart *part);
 CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
 const char *Curl_mime_contenttype(const char *filename);
 
+#else
+/* if disabled */
+#define Curl_mime_initpart(x,y)
+#define Curl_mime_cleanpart(x)
+#define Curl_mime_duppart(x,y) CURLE_OK /* Nothing to duplicate. Succeed */
+#define Curl_mime_set_subparts(a,b,c) CURLE_NOT_BUILT_IN
+#define Curl_mime_prepare_headers(a,b,c,d) CURLE_NOT_BUILT_IN
+#define Curl_mime_size(x) (curl_off_t) -1
+#define Curl_mime_read NULL
+#define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define Curl_mime_add_header(x,y,...) CURLE_NOT_BUILT_IN
+#endif
+
+
 #endif /* HEADER_CURL_MIME_H */
diff --git a/lib/mprintf.c b/lib/mprintf.c
index d2d91d7..e190936 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -835,7 +835,7 @@ static int dprintf_formatf(
           while(width-- > 0)
             OUTCHAR(' ');
 
-        while((len-- > 0) && *str)
+        for(; len && *str; len--)
           OUTCHAR(*str++);
         if(p->flags&FLAGS_LEFT)
           while(width-- > 0)
diff --git a/lib/multi.c b/lib/multi.c
index 0db2a97..c7c46ee 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -41,11 +41,11 @@
 #include "speedcheck.h"
 #include "conncache.h"
 #include "multihandle.h"
-#include "pipeline.h"
 #include "sigpipe.h"
 #include "vtls/vtls.h"
 #include "connect.h"
 #include "http_proxy.h"
+#include "http2.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -79,6 +79,7 @@ static CURLMcode add_next_timeout(struct curltime now,
 static CURLMcode multi_timeout(struct Curl_multi *multi,
                                long *timeout_ms);
 static void process_pending_handles(struct Curl_multi *multi);
+static void detach_connnection(struct Curl_easy *data);
 
 #ifdef DEBUGBUILD
 static const char * const statename[]={
@@ -90,12 +91,10 @@ static const char * const statename[]={
   "WAITPROXYCONNECT",
   "SENDPROTOCONNECT",
   "PROTOCONNECT",
-  "WAITDO",
   "DO",
   "DOING",
   "DO_MORE",
   "DO_DONE",
-  "WAITPERFORM",
   "PERFORM",
   "TOOFAST",
   "DONE",
@@ -113,7 +112,7 @@ static void Curl_init_completed(struct Curl_easy *data)
 
   /* Important: reset the conn pointer so that we don't point to memory
      that could be freed anytime */
-  data->easy_conn = NULL;
+  detach_connnection(data);
   Curl_expire_clear(data); /* stop all timers */
 }
 
@@ -134,12 +133,10 @@ static void mstate(struct Curl_easy *data, CURLMstate state
     NULL,              /* WAITPROXYCONNECT */
     NULL,              /* SENDPROTOCONNECT */
     NULL,              /* PROTOCONNECT */
-    NULL,              /* WAITDO */
     Curl_connect_free, /* DO */
     NULL,              /* DOING */
     NULL,              /* DO_MORE */
     NULL,              /* DO_DONE */
-    NULL,              /* WAITPERFORM */
     NULL,              /* PERFORM */
     NULL,              /* TOOFAST */
     NULL,              /* DONE */
@@ -162,8 +159,8 @@ static void mstate(struct Curl_easy *data, CURLMstate state
      data->mstate < CURLM_STATE_COMPLETED) {
     long connection_id = -5000;
 
-    if(data->easy_conn)
-      connection_id = data->easy_conn->connection_id;
+    if(data->conn)
+      connection_id = data->conn->connection_id;
 
     infof(data,
           "STATE: %s => %s handle %p; line %d (connection #%ld)\n",
@@ -188,14 +185,17 @@ static void mstate(struct Curl_easy *data, CURLMstate state
 #endif
 
 /*
- * We add one of these structs to the sockhash for a particular socket
+ * We add one of these structs to the sockhash for each socket
  */
 
 struct Curl_sh_entry {
-  struct Curl_easy *easy;
-  int action;  /* what action READ/WRITE this socket waits for */
-  curl_socket_t socket; /* mainly to ease debugging */
+  struct curl_llist list; /* list of easy handles using this socket */
+  unsigned int action;  /* what combined action READ/WRITE this socket waits
+                           for */
   void *socketp; /* settable by users with curl_multi_assign() */
+  unsigned int users; /* number of transfers using this */
+  unsigned int readers; /* this many transfers want to read */
+  unsigned int writers; /* this many transfers want to write */
 };
 /* bits for 'action' having no bits means this socket is not expecting any
    action */
@@ -214,8 +214,7 @@ static struct Curl_sh_entry *sh_getentry(struct curl_hash *sh,
 
 /* make sure this socket is present in the hash for this handle */
 static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
-                                         curl_socket_t s,
-                                         struct Curl_easy *data)
+                                         curl_socket_t s)
 {
   struct Curl_sh_entry *there = sh_getentry(sh, s);
   struct Curl_sh_entry *check;
@@ -229,8 +228,7 @@ static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
   if(!check)
     return NULL; /* major failure */
 
-  check->easy = data;
-  check->socket = s;
+  Curl_llist_init(&check->list, NULL);
 
   /* make/add new hash entry */
   if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
@@ -346,9 +344,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
   Curl_llist_init(&multi->msglist, multi_freeamsg);
   Curl_llist_init(&multi->pending, multi_freeamsg);
 
-  multi->max_pipeline_length = 5;
-  multi->pipelining = CURLPIPE_MULTIPLEX;
-
   /* -1 means it not set by user, use the default value */
   multi->maxconnects = -1;
   return multi;
@@ -405,19 +400,9 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
   /* set the easy handle */
   multistate(data, CURLM_STATE_INIT);
 
-  if((data->set.global_dns_cache) &&
-     (data->dns.hostcachetype != HCACHE_GLOBAL)) {
-    /* global dns cache was requested but still isn't */
-    struct curl_hash *global = Curl_global_host_cache_init();
-    if(global) {
-      /* only do this if the global cache init works */
-      data->dns.hostcache = global;
-      data->dns.hostcachetype = HCACHE_GLOBAL;
-    }
-  }
   /* for multi interface connections, we share DNS cache automatically if the
      easy handle's one is currently not set. */
-  else if(!data->dns.hostcache ||
+  if(!data->dns.hostcache ||
      (data->dns.hostcachetype == HCACHE_NONE)) {
     data->dns.hostcache = &multi->hostcache;
     data->dns.hostcachetype = HCACHE_MULTI;
@@ -437,12 +422,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
     data->psl = &multi->psl;
 #endif
 
-  /* This adds the new entry at the 'end' of the doubly-linked circular
-     list of Curl_easy structs to try and maintain a FIFO queue so
-     the pipelined requests are in order. */
-
-  /* We add this new entry last in the list. */
-
+  /* We add the new entry last in the list. */
   data->next = NULL; /* end of the line */
   if(multi->easyp) {
     struct Curl_easy *last = multi->easylp;
@@ -515,33 +495,23 @@ static void debug_print_sock_hash(void *p)
 }
 #endif
 
-static CURLcode multi_done(struct connectdata **connp,
-                          CURLcode status,  /* an error if this is called
-                                               after an error was detected */
-                          bool premature)
+static CURLcode multi_done(struct Curl_easy *data,
+                           CURLcode status,  /* an error if this is called
+                                                after an error was detected */
+                           bool premature)
 {
   CURLcode result;
-  struct connectdata *conn;
-  struct Curl_easy *data;
+  struct connectdata *conn = data->conn;
   unsigned int i;
 
-  DEBUGASSERT(*connp);
-
-  conn = *connp;
-  data = conn->data;
-
   DEBUGF(infof(data, "multi_done\n"));
 
   if(data->state.done)
     /* Stop if multi_done() has already been called */
     return CURLE_OK;
 
-  if(data->mstate == CURLM_STATE_WAITRESOLVE) {
-    /* still waiting for the resolve to complete */
-    (void)Curl_resolver_wait_resolv(conn, NULL);
-  }
-
-  Curl_getoff_all_pipelines(data, conn);
+  /* Stop the resolver and free its own resources (but not dns_entry yet). */
+  Curl_resolver_kill(conn);
 
   /* Cleanup possible redirect junk */
   Curl_safefree(data->req.newurl);
@@ -576,17 +546,16 @@ static CURLcode multi_done(struct connectdata **connp,
 
   process_pending_handles(data->multi); /* connection / multiplex */
 
-  if(conn->send_pipe.size || conn->recv_pipe.size) {
-    /* Stop if pipeline is not empty . */
-    data->easy_conn = NULL;
-    DEBUGF(infof(data, "Connection still in use %zu/%zu, "
+  detach_connnection(data);
+  if(CONN_INUSE(conn)) {
+    /* Stop if still used. */
+    DEBUGF(infof(data, "Connection still in use %zu, "
                  "no more multi_done now!\n",
-                 conn->send_pipe.size, conn->recv_pipe.size));
+                 conn->easyq.size));
     return CURLE_OK;
   }
 
   data->state.done = TRUE; /* called just now! */
-  Curl_resolver_cancel(conn);
 
   if(conn->dns_entry) {
     Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
@@ -604,7 +573,7 @@ static CURLcode multi_done(struct connectdata **connp,
 
   /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
      forced us to close this connection. This is ignored for requests taking
-     place in a NTLM authentication handshake
+     place in a NTLM/NEGOTIATE authentication handshake
 
      if conn->bits.close is TRUE, it means that the connection should be
      closed in spite of all our efforts to be nice, due to protocol
@@ -619,8 +588,12 @@ static CURLcode multi_done(struct connectdata **connp,
 
   if((data->set.reuse_forbid
 #if defined(USE_NTLM)
-      && !(conn->ntlm.state == NTLMSTATE_TYPE2 ||
-           conn->proxyntlm.state == NTLMSTATE_TYPE2)
+      && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
+           conn->proxy_ntlm_state == NTLMSTATE_TYPE2)
+#endif
+#if defined(USE_SPNEGO)
+      && !(conn->http_negotiate_state == GSS_AUTHRECV ||
+           conn->proxy_negotiate_state == GSS_AUTHRECV)
 #endif
      ) || conn->bits.close
        || (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
@@ -634,13 +607,13 @@ static CURLcode multi_done(struct connectdata **connp,
   else {
     char buffer[256];
     /* create string before returning the connection */
-    snprintf(buffer, sizeof(buffer),
-             "Connection #%ld to host %s left intact",
-             conn->connection_id,
-             conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
-             conn->bits.httpproxy ? conn->http_proxy.host.dispname :
-             conn->bits.conn_to_host ? conn->conn_to_host.dispname :
-             conn->host.dispname);
+    msnprintf(buffer, sizeof(buffer),
+              "Connection #%ld to host %s left intact",
+              conn->connection_id,
+              conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
+              conn->bits.httpproxy ? conn->http_proxy.host.dispname :
+              conn->bits.conn_to_host ? conn->conn_to_host.dispname :
+              conn->host.dispname);
 
     /* the connection is no longer in use by this transfer */
     if(Curl_conncache_return_conn(conn)) {
@@ -652,10 +625,6 @@ static CURLcode multi_done(struct connectdata **connp,
       data->state.lastconnect = NULL;
   }
 
-  *connp = NULL; /* to make the caller of this function better detect that
-                    this was either closed or handed over to the connection
-                    cache here, and therefore cannot be used from this point on
-                 */
   Curl_free_request_state(data);
   return result;
 }
@@ -684,7 +653,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
     return CURLM_RECURSIVE_API_CALL;
 
   premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
-  easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ?
+  easy_owns_conn = (data->conn && (data->conn->data == easy)) ?
     TRUE : FALSE;
 
   /* If the 'state' is not INIT or COMPLETED, we might need to do something
@@ -695,16 +664,13 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
     multi->num_alive--;
   }
 
-  if(data->easy_conn &&
+  if(data->conn &&
      data->mstate > CURLM_STATE_DO &&
      data->mstate < CURLM_STATE_COMPLETED) {
     /* Set connection owner so that the DONE function closes it.  We can
        safely do this here since connection is killed. */
-    data->easy_conn->data = easy;
-    /* If the handle is in a pipeline and has started sending off its
-       request but not received its response yet, we need to close
-       connection. */
-    streamclose(data->easy_conn, "Removed with partial response");
+    data->conn->data = easy;
+    streamclose(data->conn, "Removed with partial response");
     easy_owns_conn = TRUE;
   }
 
@@ -713,7 +679,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
      curl_easy_cleanup is called. */
   Curl_expire_clear(data);
 
-  if(data->easy_conn) {
+  if(data->conn) {
 
     /* we must call multi_done() here (if we still own the connection) so that
        we don't leave a half-baked one around */
@@ -724,11 +690,8 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
 
          Note that this ignores the return code simply because there's
          nothing really useful to do with it anyway! */
-      (void)multi_done(&data->easy_conn, data->result, premature);
+      (void)multi_done(data, data->result, premature);
     }
-    else
-      /* Clear connection pipelines, if multi_done above was not called */
-      Curl_getoff_all_pipelines(data, data->easy_conn);
   }
 
   if(data->connect_queue.ptr)
@@ -760,9 +723,9 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
                                 vanish with this handle */
 
   /* Remove the association between the connection and the handle */
-  if(data->easy_conn) {
-    data->easy_conn->data = NULL;
-    data->easy_conn = NULL;
+  if(data->conn) {
+    data->conn->data = NULL;
+    detach_connnection(data);
   }
 
 #ifdef USE_LIBPSL
@@ -806,15 +769,31 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
   return CURLM_OK;
 }
 
-/* Return TRUE if the application asked for a certain set of pipelining */
-bool Curl_pipeline_wanted(const struct Curl_multi *multi, int bits)
+/* Return TRUE if the application asked for multiplexing */
+bool Curl_multiplex_wanted(const struct Curl_multi *multi)
+{
+  return (multi && (multi->multiplexing));
+}
+
+/* This is the only function that should clear data->conn. This will
+   occasionally be called with the pointer already cleared. */
+static void detach_connnection(struct Curl_easy *data)
 {
-  return (multi && (multi->pipelining & bits)) ? TRUE : FALSE;
+  struct connectdata *conn = data->conn;
+  if(conn)
+    Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
+  data->conn = NULL;
 }
 
-void Curl_multi_handlePipeBreak(struct Curl_easy *data)
+/* This is the only function that should assign data->conn */
+void Curl_attach_connnection(struct Curl_easy *data,
+                             struct connectdata *conn)
 {
-  data->easy_conn = NULL;
+  DEBUGASSERT(!data->conn);
+  DEBUGASSERT(conn);
+  data->conn = conn;
+  Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
+                         &data->conn_queue);
 }
 
 static int waitconnect_getsock(struct connectdata *conn,
@@ -878,13 +857,13 @@ static int multi_getsock(struct Curl_easy *data,
   /* The no connection case can happen when this is called from
      curl_multi_remove_handle() => singlesocket() => multi_getsock().
   */
-  if(!data->easy_conn)
+  if(!data->conn)
     return 0;
 
   if(data->mstate > CURLM_STATE_CONNECT &&
      data->mstate < CURLM_STATE_COMPLETED) {
     /* Set up ownership correctly */
-    data->easy_conn->data = data;
+    data->conn->data = data;
   }
 
   switch(data->mstate) {
@@ -905,31 +884,30 @@ static int multi_getsock(struct Curl_easy *data,
     return 0;
 
   case CURLM_STATE_WAITRESOLVE:
-    return Curl_resolv_getsock(data->easy_conn, socks, numsocks);
+    return Curl_resolv_getsock(data->conn, socks, numsocks);
 
   case CURLM_STATE_PROTOCONNECT:
   case CURLM_STATE_SENDPROTOCONNECT:
-    return Curl_protocol_getsock(data->easy_conn, socks, numsocks);
+    return Curl_protocol_getsock(data->conn, socks, numsocks);
 
   case CURLM_STATE_DO:
   case CURLM_STATE_DOING:
-    return Curl_doing_getsock(data->easy_conn, socks, numsocks);
+    return Curl_doing_getsock(data->conn, socks, numsocks);
 
   case CURLM_STATE_WAITPROXYCONNECT:
-    return waitproxyconnect_getsock(data->easy_conn, socks, numsocks);
+    return waitproxyconnect_getsock(data->conn, socks, numsocks);
 
   case CURLM_STATE_WAITCONNECT:
-    return waitconnect_getsock(data->easy_conn, socks, numsocks);
+    return waitconnect_getsock(data->conn, socks, numsocks);
 
   case CURLM_STATE_DO_MORE:
-    return domore_getsock(data->easy_conn, socks, numsocks);
+    return domore_getsock(data->conn, socks, numsocks);
 
   case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
                                to waiting for the same as the *PERFORM
                                states */
   case CURLM_STATE_PERFORM:
-  case CURLM_STATE_WAITPERFORM:
-    return Curl_single_getsock(data->easy_conn, socks, numsocks);
+    return Curl_single_getsock(data->conn, socks, numsocks);
   }
 
 }
@@ -985,11 +963,12 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
 
 #define NUM_POLLS_ON_STACK 10
 
-CURLMcode curl_multi_wait(struct Curl_multi *multi,
+CURLMcode Curl_multi_wait(struct Curl_multi *multi,
                           struct curl_waitfd extra_fds[],
                           unsigned int extra_nfds,
                           int timeout_ms,
-                          int *ret)
+                          int *ret,
+                          bool *gotsocket) /* if any socket was checked */
 {
   struct Curl_easy *data;
   curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
@@ -997,11 +976,14 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
   unsigned int i;
   unsigned int nfds = 0;
   unsigned int curlfds;
-  struct pollfd *ufds = NULL;
   bool ufds_malloc = FALSE;
   long timeout_internal;
   int retcode = 0;
   struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
+  struct pollfd *ufds = &a_few_on_stack[0];
+
+  if(gotsocket)
+    *gotsocket = FALSE;
 
   if(!GOOD_MULTI_HANDLE(multi))
     return CURLM_BAD_HANDLE;
@@ -1043,19 +1025,15 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
   curlfds = nfds; /* number of internal file descriptors */
   nfds += extra_nfds; /* add the externally provided ones */
 
-  if(nfds) {
-    if(nfds > NUM_POLLS_ON_STACK) {
-      /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
-         big, so at 2^29 sockets this value might wrap. When a process gets
-         the capability to actually handle over 500 million sockets this
-         calculation needs a integer overflow check. */
-      ufds = malloc(nfds * sizeof(struct pollfd));
-      if(!ufds)
-        return CURLM_OUT_OF_MEMORY;
-      ufds_malloc = TRUE;
-    }
-    else
-      ufds = &a_few_on_stack[0];
+  if(nfds > NUM_POLLS_ON_STACK) {
+    /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
+       big, so at 2^29 sockets this value might wrap. When a process gets
+       the capability to actually handle over 500 million sockets this
+       calculation needs a integer overflow check. */
+    ufds = malloc(nfds * sizeof(struct pollfd));
+    if(!ufds)
+      return CURLM_OUT_OF_MEMORY;
+    ufds_malloc = TRUE;
   }
   nfds = 0;
 
@@ -1135,19 +1113,20 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
     free(ufds);
   if(ret)
     *ret = retcode;
+  if(gotsocket && (extra_fds || curlfds))
+    /* if any socket was checked */
+    *gotsocket = TRUE;
+
   return CURLM_OK;
 }
 
-/*
- * Curl_multi_connchanged() is called to tell that there is a connection in
- * this multi handle that has changed state (pipelining become possible, the
- * number of allowed streams changed or similar), and a subsequent use of this
- * multi handle should move CONNECT_PEND handles back to CONNECT to have them
- * retry.
- */
-void Curl_multi_connchanged(struct Curl_multi *multi)
+CURLMcode curl_multi_wait(struct Curl_multi *multi,
+                          struct curl_waitfd extra_fds[],
+                          unsigned int extra_nfds,
+                          int timeout_ms,
+                          int *ret)
 {
-  multi->recheckstate = TRUE;
+  return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, NULL);
 }
 
 /*
@@ -1185,111 +1164,36 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
 
     /* take this handle to the perform state right away */
     multistate(data, CURLM_STATE_PERFORM);
-    data->easy_conn = conn;
+    Curl_attach_connnection(data, conn);
     k->keepon |= KEEP_RECV; /* setup to receive! */
   }
   return rc;
 }
 
-static CURLcode multi_reconnect_request(struct connectdata **connp)
-{
-  CURLcode result = CURLE_OK;
-  struct connectdata *conn = *connp;
-  struct Curl_easy *data = conn->data;
-
-  /* This was a re-use of a connection and we got a write error in the
-   * DO-phase. Then we DISCONNECT this connection and have another attempt to
-   * CONNECT and then DO again! The retry cannot possibly find another
-   * connection to re-use, since we only keep one possible connection for
-   * each.  */
-
-  infof(data, "Re-used connection seems dead, get a new one\n");
-
-  connclose(conn, "Reconnect dead connection"); /* enforce close */
-  result = multi_done(&conn, result, FALSE); /* we are so done with this */
-
-  /* conn may no longer be a good pointer, clear it to avoid mistakes by
-     parent functions */
-  *connp = NULL;
-
-  /*
-   * We need to check for CURLE_SEND_ERROR here as well. This could happen
-   * when the request failed on a FTP connection and thus multi_done() itself
-   * tried to use the connection (again).
-   */
-  if(!result || (CURLE_SEND_ERROR == result)) {
-    bool async;
-    bool protocol_done = TRUE;
-
-    /* Now, redo the connect and get a new connection */
-    result = Curl_connect(data, connp, &async, &protocol_done);
-    if(!result) {
-      /* We have connected or sent away a name resolve query fine */
-
-      conn = *connp; /* setup conn to again point to something nice */
-      if(async) {
-        /* Now, if async is TRUE here, we need to wait for the name
-           to resolve */
-        result = Curl_resolver_wait_resolv(conn, NULL);
-        if(result)
-          return result;
-
-        /* Resolved, continue with the connection */
-        result = Curl_once_resolved(conn, &protocol_done);
-        if(result)
-          return result;
-      }
-    }
-  }
-
-  return result;
-}
-
 /*
  * do_complete is called when the DO actions are complete.
  *
  * We init chunking and trailer bits to their default values here immediately
- * before receiving any header data for the current request in the pipeline.
+ * before receiving any header data for the current request.
  */
 static void do_complete(struct connectdata *conn)
 {
   conn->data->req.chunk = FALSE;
-  conn->data->req.maxfd = (conn->sockfd>conn->writesockfd?
-                           conn->sockfd:conn->writesockfd) + 1;
   Curl_pgrsTime(conn->data, TIMER_PRETRANSFER);
 }
 
-static CURLcode multi_do(struct connectdata **connp, bool *done)
+static CURLcode multi_do(struct Curl_easy *data, bool *done)
 {
   CURLcode result = CURLE_OK;
-  struct connectdata *conn = *connp;
-  struct Curl_easy *data = conn->data;
+  struct connectdata *conn = data->conn;
+
+  DEBUGASSERT(conn);
+  DEBUGASSERT(conn->handler);
 
   if(conn->handler->do_it) {
     /* generic protocol-specific function pointer set in curl_connect() */
     result = conn->handler->do_it(conn, done);
 
-    /* This was formerly done in transfer.c, but we better do it here */
-    if((CURLE_SEND_ERROR == result) && conn->bits.reuse) {
-      /*
-       * If the connection is using an easy handle, call reconnect
-       * to re-establish the connection.  Otherwise, let the multi logic
-       * figure out how to re-establish the connection.
-       */
-      if(!data->multi) {
-        result = multi_reconnect_request(connp);
-
-        if(!result) {
-          /* ... finally back to actually retry the DO phase */
-          conn = *connp; /* re-assign conn since multi_reconnect_request
-                            creates a new connection */
-          result = conn->handler->do_it(conn, done);
-        }
-      }
-      else
-        return result;
-    }
-
     if(!result && *done)
       /* do_complete must be called after the protocol-specific DO function */
       do_complete(conn);
@@ -1302,8 +1206,6 @@ static CURLcode multi_do(struct connectdata **connp, bool *done)
  * second stage DO state which (wrongly) was introduced to support FTP's
  * second connection.
  *
- * TODO: A future libcurl should be able to work away this state.
- *
  * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to
  * DOING state there's more work to do!
  */
@@ -1336,9 +1238,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
   bool done = FALSE;
   CURLMcode rc;
   CURLcode result = CURLE_OK;
-  struct SingleRequest *k;
-  time_t timeout_ms;
-  time_t recv_timeout_ms;
+  timediff_t timeout_ms;
+  timediff_t recv_timeout_ms;
   timediff_t send_timeout_ms;
   int control;
 
@@ -1351,56 +1252,59 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
     bool stream_error = FALSE;
     rc = CURLM_OK;
 
-    if(!data->easy_conn &&
+    if(!data->conn &&
        data->mstate > CURLM_STATE_CONNECT &&
        data->mstate < CURLM_STATE_DONE) {
-      /* In all these states, the code will blindly access 'data->easy_conn'
+      /* In all these states, the code will blindly access 'data->conn'
          so this is precaution that it isn't NULL. And it silences static
          analyzers. */
-      failf(data, "In state %d with no easy_conn, bail out!\n", data->mstate);
+      failf(data, "In state %d with no conn, bail out!\n", data->mstate);
       return CURLM_INTERNAL_ERROR;
     }
 
     if(multi_ischanged(multi, TRUE)) {
       DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
-      process_pending_handles(multi); /* pipelined/multiplexed */
+      process_pending_handles(multi); /* multiplexed */
     }
 
-    if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
+    if(data->conn && data->mstate > CURLM_STATE_CONNECT &&
        data->mstate < CURLM_STATE_COMPLETED) {
       /* Make sure we set the connection's current owner */
-      data->easy_conn->data = data;
+      data->conn->data = data;
     }
 
-    if(data->easy_conn &&
+    if(data->conn &&
        (data->mstate >= CURLM_STATE_CONNECT) &&
        (data->mstate < CURLM_STATE_COMPLETED)) {
       /* we need to wait for the connect state as only then is the start time
          stored, but we must not check already completed handles */
       timeout_ms = Curl_timeleft(data, &now,
-                                 (data->mstate <= CURLM_STATE_WAITDO)?
+                                 (data->mstate <= CURLM_STATE_DO)?
                                  TRUE:FALSE);
 
       if(timeout_ms < 0) {
         /* Handle timed out */
         if(data->mstate == CURLM_STATE_WAITRESOLVE)
-          failf(data, "Resolving timed out after %ld milliseconds",
+          failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
+                " milliseconds",
                 Curl_timediff(now, data->progress.t_startsingle));
         else if(data->mstate == CURLM_STATE_WAITCONNECT)
-          failf(data, "Connection timed out after %ld milliseconds",
+          failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
+                " milliseconds",
                 Curl_timediff(now, data->progress.t_startsingle));
         else {
-          k = &data->req;
+          struct SingleRequest *k = &data->req;
           if(k->size != -1) {
-            failf(data, "Operation timed out after %ld milliseconds with %"
-                  CURL_FORMAT_CURL_OFF_T " out of %"
+            failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
+                  " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
                   CURL_FORMAT_CURL_OFF_T " bytes received",
                   Curl_timediff(now, data->progress.t_startsingle),
                   k->bytecount, k->size);
           }
           else {
-            failf(data, "Operation timed out after %ld milliseconds with %"
-                  CURL_FORMAT_CURL_OFF_T " bytes received",
+            failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
+                  " milliseconds with %" CURL_FORMAT_CURL_OFF_T
+                  " bytes received",
                   Curl_timediff(now, data->progress.t_startsingle),
                   k->bytecount);
           }
@@ -1408,11 +1312,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
 
         /* Force connection closed if the connection has indeed been used */
         if(data->mstate > CURLM_STATE_DO) {
-          streamclose(data->easy_conn, "Disconnected with pending data");
+          streamclose(data->conn, "Disconnected with pending data");
           stream_error = TRUE;
         }
         result = CURLE_OPERATION_TIMEDOUT;
-        (void)multi_done(&data->easy_conn, result, TRUE);
+        (void)multi_done(data, result, TRUE);
         /* Skip the statemachine and go directly to error handling section. */
         goto statemachine_end;
       }
@@ -1439,8 +1343,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
     case CURLM_STATE_CONNECT:
       /* Connect. We want to get a connection identifier filled in. */
       Curl_pgrsTime(data, TIMER_STARTSINGLE);
-      result = Curl_connect(data, &data->easy_conn,
-                            &async, &protocol_connect);
+      if(data->set.timeout)
+        Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
+
+      if(data->set.connecttimeout)
+        Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
+
+      result = Curl_connect(data, &async, &protocol_connect);
       if(CURLE_NO_CONNECTION_AVAILABLE == result) {
         /* There was no connection available. We will go to the pending
            state and wait for an available connection. */
@@ -1452,33 +1361,31 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         result = CURLE_OK;
         break;
       }
+      else if(data->state.previouslypending) {
+        /* this transfer comes from the pending queue so try move another */
+        infof(data, "Transfer was pending, now try another\n");
+        process_pending_handles(data->multi);
+      }
 
       if(!result) {
-        /* Add this handle to the send or pend pipeline */
-        result = Curl_add_handle_to_pipeline(data, data->easy_conn);
-        if(result)
-          stream_error = TRUE;
+        if(async)
+          /* We're now waiting for an asynchronous name lookup */
+          multistate(data, CURLM_STATE_WAITRESOLVE);
         else {
-          if(async)
-            /* We're now waiting for an asynchronous name lookup */
-            multistate(data, CURLM_STATE_WAITRESOLVE);
-          else {
-            /* after the connect has been sent off, go WAITCONNECT unless the
-               protocol connect is already done and we can go directly to
-               WAITDO or DO! */
-            rc = CURLM_CALL_MULTI_PERFORM;
+          /* after the connect has been sent off, go WAITCONNECT unless the
+             protocol connect is already done and we can go directly to
+             WAITDO or DO! */
+          rc = CURLM_CALL_MULTI_PERFORM;
 
-            if(protocol_connect)
-              multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
-                         CURLM_STATE_WAITDO:CURLM_STATE_DO);
-            else {
+          if(protocol_connect)
+            multistate(data, CURLM_STATE_DO);
+          else {
 #ifndef CURL_DISABLE_HTTP
-              if(Curl_connect_ongoing(data->easy_conn))
-                multistate(data, CURLM_STATE_WAITPROXYCONNECT);
-              else
+            if(Curl_connect_ongoing(data->conn))
+              multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+            else
 #endif
-                multistate(data, CURLM_STATE_WAITCONNECT);
-            }
+              multistate(data, CURLM_STATE_WAITCONNECT);
           }
         }
       }
@@ -1488,9 +1395,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       /* awaiting an asynch name resolve to complete */
     {
       struct Curl_dns_entry *dns = NULL;
-      struct connectdata *conn = data->easy_conn;
+      struct connectdata *conn = data->conn;
       const char *hostname;
 
+      DEBUGASSERT(conn);
       if(conn->bits.httpproxy)
         hostname = conn->http_proxy.host.name;
       else if(conn->bits.conn_to_host)
@@ -1511,7 +1419,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       }
 
       if(!dns)
-        result = Curl_resolv_check(data->easy_conn, &dns);
+        result = Curl_resolv_check(data->conn, &dns);
 
       /* Update sockets here, because the socket(s) may have been
          closed and the application thus needs to be told, even if it
@@ -1524,21 +1432,20 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       if(dns) {
         /* Perform the next step in the connection phase, and then move on
            to the WAITCONNECT state */
-        result = Curl_once_resolved(data->easy_conn, &protocol_connect);
+        result = Curl_once_resolved(data->conn, &protocol_connect);
 
         if(result)
           /* if Curl_once_resolved() returns failure, the connection struct
              is already freed and gone */
-          data->easy_conn = NULL;           /* no more connection */
+          data->conn = NULL; /* no more connection */
         else {
           /* call again please so that we get the next socket setup */
           rc = CURLM_CALL_MULTI_PERFORM;
           if(protocol_connect)
-            multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
-                       CURLM_STATE_WAITDO:CURLM_STATE_DO);
+            multistate(data, CURLM_STATE_DO);
           else {
 #ifndef CURL_DISABLE_HTTP
-            if(Curl_connect_ongoing(data->easy_conn))
+            if(Curl_connect_ongoing(data->conn))
               multistate(data, CURLM_STATE_WAITPROXYCONNECT);
             else
 #endif
@@ -1558,19 +1465,20 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
 #ifndef CURL_DISABLE_HTTP
     case CURLM_STATE_WAITPROXYCONNECT:
       /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
-      result = Curl_http_connect(data->easy_conn, &protocol_connect);
+      DEBUGASSERT(data->conn);
+      result = Curl_http_connect(data->conn, &protocol_connect);
 
-      if(data->easy_conn->bits.proxy_connect_closed) {
+      if(data->conn->bits.proxy_connect_closed) {
         rc = CURLM_CALL_MULTI_PERFORM;
         /* connect back to proxy again */
         result = CURLE_OK;
-        multi_done(&data->easy_conn, CURLE_OK, FALSE);
+        multi_done(data, CURLE_OK, FALSE);
         multistate(data, CURLM_STATE_CONNECT);
       }
       else if(!result) {
-        if((data->easy_conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
-           data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
-           Curl_connect_complete(data->easy_conn)) {
+        if((data->conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
+           data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
+           Curl_connect_complete(data->conn)) {
           rc = CURLM_CALL_MULTI_PERFORM;
           /* initiate protocol connect phase */
           multistate(data, CURLM_STATE_SENDPROTOCONNECT);
@@ -1583,101 +1491,94 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
 
     case CURLM_STATE_WAITCONNECT:
       /* awaiting a completion of an asynch TCP connect */
-      result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
+      DEBUGASSERT(data->conn);
+      result = Curl_is_connected(data->conn, FIRSTSOCKET, &connected);
       if(connected && !result) {
 #ifndef CURL_DISABLE_HTTP
-        if((data->easy_conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
-            !data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
-           Curl_connect_ongoing(data->easy_conn)) {
+        if((data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
+            !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
+           Curl_connect_ongoing(data->conn)) {
           multistate(data, CURLM_STATE_WAITPROXYCONNECT);
           break;
         }
 #endif
         rc = CURLM_CALL_MULTI_PERFORM;
-        multistate(data, data->easy_conn->bits.tunnel_proxy?
+        multistate(data, data->conn->bits.tunnel_proxy?
                    CURLM_STATE_WAITPROXYCONNECT:
                    CURLM_STATE_SENDPROTOCONNECT);
       }
       else if(result) {
         /* failure detected */
-        /* Just break, the cleaning up is handled all in one place */
+        Curl_posttransfer(data);
+        multi_done(data, result, TRUE);
         stream_error = TRUE;
         break;
       }
       break;
 
     case CURLM_STATE_SENDPROTOCONNECT:
-      result = Curl_protocol_connect(data->easy_conn, &protocol_connect);
+      result = Curl_protocol_connect(data->conn, &protocol_connect);
       if(!result && !protocol_connect)
         /* switch to waiting state */
         multistate(data, CURLM_STATE_PROTOCONNECT);
       else if(!result) {
         /* protocol connect has completed, go WAITDO or DO */
-        multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
-                   CURLM_STATE_WAITDO:CURLM_STATE_DO);
+        multistate(data, CURLM_STATE_DO);
         rc = CURLM_CALL_MULTI_PERFORM;
       }
       else if(result) {
         /* failure detected */
         Curl_posttransfer(data);
-        multi_done(&data->easy_conn, result, TRUE);
+        multi_done(data, result, TRUE);
         stream_error = TRUE;
       }
       break;
 
     case CURLM_STATE_PROTOCONNECT:
       /* protocol-specific connect phase */
-      result = Curl_protocol_connecting(data->easy_conn, &protocol_connect);
+      result = Curl_protocol_connecting(data->conn, &protocol_connect);
       if(!result && protocol_connect) {
         /* after the connect has completed, go WAITDO or DO */
-        multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
-                   CURLM_STATE_WAITDO:CURLM_STATE_DO);
+        multistate(data, CURLM_STATE_DO);
         rc = CURLM_CALL_MULTI_PERFORM;
       }
       else if(result) {
         /* failure detected */
         Curl_posttransfer(data);
-        multi_done(&data->easy_conn, result, TRUE);
+        multi_done(data, result, TRUE);
         stream_error = TRUE;
       }
       break;
 
-    case CURLM_STATE_WAITDO:
-      /* Wait for our turn to DO when we're pipelining requests */
-      if(Curl_pipeline_checkget_write(data, data->easy_conn)) {
-        /* Grabbed the channel */
-        multistate(data, CURLM_STATE_DO);
-        rc = CURLM_CALL_MULTI_PERFORM;
-      }
-      break;
-
     case CURLM_STATE_DO:
       if(data->set.connect_only) {
         /* keep connection open for application to use the socket */
-        connkeep(data->easy_conn, "CONNECT_ONLY");
+        connkeep(data->conn, "CONNECT_ONLY");
         multistate(data, CURLM_STATE_DONE);
         result = CURLE_OK;
         rc = CURLM_CALL_MULTI_PERFORM;
       }
       else {
         /* Perform the protocol's DO action */
-        result = multi_do(&data->easy_conn, &dophase_done);
+        result = multi_do(data, &dophase_done);
 
-        /* When multi_do() returns failure, data->easy_conn might be NULL! */
+        /* When multi_do() returns failure, data->conn might be NULL! */
 
         if(!result) {
           if(!dophase_done) {
+#ifndef CURL_DISABLE_FTP
             /* some steps needed for wildcard matching */
             if(data->state.wildcardmatch) {
               struct WildcardData *wc = &data->wildcard;
               if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
                 /* skip some states if it is important */
-                multi_done(&data->easy_conn, CURLE_OK, FALSE);
+                multi_done(data, CURLE_OK, FALSE);
                 multistate(data, CURLM_STATE_DONE);
                 rc = CURLM_CALL_MULTI_PERFORM;
                 break;
               }
             }
+#endif
             /* DO was not completed in one function call, we must continue
                DOING... */
             multistate(data, CURLM_STATE_DOING);
@@ -1685,7 +1586,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           }
 
           /* after DO, go DO_DONE... or DO_MORE */
-          else if(data->easy_conn->bits.do_more) {
+          else if(data->conn->bits.do_more) {
             /* we're supposed to do more, but we need to sit down, relax
                and wait a little while first */
             multistate(data, CURLM_STATE_DO_MORE);
@@ -1698,7 +1599,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           }
         }
         else if((CURLE_SEND_ERROR == result) &&
-                data->easy_conn->bits.reuse) {
+                data->conn->bits.reuse) {
           /*
            * In this situation, a connection that we were trying to use
            * may have unexpectedly died.  If possible, send the connection
@@ -1708,7 +1609,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           followtype follow = FOLLOW_NONE;
           CURLcode drc;
 
-          drc = Curl_retry_request(data->easy_conn, &newurl);
+          drc = Curl_retry_request(data->conn, &newurl);
           if(drc) {
             /* a failure here pretty much implies an out of memory */
             result = drc;
@@ -1716,7 +1617,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           }
 
           Curl_posttransfer(data);
-          drc = multi_done(&data->easy_conn, result, FALSE);
+          drc = multi_done(data, result, FALSE);
 
           /* When set to retry the connection, we must to go back to
            * the CONNECT state */
@@ -1748,8 +1649,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         else {
           /* failure detected */
           Curl_posttransfer(data);
-          if(data->easy_conn)
-            multi_done(&data->easy_conn, result, FALSE);
+          if(data->conn)
+            multi_done(data, result, FALSE);
           stream_error = TRUE;
         }
       }
@@ -1757,12 +1658,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
 
     case CURLM_STATE_DOING:
       /* we continue DOING until the DO phase is complete */
-      result = Curl_protocol_doing(data->easy_conn,
+      DEBUGASSERT(data->conn);
+      result = Curl_protocol_doing(data->conn,
                                    &dophase_done);
       if(!result) {
         if(dophase_done) {
           /* after DO, go DO_DONE or DO_MORE */
-          multistate(data, data->easy_conn->bits.do_more?
+          multistate(data, data->conn->bits.do_more?
                      CURLM_STATE_DO_MORE:
                      CURLM_STATE_DO_DONE);
           rc = CURLM_CALL_MULTI_PERFORM;
@@ -1771,7 +1673,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       else {
         /* failure detected */
         Curl_posttransfer(data);
-        multi_done(&data->easy_conn, result, FALSE);
+        multi_done(data, result, FALSE);
         stream_error = TRUE;
       }
       break;
@@ -1780,10 +1682,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       /*
        * When we are connected, DO MORE and then go DO_DONE
        */
-      result = multi_do_more(data->easy_conn, &control);
+      DEBUGASSERT(data->conn);
+      result = multi_do_more(data->conn, &control);
 
-      /* No need to remove this handle from the send pipeline here since that
-         is done in multi_done() */
       if(!result) {
         if(control) {
           /* if positive, advance to DO_DONE
@@ -1800,46 +1701,38 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       else {
         /* failure detected */
         Curl_posttransfer(data);
-        multi_done(&data->easy_conn, result, FALSE);
+        multi_done(data, result, FALSE);
         stream_error = TRUE;
       }
       break;
 
     case CURLM_STATE_DO_DONE:
-      /* Move ourselves from the send to recv pipeline */
-      Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn);
-
-      if(data->easy_conn->bits.multiplex || data->easy_conn->send_pipe.size)
+      DEBUGASSERT(data->conn);
+      if(data->conn->bits.multiplex)
         /* Check if we can move pending requests to send pipe */
-        process_pending_handles(multi); /*  pipelined/multiplexed */
+        process_pending_handles(multi); /*  multiplexed */
 
       /* Only perform the transfer if there's a good socket to work with.
          Having both BAD is a signal to skip immediately to DONE */
-      if((data->easy_conn->sockfd != CURL_SOCKET_BAD) ||
-         (data->easy_conn->writesockfd != CURL_SOCKET_BAD))
-        multistate(data, CURLM_STATE_WAITPERFORM);
+      if((data->conn->sockfd != CURL_SOCKET_BAD) ||
+         (data->conn->writesockfd != CURL_SOCKET_BAD))
+        multistate(data, CURLM_STATE_PERFORM);
       else {
+#ifndef CURL_DISABLE_FTP
         if(data->state.wildcardmatch &&
-           ((data->easy_conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
-           data->wildcard.state = CURLWC_DONE;
+           ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
+          data->wildcard.state = CURLWC_DONE;
         }
+#endif
         multistate(data, CURLM_STATE_DONE);
       }
       rc = CURLM_CALL_MULTI_PERFORM;
       break;
 
-    case CURLM_STATE_WAITPERFORM:
-      /* Wait for our turn to PERFORM */
-      if(Curl_pipeline_checkget_read(data, data->easy_conn)) {
-        /* Grabbed the channel */
-        multistate(data, CURLM_STATE_PERFORM);
-        rc = CURLM_CALL_MULTI_PERFORM;
-      }
-      break;
-
     case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
+      DEBUGASSERT(data->conn);
       /* if both rates are within spec, resume transfer */
-      if(Curl_pgrsUpdate(data->easy_conn))
+      if(Curl_pgrsUpdate(data->conn))
         result = CURLE_ABORTED_BY_CALLBACK;
       else
         result = Curl_speedcheck(data, now);
@@ -1909,24 +1802,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       }
 
       /* read/write data if it is ready to do so */
-      result = Curl_readwrite(data->easy_conn, data, &done, &comeback);
-
-      k = &data->req;
-
-      if(!(k->keepon & KEEP_RECV))
-        /* We're done receiving */
-        Curl_pipeline_leave_read(data->easy_conn);
-
-      if(!(k->keepon & KEEP_SEND))
-        /* We're done sending */
-        Curl_pipeline_leave_write(data->easy_conn);
+      result = Curl_readwrite(data->conn, data, &done, &comeback);
 
       if(done || (result == CURLE_RECV_ERROR)) {
         /* If CURLE_RECV_ERROR happens early enough, we assume it was a race
          * condition and the server closed the re-used connection exactly when
          * we wanted to use it, so figure out if that is indeed the case.
          */
-        CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
+        CURLcode ret = Curl_retry_request(data->conn, &newurl);
         if(!ret)
           retry = (newurl)?TRUE:FALSE;
         else if(!result)
@@ -1939,6 +1822,27 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           done = TRUE;
         }
       }
+      else if((CURLE_HTTP2_STREAM == result) &&
+              Curl_h2_http_1_1_error(data->conn)) {
+        CURLcode ret = Curl_retry_request(data->conn, &newurl);
+
+        if(!ret) {
+          infof(data, "Downgrades to HTTP/1.1!\n");
+          data->set.httpversion = CURL_HTTP_VERSION_1_1;
+          /* clear the error message bit too as we ignore the one we got */
+          data->state.errorbuf = FALSE;
+          if(!newurl)
+            /* typically for HTTP_1_1_REQUIRED error on first flight */
+            newurl = strdup(data->change.url);
+          /* if we are to retry, set the result to OK and consider the request
+             as done */
+          retry = TRUE;
+          result = CURLE_OK;
+          done = TRUE;
+        }
+        else
+          result = ret;
+      }
 
       if(result) {
         /*
@@ -1949,12 +1853,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
          * happened in the data connection.
          */
 
-        if(!(data->easy_conn->handler->flags & PROTOPT_DUAL) &&
+        if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
            result != CURLE_HTTP2_STREAM)
-          streamclose(data->easy_conn, "Transfer returned error");
+          streamclose(data->conn, "Transfer returned error");
 
         Curl_posttransfer(data);
-        multi_done(&data->easy_conn, result, TRUE);
+        multi_done(data, result, TRUE);
       }
       else if(done) {
         followtype follow = FOLLOW_NONE;
@@ -1962,13 +1866,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         /* call this even if the readwrite function returned error */
         Curl_posttransfer(data);
 
-        /* we're no longer receiving */
-        Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe);
-
-        /* expire the new receiving pipeline head */
-        if(data->easy_conn->recv_pipe.head)
-          Curl_expire(data->easy_conn->recv_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
-
         /* When we follow redirects or is set to retry the connection, we must
            to go back to the CONNECT state */
         if(data->req.newurl || retry) {
@@ -1982,13 +1879,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           }
           else
             follow = FOLLOW_RETRY;
-          result = multi_done(&data->easy_conn, CURLE_OK, FALSE);
+          (void)multi_done(data, CURLE_OK, FALSE);
+          /* multi_done() might return CURLE_GOT_NOTHING */
+          result = Curl_follow(data, newurl, follow);
           if(!result) {
-            result = Curl_follow(data, newurl, follow);
-            if(!result) {
-              multistate(data, CURLM_STATE_CONNECT);
-              rc = CURLM_CALL_MULTI_PERFORM;
-            }
+            multistate(data, CURLM_STATE_CONNECT);
+            rc = CURLM_CALL_MULTI_PERFORM;
           }
           free(newurl);
         }
@@ -2005,7 +1901,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
             free(newurl);
             if(result) {
               stream_error = TRUE;
-              result = multi_done(&data->easy_conn, result, TRUE);
+              result = multi_done(data, result, TRUE);
             }
           }
 
@@ -2024,33 +1920,31 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       /* this state is highly transient, so run another loop after this */
       rc = CURLM_CALL_MULTI_PERFORM;
 
-      if(data->easy_conn) {
+      if(data->conn) {
         CURLcode res;
 
-        /* Remove ourselves from the receive pipeline, if we are there. */
-        Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe);
-
-        if(data->easy_conn->bits.multiplex || data->easy_conn->send_pipe.size)
+        if(data->conn->bits.multiplex)
           /* Check if we can move pending requests to connection */
-          process_pending_handles(multi); /* pipelined/multiplexing */
+          process_pending_handles(multi); /* multiplexing */
 
         /* post-transfer command */
-        res = multi_done(&data->easy_conn, result, FALSE);
+        res = multi_done(data, result, FALSE);
 
         /* allow a previously set error code take precedence */
         if(!result)
           result = res;
 
         /*
-         * If there are other handles on the pipeline, multi_done won't set
-         * easy_conn to NULL.  In such a case, curl_multi_remove_handle() can
+         * If there are other handles on the connection, multi_done won't set
+         * conn to NULL.  In such a case, curl_multi_remove_handle() can
          * access free'd data, if the connection is free'd and the handle
          * removed before we perform the processing in CURLM_STATE_COMPLETED
          */
-        if(data->easy_conn)
-          data->easy_conn = NULL;
+        if(data->conn)
+          detach_connnection(data);
       }
 
+#ifndef CURL_DISABLE_FTP
       if(data->state.wildcardmatch) {
         if(data->wildcard.state != CURLWC_DONE) {
           /* if a wildcard is set and we are not ending -> lets start again
@@ -2059,7 +1953,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           break;
         }
       }
-
+#endif
       /* after we have DONE what we're supposed to do, go COMPLETED, and
          it doesn't matter what the multi_done() returned! */
       multistate(data, CURLM_STATE_COMPLETED);
@@ -2090,23 +1984,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         /* Check if we can move pending requests to send pipe */
         process_pending_handles(multi); /* connection */
 
-        if(data->easy_conn) {
-          /* if this has a connection, unsubscribe from the pipelines */
-          Curl_pipeline_leave_write(data->easy_conn);
-          Curl_pipeline_leave_read(data->easy_conn);
-          Curl_removeHandleFromPipeline(data, &data->easy_conn->send_pipe);
-          Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe);
-
+        if(data->conn) {
           if(stream_error) {
             /* Don't attempt to send data over a connection that timed out */
             bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
             /* disconnect properly */
-            Curl_disconnect(data, data->easy_conn, dead_connection);
+            Curl_disconnect(data, data->conn, dead_connection);
 
-            /* This is where we make sure that the easy_conn pointer is reset.
+            /* This is where we make sure that the conn pointer is reset.
                We don't have to do this in every case block above where a
                failure is detected */
-            data->easy_conn = NULL;
+            detach_connnection(data);
           }
         }
         else if(data->mstate == CURLM_STATE_CONNECT) {
@@ -2118,11 +2006,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         rc = CURLM_CALL_MULTI_PERFORM;
       }
       /* if there's still a connection to use, call the progress function */
-      else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) {
+      else if(data->conn && Curl_pgrsUpdate(data->conn)) {
         /* aborted due to progress callback return code must close the
            connection */
         result = CURLE_ABORTED_BY_CALLBACK;
-        streamclose(data->easy_conn, "Aborted by callback");
+        streamclose(data->conn, "Aborted by callback");
 
         /* if not yet in DONE state, go there, otherwise COMPLETED */
         multistate(data, (data->mstate < CURLM_STATE_DONE)?
@@ -2145,7 +2033,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         msg->extmsg.data.result = result;
 
         rc = multi_addmsg(multi, msg);
-        DEBUGASSERT(!data->easy_conn);
+        DEBUGASSERT(!data->conn);
       }
       multistate(data, CURLM_STATE_MSGSENT);
     }
@@ -2225,9 +2113,9 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
     data = multi->easyp;
     while(data) {
       nextdata = data->next;
-      if(!data->state.done && data->easy_conn)
+      if(!data->state.done && data->conn)
         /* if DONE was never called for this handle */
-        (void)multi_done(&data->easy_conn, CURLE_OK, TRUE);
+        (void)multi_done(data, CURLE_OK, TRUE);
       if(data->dns.hostcachetype == HCACHE_MULTI) {
         /* clear out the usage of the shared DNS cache */
         Curl_hostcache_clean(data, data->dns.hostcache);
@@ -2257,11 +2145,6 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
 
     Curl_hash_destroy(&multi->hostcache);
     Curl_psl_destroy(&multi->psl);
-
-    /* Free the blacklists by setting them to NULL */
-    Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
-    Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
-
     free(multi);
 
     return CURLM_OK;
@@ -2320,6 +2203,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
   curl_socket_t s;
   int num;
   unsigned int curraction;
+  int actions[MAX_SOCKSPEREASYHANDLE];
 
   for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
     socks[i] = CURL_SOCKET_BAD;
@@ -2336,7 +2220,10 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
   for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
         (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
       i++) {
-    int action = CURL_POLL_NONE;
+    unsigned int action = CURL_POLL_NONE;
+    unsigned int prevaction = 0;
+    unsigned int comboaction;
+    bool sincebefore = FALSE;
 
     s = socks[i];
 
@@ -2348,29 +2235,70 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
     if(curraction & GETSOCK_WRITESOCK(i))
       action |= CURL_POLL_OUT;
 
+    actions[i] = action;
     if(entry) {
-      /* yeps, already present so check if it has the same action set */
-      if(entry->action == action)
-        /* same, continue */
-        continue;
+      /* check if new for this transfer */
+      for(i = 0; i< data->numsocks; i++) {
+        if(s == data->sockets[i]) {
+          prevaction = data->actions[i];
+          sincebefore = TRUE;
+          break;
+        }
+      }
+
     }
     else {
-      /* this is a socket we didn't have before, add it! */
-      entry = sh_addentry(&multi->sockhash, s, data);
+      /* this is a socket we didn't have before, add it to the hash! */
+      entry = sh_addentry(&multi->sockhash, s);
       if(!entry)
         /* fatal */
         return CURLM_OUT_OF_MEMORY;
     }
+    if(sincebefore && (prevaction != action)) {
+      /* Socket was used already, but different action now */
+      if(prevaction & CURL_POLL_IN)
+        entry->readers--;
+      if(prevaction & CURL_POLL_OUT)
+        entry->writers--;
+      if(action & CURL_POLL_IN)
+        entry->readers++;
+      if(action & CURL_POLL_OUT)
+        entry->writers++;
+    }
+    else if(!sincebefore) {
+      /* a new user */
+      entry->users++;
+      if(action & CURL_POLL_IN)
+        entry->readers++;
+      if(action & CURL_POLL_OUT)
+        entry->writers++;
+
+      /* add 'data' to the list of handles using this socket! */
+      Curl_llist_insert_next(&entry->list, entry->list.tail,
+                             data, &data->sh_queue);
+    }
+
+    comboaction = (entry->writers? CURL_POLL_OUT : 0) |
+      (entry->readers ? CURL_POLL_IN : 0);
+
+#if 0
+    infof(data, "--- Comboaction: %u readers %u writers\n",
+          entry->readers, entry->writers);
+#endif
+    /* check if it has the same action set */
+    if(entry->action == comboaction)
+      /* same, continue */
+      continue;
 
     /* we know (entry != NULL) at this point, see the logic above */
     if(multi->socket_cb)
       multi->socket_cb(data,
                        s,
-                       action,
+                       comboaction,
                        multi->socket_userp,
                        entry->socketp);
 
-    entry->action = action; /* store the current action state */
+    entry->action = comboaction; /* store the current action state */
   }
 
   num = i; /* number of sockets */
@@ -2379,73 +2307,45 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
      make sure to detect sockets that are removed */
   for(i = 0; i< data->numsocks; i++) {
     int j;
+    bool stillused = FALSE;
     s = data->sockets[i];
-    for(j = 0; j<num; j++) {
+    for(j = 0; j < num; j++) {
       if(s == socks[j]) {
         /* this is still supervised */
-        s = CURL_SOCKET_BAD;
+        stillused = TRUE;
         break;
       }
     }
+    if(stillused)
+      continue;
 
     entry = sh_getentry(&multi->sockhash, s);
+    /* if this is NULL here, the socket has been closed and notified so
+       already by Curl_multi_closed() */
     if(entry) {
-      /* this socket has been removed. Tell the app to remove it */
-      bool remove_sock_from_hash = TRUE;
-
-      /* check if the socket to be removed serves a connection which has
-         other easy-s in a pipeline. In this case the socket should not be
-         removed. */
-      struct connectdata *easy_conn = data->easy_conn;
-      if(easy_conn) {
-        if(easy_conn->recv_pipe.size > 1) {
-          /* the handle should not be removed from the pipe yet */
-          remove_sock_from_hash = FALSE;
-
-          /* Update the sockhash entry to instead point to the next in line
-             for the recv_pipe, or the first (in case this particular easy
-             isn't already) */
-          if(entry->easy == data) {
-            if(Curl_recvpipe_head(data, easy_conn))
-              entry->easy = easy_conn->recv_pipe.head->next->ptr;
-            else
-              entry->easy = easy_conn->recv_pipe.head->ptr;
-          }
-        }
-        if(easy_conn->send_pipe.size > 1) {
-          /* the handle should not be removed from the pipe yet */
-          remove_sock_from_hash = FALSE;
-
-          /* Update the sockhash entry to instead point to the next in line
-             for the send_pipe, or the first (in case this particular easy
-             isn't already) */
-          if(entry->easy == data) {
-            if(Curl_sendpipe_head(data, easy_conn))
-              entry->easy = easy_conn->send_pipe.head->next->ptr;
-            else
-              entry->easy = easy_conn->send_pipe.head->ptr;
-          }
-        }
-        /* Don't worry about overwriting recv_pipe head with send_pipe_head,
-           when action will be asked on the socket (see multi_socket()), the
-           head of the correct pipe will be taken according to the
-           action. */
-      }
-
-      if(remove_sock_from_hash) {
-        /* in this case 'entry' is always non-NULL */
+      int oldactions = data->actions[i];
+      /* this socket has been removed. Decrease user count */
+      entry->users--;
+      if(oldactions & CURL_POLL_OUT)
+        entry->writers--;
+      if(oldactions & CURL_POLL_IN)
+        entry->readers--;
+      if(!entry->users) {
         if(multi->socket_cb)
-          multi->socket_cb(data,
-                           s,
-                           CURL_POLL_REMOVE,
+          multi->socket_cb(data, s, CURL_POLL_REMOVE,
                            multi->socket_userp,
                            entry->socketp);
         sh_delentry(&multi->sockhash, s);
       }
-    } /* if sockhash entry existed */
+      else {
+        /* remove this transfer as a user of this socket */
+        Curl_llist_remove(&entry->list, &data->sh_queue, NULL);
+      }
+    }
   } /* for loop over numsocks */
 
   memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
+  memcpy(data->actions, actions, num*sizeof(int));
   data->numsocks = num;
   return CURLM_OK;
 }
@@ -2466,11 +2366,11 @@ void Curl_updatesocket(struct Curl_easy *data)
  * socket again and it gets the same file descriptor number.
  */
 
-void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
+void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s)
 {
-  if(conn->data) {
+  if(data) {
     /* if there's still an easy handle associated with this connection */
-    struct Curl_multi *multi = conn->data->multi;
+    struct Curl_multi *multi = data->multi;
     if(multi) {
       /* this is set if this connection is part of a handle that is added to
          a multi handle, and only then this is necessary */
@@ -2478,7 +2378,7 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
 
       if(entry) {
         if(multi->socket_cb)
-          multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
+          multi->socket_cb(data, s, CURL_POLL_REMOVE,
                            multi->socket_userp,
                            entry->socketp);
 
@@ -2585,46 +2485,37 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
          and just move on. */
       ;
     else {
+      struct curl_llist *list = &entry->list;
+      struct curl_llist_element *e;
       SIGPIPE_VARIABLE(pipe_st);
 
-      data = entry->easy;
-
-      if(data->magic != CURLEASY_MAGIC_NUMBER)
-        /* bad bad bad bad bad bad bad */
-        return CURLM_INTERNAL_ERROR;
-
-      /* If the pipeline is enabled, take the handle which is in the head of
-         the pipeline. If we should write into the socket, take the send_pipe
-         head.  If we should read from the socket, take the recv_pipe head. */
-      if(data->easy_conn) {
-        if((ev_bitmask & CURL_POLL_OUT) &&
-           data->easy_conn->send_pipe.head)
-          data = data->easy_conn->send_pipe.head->ptr;
-        else if((ev_bitmask & CURL_POLL_IN) &&
-                data->easy_conn->recv_pipe.head)
-          data = data->easy_conn->recv_pipe.head->ptr;
-      }
+      /* the socket can be shared by many transfers, iterate */
+      for(e = list->head; e; e = e->next) {
+        data = (struct Curl_easy *)e->ptr;
 
-      if(data->easy_conn &&
-         !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
-        /* set socket event bitmask if they're not locked */
-        data->easy_conn->cselect_bits = ev_bitmask;
+        if(data->magic != CURLEASY_MAGIC_NUMBER)
+          /* bad bad bad bad bad bad bad */
+          return CURLM_INTERNAL_ERROR;
 
-      sigpipe_ignore(data, &pipe_st);
-      result = multi_runsingle(multi, now, data);
-      sigpipe_restore(&pipe_st);
+        if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
+          /* set socket event bitmask if they're not locked */
+          data->conn->cselect_bits = ev_bitmask;
 
-      if(data->easy_conn &&
-         !(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
-        /* clear the bitmask only if not locked */
-        data->easy_conn->cselect_bits = 0;
+        sigpipe_ignore(data, &pipe_st);
+        result = multi_runsingle(multi, now, data);
+        sigpipe_restore(&pipe_st);
 
-      if(CURLM_OK >= result) {
-        /* get the socket(s) and check if the state has been changed since
-           last */
-        result = singlesocket(multi, data);
-        if(result)
-          return result;
+        if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
+          /* clear the bitmask only if not locked */
+          data->conn->cselect_bits = 0;
+
+        if(CURLM_OK >= result) {
+          /* get the socket(s) and check if the state has been changed since
+             last */
+          result = singlesocket(multi, data);
+          if(result)
+            return result;
+        }
       }
 
       /* Now we fall-through and do the timer-based stuff, since we don't want
@@ -2712,7 +2603,7 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
     multi->push_userp = va_arg(param, void *);
     break;
   case CURLMOPT_PIPELINING:
-    multi->pipelining = va_arg(param, long) & CURLPIPE_MULTIPLEX;
+    multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX;
     break;
   case CURLMOPT_TIMERFUNCTION:
     multi->timer_cb = va_arg(param, curl_multi_timer_callback);
@@ -2726,25 +2617,19 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
   case CURLMOPT_MAX_HOST_CONNECTIONS:
     multi->max_host_connections = va_arg(param, long);
     break;
+  case CURLMOPT_MAX_TOTAL_CONNECTIONS:
+    multi->max_total_connections = va_arg(param, long);
+    break;
+    /* options formerly used for pipelining */
   case CURLMOPT_MAX_PIPELINE_LENGTH:
-    multi->max_pipeline_length = va_arg(param, long);
     break;
   case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
-    multi->content_length_penalty_size = va_arg(param, long);
     break;
   case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
-    multi->chunk_length_penalty_size = va_arg(param, long);
     break;
   case CURLMOPT_PIPELINING_SITE_BL:
-    res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
-                                           &multi->pipelining_site_bl);
     break;
   case CURLMOPT_PIPELINING_SERVER_BL:
-    res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
-                                             &multi->pipelining_server_bl);
-    break;
-  case CURLMOPT_MAX_TOTAL_CONNECTIONS:
-    multi->max_total_connections = va_arg(param, long);
     break;
   default:
     res = CURLM_UNKNOWN_OPTION;
@@ -3059,7 +2944,7 @@ void Curl_expire_clear(struct Curl_easy *data)
     }
 
 #ifdef DEBUGBUILD
-    infof(data, "Expire cleared\n");
+    infof(data, "Expire cleared (transfer %p)\n", data);
 #endif
     nowp->tv_sec = 0;
     nowp->tv_usec = 0;
@@ -3097,24 +2982,20 @@ size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
   return multi ? multi->max_total_connections : 0;
 }
 
-curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
-{
-  return multi ? multi->content_length_penalty_size : 0;
-}
-
-curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
-{
-  return multi ? multi->chunk_length_penalty_size : 0;
-}
+/*
+ * When information about a connection has appeared, call this!
+ */
 
-struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
+void Curl_multiuse_state(struct connectdata *conn,
+                         int bundlestate) /* use BUNDLE_* defines */
 {
-  return &multi->pipelining_site_bl;
-}
+  DEBUGASSERT(conn);
+  DEBUGASSERT(conn->bundle);
+  DEBUGASSERT(conn->data);
+  DEBUGASSERT(conn->data->multi);
 
-struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
-{
-  return &multi->pipelining_server_bl;
+  conn->bundle->multiuse = bundlestate;
+  process_pending_handles(conn->data->multi);
 }
 
 static void process_pending_handles(struct Curl_multi *multi)
@@ -3132,6 +3013,9 @@ static void process_pending_handles(struct Curl_multi *multi)
 
     /* Make sure that the handle will be processed soonish. */
     Curl_expire(data, 0, EXPIRE_RUN_NOW);
+
+    /* mark this as having been in the pending queue */
+    data->state.previouslypending = TRUE;
   }
 }
 
@@ -3175,8 +3059,8 @@ void Curl_multi_dump(struct Curl_multi *multi)
           continue;
         }
         fprintf(stderr, "[%s %s] ",
-                entry->action&CURL_POLL_IN?"RECVING":"",
-                entry->action&CURL_POLL_OUT?"SENDING":"");
+                (entry->action&CURL_POLL_IN)?"RECVING":"",
+                (entry->action&CURL_POLL_OUT)?"SENDING":"");
       }
       if(data->numsocks)
         fprintf(stderr, "\n");
diff --git a/lib/multihandle.h b/lib/multihandle.h
index ea2bf35..279379a 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -46,18 +46,16 @@ typedef enum {
   CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
   CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
                                    phase */
-  CURLM_STATE_WAITDO,       /* 8 - wait for our turn to send the request */
-  CURLM_STATE_DO,           /* 9 - start send off the request (part 1) */
-  CURLM_STATE_DOING,        /* 10 - sending off the request (part 1) */
-  CURLM_STATE_DO_MORE,      /* 11 - send off the request (part 2) */
-  CURLM_STATE_DO_DONE,      /* 12 - done sending off request */
-  CURLM_STATE_WAITPERFORM,  /* 13 - wait for our turn to read the response */
-  CURLM_STATE_PERFORM,      /* 14 - transfer data */
-  CURLM_STATE_TOOFAST,      /* 15 - wait because limit-rate exceeded */
-  CURLM_STATE_DONE,         /* 16 - post data transfer operation */
-  CURLM_STATE_COMPLETED,    /* 17 - operation complete */
-  CURLM_STATE_MSGSENT,      /* 18 - the operation complete message is sent */
-  CURLM_STATE_LAST          /* 19 - not a true state, never use this */
+  CURLM_STATE_DO,           /* 8 - start send off the request (part 1) */
+  CURLM_STATE_DOING,        /* 9 - sending off the request (part 1) */
+  CURLM_STATE_DO_MORE,      /* 10 - send off the request (part 2) */
+  CURLM_STATE_DO_DONE,      /* 11 - done sending off request */
+  CURLM_STATE_PERFORM,      /* 12 - transfer data */
+  CURLM_STATE_TOOFAST,      /* 13 - wait because limit-rate exceeded */
+  CURLM_STATE_DONE,         /* 14 - post data transfer operation */
+  CURLM_STATE_COMPLETED,    /* 15 - operation complete */
+  CURLM_STATE_MSGSENT,      /* 16 - the operation complete message is sent */
+  CURLM_STATE_LAST          /* 17 - not a true state, never use this */
 } CURLMstate;
 
 /* we support N sockets per easy handle. Set the corresponding bit to what
@@ -66,7 +64,7 @@ typedef enum {
 #define GETSOCK_READABLE (0x00ff)
 #define GETSOCK_WRITABLE (0xff00)
 
-#define CURLPIPE_ANY (CURLPIPE_HTTP1 | CURLPIPE_MULTIPLEX)
+#define CURLPIPE_ANY (CURLPIPE_MULTIPLEX)
 
 /* This is the struct known as CURLM on the outside */
 struct Curl_multi {
@@ -112,8 +110,8 @@ struct Curl_multi {
      same actual socket) */
   struct curl_hash sockhash;
 
-  /* pipelining wanted bits (CURLPIPE*) */
-  long pipelining;
+  /* multiplexing wanted */
+  bool multiplexing;
 
   bool recheckstate; /* see Curl_multi_connchanged */
 
@@ -129,24 +127,6 @@ struct Curl_multi {
   long max_total_connections; /* if >0, a fixed limit of the maximum number
                                  of connections in total */
 
-  long max_pipeline_length; /* if >0, maximum number of requests in a
-                               pipeline */
-
-  long content_length_penalty_size; /* a connection with a
-                                       content-length bigger than
-                                       this is not considered
-                                       for pipelining */
-
-  long chunk_length_penalty_size; /* a connection with a chunk length
-                                     bigger than this is not
-                                     considered for pipelining */
-
-  struct curl_llist pipelining_site_bl; /* List of sites that are blacklisted
-                                           from pipelining */
-
-  struct curl_llist pipelining_server_bl; /* List of server types that are
-                                             blacklisted from pipelining */
-
   /* timer callback and user data pointer for the *socket() API */
   curl_multi_timer_callback timer_cb;
   void *timer_userp;
diff --git a/lib/multiif.h b/lib/multiif.h
index c8fb5ca..e8a5e70 100644
--- a/lib/multiif.h
+++ b/lib/multiif.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -30,8 +30,10 @@ void Curl_updatesocket(struct Curl_easy *data);
 void Curl_expire(struct Curl_easy *data, time_t milli, expire_id);
 void Curl_expire_clear(struct Curl_easy *data);
 void Curl_expire_done(struct Curl_easy *data, expire_id id);
-bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
-void Curl_multi_handlePipeBreak(struct Curl_easy *data);
+void Curl_detach_connnection(struct Curl_easy *data);
+void Curl_attach_connnection(struct Curl_easy *data,
+                             struct connectdata *conn);
+bool Curl_multiplex_wanted(const struct Curl_multi *multi);
 void Curl_set_in_callback(struct Curl_easy *data, bool value);
 bool Curl_is_in_callback(struct Curl_easy *easy);
 
@@ -62,22 +64,11 @@ void Curl_multi_dump(struct Curl_multi *multi);
 /* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
 size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
 
-/* Return the value of the CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE option */
-curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi);
-
-/* Return the value of the CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE option */
-curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi);
-
-/* Return the value of the CURLMOPT_PIPELINING_SITE_BL option */
-struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi);
-
-/* Return the value of the CURLMOPT_PIPELINING_SERVER_BL option */
-struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi);
-
 /* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
 size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
 
-void Curl_multi_connchanged(struct Curl_multi *multi);
+void Curl_multiuse_state(struct connectdata *conn,
+                         int bundlestate); /* use BUNDLE_* defines */
 
 /*
  * Curl_multi_closed()
@@ -89,7 +80,7 @@ void Curl_multi_connchanged(struct Curl_multi *multi);
  * socket again and it gets the same file descriptor number.
  */
 
-void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
+void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s);
 
 /*
  * Add a handle and move it into PERFORM state at once. For pushed streams.
@@ -97,4 +88,12 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
                                  struct Curl_easy *data,
                                  struct connectdata *conn);
+
+CURLMcode Curl_multi_wait(struct Curl_multi *multi,
+                          struct curl_waitfd extra_fds[],
+                          unsigned int extra_nfds,
+                          int timeout_ms,
+                          int *ret,
+                          bool *gotsocket); /* if any socket was checked */
+
 #endif /* HEADER_CURL_MULTIIF_H */
diff --git a/lib/netrc.c b/lib/netrc.c
index 1724b35..1bd998f 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -21,6 +21,7 @@
  ***************************************************************************/
 
 #include "curl_setup.h"
+#ifndef CURL_DISABLE_NETRC
 
 #ifdef HAVE_PWD_H
 #include <pwd.h>
@@ -53,6 +54,8 @@ enum host_lookup_state {
 int Curl_parsenetrc(const char *host,
                     char **loginp,
                     char **passwordp,
+                    bool *login_changed,
+                    bool *password_changed,
                     char *netrcfile)
 {
   FILE *file;
@@ -164,7 +167,7 @@ int Curl_parsenetrc(const char *host,
             if(specific_login) {
               state_our_login = strcasecompare(login, tok);
             }
-            else {
+            else if(!login || strcmp(login, tok)) {
               if(login_alloc) {
                 free(login);
                 login_alloc = FALSE;
@@ -179,7 +182,8 @@ int Curl_parsenetrc(const char *host,
             state_login = 0;
           }
           else if(state_password) {
-            if(state_our_login || !specific_login) {
+            if((state_our_login || !specific_login)
+                && (!password || strcmp(password, tok))) {
               if(password_alloc) {
                 free(password);
                 password_alloc = FALSE;
@@ -211,15 +215,19 @@ int Curl_parsenetrc(const char *host,
 
     out:
     if(!retcode) {
+      *login_changed = FALSE;
+      *password_changed = FALSE;
       if(login_alloc) {
         if(*loginp)
           free(*loginp);
         *loginp = login;
+        *login_changed = TRUE;
       }
       if(password_alloc) {
         if(*passwordp)
           free(*passwordp);
         *passwordp = password;
+        *password_changed = TRUE;
       }
     }
     else {
@@ -233,3 +241,5 @@ int Curl_parsenetrc(const char *host,
 
   return retcode;
 }
+
+#endif
diff --git a/lib/netrc.h b/lib/netrc.h
index d980166..7f56c4b 100644
--- a/lib/netrc.h
+++ b/lib/netrc.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,15 +22,24 @@
  *
  ***************************************************************************/
 
+#include "curl_setup.h"
+#ifndef CURL_DISABLE_NETRC
+
 /* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
 int Curl_parsenetrc(const char *host,
                     char **loginp,
                     char **passwordp,
+                    bool *login_changed,
+                    bool *password_changed,
                     char *filename);
   /* Assume: (*passwordp)[0]=0, host[0] != 0.
    * If (*loginp)[0] = 0, search for login and password within a machine
    * section in the netrc.
    * If (*loginp)[0] != 0, search for password within machine and login.
    */
+#else
+/* disabled */
+#define Curl_parsenetrc(a,b,c,d,e,f) 1
+#endif
 
 #endif /* HEADER_CURL_NETRC_H */
diff --git a/lib/non-ascii.c b/lib/non-ascii.c
index 1414324..42beaec 100644
--- a/lib/non-ascii.c
+++ b/lib/non-ascii.c
@@ -78,7 +78,7 @@ CURLcode Curl_convert_clone(struct Curl_easy *data,
 
 /*
  * Curl_convert_to_network() is an internal function for performing ASCII
- * conversions on non-ASCII platforms. It convers the buffer _in place_.
+ * conversions on non-ASCII platforms. It converts the buffer _in place_.
  */
 CURLcode Curl_convert_to_network(struct Curl_easy *data,
                                  char *buffer, size_t length)
@@ -144,7 +144,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
 
 /*
  * Curl_convert_from_network() is an internal function for performing ASCII
- * conversions on non-ASCII platforms. It convers the buffer _in place_.
+ * conversions on non-ASCII platforms. It converts the buffer _in place_.
  */
 CURLcode Curl_convert_from_network(struct Curl_easy *data,
                                    char *buffer, size_t length)
diff --git a/lib/openldap.c b/lib/openldap.c
index c6cb794..eeab2c7 100644
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -6,7 +6,7 @@
  *                 \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2010, Howard Chu, <hyc at openldap.org>
- * Copyright (C) 2011 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2011 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -196,9 +196,6 @@ static CURLcode ldap_setup_connection(struct connectdata *conn)
   li->proto = proto;
   conn->proto.generic = li;
   connkeep(conn, "OpenLDAP default");
-  /* TODO:
-   * - provide option to choose SASL Binds instead of Simple
-   */
   return CURLE_OK;
 }
 
@@ -220,8 +217,8 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
   ptr = hosturl + 4;
   if(conn->handler->flags & PROTOPT_SSL)
     *ptr++ = 's';
-  snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
-           conn->host.name, conn->remote_port);
+  msnprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
+            conn->host.name, conn->remote_port);
 
 #ifdef CURL_OPENLDAP_DEBUG
   static int do_trace = 0;
@@ -414,7 +411,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
     return CURLE_OUT_OF_MEMORY;
   lr->msgid = msgid;
   data->req.protop = lr;
-  Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+  Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   *done = TRUE;
   return CURLE_OK;
 }
@@ -510,8 +507,6 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
     lr->nument++;
     rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
     if(rc < 0) {
-      /* TODO: verify that this is really how this return code should be
-         handled */
       *err = CURLE_RECV_ERROR;
       return -1;
     }
diff --git a/lib/parsedate.c b/lib/parsedate.c
index 3d3c00b..7ae5eb8 100644
--- a/lib/parsedate.c
+++ b/lib/parsedate.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -82,20 +82,6 @@
 #include "warnless.h"
 #include "parsedate.h"
 
-const char * const Curl_wkday[] =
-{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
-static const char * const weekday[] =
-{ "Monday", "Tuesday", "Wednesday", "Thursday",
-  "Friday", "Saturday", "Sunday" };
-const char * const Curl_month[]=
-{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-struct tzinfo {
-  char name[5];
-  int offset; /* +/- in minutes */
-};
-
 /*
  * parsedate()
  *
@@ -114,6 +100,22 @@ static int parsedate(const char *date, time_t *output);
 #define PARSEDATE_LATER  1
 #define PARSEDATE_SOONER 2
 
+#ifndef CURL_DISABLE_PARSEDATE
+
+const char * const Curl_wkday[] =
+{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
+static const char * const weekday[] =
+{ "Monday", "Tuesday", "Wednesday", "Thursday",
+  "Friday", "Saturday", "Sunday" };
+const char * const Curl_month[]=
+{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+struct tzinfo {
+  char name[5];
+  int offset; /* +/- in minutes */
+};
+
 /* Here's a bunch of frequently used time zone names. These were supported
    by the old getdate parser. */
 #define tDAYZONE -60       /* offset for daylight savings time */
@@ -555,6 +557,15 @@ static int parsedate(const char *date, time_t *output)
 
   return PARSEDATE_OK;
 }
+#else
+/* disabled */
+static int parsedate(const char *date, time_t *output)
+{
+  (void)date;
+  *output = 0;
+  return PARSEDATE_OK; /* a lie */
+}
+#endif
 
 time_t curl_getdate(const char *p, const time_t *now)
 {
diff --git a/lib/pingpong.c b/lib/pingpong.c
index 2e93d20..e9568ee 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -44,7 +44,7 @@
 
 /* Returns timeout in ms. 0 or negative number means the timeout has already
    triggered */
-time_t Curl_pp_state_timeout(struct pingpong *pp)
+time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting)
 {
   struct connectdata *conn = pp->conn;
   struct Curl_easy *data = conn->data;
@@ -62,7 +62,7 @@ time_t Curl_pp_state_timeout(struct pingpong *pp)
   timeout_ms = response_time -
     Curl_timediff(Curl_now(), pp->response); /* spent time */
 
-  if(data->set.timeout) {
+  if(data->set.timeout && !disconnecting) {
     /* if timeout is requested, find out how much remaining time we have */
     time_t timeout2_ms = data->set.timeout - /* timeout time */
       Curl_timediff(Curl_now(), conn->now); /* spent time */
@@ -77,13 +77,14 @@ time_t Curl_pp_state_timeout(struct pingpong *pp)
 /*
  * Curl_pp_statemach()
  */
-CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
+CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
+                           bool disconnecting)
 {
   struct connectdata *conn = pp->conn;
   curl_socket_t sock = conn->sock[FIRSTSOCKET];
   int rc;
   time_t interval_ms;
-  time_t timeout_ms = Curl_pp_state_timeout(pp);
+  time_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting);
   struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_OK;
 
diff --git a/lib/pingpong.h b/lib/pingpong.h
index 5ac8df8..dbe1f8d 100644
--- a/lib/pingpong.h
+++ b/lib/pingpong.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -81,14 +81,15 @@ struct pingpong {
  * called repeatedly until done. Set 'wait' to make it wait a while on the
  * socket if there's no traffic.
  */
-CURLcode Curl_pp_statemach(struct pingpong *pp, bool block);
+CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
+                           bool disconnecting);
 
 /* initialize stuff to prepare for reading a fresh new response */
 void Curl_pp_init(struct pingpong *pp);
 
 /* Returns timeout in ms. 0 or negative number means the timeout has already
    triggered */
-time_t Curl_pp_state_timeout(struct pingpong *pp);
+time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting);
 
 
 /***********************************************************************
diff --git a/lib/pipeline.c b/lib/pipeline.c
deleted file mode 100644
index 8de3bab..0000000
--- a/lib/pipeline.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/***************************************************************************
- *                                  _   _ ____  _
- *  Project                     ___| | | |  _ \| |
- *                             / __| | | | |_) | |
- *                            | (__| |_| |  _ <| |___
- *                             \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2013, Linus Nielsen Feltzing, <linus at haxx.se>
- * Copyright (C) 2013 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-#include "curl_setup.h"
-
-#include <curl/curl.h>
-
-#include "urldata.h"
-#include "url.h"
-#include "progress.h"
-#include "multiif.h"
-#include "pipeline.h"
-#include "sendf.h"
-#include "strcase.h"
-
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
-
-struct site_blacklist_entry {
-  struct curl_llist_element list;
-  unsigned short port;
-  char hostname[1];
-};
-
-static void site_blacklist_llist_dtor(void *user, void *element)
-{
-  struct site_blacklist_entry *entry = element;
-  (void)user;
-  free(entry);
-}
-
-static void server_blacklist_llist_dtor(void *user, void *element)
-{
-  (void)user;
-  free(element);
-}
-
-bool Curl_pipeline_penalized(struct Curl_easy *data,
-                             struct connectdata *conn)
-{
-  if(data) {
-    bool penalized = FALSE;
-    curl_off_t penalty_size =
-      Curl_multi_content_length_penalty_size(data->multi);
-    curl_off_t chunk_penalty_size =
-      Curl_multi_chunk_length_penalty_size(data->multi);
-    curl_off_t recv_size = -2; /* Make it easy to spot in the log */
-
-    /* Find the head of the recv pipe, if any */
-    if(conn->recv_pipe.head) {
-      struct Curl_easy *recv_handle = conn->recv_pipe.head->ptr;
-
-      recv_size = recv_handle->req.size;
-
-      if(penalty_size > 0 && recv_size > penalty_size)
-        penalized = TRUE;
-    }
-
-    if(chunk_penalty_size > 0 &&
-       (curl_off_t)conn->chunk.datasize > chunk_penalty_size)
-      penalized = TRUE;
-
-    infof(data, "Conn: %ld (%p) Receive pipe weight: (%"
-          CURL_FORMAT_CURL_OFF_T "/%" CURL_FORMAT_CURL_OFF_T
-          "), penalized: %s\n",
-          conn->connection_id, (void *)conn, recv_size,
-          conn->chunk.datasize, penalized?"TRUE":"FALSE");
-    return penalized;
-  }
-  return FALSE;
-}
-
-static CURLcode addHandleToPipeline(struct Curl_easy *data,
-                                    struct curl_llist *pipeline)
-{
-  Curl_llist_insert_next(pipeline, pipeline->tail, data,
-                         &data->pipeline_queue);
-  return CURLE_OK;
-}
-
-
-CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle,
-                                     struct connectdata *conn)
-{
-  struct curl_llist_element *sendhead = conn->send_pipe.head;
-  struct curl_llist *pipeline;
-  CURLcode result;
-
-  pipeline = &conn->send_pipe;
-
-  result = addHandleToPipeline(handle, pipeline);
-  if((conn->bundle->multiuse == BUNDLE_PIPELINING) &&
-     (pipeline == &conn->send_pipe && sendhead != conn->send_pipe.head)) {
-    /* this is a new one as head, expire it */
-    Curl_pipeline_leave_write(conn); /* not in use yet */
-    Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
-  }
-
-#if 0 /* enable for pipeline debugging */
-  print_pipeline(conn);
-#endif
-
-  return result;
-}
-
-/* Move this transfer from the sending list to the receiving list.
-
-   Pay special attention to the new sending list "leader" as it needs to get
-   checked to update what sockets it acts on.
-
-*/
-void Curl_move_handle_from_send_to_recv_pipe(struct Curl_easy *handle,
-                                             struct connectdata *conn)
-{
-  struct curl_llist_element *curr;
-
-  curr = conn->send_pipe.head;
-  while(curr) {
-    if(curr->ptr == handle) {
-      Curl_llist_move(&conn->send_pipe, curr,
-                      &conn->recv_pipe, conn->recv_pipe.tail);
-
-      if(conn->send_pipe.head) {
-        /* Since there's a new easy handle at the start of the send pipeline,
-           set its timeout value to 1ms to make it trigger instantly */
-        Curl_pipeline_leave_write(conn); /* not used now */
-#ifdef DEBUGBUILD
-        infof(conn->data, "%p is at send pipe head B!\n",
-              (void *)conn->send_pipe.head->ptr);
-#endif
-        Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
-      }
-
-      /* The receiver's list is not really interesting here since either this
-         handle is now first in the list and we'll deal with it soon, or
-         another handle is already first and thus is already taken care of */
-
-      break; /* we're done! */
-    }
-    curr = curr->next;
-  }
-}
-
-bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle,
-                                    struct connectdata *conn)
-{
-  if(handle->multi) {
-    struct curl_llist *blacklist =
-      Curl_multi_pipelining_site_bl(handle->multi);
-
-    if(blacklist) {
-      struct curl_llist_element *curr;
-
-      curr = blacklist->head;
-      while(curr) {
-        struct site_blacklist_entry *site;
-
-        site = curr->ptr;
-        if(strcasecompare(site->hostname, conn->host.name) &&
-           site->port == conn->remote_port) {
-          infof(handle, "Site %s:%d is pipeline blacklisted\n",
-                conn->host.name, conn->remote_port);
-          return TRUE;
-        }
-        curr = curr->next;
-      }
-    }
-  }
-  return FALSE;
-}
-
-CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
-                                           struct curl_llist *list)
-{
-  /* Free the old list */
-  if(list->size)
-    Curl_llist_destroy(list, NULL);
-
-  if(sites) {
-    Curl_llist_init(list, (curl_llist_dtor) site_blacklist_llist_dtor);
-
-    /* Parse the URLs and populate the list */
-    while(*sites) {
-      char *port;
-      struct site_blacklist_entry *entry;
-
-      entry = malloc(sizeof(struct site_blacklist_entry) + strlen(*sites));
-      if(!entry) {
-        Curl_llist_destroy(list, NULL);
-        return CURLM_OUT_OF_MEMORY;
-      }
-      strcpy(entry->hostname, *sites);
-
-      port = strchr(entry->hostname, ':');
-      if(port) {
-        *port = '\0';
-        port++;
-        entry->port = (unsigned short)strtol(port, NULL, 10);
-      }
-      else {
-        /* Default port number for HTTP */
-        entry->port = 80;
-      }
-
-      Curl_llist_insert_next(list, list->tail, entry, &entry->list);
-      sites++;
-    }
-  }
-
-  return CURLM_OK;
-}
-
-struct blacklist_node {
-  struct curl_llist_element list;
-  char server_name[1];
-};
-
-bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle,
-                                      char *server_name)
-{
-  if(handle->multi && server_name) {
-    struct curl_llist *list =
-      Curl_multi_pipelining_server_bl(handle->multi);
-
-    struct curl_llist_element *e = list->head;
-    while(e) {
-      struct blacklist_node *bl = (struct blacklist_node *)e;
-      if(strncasecompare(bl->server_name, server_name,
-                         strlen(bl->server_name))) {
-        infof(handle, "Server %s is blacklisted\n", server_name);
-        return TRUE;
-      }
-      e = e->next;
-    }
-
-    DEBUGF(infof(handle, "Server %s is not blacklisted\n", server_name));
-  }
-  return FALSE;
-}
-
-CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
-                                             struct curl_llist *list)
-{
-  /* Free the old list */
-  if(list->size)
-    Curl_llist_destroy(list, NULL);
-
-  if(servers) {
-    Curl_llist_init(list, (curl_llist_dtor) server_blacklist_llist_dtor);
-
-    /* Parse the URLs and populate the list */
-    while(*servers) {
-      struct blacklist_node *n;
-      size_t len = strlen(*servers);
-
-      n = malloc(sizeof(struct blacklist_node) + len);
-      if(!n) {
-        Curl_llist_destroy(list, NULL);
-        return CURLM_OUT_OF_MEMORY;
-      }
-      strcpy(n->server_name, *servers);
-
-      Curl_llist_insert_next(list, list->tail, n, &n->list);
-      servers++;
-    }
-  }
-
-
-  return CURLM_OK;
-}
-
-static bool pipe_head(struct Curl_easy *data,
-                      struct curl_llist *pipeline)
-{
-  if(pipeline) {
-    struct curl_llist_element *curr = pipeline->head;
-    if(curr)
-      return (curr->ptr == data) ? TRUE : FALSE;
-  }
-  return FALSE;
-}
-
-/* returns TRUE if the given handle is head of the recv pipe */
-bool Curl_recvpipe_head(struct Curl_easy *data,
-                        struct connectdata *conn)
-{
-  return pipe_head(data, &conn->recv_pipe);
-}
-
-/* returns TRUE if the given handle is head of the send pipe */
-bool Curl_sendpipe_head(struct Curl_easy *data,
-                        struct connectdata *conn)
-{
-  return pipe_head(data, &conn->send_pipe);
-}
-
-
-/*
- * Check if the write channel is available and this handle as at the head,
- * then grab the channel and return TRUE.
- *
- * If not available, return FALSE.
- */
-
-bool Curl_pipeline_checkget_write(struct Curl_easy *data,
-                                  struct connectdata *conn)
-{
-  if(conn->bits.multiplex)
-    /* when multiplexing, we can use it at once */
-    return TRUE;
-
-  if(!conn->writechannel_inuse && Curl_sendpipe_head(data, conn)) {
-    /* Grab the channel */
-    conn->writechannel_inuse = TRUE;
-    return TRUE;
-  }
-  return FALSE;
-}
-
-
-/*
- * Check if the read channel is available and this handle as at the head, then
- * grab the channel and return TRUE.
- *
- * If not available, return FALSE.
- */
-
-bool Curl_pipeline_checkget_read(struct Curl_easy *data,
-                                 struct connectdata *conn)
-{
-  if(conn->bits.multiplex)
-    /* when multiplexing, we can use it at once */
-    return TRUE;
-
-  if(!conn->readchannel_inuse && Curl_recvpipe_head(data, conn)) {
-    /* Grab the channel */
-    conn->readchannel_inuse = TRUE;
-    return TRUE;
-  }
-  return FALSE;
-}
-
-/*
- * The current user of the pipeline write channel gives it up.
- */
-void Curl_pipeline_leave_write(struct connectdata *conn)
-{
-  conn->writechannel_inuse = FALSE;
-}
-
-/*
- * The current user of the pipeline read channel gives it up.
- */
-void Curl_pipeline_leave_read(struct connectdata *conn)
-{
-  conn->readchannel_inuse = FALSE;
-}
-
-
-#if 0
-void print_pipeline(struct connectdata *conn)
-{
-  struct curl_llist_element *curr;
-  struct connectbundle *cb_ptr;
-  struct Curl_easy *data = conn->data;
-
-  cb_ptr = conn->bundle;
-
-  if(cb_ptr) {
-    curr = cb_ptr->conn_list->head;
-    while(curr) {
-      conn = curr->ptr;
-      infof(data, "- Conn %ld (%p) send_pipe: %zu, recv_pipe: %zu\n",
-            conn->connection_id,
-            (void *)conn,
-            conn->send_pipe->size,
-            conn->recv_pipe->size);
-      curr = curr->next;
-    }
-  }
-}
-
-#endif
diff --git a/lib/pipeline.h b/lib/pipeline.h
deleted file mode 100644
index 413ba31..0000000
--- a/lib/pipeline.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef HEADER_CURL_PIPELINE_H
-#define HEADER_CURL_PIPELINE_H
-/***************************************************************************
- *                                  _   _ ____  _
- *  Project                     ___| | | |  _ \| |
- *                             / __| | | | |_) | |
- *                            | (__| |_| |  _ <| |___
- *                             \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2015 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
- * Copyright (C) 2013 - 2014, Linus Nielsen Feltzing, <linus at haxx.se>
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle,
-                                     struct connectdata *conn);
-void Curl_move_handle_from_send_to_recv_pipe(struct Curl_easy *handle,
-                                             struct connectdata *conn);
-bool Curl_pipeline_penalized(struct Curl_easy *data,
-                             struct connectdata *conn);
-
-bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle,
-                                    struct connectdata *conn);
-
-CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
-                                           struct curl_llist *list_ptr);
-
-bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle,
-                                      char *server_name);
-
-CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
-                                             struct curl_llist *list_ptr);
-
-bool Curl_pipeline_checkget_write(struct Curl_easy *data,
-                                  struct connectdata *conn);
-bool Curl_pipeline_checkget_read(struct Curl_easy *data,
-                                 struct connectdata *conn);
-void Curl_pipeline_leave_write(struct connectdata *conn);
-void Curl_pipeline_leave_read(struct connectdata *conn);
-bool Curl_recvpipe_head(struct Curl_easy *data,
-                        struct connectdata *conn);
-bool Curl_sendpipe_head(struct Curl_easy *data,
-                        struct connectdata *conn);
-
-#endif /* HEADER_CURL_PIPELINE_H */
diff --git a/lib/pop3.c b/lib/pop3.c
index 5e0fd22..c8f3965 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -30,6 +30,7 @@
  * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
  * RFC5034 POP3 SASL Authentication Mechanism
  * RFC6749 OAuth 2.0 Authorization Framework
+ * RFC8314 Use of TLS for Email Submission and Access
  * Draft   LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
  *
  ***************************************************************************/
@@ -208,7 +209,7 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
   /* Are we processing CAPA command responses? */
   if(pop3c->state == POP3_CAPA) {
     /* Do we have the terminating line? */
-    if(len >= 1 && !memcmp(line, ".", 1))
+    if(len >= 1 && line[0] == '.')
       /* Treat the response as a success */
       *resp = '+';
     else
@@ -226,7 +227,7 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
   }
 
   /* Do we have a continuation response? */
-  if(len >= 1 && !memcmp("+", line, 1)) {
+  if(len >= 1 && line[0] == '+') {
     *resp = '*';
 
     return TRUE;
@@ -443,7 +444,7 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
 
   /* Convert the calculated 16 octet digest into a 32 byte hex string */
   for(i = 0; i < MD5_DIGEST_LEN; i++)
-    snprintf(&secret[2 * i], 3, "%02x", digest[i]);
+    msnprintf(&secret[2 * i], 3, "%02x", digest[i]);
 
   result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret);
 
@@ -629,6 +630,7 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
         if(line[i] == '<') {
           /* Calculate the length of the timestamp */
           size_t timestamplen = len - 1 - i;
+          char *at;
           if(!timestamplen)
             break;
 
@@ -642,8 +644,15 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
           memcpy(pop3c->apoptimestamp, line + i, timestamplen);
           pop3c->apoptimestamp[timestamplen] = '\0';
 
-          /* Store the APOP capability */
-          pop3c->authtypes |= POP3_TYPE_APOP;
+          /* If the timestamp does not contain '@' it is not (as required by
+             RFC-1939) conformant to the RFC-822 message id syntax, and we
+             therefore do not use APOP authentication. */
+          at = strchr(pop3c->apoptimestamp, '@');
+          if(!at)
+            Curl_safefree(pop3c->apoptimestamp);
+          else
+            /* Store the APOP capability */
+            pop3c->authtypes |= POP3_TYPE_APOP;
           break;
         }
       }
@@ -904,7 +913,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn,
 
   if(pop3->transfer == FTPTRANSFER_BODY) {
     /* POP3 download */
-    Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
 
     if(pp->cache) {
       /* The header "cache" contains a bunch of data that is actually body
@@ -1017,19 +1026,20 @@ static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done)
       return result;
   }
 
-  result = Curl_pp_statemach(&pop3c->pp, FALSE);
+  result = Curl_pp_statemach(&pop3c->pp, FALSE, FALSE);
   *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;
 
   return result;
 }
 
-static CURLcode pop3_block_statemach(struct connectdata *conn)
+static CURLcode pop3_block_statemach(struct connectdata *conn,
+                                     bool disconnecting)
 {
   CURLcode result = CURLE_OK;
   struct pop3_conn *pop3c = &conn->proto.pop3c;
 
   while(pop3c->state != POP3_STOP && !result)
-    result = Curl_pp_statemach(&pop3c->pp, TRUE);
+    result = Curl_pp_statemach(&pop3c->pp, TRUE, disconnecting);
 
   return result;
 }
@@ -1227,7 +1237,7 @@ static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection)
      point! */
   if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart)
     if(!pop3_perform_quit(conn))
-      (void)pop3_block_statemach(conn); /* ignore errors on QUIT */
+      (void)pop3_block_statemach(conn, TRUE); /* ignore errors on QUIT */
 
   /* Disconnect from the server */
   Curl_pp_disconnect(&pop3c->pp);
diff --git a/lib/progress.c b/lib/progress.c
index a94668d..f586d59 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -31,6 +31,7 @@
 /* check rate limits within this many recent milliseconds, at minimum. */
 #define MIN_RATE_LIMIT_PERIOD 3000
 
+#ifndef CURL_DISABLE_PROGRESS_METER
 /* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
    byte) */
 static void time2str(char *r, curl_off_t seconds)
@@ -44,8 +45,8 @@ static void time2str(char *r, curl_off_t seconds)
   if(h <= CURL_OFF_T_C(99)) {
     curl_off_t m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
     curl_off_t s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
-    snprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T
-             ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s);
+    msnprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T
+              ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s);
   }
   else {
     /* this equals to more than 99 hours, switch to a more suitable output
@@ -53,10 +54,10 @@ static void time2str(char *r, curl_off_t seconds)
     curl_off_t d = seconds / CURL_OFF_T_C(86400);
     h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600);
     if(d <= CURL_OFF_T_C(999))
-      snprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T
-               "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h);
+      msnprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T
+                "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h);
     else
-      snprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d);
+      msnprintf(r, 9, "%7" CURL_FORMAT_CURL_OFF_T "d", d);
   }
 }
 
@@ -72,40 +73,40 @@ static char *max5data(curl_off_t bytes, char *max5)
 #define ONE_PETABYTE (CURL_OFF_T_C(1024) * ONE_TERABYTE)
 
   if(bytes < CURL_OFF_T_C(100000))
-    snprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes);
+    msnprintf(max5, 6, "%5" CURL_FORMAT_CURL_OFF_T, bytes);
 
   else if(bytes < CURL_OFF_T_C(10000) * ONE_KILOBYTE)
-    snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "k", bytes/ONE_KILOBYTE);
+    msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "k", bytes/ONE_KILOBYTE);
 
   else if(bytes < CURL_OFF_T_C(100) * ONE_MEGABYTE)
     /* 'XX.XM' is good as long as we're less than 100 megs */
-    snprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
-             CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
-             (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
+    msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
+              CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
+              (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
 
 #if (CURL_SIZEOF_CURL_OFF_T > 4)
 
   else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE)
     /* 'XXXXM' is good until we're at 10000MB or above */
-    snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
+    msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
 
   else if(bytes < CURL_OFF_T_C(100) * ONE_GIGABYTE)
     /* 10000 MB - 100 GB, we show it as XX.XG */
-    snprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
-             CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE,
-             (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) );
+    msnprintf(max5, 6, "%2" CURL_FORMAT_CURL_OFF_T ".%0"
+              CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE,
+              (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) );
 
   else if(bytes < CURL_OFF_T_C(10000) * ONE_GIGABYTE)
     /* up to 10000GB, display without decimal: XXXXG */
-    snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE);
+    msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "G", bytes/ONE_GIGABYTE);
 
   else if(bytes < CURL_OFF_T_C(10000) * ONE_TERABYTE)
     /* up to 10000TB, display without decimal: XXXXT */
-    snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "T", bytes/ONE_TERABYTE);
+    msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "T", bytes/ONE_TERABYTE);
 
   else
     /* up to 10000PB, display without decimal: XXXXP */
-    snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE);
+    msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "P", bytes/ONE_PETABYTE);
 
     /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number
        can hold, but our data type is signed so 8192PB will be the maximum. */
@@ -113,12 +114,13 @@ static char *max5data(curl_off_t bytes, char *max5)
 #else
 
   else
-    snprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
+    msnprintf(max5, 6, "%4" CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE);
 
 #endif
 
   return max5;
 }
+#endif
 
 /*
 
@@ -362,17 +364,13 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
   }
 }
 
-/*
- * Curl_pgrsUpdate() returns 0 for success or the value returned by the
- * progress callback!
- */
-int Curl_pgrsUpdate(struct connectdata *conn)
+#ifndef CURL_DISABLE_PROGRESS_METER
+static void progress_meter(struct connectdata *conn)
 {
   struct curltime now;
   curl_off_t timespent;
   curl_off_t timespent_ms; /* milliseconds */
   struct Curl_easy *data = conn->data;
-  int nowindex = data->progress.speeder_c% CURR_TIME;
   bool shownow = FALSE;
   curl_off_t dl = data->progress.downloaded;
   curl_off_t ul = data->progress.uploaded;
@@ -399,7 +397,9 @@ int Curl_pgrsUpdate(struct connectdata *conn)
   /* Calculations done at most once a second, unless end is reached */
   if(data->progress.lastshow != now.tv_sec) {
     int countindex; /* amount of seconds stored in the speeder array */
-    shownow = TRUE;
+    int nowindex = data->progress.speeder_c% CURR_TIME;
+    if(!(data->progress.flags & PGRS_HIDE))
+      shownow = TRUE;
 
     data->progress.lastshow = now.tv_sec;
 
@@ -461,8 +461,12 @@ int Curl_pgrsUpdate(struct connectdata *conn)
         data->progress.ulspeed + data->progress.dlspeed;
 
   } /* Calculations end */
-
-  if(!(data->progress.flags & PGRS_HIDE)) {
+  if(!shownow)
+    /* only show the internal progress meter once per second */
+    return;
+  else {
+    /* If there's no external callback set, use internal code to show
+       progress */
     /* progress meter has not been shut off */
     char max5[6][10];
     curl_off_t dlpercen = 0;
@@ -477,42 +481,6 @@ int Curl_pgrsUpdate(struct connectdata *conn)
     curl_off_t dlestimate = 0;
     curl_off_t total_estimate;
 
-    if(data->set.fxferinfo) {
-      int result;
-      /* There's a callback set, call that */
-      Curl_set_in_callback(data, true);
-      result = data->set.fxferinfo(data->set.progress_client,
-                                   data->progress.size_dl,
-                                   data->progress.downloaded,
-                                   data->progress.size_ul,
-                                   data->progress.uploaded);
-      Curl_set_in_callback(data, false);
-      if(result)
-        failf(data, "Callback aborted");
-      return result;
-    }
-    if(data->set.fprogress) {
-      int result;
-      /* The older deprecated callback is set, call that */
-      Curl_set_in_callback(data, true);
-      result = data->set.fprogress(data->set.progress_client,
-                                   (double)data->progress.size_dl,
-                                   (double)data->progress.downloaded,
-                                   (double)data->progress.size_ul,
-                                   (double)data->progress.uploaded);
-      Curl_set_in_callback(data, false);
-      if(result)
-        failf(data, "Callback aborted");
-      return result;
-    }
-
-    if(!shownow)
-      /* only show the internal progress meter once per second */
-      return 0;
-
-    /* If there's no external callback set, use internal code to show
-       progress */
-
     if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
       if(data->state.resume_from) {
         fprintf(data->set.err,
@@ -564,9 +532,9 @@ int Curl_pgrsUpdate(struct connectdata *conn)
 
     /* Get the total amount of data expected to get transferred */
     total_expected_transfer =
-      (data->progress.flags & PGRS_UL_SIZE_KNOWN?
+      ((data->progress.flags & PGRS_UL_SIZE_KNOWN)?
        data->progress.size_ul:data->progress.uploaded)+
-      (data->progress.flags & PGRS_DL_SIZE_KNOWN?
+      ((data->progress.flags & PGRS_DL_SIZE_KNOWN)?
        data->progress.size_dl:data->progress.downloaded);
 
     /* We have transferred this much so far */
@@ -595,13 +563,57 @@ int Curl_pgrsUpdate(struct connectdata *conn)
             time_total,    /* 8 letters */                /* total time */
             time_spent,    /* 8 letters */                /* time spent */
             time_left,     /* 8 letters */                /* time left */
-            max5data(data->progress.current_speed, max5[5]) /* current speed */
-            );
+            max5data(data->progress.current_speed, max5[5])
+      );
 
     /* we flush the output stream to make it appear as soon as possible */
     fflush(data->set.err);
+  } /* don't show now */
+}
+#else
+ /* progress bar disabled */
+#define progress_meter(x)
+#endif
+
 
-  } /* !(data->progress.flags & PGRS_HIDE) */
+/*
+ * Curl_pgrsUpdate() returns 0 for success or the value returned by the
+ * progress callback!
+ */
+int Curl_pgrsUpdate(struct connectdata *conn)
+{
+  struct Curl_easy *data = conn->data;
+  if(!(data->progress.flags & PGRS_HIDE)) {
+    if(data->set.fxferinfo) {
+      int result;
+      /* There's a callback set, call that */
+      Curl_set_in_callback(data, true);
+      result = data->set.fxferinfo(data->set.progress_client,
+                                   data->progress.size_dl,
+                                   data->progress.downloaded,
+                                   data->progress.size_ul,
+                                   data->progress.uploaded);
+      Curl_set_in_callback(data, false);
+      if(result)
+        failf(data, "Callback aborted");
+      return result;
+    }
+    if(data->set.fprogress) {
+      int result;
+      /* The older deprecated callback is set, call that */
+      Curl_set_in_callback(data, true);
+      result = data->set.fprogress(data->set.progress_client,
+                                   (double)data->progress.size_dl,
+                                   (double)data->progress.downloaded,
+                                   (double)data->progress.size_ul,
+                                   (double)data->progress.uploaded);
+      Curl_set_in_callback(data, false);
+      if(result)
+        failf(data, "Callback aborted");
+      return result;
+    }
+  }
+  progress_meter(conn);
 
   return 0;
 }
diff --git a/lib/rand.h b/lib/rand.h
index c6fae35..5deb041 100644
--- a/lib/rand.h
+++ b/lib/rand.h
@@ -39,8 +39,11 @@
  */
 CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
 
-/* Same as above but outputs only random lowercase hex characters.
-   Does NOT terminate.*/
+/*
+ * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
+ * hexadecimal digits PLUS a zero terminating byte. It must be an odd number
+ * size.
+ */
 CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
                        size_t num);
 
diff --git a/lib/rtsp.c b/lib/rtsp.c
index 01dfce6..74cf232 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -42,16 +42,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-/*
- * TODO (general)
- *  -incoming server requests
- *      -server CSeq counter
- *  -digest authentication
- *  -connect through proxy
- *  -pipelining?
- */
-
-
 #define RTP_PKT_CHANNEL(p)   ((int)((unsigned char)((p)[1])))
 
 #define RTP_PKT_LENGTH(p)  ((((int)((unsigned char)((p)[2]))) << 8) | \
@@ -80,8 +70,6 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
                                    bool *readmore);
 
 static CURLcode rtsp_setup_connection(struct connectdata *conn);
-
-bool rtsp_connisdead(struct connectdata *check);
 static unsigned int rtsp_conncheck(struct connectdata *check,
                                    unsigned int checks_to_perform);
 
@@ -147,7 +135,7 @@ static CURLcode rtsp_setup_connection(struct connectdata *conn)
  * Instead, if it is readable, run Curl_connalive() to peek at the socket
  * and distinguish between closed and data.
  */
-bool rtsp_connisdead(struct connectdata *check)
+static bool rtsp_connisdead(struct connectdata *check)
 {
   int sval;
   bool ret_val = TRUE;
@@ -238,7 +226,6 @@ static CURLcode rtsp_done(struct connectdata *conn,
     if(data->set.rtspreq == RTSPREQ_RECEIVE &&
             (conn->proto.rtspc.rtp_channel == -1)) {
       infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
-      /* TODO CPC: Server -> Client logic here */
     }
   }
 
@@ -251,7 +238,6 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
   CURLcode result = CURLE_OK;
   Curl_RtspReq rtspreq = data->set.rtspreq;
   struct RTSP *rtsp = data->req.protop;
-  struct HTTP *http;
   Curl_send_buffer *req_buffer;
   curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
   curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */
@@ -270,10 +256,6 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
 
   *done = TRUE;
 
-  http = &(rtsp->http_wrapper);
-  /* Assert that no one has changed the RTSP struct in an evil way */
-  DEBUGASSERT((void *)http == (void *)rtsp);
-
   rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq;
   rtsp->CSeq_recv = 0;
 
@@ -330,8 +312,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
   }
 
   if(rtspreq == RTSPREQ_RECEIVE) {
-    Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
-                        &http->readbytecount, -1, NULL);
+    Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
 
     return result;
   }
@@ -344,8 +325,6 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
     return CURLE_BAD_FUNCTION_ARGUMENT;
   }
 
-  /* TODO: proxy? */
-
   /* Stream URI. Default to server '*' if not specified */
   if(data->set.str[STRING_RTSP_STREAM_URI]) {
     p_stream_uri = data->set.str[STRING_RTSP_STREAM_URI];
@@ -599,17 +578,15 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
     return result;
   }
 
-  Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
-                      putsize?FIRSTSOCKET:-1,
-                      putsize?&http->writebytecount:NULL);
+  Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, putsize?FIRSTSOCKET:-1);
 
   /* Increment the CSeq on success */
   data->state.rtsp_next_client_CSeq++;
 
-  if(http->writebytecount) {
+  if(data->req.writebytecount) {
     /* if a request-body has been sent off, we make sure this progress is
        noted properly */
-    Curl_pgrsSetUploadCounter(data, http->writebytecount);
+    Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
     if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
   }
diff --git a/lib/security.c b/lib/security.c
index c278406..7695154 100644
--- a/lib/security.c
+++ b/lib/security.c
@@ -10,7 +10,7 @@
  * Copyright (c) 1998, 1999, 2017 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
  *
- * Copyright (C) 2001 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2001 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * All rights reserved.
  *
@@ -120,7 +120,7 @@ static int ftp_send_command(struct connectdata *conn, const char *message, ...)
   char print_buffer[50];
 
   va_start(args, message);
-  vsnprintf(print_buffer, sizeof(print_buffer), message, args);
+  mvsnprintf(print_buffer, sizeof(print_buffer), message, args);
   va_end(args);
 
   if(Curl_ftpsend(conn, print_buffer)) {
@@ -142,7 +142,7 @@ socket_read(curl_socket_t fd, void *to, size_t len)
 {
   char *to_p = to;
   CURLcode result;
-  ssize_t nread;
+  ssize_t nread = 0;
 
   while(len > 0) {
     result = Curl_read_plain(fd, to_p, len, &nread);
@@ -151,7 +151,6 @@ socket_read(curl_socket_t fd, void *to, size_t len)
       to_p += nread;
     }
     else {
-      /* FIXME: We are doing a busy wait */
       if(result == CURLE_AGAIN)
         continue;
       return result;
@@ -179,7 +178,6 @@ socket_write(struct connectdata *conn, curl_socket_t fd, const void *to,
       to_p += written;
     }
     else {
-      /* FIXME: We are doing a busy wait */
       if(result == CURLE_AGAIN)
         continue;
       return result;
@@ -265,13 +263,11 @@ static ssize_t sec_recv(struct connectdata *conn, int sockindex,
     total_read += bytes_read;
     buffer += bytes_read;
   }
-  /* FIXME: Check for overflow */
   return total_read;
 }
 
 /* Send |length| bytes from |from| to the |fd| socket taking care of encoding
    and negociating with the server. |from| can be NULL. */
-/* FIXME: We don't check for errors nor report any! */
 static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
                         const char *from, int length)
 {
@@ -406,18 +402,14 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
 
   if(buf[decoded_len - 1] == '\n')
     buf[decoded_len - 1] = '\0';
-  /* FIXME: Is |buffer| length always greater than |decoded_len|? */
   strcpy(buffer, buf);
   free(buf);
   return ret_code;
 }
 
-/* FIXME: The error code returned here is never checked. */
 static int sec_set_protection_level(struct connectdata *conn)
 {
   int code;
-  char *pbsz;
-  static unsigned int buffer_size = 1 << 20; /* 1048576 */
   enum protection_level level = conn->request_data_prot;
 
   DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
@@ -433,6 +425,9 @@ static int sec_set_protection_level(struct connectdata *conn)
     return 0;
 
   if(level) {
+    char *pbsz;
+    static unsigned int buffer_size = 1 << 20; /* 1048576 */
+
     code = ftp_send_command(conn, "PBSZ %u", buffer_size);
     if(code < 0)
       return -1;
@@ -508,7 +503,6 @@ static CURLcode choose_mech(struct connectdata *conn)
   infof(data, "Trying mechanism %s...\n", mech->name);
   ret = ftp_send_command(conn, "AUTH %s", mech->name);
   if(ret < 0)
-    /* FIXME: This error is too generic but it is OK for now. */
     return CURLE_COULDNT_CONNECT;
 
   if(ret/100 != 3) {
@@ -575,7 +569,6 @@ Curl_sec_end(struct connectdata *conn)
     conn->in_buffer.data = NULL;
     conn->in_buffer.size = 0;
     conn->in_buffer.index = 0;
-    /* FIXME: Is this really needed? */
     conn->in_buffer.eof_flag = 0;
   }
   conn->sec_complete = 0;
diff --git a/lib/sendf.c b/lib/sendf.c
index d3c10b3..5913ea4 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -237,7 +237,18 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
     size_t len;
     char print_buffer[2048 + 1];
     va_start(ap, fmt);
-    vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
+    len = mvsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
+    /*
+     * Indicate truncation of the input by replacing the last 3 characters
+     * with "...", and transfer the newline over in case the format had one.
+     */
+    if(len >= sizeof(print_buffer)) {
+      len = strlen(fmt);
+      if(fmt[--len] == '\n')
+        msnprintf(print_buffer + (sizeof(print_buffer) - 5), 5, "...\n");
+      else
+        msnprintf(print_buffer + (sizeof(print_buffer) - 4), 4, "...");
+    }
     va_end(ap);
     len = strlen(print_buffer);
     Curl_debug(data, CURLINFO_TEXT, print_buffer, len);
@@ -255,7 +266,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
     size_t len;
     char error[CURL_ERROR_SIZE + 2];
     va_start(ap, fmt);
-    vsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
+    mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
     len = strlen(error);
 
     if(data->set.errorbuffer && !data->state.errorbuf) {
@@ -400,8 +411,9 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
       *code = CURLE_AGAIN;
     }
     else {
+      char buffer[STRERROR_LEN];
       failf(conn->data, "Send failure: %s",
-            Curl_strerror(conn, err));
+            Curl_strerror(err, buffer, sizeof(buffer)));
       conn->data->state.os_errno = err;
       *code = CURLE_SEND_ERROR;
     }
@@ -465,8 +477,9 @@ ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
       *code = CURLE_AGAIN;
     }
     else {
+      char buffer[STRERROR_LEN];
       failf(conn->data, "Recv failure: %s",
-            Curl_strerror(conn, err));
+            Curl_strerror(err, buffer, sizeof(buffer)));
       conn->data->state.os_errno = err;
       *code = CURLE_RECV_ERROR;
     }
@@ -582,7 +595,10 @@ static CURLcode chop_write(struct connectdata *conn,
     size_t chunklen = len <= CURL_MAX_WRITE_SIZE? len: CURL_MAX_WRITE_SIZE;
 
     if(writebody) {
-      size_t wrote = writebody(ptr, 1, chunklen, data->set.out);
+      size_t wrote;
+      Curl_set_in_callback(data, true);
+      wrote = writebody(ptr, 1, chunklen, data->set.out);
+      Curl_set_in_callback(data, false);
 
       if(CURL_WRITEFUNC_PAUSE == wrote) {
         if(conn->handler->flags & PROTOPT_NONETWORK) {
@@ -711,10 +727,6 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
   char *buffertofill = NULL;
   struct Curl_easy *data = conn->data;
 
-  /* if HTTP/1 pipelining is both wanted and possible */
-  bool pipelining = Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
-    (conn->bundle->multiuse == BUNDLE_PIPELINING);
-
   /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
      If it is the second socket, we set num to 1. Otherwise to 0. This lets
      us use the correct ssl handle. */
@@ -722,40 +734,13 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
 
   *n = 0; /* reset amount to zero */
 
-  /* If session can pipeline, check connection buffer  */
-  if(pipelining) {
-    size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
-                                 sizerequested);
-
-    /* Copy from our master buffer first if we have some unread data there*/
-    if(bytestocopy > 0) {
-      memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
-      conn->read_pos += bytestocopy;
-      conn->bits.stream_was_rewound = FALSE;
-
-      *n = (ssize_t)bytestocopy;
-      return CURLE_OK;
-    }
-    /* If we come here, it means that there is no data to read from the buffer,
-     * so we read from the socket */
-    bytesfromsocket = CURLMIN(sizerequested, MASTERBUF_SIZE);
-    buffertofill = conn->master_buffer;
-  }
-  else {
-    bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
-    buffertofill = buf;
-  }
+  bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
+  buffertofill = buf;
 
   nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result);
   if(nread < 0)
     return result;
 
-  if(pipelining) {
-    memcpy(buf, conn->master_buffer, nread);
-    conn->buf_len = nread;
-    conn->read_pos = nread;
-  }
-
   *n += nread;
 
   return CURLE_OK;
diff --git a/lib/setopt.c b/lib/setopt.c
index 22956a2..92cd5b2 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -44,6 +44,7 @@
 #include "http2.h"
 #include "setopt.h"
 #include "multiif.h"
+#include "altsvc.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -60,6 +61,13 @@ CURLcode Curl_setstropt(char **charp, const char *s)
   if(s) {
     char *str = strdup(s);
 
+    if(str) {
+      size_t len = strlen(str);
+      if(len > CURL_MAX_INPUT_LENGTH) {
+        free(str);
+        return CURLE_BAD_FUNCTION_ARGUMENT;
+      }
+    }
     if(!str)
       return CURLE_OUT_OF_MEMORY;
 
@@ -111,12 +119,13 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
 #define C_SSLVERSION_VALUE(x) (x & 0xffff)
 #define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
 
-CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
-                      va_list param)
+static CURLcode vsetopt(struct Curl_easy *data, CURLoption option,
+                        va_list param)
 {
   char *argptr;
   CURLcode result = CURLE_OK;
   long arg;
+  unsigned long uarg;
   curl_off_t bigsize;
 
   switch(option) {
@@ -127,23 +136,20 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     data->set.dns_cache_timeout = arg;
     break;
   case CURLOPT_DNS_USE_GLOBAL_CACHE:
-#if 0 /* deprecated */
-    /* remember we want this enabled */
-    arg = va_arg(param, long);
-    data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
-#endif
+    /* deprecated */
     break;
   case CURLOPT_SSL_CIPHER_LIST:
     /* set a list of cipher we want to use in the SSL connection */
     result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
                             va_arg(param, char *));
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_SSL_CIPHER_LIST:
     /* set a list of cipher we want to use in the SSL connection for proxy */
     result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
                             va_arg(param, char *));
     break;
-
+#endif
   case CURLOPT_TLS13_CIPHERS:
     if(Curl_ssl_tls13_ciphersuites()) {
       /* set preferred list of TLS 1.3 cipher suites */
@@ -153,6 +159,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     else
       return CURLE_NOT_BUILT_IN;
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_TLS13_CIPHERS:
     if(Curl_ssl_tls13_ciphersuites()) {
       /* set preferred list of TLS 1.3 cipher suites for proxy */
@@ -162,7 +169,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     else
       return CURLE_NOT_BUILT_IN;
     break;
-
+#endif
   case CURLOPT_RANDOM_FILE:
     /*
      * This is the path name to a file that contains random data to seed
@@ -270,27 +277,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
      */
     data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
-  case CURLOPT_FTP_CREATE_MISSING_DIRS:
-    /*
-     * An FTP option that modifies an upload to create missing directories on
-     * the server.
-     */
-    switch(va_arg(param, long)) {
-    case 0:
-      data->set.ftp_create_missing_dirs = 0;
-      break;
-    case 1:
-      data->set.ftp_create_missing_dirs = 1;
-      break;
-    case 2:
-      data->set.ftp_create_missing_dirs = 2;
-      break;
-    default:
-      /* reserve other values for future use */
-      result = CURLE_UNKNOWN_OPTION;
-      break;
-    }
-    break;
   case CURLOPT_SERVER_RESPONSE_TIMEOUT:
     /*
      * Option that specifies how quickly an server response must be obtained
@@ -302,6 +288,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     else
       return CURLE_BAD_FUNCTION_ARGUMENT;
     break;
+#ifndef CURL_DISABLE_TFTP
   case CURLOPT_TFTP_NO_OPTIONS:
     /*
      * Option that prevents libcurl from sending TFTP option requests to the
@@ -318,28 +305,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
       return CURLE_BAD_FUNCTION_ARGUMENT;
     data->set.tftp_blksize = arg;
     break;
-  case CURLOPT_DIRLISTONLY:
-    /*
-     * An option that changes the command to one that asks for a list
-     * only, no file info details.
-     */
-    data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_APPEND:
-    /*
-     * We want to upload and append to an existing file.
-     */
-    data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_FTP_FILEMETHOD:
-    /*
-     * How do access files over FTP.
-     */
-    arg = va_arg(param, long);
-    if((arg < CURLFTPMETHOD_DEFAULT) || (arg > CURLFTPMETHOD_SINGLECWD))
-      return CURLE_BAD_FUNCTION_ARGUMENT;
-    data->set.ftp_filemethod = (curl_ftpfile)arg;
-    break;
+#endif
+#ifndef CURL_DISABLE_NETRC
   case CURLOPT_NETRC:
     /*
      * Parse the $HOME/.netrc file
@@ -356,6 +323,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_NETRC_FILE],
                             va_arg(param, char *));
     break;
+#endif
   case CURLOPT_TRANSFERTEXT:
     /*
      * This option was previously named 'FTPASCII'. Renamed to work with
@@ -663,6 +631,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     break;
 
 #ifndef CURL_DISABLE_HTTP
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXYHEADER:
     /*
      * Set a list with proxy headers to use (or replace internals with)
@@ -676,13 +645,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
      */
     data->set.proxyheaders = va_arg(param, struct curl_slist *);
     break;
-
+#endif
   case CURLOPT_HEADEROPT:
     /*
      * Set header option.
      */
     arg = va_arg(param, long);
-    data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
+    data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE);
     break;
 
   case CURLOPT_HTTP200ALIASES:
@@ -803,12 +772,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
         if(checkprefix("Set-Cookie:", argptr))
           /* HTTP Header format line */
           Curl_cookie_add(data, data->cookies, TRUE, FALSE, argptr + 11, NULL,
-                          NULL);
+                          NULL, TRUE);
 
         else
           /* Netscape format line */
           Curl_cookie_add(data, data->cookies, FALSE, FALSE, argptr, NULL,
-                          NULL);
+                          NULL, TRUE);
 
         Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
         free(argptr);
@@ -860,6 +829,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     data->set.expect_100_timeout = arg;
     break;
 
+  case CURLOPT_HTTP09_ALLOWED:
+    arg = va_arg(param, unsigned long);
+    if(arg > 1L)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.http09_allowed = arg ? TRUE : FALSE;
+    break;
 #endif   /* CURL_DISABLE_HTTP */
 
   case CURLOPT_HTTPAUTH:
@@ -878,7 +853,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
 
     /* the DIGEST_IE bit is only used to set a special marker, for all the
        rest we need to handle it as normal DIGEST */
-    data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
+    data->state.authhost.iestyle =
+      (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE);
 
     if(auth & CURLAUTH_DIGEST_IE) {
       auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -961,7 +937,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
 
     /* the DIGEST_IE bit is only used to set a special marker, for all the
        rest we need to handle it as normal DIGEST */
-    data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
+    data->state.authproxy.iestyle =
+      (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE);
 
     if(auth & CURLAUTH_DIGEST_IE) {
       auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1063,7 +1040,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
 #endif
-
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_SOCKS5_GSSAPI_SERVICE:
   case CURLOPT_PROXY_SERVICE_NAME:
     /*
@@ -1072,7 +1049,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
                             va_arg(param, char *));
     break;
-
+#endif
   case CURLOPT_SERVICE_NAME:
     /*
      * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
@@ -1101,6 +1078,33 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
      */
     data->set.out = va_arg(param, void *);
     break;
+
+  case CURLOPT_DIRLISTONLY:
+    /*
+     * An option that changes the command to one that asks for a list only, no
+     * file info details. Used for FTP, POP3 and SFTP.
+     */
+    data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_APPEND:
+    /*
+     * We want to upload and append to an existing file. Used for FTP and
+     * SFTP.
+     */
+    data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+#ifndef CURL_DISABLE_FTP
+  case CURLOPT_FTP_FILEMETHOD:
+    /*
+     * How do access files over FTP.
+     */
+    arg = va_arg(param, long);
+    if((arg < CURLFTPMETHOD_DEFAULT) || (arg > CURLFTPMETHOD_SINGLECWD))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.ftp_filemethod = (curl_ftpfile)arg;
+    break;
   case CURLOPT_FTPPORT:
     /*
      * Use FTP PORT, this also specifies which IP address to use
@@ -1137,6 +1141,55 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
 
+  case CURLOPT_FTP_ACCOUNT:
+    result = Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_FTP_ALTERNATIVE_TO_USER:
+    result = Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_FTPSSLAUTH:
+    /*
+     * Set a specific auth for FTP-SSL transfers.
+     */
+    arg = va_arg(param, long);
+    if((arg < CURLFTPAUTH_DEFAULT) || (arg > CURLFTPAUTH_TLS))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.ftpsslauth = (curl_ftpauth)arg;
+    break;
+  case CURLOPT_KRBLEVEL:
+    /*
+     * A string that defines the kerberos security level.
+     */
+    result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL],
+                            va_arg(param, char *));
+    data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
+    break;
+#endif
+  case CURLOPT_FTP_CREATE_MISSING_DIRS:
+    /*
+     * An FTP/SFTP option that modifies an upload to create missing
+     * directories on the server.
+     */
+    switch(va_arg(param, long)) {
+    case 0:
+      data->set.ftp_create_missing_dirs = 0;
+      break;
+    case 1:
+      data->set.ftp_create_missing_dirs = 1;
+      break;
+    case 2:
+      data->set.ftp_create_missing_dirs = 2;
+      break;
+    default:
+      /* reserve other values for future use */
+      result = CURLE_UNKNOWN_OPTION;
+      break;
+    }
+    break;
   case CURLOPT_READDATA:
     /*
      * FILE pointer to read the file to be uploaded from. Or possibly
@@ -1204,6 +1257,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
       return CURLE_BAD_FUNCTION_ARGUMENT;
     data->set.low_speed_time = arg;
     break;
+  case CURLOPT_CURLU:
+    /*
+     * pass CURLU to set URL
+     */
+    data->set.uh = va_arg(param, CURLU *);
+    break;
   case CURLOPT_URL:
     /*
      * The URL to fetch.
@@ -1539,6 +1598,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG],
                             va_arg(param, char *));
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_SSLCERT:
     /*
      * String that holds file name of the SSL certificate to use for proxy
@@ -1546,6 +1606,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_CERT_PROXY],
                             va_arg(param, char *));
     break;
+#endif
   case CURLOPT_SSLCERTTYPE:
     /*
      * String that holds file type of the SSL certificate to use
@@ -1553,6 +1614,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
                             va_arg(param, char *));
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_SSLCERTTYPE:
     /*
      * String that holds file type of the SSL certificate to use for proxy
@@ -1560,6 +1622,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
                             va_arg(param, char *));
     break;
+#endif
   case CURLOPT_SSLKEY:
     /*
      * String that holds file name of the SSL key to use
@@ -1567,6 +1630,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG],
                             va_arg(param, char *));
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_SSLKEY:
     /*
      * String that holds file name of the SSL key to use for proxy
@@ -1574,6 +1638,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_KEY_PROXY],
                             va_arg(param, char *));
     break;
+#endif
   case CURLOPT_SSLKEYTYPE:
     /*
      * String that holds file type of the SSL key to use
@@ -1581,6 +1646,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
                             va_arg(param, char *));
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_SSLKEYTYPE:
     /*
      * String that holds file type of the SSL key to use for proxy
@@ -1588,6 +1654,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
                             va_arg(param, char *));
     break;
+#endif
   case CURLOPT_KEYPASSWD:
     /*
      * String that holds the SSL or SSH private key password.
@@ -1595,6 +1662,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
                             va_arg(param, char *));
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_KEYPASSWD:
     /*
      * String that holds the SSL private key password for proxy.
@@ -1602,6 +1670,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
                             va_arg(param, char *));
     break;
+#endif
   case CURLOPT_SSLENGINE:
     /*
      * String that holds the SSL crypto engine.
@@ -1628,14 +1697,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
      */
     data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
-
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_HAPROXYPROTOCOL:
     /*
      * Set to send the HAProxy Proxy Protocol header
      */
     data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
-
+#endif
   case CURLOPT_INTERFACE:
     /*
      * Set what interface or address/hostname to bind the socket to when
@@ -1662,14 +1731,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
       return CURLE_BAD_FUNCTION_ARGUMENT;
     data->set.localportrange = curlx_sltosi(arg);
     break;
-  case CURLOPT_KRBLEVEL:
-    /*
-     * A string that defines the kerberos security level.
-     */
-    result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL],
-                            va_arg(param, char *));
-    data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
-    break;
   case CURLOPT_GSSAPI_DELEGATION:
     /*
      * GSS-API credential delegation bitmask
@@ -1687,11 +1748,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
       TRUE : FALSE;
 
     /* Update the current connection ssl_config. */
-    if(data->easy_conn) {
-      data->easy_conn->ssl_config.verifypeer =
+    if(data->conn) {
+      data->conn->ssl_config.verifypeer =
         data->set.ssl.primary.verifypeer;
     }
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_SSL_VERIFYPEER:
     /*
      * Enable peer SSL verifying for proxy.
@@ -1700,11 +1762,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
       (0 != va_arg(param, long))?TRUE:FALSE;
 
     /* Update the current connection proxy_ssl_config. */
-    if(data->easy_conn) {
-      data->easy_conn->proxy_ssl_config.verifypeer =
+    if(data->conn) {
+      data->conn->proxy_ssl_config.verifypeer =
         data->set.proxy_ssl.primary.verifypeer;
     }
     break;
+#endif
   case CURLOPT_SSL_VERIFYHOST:
     /*
      * Enable verification of the host name in the peer certificate
@@ -1724,11 +1787,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
 
     /* Update the current connection ssl_config. */
-    if(data->easy_conn) {
-      data->easy_conn->ssl_config.verifyhost =
+    if(data->conn) {
+      data->conn->ssl_config.verifyhost =
         data->set.ssl.primary.verifyhost;
     }
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_SSL_VERIFYHOST:
     /*
      * Enable verification of the host name in the peer certificate for proxy
@@ -1748,11 +1812,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
 
     /* Update the current connection proxy_ssl_config. */
-    if(data->easy_conn) {
-      data->easy_conn->proxy_ssl_config.verifyhost =
+    if(data->conn) {
+      data->conn->proxy_ssl_config.verifyhost =
         data->set.proxy_ssl.primary.verifyhost;
     }
     break;
+#endif
   case CURLOPT_SSL_VERIFYSTATUS:
     /*
      * Enable certificate status verifying.
@@ -1766,8 +1831,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
       TRUE : FALSE;
 
     /* Update the current connection ssl_config. */
-    if(data->easy_conn) {
-      data->easy_conn->ssl_config.verifystatus =
+    if(data->conn) {
+      data->conn->ssl_config.verifystatus =
         data->set.ssl.primary.verifystatus;
     }
     break;
@@ -1825,6 +1890,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
 #endif
       result = CURLE_NOT_BUILT_IN;
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_PINNEDPUBLICKEY:
     /*
      * Set pinned public key for SSL connection.
@@ -1838,6 +1904,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
 #endif
       result = CURLE_NOT_BUILT_IN;
     break;
+#endif
   case CURLOPT_CAINFO:
     /*
      * Set CA info for SSL connection. Specify file name of the CA certificate
@@ -1845,6 +1912,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
                             va_arg(param, char *));
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_CAINFO:
     /*
      * Set CA info SSL connection for proxy. Specify file name of the
@@ -1853,6 +1921,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
                             va_arg(param, char *));
     break;
+#endif
   case CURLOPT_CAPATH:
     /*
      * Set CA path info for SSL connection. Specify directory name of the CA
@@ -1867,6 +1936,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
 #endif
       result = CURLE_NOT_BUILT_IN;
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_CAPATH:
     /*
      * Set CA path info for SSL connection proxy. Specify directory name of the
@@ -1881,6 +1951,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
 #endif
       result = CURLE_NOT_BUILT_IN;
     break;
+#endif
   case CURLOPT_CRLFILE:
     /*
      * Set CRL file info for SSL connection. Specify file name of the CRL
@@ -1889,6 +1960,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
                             va_arg(param, char *));
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_CRLFILE:
     /*
      * Set CRL file info for SSL connection for proxy. Specify file name of the
@@ -1897,6 +1969,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
                             va_arg(param, char *));
     break;
+#endif
   case CURLOPT_ISSUERCERT:
     /*
      * Set Issuer certificate file
@@ -1905,13 +1978,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
                             va_arg(param, char *));
     break;
+#ifndef CURL_DISABLE_TELNET
   case CURLOPT_TELNETOPTIONS:
     /*
      * Set a linked list of telnet options
      */
     data->set.telnet_options = va_arg(param, struct curl_slist *);
     break;
-
+#endif
   case CURLOPT_BUFFERSIZE:
     /*
      * The application kindly asks for a differently sized receive buffer.
@@ -2064,27 +2138,21 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
 
   case CURLOPT_SSL_OPTIONS:
     arg = va_arg(param, long);
-    data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+    data->set.ssl.enable_beast =
+      (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE);
     data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
     break;
 
+#ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_SSL_OPTIONS:
     arg = va_arg(param, long);
-    data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+    data->set.proxy_ssl.enable_beast =
+      (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE);
     data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
     break;
-
 #endif
-  case CURLOPT_FTPSSLAUTH:
-    /*
-     * Set a specific auth for FTP-SSL transfers.
-     */
-    arg = va_arg(param, long);
-    if((arg < CURLFTPAUTH_DEFAULT) || (arg > CURLFTPAUTH_TLS))
-      return CURLE_BAD_FUNCTION_ARGUMENT;
-    data->set.ftpsslauth = (curl_ftpauth)arg;
-    break;
 
+#endif
   case CURLOPT_IPRESOLVE:
     arg = va_arg(param, long);
     if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
@@ -2110,11 +2178,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
 
-  case CURLOPT_FTP_ACCOUNT:
-    result = Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT],
-                            va_arg(param, char *));
-    break;
-
   case CURLOPT_IGNORE_CONTENT_LENGTH:
     data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
@@ -2126,11 +2189,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
 
-  case CURLOPT_FTP_ALTERNATIVE_TO_USER:
-    result = Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
-                            va_arg(param, char *));
-    break;
-
   case CURLOPT_SOCKOPTFUNCTION:
     /*
      * socket callback function: called after socket() but before connect()
@@ -2196,7 +2254,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
     break;
 
-#if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
+#ifdef USE_SSH
     /* we only include SSH options if explicitly built to support SSH */
   case CURLOPT_SSH_AUTH_TYPES:
     data->set.ssh_auth_types = va_arg(param, long);
@@ -2225,7 +2283,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
                             va_arg(param, char *));
     break;
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+
   case CURLOPT_SSH_KNOWNHOSTS:
     /*
      * Store the file name to read known hosts from.
@@ -2246,8 +2304,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
      */
     data->set.ssh_keyfunc_userp = va_arg(param, void *);
     break;
-#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
-#endif /* USE_LIBSSH2 */
+
+  case CURLOPT_SSH_COMPRESSION:
+    data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
+    break;
+#endif /* USE_SSH */
 
   case CURLOPT_HTTP_TRANSFER_DECODING:
     /*
@@ -2263,6 +2324,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
     break;
 
+#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
   case CURLOPT_NEW_FILE_PERMS:
     /*
      * Uses these permissions instead of 0644
@@ -2282,17 +2344,20 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
       return CURLE_BAD_FUNCTION_ARGUMENT;
     data->set.new_directory_perms = arg;
     break;
+#endif
 
   case CURLOPT_ADDRESS_SCOPE:
     /*
-     * We always get longs when passed plain numericals, but for this value we
-     * know that an unsigned int will always hold the value so we blindly
-     * typecast to this type
+     * Use this scope id when using IPv6
+     * We always get longs when passed plain numericals so we should check
+     * that the value fits into an unsigned 32 bit integer.
      */
-    arg = va_arg(param, long);
-    if((arg < 0) || (arg > 0xf))
+    uarg = va_arg(param, unsigned long);
+#if SIZEOF_LONG > 4
+    if(uarg > UINT_MAX)
       return CURLE_BAD_FUNCTION_ARGUMENT;
-    data->set.scope_id = curlx_sltoui(arg);
+#endif
+    data->set.scope_id = (unsigned int)uarg;
     break;
 
   case CURLOPT_PROTOCOLS:
@@ -2316,7 +2381,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
                             va_arg(param, char *));
     break;
-
+#ifndef CURL_DISABLE_SMTP
   case CURLOPT_MAIL_FROM:
     /* Set the SMTP mail originator */
     result = Curl_setstropt(&data->set.str[STRING_MAIL_FROM],
@@ -2333,12 +2398,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     /* Set the list of mail recipients */
     data->set.mail_rcpt = va_arg(param, struct curl_slist *);
     break;
+#endif
 
   case CURLOPT_SASL_IR:
     /* Enable/disable SASL initial response */
     data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
-
+#ifndef CURL_DISABLE_RTSP
   case CURLOPT_RTSP_REQUEST:
   {
     /*
@@ -2447,7 +2513,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     /* Set the user defined RTP write function */
     data->set.fwrite_rtp = va_arg(param, curl_write_callback);
     break;
-
+#endif
+#ifndef CURL_DISABLE_FTP
   case CURLOPT_WILDCARDMATCH:
     data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
@@ -2466,6 +2533,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
   case CURLOPT_FNMATCH_DATA:
     data->set.fnmatch_data = va_arg(param, void *);
     break;
+#endif
 #ifdef USE_TLS_SRP
   case CURLOPT_TLSAUTH_USERNAME:
     result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
@@ -2510,6 +2578,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
       data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
     break;
 #endif
+#ifdef USE_ARES
   case CURLOPT_DNS_SERVERS:
     result = Curl_set_dns_servers(data, va_arg(param, char *));
     break;
@@ -2522,7 +2591,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
   case CURLOPT_DNS_LOCAL_IP6:
     result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
     break;
-
+#endif
   case CURLOPT_TCP_KEEPALIVE:
     data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
@@ -2546,13 +2615,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
     result = CURLE_NOT_BUILT_IN;
 #endif
     break;
+#ifdef USE_NGHTTP2
   case CURLOPT_SSL_ENABLE_NPN:
     data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
   case CURLOPT_SSL_ENABLE_ALPN:
     data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
-
+#endif
 #ifdef USE_UNIX_SOCKETS
   case CURLOPT_UNIX_SOCKET_PATH:
     data->set.abstract_unix_socket = FALSE;
@@ -2603,33 +2673,75 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
   case CURLOPT_SUPPRESS_CONNECT_HEADERS:
     data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
     break;
-  case CURLOPT_SSH_COMPRESSION:
-    data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
-    break;
   case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
     arg = va_arg(param, long);
     if(arg < 0)
       return CURLE_BAD_FUNCTION_ARGUMENT;
     data->set.happy_eyeballs_timeout = arg;
     break;
+#ifndef CURL_DISABLE_SHUFFLE_DNS
   case CURLOPT_DNS_SHUFFLE_ADDRESSES:
     data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
     break;
+#endif
   case CURLOPT_DISALLOW_USERNAME_IN_URL:
     data->set.disallow_username_in_url =
       (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
+#ifndef CURL_DISABLE_DOH
   case CURLOPT_DOH_URL:
     result = Curl_setstropt(&data->set.str[STRING_DOH],
                             va_arg(param, char *));
     data->set.doh = data->set.str[STRING_DOH]?TRUE:FALSE;
     break;
+#endif
   case CURLOPT_UPKEEP_INTERVAL_MS:
     arg = va_arg(param, long);
     if(arg < 0)
       return CURLE_BAD_FUNCTION_ARGUMENT;
     data->set.upkeep_interval_ms = arg;
     break;
+  case CURLOPT_MAXAGE_CONN:
+    arg = va_arg(param, long);
+    if(arg < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.maxage_conn = arg;
+    break;
+  case CURLOPT_TRAILERFUNCTION:
+#ifndef CURL_DISABLE_HTTP
+    data->set.trailer_callback = va_arg(param, curl_trailer_callback);
+#endif
+    break;
+  case CURLOPT_TRAILERDATA:
+#ifndef CURL_DISABLE_HTTP
+    data->set.trailer_data = va_arg(param, void *);
+#endif
+    break;
+#ifdef USE_ALTSVC
+  case CURLOPT_ALTSVC:
+    if(!data->asi) {
+      data->asi = Curl_altsvc_init();
+      if(!data->asi)
+        return CURLE_OUT_OF_MEMORY;
+    }
+    argptr = va_arg(param, char *);
+    result = Curl_setstropt(&data->set.str[STRING_ALTSVC], argptr);
+    if(result)
+      return result;
+    (void)Curl_altsvc_load(data->asi, argptr);
+    break;
+  case CURLOPT_ALTSVC_CTRL:
+    if(!data->asi) {
+      data->asi = Curl_altsvc_init();
+      if(!data->asi)
+        return CURLE_OUT_OF_MEMORY;
+    }
+    arg = va_arg(param, long);
+    result = Curl_altsvc_ctrl(data->asi, arg);
+    if(result)
+      return result;
+    break;
+#endif
   default:
     /* unknown tag and its companion, just ignore: */
     result = CURLE_UNKNOWN_OPTION;
@@ -2658,7 +2770,7 @@ CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
 
   va_start(arg, tag);
 
-  result = Curl_vsetopt(data, tag, arg);
+  result = vsetopt(data, tag, arg);
 
   va_end(arg);
   return result;
diff --git a/lib/sigpipe.h b/lib/sigpipe.h
index 800f9d3..3960a13 100644
--- a/lib/sigpipe.h
+++ b/lib/sigpipe.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,7 +23,8 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
-#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && defined(USE_OPENSSL)
+#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) &&        \
+  (defined(USE_OPENSSL) || defined(USE_MBEDTLS))
 #include <signal.h>
 
 struct sigpipe_ignore {
diff --git a/lib/smb.c b/lib/smb.c
index e4f266e..76c99a2 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -947,15 +947,10 @@ static int smb_getsock(struct connectdata *conn, curl_socket_t *socks,
 static CURLcode smb_do(struct connectdata *conn, bool *done)
 {
   struct smb_conn *smbc = &conn->proto.smbc;
-  struct smb_request *req = conn->data->req.protop;
 
   *done = FALSE;
   if(smbc->share) {
-    req->path = strchr(smbc->share, '\0');
-    if(req->path) {
-      req->path++;
-      return CURLE_OK;
-    }
+    return CURLE_OK;
   }
   return CURLE_URL_MALFORMAT;
 }
@@ -964,6 +959,7 @@ static CURLcode smb_parse_url_path(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
+  struct smb_request *req = data->req.protop;
   struct smb_conn *smbc = &conn->proto.smbc;
   char *path;
   char *slash;
@@ -992,6 +988,7 @@ static CURLcode smb_parse_url_path(struct connectdata *conn)
   /* Parse the path for the file path converting any forward slashes into
      backslashes */
   *slash++ = 0;
+  req->path = slash;
 
   for(; *slash; slash++) {
     if(*slash == '/')
diff --git a/lib/smtp.c b/lib/smtp.c
index 5875623..4a3462b 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
  * RFC4954 SMTP Authentication
  * RFC5321 SMTP protocol
  * RFC6749 OAuth 2.0 Authorization Framework
+ * RFC8314 Use of TLS for Email Submission and Access
  * Draft   SMTP URL Interface   <draft-earhart-url-smtp-00.txt>
  * Draft   LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
  *
@@ -207,8 +208,12 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
      Section 4. Examples of RFC-4954 but some e-mail servers ignore this and
      only send the response code instead as per Section 4.2. */
   if(line[3] == ' ' || len == 5) {
+    char tmpline[6];
+
     result = TRUE;
-    *resp = curlx_sltosi(strtol(line, NULL, 10));
+    memset(tmpline, '\0', sizeof(tmpline));
+    memcpy(tmpline, line, (len == 5 ? 5 : 3));
+    *resp = curlx_sltosi(strtol(tmpline, NULL, 10));
 
     /* Make sure real server never sends internal value */
     if(*resp == 1)
@@ -955,7 +960,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
 
     /* SMTP upload */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
 
     /* End of DO phase */
     state(conn, SMTP_STOP);
@@ -1080,19 +1085,20 @@ static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done)
       return result;
   }
 
-  result = Curl_pp_statemach(&smtpc->pp, FALSE);
+  result = Curl_pp_statemach(&smtpc->pp, FALSE, FALSE);
   *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE;
 
   return result;
 }
 
-static CURLcode smtp_block_statemach(struct connectdata *conn)
+static CURLcode smtp_block_statemach(struct connectdata *conn,
+                                     bool disconnecting)
 {
   CURLcode result = CURLE_OK;
   struct smtp_conn *smtpc = &conn->proto.smtpc;
 
   while(smtpc->state != SMTP_STOP && !result)
-    result = Curl_pp_statemach(&smtpc->pp, TRUE);
+    result = Curl_pp_statemach(&smtpc->pp, TRUE, disconnecting);
 
   return result;
 }
@@ -1213,7 +1219,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
        returned CURLE_AGAIN, we duplicate the EOB now rather than when the
        bytes written doesn't equal len. */
     if(smtp->trailing_crlf || !conn->data->state.infilesize) {
-      eob = strdup(SMTP_EOB + 2);
+      eob = strdup(&SMTP_EOB[2]);
       len = SMTP_EOB_LEN - 2;
     }
     else {
@@ -1247,13 +1253,8 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
 
     state(conn, SMTP_POSTDATA);
 
-    /* Run the state-machine
-
-       TODO: when the multi interface is used, this _really_ should be using
-       the smtp_multi_statemach function but we have no general support for
-       non-blocking DONE operations!
-    */
-    result = smtp_block_statemach(conn);
+    /* Run the state-machine */
+    result = smtp_block_statemach(conn, FALSE);
   }
 
   /* Clear the transfer mode for the next request */
@@ -1360,7 +1361,7 @@ static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
      point! */
   if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart)
     if(!smtp_perform_quit(conn))
-      (void)smtp_block_statemach(conn); /* ignore errors on QUIT */
+      (void)smtp_block_statemach(conn, TRUE); /* ignore errors on QUIT */
 
   /* Disconnect from the server */
   Curl_pp_disconnect(&smtpc->pp);
@@ -1383,7 +1384,7 @@ static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected)
 
   if(smtp->transfer != FTPTRANSFER_BODY)
     /* no data to transfer */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
 
   return CURLE_OK;
 }
diff --git a/lib/socks.c b/lib/socks.c
index d2209ad..d8fcc3b 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -54,7 +54,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
                        ssize_t buffersize,       /* max amount to read */
                        ssize_t *n)               /* amount bytes read */
 {
-  ssize_t nread;
+  ssize_t nread = 0;
   ssize_t allread = 0;
   int result;
   *n = 0;
@@ -155,7 +155,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
     Curl_addrinfo *hp = NULL;
     int rc;
 
-    rc = Curl_resolv(conn, hostname, remote_port, &dns);
+    rc = Curl_resolv(conn, hostname, remote_port, FALSE, &dns);
 
     if(rc == CURLRESOLV_ERROR)
       return CURLE_COULDNT_RESOLVE_PROXY;
@@ -290,7 +290,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
     /* wrong version ? */
     if(socksreq[0] != 0) {
       failf(data,
-            "SOCKS4 reply has wrong version, version should be 4.");
+            "SOCKS4 reply has wrong version, version should be 0.");
       return CURLE_COULDNT_CONNECT;
     }
 
@@ -527,12 +527,24 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
     len = 0;
     socksreq[len++] = 1;    /* username/pw subnegotiation version */
     socksreq[len++] = (unsigned char) proxy_user_len;
-    if(proxy_user && proxy_user_len)
+    if(proxy_user && proxy_user_len) {
+      /* the length must fit in a single byte */
+      if(proxy_user_len >= 255) {
+        failf(data, "Excessive user name length for proxy auth");
+        return CURLE_BAD_FUNCTION_ARGUMENT;
+      }
       memcpy(socksreq + len, proxy_user, proxy_user_len);
+    }
     len += proxy_user_len;
     socksreq[len++] = (unsigned char) proxy_password_len;
-    if(proxy_password && proxy_password_len)
+    if(proxy_password && proxy_password_len) {
+      /* the length must fit in a single byte */
+      if(proxy_password_len > 255) {
+        failf(data, "Excessive password length for proxy auth");
+        return CURLE_BAD_FUNCTION_ARGUMENT;
+      }
       memcpy(socksreq + len, proxy_password, proxy_password_len);
+    }
     len += proxy_password_len;
 
     code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written);
@@ -597,7 +609,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
   else {
     struct Curl_dns_entry *dns;
     Curl_addrinfo *hp = NULL;
-    int rc = Curl_resolv(conn, hostname, remote_port, &dns);
+    int rc = Curl_resolv(conn, hostname, remote_port, FALSE, &dns);
 
     if(rc == CURLRESOLV_ERROR)
       return CURLE_COULDNT_RESOLVE_HOST;
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c
index 96948ac..65294bb 100644
--- a/lib/socks_gssapi.c
+++ b/lib/socks_gssapi.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2009, Markus Moeller, <markus_moeller at compuserve.com>
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -151,8 +151,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
       return CURLE_OUT_OF_MEMORY;
     service.length = serviceptr_length +
       strlen(conn->socks_proxy.host.name) + 1;
-    snprintf(service.value, service.length + 1, "%s@%s",
-             serviceptr, conn->socks_proxy.host.name);
+    msnprintf(service.value, service.length + 1, "%s@%s",
+              serviceptr, conn->socks_proxy.host.name);
 
     gss_major_status = gss_import_name(&gss_minor_status, &service,
                                        GSS_C_NT_HOSTBASED_SERVICE, &server);
diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c
index 34699d3..57027ef 100644
--- a/lib/socks_sspi.c
+++ b/lib/socks_sspi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller at compuserve.com>
  *
  * This software is licensed as described in the file COPYING, which
@@ -51,8 +51,9 @@ static int check_sspi_err(struct connectdata *conn,
      status != SEC_I_COMPLETE_AND_CONTINUE &&
      status != SEC_I_COMPLETE_NEEDED &&
      status != SEC_I_CONTINUE_NEEDED) {
+    char buffer[STRERROR_LEN];
     failf(conn->data, "SSPI error: %s failed: %s", function,
-          Curl_sspi_strerror(conn, status));
+          Curl_sspi_strerror(status, buffer, sizeof(buffer)));
     return 1;
   }
   return 0;
@@ -107,9 +108,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
                           strlen(conn->socks_proxy.host.name) + 2);
     if(!service_name)
       return CURLE_OUT_OF_MEMORY;
-    snprintf(service_name, service_length +
-             strlen(conn->socks_proxy.host.name) + 2, "%s/%s",
-             service, conn->socks_proxy.host.name);
+    msnprintf(service_name, service_length +
+              strlen(conn->socks_proxy.host.name) + 2, "%s/%s",
+              service, conn->socks_proxy.host.name);
   }
 
   input_desc.cBuffers = 1;
diff --git a/lib/splay.c b/lib/splay.c
index baf07e0..0f5fcd1 100644
--- a/lib/splay.c
+++ b/lib/splay.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1997 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1997 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -198,7 +198,7 @@ struct Curl_tree *Curl_splaygetbest(struct curltime i,
 /* Deletes the very node we point out from the tree if it's there. Stores a
  * pointer to the new resulting tree in 'newroot'.
  *
- * Returns zero on success and non-zero on errors! TODO: document error codes.
+ * Returns zero on success and non-zero on errors!
  * When returning error, it does not touch the 'newroot' pointer.
  *
  * NOTE: when the last node of the tree is removed, there's no tree left so
diff --git a/lib/ssh-libssh.c b/lib/ssh-libssh.c
index 7d59089..6cfd6bd 100644
--- a/lib/ssh-libssh.c
+++ b/lib/ssh-libssh.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2017 - 2018 Red Hat, Inc.
+ * Copyright (C) 2017 - 2019 Red Hat, Inc.
  *
  * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
  *          Robert Kolcun, Andreas Schneider
@@ -95,6 +95,13 @@
 #include "memdebug.h"
 #include "curl_path.h"
 
+/* A recent macro provided by libssh. Or make our own. */
+#ifndef SSH_STRING_FREE_CHAR
+/* !checksrc! disable ASSIGNWITHINCONDITION 1 */
+#define SSH_STRING_FREE_CHAR(x) \
+    do { if((x) != NULL) { ssh_string_free_char(x); x = NULL; } } while(0)
+#endif
+
 /* Local functions: */
 static CURLcode myssh_connect(struct connectdata *conn, bool *done);
 static CURLcode myssh_multi_statemach(struct connectdata *conn,
@@ -549,6 +556,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
   struct Curl_easy *data = conn->data;
   struct SSHPROTO *protop = data->req.protop;
   struct ssh_conn *sshc = &conn->proto.sshc;
+  curl_socket_t sock = conn->sock[FIRSTSOCKET];
   int rc = SSH_NO_ERROR, err;
   char *new_readdir_line;
   int seekerr = CURL_SEEKFUNC_OK;
@@ -792,7 +800,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
 
       Curl_pgrsTime(conn->data, TIMER_APPCONNECT);      /* SSH is connected */
 
-      conn->sockfd = ssh_get_fd(sshc->ssh_session);
+      conn->sockfd = sock;
       conn->writesockfd = CURL_SOCKET_BAD;
 
       if(conn->handler->protocol == CURLPROTO_SFTP) {
@@ -1192,7 +1200,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
         Curl_pgrsSetUploadSize(data, data->state.infilesize);
       }
       /* upload data */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
 
       /* not set by Curl_setup_transfer to preserve keepon bits */
       conn->sockfd = conn->writesockfd;
@@ -1342,8 +1350,8 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
               break;
             }
 
-            snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
-                     sshc->readdir_filename);
+            msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
+                      sshc->readdir_filename);
 
             state(conn, SSH_SFTP_READDIR_LINK);
             break;
@@ -1406,12 +1414,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
       }
       sshc->readdir_line = new_readdir_line;
 
-      sshc->readdir_currLen += snprintf(sshc->readdir_line +
-                                        sshc->readdir_currLen,
-                                        sshc->readdir_totalLen -
-                                        sshc->readdir_currLen,
-                                        " -> %s",
-                                        sshc->readdir_filename);
+      sshc->readdir_currLen += msnprintf(sshc->readdir_line +
+                                         sshc->readdir_currLen,
+                                         sshc->readdir_totalLen -
+                                         sshc->readdir_currLen,
+                                         " -> %s",
+                                         sshc->readdir_filename);
 
       sftp_attributes_free(sshc->readdir_link_attrs);
       sshc->readdir_link_attrs = NULL;
@@ -1421,10 +1429,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
       state(conn, SSH_SFTP_READDIR_BOTTOM);
       /* FALLTHROUGH */
     case SSH_SFTP_READDIR_BOTTOM:
-      sshc->readdir_currLen += snprintf(sshc->readdir_line +
-                                        sshc->readdir_currLen,
-                                        sshc->readdir_totalLen -
-                                        sshc->readdir_currLen, "\n");
+      sshc->readdir_currLen += msnprintf(sshc->readdir_line +
+                                         sshc->readdir_currLen,
+                                         sshc->readdir_totalLen -
+                                         sshc->readdir_currLen, "\n");
       result = Curl_client_write(conn, CLIENTWRITE_BODY,
                                  sshc->readdir_line,
                                  sshc->readdir_currLen);
@@ -1454,7 +1462,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
       sshc->sftp_dir = NULL;
 
       /* no data to transfer */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
       state(conn, SSH_STOP);
       break;
 
@@ -1595,13 +1603,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
     /* Setup the actual download */
     if(data->req.size == 0) {
       /* no data to transfer */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
       infof(data, "File already completely downloaded\n");
       state(conn, SSH_STOP);
       break;
     }
-    Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
-                        FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
 
     /* not set by Curl_setup_transfer to preserve keepon bits */
     conn->writesockfd = conn->sockfd;
@@ -1661,7 +1668,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
         sshc->sftp_session = NULL;
       }
 
-      Curl_safefree(sshc->homedir);
+      SSH_STRING_FREE_CHAR(sshc->homedir);
       conn->data->state.most_recent_ftp_entrypath = NULL;
 
       state(conn, SSH_SESSION_DISCONNECT);
@@ -1723,8 +1730,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
       }
 
       /* upload data */
-      Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
-                          FIRSTSOCKET, NULL);
+      Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET);
 
       /* not set by Curl_setup_transfer to preserve keepon bits */
       conn->sockfd = conn->writesockfd;
@@ -1767,8 +1773,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
         /* download data */
         bytecount = ssh_scp_request_get_size(sshc->scp_session);
         data->req.maxdownload = (curl_off_t) bytecount;
-        Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1,
-                            NULL);
+        Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);
 
         /* not set by Curl_setup_transfer to preserve keepon bits */
         conn->writesockfd = conn->sockfd;
@@ -1829,7 +1834,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
 
       ssh_disconnect(sshc->ssh_session);
 
-      Curl_safefree(sshc->homedir);
+      SSH_STRING_FREE_CHAR(sshc->homedir);
       conn->data->state.most_recent_ftp_entrypath = NULL;
 
       state(conn, SSH_SESSION_FREE);
@@ -1866,14 +1871,11 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
 
       Curl_safefree(sshc->rsa_pub);
       Curl_safefree(sshc->rsa);
-
       Curl_safefree(sshc->quote_path1);
       Curl_safefree(sshc->quote_path2);
-
-      Curl_safefree(sshc->homedir);
-
       Curl_safefree(sshc->readdir_line);
       Curl_safefree(sshc->readdir_linkPath);
+      SSH_STRING_FREE_CHAR(sshc->homedir);
 
       /* the code we are about to return */
       result = sshc->actualcode;
@@ -1944,14 +1946,13 @@ static int myssh_getsock(struct connectdata *conn,
 static void myssh_block2waitfor(struct connectdata *conn, bool block)
 {
   struct ssh_conn *sshc = &conn->proto.sshc;
-  int dir;
 
   /* If it didn't block, or nothing was returned by ssh_get_poll_flags
    * have the original set */
   conn->waitfor = sshc->orig_waitfor;
 
   if(block) {
-    dir = ssh_get_poll_flags(sshc->ssh_session);
+    int dir = ssh_get_poll_flags(sshc->ssh_session);
     if(dir & SSH_READ_PENDING) {
       /* translate the libssh define bits into our own bit defines */
       conn->waitfor = KEEP_RECV;
@@ -2010,9 +2011,7 @@ static CURLcode myssh_block_statemach(struct connectdata *conn,
     }
 
     if(!result && block) {
-      curl_socket_t sock = conn->sock[FIRSTSOCKET];
-      curl_socket_t fd_read = CURL_SOCKET_BAD;
-      fd_read = sock;
+      curl_socket_t fd_read = conn->sock[FIRSTSOCKET];
       /* wait for the socket to become ready */
       (void) Curl_socket_check(fd_read, CURL_SOCKET_BAD,
                                CURL_SOCKET_BAD, left > 1000 ? 1000 : left);
@@ -2048,8 +2047,8 @@ static CURLcode myssh_connect(struct connectdata *conn, bool *done)
 {
   struct ssh_conn *ssh;
   CURLcode result;
+  curl_socket_t sock = conn->sock[FIRSTSOCKET];
   struct Curl_easy *data = conn->data;
-  int rc;
 
   /* initialize per-handle data if not already */
   if(!data->req.protop)
@@ -2076,6 +2075,8 @@ static CURLcode myssh_connect(struct connectdata *conn, bool *done)
     return CURLE_FAILED_INIT;
   }
 
+  ssh_options_set(ssh->ssh_session, SSH_OPTIONS_FD, &sock);
+
   if(conn->user) {
     infof(data, "User: %s\n", conn->user);
     ssh_options_set(ssh->ssh_session, SSH_OPTIONS_USER, conn->user);
@@ -2101,8 +2102,8 @@ static CURLcode myssh_connect(struct connectdata *conn, bool *done)
   ssh->pubkey = NULL;
 
   if(data->set.str[STRING_SSH_PUBLIC_KEY]) {
-    rc = ssh_pki_import_pubkey_file(data->set.str[STRING_SSH_PUBLIC_KEY],
-                                    &ssh->pubkey);
+    int rc = ssh_pki_import_pubkey_file(data->set.str[STRING_SSH_PUBLIC_KEY],
+                                        &ssh->pubkey);
     if(rc != SSH_OK) {
       failf(data, "Could not load public key file");
       /* ignore */
@@ -2222,12 +2223,7 @@ static CURLcode myssh_done(struct connectdata *conn, CURLcode status)
   struct SSHPROTO *protop = conn->data->req.protop;
 
   if(!status) {
-    /* run the state-machine
-
-       TODO: when the multi interface is used, this _really_ should be using
-       the ssh_multi_statemach function but we have no general support for
-       non-blocking DONE operations!
-     */
+    /* run the state-machine */
     result = myssh_block_statemach(conn, FALSE);
   }
   else
@@ -2390,13 +2386,9 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
     /* Post quote commands are executed after the SFTP_CLOSE state to avoid
        errors that could happen due to open file handles during POSTQUOTE
        operation */
-    if(!status && !premature && conn->data->set.postquote &&
-       !conn->bits.retry) {
+    if(!premature && conn->data->set.postquote && !conn->bits.retry)
       sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
-      state(conn, SSH_SFTP_CLOSE);
-    }
-    else
-      state(conn, SSH_SFTP_CLOSE);
+    state(conn, SSH_SFTP_CLOSE);
   }
   return myssh_done(conn, status);
 }
diff --git a/lib/ssh.c b/lib/ssh.c
index da89619..a265c3c 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -81,11 +81,11 @@
 #include "multiif.h"
 #include "select.h"
 #include "warnless.h"
+#include "curl_path.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
-#include "curl_path.h"
 #include "memdebug.h"
 
 #if LIBSSH2_VERSION_NUM >= 0x010206
@@ -290,10 +290,6 @@ static CURLcode libssh2_session_error_to_CURLE(int err)
       return CURLE_AGAIN;
   }
 
-  /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode
-     error code, and possibly add a few new SSH-related one. We must however
-     not return or even depend on libssh2 errors in the public libcurl API */
-
   return CURLE_SSH;
 }
 
@@ -591,15 +587,15 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
   struct Curl_easy *data = conn->data;
   const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
   char md5buffer[33];
-  int i;
 
   const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
       LIBSSH2_HOSTKEY_HASH_MD5);
 
   if(fingerprint) {
     /* The fingerprint points to static storage (!), don't free() it. */
+    int i;
     for(i = 0; i < 16; i++)
-      snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
+      msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
     infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
   }
 
@@ -667,7 +663,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         break;
       }
       if(rc) {
-        failf(data, "Failure establishing ssh session");
+        char *err_msg = NULL;
+        (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
+        failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);
+
         state(conn, SSH_SESSION_FREE);
         sshc->actualcode = CURLE_FAILED_INIT;
         break;
@@ -734,18 +733,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
 
       if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
          (strstr(sshc->authlist, "publickey") != NULL)) {
-        char *home = NULL;
         bool out_of_memory = FALSE;
 
         sshc->rsa_pub = sshc->rsa = NULL;
 
-        /* To ponder about: should really the lib be messing about with the
-           HOME environment variable etc? */
-        home = curl_getenv("HOME");
-
         if(data->set.str[STRING_SSH_PRIVATE_KEY])
           sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]);
         else {
+          /* To ponder about: should really the lib be messing about with the
+             HOME environment variable etc? */
+          char *home = curl_getenv("HOME");
+
           /* If no private key file is specified, try some common paths. */
           if(home) {
             /* Try ~/.ssh first. */
@@ -761,6 +759,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
                 Curl_safefree(sshc->rsa);
               }
             }
+            free(home);
           }
           if(!out_of_memory && !sshc->rsa) {
             /* Nothing found; try the current dir. */
@@ -792,7 +791,6 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         }
 
         if(out_of_memory || sshc->rsa == NULL) {
-          free(home);
           Curl_safefree(sshc->rsa);
           Curl_safefree(sshc->rsa_pub);
           state(conn, SSH_SESSION_FREE);
@@ -804,8 +802,6 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(!sshc->passphrase)
           sshc->passphrase = "";
 
-        free(home);
-
         if(sshc->rsa_pub)
           infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub);
         infof(data, "Using SSH private key file '%s'\n", sshc->rsa);
@@ -1805,7 +1801,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         Curl_pgrsSetUploadSize(data, data->state.infilesize);
       }
       /* upload data */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
 
       /* not set by Curl_setup_transfer to preserve keepon bits */
       conn->sockfd = conn->writesockfd;
@@ -1999,8 +1995,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
               break;
             }
 
-            snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
-                     sshc->readdir_filename);
+            msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
+                      sshc->readdir_filename);
             state(conn, SSH_SFTP_READDIR_LINK);
             break;
           }
@@ -2055,21 +2051,21 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       }
       sshc->readdir_line = new_readdir_line;
 
-      sshc->readdir_currLen += snprintf(sshc->readdir_line +
-                                        sshc->readdir_currLen,
-                                        sshc->readdir_totalLen -
-                                        sshc->readdir_currLen,
-                                        " -> %s",
-                                        sshc->readdir_filename);
+      sshc->readdir_currLen += msnprintf(sshc->readdir_line +
+                                         sshc->readdir_currLen,
+                                         sshc->readdir_totalLen -
+                                         sshc->readdir_currLen,
+                                         " -> %s",
+                                         sshc->readdir_filename);
 
       state(conn, SSH_SFTP_READDIR_BOTTOM);
       break;
 
     case SSH_SFTP_READDIR_BOTTOM:
-      sshc->readdir_currLen += snprintf(sshc->readdir_line +
-                                        sshc->readdir_currLen,
-                                        sshc->readdir_totalLen -
-                                        sshc->readdir_currLen, "\n");
+      sshc->readdir_currLen += msnprintf(sshc->readdir_line +
+                                         sshc->readdir_currLen,
+                                         sshc->readdir_totalLen -
+                                         sshc->readdir_currLen, "\n");
       result = Curl_client_write(conn, CLIENTWRITE_BODY,
                                  sshc->readdir_line,
                                  sshc->readdir_currLen);
@@ -2102,7 +2098,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       Curl_safefree(sshc->readdir_longentry);
 
       /* no data to transfer */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
       state(conn, SSH_STOP);
       break;
 
@@ -2242,13 +2238,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
     /* Setup the actual download */
     if(data->req.size == 0) {
       /* no data to transfer */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
       infof(data, "File already completely downloaded\n");
       state(conn, SSH_STOP);
       break;
     }
-    Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
-                        FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
 
     /* not set by Curl_setup_transfer to preserve keepon bits */
     conn->writesockfd = conn->sockfd;
@@ -2392,8 +2387,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       }
 
       /* upload data */
-      Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
-                          FIRSTSOCKET, NULL);
+      Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET);
 
       /* not set by Curl_setup_transfer to preserve keepon bits */
       conn->sockfd = conn->writesockfd;
@@ -2464,7 +2458,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       /* download data */
       bytecount = (curl_off_t)sb.st_size;
       data->req.maxdownload =  (curl_off_t)sb.st_size;
-      Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);
 
       /* not set by Curl_setup_transfer to preserve keepon bits */
       conn->writesockfd = conn->sockfd;
@@ -2788,9 +2782,12 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
   CURLcode result = CURLE_OK;
   bool block; /* we store the status and use that to provide a ssh_getsock()
                  implementation */
-
-  result = ssh_statemach_act(conn, &block);
-  *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
+  do {
+    result = ssh_statemach_act(conn, &block);
+    *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
+    /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
+       try again */
+  } while(!result && !*done && !block);
   ssh_block2waitfor(conn, block);
 
   return result;
@@ -3061,12 +3058,7 @@ static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
   struct SSHPROTO *sftp_scp = conn->data->req.protop;
 
   if(!status) {
-    /* run the state-machine
-
-       TODO: when the multi interface is used, this _really_ should be using
-       the ssh_multi_statemach function but we have no general support for
-       non-blocking DONE operations!
-    */
+    /* run the state-machine */
     result = ssh_block_statemach(conn, FALSE);
   }
   else
@@ -3219,13 +3211,9 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
     /* Post quote commands are executed after the SFTP_CLOSE state to avoid
        errors that could happen due to open file handles during POSTQUOTE
        operation */
-    if(!status && !premature && conn->data->set.postquote &&
-       !conn->bits.retry) {
+    if(!premature && conn->data->set.postquote && !conn->bits.retry)
       sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
-      state(conn, SSH_SFTP_CLOSE);
-    }
-    else
-      state(conn, SSH_SFTP_CLOSE);
+    state(conn, SSH_SFTP_CLOSE);
   }
   return ssh_done(conn, status);
 }
diff --git a/lib/strerror.c b/lib/strerror.c
index 47ef44a..e273f37 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2004 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2004 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -646,20 +646,18 @@ get_winsock_error (int err, char *buf, size_t len)
  * We don't do range checking (on systems other than Windows) since there is
  * no good reliable and portable way to do it.
  */
-const char *Curl_strerror(struct connectdata *conn, int err)
+const char *Curl_strerror(int err, char *buf, size_t buflen)
 {
 #ifdef PRESERVE_WINDOWS_ERROR_CODE
   DWORD old_win_err = GetLastError();
 #endif
   int old_errno = errno;
-  char *buf, *p;
+  char *p;
   size_t max;
 
-  DEBUGASSERT(conn);
   DEBUGASSERT(err >= 0);
 
-  buf = conn->syserr_buf;
-  max = sizeof(conn->syserr_buf)-1;
+  max = buflen - 1;
   *buf = '\0';
 
 #ifdef USE_WINSOCK
@@ -681,7 +679,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
     if(!get_winsock_error(err, buf, max) &&
        !FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
                        LANG_NEUTRAL, buf, (DWORD)max, NULL))
-      snprintf(buf, max, "Unknown error %d (%#x)", err, err);
+      msnprintf(buf, max, "Unknown error %d (%#x)", err, err);
   }
 #endif
 
@@ -695,7 +693,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
   */
   if(0 != strerror_r(err, buf, max)) {
     if('\0' == buf[0])
-      snprintf(buf, max, "Unknown error %d", err);
+      msnprintf(buf, max, "Unknown error %d", err);
   }
 #elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
  /*
@@ -709,7 +707,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
     if(msg)
       strncpy(buf, msg, max);
     else
-      snprintf(buf, max, "Unknown error %d", err);
+      msnprintf(buf, max, "Unknown error %d", err);
   }
 #elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)
  /*
@@ -721,7 +719,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
     if(OK == strerror_r(err, buffer))
       strncpy(buf, buffer, max);
     else
-      snprintf(buf, max, "Unknown error %d", err);
+      msnprintf(buf, max, "Unknown error %d", err);
   }
 #else
   {
@@ -729,7 +727,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
     if(msg)
       strncpy(buf, msg, max);
     else
-      snprintf(buf, max, "Unknown error %d", err);
+      msnprintf(buf, max, "Unknown error %d", err);
   }
 #endif
 
@@ -757,7 +755,7 @@ const char *Curl_strerror(struct connectdata *conn, int err)
 }
 
 #ifdef USE_WINDOWS_SSPI
-const char *Curl_sspi_strerror (struct connectdata *conn, int err)
+const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
 {
 #ifdef PRESERVE_WINDOWS_ERROR_CODE
   DWORD old_win_err = GetLastError();
@@ -768,15 +766,13 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
   size_t outmax;
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   char txtbuf[80];
-  char msgbuf[sizeof(conn->syserr_buf)];
+  char msgbuf[256];
   char *p, *str, *msg = NULL;
   bool msg_formatted = FALSE;
 #endif
 
-  DEBUGASSERT(conn);
-
-  outbuf = conn->syserr_buf;
-  outmax = sizeof(conn->syserr_buf)-1;
+  outbuf = buf;
+  outmax = buflen - 1;
   *outbuf = '\0';
 
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
@@ -1032,14 +1028,14 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
   if(err == SEC_E_OK)
     strncpy(outbuf, txt, outmax);
   else if(err == SEC_E_ILLEGAL_MESSAGE)
-    snprintf(outbuf, outmax,
-             "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs "
-             "when a fatal SSL/TLS alert is received (e.g. handshake failed). "
-             "More detail may be available in the Windows System event log.",
-             err);
+    msnprintf(outbuf, outmax,
+              "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs "
+              "when a fatal SSL/TLS alert is received (e.g. handshake failed)."
+              " More detail may be available in the Windows System event log.",
+              err);
   else {
     str = txtbuf;
-    snprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err);
+    msnprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err);
     txtbuf[sizeof(txtbuf)-1] = '\0';
 
 #ifdef _WIN32_WCE
@@ -1075,7 +1071,7 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
       msg = msgbuf;
     }
     if(msg)
-      snprintf(outbuf, outmax, "%s - %s", str, msg);
+      msnprintf(outbuf, outmax, "%s - %s", str, msg);
     else
       strncpy(outbuf, str, outmax);
   }
diff --git a/lib/strerror.h b/lib/strerror.h
index 627273e..683b5b4 100644
--- a/lib/strerror.h
+++ b/lib/strerror.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -24,14 +24,11 @@
 
 #include "urldata.h"
 
-const char *Curl_strerror (struct connectdata *conn, int err);
-
-#ifdef USE_LIBIDN2
-const char *Curl_idn_strerror (struct connectdata *conn, int err);
-#endif
+#define STRERROR_LEN 128 /* a suitable length */
 
+const char *Curl_strerror(int err, char *buf, size_t buflen);
 #ifdef USE_WINDOWS_SSPI
-const char *Curl_sspi_strerror (struct connectdata *conn, int err);
+const char *Curl_sspi_strerror(int err, char *buf, size_t buflen);
 #endif
 
 #endif /* HEADER_CURL_STRERROR_H */
diff --git a/lib/system_win32.c b/lib/system_win32.c
index 6b8004e..f7f817d 100644
--- a/lib/system_win32.c
+++ b/lib/system_win32.c
@@ -26,12 +26,94 @@
 
 #include <curl/curl.h>
 #include "system_win32.h"
+#include "curl_sspi.h"
 #include "warnless.h"
 
 /* The last #include files should be: */
 #include "curl_memory.h"
 #include "memdebug.h"
 
+LARGE_INTEGER Curl_freq;
+bool Curl_isVistaOrGreater;
+
+/* Curl_win32_init() performs win32 global initialization */
+CURLcode Curl_win32_init(long flags)
+{
+  /* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which
+     is just for Winsock at the moment. Any required win32 initialization
+     should take place after this block. */
+  if(flags & CURL_GLOBAL_WIN32) {
+#ifdef USE_WINSOCK
+    WORD wVersionRequested;
+    WSADATA wsaData;
+    int res;
+
+#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
+#error IPV6_requires_winsock2
+#endif
+
+    wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
+
+    res = WSAStartup(wVersionRequested, &wsaData);
+
+    if(res != 0)
+      /* Tell the user that we couldn't find a usable */
+      /* winsock.dll.     */
+      return CURLE_FAILED_INIT;
+
+    /* Confirm that the Windows Sockets DLL supports what we need.*/
+    /* Note that if the DLL supports versions greater */
+    /* than wVersionRequested, it will still return */
+    /* wVersionRequested in wVersion. wHighVersion contains the */
+    /* highest supported version. */
+
+    if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
+       HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
+      /* Tell the user that we couldn't find a usable */
+
+      /* winsock.dll. */
+      WSACleanup();
+      return CURLE_FAILED_INIT;
+    }
+    /* The Windows Sockets DLL is acceptable. Proceed. */
+  #elif defined(USE_LWIPSOCK)
+    lwip_init();
+  #endif
+  } /* CURL_GLOBAL_WIN32 */
+
+#ifdef USE_WINDOWS_SSPI
+  {
+    CURLcode result = Curl_sspi_global_init();
+    if(result)
+      return result;
+  }
+#endif
+
+  if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
+                                 VERSION_GREATER_THAN_EQUAL)) {
+    Curl_isVistaOrGreater = TRUE;
+    QueryPerformanceFrequency(&Curl_freq);
+  }
+  else
+    Curl_isVistaOrGreater = FALSE;
+
+  return CURLE_OK;
+}
+
+/* Curl_win32_cleanup() is the opposite of Curl_win32_init() */
+void Curl_win32_cleanup(long init_flags)
+{
+#ifdef USE_WINDOWS_SSPI
+  Curl_sspi_global_cleanup();
+#endif
+
+  if(init_flags & CURL_GLOBAL_WIN32) {
+#ifdef USE_WINSOCK
+    WSACleanup();
+#endif
+  }
+}
+
 #if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \
                                   defined(USE_WINSOCK))
 
diff --git a/lib/system_win32.h b/lib/system_win32.h
index 1e77285..926328a 100644
--- a/lib/system_win32.h
+++ b/lib/system_win32.h
@@ -26,6 +26,12 @@
 
 #if defined(WIN32)
 
+extern LARGE_INTEGER Curl_freq;
+extern bool Curl_isVistaOrGreater;
+
+CURLcode Curl_win32_init(long flags);
+void Curl_win32_cleanup(long init_flags);
+
 /* Version condition */
 typedef enum {
   VERSION_LESS_THAN,
diff --git a/lib/telnet.c b/lib/telnet.c
index 05fe744..955255c 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -829,7 +829,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
   /* Add the user name as an environment variable if it
      was given on the command line */
   if(conn->bits.user_passwd) {
-    snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
+    msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
     beg = curl_slist_append(tn->telnet_vars, option_arg);
     if(!beg) {
       curl_slist_free_all(tn->telnet_vars);
@@ -935,9 +935,9 @@ static void suboption(struct connectdata *conn)
   switch(CURL_SB_GET(tn)) {
     case CURL_TELOPT_TTYPE:
       len = strlen(tn->subopt_ttype) + 4 + 2;
-      snprintf((char *)temp, sizeof(temp),
-               "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
-               CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE);
+      msnprintf((char *)temp, sizeof(temp),
+                "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
+                CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE);
       bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
       if(bytes_written < 0) {
         err = SOCKERRNO;
@@ -947,9 +947,9 @@ static void suboption(struct connectdata *conn)
       break;
     case CURL_TELOPT_XDISPLOC:
       len = strlen(tn->subopt_xdisploc) + 4 + 2;
-      snprintf((char *)temp, sizeof(temp),
-               "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC,
-               CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE);
+      msnprintf((char *)temp, sizeof(temp),
+                "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC,
+                CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE);
       bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
       if(bytes_written < 0) {
         err = SOCKERRNO;
@@ -958,9 +958,9 @@ static void suboption(struct connectdata *conn)
       printsub(data, '>', &temp[2], len-2);
       break;
     case CURL_TELOPT_NEW_ENVIRON:
-      snprintf((char *)temp, sizeof(temp),
-               "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON,
-               CURL_TELQUAL_IS);
+      msnprintf((char *)temp, sizeof(temp),
+                "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON,
+                CURL_TELQUAL_IS);
       len = 4;
 
       for(v = tn->telnet_vars; v; v = v->next) {
@@ -968,15 +968,15 @@ static void suboption(struct connectdata *conn)
         /* Add the variable only if it fits */
         if(len + tmplen < (int)sizeof(temp)-6) {
           if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
-            snprintf((char *)&temp[len], sizeof(temp) - len,
-                     "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
-                     CURL_NEW_ENV_VALUE, varval);
+            msnprintf((char *)&temp[len], sizeof(temp) - len,
+                      "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
+                      CURL_NEW_ENV_VALUE, varval);
             len += tmplen;
           }
         }
       }
-      snprintf((char *)&temp[len], sizeof(temp) - len,
-               "%c%c", CURL_IAC, CURL_SE);
+      msnprintf((char *)&temp[len], sizeof(temp) - len,
+                "%c%c", CURL_IAC, CURL_SE);
       len += 2;
       bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
       if(bytes_written < 0) {
@@ -1692,7 +1692,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
   }
 #endif
   /* mark this as "no further transfer wanted" */
-  Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+  Curl_setup_transfer(data, -1, -1, FALSE, -1);
 
   return result;
 }
diff --git a/lib/tftp.c b/lib/tftp.c
index 5b74e8e..289cda2 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -496,9 +496,9 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
       return CURLE_TFTP_ILLEGAL; /* too long file name field */
     }
 
-    snprintf((char *)state->spacket.data + 2,
-             state->blksize,
-             "%s%c%s%c", filename, '\0',  mode, '\0');
+    msnprintf((char *)state->spacket.data + 2,
+              state->blksize,
+              "%s%c%s%c", filename, '\0',  mode, '\0');
     sbytes = 4 + strlen(filename) + strlen(mode);
 
     /* optional addition of TFTP options */
@@ -506,8 +506,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
       char buf[64];
       /* add tsize option */
       if(data->set.upload && (data->state.infilesize != -1))
-        snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
-                 data->state.infilesize);
+        msnprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
+                  data->state.infilesize);
       else
         strcpy(buf, "0"); /* the destination is large enough */
 
@@ -517,7 +517,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
       sbytes += tftp_option_add(state, sbytes,
                                 (char *)state->spacket.data + sbytes, buf);
       /* add blksize option */
-      snprintf(buf, sizeof(buf), "%d", state->requested_blksize);
+      msnprintf(buf, sizeof(buf), "%d", state->requested_blksize);
       sbytes += tftp_option_add(state, sbytes,
                                 (char *)state->spacket.data + sbytes,
                                 TFTP_OPTION_BLKSIZE);
@@ -525,7 +525,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
                                 (char *)state->spacket.data + sbytes, buf);
 
       /* add timeout option */
-      snprintf(buf, sizeof(buf), "%d", state->retry_time);
+      msnprintf(buf, sizeof(buf), "%d", state->retry_time);
       sbytes += tftp_option_add(state, sbytes,
                                 (char *)state->spacket.data + sbytes,
                                 TFTP_OPTION_INTERVAL);
@@ -540,7 +540,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
                       state->conn->ip_addr->ai_addr,
                       state->conn->ip_addr->ai_addrlen);
     if(senddata != (ssize_t)sbytes) {
-      failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+      char buffer[STRERROR_LEN];
+      failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
     }
     free(filename);
     break;
@@ -590,6 +591,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
   ssize_t sbytes;
   int rblock;
   struct Curl_easy *data = state->conn->data;
+  char buffer[STRERROR_LEN];
 
   switch(event) {
 
@@ -622,7 +624,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
                     (struct sockaddr *)&state->remote_addr,
                     state->remote_addrlen);
     if(sbytes < 0) {
-      failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+      failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
       return CURLE_SEND_ERROR;
     }
 
@@ -647,7 +649,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
                     (struct sockaddr *)&state->remote_addr,
                     state->remote_addrlen);
     if(sbytes < 0) {
-      failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+      failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
       return CURLE_SEND_ERROR;
     }
 
@@ -673,7 +675,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
                       (struct sockaddr *)&state->remote_addr,
                       state->remote_addrlen);
       if(sbytes<0) {
-        failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+        failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
         return CURLE_SEND_ERROR;
       }
     }
@@ -713,6 +715,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
   CURLcode result = CURLE_OK;
   struct SingleRequest *k = &data->req;
   size_t cb; /* Bytes currently read */
+  char buffer[STRERROR_LEN];
 
   switch(event) {
 
@@ -747,7 +750,8 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
                           state->remote_addrlen);
           /* Check all sbytes were sent */
           if(sbytes<0) {
-            failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+            failf(data, "%s", Curl_strerror(SOCKERRNO,
+                                            buffer, sizeof(buffer)));
             result = CURLE_SEND_ERROR;
           }
         }
@@ -791,7 +795,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
                     state->remote_addrlen);
     /* Check all sbytes were sent */
     if(sbytes<0) {
-      failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+      failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
       return CURLE_SEND_ERROR;
     }
     /* Update the progress meter */
@@ -817,7 +821,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
                       state->remote_addrlen);
       /* Check all sbytes were sent */
       if(sbytes<0) {
-        failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
+        failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
         return CURLE_SEND_ERROR;
       }
       /* since this was a re-send, we remain at the still byte position */
@@ -1005,7 +1009,7 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
   state->sockfd = state->conn->sock[FIRSTSOCKET];
   state->state = TFTP_STATE_START;
   state->error = TFTP_ERR_NONE;
-  state->blksize = TFTP_BLKSIZE_DEFAULT;
+  state->blksize = blksize;
   state->requested_blksize = blksize;
 
   ((struct sockaddr *)&state->local_addr)->sa_family =
@@ -1030,8 +1034,9 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
     int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
                   conn->ip_addr->ai_addrlen);
     if(rc) {
+      char buffer[STRERROR_LEN];
       failf(conn->data, "bind() failed; %s",
-            Curl_strerror(conn, SOCKERRNO));
+            Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
       return CURLE_COULDNT_CONNECT;
     }
     conn->bits.bound = TRUE;
@@ -1242,7 +1247,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
     *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
     if(*done)
       /* Tell curl we're done */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
   }
   else {
     /* no timeouts to handle, check our socket */
@@ -1251,7 +1256,8 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
     if(rc == -1) {
       /* bail out */
       int error = SOCKERRNO;
-      failf(data, "%s", Curl_strerror(conn, error));
+      char buffer[STRERROR_LEN];
+      failf(data, "%s", Curl_strerror(error, buffer, sizeof(buffer)));
       state->event = TFTP_EVENT_ERROR;
     }
     else if(rc != 0) {
@@ -1264,7 +1270,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
       *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
       if(*done)
         /* Tell curl we're done */
-        Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+        Curl_setup_transfer(data, -1, -1, FALSE, -1);
     }
     /* if rc == 0, then select() timed out */
   }
diff --git a/lib/timeval.c b/lib/timeval.c
index dce1a76..e2bd7fd 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -24,26 +24,34 @@
 
 #if defined(WIN32) && !defined(MSDOS)
 
+/* set in win32_init() */
+extern LARGE_INTEGER Curl_freq;
+extern bool Curl_isVistaOrGreater;
+
 struct curltime Curl_now(void)
 {
-  /*
-  ** GetTickCount() is available on _all_ Windows versions from W95 up
-  ** to nowadays. Returns milliseconds elapsed since last system boot,
-  ** increases monotonically and wraps once 49.7 days have elapsed.
-  */
   struct curltime now;
-#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
-    (_WIN32_WINNT < _WIN32_WINNT_VISTA) || \
-    (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
-  DWORD milliseconds = GetTickCount();
-  now.tv_sec = milliseconds / 1000;
-  now.tv_usec = (milliseconds % 1000) * 1000;
-#else
-  ULONGLONG milliseconds = GetTickCount64();
-  now.tv_sec = (time_t) (milliseconds / 1000);
-  now.tv_usec = (unsigned int) (milliseconds % 1000) * 1000;
+  if(Curl_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */
+    LARGE_INTEGER count;
+    QueryPerformanceCounter(&count);
+    now.tv_sec = (time_t)(count.QuadPart / Curl_freq.QuadPart);
+    now.tv_usec = (int)((count.QuadPart % Curl_freq.QuadPart) * 1000000 /
+                        Curl_freq.QuadPart);
+  }
+  else {
+    /* Disable /analyze warning that GetTickCount64 is preferred  */
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:28159)
+#endif
+    DWORD milliseconds = GetTickCount();
+#if defined(_MSC_VER)
+#pragma warning(pop)
 #endif
 
+    now.tv_sec = milliseconds / 1000;
+    now.tv_usec = (milliseconds % 1000) * 1000;
+  }
   return now;
 }
 
@@ -58,7 +66,9 @@ struct curltime Curl_now(void)
   ** in any case the time starting point does not change once that the
   ** system has started up.
   */
+#ifdef HAVE_GETTIMEOFDAY
   struct timeval now;
+#endif
   struct curltime cnow;
   struct timespec tsnow;
 
@@ -180,7 +190,7 @@ struct curltime Curl_now(void)
  */
 timediff_t Curl_timediff(struct curltime newer, struct curltime older)
 {
-  timediff_t diff = newer.tv_sec-older.tv_sec;
+  timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
   if(diff >= (TIME_MAX/1000))
     return TIME_MAX;
   else if(diff <= (TIME_MIN/1000))
@@ -194,7 +204,7 @@ timediff_t Curl_timediff(struct curltime newer, struct curltime older)
  */
 timediff_t Curl_timediff_us(struct curltime newer, struct curltime older)
 {
-  timediff_t diff = newer.tv_sec-older.tv_sec;
+  timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
   if(diff >= (TIME_MAX/1000000))
     return TIME_MAX;
   else if(diff <= (TIME_MIN/1000000))
diff --git a/lib/timeval.h b/lib/timeval.h
index fb3f680..96867d7 100644
--- a/lib/timeval.h
+++ b/lib/timeval.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -26,8 +26,10 @@
 
 #if SIZEOF_TIME_T < 8
 typedef int timediff_t;
+#define CURL_FORMAT_TIMEDIFF_T "d"
 #else
 typedef curl_off_t timediff_t;
+#define CURL_FORMAT_TIMEDIFF_T CURL_FORMAT_CURL_OFF_T
 #endif
 
 struct curltime {
diff --git a/lib/transfer.c b/lib/transfer.c
index b73f94d..514330e 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -117,6 +117,35 @@ CURLcode Curl_get_upload_buffer(struct Curl_easy *data)
   return CURLE_OK;
 }
 
+#ifndef CURL_DISABLE_HTTP
+/*
+ * This function will be called to loop through the trailers buffer
+ * until no more data is available for sending.
+ */
+static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems,
+                                 void *raw)
+{
+  struct Curl_easy *data = (struct Curl_easy *)raw;
+  Curl_send_buffer *trailers_buf = data->state.trailers_buf;
+  size_t bytes_left = trailers_buf->size_used-data->state.trailers_bytes_sent;
+  size_t to_copy = (size*nitems < bytes_left) ? size*nitems : bytes_left;
+  if(to_copy) {
+    memcpy(buffer,
+           &trailers_buf->buffer[data->state.trailers_bytes_sent],
+           to_copy);
+    data->state.trailers_bytes_sent += to_copy;
+  }
+  return to_copy;
+}
+
+static size_t Curl_trailers_left(void *raw)
+{
+  struct Curl_easy *data = (struct Curl_easy *)raw;
+  Curl_send_buffer *trailers_buf = data->state.trailers_buf;
+  return trailers_buf->size_used - data->state.trailers_bytes_sent;
+}
+#endif
+
 /*
  * This function will call the read callback to fill our buffer with data
  * to upload.
@@ -127,6 +156,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
   struct Curl_easy *data = conn->data;
   size_t buffersize = bytes;
   size_t nread;
+
+  curl_read_callback readfunc = NULL;
+  void *extra_data = NULL;
+
 #ifdef CURL_DOES_CONVERSIONS
   bool sending_http_headers = FALSE;
 
@@ -140,15 +173,75 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
   }
 #endif
 
-  if(data->req.upload_chunky) {
+#ifndef CURL_DISABLE_HTTP
+  if(data->state.trailers_state == TRAILERS_INITIALIZED) {
+    struct curl_slist *trailers = NULL;
+    CURLcode c;
+    int trailers_ret_code;
+
+    /* at this point we already verified that the callback exists
+       so we compile and store the trailers buffer, then proceed */
+    infof(data,
+          "Moving trailers state machine from initialized to sending.\n");
+    data->state.trailers_state = TRAILERS_SENDING;
+    data->state.trailers_buf = Curl_add_buffer_init();
+    if(!data->state.trailers_buf) {
+      failf(data, "Unable to allocate trailing headers buffer !");
+      return CURLE_OUT_OF_MEMORY;
+    }
+    data->state.trailers_bytes_sent = 0;
+    Curl_set_in_callback(data, true);
+    trailers_ret_code = data->set.trailer_callback(&trailers,
+                                                   data->set.trailer_data);
+    Curl_set_in_callback(data, false);
+    if(trailers_ret_code == CURL_TRAILERFUNC_OK) {
+      c = Curl_http_compile_trailers(trailers, data->state.trailers_buf, data);
+    }
+    else {
+      failf(data, "operation aborted by trailing headers callback");
+      *nreadp = 0;
+      c = CURLE_ABORTED_BY_CALLBACK;
+    }
+    if(c != CURLE_OK) {
+      Curl_add_buffer_free(&data->state.trailers_buf);
+      curl_slist_free_all(trailers);
+      return c;
+    }
+    infof(data, "Successfully compiled trailers.\r\n");
+    curl_slist_free_all(trailers);
+  }
+#endif
+
+  /* if we are transmitting trailing data, we don't need to write
+     a chunk size so we skip this */
+  if(data->req.upload_chunky &&
+     data->state.trailers_state == TRAILERS_NONE) {
     /* if chunked Transfer-Encoding */
     buffersize -= (8 + 2 + 2);   /* 32bit hex + CRLF + CRLF */
     data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
   }
 
+#ifndef CURL_DISABLE_HTTP
+  if(data->state.trailers_state == TRAILERS_SENDING) {
+    /* if we're here then that means that we already sent the last empty chunk
+       but we didn't send a final CR LF, so we sent 0 CR LF. We then start
+       pulling trailing data until we ²have no more at which point we
+       simply return to the previous point in the state machine as if
+       nothing happened.
+       */
+    readfunc = Curl_trailers_read;
+    extra_data = (void *)data;
+  }
+  else
+#endif
+  {
+    readfunc = data->state.fread_func;
+    extra_data = data->state.in;
+  }
+
   Curl_set_in_callback(data, true);
-  nread = data->state.fread_func(data->req.upload_fromhere, 1,
-                                 buffersize, data->state.in);
+  nread = readfunc(data->req.upload_fromhere, 1,
+                   buffersize, extra_data);
   Curl_set_in_callback(data, false);
 
   if(nread == CURL_READFUNC_ABORT) {
@@ -200,10 +293,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
        here, knowing they'll become CRLFs later on.
      */
 
-    char hexbuffer[11];
+    bool added_crlf = FALSE;
+    int hexlen = 0;
     const char *endofline_native;
     const char *endofline_network;
-    int hexlen;
 
     if(
 #ifdef CURL_DO_LINEEND_CONV
@@ -218,20 +311,37 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
       endofline_native  = "\r\n";
       endofline_network = "\x0d\x0a";
     }
-    hexlen = snprintf(hexbuffer, sizeof(hexbuffer),
-                      "%x%s", nread, endofline_native);
 
-    /* move buffer pointer */
-    data->req.upload_fromhere -= hexlen;
-    nread += hexlen;
+    /* if we're not handling trailing data, proceed as usual */
+    if(data->state.trailers_state != TRAILERS_SENDING) {
+      char hexbuffer[11] = "";
+      hexlen = msnprintf(hexbuffer, sizeof(hexbuffer),
+                         "%zx%s", nread, endofline_native);
 
-    /* copy the prefix to the buffer, leaving out the NUL */
-    memcpy(data->req.upload_fromhere, hexbuffer, hexlen);
+      /* move buffer pointer */
+      data->req.upload_fromhere -= hexlen;
+      nread += hexlen;
 
-    /* always append ASCII CRLF to the data */
-    memcpy(data->req.upload_fromhere + nread,
-           endofline_network,
-           strlen(endofline_network));
+      /* copy the prefix to the buffer, leaving out the NUL */
+      memcpy(data->req.upload_fromhere, hexbuffer, hexlen);
+
+      /* always append ASCII CRLF to the data unless
+         we have a valid trailer callback */
+#ifndef CURL_DISABLE_HTTP
+      if((nread-hexlen) == 0 &&
+          data->set.trailer_callback != NULL &&
+          data->state.trailers_state == TRAILERS_NONE) {
+        data->state.trailers_state = TRAILERS_INITIALIZED;
+      }
+      else
+#endif
+      {
+        memcpy(data->req.upload_fromhere + nread,
+               endofline_network,
+               strlen(endofline_network));
+        added_crlf = TRUE;
+      }
+    }
 
 #ifdef CURL_DOES_CONVERSIONS
     {
@@ -242,22 +352,40 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
         length = nread;
       else
         /* just translate the protocol portion */
-        length = strlen(hexbuffer);
-      result = Curl_convert_to_network(data, data->req.upload_fromhere,
-                                       length);
-      /* Curl_convert_to_network calls failf if unsuccessful */
-      if(result)
-        return result;
+        length = hexlen;
+      if(length) {
+        result = Curl_convert_to_network(data, data->req.upload_fromhere,
+                                         length);
+        /* Curl_convert_to_network calls failf if unsuccessful */
+        if(result)
+          return result;
+      }
     }
 #endif /* CURL_DOES_CONVERSIONS */
 
-    if((nread - hexlen) == 0) {
-      /* mark this as done once this chunk is transferred */
+#ifndef CURL_DISABLE_HTTP
+    if(data->state.trailers_state == TRAILERS_SENDING &&
+       !Curl_trailers_left(data)) {
+      Curl_add_buffer_free(&data->state.trailers_buf);
+      data->state.trailers_state = TRAILERS_DONE;
+      data->set.trailer_data = NULL;
+      data->set.trailer_callback = NULL;
+      /* mark the transfer as done */
       data->req.upload_done = TRUE;
-      infof(data, "Signaling end of chunked upload via terminating chunk.\n");
+      infof(data, "Signaling end of chunked upload after trailers.\n");
     }
+    else
+#endif
+      if((nread - hexlen) == 0 &&
+         data->state.trailers_state != TRAILERS_INITIALIZED) {
+        /* mark this as done once this chunk is transferred */
+        data->req.upload_done = TRUE;
+        infof(data,
+              "Signaling end of chunked upload via terminating chunk.\n");
+      }
 
-    nread += strlen(endofline_native); /* for the added end of line */
+    if(added_crlf)
+      nread += strlen(endofline_network); /* for the added end of line */
   }
 #ifdef CURL_DOES_CONVERSIONS
   else if((data->set.prefer_ascii) && (!sending_http_headers)) {
@@ -333,7 +461,6 @@ CURLcode Curl_readrewind(struct connectdata *conn)
       infof(data, "the ioctl callback returned %d\n", (int)err);
 
       if(err) {
-        /* FIXME: convert to a human readable error message */
         failf(data, "ioctl callback returned error %d", (int)err);
         return CURLE_SEND_FAIL_REWIND;
       }
@@ -376,35 +503,6 @@ static int data_pending(const struct connectdata *conn)
 #endif
 }
 
-static void read_rewind(struct connectdata *conn,
-                        size_t thismuch)
-{
-  DEBUGASSERT(conn->read_pos >= thismuch);
-
-  conn->read_pos -= thismuch;
-  conn->bits.stream_was_rewound = TRUE;
-
-#ifdef DEBUGBUILD
-  {
-    char buf[512 + 1];
-    size_t show;
-
-    show = CURLMIN(conn->buf_len - conn->read_pos, sizeof(buf)-1);
-    if(conn->master_buffer) {
-      memcpy(buf, conn->master_buffer + conn->read_pos, show);
-      buf[show] = '\0';
-    }
-    else {
-      buf[0] = '\0';
-    }
-
-    DEBUGF(infof(conn->data,
-                 "Buffer after stream rewind (read_pos = %zu): [%s]\n",
-                 conn->read_pos, buf));
-  }
-#endif
-}
-
 /*
  * Check to see if CURLOPT_TIMECONDITION was met by comparing the time of the
  * remote document with the time provided by CURLOPT_TIMEVAL
@@ -479,9 +577,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
          conn->httpversion == 20) &&
 #endif
        k->size != -1 && !k->header) {
-      /* make sure we don't read "too much" if we can help it since we
-         might be pipelining and then someone else might want to read what
-         follows! */
+      /* make sure we don't read too much */
       curl_off_t totalleft = k->size - k->bytecount;
       if(totalleft < (curl_off_t)bytestoread)
         bytestoread = (size_t)totalleft;
@@ -520,7 +616,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
     if(0 < nread || is_empty_data) {
       k->buf[nread] = 0;
     }
-    else if(0 >= nread) {
+    else {
       /* if we receive 0 or less here, the server closed the connection
          and we bail out from this! */
       DEBUGF(infof(data, "nread <= 0, server closed connection, bailing\n"));
@@ -563,20 +659,11 @@ static CURLcode readwrite_data(struct Curl_easy *data,
         /* We've stopped dealing with input, get out of the do-while loop */
 
         if(nread > 0) {
-          if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) {
-            infof(data,
-                  "Rewinding stream by : %zd"
-                  " bytes on url %s (zero-length body)\n",
-                  nread, data->state.up.path);
-            read_rewind(conn, (size_t)nread);
-          }
-          else {
-            infof(data,
-                  "Excess found in a non pipelined read:"
-                  " excess = %zd"
-                  " url = %s (zero-length body)\n",
-                  nread, data->state.up.path);
-          }
+          infof(data,
+                "Excess found:"
+                " excess = %zd"
+                " url = %s (zero-length body)\n",
+                nread, data->state.up.path);
         }
 
         break;
@@ -707,19 +794,12 @@ static CURLcode readwrite_data(struct Curl_easy *data,
 
           /* There are now possibly N number of bytes at the end of the
              str buffer that weren't written to the client.
-
-             We DO care about this data if we are pipelining.
              Push it back to be read on the next pass. */
 
           dataleft = conn->chunk.dataleft;
           if(dataleft != 0) {
             infof(conn->data, "Leftovers after chunking: %zu bytes\n",
                   dataleft);
-            if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) {
-              /* only attempt the rewind if we truly are pipelining */
-              infof(conn->data, "Rewinding %zu bytes\n",dataleft);
-              read_rewind(conn, dataleft);
-            }
           }
         }
         /* If it returned OK, we just keep going */
@@ -738,25 +818,13 @@ static CURLcode readwrite_data(struct Curl_easy *data,
 
         excess = (size_t)(k->bytecount + nread - k->maxdownload);
         if(excess > 0 && !k->ignorebody) {
-          if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) {
-            infof(data,
-                  "Rewinding stream by : %zu"
-                  " bytes on url %s (size = %" CURL_FORMAT_CURL_OFF_T
-                  ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
-                  ", bytecount = %" CURL_FORMAT_CURL_OFF_T ", nread = %zd)\n",
-                  excess, data->state.up.path,
-                  k->size, k->maxdownload, k->bytecount, nread);
-            read_rewind(conn, excess);
-          }
-          else {
-            infof(data,
-                  "Excess found in a non pipelined read:"
-                  " excess = %zu"
-                  ", size = %" CURL_FORMAT_CURL_OFF_T
-                  ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
-                  ", bytecount = %" CURL_FORMAT_CURL_OFF_T "\n",
-                  excess, k->size, k->maxdownload, k->bytecount);
-          }
+          infof(data,
+                "Excess found in a read:"
+                " excess = %zu"
+                ", size = %" CURL_FORMAT_CURL_OFF_T
+                ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
+                ", bytecount = %" CURL_FORMAT_CURL_OFF_T "\n",
+                excess, k->size, k->maxdownload, k->bytecount);
         }
 
         nread = (ssize_t) (k->maxdownload - k->bytecount);
@@ -844,6 +912,11 @@ static CURLcode readwrite_data(struct Curl_easy *data,
       k->keepon &= ~KEEP_RECV;
     }
 
+    if(k->keepon & KEEP_RECV_PAUSE) {
+      /* this is a paused transfer */
+      break;
+    }
+
   } while(data_pending(conn) && maxloops--);
 
   if(maxloops <= 0) {
@@ -920,7 +993,6 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
   *didwhat |= KEEP_SEND;
 
   do {
-
     /* only read more data if there's no upload data already
        present in the upload buffer */
     if(0 == k->upload_present) {
@@ -945,7 +1017,6 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
           k->keepon &= ~KEEP_SEND;         /* disable writing */
           k->start100 = Curl_now();       /* timeout count starts now */
           *didwhat &= ~KEEP_SEND;  /* we didn't write anything actually */
-
           /* set a timeout for the multi interface */
           Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
           break;
@@ -1065,6 +1136,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
                  (size_t)bytes_written);
 
     k->writebytecount += bytes_written;
+    Curl_pgrsSetUploadCounter(data, k->writebytecount);
 
     if((!k->upload_chunky || k->forbidchunk) &&
        (k->writebytecount == data->state.infilesize)) {
@@ -1098,7 +1170,6 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
       }
     }
 
-    Curl_pgrsSetUploadCounter(data, k->writebytecount);
 
   } WHILE_FALSE; /* just to break out from! */
 
@@ -1176,11 +1247,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
 
   k->now = Curl_now();
   if(didwhat) {
-    /* Update read/write counters */
-    if(k->bytecountp)
-      *k->bytecountp = k->bytecount; /* read count */
-    if(k->writebytecountp)
-      *k->writebytecountp = k->writebytecount; /* write count */
+    ;
   }
   else {
     /* no read no write, this is a timeout? */
@@ -1219,15 +1286,15 @@ CURLcode Curl_readwrite(struct connectdata *conn,
   if(k->keepon) {
     if(0 > Curl_timeleft(data, &k->now, FALSE)) {
       if(k->size != -1) {
-        failf(data, "Operation timed out after %ld milliseconds with %"
-              CURL_FORMAT_CURL_OFF_T " out of %"
+        failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
+              " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
               CURL_FORMAT_CURL_OFF_T " bytes received",
               Curl_timediff(k->now, data->progress.t_startsingle),
               k->bytecount, k->size);
       }
       else {
-        failf(data, "Operation timed out after %ld milliseconds with %"
-              CURL_FORMAT_CURL_OFF_T " bytes received",
+        failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
+              " milliseconds with %" CURL_FORMAT_CURL_OFF_T " bytes received",
               Curl_timediff(k->now, data->progress.t_startsingle),
               k->bytecount);
       }
@@ -1348,17 +1415,30 @@ void Curl_init_CONNECT(struct Curl_easy *data)
 CURLcode Curl_pretransfer(struct Curl_easy *data)
 {
   CURLcode result;
-  if(!data->change.url) {
+
+  if(!data->change.url && !data->set.uh) {
     /* we can't do anything without URL */
     failf(data, "No URL set!");
     return CURLE_URL_MALFORMAT;
   }
+
   /* since the URL may have been redirected in a previous use of this handle */
   if(data->change.url_alloc) {
     /* the already set URL is allocated, free it first! */
     Curl_safefree(data->change.url);
     data->change.url_alloc = FALSE;
   }
+
+  if(!data->change.url && data->set.uh) {
+    CURLUcode uc;
+    uc = curl_url_get(data->set.uh,
+                        CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
+    if(uc) {
+      failf(data, "No URL set!");
+      return CURLE_URL_MALFORMAT;
+    }
+  }
+
   data->change.url = data->set.str[STRING_SET_URL];
 
   /* Init the SSL session ID cache here. We do it here since we want to do it
@@ -1382,11 +1462,14 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
 
   if(data->set.httpreq == HTTPREQ_PUT)
     data->state.infilesize = data->set.filesize;
-  else {
+  else if((data->set.httpreq != HTTPREQ_GET) &&
+          (data->set.httpreq != HTTPREQ_HEAD)) {
     data->state.infilesize = data->set.postfieldsize;
     if(data->set.postfields && (data->state.infilesize == -1))
       data->state.infilesize = (curl_off_t)strlen(data->set.postfields);
   }
+  else
+    data->state.infilesize = 0;
 
   /* If there is a list of cookie files to read, do it now! */
   if(data->change.cookielist)
@@ -1414,18 +1497,13 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
     Curl_pgrsResetTransferSizes(data);
     Curl_pgrsStartNow(data);
 
-    if(data->set.timeout)
-      Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
-
-    if(data->set.connecttimeout)
-      Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
-
     /* In case the handle is re-used and an authentication method was picked
        in the session we need to make sure we only use the one(s) we now
        consider to be fine */
     data->state.authhost.picked &= data->state.authhost.want;
     data->state.authproxy.picked &= data->state.authproxy.want;
 
+#ifndef CURL_DISABLE_FTP
     if(data->state.wildcardmatch) {
       struct WildcardData *wc = &data->wildcard;
       if(wc->state < CURLWC_INIT) {
@@ -1434,6 +1512,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
           return CURLE_OUT_OF_MEMORY;
       }
     }
+#endif
   }
 
   return result;
@@ -1514,13 +1593,24 @@ CURLcode Curl_follow(struct Curl_easy *data,
     disallowport = TRUE;
 
   DEBUGASSERT(data->state.uh);
-  uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, 0);
-  if(uc)
-    return Curl_uc_to_curlcode(uc);
+  uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
+                    (type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME : 0);
+  if(uc) {
+    if(type != FOLLOW_FAKE)
+      return Curl_uc_to_curlcode(uc);
+
+    /* the URL could not be parsed for some reason, but since this is FAKE
+       mode, just duplicate the field as-is */
+    newurl = strdup(newurl);
+    if(!newurl)
+      return CURLE_OUT_OF_MEMORY;
+  }
+  else {
 
-  uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
-  if(uc)
-    return Curl_uc_to_curlcode(uc);
+    uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
+    if(uc)
+      return Curl_uc_to_curlcode(uc);
+  }
 
   if(type == FOLLOW_FAKE) {
     /* we're only figuring out the new url if we would've followed locations
@@ -1703,8 +1793,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
 
 
     if(conn->handler->protocol&PROTO_FAMILY_HTTP) {
-      struct HTTP *http = data->req.protop;
-      if(http->writebytecount) {
+      if(data->req.writebytecount) {
         CURLcode result = Curl_readrewind(conn);
         if(result) {
           Curl_safefree(*url);
@@ -1722,24 +1811,17 @@ CURLcode Curl_retry_request(struct connectdata *conn,
  */
 void
 Curl_setup_transfer(
-  struct connectdata *conn, /* connection data */
+  struct Curl_easy *data,   /* transfer */
   int sockindex,            /* socket index to read from or -1 */
   curl_off_t size,          /* -1 if unknown at this point */
   bool getheader,           /* TRUE if header parsing is wanted */
-  curl_off_t *bytecountp,   /* return number of bytes read or NULL */
-  int writesockindex,       /* socket index to write to, it may very well be
+  int writesockindex        /* socket index to write to, it may very well be
                                the same we read from. -1 disables */
-  curl_off_t *writecountp   /* return number of bytes written or NULL */
   )
 {
-  struct Curl_easy *data;
-  struct SingleRequest *k;
-
+  struct SingleRequest *k = &data->req;
+  struct connectdata *conn = data->conn;
   DEBUGASSERT(conn != NULL);
-
-  data = conn->data;
-  k = &data->req;
-
   DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
 
   if(conn->bits.multiplex || conn->httpversion == 20) {
@@ -1758,8 +1840,6 @@ Curl_setup_transfer(
   k->getheader = getheader;
 
   k->size = size;
-  k->bytecountp = bytecountp;
-  k->writebytecountp = writecountp;
 
   /* The code sequence below is placed in this function just because all
      necessary input is not always known in do_complete() as this function may
diff --git a/lib/transfer.h b/lib/transfer.h
index 9742455..a9bff63 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -59,15 +59,13 @@ CURLcode Curl_get_upload_buffer(struct Curl_easy *data);
 
 /* This sets up a forthcoming transfer */
 void
-Curl_setup_transfer (struct connectdata *data,
-               int sockindex,           /* socket index to read from or -1 */
-               curl_off_t size,         /* -1 if unknown at this point */
-               bool getheader,          /* TRUE if header parsing is wanted */
-               curl_off_t *bytecountp,  /* return number of bytes read */
-               int writesockindex,      /* socket index to write to, it may
-                                           very well be the same we read from.
-                                           -1 disables */
-               curl_off_t *writecountp /* return number of bytes written */
-);
+Curl_setup_transfer (struct Curl_easy *data,
+                     int sockindex,     /* socket index to read from or -1 */
+                     curl_off_t size,   /* -1 if unknown at this point */
+                     bool getheader,    /* TRUE if header parsing is wanted */
+                     int writesockindex /* socket index to write to. May be
+                                           the same we read from. -1
+                                           disables */
+  );
 
 #endif /* HEADER_CURL_TRANSFER_H */
diff --git a/lib/url.c b/lib/url.c
index 0d5a13f..c441ae7 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -109,17 +109,16 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
 #include "connect.h"
 #include "inet_ntop.h"
 #include "http_ntlm.h"
-#include "curl_ntlm_wb.h"
 #include "socks.h"
 #include "curl_rtmp.h"
 #include "gopher.h"
 #include "http_proxy.h"
 #include "conncache.h"
 #include "multihandle.h"
-#include "pipeline.h"
 #include "dotdot.h"
 #include "strdup.h"
 #include "setopt.h"
+#include "altsvc.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -127,7 +126,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
 #include "memdebug.h"
 
 static void conn_free(struct connectdata *conn);
-static void free_fixed_hostname(struct hostname *host);
+static void free_idnconverted_hostname(struct hostname *host);
 static unsigned int get_protocol_family(unsigned int protocol);
 
 /* Some parts of the code (e.g. chunked encoding) assume this buffer has at
@@ -186,11 +185,11 @@ static const struct Curl_handler * const protocols[] = {
   &Curl_handler_tftp,
 #endif
 
-#if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
+#if defined(USE_SSH)
   &Curl_handler_scp,
 #endif
 
-#if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
+#if defined(USE_SSH)
   &Curl_handler_sftp,
 #endif
 
@@ -292,7 +291,7 @@ void Curl_freeset(struct Curl_easy *data)
 }
 
 /* free the URL pieces */
-void Curl_up_free(struct Curl_easy *data)
+static void up_free(struct Curl_easy *data)
 {
   struct urlpieces *up = &data->state.up;
   Curl_safefree(up->scheme);
@@ -369,12 +368,19 @@ CURLcode Curl_close(struct Curl_easy *data)
   }
   data->change.referer = NULL;
 
-  Curl_up_free(data);
+  up_free(data);
   Curl_safefree(data->state.buffer);
   Curl_safefree(data->state.headerbuff);
   Curl_safefree(data->state.ulbuf);
   Curl_flush_cookies(data, 1);
-  Curl_digest_cleanup(data);
+#ifdef USE_ALTSVC
+  Curl_altsvc_save(data->asi, data->set.str[STRING_ALTSVC]);
+  Curl_altsvc_cleanup(data->asi);
+  data->asi = NULL;
+#endif
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+  Curl_http_auth_cleanup_digest(data);
+#endif
   Curl_safefree(data->info.contenttype);
   Curl_safefree(data->info.wouldredirect);
 
@@ -433,11 +439,12 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
 
   set->httpreq = HTTPREQ_GET; /* Default HTTP request */
   set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
+#ifndef CURL_DISABLE_FILE
   set->ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */
   set->ftp_use_eprt = TRUE;   /* FTP defaults to EPRT operations */
   set->ftp_use_pret = FALSE;  /* mainly useful for drftpd servers */
   set->ftp_filemethod = FTPFILE_MULTICWD;
-
+#endif
   set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
 
   /* Set the default size of the SSL session ID cache */
@@ -492,9 +499,9 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
 
   /* Set the default CA cert bundle/path detected/specified at build time.
    *
-   * If Schannel (WinSSL) is the selected SSL backend then these locations
-   * are ignored. We allow setting CA location for schannel only when
-   * explicitly specified by the user via CURLOPT_CAINFO / --cacert.
+   * If Schannel is the selected SSL backend then these locations are
+   * ignored. We allow setting CA location for schannel only when explicitly
+   * specified by the user via CURLOPT_CAINFO / --cacert.
    */
   if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
 #if defined(CURL_CA_BUNDLE)
@@ -536,6 +543,8 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
   set->fnmatch = ZERO_NULL;
   set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT;
   set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
+  set->maxage_conn = 118;
+  set->http09_allowed = TRUE;
   set->httpversion =
 #ifdef USE_NGHTTP2
     CURL_HTTP_VERSION_2TLS
@@ -570,7 +579,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
 
   data->magic = CURLEASY_MAGIC_NUMBER;
 
-  result = Curl_resolver_init(&data->state.resolver);
+  result = Curl_resolver_init(data, &data->state.resolver);
   if(result) {
     DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
     free(data);
@@ -659,11 +668,15 @@ static void conn_reset_all_postponed_data(struct connectdata *conn)
 #define conn_reset_all_postponed_data(c) do {} WHILE_FALSE
 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
 
-static void conn_free(struct connectdata *conn)
+
+static void conn_shutdown(struct connectdata *conn)
 {
   if(!conn)
     return;
 
+  infof(conn->data, "Closing connection %ld\n", conn->connection_id);
+  DEBUGASSERT(conn->data);
+
   /* possible left-overs from the async name resolvers */
   Curl_resolver_cancel(conn);
 
@@ -682,10 +695,20 @@ static void conn_free(struct connectdata *conn)
   if(CURL_SOCKET_BAD != conn->tempsock[1])
     Curl_closesocket(conn, conn->tempsock[1]);
 
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
-    defined(NTLM_WB_ENABLED)
-  Curl_ntlm_wb_cleanup(conn);
-#endif
+  /* unlink ourselves. this should be called last since other shutdown
+     procedures need a valid conn->data and this may clear it. */
+  Curl_conncache_remove_conn(conn->data, conn, TRUE);
+}
+
+static void conn_free(struct connectdata *conn)
+{
+  if(!conn)
+    return;
+
+  free_idnconverted_hostname(&conn->host);
+  free_idnconverted_hostname(&conn->conn_to_host);
+  free_idnconverted_hostname(&conn->http_proxy.host);
+  free_idnconverted_hostname(&conn->socks_proxy.host);
 
   Curl_safefree(conn->user);
   Curl_safefree(conn->passwd);
@@ -708,17 +731,14 @@ static void conn_free(struct connectdata *conn)
   Curl_safefree(conn->trailer);
   Curl_safefree(conn->host.rawalloc); /* host name buffer */
   Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
+  Curl_safefree(conn->hostname_resolve);
   Curl_safefree(conn->secondaryhostname);
   Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
   Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
-  Curl_safefree(conn->master_buffer);
   Curl_safefree(conn->connect_state);
 
   conn_reset_all_postponed_data(conn);
-
-  Curl_llist_destroy(&conn->send_pipe, NULL);
-  Curl_llist_destroy(&conn->recv_pipe, NULL);
-
+  Curl_llist_destroy(&conn->easyq, NULL);
   Curl_safefree(conn->localdev);
   Curl_free_primary_ssl_config(&conn->ssl_config);
   Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
@@ -767,7 +787,6 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
     return CURLE_OK;
   }
 
-  conn->data = data;
   if(conn->dns_entry != NULL) {
     Curl_resolv_unlock(data, conn->dns_entry);
     conn->dns_entry = NULL;
@@ -777,27 +796,26 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
 
 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
   /* Cleanup NTLM connection-related data */
-  Curl_http_ntlm_cleanup(conn);
+  Curl_http_auth_cleanup_ntlm(conn);
 #endif
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
+  /* Cleanup NEGOTIATE connection-related data */
+  Curl_http_auth_cleanup_negotiate(conn);
+#endif
+
+  /* the protocol specific disconnect handler and conn_shutdown need a transfer
+     for the connection! */
+  conn->data = data;
+
+  if(conn->bits.connect_only)
+    /* treat the connection as dead in CONNECT_ONLY situations */
+    dead_connection = TRUE;
 
   if(conn->handler->disconnect)
     /* This is set if protocol-specific cleanups should be made */
     conn->handler->disconnect(conn, dead_connection);
 
-    /* unlink ourselves! */
-  infof(data, "Closing connection %ld\n", conn->connection_id);
-  Curl_conncache_remove_conn(conn, TRUE);
-
-  free_fixed_hostname(&conn->host);
-  free_fixed_hostname(&conn->conn_to_host);
-  free_fixed_hostname(&conn->http_proxy.host);
-  free_fixed_hostname(&conn->socks_proxy.host);
-
-  DEBUGASSERT(conn->data == data);
-  /* this assumes that the pointer is still there after the connection was
-     detected from the cache */
-  Curl_ssl_close(conn, FIRSTSOCKET);
-
+  conn_shutdown(conn);
   conn_free(conn);
   return CURLE_OK;
 }
@@ -821,28 +839,21 @@ static bool SocketIsDead(curl_socket_t sock)
 }
 
 /*
- * IsPipeliningPossible()
+ * IsMultiplexingPossible()
  *
- * Return a bitmask with the available pipelining and multiplexing options for
- * the given requested connection.
+ * Return a bitmask with the available multiplexing options for the given
+ * requested connection.
  */
-static int IsPipeliningPossible(const struct Curl_easy *handle,
-                                const struct connectdata *conn)
+static int IsMultiplexingPossible(const struct Curl_easy *handle,
+                                  const struct connectdata *conn)
 {
   int avail = 0;
 
-  /* If a HTTP protocol and pipelining is enabled */
+  /* If a HTTP protocol and multiplexing is enabled */
   if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
      (!conn->bits.protoconnstart || !conn->bits.close)) {
 
-    if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
-       (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
-       (handle->set.httpreq == HTTPREQ_GET ||
-        handle->set.httpreq == HTTPREQ_HEAD))
-      /* didn't ask for HTTP/1.0 and a GET or HEAD */
-      avail |= CURLPIPE_HTTP1;
-
-    if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) &&
+    if(Curl_multiplex_wanted(handle->multi) &&
        (handle->set.httpversion >= CURL_HTTP_VERSION_2))
       /* allows HTTP/2 */
       avail |= CURLPIPE_MULTIPLEX;
@@ -850,84 +861,7 @@ static int IsPipeliningPossible(const struct Curl_easy *handle,
   return avail;
 }
 
-/* Returns non-zero if a handle was removed */
-int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
-                                  struct curl_llist *pipeline)
-{
-  if(pipeline) {
-    struct curl_llist_element *curr;
-
-    curr = pipeline->head;
-    while(curr) {
-      if(curr->ptr == handle) {
-        Curl_llist_remove(pipeline, curr, NULL);
-        return 1; /* we removed a handle */
-      }
-      curr = curr->next;
-    }
-  }
-
-  return 0;
-}
-
-#if 0 /* this code is saved here as it is useful for debugging purposes */
-static void Curl_printPipeline(struct curl_llist *pipeline)
-{
-  struct curl_llist_element *curr;
-
-  curr = pipeline->head;
-  while(curr) {
-    struct Curl_easy *data = (struct Curl_easy *) curr->ptr;
-    infof(data, "Handle in pipeline: %s\n", data->state.path);
-    curr = curr->next;
-  }
-}
-#endif
-
-static struct Curl_easy* gethandleathead(struct curl_llist *pipeline)
-{
-  struct curl_llist_element *curr = pipeline->head;
-#ifdef DEBUGBUILD
-  {
-    struct curl_llist_element *p = pipeline->head;
-    while(p) {
-      struct Curl_easy *e = p->ptr;
-      DEBUGASSERT(GOOD_EASY_HANDLE(e));
-      p = p->next;
-    }
-  }
-#endif
-  if(curr) {
-    return (struct Curl_easy *) curr->ptr;
-  }
-
-  return NULL;
-}
-
-/* remove the specified connection from all (possible) pipelines and related
-   queues */
-void Curl_getoff_all_pipelines(struct Curl_easy *data,
-                               struct connectdata *conn)
-{
-  if(!conn->bundle)
-    return;
-  if(conn->bundle->multiuse == BUNDLE_PIPELINING) {
-    bool recv_head = (conn->readchannel_inuse &&
-                      Curl_recvpipe_head(data, conn));
-    bool send_head = (conn->writechannel_inuse &&
-                      Curl_sendpipe_head(data, conn));
-
-    if(Curl_removeHandleFromPipeline(data, &conn->recv_pipe) && recv_head)
-      Curl_pipeline_leave_read(conn);
-    if(Curl_removeHandleFromPipeline(data, &conn->send_pipe) && send_head)
-      Curl_pipeline_leave_write(conn);
-  }
-  else {
-    (void)Curl_removeHandleFromPipeline(data, &conn->recv_pipe);
-    (void)Curl_removeHandleFromPipeline(data, &conn->send_pipe);
-  }
-}
-
+#ifndef CURL_DISABLE_PROXY
 static bool
 proxy_info_matches(const struct proxy_info* data,
                    const struct proxy_info* needle)
@@ -939,6 +873,10 @@ proxy_info_matches(const struct proxy_info* data,
 
   return FALSE;
 }
+#else
+/* disabled, won't get called */
+#define proxy_info_matches(x,y) FALSE
+#endif
 
 /*
  * This function checks if the given connection is dead and extracts it from
@@ -952,20 +890,18 @@ proxy_info_matches(const struct proxy_info* data,
 static bool extract_if_dead(struct connectdata *conn,
                             struct Curl_easy *data)
 {
-  size_t pipeLen = conn->send_pipe.size + conn->recv_pipe.size;
-  if(!pipeLen && !CONN_INUSE(conn)) {
-    /* The check for a dead socket makes sense only if there are no
-       handles in pipeline and the connection isn't already marked in
+  if(!CONN_INUSE(conn) && !conn->data) {
+    /* The check for a dead socket makes sense only if the connection isn't in
        use */
     bool dead;
-
-    conn->data = data;
     if(conn->handler->connection_check) {
       /* The protocol has a special method for checking the state of the
          connection. Use it to check if the connection is dead. */
       unsigned int state;
-
+      struct Curl_easy *olddata = conn->data;
+      conn->data = data; /* use this transfer for now */
       state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD);
+      conn->data = olddata;
       dead = (state & CONNRESULT_DEAD);
     }
     else {
@@ -975,8 +911,7 @@ static bool extract_if_dead(struct connectdata *conn,
 
     if(dead) {
       infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
-      Curl_conncache_remove_conn(conn, FALSE);
-      conn->data = NULL; /* detach */
+      Curl_conncache_remove_conn(data, conn, FALSE);
       return TRUE;
     }
   }
@@ -1026,13 +961,25 @@ static void prune_dead_connections(struct Curl_easy *data)
   }
 }
 
+/* A connection has to have been idle for a shorter time than 'maxage_conn' to
+   be subject for reuse. The success rate is just too low after this. */
 
-static size_t max_pipeline_length(struct Curl_multi *multi)
+static bool conn_maxage(struct Curl_easy *data,
+                        struct connectdata *conn,
+                        struct curltime now)
 {
-  return multi ? multi->max_pipeline_length : 0;
-}
-
+  if(!conn->data) {
+    timediff_t idletime = Curl_timediff(now, conn->lastused);
+    idletime /= 1000; /* integer seconds is fine */
 
+    if(idletime/1000 > data->set.maxage_conn) {
+      infof(data, "Too old connection (%ld seconds), disconnect it\n",
+            idletime);
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
 /*
  * Given one filled in connection struct (named needle), this function should
  * detect if there already is one that has all the significant details
@@ -1042,8 +989,7 @@ static size_t max_pipeline_length(struct Curl_multi *multi)
  * connection as 'in-use'. It must later be called with ConnectionDone() to
  * return back to 'idle' (unused) state.
  *
- * The force_reuse flag is set if the connection must be used, even if
- * the pipelining strategy wants to open a new connection instead of reusing.
+ * The force_reuse flag is set if the connection must be used.
  */
 static bool
 ConnectionExists(struct Curl_easy *data,
@@ -1055,8 +1001,9 @@ ConnectionExists(struct Curl_easy *data,
   struct connectdata *check;
   struct connectdata *chosen = 0;
   bool foundPendingCandidate = FALSE;
-  int canpipe = IsPipeliningPossible(data, needle);
+  bool canmultiplex = IsMultiplexingPossible(data, needle);
   struct connectbundle *bundle;
+  struct curltime now = Curl_now();
 
 #ifdef USE_NTLM
   bool wantNTLMhttp = ((data->state.authhost.want &
@@ -1071,59 +1018,47 @@ ConnectionExists(struct Curl_easy *data,
   *force_reuse = FALSE;
   *waitpipe = FALSE;
 
-  /* We can't pipeline if the site is blacklisted */
-  if((canpipe & CURLPIPE_HTTP1) &&
-     Curl_pipeline_site_blacklisted(data, needle))
-    canpipe &= ~ CURLPIPE_HTTP1;
-
   /* Look up the bundle with all the connections to this particular host.
      Locks the connection cache, beware of early returns! */
   bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache);
   if(bundle) {
     /* Max pipe length is zero (unlimited) for multiplexed connections */
-    size_t max_pipe_len = (bundle->multiuse != BUNDLE_MULTIPLEX)?
-      max_pipeline_length(data->multi):0;
-    size_t best_pipe_len = max_pipe_len;
     struct curl_llist_element *curr;
 
     infof(data, "Found bundle for host %s: %p [%s]\n",
           (needle->bits.conn_to_host ? needle->conn_to_host.name :
            needle->host.name), (void *)bundle,
-          (bundle->multiuse == BUNDLE_PIPELINING ?
-           "can pipeline" :
-           (bundle->multiuse == BUNDLE_MULTIPLEX ?
-            "can multiplex" : "serially")));
-
-    /* We can't pipeline if we don't know anything about the server */
-    if(canpipe) {
-      if(bundle->multiuse <= BUNDLE_UNKNOWN) {
+          (bundle->multiuse == BUNDLE_MULTIPLEX ?
+           "can multiplex" : "serially"));
+
+    /* We can't multiplex if we don't know anything about the server */
+    if(canmultiplex) {
+      if(bundle->multiuse == BUNDLE_UNKNOWN) {
         if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) {
-          infof(data, "Server doesn't support multi-use yet, wait\n");
+          infof(data, "Server doesn't support multiplex yet, wait\n");
           *waitpipe = TRUE;
-          Curl_conncache_unlock(needle);
+          Curl_conncache_unlock(data);
           return FALSE; /* no re-use */
         }
 
-        infof(data, "Server doesn't support multi-use (yet)\n");
-        canpipe = 0;
+        infof(data, "Server doesn't support multiplex (yet)\n");
+        canmultiplex = FALSE;
       }
-      if((bundle->multiuse == BUNDLE_PIPELINING) &&
-         !Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1)) {
-        /* not asked for, switch off */
-        infof(data, "Could pipeline, but not asked to!\n");
-        canpipe = 0;
-      }
-      else if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
-              !Curl_pipeline_wanted(data->multi, CURLPIPE_MULTIPLEX)) {
+      if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
+         !Curl_multiplex_wanted(data->multi)) {
         infof(data, "Could multiplex, but not asked to!\n");
-        canpipe = 0;
+        canmultiplex = FALSE;
+      }
+      if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
+        infof(data, "Can not multiplex, even if we wanted to!\n");
+        canmultiplex = FALSE;
       }
     }
 
     curr = bundle->conn_list.head;
     while(curr) {
       bool match = FALSE;
-      size_t pipeLen;
+      size_t multiplexed;
 
       /*
        * Note that if we use a HTTP proxy in normal mode (no tunneling), we
@@ -1132,35 +1067,25 @@ ConnectionExists(struct Curl_easy *data,
       check = curr->ptr;
       curr = curr->next;
 
-      if(extract_if_dead(check, data)) {
+      if(check->bits.connect_only)
+        /* connect-only connections will not be reused */
+        continue;
+
+      if(conn_maxage(data, check, now) || extract_if_dead(check, data)) {
         /* disconnect it */
         (void)Curl_disconnect(data, check, /* dead_connection */TRUE);
         continue;
       }
 
-      pipeLen = check->send_pipe.size + check->recv_pipe.size;
+      multiplexed = CONN_INUSE(check) &&
+        (bundle->multiuse == BUNDLE_MULTIPLEX);
 
-      if(canpipe) {
+      if(canmultiplex) {
         if(check->bits.protoconnstart && check->bits.close)
           continue;
-
-        if(!check->bits.multiplex) {
-          /* If not multiplexing, make sure the connection is fine for HTTP/1
-             pipelining */
-          struct Curl_easy* sh = gethandleathead(&check->send_pipe);
-          struct Curl_easy* rh = gethandleathead(&check->recv_pipe);
-          if(sh) {
-            if(!(IsPipeliningPossible(sh, check) & CURLPIPE_HTTP1))
-              continue;
-          }
-          else if(rh) {
-            if(!(IsPipeliningPossible(rh, check) & CURLPIPE_HTTP1))
-              continue;
-          }
-        }
       }
       else {
-        if(pipeLen > 0) {
+        if(multiplexed) {
           /* can only happen within multi handles, and means that another easy
              handle is using this connection */
           continue;
@@ -1185,13 +1110,6 @@ ConnectionExists(struct Curl_easy *data,
              to get closed. */
           infof(data, "Connection #%ld isn't open enough, can't reuse\n",
                 check->connection_id);
-#ifdef DEBUGBUILD
-          if(check->recv_pipe.size > 0) {
-            infof(data,
-                  "BAD! Unconnected #%ld has a non-empty recv pipeline!\n",
-                  check->connection_id);
-          }
-#endif
           continue;
         }
       }
@@ -1262,14 +1180,15 @@ ConnectionExists(struct Curl_easy *data,
         }
       }
 
-      if(!canpipe && CONN_INUSE(check))
-        /* this request can't be pipelined but the checked connection is
+      if(!canmultiplex && check->data)
+        /* this request can't be multiplexed but the checked connection is
            already in use so we skip it */
         continue;
 
-      if(CONN_INUSE(check) && (check->data->multi != needle->data->multi))
-        /* this could be subject for pipeline/multiplex use, but only
-           if they belong to the same multi handle */
+      if(CONN_INUSE(check) && check->data &&
+         (check->data->multi != needle->data->multi))
+        /* this could be subject for multiplex use, but only if they belong to
+         * the same multi handle */
         continue;
 
       if(needle->localdev || needle->localport) {
@@ -1360,7 +1279,7 @@ ConnectionExists(struct Curl_easy *data,
              strcmp(needle->passwd, check->passwd))
             continue;
         }
-        else if(check->ntlm.state != NTLMSTATE_NONE) {
+        else if(check->http_ntlm_state != NTLMSTATE_NONE) {
           /* Connection is using NTLM auth but we don't want NTLM */
           continue;
         }
@@ -1376,7 +1295,7 @@ ConnectionExists(struct Curl_easy *data,
              strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
             continue;
         }
-        else if(check->proxyntlm.state != NTLMSTATE_NONE) {
+        else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
           /* Proxy connection is using NTLM auth but we don't want NTLM */
           continue;
         }
@@ -1386,9 +1305,9 @@ ConnectionExists(struct Curl_easy *data,
           chosen = check;
 
           if((wantNTLMhttp &&
-             (check->ntlm.state != NTLMSTATE_NONE)) ||
+             (check->http_ntlm_state != NTLMSTATE_NONE)) ||
               (wantProxyNTLMhttp &&
-               (check->proxyntlm.state != NTLMSTATE_NONE))) {
+               (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
             /* We must use this connection, no other */
             *force_reuse = TRUE;
             break;
@@ -1398,55 +1317,32 @@ ConnectionExists(struct Curl_easy *data,
           continue;
         }
 #endif
-        if(canpipe) {
-          /* We can pipeline if we want to. Let's continue looking for
-             the optimal connection to use, i.e the shortest pipe that is not
-             blacklisted. */
+        if(canmultiplex) {
+          /* We can multiplex if we want to. Let's continue looking for
+             the optimal connection to use. */
 
-          if(pipeLen == 0) {
+          if(!multiplexed) {
             /* We have the optimal connection. Let's stop looking. */
             chosen = check;
             break;
           }
 
-          /* We can't use the connection if the pipe is full */
-          if(max_pipe_len && (pipeLen >= max_pipe_len)) {
-            infof(data, "Pipe is full, skip (%zu)\n", pipeLen);
-            continue;
-          }
 #ifdef USE_NGHTTP2
           /* If multiplexed, make sure we don't go over concurrency limit */
           if(check->bits.multiplex) {
             /* Multiplexed connections can only be HTTP/2 for now */
             struct http_conn *httpc = &check->proto.httpc;
-            if(pipeLen >= httpc->settings.max_concurrent_streams) {
+            if(multiplexed >= httpc->settings.max_concurrent_streams) {
               infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n",
-                    pipeLen);
+                    multiplexed);
               continue;
             }
           }
 #endif
-          /* We can't use the connection if the pipe is penalized */
-          if(Curl_pipeline_penalized(data, check)) {
-            infof(data, "Penalized, skip\n");
-            continue;
-          }
-
-          if(max_pipe_len) {
-            if(pipeLen < best_pipe_len) {
-              /* This connection has a shorter pipe so far. We'll pick this
-                 and continue searching */
-              chosen = check;
-              best_pipe_len = pipeLen;
-              continue;
-            }
-          }
-          else {
-            /* When not pipelining (== multiplexed), we have a match here! */
-            chosen = check;
-            infof(data, "Multiplexed connection found!\n");
-            break;
-          }
+          /* When not multiplexed, we have a match here! */
+          chosen = check;
+          infof(data, "Multiplexed connection found!\n");
+          break;
         }
         else {
           /* We have found a connection. Let's stop searching. */
@@ -1460,11 +1356,11 @@ ConnectionExists(struct Curl_easy *data,
   if(chosen) {
     /* mark it as used before releasing the lock */
     chosen->data = data; /* own it! */
-    Curl_conncache_unlock(needle);
+    Curl_conncache_unlock(data);
     *usethis = chosen;
     return TRUE; /* yes, we found one to use! */
   }
-  Curl_conncache_unlock(needle);
+  Curl_conncache_unlock(data);
 
   if(foundPendingCandidate && data->set.pipewait) {
     infof(data,
@@ -1679,11 +1575,25 @@ static bool is_ASCII_name(const char *hostname)
 }
 
 /*
- * Perform any necessary IDN conversion of hostname
+ * Strip single trailing dot in the hostname,
+ * primarily for SNI and http host header.
  */
-static CURLcode fix_hostname(struct connectdata *conn, struct hostname *host)
+static void strip_trailing_dot(struct hostname *host)
 {
   size_t len;
+  if(!host || !host->name)
+    return;
+  len = strlen(host->name);
+  if(len && (host->name[len-1] == '.'))
+    host->name[len-1] = 0;
+}
+
+/*
+ * Perform any necessary IDN conversion of hostname
+ */
+static CURLcode idnconvert_hostname(struct connectdata *conn,
+                                    struct hostname *host)
+{
   struct Curl_easy *data = conn->data;
 
 #ifndef USE_LIBIDN2
@@ -1696,12 +1606,6 @@ static CURLcode fix_hostname(struct connectdata *conn, struct hostname *host)
   /* set the name we use to display the host name */
   host->dispname = host->name;
 
-  len = strlen(host->name);
-  if(len && (host->name[len-1] == '.'))
-    /* strip off a single trailing dot if present, primarily for SNI but
-       there's no use for it */
-    host->name[len-1] = 0;
-
   /* Check name for non-ASCII and convert hostname to ACE form if we can */
   if(!is_ASCII_name(host->name)) {
 #ifdef USE_LIBIDN2
@@ -1743,22 +1647,13 @@ static CURLcode fix_hostname(struct connectdata *conn, struct hostname *host)
     infof(data, "IDN support not present, can't parse Unicode domains\n");
 #endif
   }
-  {
-    char *hostp;
-    for(hostp = host->name; *hostp; hostp++) {
-      if(*hostp <= 32) {
-        failf(data, "Host name '%s' contains bad letter", host->name);
-        return CURLE_URL_MALFORMAT;
-      }
-    }
-  }
   return CURLE_OK;
 }
 
 /*
- * Frees data allocated by fix_hostname()
+ * Frees data allocated by idnconvert_hostname()
  */
-static void free_fixed_hostname(struct hostname *host)
+static void free_idnconverted_hostname(struct hostname *host)
 {
 #if defined(USE_LIBIDN2)
   if(host->encalloc) {
@@ -1849,16 +1744,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->http_proxy.proxytype = data->set.proxytype;
   conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
 
-#ifdef CURL_DISABLE_PROXY
-
-  conn->bits.proxy = FALSE;
-  conn->bits.httpproxy = FALSE;
-  conn->bits.socksproxy = FALSE;
-  conn->bits.proxy_user_passwd = FALSE;
-  conn->bits.tunnel_proxy = FALSE;
-
-#else /* CURL_DISABLE_PROXY */
-
+#if !defined(CURL_DISABLE_PROXY)
   /* note that these two proxy bits are now just on what looks to be
      requested, they may be altered down the road */
   conn->bits.proxy = (data->set.str[STRING_PROXY] &&
@@ -1879,13 +1765,13 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->bits.proxy_user_passwd =
     (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
   conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
-
 #endif /* CURL_DISABLE_PROXY */
 
   conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE;
+#ifndef CURL_DISABLE_FTP
   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
-
+#endif
   conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
   conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
   conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
@@ -1893,28 +1779,16 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
     data->set.proxy_ssl.primary.verifystatus;
   conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
   conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
-
   conn->ip_version = data->set.ipver;
+  conn->bits.connect_only = data->set.connect_only;
 
 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
     defined(NTLM_WB_ENABLED)
   conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
-  conn->ntlm_auth_hlpr_pid = 0;
-  conn->challenge_header = NULL;
-  conn->response_header = NULL;
 #endif
 
-  if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
-     !conn->master_buffer) {
-    /* Allocate master_buffer to be used for HTTP/1 pipelining */
-    conn->master_buffer = calloc(MASTERBUF_SIZE, sizeof(char));
-    if(!conn->master_buffer)
-      goto error;
-  }
-
-  /* Initialize the pipeline lists */
-  Curl_llist_init(&conn->send_pipe, (curl_llist_dtor) llist_dtor);
-  Curl_llist_init(&conn->recv_pipe, (curl_llist_dtor) llist_dtor);
+  /* Initialize the easy handle list */
+  Curl_llist_init(&conn->easyq, (curl_llist_dtor) llist_dtor);
 
 #ifdef HAVE_GSSAPI
   conn->data_prot = PROT_CLEAR;
@@ -1937,10 +1811,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   return conn;
   error:
 
-  Curl_llist_destroy(&conn->send_pipe, NULL);
-  Curl_llist_destroy(&conn->recv_pipe, NULL);
-
-  free(conn->master_buffer);
+  Curl_llist_destroy(&conn->easyq, NULL);
   free(conn->localdev);
 #ifdef USE_SSL
   free(conn->ssl_extra);
@@ -2023,10 +1894,16 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   CURLUcode uc;
   char *hostname;
 
-  Curl_up_free(data); /* cleanup previous leftovers first */
+  up_free(data); /* cleanup previous leftovers first */
 
   /* parse the URL */
-  uh = data->state.uh = curl_url();
+  if(data->set.uh) {
+    uh = data->state.uh = curl_url_dup(data->set.uh);
+  }
+  else {
+    uh = data->state.uh = curl_url();
+  }
+
   if(!uh)
     return CURLE_OUT_OF_MEMORY;
 
@@ -2043,14 +1920,18 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
     data->change.url_alloc = TRUE;
   }
 
-  uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
+  if(!data->set.uh) {
+    uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
                     CURLU_GUESS_SCHEME |
                     CURLU_NON_SUPPORT_SCHEME |
                     (data->set.disallow_username_in_url ?
                      CURLU_DISALLOW_USER : 0) |
                     (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
-  if(uc)
-    return Curl_uc_to_curlcode(uc);
+    if(uc) {
+      DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url));
+      return Curl_uc_to_curlcode(uc);
+    }
+  }
 
   uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
   if(uc)
@@ -2121,61 +2002,40 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
     hostname = (char *)"";
 
   if(hostname[0] == '[') {
-    /* This looks like an IPv6 address literal.  See if there is an address
+    /* This looks like an IPv6 address literal. See if there is an address
        scope. */
-    char *percent = strchr(++hostname, '%');
+    char *zoneid;
+    size_t hlen;
+    uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
     conn->bits.ipv6_ip = TRUE;
-    if(percent) {
-      unsigned int identifier_offset = 3;
+
+    /* cut off the brackets! */
+    hostname++;
+    hlen = strlen(hostname);
+    hostname[hlen - 1] = 0;
+    if(!uc && zoneid) {
       char *endp;
       unsigned long scope;
-      if(strncmp("%25", percent, 3) != 0) {
-        infof(data,
-              "Please URL encode %% as %%25, see RFC 6874.\n");
-        identifier_offset = 1;
-      }
-      scope = strtoul(percent + identifier_offset, &endp, 10);
-      if(*endp == ']') {
-        /* The address scope was well formed.  Knock it out of the
-           hostname. */
-        memmove(percent, endp, strlen(endp) + 1);
+      scope = strtoul(zoneid, &endp, 10);
+      if(!*endp && (scope < UINT_MAX)) {
+        /* A plain number, use it direcly as a scope id. */
         conn->scope_id = (unsigned int)scope;
       }
+#ifdef HAVE_IF_NAMETOINDEX
       else {
         /* Zone identifier is not numeric */
-#if defined(HAVE_NET_IF_H) && defined(IFNAMSIZ) && defined(HAVE_IF_NAMETOINDEX)
-        char ifname[IFNAMSIZ + 2];
-        char *square_bracket;
         unsigned int scopeidx = 0;
-        strncpy(ifname, percent + identifier_offset, IFNAMSIZ + 2);
-        /* Ensure nullbyte termination */
-        ifname[IFNAMSIZ + 1] = '\0';
-        square_bracket = strchr(ifname, ']');
-        if(square_bracket) {
-          /* Remove ']' */
-          *square_bracket = '\0';
-          scopeidx = if_nametoindex(ifname);
-          if(scopeidx == 0) {
-            infof(data, "Invalid network interface: %s; %s\n", ifname,
-                  strerror(errno));
-          }
-        }
-        if(scopeidx > 0) {
-          char *p = percent + identifier_offset + strlen(ifname);
-
-          /* Remove zone identifier from hostname */
-          memmove(percent, p, strlen(p) + 1);
-          conn->scope_id = scopeidx;
-        }
+        scopeidx = if_nametoindex(zoneid);
+        if(!scopeidx)
+          infof(data, "Invalid zoneid id: %s; %s\n", zoneid,
+                strerror(errno));
         else
-#endif /* HAVE_NET_IF_H && IFNAMSIZ */
-          infof(data, "Invalid IPv6 address format\n");
+          conn->scope_id = scopeidx;
+
       }
+#endif /* HAVE_IF_NAMETOINDEX */
+      free(zoneid);
     }
-    percent = strchr(hostname, ']');
-    if(percent)
-      /* terminate IPv6 numerical at end bracket */
-      *percent = 0;
   }
 
   /* make sure the connect struct gets its own copy of the host name */
@@ -2191,6 +2051,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   return CURLE_OK;
 }
 
+
 /*
  * If we're doing a resumed transfer, we need to setup our stuff
  * properly.
@@ -2437,46 +2298,55 @@ static CURLcode parse_proxy(struct Curl_easy *data,
                             struct connectdata *conn, char *proxy,
                             curl_proxytype proxytype)
 {
-  char *prox_portno;
-  char *endofprot;
-
-  /* We use 'proxyptr' to point to the proxy name from now on... */
-  char *proxyptr;
   char *portptr;
-  char *atsign;
   long port = -1;
   char *proxyuser = NULL;
   char *proxypasswd = NULL;
+  char *host;
   bool sockstype;
+  CURLUcode uc;
+  struct proxy_info *proxyinfo;
+  CURLU *uhp = curl_url();
+  CURLcode result = CURLE_OK;
+  char *scheme = NULL;
 
-  /* We do the proxy host string parsing here. We want the host name and the
-   * port name. Accept a protocol:// prefix
-   */
+  /* When parsing the proxy, allowing non-supported schemes since we have
+     these made up ones for proxies. Guess scheme for URLs without it. */
+  uc = curl_url_set(uhp, CURLUPART_URL, proxy,
+                    CURLU_NON_SUPPORT_SCHEME|CURLU_GUESS_SCHEME);
+  if(!uc) {
+    /* parsed okay as a URL */
+    uc = curl_url_get(uhp, CURLUPART_SCHEME, &scheme, 0);
+    if(uc) {
+      result = CURLE_OUT_OF_MEMORY;
+      goto error;
+    }
 
-  /* Parse the protocol part if present */
-  endofprot = strstr(proxy, "://");
-  if(endofprot) {
-    proxyptr = endofprot + 3;
-    if(checkprefix("https", proxy))
+    if(strcasecompare("https", scheme))
       proxytype = CURLPROXY_HTTPS;
-    else if(checkprefix("socks5h", proxy))
+    else if(strcasecompare("socks5h", scheme))
       proxytype = CURLPROXY_SOCKS5_HOSTNAME;
-    else if(checkprefix("socks5", proxy))
+    else if(strcasecompare("socks5", scheme))
       proxytype = CURLPROXY_SOCKS5;
-    else if(checkprefix("socks4a", proxy))
+    else if(strcasecompare("socks4a", scheme))
       proxytype = CURLPROXY_SOCKS4A;
-    else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
+    else if(strcasecompare("socks4", scheme) ||
+            strcasecompare("socks", scheme))
       proxytype = CURLPROXY_SOCKS4;
-    else if(checkprefix("http:", proxy))
+    else if(strcasecompare("http", scheme))
       ; /* leave it as HTTP or HTTP/1.0 */
     else {
       /* Any other xxx:// reject! */
       failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
-      return CURLE_COULDNT_CONNECT;
+      result = CURLE_COULDNT_CONNECT;
+      goto error;
     }
   }
-  else
-    proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
+  else {
+    failf(data, "Unsupported proxy syntax in \'%s\'", proxy);
+    result = CURLE_COULDNT_RESOLVE_PROXY;
+    goto error;
+  }
 
 #ifdef USE_SSL
   if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
@@ -2484,93 +2354,44 @@ static CURLcode parse_proxy(struct Curl_easy *data,
     if(proxytype == CURLPROXY_HTTPS) {
       failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
                   "HTTPS-proxy support.", proxy);
-      return CURLE_NOT_BUILT_IN;
+      result = CURLE_NOT_BUILT_IN;
+      goto error;
     }
 
-  sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
-              proxytype == CURLPROXY_SOCKS5 ||
-              proxytype == CURLPROXY_SOCKS4A ||
-              proxytype == CURLPROXY_SOCKS4;
-
-  /* Is there a username and password given in this proxy url? */
-  atsign = strchr(proxyptr, '@');
-  if(atsign) {
-    CURLcode result =
-      Curl_parse_login_details(proxyptr, atsign - proxyptr,
-                               &proxyuser, &proxypasswd, NULL);
-    if(result)
-      return result;
-    proxyptr = atsign + 1;
-  }
+  sockstype =
+    proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
+    proxytype == CURLPROXY_SOCKS5 ||
+    proxytype == CURLPROXY_SOCKS4A ||
+    proxytype == CURLPROXY_SOCKS4;
 
-  /* start scanning for port number at this point */
-  portptr = proxyptr;
+  proxyinfo = sockstype ? &conn->socks_proxy : &conn->http_proxy;
+  proxyinfo->proxytype = proxytype;
 
-  /* detect and extract RFC6874-style IPv6-addresses */
-  if(*proxyptr == '[') {
-    char *ptr = ++proxyptr; /* advance beyond the initial bracket */
-    while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
-      ptr++;
-    if(*ptr == '%') {
-      /* There might be a zone identifier */
-      if(strncmp("%25", ptr, 3))
-        infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
-      ptr++;
-      /* Allow unreserved characters as defined in RFC 3986 */
-      while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
-                     (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
-        ptr++;
+  /* Is there a username and password given in this proxy url? */
+  curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE);
+  curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE);
+  if(proxyuser || proxypasswd) {
+    Curl_safefree(proxyinfo->user);
+    proxyinfo->user = proxyuser;
+    Curl_safefree(proxyinfo->passwd);
+    if(!proxypasswd) {
+      proxypasswd = strdup("");
+      if(!proxypasswd) {
+        result = CURLE_OUT_OF_MEMORY;
+        goto error;
+      }
     }
-    if(*ptr == ']')
-      /* yeps, it ended nicely with a bracket as well */
-      *ptr++ = 0;
-    else
-      infof(data, "Invalid IPv6 address format\n");
-    portptr = ptr;
-    /* Note that if this didn't end with a bracket, we still advanced the
-     * proxyptr first, but I can't see anything wrong with that as no host
-     * name nor a numeric can legally start with a bracket.
-     */
+    proxyinfo->passwd = proxypasswd;
+    conn->bits.proxy_user_passwd = TRUE; /* enable it */
   }
 
-  /* Get port number off proxy.server.com:1080 */
-  prox_portno = strchr(portptr, ':');
-  if(prox_portno) {
-    char *endp = NULL;
+  curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
 
-    *prox_portno = 0x0; /* cut off number from host name */
-    prox_portno ++;
-    /* now set the local port number */
-    port = strtol(prox_portno, &endp, 10);
-    if((endp && *endp && (*endp != '/') && (*endp != ' ')) ||
-       (port < 0) || (port > 65535)) {
-      /* meant to detect for example invalid IPv6 numerical addresses without
-         brackets: "2a00:fac0:a000::7:13". Accept a trailing slash only
-         because we then allow "URL style" with the number followed by a
-         slash, used in curl test cases already. Space is also an acceptable
-         terminating symbol. */
-      infof(data, "No valid port number in proxy string (%s)\n",
-            prox_portno);
-    }
-    else
-      conn->port = port;
+  if(portptr) {
+    port = strtol(portptr, NULL, 10);
+    free(portptr);
   }
   else {
-    if(proxyptr[0]=='/') {
-      /* If the first character in the proxy string is a slash, fail
-         immediately. The following code will otherwise clear the string which
-         will lead to code running as if no proxy was set! */
-      Curl_safefree(proxyuser);
-      Curl_safefree(proxypasswd);
-      return CURLE_COULDNT_RESOLVE_PROXY;
-    }
-
-    /* without a port number after the host name, some people seem to use
-       a slash so we strip everything from the first slash */
-    atsign = strchr(proxyptr, '/');
-    if(atsign)
-      *atsign = '\0'; /* cut off path part from host name */
-
     if(data->set.proxyport)
       /* None given in the proxy string, then get the default one if it is
          given */
@@ -2582,57 +2403,32 @@ static CURLcode parse_proxy(struct Curl_easy *data,
         port = CURL_DEFAULT_PROXY_PORT;
     }
   }
-
-  if(*proxyptr) {
-    struct proxy_info *proxyinfo =
-      sockstype ? &conn->socks_proxy : &conn->http_proxy;
-    proxyinfo->proxytype = proxytype;
-
-    if(proxyuser) {
-      /* found user and password, rip them out.  note that we are unescaping
-         them, as there is otherwise no way to have a username or password
-         with reserved characters like ':' in them. */
-      Curl_safefree(proxyinfo->user);
-      proxyinfo->user = curl_easy_unescape(data, proxyuser, 0, NULL);
-      Curl_safefree(proxyuser);
-
-      if(!proxyinfo->user) {
-        Curl_safefree(proxypasswd);
-        return CURLE_OUT_OF_MEMORY;
-      }
-
-      Curl_safefree(proxyinfo->passwd);
-      if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
-        proxyinfo->passwd = curl_easy_unescape(data, proxypasswd, 0, NULL);
-      else
-        proxyinfo->passwd = strdup("");
-      Curl_safefree(proxypasswd);
-
-      if(!proxyinfo->passwd)
-        return CURLE_OUT_OF_MEMORY;
-
-      conn->bits.proxy_user_passwd = TRUE; /* enable it */
-    }
-
-    if(port >= 0) {
-      proxyinfo->port = port;
-      if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
-        conn->port = port;
-    }
-
-    /* now, clone the cleaned proxy host name */
-    Curl_safefree(proxyinfo->host.rawalloc);
-    proxyinfo->host.rawalloc = strdup(proxyptr);
-    proxyinfo->host.name = proxyinfo->host.rawalloc;
-
-    if(!proxyinfo->host.rawalloc)
-      return CURLE_OUT_OF_MEMORY;
+  if(port >= 0) {
+    proxyinfo->port = port;
+    if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
+      conn->port = port;
   }
 
-  Curl_safefree(proxyuser);
-  Curl_safefree(proxypasswd);
+  /* now, clone the proxy host name */
+  uc = curl_url_get(uhp, CURLUPART_HOST, &host, CURLU_URLDECODE);
+  if(uc) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto error;
+  }
+  Curl_safefree(proxyinfo->host.rawalloc);
+  proxyinfo->host.rawalloc = host;
+  if(host[0] == '[') {
+    /* this is a numerical IPv6, strip off the brackets */
+    size_t len = strlen(host);
+    host[len-1] = 0; /* clear the trailing bracket */
+    host++;
+  }
+  proxyinfo->host.name = host;
 
-  return CURLE_OK;
+  error:
+  free(scheme);
+  curl_url_cleanup(uhp);
+  return result;
 }
 
 /*
@@ -2979,7 +2775,7 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
     char portbuf[16];
     CURLUcode uc;
     conn->remote_port = (unsigned short)data->set.use_port;
-    snprintf(portbuf, sizeof(portbuf), "%u", conn->remote_port);
+    msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port);
     uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
     if(uc)
       return CURLE_OUT_OF_MEMORY;
@@ -2999,6 +2795,20 @@ static CURLcode override_login(struct Curl_easy *data,
   bool user_changed = FALSE;
   bool passwd_changed = FALSE;
   CURLUcode uc;
+
+  if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
+    /* ignore user+password in the URL */
+    if(*userp) {
+      Curl_safefree(*userp);
+      user_changed = TRUE;
+    }
+    if(*passwdp) {
+      Curl_safefree(*passwdp);
+      passwd_changed = TRUE;
+    }
+    conn->bits.user_passwd = FALSE; /* disable user+password */
+  }
+
   if(data->set.str[STRING_USERNAME]) {
     free(*userp);
     *userp = strdup(data->set.str[STRING_USERNAME]);
@@ -3025,16 +2835,15 @@ static CURLcode override_login(struct Curl_easy *data,
   }
 
   conn->bits.netrc = FALSE;
-  if(data->set.use_netrc != CURL_NETRC_IGNORED) {
-    char *nuser = NULL;
-    char *npasswd = NULL;
+  if(data->set.use_netrc != CURL_NETRC_IGNORED &&
+      (!*userp || !**userp || !*passwdp || !**passwdp)) {
+    bool netrc_user_changed = FALSE;
+    bool netrc_passwd_changed = FALSE;
     int ret;
 
-    if(data->set.use_netrc == CURL_NETRC_OPTIONAL)
-      nuser = *userp; /* to separate otherwise identical machines */
-
     ret = Curl_parsenetrc(conn->host.name,
-                          &nuser, &npasswd,
+                          userp, passwdp,
+                          &netrc_user_changed, &netrc_passwd_changed,
                           data->set.str[STRING_NETRC_FILE]);
     if(ret > 0) {
       infof(data, "Couldn't find host %s in the "
@@ -3051,31 +2860,11 @@ static CURLcode override_login(struct Curl_easy *data,
       conn->bits.netrc = TRUE;
       conn->bits.user_passwd = TRUE; /* enable user+password */
 
-      if(data->set.use_netrc == CURL_NETRC_OPTIONAL) {
-        /* prefer credentials outside netrc */
-        if(nuser && !*userp) {
-          free(*userp);
-          *userp = nuser;
-          user_changed = TRUE;
-        }
-        if(npasswd && !*passwdp) {
-          free(*passwdp);
-          *passwdp = npasswd;
-          passwd_changed = TRUE;
-        }
+      if(netrc_user_changed) {
+        user_changed = TRUE;
       }
-      else {
-        /* prefer netrc credentials */
-        if(nuser) {
-          free(*userp);
-          *userp = nuser;
-          user_changed = TRUE;
-        }
-        if(npasswd) {
-          free(*passwdp);
-          *passwdp = npasswd;
-          passwd_changed = TRUE;
-        }
+      if(netrc_passwd_changed) {
+        passwd_changed = TRUE;
       }
     }
   }
@@ -3351,6 +3140,34 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
     conn_to_host = conn_to_host->next;
   }
 
+#ifdef USE_ALTSVC
+  if(data->asi && !host && (port == -1) &&
+     (conn->handler->protocol == CURLPROTO_HTTPS)) {
+    /* no connect_to match, try alt-svc! */
+    const char *nhost;
+    int nport;
+    enum alpnid nalpnid;
+    bool hit;
+    host = conn->host.rawalloc;
+    hit = Curl_altsvc_lookup(data->asi,
+                             ALPN_h1, host, conn->remote_port, /* from */
+                             &nalpnid, &nhost, &nport /* to */);
+    if(hit) {
+      char *hostd = strdup((char *)nhost);
+      if(!hostd)
+        return CURLE_OUT_OF_MEMORY;
+      conn->conn_to_host.rawalloc = hostd;
+      conn->conn_to_host.name = hostd;
+      conn->bits.conn_to_host = TRUE;
+      conn->conn_to_port = nport;
+      conn->bits.conn_to_port = TRUE;
+      infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n",
+            Curl_alpnid2str(ALPN_h1), host, conn->remote_port,
+            Curl_alpnid2str(nalpnid), hostd, nport);
+    }
+  }
+#endif
+
   return result;
 }
 
@@ -3364,12 +3181,14 @@ static CURLcode resolve_server(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
   timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
 
+  DEBUGASSERT(conn);
+  DEBUGASSERT(data);
   /*************************************************************
    * Resolve the name of the server or proxy
    *************************************************************/
   if(conn->bits.reuse)
     /* We're reusing the connection - no need to resolve anything, and
-       fix_hostname() was called already in create_conn() for the re-use
+       idnconvert_hostname() was called already in create_conn() for the re-use
        case. */
     *async = FALSE;
 
@@ -3424,7 +3243,10 @@ static CURLcode resolve_server(struct Curl_easy *data,
         conn->port = conn->remote_port;
 
       /* Resolve target host right on */
-      rc = Curl_resolv_timeout(conn, connhost->name, (int)conn->port,
+      conn->hostname_resolve = strdup(connhost->name);
+      if(!conn->hostname_resolve)
+        return CURLE_OUT_OF_MEMORY;
+      rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
                                &hostaddr, timeout_ms);
       if(rc == CURLRESOLV_PENDING)
         *async = TRUE;
@@ -3445,7 +3267,10 @@ static CURLcode resolve_server(struct Curl_easy *data,
         &conn->socks_proxy.host : &conn->http_proxy.host;
 
       /* resolve proxy */
-      rc = Curl_resolv_timeout(conn, host->name, (int)conn->port,
+      conn->hostname_resolve = strdup(host->name);
+      if(!conn->hostname_resolve)
+        return CURLE_OUT_OF_MEMORY;
+      rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
                                &hostaddr, timeout_ms);
 
       if(rc == CURLRESOLV_PENDING)
@@ -3475,8 +3300,8 @@ static CURLcode resolve_server(struct Curl_easy *data,
 static void reuse_conn(struct connectdata *old_conn,
                        struct connectdata *conn)
 {
-  free_fixed_hostname(&old_conn->http_proxy.host);
-  free_fixed_hostname(&old_conn->socks_proxy.host);
+  free_idnconverted_hostname(&old_conn->http_proxy.host);
+  free_idnconverted_hostname(&old_conn->socks_proxy.host);
 
   free(old_conn->http_proxy.host.rawalloc);
   free(old_conn->socks_proxy.host.rawalloc);
@@ -3520,14 +3345,18 @@ static void reuse_conn(struct connectdata *old_conn,
 
   /* host can change, when doing keepalive with a proxy or if the case is
      different this time etc */
-  free_fixed_hostname(&conn->host);
-  free_fixed_hostname(&conn->conn_to_host);
+  free_idnconverted_hostname(&conn->host);
+  free_idnconverted_hostname(&conn->conn_to_host);
   Curl_safefree(conn->host.rawalloc);
   Curl_safefree(conn->conn_to_host.rawalloc);
   conn->host = old_conn->host;
   conn->conn_to_host = old_conn->conn_to_host;
   conn->conn_to_port = old_conn->conn_to_port;
   conn->remote_port = old_conn->remote_port;
+  Curl_safefree(conn->hostname_resolve);
+
+  conn->hostname_resolve = old_conn->hostname_resolve;
+  old_conn->hostname_resolve = NULL;
 
   /* persist connection info in session handle */
   Curl_persistconninfo(conn);
@@ -3545,11 +3374,7 @@ static void reuse_conn(struct connectdata *old_conn,
   Curl_safefree(old_conn->http_proxy.passwd);
   Curl_safefree(old_conn->socks_proxy.passwd);
   Curl_safefree(old_conn->localdev);
-
-  Curl_llist_destroy(&old_conn->send_pipe, NULL);
-  Curl_llist_destroy(&old_conn->recv_pipe, NULL);
-
-  Curl_safefree(old_conn->master_buffer);
+  Curl_llist_destroy(&old_conn->easyq, NULL);
 
 #ifdef USE_UNIX_SOCKETS
   Curl_safefree(old_conn->unix_domain_socket);
@@ -3587,6 +3412,7 @@ static CURLcode create_conn(struct Curl_easy *data,
   size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
 
   *async = FALSE;
+  *in_connect = NULL;
 
   /*************************************************************
    * Check input data
@@ -3677,30 +3503,30 @@ static CURLcode create_conn(struct Curl_easy *data,
     goto out;
 
   /*************************************************************
-   * IDN-fix the hostnames
+   * IDN-convert the hostnames
    *************************************************************/
-  result = fix_hostname(conn, &conn->host);
+  result = idnconvert_hostname(conn, &conn->host);
   if(result)
     goto out;
   if(conn->bits.conn_to_host) {
-    result = fix_hostname(conn, &conn->conn_to_host);
+    result = idnconvert_hostname(conn, &conn->conn_to_host);
     if(result)
       goto out;
   }
   if(conn->bits.httpproxy) {
-    result = fix_hostname(conn, &conn->http_proxy.host);
+    result = idnconvert_hostname(conn, &conn->http_proxy.host);
     if(result)
       goto out;
   }
   if(conn->bits.socksproxy) {
-    result = fix_hostname(conn, &conn->socks_proxy.host);
+    result = idnconvert_hostname(conn, &conn->socks_proxy.host);
     if(result)
       goto out;
   }
 
   /*************************************************************
    * Check whether the host and the "connect to host" are equal.
-   * Do this after the hostnames have been IDN-fixed.
+   * Do this after the hostnames have been IDN-converted.
    *************************************************************/
   if(conn->bits.conn_to_host &&
      strcasecompare(conn->conn_to_host.name, conn->host.name)) {
@@ -3752,7 +3578,6 @@ static CURLcode create_conn(struct Curl_easy *data,
 
     /* Setup a "faked" transfer that'll do nothing */
     if(!result) {
-      conn->data = data;
       conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
 
       result = Curl_conncache_add_conn(data->state.conn_cache, conn);
@@ -3769,9 +3594,8 @@ static CURLcode create_conn(struct Curl_easy *data,
         (void)conn->handler->done(conn, result, FALSE);
         goto out;
       }
-
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
-                          -1, NULL); /* no upload */
+      Curl_attach_connnection(data, conn);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
     }
 
     /* since we skip do_init() */
@@ -3857,19 +3681,20 @@ static CURLcode create_conn(struct Curl_easy *data,
   /* reuse_fresh is TRUE if we are told to use a new connection by force, but
      we only acknowledge this option if this is not a re-used connection
      already (which happens due to follow-location or during a HTTP
-     authentication phase). */
-  if(data->set.reuse_fresh && !data->state.this_is_a_follow)
+     authentication phase). CONNECT_ONLY transfers also refuse reuse. */
+  if((data->set.reuse_fresh && !data->state.this_is_a_follow) ||
+     data->set.connect_only)
     reuse = FALSE;
   else
     reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
 
   /* If we found a reusable connection that is now marked as in use, we may
-     still want to open a new connection if we are pipelining. */
-  if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) {
-    size_t pipelen = conn_temp->send_pipe.size + conn_temp->recv_pipe.size;
-    if(pipelen > 0) {
-      infof(data, "Found connection %ld, with requests in the pipe (%zu)\n",
-            conn_temp->connection_id, pipelen);
+     still want to open a new connection if we are multiplexing. */
+  if(reuse && !force_reuse && IsMultiplexingPossible(data, conn_temp)) {
+    size_t multiplexed = CONN_INUSE(conn_temp);
+    if(multiplexed > 0) {
+      infof(data, "Found connection %ld, with %zu requests on it\n",
+            conn_temp->connection_id, multiplexed);
 
       if(Curl_conncache_bundle_size(conn_temp) < max_host_connections &&
          Curl_conncache_size(data) < max_total_connections) {
@@ -3919,7 +3744,7 @@ static CURLcode create_conn(struct Curl_easy *data,
     }
 
     if(waitpipe)
-      /* There is a connection that *might* become usable for pipelining
+      /* There is a connection that *might* become usable for multiplexing
          "soon", and we wait for that */
       connections_available = FALSE;
     else {
@@ -3933,7 +3758,7 @@ static CURLcode create_conn(struct Curl_easy *data,
 
         /* The bundle is full. Extract the oldest connection. */
         conn_candidate = Curl_conncache_extract_bundle(data, bundle);
-        Curl_conncache_unlock(conn);
+        Curl_conncache_unlock(data);
 
         if(conn_candidate)
           (void)Curl_disconnect(data, conn_candidate,
@@ -3945,7 +3770,7 @@ static CURLcode create_conn(struct Curl_easy *data,
         }
       }
       else
-        Curl_conncache_unlock(conn);
+        Curl_conncache_unlock(data);
 
     }
 
@@ -4028,6 +3853,15 @@ static CURLcode create_conn(struct Curl_easy *data,
    *************************************************************/
   result = resolve_server(data, conn, async);
 
+  /* Strip trailing dots. resolve_server copied the name. */
+  strip_trailing_dot(&conn->host);
+  if(conn->bits.httpproxy)
+    strip_trailing_dot(&conn->http_proxy.host);
+  if(conn->bits.socksproxy)
+    strip_trailing_dot(&conn->socks_proxy.host);
+  if(conn->bits.conn_to_host)
+    strip_trailing_dot(&conn->conn_to_host);
+
 out:
   return result;
 }
@@ -4105,11 +3939,11 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
 }
 
 CURLcode Curl_connect(struct Curl_easy *data,
-                      struct connectdata **in_connect,
                       bool *asyncp,
                       bool *protocol_done)
 {
   CURLcode result;
+  struct connectdata *conn;
 
   *asyncp = FALSE; /* assume synchronous resolves by default */
 
@@ -4119,30 +3953,31 @@ CURLcode Curl_connect(struct Curl_easy *data,
   data->req.maxdownload = -1;
 
   /* call the stuff that needs to be called */
-  result = create_conn(data, in_connect, asyncp);
+  result = create_conn(data, &conn, asyncp);
 
   if(!result) {
-    if(CONN_INUSE(*in_connect))
-      /* pipelining */
+    if(CONN_INUSE(conn))
+      /* multiplexed */
       *protocol_done = TRUE;
     else if(!*asyncp) {
       /* DNS resolution is done: that's either because this is a reused
          connection, in which case DNS was unnecessary, or because DNS
          really did finish already (synch resolver/fast async resolve) */
-      result = Curl_setup_conn(*in_connect, protocol_done);
+      result = Curl_setup_conn(conn, protocol_done);
     }
   }
 
   if(result == CURLE_NO_CONNECTION_AVAILABLE) {
-    *in_connect = NULL;
     return result;
   }
-  else if(result && *in_connect) {
+  else if(result && conn) {
     /* We're not allowed to return failure with memory left allocated in the
        connectdata struct, free those here */
-    Curl_disconnect(data, *in_connect, TRUE);
-    *in_connect = NULL; /* return a NULL */
+    Curl_disconnect(data, conn, TRUE);
   }
+  else if(!result && !data->conn)
+    /* FILE: transfers already have the connection attached */
+    Curl_attach_connnection(data, conn);
 
   return result;
 }
diff --git a/lib/url.h b/lib/url.h
index 095d638..4db9e86 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -52,8 +52,7 @@ void Curl_freeset(struct Curl_easy * data);
 void Curl_up_free(struct Curl_easy *data);
 CURLcode Curl_uc_to_curlcode(CURLUcode uc);
 CURLcode Curl_close(struct Curl_easy *data); /* opposite of curl_open() */
-CURLcode Curl_connect(struct Curl_easy *, struct connectdata **,
-                      bool *async, bool *protocol_connect);
+CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect);
 CURLcode Curl_disconnect(struct Curl_easy *data,
                          struct connectdata *, bool dead_connection);
 CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
@@ -72,14 +71,7 @@ int Curl_doing_getsock(struct connectdata *conn,
 CURLcode Curl_parse_login_details(const char *login, const size_t len,
                                   char **userptr, char **passwdptr,
                                   char **optionsptr);
-
-int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
-                                  struct curl_llist *pipeline);
-/* remove the specified connection from all (possible) pipelines and related
-   queues */
-void Curl_getoff_all_pipelines(struct Curl_easy *data,
-                               struct connectdata *conn);
-
+void Curl_close_connections(struct Curl_easy *data);
 CURLcode Curl_upkeep(struct conncache *conn_cache, void *data);
 
 const struct Curl_handler *Curl_builtin_scheme(const char *scheme);
diff --git a/lib/urlapi-int.h b/lib/urlapi-int.h
index a57d2e2..5f059c2 100644
--- a/lib/urlapi-int.h
+++ b/lib/urlapi-int.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,12 +22,16 @@
  *
  ***************************************************************************/
 #include "curl_setup.h"
-/* scheme is not URL encoded, the longest libcurl supported ones are 6
-   letters */
-#define MAX_SCHEME_LEN 8
+/* scheme is not URL encoded, the longest libcurl supported ones are... */
+#define MAX_SCHEME_LEN 40
 
 bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen);
 char *Curl_concat_url(const char *base, const char *relurl);
 size_t Curl_strlen_url(const char *url, bool relative);
 void Curl_strcpy_url(char *output, const char *url, bool relative);
+
+#ifdef DEBUGBUILD
+CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname);
+#endif
+
 #endif /* HEADER_CURL_URLAPI_INT_H */
diff --git a/lib/urlapi.c b/lib/urlapi.c
index c53e523..d07e4f5 100644
--- a/lib/urlapi.c
+++ b/lib/urlapi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -56,6 +56,7 @@ struct Curl_URL {
   char *password;
   char *options; /* IMAP only? */
   char *host;
+  char *zoneid; /* for numerical IPv6 addresses */
   char *port;
   char *path;
   char *query;
@@ -74,6 +75,7 @@ static void free_urlhandle(struct Curl_URL *u)
   free(u->password);
   free(u->options);
   free(u->host);
+  free(u->zoneid);
   free(u->port);
   free(u->path);
   free(u->query);
@@ -135,7 +137,7 @@ static bool urlchar_needs_escaping(int c)
  * URL encoding should be skipped for host names, otherwise IDN resolution
  * will fail.
  */
-size_t Curl_strlen_url(const char *url, bool relative)
+static size_t strlen_url(const char *url, bool relative)
 {
   const unsigned char *ptr;
   size_t newlen = 0;
@@ -177,7 +179,7 @@ size_t Curl_strlen_url(const char *url, bool relative)
  * URL encoding should be skipped for host names, otherwise IDN resolution
  * will fail.
  */
-void Curl_strcpy_url(char *output, const char *url, bool relative)
+static void strcpy_url(char *output, const char *url, bool relative)
 {
   /* we must add this with whitespace-replacing */
   bool left = TRUE;
@@ -203,7 +205,7 @@ void Curl_strcpy_url(char *output, const char *url, bool relative)
       /* FALLTHROUGH */
     default:
       if(urlchar_needs_escaping(*iptr)) {
-        snprintf(optr, 4, "%%%02x", *iptr);
+        msnprintf(optr, 4, "%%%02x", *iptr);
         optr += 3;
       }
       else
@@ -238,7 +240,7 @@ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
 #endif
   for(i = 0; i < buflen && url[i]; ++i) {
     char s = url[i];
-    if(s == ':') {
+    if((s == ':') && (url[i + 1] == '/')) {
       if(buf)
         buf[i] = 0;
       return TRUE;
@@ -262,7 +264,7 @@ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
  * The returned pointer must be freed by the caller unless NULL
  * (returns NULL on out of memory).
  */
-char *Curl_concat_url(const char *base, const char *relurl)
+static char *concat_url(const char *base, const char *relurl)
 {
   /***
    TRY to append this new path to the old URL
@@ -386,7 +388,7 @@ char *Curl_concat_url(const char *base, const char *relurl)
      letter we replace each space with %20 while it is replaced with '+'
      on the right side of the '?' letter.
   */
-  newlen = Curl_strlen_url(useurl, !host_changed);
+  newlen = strlen_url(useurl, !host_changed);
 
   urllen = strlen(url_clone);
 
@@ -408,7 +410,7 @@ char *Curl_concat_url(const char *base, const char *relurl)
     newest[urllen++]='/';
 
   /* then append the new piece on the right side */
-  Curl_strcpy_url(&newest[urllen], useurl, !host_changed);
+  strcpy_url(&newest[urllen], useurl, !host_changed);
 
   free(url_clone);
 
@@ -488,19 +490,40 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
   return result;
 }
 
-static CURLUcode parse_port(struct Curl_URL *u, char *hostname)
+UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname)
 {
-  char *portptr;
+  char *portptr = NULL;
   char endbracket;
   int len;
 
-  if((1 == sscanf(hostname, "[%*45[0123456789abcdefABCDEF:.%%]%c%n",
-                  &endbracket, &len)) &&
-     (']' == endbracket)) {
-    /* this is a RFC2732-style specified IP-address */
-    portptr = &hostname[len];
-    if (*portptr != ':')
+  /*
+   * Find the end of an IPv6 address, either on the ']' ending bracket or
+   * a percent-encoded zone index.
+   */
+  if(1 == sscanf(hostname, "[%*45[0123456789abcdefABCDEF:.]%c%n",
+                 &endbracket, &len)) {
+    if(']' == endbracket)
+      portptr = &hostname[len];
+    else if('%' == endbracket) {
+      int zonelen = len;
+      if(1 == sscanf(hostname + zonelen, "%*[^]]%c%n", &endbracket, &len)) {
+        if(']' != endbracket)
+          return CURLUE_MALFORMED_INPUT;
+        portptr = &hostname[--zonelen + len + 1];
+      }
+      else
+        return CURLUE_MALFORMED_INPUT;
+    }
+    else
       return CURLUE_MALFORMED_INPUT;
+
+    /* this is a RFC2732-style specified IP-address */
+    if(portptr && *portptr) {
+      if(*portptr != ':')
+        return CURLUE_MALFORMED_INPUT;
+    }
+    else
+      portptr = NULL;
   }
   else
     portptr = strchr(hostname, ':');
@@ -510,6 +533,14 @@ static CURLUcode parse_port(struct Curl_URL *u, char *hostname)
     long port;
     char portbuf[7];
 
+    /* Browser behavior adaptation. If there's a colon with no digits after,
+       just cut off the name there which makes us ignore the colon and just
+       use the default port. Firefox, Chrome and Safari all do that. */
+    if(!portptr[1]) {
+      *portptr = '\0';
+      return CURLUE_OK;
+    }
+
     if(!ISDIGIT(portptr[1]))
       return CURLUE_BAD_PORT_NUMBER;
 
@@ -523,22 +554,14 @@ static CURLUcode parse_port(struct Curl_URL *u, char *hostname)
     if(rest[0])
       return CURLUE_BAD_PORT_NUMBER;
 
-    if(rest != &portptr[1]) {
-      *portptr++ = '\0'; /* cut off the name there */
-      *rest = 0;
-      /* generate a new to get rid of leading zeroes etc */
-      snprintf(portbuf, sizeof(portbuf), "%ld", port);
-      u->portnum = port;
-      u->port = strdup(portbuf);
-      if(!u->port)
-        return CURLUE_OUT_OF_MEMORY;
-    }
-    else {
-      /* Browser behavior adaptation. If there's a colon with no digits after,
-         just cut off the name there which makes us ignore the colon and just
-         use the default port. Firefox and Chrome both do that. */
-      *portptr = '\0';
-    }
+    *portptr++ = '\0'; /* cut off the name there */
+    *rest = 0;
+    /* generate a new port number string to get rid of leading zeroes etc */
+    msnprintf(portbuf, sizeof(portbuf), "%ld", port);
+    u->portnum = port;
+    u->port = strdup(portbuf);
+    if(!u->port)
+      return CURLUE_OUT_OF_MEMORY;
   }
 
   return CURLUE_OK;
@@ -547,15 +570,15 @@ static CURLUcode parse_port(struct Curl_URL *u, char *hostname)
 /* scan for byte values < 31 or 127 */
 static CURLUcode junkscan(char *part)
 {
-  char badbytes[]={
-    /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    0x7f,
-    0x00 /* zero terminate */
-  };
   if(part) {
+    static const char badbytes[]={
+      /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+      0x7f,
+      0x00 /* zero terminate */
+    };
     size_t n = strlen(part);
     size_t nfine = strcspn(part, badbytes);
     if(nfine != n)
@@ -566,25 +589,45 @@ static CURLUcode junkscan(char *part)
   return CURLUE_OK;
 }
 
-static CURLUcode hostname_check(char *hostname, unsigned int flags)
+static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
 {
   const char *l = NULL; /* accepted characters */
   size_t len;
   size_t hlen = strlen(hostname);
-  (void)flags;
 
   if(hostname[0] == '[') {
     hostname++;
-    l = "0123456789abcdefABCDEF::.%";
+    l = "0123456789abcdefABCDEF::.";
     hlen -= 2;
   }
 
   if(l) {
     /* only valid letters are ok */
     len = strspn(hostname, l);
-    if(hlen != len)
-      /* hostname with bad content */
-      return CURLUE_MALFORMED_INPUT;
+    if(hlen != len) {
+      if(hostname[len] == '%') {
+        /* this could now be '%[zone id]' */
+        char zoneid[16];
+        int i = 0;
+        char *h = &hostname[len + 1];
+        /* pass '25' if present and is a url encoded percent sign */
+        if(!strncmp(h, "25", 2) && h[2] && (h[2] != ']'))
+          h += 2;
+        while(*h && (*h != ']') && (i < 15))
+          zoneid[i++] = *h++;
+        if(!i || (']' != *h))
+          return CURLUE_MALFORMED_INPUT;
+        zoneid[i] = 0;
+        u->zoneid = strdup(zoneid);
+        if(!u->zoneid)
+          return CURLUE_OUT_OF_MEMORY;
+        hostname[len] = ']'; /* insert end bracket */
+        hostname[len + 1] = 0; /* terminate the hostname */
+      }
+      else
+        return CURLUE_MALFORMED_INPUT;
+      /* hostname is fine */
+    }
   }
   else {
     /* letters from the second string is not ok */
@@ -593,6 +636,8 @@ static CURLUcode hostname_check(char *hostname, unsigned int flags)
       /* hostname with bad content */
       return CURLUE_MALFORMED_INPUT;
   }
+  if(!hostname[0])
+    return CURLUE_NO_HOST;
   return CURLUE_OK;
 }
 
@@ -607,7 +652,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
   char *fragment = NULL;
   CURLUcode result;
   bool url_has_scheme = FALSE;
-  char schemebuf[MAX_SCHEME_LEN];
+  char schemebuf[MAX_SCHEME_LEN + 1];
   char *schemep = NULL;
   size_t schemelen = 0;
   size_t urllen;
@@ -621,6 +666,10 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
    ************************************************************/
   /* allocate scratch area */
   urllen = strlen(url);
+  if(urllen > CURL_MAX_INPUT_LENGTH)
+    /* excessive input length */
+    return CURLUE_MALFORMED_INPUT;
+
   path = u->scratch = malloc(urllen * 2 + 2);
   if(!path)
     return CURLUE_OUT_OF_MEMORY;
@@ -827,11 +876,11 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
     if(result)
       return result;
 
-    result = parse_port(u, hostname);
+    result = Curl_parse_port(u, hostname);
     if(result)
       return result;
 
-    result = hostname_check(hostname, flags);
+    result = hostname_check(u, hostname);
     if(result)
       return result;
 
@@ -840,7 +889,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
       return CURLUE_OUT_OF_MEMORY;
   }
 
-  if(query && query[0]) {
+  if(query) {
     u->query = strdup(query);
     if(!u->query)
       return CURLUE_OUT_OF_MEMORY;
@@ -950,6 +999,9 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
     ptr = u->host;
     ifmissing = CURLUE_NO_HOST;
     break;
+  case CURLUPART_ZONEID:
+    ptr = u->zoneid;
+    break;
   case CURLUPART_PORT:
     ptr = u->port;
     ifmissing = CURLUE_NO_PORT;
@@ -960,7 +1012,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
       const struct Curl_handler *h =
         Curl_builtin_scheme(u->scheme);
       if(h) {
-        snprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
+        msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
         ptr = portbuf;
       }
     }
@@ -996,6 +1048,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
     char *scheme;
     char *options = u->options;
     char *port = u->port;
+    char *allochost = NULL;
     if(u->scheme && strcasecompare("file", u->scheme)) {
       url = aprintf("file://%s%s%s",
                     u->path,
@@ -1019,7 +1072,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
           /* there's no stored port number, but asked to deliver
              a default one for the scheme */
           if(h) {
-            snprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
+            msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
             port = portbuf;
           }
         }
@@ -1034,6 +1087,18 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
       if(h && !(h->flags & PROTOPT_URLOPTIONS))
         options = NULL;
 
+      if((u->host[0] == '[') && u->zoneid) {
+        /* make it '[ host %25 zoneid ]' */
+        size_t hostlen = strlen(u->host);
+        size_t alen = hostlen + 3 + strlen(u->zoneid) + 1;
+        allochost = malloc(alen);
+        if(!allochost)
+          return CURLUE_OUT_OF_MEMORY;
+        memcpy(allochost, u->host, hostlen - 1);
+        msnprintf(&allochost[hostlen - 1], alen - hostlen + 1,
+                  "%%25%s]", u->zoneid);
+      }
+
       url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                     scheme,
                     u->user ? u->user : "",
@@ -1042,24 +1107,25 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
                     options ? ";" : "",
                     options ? options : "",
                     (u->user || u->password || options) ? "@": "",
-                    u->host,
+                    allochost ? allochost : u->host,
                     port ? ":": "",
                     port ? port : "",
                     (u->path && (u->path[0] != '/')) ? "/": "",
                     u->path ? u->path : "/",
-                    u->query? "?": "",
-                    u->query? u->query : "",
+                    (u->query && u->query[0]) ? "?": "",
+                    (u->query && u->query[0]) ? u->query : "",
                     u->fragment? "#": "",
                     u->fragment? u->fragment : "");
+      free(allochost);
     }
     if(!url)
       return CURLUE_OUT_OF_MEMORY;
     *part = url;
     return CURLUE_OK;
-    break;
   }
   default:
     ptr = NULL;
+    break;
   }
   if(ptr) {
     *part = strdup(ptr);
@@ -1099,6 +1165,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
   bool plusencode = FALSE;
   bool urlskipslash = FALSE;
   bool appendquery = FALSE;
+  bool equalsencode = FALSE;
 
   if(!u)
     return CURLUE_BAD_HANDLE;
@@ -1122,7 +1189,11 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     case CURLUPART_HOST:
       storep = &u->host;
       break;
+    case CURLUPART_ZONEID:
+      storep = &u->zoneid;
+      break;
     case CURLUPART_PORT:
+      u->portnum = 0;
       storep = &u->port;
       break;
     case CURLUPART_PATH:
@@ -1146,6 +1217,9 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
 
   switch(what) {
   case CURLUPART_SCHEME:
+    if(strlen(part) > MAX_SCHEME_LEN)
+      /* too long */
+      return CURLUE_MALFORMED_INPUT;
     if(!(flags & CURLU_NON_SUPPORT_SCHEME) &&
        /* verify that it is a fine scheme */
        !Curl_builtin_scheme(part))
@@ -1164,14 +1238,25 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     break;
   case CURLUPART_HOST:
     storep = &u->host;
+    free(u->zoneid);
+    u->zoneid = NULL;
+    break;
+  case CURLUPART_ZONEID:
+    storep = &u->zoneid;
     break;
   case CURLUPART_PORT:
+  {
+    char *endp;
     urlencode = FALSE; /* never */
-    port = strtol(part, NULL, 10);  /* Port number must be decimal */
+    port = strtol(part, &endp, 10);  /* Port number must be decimal */
     if((port <= 0) || (port > 0xffff))
       return CURLUE_BAD_PORT_NUMBER;
+    if(*endp)
+      /* weirdly provided number, not good! */
+      return CURLUE_MALFORMED_INPUT;
     storep = &u->port;
-    break;
+  }
+  break;
   case CURLUPART_PATH:
     urlskipslash = TRUE;
     storep = &u->path;
@@ -1179,6 +1264,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
   case CURLUPART_QUERY:
     plusencode = urlencode;
     appendquery = (flags & CURLU_APPENDQUERY)?1:0;
+    equalsencode = appendquery;
     storep = &u->query;
     break;
   case CURLUPART_FRAGMENT:
@@ -1196,7 +1282,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     char *redired_url;
     CURLU *handle2;
 
-    if(Curl_is_absolute_url(part, NULL, MAX_SCHEME_LEN)) {
+    if(Curl_is_absolute_url(part, NULL, MAX_SCHEME_LEN + 1)) {
       handle2 = curl_url();
       if(!handle2)
         return CURLUE_OUT_OF_MEMORY;
@@ -1223,7 +1309,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     }
 
     /* apply the relative part to create a new URL */
-    redired_url = Curl_concat_url(oldurl, part);
+    redired_url = concat_url(oldurl, part);
     free(oldurl);
     if(!redired_url)
       return CURLUE_OUT_OF_MEMORY;
@@ -1249,8 +1335,12 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
     const char *newp = part;
     size_t nalloc = strlen(part);
 
+    if(nalloc > CURL_MAX_INPUT_LENGTH)
+      /* excessive input length */
+      return CURLUE_MALFORMED_INPUT;
+
     if(urlencode) {
-      const char *i;
+      const unsigned char *i;
       char *o;
       bool free_part = FALSE;
       char *enc = malloc(nalloc * 3 + 1); /* for worst case! */
@@ -1258,7 +1348,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
         return CURLUE_OUT_OF_MEMORY;
       if(plusencode) {
         /* space to plus */
-        i = part;
+        i = (const unsigned char *)part;
         for(o = enc; *i; ++o, ++i)
           *o = (*i == ' ') ? '+' : *i;
         *o = 0; /* zero terminate */
@@ -1269,16 +1359,19 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
         }
         free_part = TRUE;
       }
-      for(i = part, o = enc; *i; i++) {
+      for(i = (const unsigned char *)part, o = enc; *i; i++) {
         if(Curl_isunreserved(*i) ||
            ((*i == '/') && urlskipslash) ||
-           ((*i == '=') && appendquery) ||
+           ((*i == '=') && equalsencode) ||
            ((*i == '+') && plusencode)) {
+          if((*i == '=') && equalsencode)
+            /* only skip the first equals sign */
+            equalsencode = FALSE;
           *o = *i;
           o++;
         }
         else {
-          snprintf(o, 4, "%%%02x", *i);
+          msnprintf(o, 4, "%%%02x", *i);
           o += 3;
         }
       }
@@ -1329,6 +1422,13 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
       }
     }
 
+    if(what == CURLUPART_HOST) {
+      if(hostname_check(u, (char *)newp)) {
+        free((char *)newp);
+        return CURLUE_MALFORMED_INPUT;
+      }
+    }
+
     free(*storep);
     *storep = (char *)newp;
   }
diff --git a/lib/urldata.h b/lib/urldata.h
index 11a6a22..d759592 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -77,7 +77,11 @@
 /* Default FTP/IMAP etc response timeout in milliseconds.
    Symbian OS panics when given a timeout much greater than 1/2 hour.
 */
-#define RESP_TIMEOUT (1800*1000)
+#define RESP_TIMEOUT (120*1000)
+
+/* Max string intput length is a precaution against abuse and to detect junk
+   input easier and better. */
+#define CURL_MAX_INPUT_LENGTH 8000000
 
 #include "cookie.h"
 #include "psl.h"
@@ -129,12 +133,14 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
 #ifdef HAVE_GSSAPI
 # ifdef HAVE_GSSGNU
 #  include <gss.h>
-# elif defined HAVE_GSSMIT
+# elif defined HAVE_GSSAPI_GSSAPI_H
 #  include <gssapi/gssapi.h>
-#  include <gssapi/gssapi_generic.h>
 # else
 #  include <gssapi.h>
 # endif
+# ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#  include <gssapi/gssapi_generic.h>
+# endif
 #endif
 
 #ifdef HAVE_LIBSSH2_H
@@ -142,10 +148,6 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
 #include <libssh2_sftp.h>
 #endif /* HAVE_LIBSSH2_H */
 
-
-/* The "master buffer" is for HTTP pipelining */
-#define MASTERBUF_SIZE 16384
-
 /* Initial size of the buffer to store headers in, it'll be enlarged in case
    of need. */
 #define HEADERSIZE 256
@@ -154,13 +156,16 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
 #define GOOD_EASY_HANDLE(x) \
   ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))
 
+/* the type we use for storing a single boolean bit */
+typedef unsigned int bit;
+
 #ifdef HAVE_GSSAPI
 /* Types needed for krb5-ftp connections */
 struct krb5buffer {
   void *data;
   size_t size;
   size_t index;
-  int eof_flag;
+  bit eof_flag:1;
 };
 
 enum protection_level {
@@ -198,21 +203,17 @@ struct ssl_connect_data {
   /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm
      but at least asked to or meaning to use it. See 'state' for the exact
      current state of the connection. */
-  bool use;
   ssl_connection_state state;
   ssl_connect_state connecting_state;
 #if defined(USE_SSL)
   struct ssl_backend_data *backend;
 #endif
+  bit use:1;
 };
 
 struct ssl_primary_config {
   long version;          /* what version the client wants to use */
   long version_max;      /* max supported version the client wants to use*/
-  bool verifypeer;       /* set TRUE if this is desired */
-  bool verifyhost;       /* set TRUE if CN/SAN must match hostname */
-  bool verifystatus;     /* set TRUE if certificate status must be checked */
-  bool sessionid;        /* cache session IDs or not */
   char *CApath;          /* certificate dir (doesn't work on windows) */
   char *CAfile;          /* certificate to verify peer against */
   char *clientcert;
@@ -220,32 +221,33 @@ struct ssl_primary_config {
   char *egdsocket;       /* path to file containing the EGD daemon socket */
   char *cipher_list;     /* list of ciphers to use */
   char *cipher_list13;   /* list of TLS 1.3 cipher suites to use */
+  bit verifypeer:1;      /* set TRUE if this is desired */
+  bit verifyhost:1;      /* set TRUE if CN/SAN must match hostname */
+  bit verifystatus:1;    /* set TRUE if certificate status must be checked */
+  bit sessionid:1;       /* cache session IDs or not */
 };
 
 struct ssl_config_data {
   struct ssl_primary_config primary;
-  bool enable_beast; /* especially allow this flaw for interoperability's
-                        sake*/
-  bool no_revoke;    /* disable SSL certificate revocation checks */
   long certverifyresult; /* result from the certificate verification */
   char *CRLfile;   /* CRL to check certificate revocation */
   char *issuercert;/* optional issuer certificate filename */
   curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
   void *fsslctxp;        /* parameter for call back */
-  bool certinfo;         /* gather lots of certificate info */
-  bool falsestart;
-
   char *cert; /* client certificate file name */
   char *cert_type; /* format for certificate (default: PEM)*/
   char *key; /* private key file name */
   char *key_type; /* format for private key (default: PEM) */
   char *key_passwd; /* plain text private key password */
-
 #ifdef USE_TLS_SRP
   char *username; /* TLS username (for, e.g., SRP) */
   char *password; /* TLS password (for, e.g., SRP) */
   enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */
 #endif
+  bit certinfo:1;     /* gather lots of certificate info */
+  bit falsestart:1;
+  bit enable_beast:1; /* allow this flaw for interoperability's sake*/
+  bit no_revoke:1;    /* disable SSL certificate revocation checks */
 };
 
 struct ssl_general_config {
@@ -284,12 +286,12 @@ struct digestdata {
   char *cnonce;
   char *realm;
   int algo;
-  bool stale; /* set true for re-negotiation */
   char *opaque;
   char *qop;
   char *algorithm;
   int nc; /* nounce count */
-  bool userhash;
+  bit stale:1; /* set true for re-negotiation */
+  bit userhash:1;
 #endif
 };
 
@@ -301,6 +303,14 @@ typedef enum {
   NTLMSTATE_LAST
 } curlntlm;
 
+typedef enum {
+  GSS_AUTHNONE,
+  GSS_AUTHRECV,
+  GSS_AUTHSENT,
+  GSS_AUTHDONE,
+  GSS_AUTHSUCC
+} curlnegotiate;
+
 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
 #include <iconv.h>
 #endif
@@ -326,8 +336,13 @@ struct kerberos5data {
 /* Struct used for NTLM challenge-response authentication */
 #if defined(USE_NTLM)
 struct ntlmdata {
-  curlntlm state;
 #ifdef USE_WINDOWS_SSPI
+/* The sslContext is used for the Schannel bindings. The
+ * api is available on the Windows 7 SDK and later.
+ */
+#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
+  CtxtHandle *sslContext;
+#endif
   CredHandle *credentials;
   CtxtHandle *context;
   SEC_WINNT_AUTH_IDENTITY identity;
@@ -346,11 +361,9 @@ struct ntlmdata {
 };
 #endif
 
+/* Struct used for Negotiate (SPNEGO) authentication */
 #ifdef USE_SPNEGO
 struct negotiatedata {
-  /* When doing Negotiate (SPNEGO) auth, we first need to send a token
-     and then validate the received one. */
-  enum { GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT } state;
 #ifdef HAVE_GSSAPI
   OM_uint32 status;
   gss_ctx_id_t context;
@@ -358,6 +371,9 @@ struct negotiatedata {
   gss_buffer_desc output_token;
 #else
 #ifdef USE_WINDOWS_SSPI
+#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
+  CtxtHandle *sslContext;
+#endif
   DWORD status;
   CredHandle *credentials;
   CtxtHandle *context;
@@ -369,6 +385,10 @@ struct negotiatedata {
   size_t output_token_length;
 #endif
 #endif
+  bool noauthpersist;
+  bool havenoauthpersist;
+  bool havenegdata;
+  bool havemultiplerequests;
 };
 #endif
 
@@ -378,69 +398,67 @@ struct negotiatedata {
  */
 struct ConnectBits {
   /* always modify bits.close with the connclose() and connkeep() macros! */
-  bool close; /* if set, we close the connection after this request */
-  bool reuse; /* if set, this is a re-used connection */
-  bool conn_to_host; /* if set, this connection has a "connect to host"
-                        that overrides the host in the URL */
-  bool conn_to_port; /* if set, this connection has a "connect to port"
-                        that overrides the port in the URL (remote port) */
-  bool proxy; /* if set, this transfer is done through a proxy - any type */
-  bool httpproxy;    /* if set, this transfer is done through a http proxy */
-  bool socksproxy;   /* if set, this transfer is done through a socks proxy */
-  bool user_passwd;    /* do we use user+password for this connection? */
-  bool proxy_user_passwd; /* user+password for the proxy? */
-  bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6
-                   IP address */
-  bool ipv6;    /* we communicate with a site using an IPv6 address */
-
-  bool do_more; /* this is set TRUE if the ->curl_do_more() function is
-                   supposed to be called, after ->curl_do() */
-  bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set
-                         the first time on the first connect function call */
-  bool protoconnstart;/* the protocol layer has STARTED its operation after
-                         the TCP layer connect */
-
-  bool retry;         /* this connection is about to get closed and then
-                         re-attempted at another connection. */
-  bool tunnel_proxy;  /* if CONNECT is used to "tunnel" through the proxy.
-                         This is implicit when SSL-protocols are used through
-                         proxies, but can also be enabled explicitly by
-                         apps */
-  bool authneg;       /* TRUE when the auth phase has started, which means
-                         that we are creating a request with an auth header,
-                         but it is not the final request in the auth
-                         negotiation. */
-  bool rewindaftersend;/* TRUE when the sending couldn't be stopped even
-                          though it will be discarded. When the whole send
-                          operation is done, we must call the data rewind
-                          callback. */
-  bool ftp_use_epsv;  /* As set with CURLOPT_FTP_USE_EPSV, but if we find out
-                         EPSV doesn't work we disable it for the forthcoming
-                         requests */
-
-  bool ftp_use_eprt;  /* As set with CURLOPT_FTP_USE_EPRT, but if we find out
-                         EPRT doesn't work we disable it for the forthcoming
-                         requests */
-  bool ftp_use_data_ssl; /* Enabled SSL for the data connection */
-  bool netrc;         /* name+password provided by netrc */
-  bool userpwd_in_url; /* name+password found in url */
-  bool stream_was_rewound; /* Indicates that the stream was rewound after a
-                              request read past the end of its response byte
-                              boundary */
-  bool proxy_connect_closed; /* set true if a proxy disconnected the
-                                connection in a CONNECT request with auth, so
-                                that libcurl should reconnect and continue. */
-  bool bound; /* set true if bind() has already been done on this socket/
-                 connection */
-  bool type_set;  /* type= was used in the URL */
-  bool multiplex; /* connection is multiplexed */
-
-  bool tcp_fastopen; /* use TCP Fast Open */
-  bool tls_enable_npn;  /* TLS NPN extension? */
-  bool tls_enable_alpn; /* TLS ALPN extension? */
   bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy
                                   is complete */
-  bool socksproxy_connecting; /* connecting through a socks proxy */
+  bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set
+                         the first time on the first connect function call */
+  bit close:1; /* if set, we close the connection after this request */
+  bit reuse:1; /* if set, this is a re-used connection */
+  bit conn_to_host:1; /* if set, this connection has a "connect to host"
+                         that overrides the host in the URL */
+  bit conn_to_port:1; /* if set, this connection has a "connect to port"
+                         that overrides the port in the URL (remote port) */
+  bit proxy:1; /* if set, this transfer is done through a proxy - any type */
+  bit httpproxy:1;  /* if set, this transfer is done through a http proxy */
+  bit socksproxy:1; /* if set, this transfer is done through a socks proxy */
+  bit user_passwd:1; /* do we use user+password for this connection? */
+  bit proxy_user_passwd:1; /* user+password for the proxy? */
+  bit ipv6_ip:1; /* we communicate with a remote site specified with pure IPv6
+                    IP address */
+  bit ipv6:1;    /* we communicate with a site using an IPv6 address */
+  bit do_more:1; /* this is set TRUE if the ->curl_do_more() function is
+                    supposed to be called, after ->curl_do() */
+  bit protoconnstart:1;/* the protocol layer has STARTED its operation after
+                          the TCP layer connect */
+  bit retry:1;         /* this connection is about to get closed and then
+                          re-attempted at another connection. */
+  bit tunnel_proxy:1;  /* if CONNECT is used to "tunnel" through the proxy.
+                          This is implicit when SSL-protocols are used through
+                          proxies, but can also be enabled explicitly by
+                          apps */
+  bit authneg:1;       /* TRUE when the auth phase has started, which means
+                          that we are creating a request with an auth header,
+                          but it is not the final request in the auth
+                          negotiation. */
+  bit rewindaftersend:1;/* TRUE when the sending couldn't be stopped even
+                           though it will be discarded. When the whole send
+                           operation is done, we must call the data rewind
+                           callback. */
+#ifndef CURL_DISABLE_FTP
+  bit ftp_use_epsv:1;  /* As set with CURLOPT_FTP_USE_EPSV, but if we find out
+                          EPSV doesn't work we disable it for the forthcoming
+                          requests */
+  bit ftp_use_eprt:1;  /* As set with CURLOPT_FTP_USE_EPRT, but if we find out
+                          EPRT doesn't work we disable it for the forthcoming
+                          requests */
+  bit ftp_use_data_ssl:1; /* Enabled SSL for the data connection */
+#endif
+  bit netrc:1;         /* name+password provided by netrc */
+  bit userpwd_in_url:1; /* name+password found in url */
+  bit stream_was_rewound:1; /* The stream was rewound after a request read
+                               past the end of its response byte boundary */
+  bit proxy_connect_closed:1; /* TRUE if a proxy disconnected the connection
+                                 in a CONNECT request with auth, so that
+                                 libcurl should reconnect and continue. */
+  bit bound:1; /* set true if bind() has already been done on this socket/
+                  connection */
+  bit type_set:1;  /* type= was used in the URL */
+  bit multiplex:1; /* connection is multiplexed */
+  bit tcp_fastopen:1; /* use TCP Fast Open */
+  bit tls_enable_npn:1;  /* TLS NPN extension? */
+  bit tls_enable_alpn:1; /* TLS ALPN extension? */
+  bit socksproxy_connecting:1; /* connecting through a socks proxy */
+  bit connect_only:1;
 };
 
 struct hostname {
@@ -467,14 +485,13 @@ struct hostname {
 #define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE)
 #define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
 
-
 struct Curl_async {
   char *hostname;
   int port;
   struct Curl_dns_entry *dns;
-  bool done;  /* set TRUE when the lookup is complete */
   int status; /* if done is TRUE, this is the status from the callback */
   void *os_specific;  /* 'struct thread_data' for Windows */
+  bit done:1;  /* set TRUE when the lookup is complete */
 };
 
 #define FIRSTSOCKET     0
@@ -532,25 +549,21 @@ struct dohdata {
  */
 struct SingleRequest {
   curl_off_t size;        /* -1 if unknown at this point */
-  curl_off_t *bytecountp; /* return number of bytes read or NULL */
-
   curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch,
                              -1 means unlimited */
-  curl_off_t *writebytecountp; /* return number of bytes written or NULL */
-
   curl_off_t bytecount;         /* total number of bytes read */
   curl_off_t writebytecount;    /* number of bytes written */
 
-  long headerbytecount;         /* only count received headers */
-  long deductheadercount; /* this amount of bytes doesn't count when we check
-                             if anything has been transferred at the end of a
-                             connection. We use this counter to make only a
-                             100 reply (without a following second response
-                             code) result in a CURLE_GOT_NOTHING error code */
+  curl_off_t headerbytecount;   /* only count received headers */
+  curl_off_t deductheadercount; /* this amount of bytes doesn't count when we
+                                   check if anything has been transferred at
+                                   the end of a connection. We use this
+                                   counter to make only a 100 reply (without a
+                                   following second response code) result in a
+                                   CURLE_GOT_NOTHING error code */
 
   struct curltime start;         /* transfer started at this time */
   struct curltime now;           /* current time */
-  bool header;                  /* incoming data has HTTP header */
   enum {
     HEADER_NORMAL,              /* no bad header at all */
     HEADER_PARTHEADER,          /* part of the chunk is a bad header, the rest
@@ -566,7 +579,6 @@ struct SingleRequest {
   char *str_start;              /* within buf */
   char *end_ptr;                /* within buf */
   char *p;                      /* within headerbuff */
-  bool content_range;           /* set TRUE if Content-Range: was found */
   curl_off_t offset;            /* possible resume offset read from the
                                    Content-Range: header */
   int httpcode;                 /* error code from the 'HTTP/1.? XXX' or
@@ -579,19 +591,8 @@ struct SingleRequest {
                                           /* See sec 3.5, RFC2616. */
   time_t timeofdoc;
   long bodywrites;
-
   char *buf;
-  curl_socket_t maxfd;
-
   int keepon;
-
-  bool upload_done; /* set to TRUE when doing chunked transfer-encoding upload
-                       and we're uploading the last chunk */
-
-  bool ignorebody;  /* we read a response-body but we ignore it! */
-  bool ignorecl;    /* This HTTP response has no body so we ignore the Content-
-                       Length: header */
-
   char *location;   /* This points to an allocated version of the Location:
                        header data */
   char *newurl;     /* Set to the new URL to use when a redirect or a retry is
@@ -601,24 +602,30 @@ struct SingleRequest {
      still left in the buffer, aimed for upload. */
   ssize_t upload_present;
 
-   /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a
-      buffer, so the next read should read from where this pointer points to,
-      and the 'upload_present' contains the number of bytes available at this
-      position */
+  /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a
+     buffer, so the next read should read from where this pointer points to,
+     and the 'upload_present' contains the number of bytes available at this
+     position */
   char *upload_fromhere;
-
-  bool chunk; /* if set, this is a chunked transfer-encoding */
-  bool upload_chunky; /* set TRUE if we are doing chunked transfer-encoding
-                         on upload */
-  bool getheader;     /* TRUE if header parsing is wanted */
-
-  bool forbidchunk;   /* used only to explicitly forbid chunk-upload for
-                         specific upload buffers. See readmoredata() in
-                         http.c for details. */
-
   void *protop;       /* Allocated protocol-specific data. Each protocol
                          handler makes sure this points to data it needs. */
+#ifndef CURL_DISABLE_DOH
   struct dohdata doh; /* DoH specific data for this request */
+#endif
+  bit header:1;       /* incoming data has HTTP header */
+  bit content_range:1; /* set TRUE if Content-Range: was found */
+  bit upload_done:1;  /* set to TRUE when doing chunked transfer-encoding
+                         upload and we're uploading the last chunk */
+  bit ignorebody:1;   /* we read a response-body but we ignore it! */
+  bit ignorecl:1;     /* This HTTP response has no body so we ignore the
+                         Content-Length: header */
+  bit chunk:1; /* if set, this is a chunked transfer-encoding */
+  bit upload_chunky:1; /* set TRUE if we are doing chunked transfer-encoding
+                          on upload */
+  bit getheader:1;    /* TRUE if header parsing is wanted */
+  bit forbidchunk:1;  /* used only to explicitly forbid chunk-upload for
+                         specific upload buffers. See readmoredata() in http.c
+                         for details. */
 };
 
 /*
@@ -766,13 +773,13 @@ struct http_connect_state {
   char *line_start;
   char *ptr; /* where to store more data */
   curl_off_t cl; /* size of content to read and ignore */
-  bool chunked_encoding;
   enum {
     TUNNEL_INIT,    /* init/default/no tunnel state */
     TUNNEL_CONNECT, /* CONNECT has been sent off */
     TUNNEL_COMPLETE /* CONNECT response received completely */
   } tunnel_state;
-  bool close_connection;
+  bit chunked_encoding:1;
+  bit close_connection:1;
 };
 
 /*
@@ -796,11 +803,10 @@ struct connectdata {
   void *closesocket_client;
 
   /* This is used by the connection cache logic. If this returns TRUE, this
-     handle is being used by one or more easy handles and can only used by any
+     handle is still used by one or more easy handles and can only used by any
      other easy handle without careful consideration (== only for
-     pipelining/multiplexing) and it cannot be used by another multi
-     handle! */
-#define CONN_INUSE(c) ((c)->send_pipe.size + (c)->recv_pipe.size)
+     multiplexing) and it cannot be used by another multi handle! */
+#define CONN_INUSE(c) ((c)->easyq.size)
 
   /**** Fields set when inited and not modified again */
   long connection_id; /* Contains a unique number to make it easier to
@@ -828,6 +834,7 @@ struct connectdata {
   int socktype;  /* SOCK_STREAM or SOCK_DGRAM */
 
   struct hostname host;
+  char *hostname_resolve; /* host name to resolve to address, allocated */
   char *secondaryhostname; /* secondary socket host name (ftp) */
   struct hostname conn_to_host; /* the host to connect to. valid only if
                                    bits.conn_to_host is set */
@@ -870,6 +877,7 @@ struct connectdata {
 
   struct curltime now;     /* "current" time */
   struct curltime created; /* creation time */
+  struct curltime lastused; /* when returned to the connection cache */
   curl_socket_t sock[2]; /* two sockets, the second is used for the data
                             transfer when doing FTP */
   curl_socket_t tempsock[2]; /* temporary sockets for happy eyeballs */
@@ -888,8 +896,6 @@ struct connectdata {
 #endif
   struct ssl_primary_config ssl_config;
   struct ssl_primary_config proxy_ssl_config;
-  bool tls_upgraded;
-
   struct ConnectBits bits;    /* various state-flags for this connection */
 
  /* connecttime: when connect() is called on the current IP address. Used to
@@ -936,7 +942,7 @@ struct connectdata {
   } allocptr;
 
 #ifdef HAVE_GSSAPI
-  int sec_complete; /* if Kerberos is enabled for this connection */
+  bit sec_complete:1; /* if Kerberos is enabled for this connection */
   enum protection_level command_prot;
   enum protection_level data_prot;
   enum protection_level request_data_prot;
@@ -951,30 +957,19 @@ struct connectdata {
   struct kerberos5data krb5;  /* variables into the structure definition, */
 #endif                        /* however, some of them are ftp specific. */
 
-  /* the two following *_inuse fields are only flags, not counters in any way.
-     If TRUE it means the channel is in use, and if FALSE it means the channel
-     is up for grabs by one. */
-
-  bool readchannel_inuse;  /* whether the read channel is in use by an easy
-                              handle */
-  bool writechannel_inuse; /* whether the write channel is in use by an easy
-                              handle */
-  struct curl_llist send_pipe; /* List of handles waiting to send on this
-                                  pipeline */
-  struct curl_llist recv_pipe; /* List of handles waiting to read their
-                                  responses on this pipeline */
-  char *master_buffer; /* The master buffer allocated on-demand;
-                          used for pipelining. */
-  size_t read_pos; /* Current read position in the master buffer */
-  size_t buf_len; /* Length of the buffer?? */
-
-
+  struct curl_llist easyq;    /* List of easy handles using this connection */
   curl_seek_callback seek_func; /* function that seeks the input */
   void *seek_client;            /* pointer to pass to the seek() above */
 
   /*************** Request - specific items ************/
+#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS)
+  CtxtHandle *sslContext;
+#endif
 
 #if defined(USE_NTLM)
+  curlntlm http_ntlm_state;
+  curlntlm proxy_ntlm_state;
+
   struct ntlmdata ntlm;     /* NTLM differs from other authentication schemes
                                because it authenticates connections, not
                                single requests! */
@@ -989,7 +984,14 @@ struct connectdata {
 #endif
 #endif
 
-  char syserr_buf [256]; /* buffer for Curl_strerror() */
+#ifdef USE_SPNEGO
+  curlnegotiate http_negotiate_state;
+  curlnegotiate proxy_negotiate_state;
+
+  struct negotiatedata negotiate; /* state data for host Negotiate auth */
+  struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
+#endif
+
   /* data used for the asynch name resolve callback */
   struct Curl_async async;
 
@@ -1032,8 +1034,16 @@ struct connectdata {
 
 #ifdef USE_UNIX_SOCKETS
   char *unix_domain_socket;
-  bool abstract_unix_socket;
+  bit abstract_unix_socket:1;
 #endif
+  bit tls_upgraded:1;
+  /* the two following *_inuse fields are only flags, not counters in any way.
+     If TRUE it means the channel is in use, and if FALSE it means the channel
+     is up for grabs by one. */
+  bit readchannel_inuse:1;  /* whether the read channel is in use by an easy
+                               handle */
+  bit writechannel_inuse:1; /* whether the write channel is in use by an easy
+                               handle */
 };
 
 /* The end of connectdata. */
@@ -1048,10 +1058,8 @@ struct PureInfo {
   int httpversion; /* the http version number X.Y = X*10+Y */
   time_t filetime; /* If requested, this is might get set. Set to -1 if the
                       time was unretrievable. */
-  bool timecond;  /* set to TRUE if the time condition didn't match, which
-                     thus made the document NOT get fetched */
-  long header_size;  /* size of read header(s) in bytes */
-  long request_size; /* the amount of bytes sent in the request(s) */
+  curl_off_t header_size;  /* size of read header(s) in bytes */
+  curl_off_t request_size; /* the amount of bytes sent in the request(s) */
   unsigned long proxyauthavail; /* what proxy auth types were announced */
   unsigned long httpauthavail;  /* what host auth types were announced */
   long numconnects; /* how many new connection did libcurl created */
@@ -1068,16 +1076,16 @@ struct PureInfo {
 
   char conn_primary_ip[MAX_IPADR_LEN];
   long conn_primary_port;
-
   char conn_local_ip[MAX_IPADR_LEN];
   long conn_local_port;
-
   const char *conn_scheme;
   unsigned int conn_protocol;
-
   struct curl_certinfo certs; /* info about the certs, only populated in
                                  OpenSSL builds. Asked for with
                                  CURLOPT_CERTINFO / CURLINFO_CERTINFO */
+
+  bit timecond:1;  /* set to TRUE if the time condition didn't match, which
+                      thus made the document NOT get fetched */
 };
 
 
@@ -1091,7 +1099,6 @@ struct Progress {
 
   curl_off_t current_speed; /* uses the currently fastest transfer */
 
-  bool callback;  /* set when progress callback is used */
   int width; /* screen width at download start */
   int flags; /* see progress.h */
 
@@ -1112,7 +1119,6 @@ struct Progress {
   struct curltime t_startop;
   struct curltime t_acceptdata;
 
-  bool is_t_startransfer_set;
 
   /* upload speed limit */
   struct curltime ul_limit_start;
@@ -1126,6 +1132,8 @@ struct Progress {
   curl_off_t speeder[ CURR_TIME ];
   struct curltime speeder_time[ CURR_TIME ];
   int speeder_c;
+  bit callback:1;  /* set when progress callback is used */
+  bit is_t_startransfer_set:1;
 };
 
 typedef enum {
@@ -1137,7 +1145,6 @@ typedef enum {
   HTTPREQ_PUT,
   HTTPREQ_HEAD,
   HTTPREQ_OPTIONS,
-  HTTPREQ_CUSTOM,
   HTTPREQ_LAST /* last in list */
 } Curl_HttpReq;
 
@@ -1174,12 +1181,12 @@ struct auth {
   unsigned long picked;
   unsigned long avail; /* Bitmask for what the server reports to support for
                           this resource */
-  bool done;  /* TRUE when the auth phase is done and ready to do the *actual*
-                 request */
-  bool multipass; /* TRUE if this is not yet authenticated but within the
-                     auth multipass negotiation */
-  bool iestyle; /* TRUE if digest should be done IE-style or FALSE if it should
-                   be RFC compliant */
+  bit done:1;  /* TRUE when the auth phase is done and ready to do the
+                 *actual* request */
+  bit multipass:1; /* TRUE if this is not yet authenticated but within the
+                       auth multipass negotiation */
+  bit iestyle:1; /* TRUE if digest should be done IE-style or FALSE if it
+                     should be RFC compliant */
 };
 
 struct Curl_http2_dep {
@@ -1206,6 +1213,7 @@ typedef enum {
   EXPIRE_ASYNC_NAME,
   EXPIRE_CONNECTTIMEOUT,
   EXPIRE_DNS_PER_NAME,
+  EXPIRE_HAPPY_EYEBALLS_DNS, /* See asyn-ares.c */
   EXPIRE_HAPPY_EYEBALLS,
   EXPIRE_MULTI_PENDING,
   EXPIRE_RUN_NOW,
@@ -1215,6 +1223,15 @@ typedef enum {
   EXPIRE_LAST /* not an actual timer, used as a marker only */
 } expire_id;
 
+
+typedef enum {
+  TRAILERS_NONE,
+  TRAILERS_INITIALIZED,
+  TRAILERS_SENDING,
+  TRAILERS_DONE
+} trailers_state;
+
+
 /*
  * One instance for each timeout an easy handle can set.
  */
@@ -1241,11 +1258,6 @@ struct UrlState {
   /* Points to the connection cache */
   struct conncache *conn_cache;
 
-  /* when curl_easy_perform() is called, the multi handle is "owned" by
-     the easy handle so curl_easy_cleanup() on such an easy handle will
-     also close the multi handle! */
-  bool multi_owned_by_easy;
-
   /* buffers to store authentication data in, as parsed from input options */
   struct curltime keeps_speed; /* for the progress meter really */
 
@@ -1258,8 +1270,6 @@ struct UrlState {
   char *ulbuf; /* allocated upload buffer or NULL */
   curl_off_t current_speed;  /* the ProgressShow() function sets this,
                                 bytes / second */
-  bool this_is_a_follow; /* this is a followed Location: request */
-  bool refused_stream; /* this was refused, try again */
   char *first_host; /* host name of the first (not followed) request.
                        if set, this should be the host name that we will
                        sent authorization to, no else. Used to make Location:
@@ -1272,29 +1282,16 @@ struct UrlState {
   unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
   struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */
   char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */
-  bool errorbuf; /* Set to TRUE if the error buffer is already filled in.
-                    This must be set to FALSE every time _easy_perform() is
-                    called. */
   int os_errno;  /* filled in with errno whenever an error occurs */
 #ifdef HAVE_SIGNAL
   /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
   void (*prev_signal)(int sig);
 #endif
-  bool allow_port; /* Is set.use_port allowed to take effect or not. This
-                      is always set TRUE when curl_easy_perform() is called. */
   struct digestdata digest;      /* state data for host Digest auth */
   struct digestdata proxydigest; /* state data for proxy Digest auth */
 
-#ifdef USE_SPNEGO
-  struct negotiatedata negotiate; /* state data for host Negotiate auth */
-  struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
-#endif
-
   struct auth authhost;  /* auth details for host */
   struct auth authproxy; /* auth details for proxy */
-
-  bool authproblem; /* TRUE if there's some problem authenticating */
-
   void *resolver; /* resolver state, if it is used in the URL state -
                      ares_channel f.e. */
 
@@ -1310,27 +1307,18 @@ struct UrlState {
   /* a place to store the most recently set FTP entrypath */
   char *most_recent_ftp_entrypath;
 
-  /* set after initial USER failure, to prevent an authentication loop */
-  bool ftp_trying_alternative;
-  bool wildcardmatch; /* enable wildcard matching */
   int httpversion;       /* the lowest HTTP version*10 reported by any server
                             involved in this request */
-  bool expect100header;  /* TRUE if we added Expect: 100-continue */
 
 #if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \
     !defined(__SYMBIAN32__)
 /* do FTP line-end conversions on most platforms */
 #define CURL_DO_LINEEND_CONV
   /* for FTP downloads: track CRLF sequences that span blocks */
-  bool prev_block_had_trailing_cr;
+  bit prev_block_had_trailing_cr:1;
   /* for FTP downloads: how many CRLFs did we converted to LFs? */
   curl_off_t crlf_conversions;
 #endif
-  bool slash_removed; /* set TRUE if the 'path' points to a path where the
-                         initial URL slash separator has been taken off */
-  bool use_range;
-  bool rangestringalloc; /* the range string is malloc()'ed */
-
   char *range; /* range, if used. See README for detailed specification on
                   this syntax. */
   curl_off_t resume_from; /* continue [ftp] transfer from here */
@@ -1346,21 +1334,48 @@ struct UrlState {
   size_t drain; /* Increased when this stream has data to read, even if its
                    socket is not necessarily is readable. Decreased when
                    checked. */
-  bool done; /* set to FALSE when Curl_init_do() is called and set to TRUE
-                when multi_done() is called, to prevent multi_done() to get
-                invoked twice when the multi interface is used. */
 
   curl_read_callback fread_func; /* read callback/function */
   void *in;                      /* CURLOPT_READDATA */
 
   struct Curl_easy *stream_depends_on;
-  bool stream_depends_e; /* set or don't set the Exclusive bit */
   int stream_weight;
-#ifdef CURLDEBUG
-  bool conncache_lock;
-#endif
   CURLU *uh; /* URL handle for the current parsed URL */
   struct urlpieces up;
+#ifndef CURL_DISABLE_HTTP
+  size_t trailers_bytes_sent;
+  Curl_send_buffer *trailers_buf; /* a buffer containing the compiled trailing
+                                  headers */
+#endif
+  trailers_state trailers_state; /* whether we are sending trailers
+                                       and what stage are we at */
+#ifdef CURLDEBUG
+  bit conncache_lock:1;
+#endif
+  /* when curl_easy_perform() is called, the multi handle is "owned" by
+     the easy handle so curl_easy_cleanup() on such an easy handle will
+     also close the multi handle! */
+  bit multi_owned_by_easy:1;
+
+  bit this_is_a_follow:1; /* this is a followed Location: request */
+  bit refused_stream:1; /* this was refused, try again */
+  bit errorbuf:1; /* Set to TRUE if the error buffer is already filled in.
+                    This must be set to FALSE every time _easy_perform() is
+                    called. */
+  bit allow_port:1; /* Is set.use_port allowed to take effect or not. This
+                      is always set TRUE when curl_easy_perform() is called. */
+  bit authproblem:1; /* TRUE if there's some problem authenticating */
+  /* set after initial USER failure, to prevent an authentication loop */
+  bit ftp_trying_alternative:1;
+  bit wildcardmatch:1; /* enable wildcard matching */
+  bit expect100header:1;  /* TRUE if we added Expect: 100-continue */
+  bit use_range:1;
+  bit rangestringalloc:1; /* the range string is malloc()'ed */
+  bit done:1; /* set to FALSE when Curl_init_do() is called and set to TRUE
+                  when multi_done() is called, to prevent multi_done() to get
+                  invoked twice when the multi interface is used. */
+  bit stream_depends_e:1; /* set or don't set the Exclusive bit */
+  bit previouslypending:1; /* this transfer WAS in the multi->pending queue */
 };
 
 
@@ -1373,13 +1388,15 @@ struct UrlState {
 
 struct DynamicStatic {
   char *url;        /* work URL, copied from UserDefined */
-  bool url_alloc;   /* URL string is malloc()'ed */
   char *referer;    /* referer string */
-  bool referer_alloc; /* referer string is malloc()ed */
   struct curl_slist *cookielist; /* list of cookie files set by
                                     curl_easy_setopt(COOKIEFILE) calls */
   struct curl_slist *resolve; /* set to point to the set.resolve list when
                                  this should be dealt with in pretransfer */
+  bit url_alloc:1;   /* URL string is malloc()'ed */
+  bit referer_alloc:1; /* referer string is malloc()ed */
+  bit wildcard_resolve:1; /* Set to true if any resolve change is a
+                              wildcard */
 };
 
 /*
@@ -1449,7 +1466,7 @@ enum dupstring {
   STRING_RTSP_SESSION_ID, /* Session ID to use */
   STRING_RTSP_STREAM_URI, /* Stream URI for this request */
   STRING_RTSP_TRANSPORT,  /* Transport for this session */
-#if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
+#ifdef USE_SSH
   STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */
   STRING_SSH_PUBLIC_KEY,  /* path to the public key file for auth */
   STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
@@ -1472,6 +1489,9 @@ enum dupstring {
 #endif
   STRING_TARGET,                /* CURLOPT_REQUEST_TARGET */
   STRING_DOH,                   /* CURLOPT_DOH_URL */
+#ifdef USE_ALTSVC
+  STRING_ALTSVC,                /* CURLOPT_ALTSVC */
+#endif
   /* -- end of zero-terminated strings -- */
 
   STRING_LASTZEROTERMINATED,
@@ -1509,8 +1529,6 @@ struct UserDefined {
 
   int keep_post;     /* keep POSTs as POSTs after a 30x request; each
                         bit represents a request, from 301 to 303 */
-  bool free_referer; /* set TRUE if 'referer' points to a string we
-                        allocated */
   void *postfields;  /* if POST, set the fields' values here */
   curl_seek_callback seek_func;      /* function that seeks the input */
   curl_off_t postfieldsize; /* if POST, this might have a size to use instead
@@ -1523,8 +1541,6 @@ struct UserDefined {
   curl_write_callback fwrite_header; /* function that stores headers */
   curl_write_callback fwrite_rtp;    /* function that stores interleaved RTP */
   curl_read_callback fread_func_set; /* function that reads the input */
-  int is_fread_set; /* boolean, has read callback been set to non-NULL? */
-  int is_fwrite_set; /* boolean, has write callback been set to non-NULL? */
   curl_progress_callback fprogress; /* OLD and deprecated progress callback  */
   curl_xferinfo_callback fxferinfo; /* progress callback */
   curl_debug_callback fdebug;      /* function that write informational data */
@@ -1555,8 +1571,9 @@ struct UserDefined {
   long accepttimeout;   /* in milliseconds, 0 means no timeout */
   long happy_eyeballs_timeout; /* in milliseconds, 0 is a valid value */
   long server_response_timeout; /* in milliseconds, 0 means no timeout */
+  long maxage_conn;     /* in seconds, max idle time to allow a connection that
+                           is to be reused */
   long tftp_blksize;    /* in bytes, 0 means use default */
-  bool tftp_no_options; /* do not send TFTP options requests */
   curl_off_t filesize;  /* size of file to upload, -1 means unknown */
   long low_speed_limit; /* bytes/second */
   long low_speed_time;  /* number of seconds */
@@ -1568,9 +1585,6 @@ struct UserDefined {
   struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */
   struct curl_httppost *httppost;  /* linked list of old POST data */
   curl_mimepart mimepost;  /* MIME/POST data. */
-  bool sep_headers;     /* handle host and proxy headers separately */
-  bool cookiesession;   /* new cookie session? */
-  bool crlf;            /* convert crlf on ftp upload(?) */
   struct curl_slist *quote;     /* after connection is established */
   struct curl_slist *postquote; /* after the transfer */
   struct curl_slist *prequote; /* before the transfer, after type */
@@ -1589,7 +1603,6 @@ struct UserDefined {
   Curl_HttpReq httpreq;   /* what kind of HTTP request (if any) is this */
   long httpversion; /* when non-zero, a specific HTTP version requested to
                        be used in the library's request(s) */
-  bool strip_path_slash; /* strip off initial slash from path */
   struct ssl_config_data ssl;  /* user defined SSL stuff */
   struct ssl_config_data proxy_ssl;  /* user defined SSL stuff for proxy */
   struct ssl_general_config general_ssl; /* general user defined SSL stuff */
@@ -1599,87 +1612,35 @@ struct UserDefined {
   size_t upload_buffer_size; /* size of upload buffer to use,
                                 keep it >= CURL_MAX_WRITE_SIZE */
   void *private_data; /* application-private data */
-
   struct curl_slist *http200aliases; /* linked list of aliases for http200 */
-
   long ipver; /* the CURL_IPRESOLVE_* defines in the public header file
                  0 - whatever, 1 - v2, 2 - v6 */
-
   curl_off_t max_filesize; /* Maximum file size to download */
-
+#ifndef CURL_DISABLE_FTP
   curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used  */
-
+  curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */
+  curl_ftpccc ftp_ccc;   /* FTP CCC options */
+#endif
   int ftp_create_missing_dirs; /* 1 - create directories that don't exist
                                   2 - the same but also allow MKD to fail once
                                */
-
   curl_sshkeycallback ssh_keyfunc; /* key matching callback */
   void *ssh_keyfunc_userp;         /* custom pointer to callback */
-  bool ssh_compression;            /* enable SSH compression */
-
-/* Here follows boolean settings that define how to behave during
-   this session. They are STATIC, set by libcurl users or at least initially
-   and they don't change during operations. */
-  bool get_filetime;     /* get the time and get of the remote file */
-  bool tunnel_thru_httpproxy; /* use CONNECT through a HTTP proxy */
-  bool prefer_ascii;     /* ASCII rather than binary */
-  bool ftp_append;       /* append, not overwrite, on upload */
-  bool ftp_list_only;    /* switch FTP command for listing directories */
-  bool ftp_use_port;     /* use the FTP PORT command */
-  bool hide_progress;    /* don't use the progress meter */
-  bool http_fail_on_error;  /* fail on HTTP error codes >= 400 */
-  bool http_keep_sending_on_error; /* for HTTP status codes >= 300 */
-  bool http_follow_location; /* follow HTTP redirects */
-  bool http_transfer_encoding; /* request compressed HTTP transfer-encoding */
-  bool allow_auth_to_other_hosts;
-  bool include_header;   /* include received protocol headers in data output */
-  bool http_set_referer; /* is a custom referer used */
-  bool http_auto_referer; /* set "correct" referer when following location: */
-  bool opt_no_body;      /* as set with CURLOPT_NOBODY */
-  bool upload;           /* upload request */
   enum CURL_NETRC_OPTION
        use_netrc;        /* defined in include/curl.h */
-  bool verbose;          /* output verbosity */
-  bool krb;              /* Kerberos connection requested */
-  bool reuse_forbid;     /* forbidden to be reused, close after use */
-  bool reuse_fresh;      /* do not re-use an existing connection  */
-  bool ftp_use_epsv;     /* if EPSV is to be attempted or not */
-  bool ftp_use_eprt;     /* if EPRT is to be attempted or not */
-  bool ftp_use_pret;     /* if PRET is to be used before PASV or not */
-
   curl_usessl use_ssl;   /* if AUTH TLS is to be attempted etc, for FTP or
                             IMAP or POP3 or others! */
-  curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */
-  curl_ftpccc ftp_ccc;   /* FTP CCC options */
-  bool no_signal;        /* do not use any signal/alarm handler */
-  bool global_dns_cache; /* subject for future removal */
-  bool tcp_nodelay;      /* whether to enable TCP_NODELAY or not */
-  bool ignorecl;         /* ignore content length */
-  bool ftp_skip_ip;      /* skip the IP address the FTP server passes on to
-                            us */
-  bool connect_only;     /* make connection, let application use the socket */
-  long ssh_auth_types;   /* allowed SSH auth types */
-  bool http_te_skip;     /* pass the raw body data to the user, even when
-                            transfer-encoded (chunked, compressed) */
-  bool http_ce_skip;     /* pass the raw body data to the user, even when
-                            content-encoded (chunked, compressed) */
   long new_file_perms;    /* Permissions to use when creating remote files */
   long new_directory_perms; /* Permissions to use when creating remote dirs */
-  bool proxy_transfer_mode; /* set transfer mode (;type=<a|i>) when doing FTP
-                               via an HTTP proxy */
+  long ssh_auth_types;   /* allowed SSH auth types */
   char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
   unsigned int scope_id;  /* Scope id for IPv6 */
   long allowed_protocols;
   long redir_protocols;
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-  bool socks5_gssapi_nec; /* Flag to support NEC SOCKS5 server */
-#endif
   struct curl_slist *mail_rcpt; /* linked list of mail recipients */
-  bool sasl_ir;         /* Enable/disable SASL initial response */
   /* Common RTSP header options */
   Curl_RtspReq rtspreq; /* RTSP request type */
   long rtspversion; /* like httpversion, for RTSP */
-  bool wildcard_enabled; /* enable wildcard matching */
   curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer
                                         starts */
   curl_chunk_end_callback chunk_end; /* called after part transferring
@@ -1691,50 +1652,109 @@ struct UserDefined {
   long gssapi_delegation; /* GSS-API credential delegation, see the
                              documentation of CURLOPT_GSSAPI_DELEGATION */
 
-  bool tcp_keepalive;    /* use TCP keepalives */
   long tcp_keepidle;     /* seconds in idle before sending keepalive probe */
   long tcp_keepintvl;    /* seconds between TCP keepalive probes */
-  bool tcp_fastopen;     /* use TCP Fast Open */
 
-  size_t maxconnects;  /* Max idle connections in the connection cache */
+  size_t maxconnects;    /* Max idle connections in the connection cache */
 
-  bool ssl_enable_npn;      /* TLS NPN extension? */
-  bool ssl_enable_alpn;     /* TLS ALPN extension? */
-  bool path_as_is;      /* allow dotdots? */
-  bool pipewait;        /* wait for pipe/multiplex status before starting a
-                           new connection */
   long expect_100_timeout; /* in milliseconds */
-  bool suppress_connect_headers;  /* suppress proxy CONNECT response headers
-                                     from user callbacks */
-
-  bool dns_shuffle_addresses; /* whether to shuffle addresses before use */
-
   struct Curl_easy *stream_depends_on;
-  bool stream_depends_e; /* set or don't set the Exclusive bit */
   int stream_weight;
-
-  bool haproxyprotocol; /* whether to send HAProxy PROXY protocol v1 header */
-
   struct Curl_http2_dep *stream_dependents;
 
-  bool abstract_unix_socket;
-
   curl_resolver_start_callback resolver_start; /* optional callback called
                                                   before resolver start */
   void *resolver_start_client; /* pointer to pass to resolver start callback */
-  bool disallow_username_in_url; /* disallow username in url */
   long upkeep_interval_ms;      /* Time between calls for connection upkeep. */
-  bool doh; /* DNS-over-HTTPS enabled */
-  bool doh_get; /* use GET for DoH requests, instead of POST */
   multidone_func fmultidone;
   struct Curl_easy *dohfor; /* this is a DoH request for that transfer */
+  CURLU *uh; /* URL handle for the current parsed URL */
+  void *trailer_data; /* pointer to pass to trailer data callback */
+  curl_trailer_callback trailer_callback; /* trailing data callback */
+  bit is_fread_set:1; /* has read callback been set to non-NULL? */
+  bit is_fwrite_set:1; /* has write callback been set to non-NULL? */
+  bit free_referer:1; /* set TRUE if 'referer' points to a string we
+                        allocated */
+  bit tftp_no_options:1; /* do not send TFTP options requests */
+  bit sep_headers:1;     /* handle host and proxy headers separately */
+  bit cookiesession:1;   /* new cookie session? */
+  bit crlf:1;            /* convert crlf on ftp upload(?) */
+  bit strip_path_slash:1; /* strip off initial slash from path */
+  bit ssh_compression:1;            /* enable SSH compression */
+
+/* Here follows boolean settings that define how to behave during
+   this session. They are STATIC, set by libcurl users or at least initially
+   and they don't change during operations. */
+  bit get_filetime:1;     /* get the time and get of the remote file */
+  bit tunnel_thru_httpproxy:1; /* use CONNECT through a HTTP proxy */
+  bit prefer_ascii:1;     /* ASCII rather than binary */
+  bit ftp_append:1;       /* append, not overwrite, on upload */
+  bit ftp_list_only:1;    /* switch FTP command for listing directories */
+#ifndef CURL_DISABLE_FTP
+  bit ftp_use_port:1;     /* use the FTP PORT command */
+  bit ftp_use_epsv:1;   /* if EPSV is to be attempted or not */
+  bit ftp_use_eprt:1;   /* if EPRT is to be attempted or not */
+  bit ftp_use_pret:1;   /* if PRET is to be used before PASV or not */
+  bit ftp_skip_ip:1;    /* skip the IP address the FTP server passes on to
+                            us */
+#endif
+  bit hide_progress:1;    /* don't use the progress meter */
+  bit http_fail_on_error:1;  /* fail on HTTP error codes >= 400 */
+  bit http_keep_sending_on_error:1; /* for HTTP status codes >= 300 */
+  bit http_follow_location:1; /* follow HTTP redirects */
+  bit http_transfer_encoding:1; /* request compressed HTTP
+                                    transfer-encoding */
+  bit allow_auth_to_other_hosts:1;
+  bit include_header:1; /* include received protocol headers in data output */
+  bit http_set_referer:1; /* is a custom referer used */
+  bit http_auto_referer:1; /* set "correct" referer when following
+                               location: */
+  bit opt_no_body:1;    /* as set with CURLOPT_NOBODY */
+  bit upload:1;         /* upload request */
+  bit verbose:1;        /* output verbosity */
+  bit krb:1;            /* Kerberos connection requested */
+  bit reuse_forbid:1;   /* forbidden to be reused, close after use */
+  bit reuse_fresh:1;    /* do not re-use an existing connection  */
+
+  bit no_signal:1;      /* do not use any signal/alarm handler */
+  bit tcp_nodelay:1;    /* whether to enable TCP_NODELAY or not */
+  bit ignorecl:1;       /* ignore content length */
+  bit connect_only:1;   /* make connection, let application use the socket */
+  bit http_te_skip:1;   /* pass the raw body data to the user, even when
+                            transfer-encoded (chunked, compressed) */
+  bit http_ce_skip:1;   /* pass the raw body data to the user, even when
+                            content-encoded (chunked, compressed) */
+  bit proxy_transfer_mode:1; /* set transfer mode (;type=<a|i>) when doing
+                                 FTP via an HTTP proxy */
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+  bit socks5_gssapi_nec:1; /* Flag to support NEC SOCKS5 server */
+#endif
+  bit sasl_ir:1;         /* Enable/disable SASL initial response */
+  bit wildcard_enabled:1; /* enable wildcard matching */
+  bit tcp_keepalive:1;  /* use TCP keepalives */
+  bit tcp_fastopen:1;   /* use TCP Fast Open */
+  bit ssl_enable_npn:1; /* TLS NPN extension? */
+  bit ssl_enable_alpn:1;/* TLS ALPN extension? */
+  bit path_as_is:1;     /* allow dotdots? */
+  bit pipewait:1;       /* wait for multiplex status before starting a new
+                           connection */
+  bit suppress_connect_headers:1; /* suppress proxy CONNECT response headers
+                                      from user callbacks */
+  bit dns_shuffle_addresses:1; /* whether to shuffle addresses before use */
+  bit stream_depends_e:1; /* set or don't set the Exclusive bit */
+  bit haproxyprotocol:1; /* whether to send HAProxy PROXY protocol v1
+                             header */
+  bit abstract_unix_socket:1;
+  bit disallow_username_in_url:1; /* disallow username in url */
+  bit doh:1; /* DNS-over-HTTPS enabled */
+  bit doh_get:1; /* use GET for DoH requests, instead of POST */
+  bit http09_allowed:1; /* allow HTTP/0.9 responses */
 };
 
 struct Names {
   struct curl_hash *hostcache;
   enum {
     HCACHE_NONE,    /* not pointing to anything */
-    HCACHE_GLOBAL,  /* points to the (shrug) global one */
     HCACHE_MULTI,   /* points to a shared one in the multi handle */
     HCACHE_SHARED   /* points to a shared one in a shared object */
   } hostcachetype;
@@ -1755,9 +1775,10 @@ struct Curl_easy {
   struct Curl_easy *next;
   struct Curl_easy *prev;
 
-  struct connectdata *easy_conn;     /* the "unit's" connection */
+  struct connectdata *conn;
   struct curl_llist_element connect_queue;
-  struct curl_llist_element pipeline_queue;
+  struct curl_llist_element sh_queue; /* list per Curl_sh_entry */
+  struct curl_llist_element conn_queue; /* list per connectdata */
 
   CURLMstate mstate;  /* the handle's state */
   CURLcode result;   /* previous result */
@@ -1769,6 +1790,8 @@ struct Curl_easy {
      the state etc are also kept. This array is mostly used to detect when a
      socket is to be removed from the hash. See singlesocket(). */
   curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
+  int actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in
+                                          sockets[] */
   int numsocks;
 
   struct Names dns;
@@ -1789,10 +1812,15 @@ struct Curl_easy {
                                   NOTE that the 'cookie' field in the
                                   UserDefined struct defines if the "engine"
                                   is to be used or not. */
+#ifdef USE_ALTSVC
+  struct altsvcinfo *asi;      /* the alt-svc cache */
+#endif
   struct Progress progress;    /* for all the progress meter data */
   struct UrlState state;       /* struct for fields used for state info and
                                   other dynamic purposes */
+#ifndef CURL_DISABLE_FTP
   struct WildcardData wildcard; /* wildcard download state info */
+#endif
   struct PureInfo info;        /* stats, reports and info data */
   struct curl_tlssessioninfo tsi; /* Information about the TLS session, only
                                      valid after a client has asked for it */
diff --git a/lib/vauth/cleartext.c b/lib/vauth/cleartext.c
index be6d611..6f452c1 100644
--- a/lib/vauth/cleartext.c
+++ b/lib/vauth/cleartext.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -25,6 +25,9 @@
 
 #include "curl_setup.h"
 
+#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) ||       \
+  !defined(CURL_DISABLE_POP3)
+
 #include <curl/curl.h>
 #include "urldata.h"
 
@@ -49,8 +52,9 @@
  * Parameters:
  *
  * data    [in]     - The session handle.
- * userp   [in]     - The user name.
- * passwdp [in]     - The user's password.
+ * authzid [in]     - The authorization identity.
+ * authcid [in]     - The authentication identity.
+ * passwd  [in]     - The password.
  * outptr  [in/out] - The address where a pointer to newly allocated memory
  *                    holding the result will be stored upon completion.
  * outlen  [out]    - The length of the output message.
@@ -58,36 +62,40 @@
  * Returns CURLE_OK on success.
  */
 CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
-                                        const char *userp,
-                                        const char *passwdp,
+                                        const char *authzid,
+                                        const char *authcid,
+                                        const char *passwd,
                                         char **outptr, size_t *outlen)
 {
   CURLcode result;
   char *plainauth;
-  size_t ulen;
+  size_t zlen;
+  size_t clen;
   size_t plen;
   size_t plainlen;
 
   *outlen = 0;
   *outptr = NULL;
-  ulen = strlen(userp);
-  plen = strlen(passwdp);
+  zlen = (authzid == NULL ? 0 : strlen(authzid));
+  clen = strlen(authcid);
+  plen = strlen(passwd);
 
   /* Compute binary message length. Check for overflows. */
-  if((ulen > SIZE_T_MAX/4) || (plen > (SIZE_T_MAX/2 - 2)))
+  if(((zlen + clen) > SIZE_T_MAX/4) || (plen > (SIZE_T_MAX/2 - 2)))
     return CURLE_OUT_OF_MEMORY;
-  plainlen = 2 * ulen + plen + 2;
+  plainlen = zlen + clen + plen + 2;
 
   plainauth = malloc(plainlen);
   if(!plainauth)
     return CURLE_OUT_OF_MEMORY;
 
   /* Calculate the reply */
-  memcpy(plainauth, userp, ulen);
-  plainauth[ulen] = '\0';
-  memcpy(plainauth + ulen + 1, userp, ulen);
-  plainauth[2 * ulen + 1] = '\0';
-  memcpy(plainauth + 2 * ulen + 2, passwdp, plen);
+  if(zlen != 0)
+    memcpy(plainauth, authzid, zlen);
+  plainauth[zlen] = '\0';
+  memcpy(plainauth + zlen + 1, authcid, clen);
+  plainauth[zlen + clen + 1] = '\0';
+  memcpy(plainauth + zlen + clen + 2, passwd, plen);
 
   /* Base64 encode the reply */
   result = Curl_base64_encode(data, plainauth, plainlen, outptr, outlen);
@@ -157,3 +165,5 @@ CURLcode Curl_auth_create_external_message(struct Curl_easy *data,
   /* This is the same formatting as the login message */
   return Curl_auth_create_login_message(data, user, outptr, outlen);
 }
+
+#endif /* if no users */
diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c
index ab5156e..f9cdc9d 100644
--- a/lib/vauth/digest.c
+++ b/lib/vauth/digest.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -143,7 +143,7 @@ static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */
 {
   int i;
   for(i = 0; i < 16; i++)
-    snprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
+    msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
 }
 
 /* Convert sha256 chunk to RFC7616 -suitable ascii string*/
@@ -152,7 +152,7 @@ static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */
 {
   int i;
   for(i = 0; i < 32; i++)
-    snprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
+    msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
 }
 
 /* Perform quoted-string escaping as described in RFC2616 and its errata */
@@ -432,7 +432,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
 
   /* Convert calculated 16 octet hex into 32 bytes string */
   for(i = 0; i < MD5_DIGEST_LEN; i++)
-    snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
+    msnprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
 
   /* Generate our SPN */
   spn = Curl_auth_build_spn(service, realm, NULL);
@@ -455,7 +455,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
   Curl_MD5_final(ctxt, digest);
 
   for(i = 0; i < MD5_DIGEST_LEN; i++)
-    snprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]);
+    msnprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]);
 
   /* Now calculate the response hash */
   ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
@@ -485,7 +485,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
   Curl_MD5_final(ctxt, digest);
 
   for(i = 0; i < MD5_DIGEST_LEN; i++)
-    snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]);
+    msnprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]);
 
   /* Generate the response */
   response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\","
@@ -785,8 +785,7 @@ static CURLcode _Curl_auth_create_digest_http_message(
     return CURLE_OUT_OF_MEMORY;
 
   if(digest->qop && strcasecompare(digest->qop, "auth-int")) {
-    /* We don't support auth-int for PUT or POST at the moment.
-       TODO: replace hash of empty string with entity-body for PUT/POST */
+    /* We don't support auth-int for PUT or POST */
     char hashed[65];
     unsigned char *hashthis2;
 
diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c
index 9287557..fe8093e 100644
--- a/lib/vauth/digest_sspi.c
+++ b/lib/vauth/digest_sspi.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2014 - 2016, Steve Holme, <steve_holme at hotmail.com>.
- * Copyright (C) 2015 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2015 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -146,7 +146,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
   }
 
   /* Generate our SPN */
-  spn = Curl_auth_build_spn(service, data->easy_conn->host.name, NULL);
+  spn = Curl_auth_build_spn(service, data->conn->host.name, NULL);
   if(!spn) {
     free(output_token);
     free(input_token);
diff --git a/lib/vauth/krb5_gssapi.c b/lib/vauth/krb5_gssapi.c
index 55daec1..ea0a5f1 100644
--- a/lib/vauth/krb5_gssapi.c
+++ b/lib/vauth/krb5_gssapi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2014 - 2017, Steve Holme, <steve_holme at hotmail.com>.
+ * Copyright (C) 2014 - 2019, Steve Holme, <steve_holme at hotmail.com>.
  * Copyright (C) 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
@@ -372,7 +372,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
 }
 
 /*
- * Curl_auth_gssapi_cleanup()
+ * Curl_auth_cleanup_gssapi()
  *
  * This is used to clean up the GSSAPI (Kerberos V5) specific data.
  *
@@ -381,7 +381,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
  * krb5     [in/out] - The Kerberos 5 data struct being cleaned up.
  *
  */
-void Curl_auth_gssapi_cleanup(struct kerberos5data *krb5)
+void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5)
 {
   OM_uint32 minor_status;
 
diff --git a/lib/vauth/krb5_sspi.c b/lib/vauth/krb5_sspi.c
index cb11ed9..1f6e462 100644
--- a/lib/vauth/krb5_sspi.c
+++ b/lib/vauth/krb5_sspi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2014 - 2017, Steve Holme, <steve_holme at hotmail.com>.
+ * Copyright (C) 2014 - 2019, Steve Holme, <steve_holme at hotmail.com>.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -474,7 +474,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
 }
 
 /*
- * Curl_auth_gssapi_cleanup()
+ * Curl_auth_cleanup_gssapi()
  *
  * This is used to clean up the GSSAPI (Kerberos V5) specific data.
  *
@@ -483,7 +483,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
  * krb5     [in/out] - The Kerberos 5 data struct being cleaned up.
  *
  */
-void Curl_auth_gssapi_cleanup(struct kerberos5data *krb5)
+void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5)
 {
   /* Free our security context */
   if(krb5->context) {
diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c
index 11f42f5..047c2b5 100644
--- a/lib/vauth/ntlm.c
+++ b/lib/vauth/ntlm.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -182,10 +182,11 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
     target_info_len = Curl_read16_le(&buffer[40]);
     target_info_offset = Curl_read32_le(&buffer[44]);
     if(target_info_len > 0) {
-      if(((target_info_offset + target_info_len) > size) ||
+      if((target_info_offset >= size) ||
+         ((target_info_offset + target_info_len) > size) ||
          (target_info_offset < 48)) {
         infof(data, "NTLM handshake failure (bad type-2 message). "
-                    "Target Info Offset Len is set incorrect by the peer\n");
+              "Target Info Offset Len is set incorrect by the peer\n");
         return CURLE_BAD_CONTENT_ENCODING;
       }
 
@@ -402,45 +403,45 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
   (void)hostname,
 
   /* Clean up any former leftovers and initialise to defaults */
-  Curl_auth_ntlm_cleanup(ntlm);
+  Curl_auth_cleanup_ntlm(ntlm);
 
 #if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION)
 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
 #else
 #define NTLM2FLAG 0
 #endif
-  snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
-           NTLMSSP_SIGNATURE "%c"
-           "\x01%c%c%c" /* 32-bit type = 1 */
-           "%c%c%c%c"   /* 32-bit NTLM flag field */
-           "%c%c"       /* domain length */
-           "%c%c"       /* domain allocated space */
-           "%c%c"       /* domain name offset */
-           "%c%c"       /* 2 zeroes */
-           "%c%c"       /* host length */
-           "%c%c"       /* host allocated space */
-           "%c%c"       /* host name offset */
-           "%c%c"       /* 2 zeroes */
-           "%s"         /* host name */
-           "%s",        /* domain string */
-           0,           /* trailing zero */
-           0, 0, 0,     /* part of type-1 long */
-
-           LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
-                       NTLMFLAG_REQUEST_TARGET |
-                       NTLMFLAG_NEGOTIATE_NTLM_KEY |
-                       NTLM2FLAG |
-                       NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
-           SHORTPAIR(domlen),
-           SHORTPAIR(domlen),
-           SHORTPAIR(domoff),
-           0, 0,
-           SHORTPAIR(hostlen),
-           SHORTPAIR(hostlen),
-           SHORTPAIR(hostoff),
-           0, 0,
-           host,  /* this is empty */
-           domain /* this is empty */);
+  msnprintf((char *)ntlmbuf, NTLM_BUFSIZE,
+            NTLMSSP_SIGNATURE "%c"
+            "\x01%c%c%c" /* 32-bit type = 1 */
+            "%c%c%c%c"   /* 32-bit NTLM flag field */
+            "%c%c"       /* domain length */
+            "%c%c"       /* domain allocated space */
+            "%c%c"       /* domain name offset */
+            "%c%c"       /* 2 zeroes */
+            "%c%c"       /* host length */
+            "%c%c"       /* host allocated space */
+            "%c%c"       /* host name offset */
+            "%c%c"       /* 2 zeroes */
+            "%s"         /* host name */
+            "%s",        /* domain string */
+            0,           /* trailing zero */
+            0, 0, 0,     /* part of type-1 long */
+
+            LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
+                        NTLMFLAG_REQUEST_TARGET |
+                        NTLMFLAG_NEGOTIATE_NTLM_KEY |
+                        NTLM2FLAG |
+                        NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
+            SHORTPAIR(domlen),
+            SHORTPAIR(domlen),
+            SHORTPAIR(domoff),
+            0, 0,
+            SHORTPAIR(hostlen),
+            SHORTPAIR(hostlen),
+            SHORTPAIR(hostoff),
+            0, 0,
+            host,  /* this is empty */
+            domain /* this is empty */);
 
   /* Initial packet length */
   size = 32 + hostlen + domlen;
@@ -562,7 +563,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
   }
 
 #if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2)
-  if(ntlm->target_info_len) {
+  if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
     unsigned char ntbuffer[0x18];
     unsigned char entropy[8];
     unsigned char ntlmv2hash[0x18];
@@ -599,7 +600,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
 
 #if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION)
   /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
-  if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
+  if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) {
     unsigned char ntbuffer[0x18];
     unsigned char tmp[0x18];
     unsigned char md5sum[MD5_DIGEST_LENGTH];
@@ -631,7 +632,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
     Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
 
     /* End of NTLM2 Session code */
-
+    /* NTLM v2 session security is a misnomer because it is not NTLM v2.
+       It is NTLM v1 using the extended session security that is also
+       in NTLM v2 */
   }
   else
 #endif
@@ -678,88 +681,88 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
   hostoff = useroff + userlen;
 
   /* Create the big type-3 message binary blob */
-  size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
-                  NTLMSSP_SIGNATURE "%c"
-                  "\x03%c%c%c"  /* 32-bit type = 3 */
-
-                  "%c%c"  /* LanManager length */
-                  "%c%c"  /* LanManager allocated space */
-                  "%c%c"  /* LanManager offset */
-                  "%c%c"  /* 2 zeroes */
-
-                  "%c%c"  /* NT-response length */
-                  "%c%c"  /* NT-response allocated space */
-                  "%c%c"  /* NT-response offset */
-                  "%c%c"  /* 2 zeroes */
-
-                  "%c%c"  /* domain length */
-                  "%c%c"  /* domain allocated space */
-                  "%c%c"  /* domain name offset */
-                  "%c%c"  /* 2 zeroes */
-
-                  "%c%c"  /* user length */
-                  "%c%c"  /* user allocated space */
-                  "%c%c"  /* user offset */
-                  "%c%c"  /* 2 zeroes */
-
-                  "%c%c"  /* host length */
-                  "%c%c"  /* host allocated space */
-                  "%c%c"  /* host offset */
-                  "%c%c"  /* 2 zeroes */
-
-                  "%c%c"  /* session key length (unknown purpose) */
-                  "%c%c"  /* session key allocated space (unknown purpose) */
-                  "%c%c"  /* session key offset (unknown purpose) */
-                  "%c%c"  /* 2 zeroes */
-
-                  "%c%c%c%c",  /* flags */
-
-                  /* domain string */
-                  /* user string */
-                  /* host string */
-                  /* LanManager response */
-                  /* NT response */
-
-                  0,                /* zero termination */
-                  0, 0, 0,          /* type-3 long, the 24 upper bits */
-
-                  SHORTPAIR(0x18),  /* LanManager response length, twice */
-                  SHORTPAIR(0x18),
-                  SHORTPAIR(lmrespoff),
-                  0x0, 0x0,
+  size = msnprintf((char *)ntlmbuf, NTLM_BUFSIZE,
+                   NTLMSSP_SIGNATURE "%c"
+                   "\x03%c%c%c"  /* 32-bit type = 3 */
+
+                   "%c%c"  /* LanManager length */
+                   "%c%c"  /* LanManager allocated space */
+                   "%c%c"  /* LanManager offset */
+                   "%c%c"  /* 2 zeroes */
+
+                   "%c%c"  /* NT-response length */
+                   "%c%c"  /* NT-response allocated space */
+                   "%c%c"  /* NT-response offset */
+                   "%c%c"  /* 2 zeroes */
+
+                   "%c%c"  /* domain length */
+                   "%c%c"  /* domain allocated space */
+                   "%c%c"  /* domain name offset */
+                   "%c%c"  /* 2 zeroes */
+
+                   "%c%c"  /* user length */
+                   "%c%c"  /* user allocated space */
+                   "%c%c"  /* user offset */
+                   "%c%c"  /* 2 zeroes */
+
+                   "%c%c"  /* host length */
+                   "%c%c"  /* host allocated space */
+                   "%c%c"  /* host offset */
+                   "%c%c"  /* 2 zeroes */
+
+                   "%c%c"  /* session key length (unknown purpose) */
+                   "%c%c"  /* session key allocated space (unknown purpose) */
+                   "%c%c"  /* session key offset (unknown purpose) */
+                   "%c%c"  /* 2 zeroes */
+
+                   "%c%c%c%c",  /* flags */
+
+                   /* domain string */
+                   /* user string */
+                   /* host string */
+                   /* LanManager response */
+                   /* NT response */
+
+                   0,                /* zero termination */
+                   0, 0, 0,          /* type-3 long, the 24 upper bits */
+
+                   SHORTPAIR(0x18),  /* LanManager response length, twice */
+                   SHORTPAIR(0x18),
+                   SHORTPAIR(lmrespoff),
+                   0x0, 0x0,
 
 #ifdef USE_NTRESPONSES
-                  SHORTPAIR(ntresplen),  /* NT-response length, twice */
-                  SHORTPAIR(ntresplen),
-                  SHORTPAIR(ntrespoff),
-                  0x0, 0x0,
+                   SHORTPAIR(ntresplen),  /* NT-response length, twice */
+                   SHORTPAIR(ntresplen),
+                   SHORTPAIR(ntrespoff),
+                   0x0, 0x0,
 #else
-                  0x0, 0x0,
-                  0x0, 0x0,
-                  0x0, 0x0,
-                  0x0, 0x0,
+                   0x0, 0x0,
+                   0x0, 0x0,
+                   0x0, 0x0,
+                   0x0, 0x0,
 #endif
-                  SHORTPAIR(domlen),
-                  SHORTPAIR(domlen),
-                  SHORTPAIR(domoff),
-                  0x0, 0x0,
+                   SHORTPAIR(domlen),
+                   SHORTPAIR(domlen),
+                   SHORTPAIR(domoff),
+                   0x0, 0x0,
 
-                  SHORTPAIR(userlen),
-                  SHORTPAIR(userlen),
-                  SHORTPAIR(useroff),
-                  0x0, 0x0,
+                   SHORTPAIR(userlen),
+                   SHORTPAIR(userlen),
+                   SHORTPAIR(useroff),
+                   0x0, 0x0,
 
-                  SHORTPAIR(hostlen),
-                  SHORTPAIR(hostlen),
-                  SHORTPAIR(hostoff),
-                  0x0, 0x0,
+                   SHORTPAIR(hostlen),
+                   SHORTPAIR(hostlen),
+                   SHORTPAIR(hostoff),
+                   0x0, 0x0,
 
-                  0x0, 0x0,
-                  0x0, 0x0,
-                  0x0, 0x0,
-                  0x0, 0x0,
+                   0x0, 0x0,
+                   0x0, 0x0,
+                   0x0, 0x0,
+                   0x0, 0x0,
 
-                  LONGQUARTET(ntlm->flags));
+                   LONGQUARTET(ntlm->flags));
 
   DEBUGASSERT(size == 64);
   DEBUGASSERT(size == (size_t)lmrespoff);
@@ -776,11 +779,14 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
   });
 
 #ifdef USE_NTRESPONSES
-  if(size < (NTLM_BUFSIZE - ntresplen)) {
-    DEBUGASSERT(size == (size_t)ntrespoff);
-    memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
-    size += ntresplen;
+  /* ntresplen + size should not be risking an integer overflow here */
+  if(ntresplen + size > sizeof(ntlmbuf)) {
+    failf(data, "incoming NTLM message too big");
+    return CURLE_OUT_OF_MEMORY;
   }
+  DEBUGASSERT(size == (size_t)ntrespoff);
+  memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
+  size += ntresplen;
 
   DEBUG_OUT({
     fprintf(stderr, "\n   ntresp=");
@@ -838,22 +844,22 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
   /* Return with binary blob encoded into base64 */
   result = Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen);
 
-  Curl_auth_ntlm_cleanup(ntlm);
+  Curl_auth_cleanup_ntlm(ntlm);
 
   return result;
 }
 
 /*
-* Curl_auth_ntlm_cleanup()
-*
-* This is used to clean up the NTLM specific data.
-*
-* Parameters:
-*
-* ntlm    [in/out] - The NTLM data struct being cleaned up.
-*
-*/
-void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
+ * Curl_auth_cleanup_ntlm()
+ *
+ * This is used to clean up the NTLM specific data.
+ *
+ * Parameters:
+ *
+ * ntlm    [in/out] - The NTLM data struct being cleaned up.
+ *
+ */
+void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm)
 {
   /* Free the target info */
   Curl_safefree(ntlm->target_info);
diff --git a/lib/vauth/ntlm_sspi.c b/lib/vauth/ntlm_sspi.c
index b66cfe7..589cca1 100644
--- a/lib/vauth/ntlm_sspi.c
+++ b/lib/vauth/ntlm_sspi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -95,7 +95,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
   TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
 
   /* Clean up any former leftovers and initialise to defaults */
-  Curl_auth_ntlm_cleanup(ntlm);
+  Curl_auth_cleanup_ntlm(ntlm);
 
   /* Query the security package for NTLM */
   status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
@@ -249,7 +249,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
                                              char **outptr, size_t *outlen)
 {
   CURLcode result = CURLE_OK;
-  SecBuffer type_2_buf;
+  SecBuffer type_2_bufs[2];
   SecBuffer type_3_buf;
   SecBufferDesc type_2_desc;
   SecBufferDesc type_3_desc;
@@ -261,12 +261,39 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
   (void) userp;
 
   /* Setup the type-2 "input" security buffer */
-  type_2_desc.ulVersion = SECBUFFER_VERSION;
-  type_2_desc.cBuffers  = 1;
-  type_2_desc.pBuffers  = &type_2_buf;
-  type_2_buf.BufferType = SECBUFFER_TOKEN;
-  type_2_buf.pvBuffer   = ntlm->input_token;
-  type_2_buf.cbBuffer   = curlx_uztoul(ntlm->input_token_len);
+  type_2_desc.ulVersion     = SECBUFFER_VERSION;
+  type_2_desc.cBuffers      = 1;
+  type_2_desc.pBuffers      = &type_2_bufs[0];
+  type_2_bufs[0].BufferType = SECBUFFER_TOKEN;
+  type_2_bufs[0].pvBuffer   = ntlm->input_token;
+  type_2_bufs[0].cbBuffer   = curlx_uztoul(ntlm->input_token_len);
+
+#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
+  /* ssl context comes from schannel.
+  * When extended protection is used in IIS server,
+  * we have to pass a second SecBuffer to the SecBufferDesc
+  * otherwise IIS will not pass the authentication (401 response).
+  * Minimum supported version is Windows 7.
+  * https://docs.microsoft.com/en-us/security-updates
+  * /SecurityAdvisories/2009/973811
+  */
+  if(ntlm->sslContext) {
+    SEC_CHANNEL_BINDINGS channelBindings;
+    SecPkgContext_Bindings pkgBindings;
+    pkgBindings.Bindings = &channelBindings;
+    status = s_pSecFn->QueryContextAttributes(
+      ntlm->sslContext,
+      SECPKG_ATTR_ENDPOINT_BINDINGS,
+      &pkgBindings
+    );
+    if(status == SEC_E_OK) {
+      type_2_desc.cBuffers++;
+      type_2_bufs[1].BufferType = SECBUFFER_CHANNEL_BINDINGS;
+      type_2_bufs[1].cbBuffer = pkgBindings.BindingsLength;
+      type_2_bufs[1].pvBuffer = pkgBindings.Bindings;
+    }
+  }
+#endif
 
   /* Setup the type-3 "output" security buffer */
   type_3_desc.ulVersion = SECBUFFER_VERSION;
@@ -296,13 +323,13 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
   result = Curl_base64_encode(data, (char *) ntlm->output_token,
                               type_3_buf.cbBuffer, outptr, outlen);
 
-  Curl_auth_ntlm_cleanup(ntlm);
+  Curl_auth_cleanup_ntlm(ntlm);
 
   return result;
 }
 
 /*
- * Curl_auth_ntlm_cleanup()
+ * Curl_auth_cleanup_ntlm()
  *
  * This is used to clean up the NTLM specific data.
  *
@@ -311,7 +338,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
  * ntlm    [in/out] - The NTLM data struct being cleaned up.
  *
  */
-void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
+void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm)
 {
   /* Free our security context */
   if(ntlm->context) {
diff --git a/lib/vauth/oauth2.c b/lib/vauth/oauth2.c
index 6288f89..b4e9f8e 100644
--- a/lib/vauth/oauth2.c
+++ b/lib/vauth/oauth2.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -24,6 +24,9 @@
 
 #include "curl_setup.h"
 
+#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \
+  !defined(CURL_DISABLE_POP3)
+
 #include <curl/curl.h>
 #include "urldata.h"
 
@@ -46,8 +49,8 @@
  *
  * data[in]         - The session handle.
  * user[in]         - The user name.
- * host[in]         - The host name(for OAUTHBEARER).
- * port[in]         - The port(for OAUTHBEARER when not Port 80).
+ * host[in]         - The host name.
+ * port[in]         - The port(when not Port 80).
  * bearer[in]       - The bearer token.
  * outptr[in / out] - The address where a pointer to newly allocated memory
  *                    holding the result will be stored upon completion.
@@ -66,13 +69,11 @@ CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data,
   char *oauth = NULL;
 
   /* Generate the message */
-  if(host == NULL && (port == 0 || port == 80))
-    oauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer);
-  else if(port == 0 || port == 80)
-    oauth = aprintf("user=%s\1host=%s\1auth=Bearer %s\1\1", user, host,
+  if(port == 0 || port == 80)
+    oauth = aprintf("n,a=%s,\1host=%s\1auth=Bearer %s\1\1", user, host,
                     bearer);
   else
-    oauth = aprintf("user=%s\1host=%s\1port=%ld\1auth=Bearer %s\1\1", user,
+    oauth = aprintf("n,a=%s,\1host=%s\1port=%ld\1auth=Bearer %s\1\1", user,
                     host, port, bearer);
   if(!oauth)
     return CURLE_OUT_OF_MEMORY;
@@ -84,3 +85,42 @@ CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data,
 
   return result;
 }
+
+/*
+ * Curl_auth_create_xoauth_bearer_message()
+ *
+ * This is used to generate an already encoded XOAuth 2.0 message ready for
+ * sending to the recipient.
+ *
+ * Parameters:
+ *
+ * data[in]         - The session handle.
+ * user[in]         - The user name.
+ * bearer[in]       - The bearer token.
+ * outptr[in / out] - The address where a pointer to newly allocated memory
+ *                    holding the result will be stored upon completion.
+ * outlen[out]      - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data,
+                                               const char *user,
+                                               const char *bearer,
+                                               char **outptr, size_t *outlen)
+{
+  CURLcode result = CURLE_OK;
+
+  /* Generate the message */
+  char *xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer);
+  if(!xoauth)
+    return CURLE_OUT_OF_MEMORY;
+
+  /* Base64 encode the reply */
+  result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen);
+
+  free(xoauth);
+
+  return result;
+}
+#endif /* disabled, no users */
+
diff --git a/lib/vauth/spnego_gssapi.c b/lib/vauth/spnego_gssapi.c
index 4a48bdd..5d43e11 100644
--- a/lib/vauth/spnego_gssapi.c
+++ b/lib/vauth/spnego_gssapi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -97,7 +97,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
     /* We finished successfully our part of authentication, but server
      * rejected it (since we're again here). Exit with an error since we
      * can't invent anything better */
-    Curl_auth_spnego_cleanup(nego);
+    Curl_auth_cleanup_spnego(nego);
     return CURLE_LOGIN_DENIED;
   }
 
@@ -170,7 +170,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
     Curl_gss_log_error(data, "gss_init_sec_context() failed: ",
                        major_status, minor_status);
 
-    return CURLE_OUT_OF_MEMORY;
+    return CURLE_LOGIN_DENIED;
   }
 
   if(!output_token.value || !output_token.length) {
@@ -238,7 +238,7 @@ CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data,
 }
 
 /*
- * Curl_auth_spnego_cleanup()
+ * Curl_auth_cleanup_spnego()
  *
  * This is used to clean up the SPNEGO (Negotiate) specific data.
  *
@@ -247,7 +247,7 @@ CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data,
  * nego     [in/out] - The Negotiate data struct being cleaned up.
  *
  */
-void Curl_auth_spnego_cleanup(struct negotiatedata *nego)
+void Curl_auth_cleanup_spnego(struct negotiatedata *nego)
 {
   OM_uint32 minor_status;
 
@@ -273,6 +273,10 @@ void Curl_auth_spnego_cleanup(struct negotiatedata *nego)
 
   /* Reset any variables */
   nego->status = 0;
+  nego->noauthpersist = FALSE;
+  nego->havenoauthpersist = FALSE;
+  nego->havenegdata = FALSE;
+  nego->havemultiplerequests = FALSE;
 }
 
 #endif /* HAVE_GSSAPI && USE_SPNEGO */
diff --git a/lib/vauth/spnego_sspi.c b/lib/vauth/spnego_sspi.c
index 77d1895..4b21cc7 100644
--- a/lib/vauth/spnego_sspi.c
+++ b/lib/vauth/spnego_sspi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -92,7 +92,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
   size_t chlglen = 0;
   unsigned char *chlg = NULL;
   PSecPkgInfo SecurityPackage;
-  SecBuffer chlg_buf;
+  SecBuffer chlg_buf[2];
   SecBuffer resp_buf;
   SecBufferDesc chlg_desc;
   SecBufferDesc resp_desc;
@@ -107,7 +107,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
     /* We finished successfully our part of authentication, but server
      * rejected it (since we're again here). Exit with an error since we
      * can't invent anything better */
-    Curl_auth_spnego_cleanup(nego);
+    Curl_auth_cleanup_spnego(nego);
     return CURLE_LOGIN_DENIED;
   }
 
@@ -189,12 +189,39 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
     }
 
     /* Setup the challenge "input" security buffer */
-    chlg_desc.ulVersion = SECBUFFER_VERSION;
-    chlg_desc.cBuffers  = 1;
-    chlg_desc.pBuffers  = &chlg_buf;
-    chlg_buf.BufferType = SECBUFFER_TOKEN;
-    chlg_buf.pvBuffer   = chlg;
-    chlg_buf.cbBuffer   = curlx_uztoul(chlglen);
+    chlg_desc.ulVersion    = SECBUFFER_VERSION;
+    chlg_desc.cBuffers     = 1;
+    chlg_desc.pBuffers     = &chlg_buf[0];
+    chlg_buf[0].BufferType = SECBUFFER_TOKEN;
+    chlg_buf[0].pvBuffer   = chlg;
+    chlg_buf[0].cbBuffer   = curlx_uztoul(chlglen);
+
+#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
+    /* ssl context comes from Schannel.
+    * When extended protection is used in IIS server,
+    * we have to pass a second SecBuffer to the SecBufferDesc
+    * otherwise IIS will not pass the authentication (401 response).
+    * Minimum supported version is Windows 7.
+    * https://docs.microsoft.com/en-us/security-updates
+    * /SecurityAdvisories/2009/973811
+    */
+    if(nego->sslContext) {
+      SEC_CHANNEL_BINDINGS channelBindings;
+      SecPkgContext_Bindings pkgBindings;
+      pkgBindings.Bindings = &channelBindings;
+      nego->status = s_pSecFn->QueryContextAttributes(
+          nego->sslContext,
+          SECPKG_ATTR_ENDPOINT_BINDINGS,
+          &pkgBindings
+      );
+      if(nego->status == SEC_E_OK) {
+        chlg_desc.cBuffers++;
+        chlg_buf[1].BufferType = SECBUFFER_CHANNEL_BINDINGS;
+        chlg_buf[1].cbBuffer   = pkgBindings.BindingsLength;
+        chlg_buf[1].pvBuffer   = pkgBindings.Bindings;
+      }
+    }
+#endif
   }
 
   /* Setup the response "output" security buffer */
@@ -221,8 +248,9 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
   free(chlg);
 
   if(GSS_ERROR(nego->status)) {
+    char buffer[STRERROR_LEN];
     failf(data, "InitializeSecurityContext failed: %s",
-          Curl_sspi_strerror(data->easy_conn, nego->status));
+          Curl_sspi_strerror(nego->status, buffer, sizeof(buffer)));
     return CURLE_OUT_OF_MEMORY;
   }
 
@@ -279,7 +307,7 @@ CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data,
 }
 
 /*
- * Curl_auth_spnego_cleanup()
+ * Curl_auth_cleanup_spnego()
  *
  * This is used to clean up the SPNEGO (Negotiate) specific data.
  *
@@ -288,7 +316,7 @@ CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data,
  * nego     [in/out] - The Negotiate data struct being cleaned up.
  *
  */
-void Curl_auth_spnego_cleanup(struct negotiatedata *nego)
+void Curl_auth_cleanup_spnego(struct negotiatedata *nego)
 {
   /* Free our security context */
   if(nego->context) {
@@ -315,6 +343,10 @@ void Curl_auth_spnego_cleanup(struct negotiatedata *nego)
   /* Reset any variables */
   nego->status = 0;
   nego->token_max = 0;
+  nego->noauthpersist = FALSE;
+  nego->havenoauthpersist = FALSE;
+  nego->havenegdata = FALSE;
+  nego->havemultiplerequests = FALSE;
 }
 
 #endif /* USE_WINDOWS_SSPI && USE_SPNEGO */
diff --git a/lib/vauth/vauth.c b/lib/vauth/vauth.c
index 502d443..a9c5c9c 100644
--- a/lib/vauth/vauth.c
+++ b/lib/vauth/vauth.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2014 - 2016, Steve Holme, <steve_holme at hotmail.com>.
+ * Copyright (C) 2014 - 2019, Steve Holme, <steve_holme at hotmail.com>.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -105,26 +105,26 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
 #endif /* USE_WINDOWS_SSPI */
 
 /*
-* Curl_auth_user_contains_domain()
-*
-* This is used to test if the specified user contains a Windows domain name as
-* follows:
-*
-* User\Domain (Down-level Logon Name)
-* User/Domain (curl Down-level format - for compatibility with existing code)
-* User at Domain (User Principal Name)
-*
-* Note: The user name may be empty when using a GSS-API library or Windows SSPI
-* as the user and domain are either obtained from the credentials cache when
-* using GSS-API or via the currently logged in user's credentials when using
-* Windows SSPI.
-*
-* Parameters:
-*
-* user  [in] - The user name.
-*
-* Returns TRUE on success; otherwise FALSE.
-*/
+ * Curl_auth_user_contains_domain()
+ *
+ * This is used to test if the specified user contains a Windows domain name as
+ * follows:
+ *
+ * Domain\User (Down-level Logon Name)
+ * Domain/User (curl Down-level format - for compatibility with existing code)
+ * User at Domain (User Principal Name)
+ *
+ * Note: The user name may be empty when using a GSS-API library or Windows
+ * SSPI as the user and domain are either obtained from the credentials cache
+ * when using GSS-API or via the currently logged in user's credentials when
+ * using Windows SSPI.
+ *
+ * Parameters:
+ *
+ * user  [in] - The user name.
+ *
+ * Returns TRUE on success; otherwise FALSE.
+ */
 bool Curl_auth_user_contains_domain(const char *user)
 {
   bool valid = FALSE;
diff --git a/lib/vauth/vauth.h b/lib/vauth/vauth.h
index f430642..73bd25e 100644
--- a/lib/vauth/vauth.h
+++ b/lib/vauth/vauth.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2014 - 2017, Steve Holme, <steve_holme at hotmail.com>.
+ * Copyright (C) 2014 - 2019, Steve Holme, <steve_holme at hotmail.com>.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -60,8 +60,9 @@ bool Curl_auth_user_contains_domain(const char *user);
 
 /* This is used to generate a base64 encoded PLAIN cleartext message */
 CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
-                                        const char *userp,
-                                        const char *passwdp,
+                                        const char *authzid,
+                                        const char *authcid,
+                                        const char *passwd,
                                         char **outptr, size_t *outlen);
 
 /* This is used to generate a base64 encoded LOGIN cleartext message */
@@ -141,7 +142,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
                                              char **outptr, size_t *outlen);
 
 /* This is used to clean up the NTLM specific data */
-void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm);
+void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm);
 #endif /* USE_NTLM */
 
 /* This is used to generate a base64 encoded OAuth 2.0 message */
@@ -151,6 +152,13 @@ CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data,
                                                const long port,
                                                const char *bearer,
                                                char **outptr, size_t *outlen);
+
+/* This is used to generate a base64 encoded XOAuth 2.0 message */
+CURLcode Curl_auth_create_xoauth_bearer_message(struct Curl_easy *data,
+                                                const char *user,
+                                                const char *bearer,
+                                                char **outptr, size_t *outlen);
+
 #if defined(USE_KERBEROS5)
 /* This is used to evaluate if GSSAPI (Kerberos V5) is supported */
 bool Curl_auth_is_gssapi_supported(void);
@@ -176,7 +184,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
                                                   size_t *outlen);
 
 /* This is used to clean up the GSSAPI specific data */
-void Curl_auth_gssapi_cleanup(struct kerberos5data *krb5);
+void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5);
 #endif /* USE_KERBEROS5 */
 
 #if defined(USE_SPNEGO)
@@ -200,7 +208,7 @@ CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data,
                                          char **outptr, size_t *outlen);
 
 /* This is used to clean up the SPNEGO specifiec data */
-void Curl_auth_spnego_cleanup(struct negotiatedata *nego);
+void Curl_auth_cleanup_spnego(struct negotiatedata *nego);
 
 #endif /* USE_SPNEGO */
 
diff --git a/lib/version.c b/lib/version.c
index 05c2cd8..14b0531 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
 
 #ifdef USE_ARES
 #  if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
-     (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
+     (defined(WIN32) || defined(__SYMBIAN32__))
 #    define CARES_STATICLIB
 #  endif
 #  include <ares.h>
@@ -95,7 +95,7 @@ static size_t brotli_version(char *buf, size_t bufsz)
   unsigned int minor = (brotli_version & 0x00FFFFFF) >> 12;
   unsigned int patch = brotli_version & 0x00000FFF;
 
-  return snprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
+  return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
 }
 #endif
 
@@ -126,12 +126,12 @@ char *curl_version(void)
   }
 
 #ifdef HAVE_LIBZ
-  len = snprintf(ptr, left, " zlib/%s", zlibVersion());
+  len = msnprintf(ptr, left, " zlib/%s", zlibVersion());
   left -= len;
   ptr += len;
 #endif
 #ifdef HAVE_BROTLI
-  len = snprintf(ptr, left, "%s", " brotli/");
+  len = msnprintf(ptr, left, "%s", " brotli/");
   left -= len;
   ptr += len;
   len = brotli_version(ptr, left);
@@ -140,45 +140,45 @@ char *curl_version(void)
 #endif
 #ifdef USE_ARES
   /* this function is only present in c-ares, not in the original ares */
-  len = snprintf(ptr, left, " c-ares/%s", ares_version(NULL));
+  len = msnprintf(ptr, left, " c-ares/%s", ares_version(NULL));
   left -= len;
   ptr += len;
 #endif
 #ifdef USE_LIBIDN2
   if(idn2_check_version(IDN2_VERSION)) {
-    len = snprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL));
+    len = msnprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL));
     left -= len;
     ptr += len;
   }
 #endif
 #ifdef USE_LIBPSL
-  len = snprintf(ptr, left, " libpsl/%s", psl_get_version());
+  len = msnprintf(ptr, left, " libpsl/%s", psl_get_version());
   left -= len;
   ptr += len;
 #endif
 #ifdef USE_WIN32_IDN
-  len = snprintf(ptr, left, " WinIDN");
+  len = msnprintf(ptr, left, " WinIDN");
   left -= len;
   ptr += len;
 #endif
 #if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
 #ifdef _LIBICONV_VERSION
-  len = snprintf(ptr, left, " iconv/%d.%d",
-                 _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
+  len = msnprintf(ptr, left, " iconv/%d.%d",
+                  _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
 #else
   /* version unknown */
-  len = snprintf(ptr, left, " iconv");
+  len = msnprintf(ptr, left, " iconv");
 #endif /* _LIBICONV_VERSION */
   left -= len;
   ptr += len;
 #endif
 #ifdef USE_LIBSSH2
-  len = snprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION);
+  len = msnprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION);
   left -= len;
   ptr += len;
 #endif
 #ifdef USE_LIBSSH
-  len = snprintf(ptr, left, " libssh/%s", CURL_LIBSSH_VERSION);
+  len = msnprintf(ptr, left, " libssh/%s", CURL_LIBSSH_VERSION);
   left -= len;
   ptr += len;
 #endif
@@ -197,14 +197,14 @@ char *curl_version(void)
     else
       suff[0] = '\0';
 
-    snprintf(ptr, left, " librtmp/%d.%d%s",
-             RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
-             suff);
+    msnprintf(ptr, left, " librtmp/%d.%d%s",
+              RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
+              suff);
 /*
   If another lib version is added below this one, this code would
   also have to do:
 
-    len = what snprintf() returned
+    len = what msnprintf() returned
 
     left -= len;
     ptr += len;
@@ -212,6 +212,10 @@ char *curl_version(void)
   }
 #endif
 
+  /* Silent scan-build even if librtmp is not enabled. */
+  (void) left;
+  (void) ptr;
+
   initialized = true;
   return version;
 }
@@ -270,7 +274,7 @@ static const char * const protocols[] = {
 #ifndef CURL_DISABLE_RTSP
   "rtsp",
 #endif
-#if defined(USE_LIBSSH) || defined(USE_LIBSSH2)
+#if defined(USE_SSH)
   "scp",
   "sftp",
 #endif
@@ -366,6 +370,9 @@ static curl_version_info_data version_info = {
 #if defined(HAVE_BROTLI)
   | CURL_VERSION_BROTLI
 #endif
+#if defined(USE_ALTSVC)
+  | CURL_VERSION_ALTSVC
+#endif
   ,
   NULL, /* ssl_version */
   0,    /* ssl_version_num, this is kept at zero */
@@ -383,12 +390,16 @@ static curl_version_info_data version_info = {
 curl_version_info_data *curl_version_info(CURLversion stamp)
 {
   static bool initialized;
-#if defined(USE_LIBSSH) || defined(USE_LIBSSH2)
+#if defined(USE_SSH)
   static char ssh_buffer[80];
 #endif
 #ifdef USE_SSL
+#ifdef CURL_WITH_MULTI_SSL
+  static char ssl_buffer[200];
+#else
   static char ssl_buffer[80];
 #endif
+#endif
 #ifdef HAVE_BROTLI
   static char brotli_buffer[80];
 #endif
@@ -436,10 +447,10 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
 #endif
 
 #if defined(USE_LIBSSH2)
-  snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION);
+  msnprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION);
   version_info.libssh_version = ssh_buffer;
 #elif defined(USE_LIBSSH)
-  snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh/%s", CURL_LIBSSH_VERSION);
+  msnprintf(ssh_buffer, sizeof(ssh_buffer), "libssh/%s", CURL_LIBSSH_VERSION);
   version_info.libssh_version = ssh_buffer;
 #endif
 
diff --git a/lib/vtls/axtls.c b/lib/vtls/axtls.c
deleted file mode 100644
index b262392..0000000
--- a/lib/vtls/axtls.c
+++ /dev/null
@@ -1,741 +0,0 @@
-/***************************************************************************
- *                                  _   _ ____  _
- *  Project                     ___| | | |  _ \| |
- *                             / __| | | | |_) | |
- *                            | (__| |_| |  _ <| |___
- *                             \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu at directv.com>.
- * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
-
-/*
- * Source file for all axTLS-specific code for the TLS/SSL layer. No code
- * but vtls.c should ever call or use these functions.
- */
-
-#include "curl_setup.h"
-
-#ifdef USE_AXTLS
-
-#error axTLS support has been disabled in curl due to doubts about quality,
-#error user dedication and a lack of use/testing. We urge users to consider
-#error using a more established TLS backend instead.
-
-#include <axTLS/config.h>
-#include <axTLS/ssl.h>
-#include "axtls.h"
-
-#include "sendf.h"
-#include "inet_pton.h"
-#include "vtls.h"
-#include "parsedate.h"
-#include "connect.h" /* for the connect timeout */
-#include "select.h"
-#include "curl_printf.h"
-#include "hostcheck.h"
-#include <unistd.h>
-
-/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
-
-struct ssl_backend_data {
-  SSL_CTX* ssl_ctx;
-  SSL*     ssl;
-};
-
-#define BACKEND connssl->backend
-
-static CURLcode map_error_to_curl(int axtls_err)
-{
-  switch(axtls_err) {
-  case SSL_ERROR_NOT_SUPPORTED:
-  case SSL_ERROR_INVALID_VERSION:
-  case -70:                       /* protocol version alert from server */
-    return CURLE_UNSUPPORTED_PROTOCOL;
-    break;
-  case SSL_ERROR_NO_CIPHER:
-    return CURLE_SSL_CIPHER;
-    break;
-  case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
-  case SSL_ERROR_NO_CERT_DEFINED:
-  case -42:                       /* bad certificate alert from server */
-  case -43:                       /* unsupported cert alert from server */
-  case -44:                       /* cert revoked alert from server */
-  case -45:                       /* cert expired alert from server */
-  case -46:                       /* cert unknown alert from server */
-    return CURLE_SSL_CERTPROBLEM;
-    break;
-  case SSL_X509_ERROR(X509_NOT_OK):
-  case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
-  case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
-  case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
-  case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
-  case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
-  case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
-  case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
-  case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
-    return CURLE_PEER_FAILED_VERIFICATION;
-    break;
-  case -48:                       /* unknown ca alert from server */
-    return CURLE_SSL_CACERT;
-    break;
-  case -49:                       /* access denied alert from server */
-    return CURLE_REMOTE_ACCESS_DENIED;
-    break;
-  case SSL_ERROR_CONN_LOST:
-  case SSL_ERROR_SOCK_SETUP_FAILURE:
-  case SSL_ERROR_INVALID_HANDSHAKE:
-  case SSL_ERROR_INVALID_PROT_MSG:
-  case SSL_ERROR_INVALID_HMAC:
-  case SSL_ERROR_INVALID_SESSION:
-  case SSL_ERROR_INVALID_KEY:     /* it's too bad this doesn't map better */
-  case SSL_ERROR_FINISHED_INVALID:
-  case SSL_ERROR_NO_CLIENT_RENOG:
-  default:
-    return CURLE_SSL_CONNECT_ERROR;
-    break;
-  }
-}
-
-static Curl_recv axtls_recv;
-static Curl_send axtls_send;
-
-static void free_ssl_structs(struct ssl_connect_data *connssl)
-{
-  if(BACKEND->ssl) {
-    ssl_free(BACKEND->ssl);
-    BACKEND->ssl = NULL;
-  }
-  if(BACKEND->ssl_ctx) {
-    ssl_ctx_free(BACKEND->ssl_ctx);
-    BACKEND->ssl_ctx = NULL;
-  }
-}
-
-/*
- * For both blocking and non-blocking connects, this function sets up the
- * ssl context and state.  This function is called after the TCP connect
- * has completed.
- */
-static CURLcode connect_prep(struct connectdata *conn, int sockindex)
-{
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  struct Curl_easy *data = conn->data;
-  SSL_CTX *ssl_ctx;
-  SSL *ssl = NULL;
-  int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
-  int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
-  int i, ssl_fcn_return;
-
-  /* Assuming users will not compile in custom key/cert to axTLS.
-  *  Also, even for blocking connects, use axTLS non-blocking feature.
-  */
-  uint32_t client_option = SSL_NO_DEFAULT_KEY |
-    SSL_SERVER_VERIFY_LATER |
-    SSL_CONNECT_IN_PARTS;
-
-  if(connssl->state == ssl_connection_complete)
-    /* to make us tolerant against being called more than once for the
-       same connection */
-    return CURLE_OK;
-
-  if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
-    failf(data, "axtls does not support CURL_SSLVERSION_MAX");
-    return CURLE_SSL_CONNECT_ERROR;
-  }
-
-
-  /* axTLS only supports TLSv1 */
-  /* check to see if we've been told to use an explicit SSL/TLS version */
-  switch(SSL_CONN_CONFIG(version)) {
-  case CURL_SSLVERSION_DEFAULT:
-  case CURL_SSLVERSION_TLSv1:
-    break;
-  default:
-    failf(data, "axTLS only supports TLS 1.0 and 1.1, "
-          "and it cannot be specified which one to use");
-    return CURLE_SSL_CONNECT_ERROR;
-  }
-
-#ifdef  AXTLSDEBUG
-  client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
-#endif /* AXTLSDEBUG */
-
-  /* Allocate an SSL_CTX struct */
-  ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
-  if(ssl_ctx == NULL) {
-    failf(data, "unable to create client SSL context");
-    return CURLE_SSL_CONNECT_ERROR;
-  }
-
-  BACKEND->ssl_ctx = ssl_ctx;
-  BACKEND->ssl = NULL;
-
-  /* Load the trusted CA cert bundle file */
-  if(SSL_CONN_CONFIG(CAfile)) {
-    if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT,
-                    SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) {
-      infof(data, "error reading ca cert file %s \n",
-            SSL_CONN_CONFIG(CAfile));
-      if(SSL_CONN_CONFIG(verifypeer)) {
-        return CURLE_SSL_CACERT_BADFILE;
-      }
-    }
-    else
-      infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile));
-  }
-
-  /* gtls.c tasks we're skipping for now:
-   * 1) certificate revocation list checking
-   * 2) dns name assignment to host
-   * 3) set protocol priority.  axTLS is TLSv1 only, so can probably ignore
-   * 4) set certificate priority.  axTLS ignores type and sends certs in
-   *  order added.  can probably ignore this.
-   */
-
-  /* Load client certificate */
-  if(SSL_SET_OPTION(cert)) {
-    i = 0;
-    /* Instead of trying to analyze cert type here, let axTLS try them all. */
-    while(cert_types[i] != 0) {
-      ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
-                                    SSL_SET_OPTION(cert), NULL);
-      if(ssl_fcn_return == SSL_OK) {
-        infof(data, "successfully read cert file %s \n",
-              SSL_SET_OPTION(cert));
-        break;
-      }
-      i++;
-    }
-    /* Tried all cert types, none worked. */
-    if(cert_types[i] == 0) {
-      failf(data, "%s is not x509 or pkcs12 format",
-            SSL_SET_OPTION(cert));
-      return CURLE_SSL_CERTPROBLEM;
-    }
-  }
-
-  /* Load client key.
-     If a pkcs12 file successfully loaded a cert, then there's nothing to do
-     because the key has already been loaded. */
-  if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) {
-    i = 0;
-    /* Instead of trying to analyze key type here, let axTLS try them all. */
-    while(key_types[i] != 0) {
-      ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
-                                    SSL_SET_OPTION(key), NULL);
-      if(ssl_fcn_return == SSL_OK) {
-        infof(data, "successfully read key file %s \n",
-              SSL_SET_OPTION(key));
-        break;
-      }
-      i++;
-    }
-    /* Tried all key types, none worked. */
-    if(key_types[i] == 0) {
-      failf(data, "Failure: %s is not a supported key file",
-            SSL_SET_OPTION(key));
-      return CURLE_SSL_CONNECT_ERROR;
-    }
-  }
-
-  /* gtls.c does more here that is being left out for now
-   * 1) set session credentials.  can probably ignore since axtls puts this
-   *    info in the ssl_ctx struct
-   * 2) setting up callbacks.  these seem gnutls specific
-   */
-
-  if(SSL_SET_OPTION(primary.sessionid)) {
-    const uint8_t *ssl_sessionid;
-    size_t ssl_idsize;
-
-    /* In axTLS, handshaking happens inside ssl_client_new. */
-    Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize,
-                              sockindex)) {
-      /* we got a session id, use it! */
-      infof(data, "SSL re-using session ID\n");
-      ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
-                           ssl_sessionid, (uint8_t)ssl_idsize, NULL);
-    }
-    Curl_ssl_sessionid_unlock(conn);
-  }
-
-  if(!ssl)
-    ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL);
-
-  BACKEND->ssl = ssl;
-  return CURLE_OK;
-}
-
-static void Curl_axtls_close(struct connectdata *conn, int sockindex)
-{
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
-  infof(conn->data, "  Curl_axtls_close\n");
-
-    /* line from openssl.c: (void)SSL_shutdown(BACKEND->ssl);
-       axTLS compat layer does nothing for SSL_shutdown */
-
-    /* The following line is from openssl.c.  There seems to be no axTLS
-       equivalent.  ssl_free and ssl_ctx_free close things.
-       SSL_set_connect_state(connssl->handle); */
-
-  free_ssl_structs(connssl);
-}
-
-/*
- * For both blocking and non-blocking connects, this function finalizes the
- * SSL connection.
- */
-static CURLcode connect_finish(struct connectdata *conn, int sockindex)
-{
-  struct Curl_easy *data = conn->data;
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  SSL *ssl = BACKEND->ssl;
-  const char *peer_CN;
-  uint32_t dns_altname_index;
-  const char *dns_altname;
-  int8_t found_subject_alt_names = 0;
-  int8_t found_subject_alt_name_matching_conn = 0;
-  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
-    conn->host.name;
-  const char * const dispname = SSL_IS_PROXY() ?
-    conn->http_proxy.host.dispname : conn->host.dispname;
-
-  /* Here, gtls.c gets the peer certificates and fails out depending on
-   * settings in "data."  axTLS api doesn't have get cert chain fcn, so omit?
-   */
-
-  /* Verify server's certificate */
-  if(SSL_CONN_CONFIG(verifypeer)) {
-    if(ssl_verify_cert(ssl) != SSL_OK) {
-      Curl_axtls_close(conn, sockindex);
-      failf(data, "server cert verify failed");
-      return CURLE_PEER_FAILED_VERIFICATION;
-    }
-  }
-  else
-    infof(data, "\t server certificate verification SKIPPED\n");
-
-  /* Here, gtls.c does issuer verification. axTLS has no straightforward
-   * equivalent, so omitting for now.*/
-
-  /* Here, gtls.c does the following
-   * 1) x509 hostname checking per RFC2818.  axTLS doesn't support this, but
-   *    it seems useful. This is now implemented, by Oscar Koeroo
-   * 2) checks cert validity based on time.  axTLS does this in ssl_verify_cert
-   * 3) displays a bunch of cert information.  axTLS doesn't support most of
-   *    this, but a couple fields are available.
-   */
-
-  /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
-     risk of an inifite loop */
-  for(dns_altname_index = 0; ; dns_altname_index++) {
-    dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index);
-    if(dns_altname == NULL) {
-      break;
-    }
-    found_subject_alt_names = 1;
-
-    infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
-          dns_altname, hostname);
-    if(Curl_cert_hostcheck(dns_altname, hostname)) {
-      found_subject_alt_name_matching_conn = 1;
-      break;
-    }
-  }
-
-  /* RFC2818 checks */
-  if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
-    if(SSL_CONN_CONFIG(verifyhost)) {
-      /* Break connection ! */
-      Curl_axtls_close(conn, sockindex);
-      failf(data, "\tsubjectAltName(s) do not match %s\n", dispname);
-      return CURLE_PEER_FAILED_VERIFICATION;
-    }
-    else
-      infof(data, "\tsubjectAltName(s) do not match %s\n", dispname);
-  }
-  else if(found_subject_alt_names == 0) {
-    /* Per RFC2818, when no Subject Alt Names were available, examine the peer
-       CN as a legacy fallback */
-    peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
-    if(peer_CN == NULL) {
-      if(SSL_CONN_CONFIG(verifyhost)) {
-        Curl_axtls_close(conn, sockindex);
-        failf(data, "unable to obtain common name from peer certificate");
-        return CURLE_PEER_FAILED_VERIFICATION;
-      }
-      else
-        infof(data, "unable to obtain common name from peer certificate");
-    }
-    else {
-      if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
-        if(SSL_CONN_CONFIG(verifyhost)) {
-          /* Break connection ! */
-          Curl_axtls_close(conn, sockindex);
-          failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
-                peer_CN, dispname);
-          return CURLE_PEER_FAILED_VERIFICATION;
-        }
-        else
-          infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
-                peer_CN, dispname);
-      }
-    }
-  }
-
-  /* General housekeeping */
-  connssl->state = ssl_connection_complete;
-  conn->recv[sockindex] = axtls_recv;
-  conn->send[sockindex] = axtls_send;
-
-  /* Put our freshly minted SSL session in cache */
-  if(SSL_SET_OPTION(primary.sessionid)) {
-    const uint8_t *ssl_sessionid = ssl_get_session_id(ssl);
-    size_t ssl_idsize = ssl_get_session_id_size(ssl);
-    Curl_ssl_sessionid_lock(conn);
-    if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize,
-                             sockindex) != CURLE_OK)
-      infof(data, "failed to add session to cache\n");
-    Curl_ssl_sessionid_unlock(conn);
-  }
-
-  return CURLE_OK;
-}
-
-/*
- * Use axTLS's non-blocking connection feature to open an SSL connection.
- * This is called after a TCP connection is already established.
- */
-static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn,
-                                               int sockindex, bool *done)
-{
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  CURLcode conn_step;
-  int ssl_fcn_return;
-  int i;
-
- *done = FALSE;
-  /* connectdata is calloc'd and connecting_state is only changed in this
-     function, so this is safe, as the state is effectively initialized. */
-  if(connssl->connecting_state == ssl_connect_1) {
-    conn_step = connect_prep(conn, sockindex);
-    if(conn_step != CURLE_OK) {
-      Curl_axtls_close(conn, sockindex);
-      return conn_step;
-    }
-    connssl->connecting_state = ssl_connect_2;
-  }
-
-  if(connssl->connecting_state == ssl_connect_2) {
-    /* Check to make sure handshake was ok. */
-    if(ssl_handshake_status(BACKEND->ssl) != SSL_OK) {
-      /* Loop to perform more work in between sleeps. This is work around the
-         fact that axtls does not expose any knowledge about when work needs
-         to be performed. This can save ~25% of time on SSL handshakes. */
-      for(i = 0; i<5; i++) {
-        ssl_fcn_return = ssl_read(BACKEND->ssl, NULL);
-        if(ssl_fcn_return < 0) {
-          Curl_axtls_close(conn, sockindex);
-          ssl_display_error(ssl_fcn_return); /* goes to stdout. */
-          return map_error_to_curl(ssl_fcn_return);
-        }
-        return CURLE_OK;
-      }
-    }
-    infof(conn->data, "handshake completed successfully\n");
-    connssl->connecting_state = ssl_connect_3;
-  }
-
-  if(connssl->connecting_state == ssl_connect_3) {
-    conn_step = connect_finish(conn, sockindex);
-    if(conn_step != CURLE_OK) {
-      Curl_axtls_close(conn, sockindex);
-      return conn_step;
-    }
-
-    /* Reset connect state */
-    connssl->connecting_state = ssl_connect_1;
-
-    *done = TRUE;
-    return CURLE_OK;
-  }
-
-  /* Unrecognized state.  Things are very bad. */
-  connssl->state  = ssl_connection_none;
-  connssl->connecting_state = ssl_connect_1;
-  /* Return value perhaps not strictly correct, but distinguishes the issue.*/
-  return CURLE_BAD_FUNCTION_ARGUMENT;
-}
-
-
-/*
- * This function is called after the TCP connect has completed. Setup the TLS
- * layer and do all necessary magic for a blocking connect.
- */
-static CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex)
-{
-  struct Curl_easy *data = conn->data;
-  CURLcode conn_step = connect_prep(conn, sockindex);
-  int ssl_fcn_return;
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  SSL *ssl = BACKEND->ssl;
-  long timeout_ms;
-
-  if(conn_step != CURLE_OK) {
-    Curl_axtls_close(conn, sockindex);
-    return conn_step;
-  }
-
-  /* Check to make sure handshake was ok. */
-  while(ssl_handshake_status(ssl) != SSL_OK) {
-    /* check allowed time left */
-    timeout_ms = Curl_timeleft(data, NULL, TRUE);
-
-    if(timeout_ms < 0) {
-      /* no need to continue if time already is up */
-      failf(data, "SSL connection timeout");
-      return CURLE_OPERATION_TIMEDOUT;
-    }
-
-    ssl_fcn_return = ssl_read(ssl, NULL);
-    if(ssl_fcn_return < 0) {
-      Curl_axtls_close(conn, sockindex);
-      ssl_display_error(ssl_fcn_return); /* goes to stdout. */
-      return map_error_to_curl(ssl_fcn_return);
-    }
-    /* TODO: avoid polling */
-    Curl_wait_ms(10);
-  }
-  infof(conn->data, "handshake completed successfully\n");
-
-  conn_step = connect_finish(conn, sockindex);
-  if(conn_step != CURLE_OK) {
-    Curl_axtls_close(conn, sockindex);
-    return conn_step;
-  }
-
-  return CURLE_OK;
-}
-
-/* return number of sent (non-SSL) bytes */
-static ssize_t axtls_send(struct connectdata *conn,
-                          int sockindex,
-                          const void *mem,
-                          size_t len,
-                          CURLcode *err)
-{
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
-  int rc = ssl_write(BACKEND->ssl, mem, (int)len);
-
-  infof(conn->data, "  axtls_send\n");
-
-  if(rc < 0) {
-    *err = map_error_to_curl(rc);
-    rc = -1; /* generic error code for send failure */
-  }
-
-  *err = CURLE_OK;
-  return rc;
-}
-
-/*
- * This function is called to shut down the SSL layer but keep the
- * socket open (CCC - Clear Command Channel)
- */
-static int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
-{
-  /* Outline taken from openssl.c since functions are in axTLS compat layer.
-     axTLS's error set is much smaller, so a lot of error-handling was removed.
-   */
-  int retval = 0;
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  struct Curl_easy *data = conn->data;
-  uint8_t *buf;
-  ssize_t nread;
-
-  infof(conn->data, "  Curl_axtls_shutdown\n");
-
-  /* This has only been tested on the proftpd server, and the mod_tls code
-     sends a close notify alert without waiting for a close notify alert in
-     response. Thus we wait for a close notify alert from the server, but
-     we do not send one. Let's hope other servers do the same... */
-
-  /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
-  if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
-      (void)SSL_shutdown(BACKEND->ssl);
-  */
-
-  if(BACKEND->ssl) {
-    int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
-    if(what > 0) {
-      /* Something to read, let's do it and hope that it is the close
-         notify alert from the server.  buf is managed internally by
-         axTLS and will be released upon calling ssl_free via
-         free_ssl_structs. */
-      nread = (ssize_t)ssl_read(BACKEND->ssl, &buf);
-
-      if(nread < SSL_OK) {
-        failf(data, "close notify alert not received during shutdown");
-        retval = -1;
-      }
-    }
-    else if(0 == what) {
-      /* timeout */
-      failf(data, "SSL shutdown timeout");
-    }
-    else {
-      /* anything that gets here is fatally bad */
-      failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
-      retval = -1;
-    }
-
-    free_ssl_structs(connssl);
-  }
-  return retval;
-}
-
-static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
-                          int num,                  /* socketindex */
-                          char *buf,                /* store read data here */
-                          size_t buffersize,        /* max amount to read */
-                          CURLcode *err)
-{
-  struct ssl_connect_data *connssl = &conn->ssl[num];
-  ssize_t ret = 0;
-  uint8_t *read_buf;
-
-  infof(conn->data, "  axtls_recv\n");
-
-  *err = CURLE_OK;
-  if(connssl) {
-    ret = ssl_read(BACKEND->ssl, &read_buf);
-    if(ret > SSL_OK) {
-      /* ssl_read returns SSL_OK if there is more data to read, so if it is
-         larger, then all data has been read already.  */
-      memcpy(buf, read_buf,
-             (size_t)ret > buffersize ? buffersize : (size_t)ret);
-    }
-    else if(ret == SSL_OK) {
-      /* more data to be read, signal caller to call again */
-      *err = CURLE_AGAIN;
-      ret = -1;
-    }
-    else if(ret == -3) {
-      /* With patched axTLS, SSL_CLOSE_NOTIFY=-3.  Hard-coding until axTLS
-         team approves proposed fix. */
-      Curl_axtls_close(conn, num);
-    }
-    else {
-      failf(conn->data, "axTLS recv error (%d)", ret);
-      *err = map_error_to_curl((int) ret);
-      ret = -1;
-    }
-  }
-
-  return ret;
-}
-
-/*
- * Return codes:
- *     1 means the connection is still in place
- *     0 means the connection has been closed
- *    -1 means the connection status is unknown
- */
-static int Curl_axtls_check_cxn(struct connectdata *conn)
-{
-  /* openssl.c line:
-     rc = SSL_peek(conn->ssl[FIRSTSOCKET].backend->ssl, (void*)&buf, 1);
-     axTLS compat layer always returns the last argument, so connection is
-     always alive? */
-
-  infof(conn->data, "  Curl_axtls_check_cxn\n");
-   return 1; /* connection still in place */
-}
-
-static void Curl_axtls_session_free(void *ptr)
-{
-  (void)ptr;
-  /* free the ID */
-  /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL
-     compatibility layer does nothing, so we do nothing too. */
-}
-
-static size_t Curl_axtls_version(char *buffer, size_t size)
-{
-  return snprintf(buffer, size, "axTLS/%s", ssl_version());
-}
-
-static CURLcode Curl_axtls_random(struct Curl_easy *data,
-                                  unsigned char *entropy, size_t length)
-{
-  static bool ssl_seeded = FALSE;
-  (void)data;
-  if(!ssl_seeded) {
-    ssl_seeded = TRUE;
-    /* Initialize the seed if not already done. This call is not exactly thread
-     * safe (and neither is the ssl_seeded check), but the worst effect of a
-     * race condition is that some global resources will leak. */
-    RNG_initialize();
-  }
-  get_random((int)length, entropy);
-  return CURLE_OK;
-}
-
-static void *Curl_axtls_get_internals(struct ssl_connect_data *connssl,
-                                      CURLINFO info UNUSED_PARAM)
-{
-  (void)info;
-  return BACKEND->ssl;
-}
-
-const struct Curl_ssl Curl_ssl_axtls = {
-  { CURLSSLBACKEND_AXTLS, "axtls" }, /* info */
-  0, /* no fancy stuff */
-  sizeof(struct ssl_backend_data),
-
-  /*
-   * axTLS has no global init.  Everything is done through SSL and SSL_CTX
-   * structs stored in connectdata structure.
-   */
-  Curl_none_init,                 /* init */
-  /* axTLS has no global cleanup. */
-  Curl_none_cleanup,              /* cleanup */
-  Curl_axtls_version,             /* version */
-  Curl_axtls_check_cxn,           /* check_cxn */
-  Curl_axtls_shutdown,            /* shutdown */
-  Curl_none_data_pending,         /* data_pending */
-  Curl_axtls_random,              /* random */
-  Curl_none_cert_status_request,  /* cert_status_request */
-  Curl_axtls_connect,             /* connect */
-  Curl_axtls_connect_nonblocking, /* connect_nonblocking */
-  Curl_axtls_get_internals,       /* get_internals */
-  Curl_axtls_close,               /* close_one */
-  Curl_none_close_all,            /* close_all */
-  Curl_axtls_session_free,        /* session_free */
-  Curl_none_set_engine,           /* set_engine */
-  Curl_none_set_engine_default,   /* set_engine_default */
-  Curl_none_engines_list,         /* engines_list */
-  Curl_none_false_start,          /* false_start */
-  Curl_none_md5sum,               /* md5sum */
-  NULL                            /* sha256sum */
-};
-
-#endif /* USE_AXTLS */
diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c
index e10398a..44a2bdd 100644
--- a/lib/vtls/cyassl.c
+++ b/lib/vtls/cyassl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -67,15 +67,6 @@ and that's a problem since options.h hasn't been included yet. */
 #endif
 #endif
 
-/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC
-   supported curve extension in options.h. Note ECC is enabled separately. */
-#ifndef HAVE_SUPPORTED_CURVES
-#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \
-    defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE)
-#define HAVE_SUPPORTED_CURVES
-#endif
-#endif
-
 #include <limits.h>
 
 #include "urldata.h"
@@ -88,6 +79,7 @@ and that's a problem since options.h hasn't been included yet. */
 #include "strcase.h"
 #include "x509asn1.h"
 #include "curl_printf.h"
+#include "multiif.h"
 
 #include <cyassl/openssl/ssl.h>
 #include <cyassl/ssl.h>
@@ -151,7 +143,6 @@ static CURLcode
 cyassl_connect_step1(struct connectdata *conn,
                      int sockindex)
 {
-  char error_buffer[CYASSL_MAX_ERROR_SZ];
   char *ciphers;
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
@@ -364,16 +355,6 @@ cyassl_connect_step1(struct connectdata *conn,
   }
 #endif
 
-#ifdef HAVE_SUPPORTED_CURVES
-  /* CyaSSL/wolfSSL does not send the supported ECC curves ext automatically:
-     https://github.com/wolfSSL/wolfssl/issues/366
-     The supported curves below are those also supported by OpenSSL 1.0.2 and
-     in the same order. */
-  CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x17); /* secp256r1 */
-  CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x19); /* secp521r1 */
-  CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x18); /* secp384r1 */
-#endif
-
   /* give application a chance to interfere with SSL set up. */
   if(data->set.ssl.fsslctx) {
     CURLcode result = CURLE_OK;
@@ -438,6 +419,7 @@ cyassl_connect_step1(struct connectdata *conn,
     if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
       /* we got a session id, use it! */
       if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
+        char error_buffer[CYASSL_MAX_ERROR_SZ];
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "SSL: SSL_set_session failed: %s",
               ERR_error_string(SSL_get_error(BACKEND->handle, 0),
@@ -618,6 +600,8 @@ cyassl_connect_step2(struct connectdata *conn,
       else
         infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len,
               protocol);
+      Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+                          BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
     }
     else if(rc == SSL_ALPN_NOT_FOUND)
       infof(data, "ALPN, server did not agree to a protocol\n");
@@ -777,13 +761,13 @@ static void Curl_cyassl_session_free(void *ptr)
 static size_t Curl_cyassl_version(char *buffer, size_t size)
 {
 #if LIBCYASSL_VERSION_HEX >= 0x03006000
-  return snprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
+  return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
 #elif defined(WOLFSSL_VERSION)
-  return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
+  return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
 #elif defined(CYASSL_VERSION)
-  return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
+  return msnprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
 #else
-  return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8");
+  return msnprintf(buffer, size, "CyaSSL/%s", "<1.8.8");
 #endif
 }
 
@@ -794,6 +778,12 @@ static int Curl_cyassl_init(void)
 }
 
 
+static void Curl_cyassl_cleanup(void)
+{
+  CyaSSL_Cleanup();
+}
+
+
 static bool Curl_cyassl_data_pending(const struct connectdata* conn,
                                      int connindex)
 {
@@ -1004,7 +994,7 @@ const struct Curl_ssl Curl_ssl_cyassl = {
   sizeof(struct ssl_backend_data),
 
   Curl_cyassl_init,                /* init */
-  Curl_none_cleanup,               /* cleanup */
+  Curl_cyassl_cleanup,             /* cleanup */
   Curl_cyassl_version,             /* version */
   Curl_none_check_cxn,             /* check_cxn */
   Curl_cyassl_shutdown,            /* shutdown */
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index 8d1b3d6..b93ff5d 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -734,12 +734,11 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
 {
   struct ssl_connect_data *connssl = &conn->ssl[num];
   struct Curl_easy *data = conn->data;
-  int buffsize;
   int nread;
   CURLcode cc = CURLE_RECV_ERROR;
 
   if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
-    buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
+    int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
     cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
                                                 buf, buffsize, &nread),
                       "gsk_secure_soc_read()", CURLE_RECV_ERROR);
@@ -806,7 +805,6 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
     conn->host.name;
   const char *sni;
   unsigned int protoflags = 0;
-  long timeout;
   Qso_OverlappedIO_t commarea;
   int sockpair[2];
   static const int sobufsize = CURL_MAX_WRITE_SIZE;
@@ -914,7 +912,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   if(!result) {
     /* Compute the handshake timeout. Since GSKit granularity is 1 second,
        we round up the required value. */
-    timeout = Curl_timeleft(data, NULL, TRUE);
+    long timeout = Curl_timeleft(data, NULL, TRUE);
     if(timeout < 0)
       result = CURLE_OPERATION_TIMEDOUT;
     else
@@ -1021,14 +1019,13 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   Qso_OverlappedIO_t cstat;
-  long timeout_ms;
   struct timeval stmv;
   CURLcode result;
 
   /* Poll or wait for end of SSL asynchronous handshake. */
 
   for(;;) {
-    timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
+    long timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
     if(timeout_ms < 0)
       timeout_ms = 0;
     stmv.tv_sec = timeout_ms / 1000;
@@ -1077,7 +1074,6 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
   const char *cert = (const char *) NULL;
   const char *certend;
   const char *ptr;
-  int i;
   CURLcode result;
 
   /* SSL handshake done: gather certificate info and verify host. */
@@ -1087,6 +1083,8 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
                                                     &cdev, &cdec),
                   "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
      CURLE_OK) {
+    int i;
+
     infof(data, "Server certificate:\n");
     p = cdev;
     for(i = 0; i++ < cdec; p++)
@@ -1160,7 +1158,6 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   long timeout_ms;
-  Qso_OverlappedIO_t cstat;
   CURLcode result = CURLE_OK;
 
   *done = connssl->state == ssl_connection_complete;
@@ -1262,7 +1259,6 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct Curl_easy *data = conn->data;
-  ssize_t nread;
   int what;
   int rc;
   char buf[120];
@@ -1270,8 +1266,10 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
   if(!BACKEND->handle)
     return 0;
 
+#ifndef CURL_DISABLE_FTP
   if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
     return 0;
+#endif
 
   close_one(connssl, conn, sockindex);
   rc = 0;
@@ -1279,6 +1277,8 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
                          SSL_SHUTDOWN_TIMEOUT);
 
   for(;;) {
+    ssize_t nread;
+
     if(what < 0) {
       /* anything that gets here is fatally bad */
       failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -1314,7 +1314,7 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
 
 static size_t Curl_gskit_version(char *buffer, size_t size)
 {
-  return snprintf(buffer, size, "GSKit");
+  return msnprintf(buffer, size, "GSKit");
 }
 
 
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index 37662a7..8693cdc 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -55,6 +55,7 @@
 #include "strcase.h"
 #include "warnless.h"
 #include "x509asn1.h"
+#include "multiif.h"
 #include "curl_printf.h"
 #include "curl_memory.h"
 /* The last #include file should be: */
@@ -227,17 +228,17 @@ static void showtime(struct Curl_easy *data,
   if(result)
     return;
 
-  snprintf(str,
-           sizeof(str),
-           "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
-           text,
-           Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-           tm->tm_mday,
-           Curl_month[tm->tm_mon],
-           tm->tm_year + 1900,
-           tm->tm_hour,
-           tm->tm_min,
-           tm->tm_sec);
+  msnprintf(str,
+            sizeof(str),
+            "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
+            text,
+            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+            tm->tm_mday,
+            Curl_month[tm->tm_mon],
+            tm->tm_year + 1900,
+            tm->tm_hour,
+            tm->tm_min,
+            tm->tm_sec);
   infof(data, "%s\n", str);
 }
 #endif
@@ -285,11 +286,11 @@ static CURLcode handshake(struct connectdata *conn,
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   gnutls_session_t session = BACKEND->session;
   curl_socket_t sockfd = conn->sock[sockindex];
-  time_t timeout_ms;
-  int rc;
-  int what;
 
   for(;;) {
+    time_t timeout_ms;
+    int rc;
+
     /* check allowed time left */
     timeout_ms = Curl_timeleft(data, NULL, duringconnect);
 
@@ -302,7 +303,7 @@ static CURLcode handshake(struct connectdata *conn,
     /* if ssl is expecting something, check if it's available. */
     if(connssl->connecting_state == ssl_connect_2_reading
        || connssl->connecting_state == ssl_connect_2_writing) {
-
+      int what;
       curl_socket_t writefd = ssl_connect_2_writing ==
         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
       curl_socket_t readfd = ssl_connect_2_reading ==
@@ -956,7 +957,6 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
   gnutls_pubkey_t key = NULL;
 
   /* Result is returned to caller */
-  int ret = 0;
   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
 
   /* if a path wasn't specified, don't pin */
@@ -967,6 +967,8 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
     return result;
 
   do {
+    int ret;
+
     /* Begin Gyrations to get the public key     */
     gnutls_pubkey_init(&key);
 
@@ -1110,7 +1112,7 @@ gtls_connect_step3(struct connectdata *conn,
               "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
               "none",
               SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
-        return CURLE_SSL_CACERT;
+        return CURLE_PEER_FAILED_VERIFICATION;
       }
       else
         infof(data, "\t server certificate verification FAILED\n");
@@ -1278,10 +1280,7 @@ gtls_connect_step3(struct connectdata *conn,
     #define use_addr in_addr
 #endif
     unsigned char addrbuf[sizeof(struct use_addr)];
-    unsigned char certaddr[sizeof(struct use_addr)];
-    size_t addrlen = 0, certaddrlen;
-    int i;
-    int ret = 0;
+    size_t addrlen = 0;
 
     if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
       addrlen = 4;
@@ -1291,10 +1290,13 @@ gtls_connect_step3(struct connectdata *conn,
 #endif
 
     if(addrlen) {
+      unsigned char certaddr[sizeof(struct use_addr)];
+      int i;
+
       for(i = 0; ; i++) {
-        certaddrlen = sizeof(certaddr);
-        ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
-                                                   &certaddrlen, NULL);
+        size_t certaddrlen = sizeof(certaddr);
+        int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
+                                                       &certaddrlen, NULL);
         /* If this happens, it wasn't an IP address. */
         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
           continue;
@@ -1423,11 +1425,6 @@ gtls_connect_step3(struct connectdata *conn,
   size = sizeof(certbuf);
   gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
   infof(data, "\t issuer: %s\n", certbuf);
-
-  /* compression algorithm (if any) */
-  ptr = gnutls_compression_get_name(gnutls_compression_get(session));
-  /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
-  infof(data, "\t compression: %s\n", ptr);
 #endif
 
   gnutls_x509_crt_deinit(x509_cert);
@@ -1454,6 +1451,9 @@ gtls_connect_step3(struct connectdata *conn,
     }
     else
       infof(data, "ALPN, server did not agree to a protocol\n");
+
+    Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
   }
 #endif
 
@@ -1466,8 +1466,6 @@ gtls_connect_step3(struct connectdata *conn,
        already got it from the cache and asked to use it in the connection, it
        might've been rejected and then a new one is in use now and we need to
        detect that. */
-    bool incache;
-    void *ssl_sessionid;
     void *connect_sessionid;
     size_t connect_idsize = 0;
 
@@ -1476,6 +1474,9 @@ gtls_connect_step3(struct connectdata *conn,
     connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
 
     if(connect_sessionid) {
+      bool incache;
+      void *ssl_sessionid;
+
       /* extract session ID to the allocated buffer */
       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
 
@@ -1636,12 +1637,10 @@ static void Curl_gtls_close(struct connectdata *conn, int sockindex)
 static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  ssize_t result;
   int retval = 0;
   struct Curl_easy *data = conn->data;
-  bool done = FALSE;
-  char buf[120];
 
+#ifndef CURL_DISABLE_FTP
   /* This has only been tested on the proftpd server, and the mod_tls code
      sends a close notify alert without waiting for a close notify alert in
      response. Thus we wait for a close notify alert from the server, but
@@ -1649,8 +1648,13 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
 
   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
       gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR);
+#endif
 
   if(BACKEND->session) {
+    ssize_t result;
+    bool done = FALSE;
+    char buf[120];
+
     while(!done) {
       int what = SOCKET_READABLE(conn->sock[sockindex],
                                  SSL_SHUTDOWN_TIMEOUT);
@@ -1748,7 +1752,7 @@ static void Curl_gtls_session_free(void *ptr)
 
 static size_t Curl_gtls_version(char *buffer, size_t size)
 {
-  return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
+  return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
 }
 
 #ifndef USE_GNUTLS_NETTLE
@@ -1763,12 +1767,6 @@ static int Curl_gtls_seed(struct Curl_easy *data)
 
   if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
      data->set.str[STRING_SSL_EGDSOCKET]) {
-
-    /* TODO: to a good job seeding the RNG
-       This may involve the gcry_control function and these options:
-       GCRYCTL_SET_RANDOM_SEED_FILE
-       GCRYCTL_SET_RNDEGD_SOCKET
-    */
     ssl_seeded = TRUE;
   }
   return 0;
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index c5ed887..63d1f4c 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan at gmail.com>
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -54,6 +54,7 @@
 #include "parsedate.h"
 #include "connect.h" /* for the connect timeout */
 #include "select.h"
+#include "multiif.h"
 #include "polarssl_threadlock.h"
 
 /* The last 3 #include files should be in this order */
@@ -342,7 +343,8 @@ mbed_connect_step1(struct connectdata *conn,
   if(SSL_SET_OPTION(key)) {
     ret = mbedtls_pk_parse_keyfile(&BACKEND->pk, SSL_SET_OPTION(key),
                                    SSL_SET_OPTION(key_passwd));
-    if(ret == 0 && !mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA))
+    if(ret == 0 && !(mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA) ||
+                     mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_ECKEY)))
       ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
 
     if(ret) {
@@ -373,7 +375,7 @@ mbed_connect_step1(struct connectdata *conn,
     }
   }
 
-  infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port);
+  infof(data, "mbedTLS: Connecting to %s:%ld\n", hostname, port);
 
   mbedtls_ssl_config_init(&BACKEND->config);
 
@@ -539,13 +541,6 @@ mbed_connect_step2(struct connectdata *conn,
         data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
         data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
 
-#ifdef HAS_ALPN
-  const char *next_protocol;
-#endif
-
-  char errorbuf[128];
-  errorbuf[0] = 0;
-
   conn->recv[sockindex] = mbed_recv;
   conn->send[sockindex] = mbed_send;
 
@@ -560,6 +555,8 @@ mbed_connect_step2(struct connectdata *conn,
     return CURLE_OK;
   }
   else if(ret) {
+    char errorbuf[128];
+    errorbuf[0] = 0;
 #ifdef MBEDTLS_ERROR_C
     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
 #endif /* MBEDTLS_ERROR_C */
@@ -574,19 +571,21 @@ mbed_connect_step2(struct connectdata *conn,
 
   ret = mbedtls_ssl_get_verify_result(&BACKEND->ssl);
 
+  if(!SSL_CONN_CONFIG(verifyhost))
+    /* Ignore hostname errors if verifyhost is disabled */
+    ret &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
+
   if(ret && SSL_CONN_CONFIG(verifypeer)) {
     if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
       failf(data, "Cert verify failed: BADCERT_EXPIRED");
 
-    if(ret & MBEDTLS_X509_BADCERT_REVOKED) {
+    else if(ret & MBEDTLS_X509_BADCERT_REVOKED)
       failf(data, "Cert verify failed: BADCERT_REVOKED");
-      return CURLE_SSL_CACERT;
-    }
 
-    if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
+    else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
       failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
 
-    if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
+    else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
       failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
 
     return CURLE_PEER_FAILED_VERIFICATION;
@@ -662,7 +661,7 @@ mbed_connect_step2(struct connectdata *conn,
 
 #ifdef HAS_ALPN
   if(conn->bits.tls_enable_alpn) {
-    next_protocol = mbedtls_ssl_get_alpn_protocol(&BACKEND->ssl);
+    const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&BACKEND->ssl);
 
     if(next_protocol) {
       infof(data, "ALPN, server accepted to use %s\n", next_protocol);
@@ -682,6 +681,8 @@ mbed_connect_step2(struct connectdata *conn,
     else {
       infof(data, "ALPN, server did not agree to a protocol\n");
     }
+    Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
   }
 #endif
 
@@ -714,6 +715,8 @@ mbed_connect_step3(struct connectdata *conn,
 
     ret = mbedtls_ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
     if(ret) {
+      if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED)
+        mbedtls_ssl_session_free(our_ssl_sessionid);
       free(our_ssl_sessionid);
       failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
       return CURLE_SSL_CONNECT_ERROR;
@@ -727,6 +730,7 @@ mbed_connect_step3(struct connectdata *conn,
     retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
     Curl_ssl_sessionid_unlock(conn);
     if(retcode) {
+      mbedtls_ssl_session_free(our_ssl_sessionid);
       free(our_ssl_sessionid);
       failf(data, "failed to store ssl session");
       return retcode;
@@ -811,9 +815,14 @@ static void Curl_mbedtls_session_free(void *ptr)
 
 static size_t Curl_mbedtls_version(char *buffer, size_t size)
 {
+#ifdef MBEDTLS_VERSION_C
+  /* if mbedtls_version_get_number() is available it is better */
   unsigned int version = mbedtls_version_get_number();
-  return snprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24,
-                  (version>>16)&0xff, (version>>8)&0xff);
+  return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24,
+                   (version>>16)&0xff, (version>>8)&0xff);
+#else
+  return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING);
+#endif
 }
 
 static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
diff --git a/lib/vtls/mesalink.c b/lib/vtls/mesalink.c
index 6a2b67e..718c282 100644
--- a/lib/vtls/mesalink.c
+++ b/lib/vtls/mesalink.c
@@ -5,8 +5,8 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2017-2018, Yiming Jing, <jingyiming at baidu.com>
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming at baidu.com>
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -268,7 +268,7 @@ mesalink_connect_step2(struct connectdata *conn, int sockindex)
     char error_buffer[MESALINK_MAX_ERROR_SZ];
     int detail = SSL_get_error(BACKEND->handle, ret);
 
-    if(SSL_ERROR_WANT_CONNECT == detail) {
+    if(SSL_ERROR_WANT_CONNECT == detail || SSL_ERROR_WANT_READ == detail) {
       connssl->connecting_state = ssl_connect_2_reading;
       return CURLE_OK;
     }
@@ -424,7 +424,7 @@ mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
 static size_t
 Curl_mesalink_version(char *buffer, size_t size)
 {
-  return snprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING);
+  return msnprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING);
 }
 
 static int
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index a3d3e58..491def1 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -38,6 +38,7 @@
 #include "select.h"
 #include "vtls.h"
 #include "llist.h"
+#include "multiif.h"
 #include "curl_printf.h"
 #include "nssg.h"
 #include <nspr.h>
@@ -246,6 +247,32 @@ static void nss_print_error_message(struct Curl_easy *data, PRUint32 err)
   failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
 }
 
+static char *nss_sslver_to_name(PRUint16 nssver)
+{
+  switch(nssver) {
+  case SSL_LIBRARY_VERSION_2:
+    return strdup("SSLv2");
+  case SSL_LIBRARY_VERSION_3_0:
+    return strdup("SSLv3");
+  case SSL_LIBRARY_VERSION_TLS_1_0:
+    return strdup("TLSv1.0");
+#ifdef SSL_LIBRARY_VERSION_TLS_1_1
+  case SSL_LIBRARY_VERSION_TLS_1_1:
+    return strdup("TLSv1.1");
+#endif
+#ifdef SSL_LIBRARY_VERSION_TLS_1_2
+  case SSL_LIBRARY_VERSION_TLS_1_2:
+    return strdup("TLSv1.2");
+#endif
+#ifdef SSL_LIBRARY_VERSION_TLS_1_3
+  case SSL_LIBRARY_VERSION_TLS_1_3:
+    return strdup("TLSv1.3");
+#endif
+  default:
+    return curl_maprintf("0x%04x", nssver);
+  }
+}
+
 static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
                              char *cipher_list)
 {
@@ -351,7 +378,7 @@ static int is_file(const char *filename)
     return 0;
 
   if(stat(filename, &st) == 0)
-    if(S_ISREG(st.st_mode))
+    if(S_ISREG(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISCHR(st.st_mode))
       return 1;
 
   return 0;
@@ -817,6 +844,8 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
        !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) {
       conn->negnpn = CURL_HTTP_VERSION_1_1;
     }
+    Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
   }
 }
 
@@ -1279,6 +1308,8 @@ static void nss_unload_module(SECMODModule **pmod)
 static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
 {
   NSSInitParameters initparams;
+  PRErrorCode err;
+  const char *err_name;
 
   if(nss_context != NULL)
     return CURLE_OK;
@@ -1299,7 +1330,9 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
     if(nss_context != NULL)
       return CURLE_OK;
 
-    infof(data, "Unable to initialize NSS database\n");
+    err = PR_GetError();
+    err_name = nss_error_to_name(err);
+    infof(data, "Unable to initialize NSS database: %d (%s)\n", err, err_name);
   }
 
   infof(data, "Initializing NSS with certpath: none\n");
@@ -1309,7 +1342,9 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
   if(nss_context != NULL)
     return CURLE_OK;
 
-  infof(data, "Unable to initialize NSS\n");
+  err = PR_GetError();
+  err_name = nss_error_to_name(err);
+  failf(data, "Unable to initialize NSS: %d (%s)", err, err_name);
   return CURLE_SSL_CACERT_BADFILE;
 }
 
@@ -1638,17 +1673,6 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
 static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version)
 {
   switch(version) {
-  case CURL_SSLVERSION_TLSv1:
-    /* TODO: set sslver->max to SSL_LIBRARY_VERSION_TLS_1_3 once stable */
-#ifdef SSL_LIBRARY_VERSION_TLS_1_2
-    *nssver = SSL_LIBRARY_VERSION_TLS_1_2;
-#elif defined SSL_LIBRARY_VERSION_TLS_1_1
-    *nssver = SSL_LIBRARY_VERSION_TLS_1_1;
-#else
-    *nssver = SSL_LIBRARY_VERSION_TLS_1_0;
-#endif
-    return CURLE_OK;
-
   case CURL_SSLVERSION_SSLv2:
     *nssver = SSL_LIBRARY_VERSION_2;
     return CURLE_OK;
@@ -1709,10 +1733,8 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver,
   }
 
   switch(min) {
-  case CURL_SSLVERSION_DEFAULT:
-    break;
   case CURL_SSLVERSION_TLSv1:
-    sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+  case CURL_SSLVERSION_DEFAULT:
     break;
   default:
     result = nss_sslver_from_curl(&sslver->min, min);
@@ -1789,10 +1811,19 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   CURLcode result;
   bool second_layer = FALSE;
+  SSLVersionRange sslver_supported;
 
   SSLVersionRange sslver = {
     SSL_LIBRARY_VERSION_TLS_1_0,  /* min */
-    SSL_LIBRARY_VERSION_TLS_1_0   /* max */
+#ifdef SSL_LIBRARY_VERSION_TLS_1_3
+    SSL_LIBRARY_VERSION_TLS_1_3   /* max */
+#elif defined SSL_LIBRARY_VERSION_TLS_1_2
+    SSL_LIBRARY_VERSION_TLS_1_2
+#elif defined SSL_LIBRARY_VERSION_TLS_1_1
+    SSL_LIBRARY_VERSION_TLS_1_1
+#else
+    SSL_LIBRARY_VERSION_TLS_1_0
+#endif
   };
 
   BACKEND->data = data;
@@ -1800,7 +1831,6 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   /* list of all NSS objects we need to destroy in Curl_nss_close() */
   Curl_llist_init(&BACKEND->obj_list, nss_destroy_object);
 
-  /* FIXME. NSS doesn't support multiple databases open at the same time. */
   PR_Lock(nss_initlock);
   result = nss_init(conn->data);
   if(result) {
@@ -1841,6 +1871,20 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   /* enable/disable the requested SSL version(s) */
   if(nss_init_sslver(&sslver, data, conn) != CURLE_OK)
     goto error;
+  if(SSL_VersionRangeGetSupported(ssl_variant_stream,
+                                  &sslver_supported) != SECSuccess)
+    goto error;
+  if(sslver_supported.max < sslver.max && sslver_supported.max >= sslver.min) {
+    char *sslver_req_str, *sslver_supp_str;
+    sslver_req_str = nss_sslver_to_name(sslver.max);
+    sslver_supp_str = nss_sslver_to_name(sslver_supported.max);
+    if(sslver_req_str && sslver_supp_str)
+      infof(data, "Falling back from %s to max supported SSL version (%s)\n",
+                  sslver_req_str, sslver_supp_str);
+    free(sslver_req_str);
+    free(sslver_supp_str);
+    sslver.max = sslver_supported.max;
+  }
   if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
     goto error;
 
@@ -2090,7 +2134,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
     else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
       result = CURLE_PEER_FAILED_VERIFICATION;
     else if(*certverifyresult != 0)
-      result = CURLE_SSL_CACERT;
+      result = CURLE_PEER_FAILED_VERIFICATION;
     goto error;
   }
 
@@ -2164,7 +2208,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
     if(!blocking)
       /* CURLE_AGAIN in non-blocking mode is not an error */
       return CURLE_OK;
-    /* fall through */
+    /* FALLTHROUGH */
   default:
     return result;
   }
@@ -2279,7 +2323,7 @@ static ssize_t nss_recv(struct connectdata *conn,  /* connection data */
 
 static size_t Curl_nss_version(char *buffer, size_t size)
 {
-  return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
+  return msnprintf(buffer, size, "NSS/%s", NSS_VERSION);
 }
 
 /* data might be NULL */
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 4c5e8c1..85e9be6 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -48,6 +48,7 @@
 #include "vtls.h"
 #include "strcase.h"
 #include "hostcheck.h"
+#include "multiif.h"
 #include "curl_printf.h"
 #include <openssl/ssl.h>
 #include <openssl/rand.h>
@@ -65,11 +66,15 @@
 #include <openssl/buffer.h>
 #include <openssl/pkcs12.h>
 
+#ifdef USE_AMISSL
+#include "amigaos.h"
+#endif
+
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
 #include <openssl/ocsp.h>
 #endif
 
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && /* 0.9.8 or later */     \
+#if (OPENSSL_VERSION_NUMBER >= 0x0090700fL) && /* 0.9.7 or later */     \
   !defined(OPENSSL_NO_ENGINE)
 #define USE_OPENSSL_ENGINE
 #include <openssl/engine.h>
@@ -82,6 +87,13 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
+   renegotiations when built with BoringSSL. Renegotiating is non-compliant
+   with HTTP/2 and "an extremely dangerous protocol feature". Beware.
+
+#define ALLOW_RENEG 1
+ */
+
 #ifndef OPENSSL_VERSION_NUMBER
 #error "OPENSSL_VERSION_NUMBER not defined"
 #endif
@@ -384,6 +396,31 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size)
   return buf;
 }
 
+/* Return an extra data index for the connection data.
+ * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
+ */
+static int ossl_get_ssl_conn_index(void)
+{
+  static int ssl_ex_data_conn_index = -1;
+  if(ssl_ex_data_conn_index < 0) {
+    ssl_ex_data_conn_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+  }
+  return ssl_ex_data_conn_index;
+}
+
+/* Return an extra data index for the sockindex.
+ * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
+ */
+static int ossl_get_ssl_sockindex_index(void)
+{
+  static int ssl_ex_data_sockindex_index = -1;
+  if(ssl_ex_data_sockindex_index < 0) {
+    ssl_ex_data_sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL,
+        NULL);
+  }
+  return ssl_ex_data_sockindex_index;
+}
+
 static int passwd_callback(char *buf, int num, int encrypting,
                            void *global_passwd)
 {
@@ -788,8 +825,11 @@ int cert_stuff(struct connectdata *conn,
   fail:
       EVP_PKEY_free(pri);
       X509_free(x509);
+#ifdef USE_AMISSL
+      sk_X509_pop_free(ca, Curl_amiga_X509_free);
+#else
       sk_X509_pop_free(ca, X509_free);
-
+#endif
       if(!cert_done)
         return 0; /* failure! */
       break;
@@ -799,15 +839,15 @@ int cert_stuff(struct connectdata *conn,
       return 0;
     }
 
-    file_type = do_file_type(key_type);
+    if(!key_file)
+      key_file = cert_file;
+    else
+      file_type = do_file_type(key_type);
 
     switch(file_type) {
     case SSL_FILETYPE_PEM:
       if(cert_done)
         break;
-      if(!key_file)
-        /* cert & key can only be in PEM case in the same file */
-        key_file = cert_file;
       /* FALLTHROUGH */
     case SSL_FILETYPE_ASN1:
       if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) {
@@ -1035,6 +1075,10 @@ static int Curl_ossl_init(void)
   }
 #endif
 
+  /* Initialize the extra data indexes */
+  if(ossl_get_ssl_conn_index() < 0 || ossl_get_ssl_sockindex_index() < 0)
+    return 0;
+
   return 1;
 }
 
@@ -1049,7 +1093,7 @@ static void Curl_ossl_cleanup(void)
   /* Free ciphers and digests lists */
   EVP_cleanup();
 
-#ifdef HAVE_ENGINE_CLEANUP
+#ifdef USE_OPENSSL_ENGINE
   /* Free engine list */
   ENGINE_cleanup();
 #endif
@@ -1264,6 +1308,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
   int err;
   bool done = FALSE;
 
+#ifndef CURL_DISABLE_FTP
   /* This has only been tested on the proftpd server, and the mod_tls code
      sends a close notify alert without waiting for a close notify alert in
      response. Thus we wait for a close notify alert from the server, but
@@ -1271,6 +1316,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
 
   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
       (void)SSL_shutdown(BACKEND->handle);
+#endif
 
   if(BACKEND->handle) {
     buffsize = (int)sizeof(buf);
@@ -1656,6 +1702,7 @@ static CURLcode verifystatus(struct connectdata *conn,
                              struct ssl_connect_data *connssl)
 {
   int i, ocsp_status;
+  unsigned char *status;
   const unsigned char *p;
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
@@ -1665,14 +1712,14 @@ static CURLcode verifystatus(struct connectdata *conn,
   X509_STORE     *st = NULL;
   STACK_OF(X509) *ch = NULL;
 
-  long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &p);
+  long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &status);
 
-  if(!p) {
+  if(!status) {
     failf(data, "No OCSP response received");
     result = CURLE_SSL_INVALIDCERTSTATUS;
     goto end;
   }
-
+  p = status;
   rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
   if(!rsp) {
     failf(data, "Invalid OCSP response");
@@ -1867,15 +1914,8 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
   return "Unknown";
 }
 
-static const char *tls_rt_type(int type, const void *buf, size_t buflen)
+static const char *tls_rt_type(int type)
 {
-  (void)buf;
-  (void)buflen;
-#ifdef SSL3_RT_INNER_CONTENT_TYPE
-  if(type == SSL3_RT_INNER_CONTENT_TYPE && buf && buflen >= 1)
-    type = *(unsigned char *)buf;
-#endif
-
   switch(type) {
 #ifdef SSL3_RT_HEADER
   case SSL3_RT_HEADER:
@@ -1945,12 +1985,20 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
   case 0:
     break;
   default:
-    snprintf(unknown, sizeof(unknown), "(%x)", ssl_ver);
+    msnprintf(unknown, sizeof(unknown), "(%x)", ssl_ver);
     verstr = unknown;
     break;
   }
 
-  if(ssl_ver) {
+  /* Log progress for interesting records only (like Handshake or Alert), skip
+   * all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0).
+   * For TLS 1.3, skip notification of the decrypted inner Content Type.
+   */
+  if(ssl_ver
+#ifdef SSL3_RT_INNER_CONTENT_TYPE
+     && content_type != SSL3_RT_INNER_CONTENT_TYPE
+#endif
+    ) {
     const char *msg_name, *tls_rt_name;
     char ssl_buf[1024];
     int msg_type, txt_len;
@@ -1964,17 +2012,10 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
      * is at 'buf[0]'.
      */
     if(ssl_ver == SSL3_VERSION_MAJOR && content_type)
-      tls_rt_name = tls_rt_type(content_type, buf, len);
+      tls_rt_name = tls_rt_type(content_type);
     else
       tls_rt_name = "";
 
-#ifdef SSL3_RT_INNER_CONTENT_TYPE
-    if(content_type == SSL3_RT_INNER_CONTENT_TYPE) {
-      msg_type = 0;
-      msg_name = "[no content]";
-    }
-    else
-#endif
     if(content_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
       msg_type = *(char *)buf;
       msg_name = "Change cipher spec";
@@ -1988,9 +2029,9 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
       msg_name = ssl_msg_type(ssl_ver, msg_type);
     }
 
-    txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n",
-                       verstr, direction?"OUT":"IN",
-                       tls_rt_name, msg_name, msg_type);
+    txt_len = msnprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n",
+                        verstr, direction?"OUT":"IN",
+                        tls_rt_name, msg_name, msg_type);
     if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) {
       Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len);
     }
@@ -2137,6 +2178,7 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
     }
 #else
       (void)sockindex;
+      (void)ctx_options;
       failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
       return CURLE_NOT_BUILT_IN;
 #endif
@@ -2189,6 +2231,62 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
   return CURLE_OK;
 }
 
+/* The "new session" callback must return zero if the session can be removed
+ * or non-zero if the session has been put into the session cache.
+ */
+static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
+{
+  int res = 0;
+  struct connectdata *conn;
+  struct Curl_easy *data;
+  int sockindex;
+  curl_socket_t *sockindex_ptr;
+  int connectdata_idx = ossl_get_ssl_conn_index();
+  int sockindex_idx = ossl_get_ssl_sockindex_index();
+
+  if(connectdata_idx < 0 || sockindex_idx < 0)
+    return 0;
+
+  conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx);
+  if(!conn)
+    return 0;
+
+  data = conn->data;
+
+  /* The sockindex has been stored as a pointer to an array element */
+  sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx);
+  sockindex = (int)(sockindex_ptr - conn->sock);
+
+  if(SSL_SET_OPTION(primary.sessionid)) {
+    bool incache;
+    void *old_ssl_sessionid = NULL;
+
+    Curl_ssl_sessionid_lock(conn);
+    incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
+                                      sockindex));
+    if(incache) {
+      if(old_ssl_sessionid != ssl_sessionid) {
+        infof(data, "old SSL session ID is stale, removing\n");
+        Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+        incache = FALSE;
+      }
+    }
+
+    if(!incache) {
+      if(!Curl_ssl_addsessionid(conn, ssl_sessionid,
+                                      0 /* unknown size */, sockindex)) {
+        /* the session has been put into the session cache */
+        res = 1;
+      }
+      else
+        failf(data, "failed to store ssl session");
+    }
+    Curl_ssl_sessionid_unlock(conn);
+  }
+
+  return res;
+}
+
 static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 {
   CURLcode result = CURLE_OK;
@@ -2585,6 +2683,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   }
 #endif
 
+  /* Enable the session cache because it's a prerequisite for the "new session"
+   * callback. Use the "external storage" mode to avoid that OpenSSL creates
+   * an internal session cache.
+   */
+  SSL_CTX_set_session_cache_mode(BACKEND->ctx,
+      SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL);
+  SSL_CTX_sess_set_new_cb(BACKEND->ctx, ossl_new_session_cb);
+
   /* give application a chance to interfere with SSL set up. */
   if(data->set.ssl.fsslctx) {
     result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
@@ -2610,6 +2716,10 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     SSL_set_tlsext_status_type(BACKEND->handle, TLSEXT_STATUSTYPE_ocsp);
 #endif
 
+#if defined(OPENSSL_IS_BORINGSSL) && defined(ALLOW_RENEG)
+  SSL_set_renegotiate_mode(BACKEND->handle, ssl_renegotiate_freely);
+#endif
+
   SSL_set_connect_state(BACKEND->handle);
 
   BACKEND->server_cert = 0x0;
@@ -2627,6 +2737,15 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   /* Check if there's a cached ID we can/should use here! */
   if(SSL_SET_OPTION(primary.sessionid)) {
     void *ssl_sessionid = NULL;
+    int connectdata_idx = ossl_get_ssl_conn_index();
+    int sockindex_idx = ossl_get_ssl_sockindex_index();
+
+    if(connectdata_idx >= 0 && sockindex_idx >= 0) {
+      /* Store the data needed for the "new session" callback.
+       * The sockindex is stored as a pointer to an array element. */
+      SSL_set_ex_data(BACKEND->handle, connectdata_idx, conn);
+      SSL_set_ex_data(BACKEND->handle, sockindex_idx, conn->sock + sockindex);
+    }
 
     Curl_ssl_sessionid_lock(conn);
     if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
@@ -2699,6 +2818,12 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
       connssl->connecting_state = ssl_connect_2_writing;
       return CURLE_OK;
     }
+#ifdef SSL_ERROR_WANT_ASYNC
+    if(SSL_ERROR_WANT_ASYNC == detail) {
+      connssl->connecting_state = ssl_connect_2;
+      return CURLE_OK;
+    }
+#endif
     else {
       /* untreated error */
       unsigned long errdetail;
@@ -2721,14 +2846,14 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
 
       if((lib == ERR_LIB_SSL) &&
          (reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) {
-        result = CURLE_SSL_CACERT;
+        result = CURLE_PEER_FAILED_VERIFICATION;
 
         lerr = SSL_get_verify_result(BACKEND->handle);
         if(lerr != X509_V_OK) {
           *certverifyresult = lerr;
-          snprintf(error_buffer, sizeof(error_buffer),
-                   "SSL certificate problem: %s",
-                   X509_verify_cert_error_string(lerr));
+          msnprintf(error_buffer, sizeof(error_buffer),
+                    "SSL certificate problem: %s",
+                    X509_verify_cert_error_string(lerr));
         }
         else
           /* strcpy() is fine here as long as the string fits within
@@ -2795,6 +2920,9 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
       }
       else
         infof(data, "ALPN, server did not agree to a protocol\n");
+
+      Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+                          BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
     }
 #endif
 
@@ -2839,7 +2967,7 @@ static void pubkey_show(struct Curl_easy *data,
   char *ptr;
   char namebuf[32];
 
-  snprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
+  msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
 
   if(bn)
     BN_print(mem, bn);
@@ -2900,8 +3028,8 @@ static int X509V3_ext(struct Curl_easy *data,
       while((j<(size_t)biomem->length) && (biomem->data[j] == ' '))
         j++;
       if(j<(size_t)biomem->length)
-        ptr += snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
-                        biomem->data[j]);
+        ptr += msnprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
+                         biomem->data[j]);
     }
 
     Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
@@ -3101,11 +3229,6 @@ static CURLcode get_cert_chain(struct connectdata *conn,
 #endif
         break;
       }
-#if 0
-      case EVP_PKEY_EC: /* symbol not present in OpenSSL 0.9.6 */
-        /* left TODO */
-        break;
-#endif
       }
       EVP_PKEY_free(pubkey);
     }
@@ -3214,20 +3337,8 @@ static CURLcode servercert(struct connectdata *conn,
     /* we've been asked to gather certificate info! */
     (void)get_cert_chain(conn, connssl);
 
-  fp = BIO_new(BIO_s_file());
-  if(fp == NULL) {
-    failf(data,
-          "BIO_new return NULL, " OSSL_PACKAGE
-          " error %s",
-          ossl_strerror(ERR_get_error(), error_buffer,
-                        sizeof(error_buffer)) );
-    BIO_free(mem);
-    return CURLE_OUT_OF_MEMORY;
-  }
-
   BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle);
   if(!BACKEND->server_cert) {
-    BIO_free(fp);
     BIO_free(mem);
     if(!strict)
       return CURLE_OK;
@@ -3262,7 +3373,6 @@ static CURLcode servercert(struct connectdata *conn,
   if(SSL_CONN_CONFIG(verifyhost)) {
     result = verifyhost(conn, BACKEND->server_cert);
     if(result) {
-      BIO_free(fp);
       X509_free(BACKEND->server_cert);
       BACKEND->server_cert = NULL;
       return result;
@@ -3284,6 +3394,18 @@ static CURLcode servercert(struct connectdata *conn,
 
     /* e.g. match issuer name with provided issuer certificate */
     if(SSL_SET_OPTION(issuercert)) {
+      fp = BIO_new(BIO_s_file());
+      if(fp == NULL) {
+        failf(data,
+              "BIO_new return NULL, " OSSL_PACKAGE
+              " error %s",
+              ossl_strerror(ERR_get_error(), error_buffer,
+                            sizeof(error_buffer)) );
+        X509_free(BACKEND->server_cert);
+        BACKEND->server_cert = NULL;
+        return CURLE_OUT_OF_MEMORY;
+      }
+
       if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) {
         if(strict)
           failf(data, "SSL: Unable to open issuer cert (%s)",
@@ -3319,6 +3441,7 @@ static CURLcode servercert(struct connectdata *conn,
 
       infof(data, " SSL certificate issuer check ok (%s)\n",
             SSL_SET_OPTION(issuercert));
+      BIO_free(fp);
       X509_free(issuer);
     }
 
@@ -3347,7 +3470,6 @@ static CURLcode servercert(struct connectdata *conn,
   if(SSL_CONN_CONFIG(verifystatus)) {
     result = verifystatus(conn, connssl);
     if(result) {
-      BIO_free(fp);
       X509_free(BACKEND->server_cert);
       BACKEND->server_cert = NULL;
       return result;
@@ -3367,7 +3489,6 @@ static CURLcode servercert(struct connectdata *conn,
       failf(data, "SSL: public key does not match pinned public key!");
   }
 
-  BIO_free(fp);
   X509_free(BACKEND->server_cert);
   BACKEND->server_cert = NULL;
   connssl->connecting_state = ssl_connect_done;
@@ -3378,52 +3499,10 @@ static CURLcode servercert(struct connectdata *conn,
 static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
 {
   CURLcode result = CURLE_OK;
-  struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(SSL_SET_OPTION(primary.sessionid)) {
-    bool incache;
-    SSL_SESSION *our_ssl_sessionid;
-    void *old_ssl_sessionid = NULL;
-
-    our_ssl_sessionid = SSL_get1_session(BACKEND->handle);
-
-    /* SSL_get1_session() will increment the reference count and the session
-        will stay in memory until explicitly freed with SSL_SESSION_free(3),
-        regardless of its state. */
-
-    Curl_ssl_sessionid_lock(conn);
-    incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
-                                      sockindex));
-    if(incache) {
-      if(old_ssl_sessionid != our_ssl_sessionid) {
-        infof(data, "old SSL session ID is stale, removing\n");
-        Curl_ssl_delsessionid(conn, old_ssl_sessionid);
-        incache = FALSE;
-      }
-    }
-
-    if(!incache) {
-      result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
-                                      0 /* unknown size */, sockindex);
-      if(result) {
-        Curl_ssl_sessionid_unlock(conn);
-        failf(data, "failed to store ssl session");
-        return result;
-      }
-    }
-    else {
-      /* Session was incache, so refcount already incremented earlier.
-        * Avoid further increments with each SSL_get1_session() call.
-        * This does not free the session as refcount remains > 0
-        */
-      SSL_SESSION_free(our_ssl_sessionid);
-    }
-    Curl_ssl_sessionid_unlock(conn);
-  }
-
   /*
    * We check certificates to authenticate the server; otherwise we risk
    * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to
@@ -3678,7 +3757,10 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
 
     switch(err) {
     case SSL_ERROR_NONE: /* this is not an error */
+      break;
     case SSL_ERROR_ZERO_RETURN: /* no more data */
+      /* close_notify alert */
+      connclose(conn, "TLS close_notify");
       break;
     case SSL_ERROR_WANT_READ:
     case SSL_ERROR_WANT_WRITE:
@@ -3709,8 +3791,13 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
 static size_t Curl_ossl_version(char *buffer, size_t size)
 {
 #ifdef OPENSSL_IS_BORINGSSL
-  return snprintf(buffer, size, OSSL_PACKAGE);
-#else /* OPENSSL_IS_BORINGSSL */
+  return msnprintf(buffer, size, OSSL_PACKAGE);
+#elif defined(HAVE_OPENSSL_VERSION) && defined(OPENSSL_VERSION_STRING)
+  return msnprintf(buffer, size, "%s/%s",
+                   OSSL_PACKAGE, OpenSSL_version(OPENSSL_VERSION_STRING));
+#else
+  /* not BoringSSL and not using OpenSSL_version */
+
   char sub[3];
   unsigned long ssleay_value;
   sub[2]='\0';
@@ -3736,12 +3823,16 @@ static size_t Curl_ossl_version(char *buffer, size_t size)
       sub[0]='\0';
   }
 
-  return snprintf(buffer, size, "%s/%lx.%lx.%lx%s",
-                  OSSL_PACKAGE,
-                  (ssleay_value>>28)&0xf,
-                  (ssleay_value>>20)&0xff,
-                  (ssleay_value>>12)&0xff,
-                  sub);
+  return msnprintf(buffer, size, "%s/%lx.%lx.%lx%s"
+#ifdef OPENSSL_FIPS
+                   "-fips"
+#endif
+                   ,
+                   OSSL_PACKAGE,
+                   (ssleay_value>>28)&0xf,
+                   (ssleay_value>>20)&0xff,
+                   (ssleay_value>>12)&0xff,
+                   sub);
 #endif /* OPENSSL_IS_BORINGSSL */
 }
 
diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
index 27af0cc..7ea26b4 100644
--- a/lib/vtls/polarssl.c
+++ b/lib/vtls/polarssl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan at gmail.com>
  *
  * This software is licensed as described in the file COPYING, which
@@ -55,6 +55,7 @@
 #include "select.h"
 #include "strcase.h"
 #include "polarssl_threadlock.h"
+#include "multiif.h"
 #include "curl_printf.h"
 #include "curl_memory.h"
 /* The last #include file should be: */
@@ -497,7 +498,7 @@ polarssl_connect_step2(struct connectdata *conn,
 
     if(ret & BADCERT_REVOKED) {
       failf(data, "Cert verify failed: BADCERT_REVOKED");
-      return CURLE_SSL_CACERT;
+      return CURLE_PEER_FAILED_VERIFICATION;
     }
 
     if(ret & BADCERT_CN_MISMATCH)
@@ -593,6 +594,8 @@ polarssl_connect_step2(struct connectdata *conn,
     }
     else
       infof(data, "ALPN, server did not agree to a protocol\n");
+    Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
   }
 #endif
 
@@ -716,9 +719,9 @@ static void Curl_polarssl_session_free(void *ptr)
 static size_t Curl_polarssl_version(char *buffer, size_t size)
 {
   unsigned int version = version_get_number();
-  return snprintf(buffer, size, "%s/%d.%d.%d",
-                  version >= 0x01030A00?"mbedTLS":"PolarSSL",
-                  version>>24, (version>>16)&0xff, (version>>8)&0xff);
+  return msnprintf(buffer, size, "%s/%d.%d.%d",
+                   version >= 0x01030A00?"mbedTLS":"PolarSSL",
+                   version>>24, (version>>16)&0xff, (version>>8)&0xff);
 }
 
 static CURLcode
@@ -908,9 +911,7 @@ const struct Curl_ssl Curl_ssl_polarssl = {
   Curl_none_check_cxn,               /* check_cxn */
   Curl_none_shutdown,                /* shutdown */
   Curl_polarssl_data_pending,        /* data_pending */
-  /* This might cause libcurl to use a weeker random!
-   * TODO: use Polarssl's CTR-DRBG or HMAC-DRBG
-  */
+  /* This might cause libcurl to use a weeker random! */
   Curl_none_random,                  /* random */
   Curl_none_cert_status_request,     /* cert_status_request */
   Curl_polarssl_connect,             /* connect */
diff --git a/lib/vtls/polarssl_threadlock.c b/lib/vtls/polarssl_threadlock.c
index dd5fbd7..27c94b1 100644
--- a/lib/vtls/polarssl_threadlock.c
+++ b/lib/vtls/polarssl_threadlock.c
@@ -23,16 +23,15 @@
 #include "curl_setup.h"
 
 #if (defined(USE_POLARSSL) || defined(USE_MBEDTLS)) && \
-    (defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32))
-
-#if defined(USE_THREADS_POSIX)
-#  ifdef HAVE_PTHREAD_H
-#    include <pthread.h>
-#  endif
-#elif defined(USE_THREADS_WIN32)
-#  ifdef HAVE_PROCESS_H
-#    include <process.h>
-#  endif
+    ((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
+     (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)))
+
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
+#  include <pthread.h>
+#  define POLARSSL_MUTEX_T pthread_mutex_t
+#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
+#  include <process.h>
+#  define POLARSSL_MUTEX_T HANDLE
 #endif
 
 #include "polarssl_threadlock.h"
@@ -50,25 +49,23 @@ static POLARSSL_MUTEX_T *mutex_buf = NULL;
 int Curl_polarsslthreadlock_thread_setup(void)
 {
   int i;
-  int ret;
 
   mutex_buf = calloc(NUMT * sizeof(POLARSSL_MUTEX_T), 1);
   if(!mutex_buf)
     return 0;     /* error, no number of threads defined */
 
-#ifdef HAVE_PTHREAD_H
   for(i = 0;  i < NUMT;  i++) {
+    int ret;
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
     ret = pthread_mutex_init(&mutex_buf[i], NULL);
     if(ret)
       return 0; /* pthread_mutex_init failed */
-  }
-#elif defined(HAVE_PROCESS_H)
-  for(i = 0;  i < NUMT;  i++) {
+#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
     mutex_buf[i] = CreateMutex(0, FALSE, 0);
     if(mutex_buf[i] == 0)
       return 0;  /* CreateMutex failed */
+#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
   }
-#endif /* HAVE_PTHREAD_H */
 
   return 1; /* OK */
 }
@@ -76,24 +73,22 @@ int Curl_polarsslthreadlock_thread_setup(void)
 int Curl_polarsslthreadlock_thread_cleanup(void)
 {
   int i;
-  int ret;
 
   if(!mutex_buf)
     return 0; /* error, no threads locks defined */
 
-#ifdef HAVE_PTHREAD_H
   for(i = 0; i < NUMT; i++) {
+    int ret;
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
     ret = pthread_mutex_destroy(&mutex_buf[i]);
     if(ret)
       return 0; /* pthread_mutex_destroy failed */
-  }
-#elif defined(HAVE_PROCESS_H)
-  for(i = 0; i < NUMT; i++) {
+#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
     ret = CloseHandle(mutex_buf[i]);
     if(!ret)
       return 0; /* CloseHandle failed */
+#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
   }
-#endif /* HAVE_PTHREAD_H */
   free(mutex_buf);
   mutex_buf = NULL;
 
@@ -102,51 +97,47 @@ int Curl_polarsslthreadlock_thread_cleanup(void)
 
 int Curl_polarsslthreadlock_lock_function(int n)
 {
-  int ret;
-#ifdef HAVE_PTHREAD_H
   if(n < NUMT) {
+    int ret;
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
     ret = pthread_mutex_lock(&mutex_buf[n]);
     if(ret) {
       DEBUGF(fprintf(stderr,
                      "Error: polarsslthreadlock_lock_function failed\n"));
       return 0; /* pthread_mutex_lock failed */
     }
-  }
-#elif defined(HAVE_PROCESS_H)
-  if(n < NUMT) {
+#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
     ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0);
     if(ret) {
       DEBUGF(fprintf(stderr,
                      "Error: polarsslthreadlock_lock_function failed\n"));
       return 0; /* pthread_mutex_lock failed */
     }
+#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
   }
-#endif /* HAVE_PTHREAD_H */
   return 1; /* OK */
 }
 
 int Curl_polarsslthreadlock_unlock_function(int n)
 {
-  int ret;
-#ifdef HAVE_PTHREAD_H
   if(n < NUMT) {
+    int ret;
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
     ret = pthread_mutex_unlock(&mutex_buf[n]);
     if(ret) {
       DEBUGF(fprintf(stderr,
                      "Error: polarsslthreadlock_unlock_function failed\n"));
       return 0; /* pthread_mutex_unlock failed */
     }
-  }
-#elif defined(HAVE_PROCESS_H)
-  if(n < NUMT) {
+#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
     ret = ReleaseMutex(mutex_buf[n]);
     if(!ret) {
       DEBUGF(fprintf(stderr,
                      "Error: polarsslthreadlock_unlock_function failed\n"));
       return 0; /* pthread_mutex_lock failed */
     }
+#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
   }
-#endif /* HAVE_PTHREAD_H */
   return 1; /* OK */
 }
 
diff --git a/lib/vtls/polarssl_threadlock.h b/lib/vtls/polarssl_threadlock.h
index dda5359..1226475 100644
--- a/lib/vtls/polarssl_threadlock.h
+++ b/lib/vtls/polarssl_threadlock.h
@@ -26,13 +26,8 @@
 
 #if (defined USE_POLARSSL) || (defined USE_MBEDTLS)
 
-#if defined(USE_THREADS_POSIX)
-#  define POLARSSL_MUTEX_T       pthread_mutex_t
-#elif defined(USE_THREADS_WIN32)
-#  define POLARSSL_MUTEX_T       HANDLE
-#endif
-
-#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
+#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
+    (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H))
 
 int Curl_polarsslthreadlock_thread_setup(void);
 int Curl_polarsslthreadlock_thread_cleanup(void);
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index e442692..0f6f734 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2012 - 2016, Marc Hoersken, <info at marc-hoersken.de>
  * Copyright (C) 2012, Mark Salisbury, <mark.salisbury at hp.com>
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,9 +23,8 @@
  ***************************************************************************/
 
 /*
- * Source file for all SChannel-specific code for the TLS/SSL layer. No code
+ * Source file for all Schannel-specific code for the TLS/SSL layer. No code
  * but vtls.c should ever call or use these functions.
- *
  */
 
 /*
@@ -59,6 +58,7 @@
 #include "warnless.h"
 #include "x509asn1.h"
 #include "curl_printf.h"
+#include "multiif.h"
 #include "system_win32.h"
 
  /* The last #include file should be: */
@@ -196,7 +196,7 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
         schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT;
         break;
       case CURL_SSLVERSION_TLSv1_3:
-        failf(data, "Schannel: TLS 1.3 is not yet supported");
+        failf(data, "schannel: TLS 1.3 is not yet supported");
         return CURLE_SSL_CONNECT_ERROR;
     }
   }
@@ -325,6 +325,9 @@ get_alg_id_by_name(char *name)
 #ifdef CALG_ECDSA
   CIPHEROPTION(CALG_ECDSA);
 #endif
+#ifdef CALG_ECDH_EPHEM
+  CIPHEROPTION(CALG_ECDH_EPHEM);
+#endif
   return 0;
 }
 
@@ -357,6 +360,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
                   TCHAR **thumbprint)
 {
   TCHAR *sep;
+  TCHAR *store_path_start;
   size_t store_name_len;
 
   sep = _tcschr(path, TEXT('\\'));
@@ -387,13 +391,17 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
   else
     return CURLE_SSL_CERTPROBLEM;
 
-  *store_path = sep + 1;
+  store_path_start = sep + 1;
 
-  sep = _tcschr(*store_path, TEXT('\\'));
+  sep = _tcschr(store_path_start, TEXT('\\'));
   if(sep == NULL)
     return CURLE_SSL_CERTPROBLEM;
 
-  *sep = 0;
+  *sep = TEXT('\0');
+  *store_path = _tcsdup(store_path_start);
+  *sep = TEXT('\\');
+  if(*store_path == NULL)
+    return CURLE_OUT_OF_MEMORY;
 
   *thumbprint = sep + 1;
   if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
@@ -429,14 +437,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
 
-  infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
-        hostname, conn->remote_port);
+  DEBUGF(infof(data,
+               "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
+               hostname, conn->remote_port));
 
   if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT,
                                  VERSION_LESS_THAN_EQUAL)) {
-     /* SChannel in Windows XP (OS version 5.1) uses legacy handshakes and
+     /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and
         algorithms that may not be supported by all servers. */
-     infof(data, "schannel: WinSSL version is old and may not be able to "
+     infof(data, "schannel: Windows version is old and may not be able to "
            "connect to some servers due to lack of SNI, algorithms, etc.\n");
   }
 
@@ -490,12 +499,13 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
     Curl_ssl_sessionid_lock(conn);
     if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
       BACKEND->cred = old_cred;
-      infof(data, "schannel: re-using existing credential handle\n");
+      DEBUGF(infof(data, "schannel: re-using existing credential handle\n"));
 
       /* increment the reference counter of the credential/session handle */
       BACKEND->cred->refcount++;
-      infof(data, "schannel: incremented credential handle refcount = %d\n",
-            BACKEND->cred->refcount);
+      DEBUGF(infof(data,
+                   "schannel: incremented credential handle refcount = %d\n",
+                   BACKEND->cred->refcount));
     }
     Curl_ssl_sessionid_unlock(conn);
   }
@@ -513,31 +523,32 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
 #endif
         schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
 
-      /* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */
       if(data->set.ssl.no_revoke) {
         schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
           SCH_CRED_IGNORE_REVOCATION_OFFLINE;
 
-        infof(data, "schannel: disabled server certificate revocation "
-                    "checks\n");
+        DEBUGF(infof(data, "schannel: disabled server certificate revocation "
+                     "checks\n"));
       }
       else {
         schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
-        infof(data, "schannel: checking server certificate revocation\n");
+        DEBUGF(infof(data,
+                     "schannel: checking server certificate revocation\n"));
       }
     }
     else {
       schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
         SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
         SCH_CRED_IGNORE_REVOCATION_OFFLINE;
-      infof(data, "schannel: disabled server certificate revocation checks\n");
+      DEBUGF(infof(data,
+                   "schannel: disabled server cert revocation checks\n"));
     }
 
     if(!conn->ssl_config.verifyhost) {
       schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
-      infof(data, "schannel: verifyhost setting prevents Schannel from "
-            "comparing the supplied target name with the subject "
-            "names in server certificates.\n");
+      DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from "
+                   "comparing the supplied target name with the subject "
+                   "names in server certificates.\n"));
     }
 
     switch(conn->ssl_config.version) {
@@ -609,9 +620,11 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
         failf(data, "schannel: Failed to open cert store %x %s, "
               "last error is %x",
               cert_store_name, cert_store_path, GetLastError());
+        free(cert_store_path);
         Curl_unicodefree(cert_path);
         return CURLE_SSL_CERTPROBLEM;
       }
+      free(cert_store_path);
 
       cert_thumbprint.pbData = cert_thumbprint_data;
       cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN;
@@ -674,8 +687,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
       CertFreeCertificateContext(client_certs[0]);
 
     if(sspi_status != SEC_E_OK) {
+      char buffer[STRERROR_LEN];
       failf(data, "schannel: AcquireCredentialsHandle failed: %s",
-            Curl_sspi_strerror(conn, sspi_status));
+            Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
       Curl_safefree(BACKEND->cred);
       switch(sspi_status) {
         case SEC_E_INSUFFICIENT_MEMORY:
@@ -790,15 +804,16 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   Curl_unicodefree(host_name);
 
   if(sspi_status != SEC_I_CONTINUE_NEEDED) {
+    char buffer[STRERROR_LEN];
     Curl_safefree(BACKEND->ctxt);
     switch(sspi_status) {
       case SEC_E_INSUFFICIENT_MEMORY:
         failf(data, "schannel: initial InitializeSecurityContext failed: %s",
-              Curl_sspi_strerror(conn, sspi_status));
+              Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
         return CURLE_OUT_OF_MEMORY;
       case SEC_E_WRONG_PRINCIPAL:
         failf(data, "schannel: SNI or certificate check failed: %s",
-              Curl_sspi_strerror(conn, sspi_status));
+              Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
         return CURLE_PEER_FAILED_VERIFICATION;
         /*
       case SEC_E_INVALID_HANDLE:
@@ -813,13 +828,13 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
         */
       default:
         failf(data, "schannel: initial InitializeSecurityContext failed: %s",
-              Curl_sspi_strerror(conn, sspi_status));
+              Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
         return CURLE_SSL_CONNECT_ERROR;
     }
   }
 
-  infof(data, "schannel: sending initial handshake data: "
-        "sending %lu bytes...\n", outbuf.cbBuffer);
+  DEBUGF(infof(data, "schannel: sending initial handshake data: "
+               "sending %lu bytes...\n", outbuf.cbBuffer));
 
   /* send initial handshake data which is now stored in output buffer */
   result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
@@ -831,8 +846,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  infof(data, "schannel: sent initial handshake data: "
-        "sent %zd bytes\n", written);
+  DEBUGF(infof(data, "schannel: sent initial handshake data: "
+               "sent %zd bytes\n", written));
 
   BACKEND->recv_unrecoverable_err = CURLE_OK;
   BACKEND->recv_sspi_close_notify = false;
@@ -853,13 +868,11 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   unsigned char *reallocated_buffer;
-  size_t reallocated_length;
   SecBuffer outbuf[3];
   SecBufferDesc outbuf_desc;
   SecBuffer inbuf[2];
   SecBufferDesc inbuf_desc;
   SECURITY_STATUS sspi_status = SEC_E_OK;
-  TCHAR *host_name;
   CURLcode result;
   bool doread;
   char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
@@ -868,8 +881,9 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
 
   doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
 
-  infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
-        hostname, conn->remote_port);
+  DEBUGF(infof(data,
+               "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
+               hostname, conn->remote_port));
 
   if(!BACKEND->cred || !BACKEND->ctxt)
     return CURLE_SSL_CONNECT_ERROR;
@@ -901,7 +915,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
   if(BACKEND->encdata_length - BACKEND->encdata_offset <
      CURL_SCHANNEL_BUFFER_FREE_SIZE) {
     /* increase internal encrypted data buffer */
-    reallocated_length = BACKEND->encdata_offset +
+    size_t reallocated_length = BACKEND->encdata_offset +
       CURL_SCHANNEL_BUFFER_FREE_SIZE;
     reallocated_buffer = realloc(BACKEND->encdata_buffer,
                                  reallocated_length);
@@ -917,6 +931,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
   }
 
   for(;;) {
+    TCHAR *host_name;
     if(doread) {
       /* read encrypted handshake data from socket */
       result = Curl_read_plain(conn->sock[sockindex],
@@ -928,8 +943,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
       if(result == CURLE_AGAIN) {
         if(connssl->connecting_state != ssl_connect_2_writing)
           connssl->connecting_state = ssl_connect_2_reading;
-        infof(data, "schannel: failed to receive handshake, "
-              "need more data\n");
+        DEBUGF(infof(data, "schannel: failed to receive handshake, "
+                     "need more data\n"));
         return CURLE_OK;
       }
       else if((result != CURLE_OK) || (nread == 0)) {
@@ -941,11 +956,12 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
       /* increase encrypted data buffer offset */
       BACKEND->encdata_offset += nread;
       BACKEND->encdata_is_incomplete = false;
-      infof(data, "schannel: encrypted data got %zd\n", nread);
+      DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread));
     }
 
-    infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
-          BACKEND->encdata_offset, BACKEND->encdata_length);
+    DEBUGF(infof(data,
+                 "schannel: encrypted data buffer: offset %zu length %zu\n",
+                 BACKEND->encdata_offset, BACKEND->encdata_length));
 
     /* setup input buffers */
     InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset),
@@ -988,7 +1004,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
     if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
       BACKEND->encdata_is_incomplete = true;
       connssl->connecting_state = ssl_connect_2_reading;
-      infof(data, "schannel: received incomplete message, need more data\n");
+      DEBUGF(infof(data,
+                   "schannel: received incomplete message, need more data\n"));
       return CURLE_OK;
     }
 
@@ -999,7 +1016,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
        !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
       BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
       connssl->connecting_state = ssl_connect_2_writing;
-      infof(data, "schannel: a client certificate has been requested\n");
+      DEBUGF(infof(data,
+                   "schannel: a client certificate has been requested\n"));
       return CURLE_OK;
     }
 
@@ -1008,8 +1026,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
       for(i = 0; i < 3; i++) {
         /* search for handshake tokens that need to be send */
         if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
-          infof(data, "schannel: sending next handshake data: "
-                "sending %lu bytes...\n", outbuf[i].cbBuffer);
+          DEBUGF(infof(data, "schannel: sending next handshake data: "
+                       "sending %lu bytes...\n", outbuf[i].cbBuffer));
 
           /* send handshake token to server */
           result = Curl_write_plain(conn, conn->sock[sockindex],
@@ -1030,14 +1048,15 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
       }
     }
     else {
+      char buffer[STRERROR_LEN];
       switch(sspi_status) {
         case SEC_E_INSUFFICIENT_MEMORY:
           failf(data, "schannel: next InitializeSecurityContext failed: %s",
-                Curl_sspi_strerror(conn, sspi_status));
+                Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
           return CURLE_OUT_OF_MEMORY;
         case SEC_E_WRONG_PRINCIPAL:
           failf(data, "schannel: SNI or certificate check failed: %s",
-                Curl_sspi_strerror(conn, sspi_status));
+                Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
           return CURLE_PEER_FAILED_VERIFICATION;
           /*
         case SEC_E_INVALID_HANDLE:
@@ -1052,14 +1071,15 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
           */
         default:
           failf(data, "schannel: next InitializeSecurityContext failed: %s",
-                Curl_sspi_strerror(conn, sspi_status));
+                Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
           return CURLE_SSL_CONNECT_ERROR;
       }
     }
 
     /* check if there was additional remaining encrypted data */
     if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
-      infof(data, "schannel: encrypted data length: %lu\n", inbuf[1].cbBuffer);
+      DEBUGF(infof(data, "schannel: encrypted data length: %lu\n",
+                   inbuf[1].cbBuffer));
       /*
         There are two cases where we could be getting extra data here:
         1) If we're renegotiating a connection and the handshake is already
@@ -1098,7 +1118,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
   /* check if the handshake is complete */
   if(sspi_status == SEC_E_OK) {
     connssl->connecting_state = ssl_connect_3;
-    infof(data, "schannel: SSL/TLS handshake complete\n");
+    DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n"));
   }
 
   pubkey_ptr = SSL_IS_PROXY() ?
@@ -1114,13 +1134,68 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
 
 #ifdef HAS_MANUAL_VERIFY_API
   if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
-    return verify_certificate(conn, sockindex);
+    return Curl_verify_certificate(conn, sockindex);
   }
 #endif
 
   return CURLE_OK;
 }
 
+static bool
+valid_cert_encoding(const CERT_CONTEXT *cert_context)
+{
+  return (cert_context != NULL) &&
+    ((cert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
+    (cert_context->pbCertEncoded != NULL) &&
+    (cert_context->cbCertEncoded > 0);
+}
+
+typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context, void *arg);
+
+static void
+traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func,
+                    void *arg)
+{
+  const CERT_CONTEXT *current_context = NULL;
+  bool should_continue = true;
+  while(should_continue &&
+        (current_context = CertEnumCertificatesInStore(
+          context->hCertStore,
+          current_context)) != NULL)
+    should_continue = func(current_context, arg);
+
+  if(current_context)
+    CertFreeCertificateContext(current_context);
+}
+
+static bool
+cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count)
+{
+  if(valid_cert_encoding(ccert_context))
+    (*(int *)certs_count)++;
+  return true;
+}
+
+struct Adder_args
+{
+  struct connectdata *conn;
+  CURLcode result;
+  int idx;
+};
+
+static bool
+add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg)
+{
+  struct Adder_args *args = (struct Adder_args*)raw_arg;
+  args->result = CURLE_OK;
+  if(valid_cert_encoding(ccert_context)) {
+    const char *beg = (const char *) ccert_context->pbCertEncoded;
+    const char *end = beg + ccert_context->cbCertEncoded;
+    args->result = Curl_extract_certinfo(args->conn, (args->idx)++, beg, end);
+  }
+  return args->result == CURLE_OK;
+}
+
 static CURLcode
 schannel_connect_step3(struct connectdata *conn, int sockindex)
 {
@@ -1129,7 +1204,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   SECURITY_STATUS sspi_status = SEC_E_OK;
   CERT_CONTEXT *ccert_context = NULL;
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef DEBUGBUILD
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
 #endif
@@ -1139,8 +1214,9 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
-        hostname, conn->remote_port);
+  DEBUGF(infof(data,
+               "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
+               hostname, conn->remote_port));
 
   if(!BACKEND->cred)
     return CURLE_SSL_CONNECT_ERROR;
@@ -1192,6 +1268,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
     }
     else
       infof(data, "ALPN, server did not agree to a protocol\n");
+    Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
   }
 #endif
 
@@ -1205,7 +1283,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
                                       sockindex));
     if(incache) {
       if(old_cred != BACKEND->cred) {
-        infof(data, "schannel: old credential handle is stale, removing\n");
+        DEBUGF(infof(data,
+                     "schannel: old credential handle is stale, removing\n"));
         /* we're not taking old_cred ownership here, no refcount++ is needed */
         Curl_ssl_delsessionid(conn, (void *)old_cred);
         incache = FALSE;
@@ -1223,13 +1302,15 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
       else {
         /* this cred session is now also referenced by sessionid cache */
         BACKEND->cred->refcount++;
-        infof(data, "schannel: stored credential handle in session cache\n");
+        DEBUGF(infof(data,
+                     "schannel: stored credential handle in session cache\n"));
       }
     }
     Curl_ssl_sessionid_unlock(conn);
   }
 
   if(data->set.ssl.certinfo) {
+    int certs_count = 0;
     sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
       SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context);
 
@@ -1238,15 +1319,15 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
       return CURLE_PEER_FAILED_VERIFICATION;
     }
 
-    result = Curl_ssl_init_certinfo(data, 1);
-    if(!result) {
-      if(((ccert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
-         (ccert_context->cbCertEncoded > 0)) {
+    traverse_cert_store(ccert_context, cert_counter_callback, &certs_count);
 
-        const char *beg = (const char *) ccert_context->pbCertEncoded;
-        const char *end = beg + ccert_context->cbCertEncoded;
-        result = Curl_extract_certinfo(conn, 0, beg, end);
-      }
+    result = Curl_ssl_init_certinfo(data, certs_count);
+    if(!result) {
+      struct Adder_args args;
+      args.conn = conn;
+      args.idx = 0;
+      traverse_cert_store(ccert_context, add_cert_to_certinfo, &args);
+      result = args.result;
     }
     CertFreeCertificateContext(ccert_context);
     if(result)
@@ -1359,6 +1440,16 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
     connssl->state = ssl_connection_complete;
     conn->recv[sockindex] = schannel_recv;
     conn->send[sockindex] = schannel_send;
+
+#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
+    /* When SSPI is used in combination with Schannel
+     * we need the Schannel context to create the Schannel
+     * binding to pass the IIS extended protection checks.
+     * Available on Windows 7 or later.
+     */
+    conn->sslContext = &BACKEND->ctxt->ctxt_handle;
+#endif
+
     *done = TRUE;
   }
   else
@@ -1543,7 +1634,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
    * handled in the cleanup.
    */
 
-  infof(data, "schannel: client wants to read %zu bytes\n", len);
+  DEBUGF(infof(data, "schannel: client wants to read %zu bytes\n", len));
   *err = CURLE_OK;
 
   if(len && len <= BACKEND->decdata_offset) {
@@ -1588,12 +1679,13 @@ schannel_recv(struct connectdata *conn, int sockindex,
       BACKEND->encdata_buffer = reallocated_buffer;
       BACKEND->encdata_length = reallocated_length;
       size = BACKEND->encdata_length - BACKEND->encdata_offset;
-      infof(data, "schannel: encdata_buffer resized %zu\n",
-            BACKEND->encdata_length);
+      DEBUGF(infof(data, "schannel: encdata_buffer resized %zu\n",
+                   BACKEND->encdata_length));
     }
 
-    infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
-          BACKEND->encdata_offset, BACKEND->encdata_length);
+    DEBUGF(infof(data,
+                 "schannel: encrypted data buffer: offset %zu length %zu\n",
+                 BACKEND->encdata_offset, BACKEND->encdata_length));
 
     /* read encrypted data from socket */
     *err = Curl_read_plain(conn->sock[sockindex],
@@ -1603,7 +1695,8 @@ schannel_recv(struct connectdata *conn, int sockindex,
     if(*err) {
       nread = -1;
       if(*err == CURLE_AGAIN)
-        infof(data, "schannel: Curl_read_plain returned CURLE_AGAIN\n");
+        DEBUGF(infof(data,
+                     "schannel: Curl_read_plain returned CURLE_AGAIN\n"));
       else if(*err == CURLE_RECV_ERROR)
         infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n");
       else
@@ -1611,17 +1704,18 @@ schannel_recv(struct connectdata *conn, int sockindex,
     }
     else if(nread == 0) {
       BACKEND->recv_connection_closed = true;
-      infof(data, "schannel: server closed the connection\n");
+      DEBUGF(infof(data, "schannel: server closed the connection\n"));
     }
     else if(nread > 0) {
       BACKEND->encdata_offset += (size_t)nread;
       BACKEND->encdata_is_incomplete = false;
-      infof(data, "schannel: encrypted data got %zd\n", nread);
+      DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread));
     }
   }
 
-  infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
-        BACKEND->encdata_offset, BACKEND->encdata_length);
+  DEBUGF(infof(data,
+               "schannel: encrypted data buffer: offset %zu length %zu\n",
+               BACKEND->encdata_offset, BACKEND->encdata_length));
 
   /* decrypt loop */
   while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK &&
@@ -1649,8 +1743,8 @@ schannel_recv(struct connectdata *conn, int sockindex,
       /* check for successfully decrypted data, even before actual
          renegotiation or shutdown of the connection context */
       if(inbuf[1].BufferType == SECBUFFER_DATA) {
-        infof(data, "schannel: decrypted data length: %lu\n",
-              inbuf[1].cbBuffer);
+        DEBUGF(infof(data, "schannel: decrypted data length: %lu\n",
+                     inbuf[1].cbBuffer));
 
         /* increase buffer in order to fit the received amount of data */
         size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ?
@@ -1682,15 +1776,16 @@ schannel_recv(struct connectdata *conn, int sockindex,
           BACKEND->decdata_offset += size;
         }
 
-        infof(data, "schannel: decrypted data added: %zu\n", size);
-        infof(data, "schannel: decrypted data cached: offset %zu length %zu\n",
-              BACKEND->decdata_offset, BACKEND->decdata_length);
+        DEBUGF(infof(data, "schannel: decrypted data added: %zu\n", size));
+        DEBUGF(infof(data,
+                     "schannel: decrypted cached: offset %zu length %zu\n",
+                     BACKEND->decdata_offset, BACKEND->decdata_length));
       }
 
       /* check for remaining encrypted data */
       if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
-        infof(data, "schannel: encrypted data length: %lu\n",
-              inbuf[3].cbBuffer);
+        DEBUGF(infof(data, "schannel: encrypted data length: %lu\n",
+                     inbuf[3].cbBuffer));
 
         /* check if the remaining data is less than the total amount
          * and therefore begins after the already processed data
@@ -1704,8 +1799,9 @@ schannel_recv(struct connectdata *conn, int sockindex,
           BACKEND->encdata_offset = inbuf[3].cbBuffer;
         }
 
-        infof(data, "schannel: encrypted data cached: offset %zu length %zu\n",
-              BACKEND->encdata_offset, BACKEND->encdata_length);
+        DEBUGF(infof(data,
+                     "schannel: encrypted cached: offset %zu length %zu\n",
+                     BACKEND->encdata_offset, BACKEND->encdata_length));
       }
       else {
         /* reset encrypted buffer offset, because there is no data remaining */
@@ -1759,22 +1855,25 @@ schannel_recv(struct connectdata *conn, int sockindex,
       goto cleanup;
     }
     else {
+      char buffer[STRERROR_LEN];
       *err = CURLE_RECV_ERROR;
       infof(data, "schannel: failed to read data from server: %s\n",
-            Curl_sspi_strerror(conn, sspi_status));
+            Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
       goto cleanup;
     }
   }
 
-  infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
-        BACKEND->encdata_offset, BACKEND->encdata_length);
+  DEBUGF(infof(data,
+               "schannel: encrypted data buffer: offset %zu length %zu\n",
+               BACKEND->encdata_offset, BACKEND->encdata_length));
 
-  infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
-        BACKEND->decdata_offset, BACKEND->decdata_length);
+  DEBUGF(infof(data,
+               "schannel: decrypted data buffer: offset %zu length %zu\n",
+               BACKEND->decdata_offset, BACKEND->decdata_length));
 
 cleanup:
   /* Warning- there is no guarantee the encdata state is valid at this point */
-  infof(data, "schannel: schannel_recv cleanup\n");
+  DEBUGF(infof(data, "schannel: schannel_recv cleanup\n"));
 
   /* Error if the connection has closed without a close_notify.
   Behavior here is a matter of debate. We don't want to be vulnerable to a
@@ -1807,10 +1906,10 @@ cleanup:
     memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size,
             BACKEND->decdata_offset - size);
     BACKEND->decdata_offset -= size;
-
-    infof(data, "schannel: decrypted data returned %zu\n", size);
-    infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
-          BACKEND->decdata_offset, BACKEND->decdata_length);
+    DEBUGF(infof(data, "schannel: decrypted data returned %zu\n", size));
+    DEBUGF(infof(data,
+                 "schannel: decrypted data buffer: offset %zu length %zu\n",
+                 BACKEND->decdata_offset, BACKEND->decdata_length));
     *err = CURLE_OK;
     return (ssize_t)size;
   }
@@ -1888,6 +1987,8 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
   char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
 
+  DEBUGASSERT(data);
+
   infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
         hostname, conn->remote_port);
 
@@ -1907,9 +2008,11 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
     sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle,
                                               &BuffDesc);
 
-    if(sspi_status != SEC_E_OK)
+    if(sspi_status != SEC_E_OK) {
+      char buffer[STRERROR_LEN];
       failf(data, "schannel: ApplyControlToken failure: %s",
-            Curl_sspi_strerror(conn, sspi_status));
+            Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+    }
 
     host_name = Curl_convert_UTF8_to_tchar(hostname);
     if(!host_name)
@@ -1951,13 +2054,18 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
 
   /* free SSPI Schannel API security context handle */
   if(BACKEND->ctxt) {
-    infof(data, "schannel: clear security context handle\n");
+    DEBUGF(infof(data, "schannel: clear security context handle\n"));
     s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle);
     Curl_safefree(BACKEND->ctxt);
   }
 
   /* free SSPI Schannel API credential handle */
   if(BACKEND->cred) {
+    /*
+     * When this function is called from Curl_schannel_close() the connection
+     * might not have an associated transfer so the check for conn->data is
+     * necessary.
+     */
     Curl_ssl_sessionid_lock(conn);
     Curl_schannel_session_free(BACKEND->cred);
     Curl_ssl_sessionid_unlock(conn);
@@ -1994,7 +2102,7 @@ static void Curl_schannel_cleanup(void)
 
 static size_t Curl_schannel_version(char *buffer, size_t size)
 {
-  size = snprintf(buffer, size, "WinSSL");
+  size = msnprintf(buffer, size, "Schannel");
 
   return size;
 }
@@ -2022,14 +2130,9 @@ static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
 static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
                                     const char *pinnedpubkey)
 {
-  SECURITY_STATUS status;
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   CERT_CONTEXT *pCertContextServer = NULL;
-  const char *x509_der;
-  DWORD x509_der_len;
-  curl_X509certificate x509_parsed;
-  curl_asn1Element *pubkey;
 
   /* Result is returned to caller */
   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
@@ -2039,13 +2142,21 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
     return CURLE_OK;
 
   do {
-    status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
-                                              SECPKG_ATTR_REMOTE_CERT_CONTEXT,
-                                              &pCertContextServer);
+    SECURITY_STATUS sspi_status;
+    const char *x509_der;
+    DWORD x509_der_len;
+    curl_X509certificate x509_parsed;
+    curl_asn1Element *pubkey;
 
-    if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
+    sspi_status =
+      s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+                                       SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+                                       &pCertContextServer);
+
+    if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) {
+      char buffer[STRERROR_LEN];
       failf(data, "schannel: Failed to read remote certificate context: %s",
-            Curl_sspi_strerror(conn, status));
+            Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
       break; /* failed */
     }
 
@@ -2082,11 +2193,11 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
 }
 
 static void Curl_schannel_checksum(const unsigned char *input,
-                      size_t inputlen,
-                      unsigned char *checksum,
-                      size_t checksumlen,
-                      DWORD provType,
-                      const unsigned int algId)
+                                   size_t inputlen,
+                                   unsigned char *checksum,
+                                   size_t checksumlen,
+                                   DWORD provType,
+                                   const unsigned int algId)
 {
   HCRYPTPROV hProv = 0;
   HCRYPTHASH hHash = 0;
@@ -2136,9 +2247,9 @@ static CURLcode Curl_schannel_md5sum(unsigned char *input,
                                      unsigned char *md5sum,
                                      size_t md5len)
 {
-    Curl_schannel_checksum(input, inputlen, md5sum, md5len,
-                           PROV_RSA_FULL, CALG_MD5);
-    return CURLE_OK;
+  Curl_schannel_checksum(input, inputlen, md5sum, md5len,
+                         PROV_RSA_FULL, CALG_MD5);
+  return CURLE_OK;
 }
 
 static CURLcode Curl_schannel_sha256sum(const unsigned char *input,
@@ -2146,9 +2257,9 @@ static CURLcode Curl_schannel_sha256sum(const unsigned char *input,
                                     unsigned char *sha256sum,
                                     size_t sha256len)
 {
-    Curl_schannel_checksum(input, inputlen, sha256sum, sha256len,
-                           PROV_RSA_AES, CALG_SHA_256);
-    return CURLE_OK;
+  Curl_schannel_checksum(input, inputlen, sha256sum, sha256len,
+                         PROV_RSA_AES, CALG_SHA_256);
+  return CURLE_OK;
 }
 
 static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
diff --git a/lib/vtls/schannel.h b/lib/vtls/schannel.h
index e491bd4..ee8d7d4 100644
--- a/lib/vtls/schannel.h
+++ b/lib/vtls/schannel.h
@@ -8,7 +8,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012, Marc Hoersken, <info at marc-hoersken.de>, et al.
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -53,7 +53,7 @@
 
 extern const struct Curl_ssl Curl_ssl_schannel;
 
-CURLcode verify_certificate(struct connectdata *conn, int sockindex);
+CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex);
 
 /* structs to expose only in schannel.c and schannel_verify.c */
 #ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c
index 2516f56..5a09e96 100644
--- a/lib/vtls/schannel_verify.c
+++ b/lib/vtls/schannel_verify.c
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2012 - 2016, Marc Hoersken, <info at marc-hoersken.de>
  * Copyright (C) 2012, Mark Salisbury, <mark.salisbury at hp.com>
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
  ***************************************************************************/
 
 /*
- * Source file for SChannel-specific certificate verification. This code should
+ * Source file for Schannel-specific certificate verification. This code should
  * only be invoked by code in schannel.c.
  */
 
@@ -87,18 +87,19 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
   LARGE_INTEGER file_size;
   char *ca_file_buffer = NULL;
   char *current_ca_file_ptr = NULL;
-  const TCHAR *ca_file_tstr = NULL;
+  TCHAR *ca_file_tstr = NULL;
   size_t ca_file_bufsize = 0;
   DWORD total_bytes_read = 0;
   bool more_certs = 0;
   int num_certs = 0;
   size_t END_CERT_LEN;
 
-  ca_file_tstr = Curl_convert_UTF8_to_tchar(ca_file);
+  ca_file_tstr = Curl_convert_UTF8_to_tchar((char *)ca_file);
   if(!ca_file_tstr) {
+    char buffer[STRERROR_LEN];
     failf(data,
           "schannel: invalid path name for CA file '%s': %s",
-          ca_file, Curl_strerror(conn, GetLastError()));
+          ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
     result = CURLE_SSL_CACERT_BADFILE;
     goto cleanup;
   }
@@ -116,17 +117,19 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
                               FILE_ATTRIBUTE_NORMAL,
                               NULL);
   if(ca_file_handle == INVALID_HANDLE_VALUE) {
+    char buffer[STRERROR_LEN];
     failf(data,
           "schannel: failed to open CA file '%s': %s",
-          ca_file, Curl_strerror(conn, GetLastError()));
+          ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
     result = CURLE_SSL_CACERT_BADFILE;
     goto cleanup;
   }
 
   if(!GetFileSizeEx(ca_file_handle, &file_size)) {
+    char buffer[STRERROR_LEN];
     failf(data,
           "schannel: failed to determine size of CA file '%s': %s",
-          ca_file, Curl_strerror(conn, GetLastError()));
+          ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
     result = CURLE_SSL_CACERT_BADFILE;
     goto cleanup;
   }
@@ -153,10 +156,10 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
 
     if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read,
                  bytes_to_read, &bytes_read, NULL)) {
-
+      char buffer[STRERROR_LEN];
       failf(data,
             "schannel: failed to read from CA file '%s': %s",
-            ca_file, Curl_strerror(conn, GetLastError()));
+            ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
       result = CURLE_SSL_CACERT_BADFILE;
       goto cleanup;
     }
@@ -215,11 +218,12 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
                              NULL,
                              NULL,
                              (const void **)&cert_context)) {
-
+          char buffer[STRERROR_LEN];
           failf(data,
                 "schannel: failed to extract certificate from CA file "
                 "'%s': %s",
-                ca_file, Curl_strerror(conn, GetLastError()));
+                ca_file,
+                Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
           result = CURLE_SSL_CACERT_BADFILE;
           more_certs = 0;
         }
@@ -243,10 +247,12 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
                                                NULL);
             CertFreeCertificateContext(cert_context);
             if(!add_cert_result) {
+              char buffer[STRERROR_LEN];
               failf(data,
                     "schannel: failed to add certificate from CA file '%s' "
                     "to certificate store: %s",
-                    ca_file, Curl_strerror(conn, GetLastError()));
+                    ca_file,
+                    Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
               result = CURLE_SSL_CACERT_BADFILE;
               more_certs = 0;
             }
@@ -406,9 +412,9 @@ cleanup:
   return result;
 }
 
-CURLcode verify_certificate(struct connectdata *conn, int sockindex)
+CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
 {
-  SECURITY_STATUS status;
+  SECURITY_STATUS sspi_status;
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   CURLcode result = CURLE_OK;
@@ -420,13 +426,15 @@ CURLcode verify_certificate(struct connectdata *conn, int sockindex)
     conn->http_proxy.host.name :
     conn->host.name;
 
-  status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
-                                            SECPKG_ATTR_REMOTE_CERT_CONTEXT,
-                                            &pCertContextServer);
+  sspi_status =
+    s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+                                     SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+                                     &pCertContextServer);
 
-  if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
+  if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) {
+    char buffer[STRERROR_LEN];
     failf(data, "schannel: Failed to read remote certificate context: %s",
-          Curl_sspi_strerror(conn, status));
+          Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
     result = CURLE_PEER_FAILED_VERIFICATION;
   }
 
@@ -450,8 +458,9 @@ CURLcode verify_certificate(struct connectdata *conn, int sockindex)
                                   CERT_STORE_CREATE_NEW_FLAG,
                                   NULL);
       if(!trust_store) {
+        char buffer[STRERROR_LEN];
         failf(data, "schannel: failed to create certificate store: %s",
-              Curl_strerror(conn, GetLastError()));
+              Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
         result = CURLE_SSL_CACERT_BADFILE;
       }
       else {
@@ -477,9 +486,10 @@ CURLcode verify_certificate(struct connectdata *conn, int sockindex)
         CertCreateCertificateChainEngine(
           (CERT_CHAIN_ENGINE_CONFIG *)&engine_config, &cert_chain_engine);
       if(!create_engine_result) {
+        char buffer[STRERROR_LEN];
         failf(data,
               "schannel: failed to create certificate chain engine: %s",
-              Curl_strerror(conn, GetLastError()));
+              Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
         result = CURLE_SSL_CACERT_BADFILE;
       }
     }
@@ -500,8 +510,9 @@ CURLcode verify_certificate(struct connectdata *conn, int sockindex)
                                  CERT_CHAIN_REVOCATION_CHECK_CHAIN),
                                 NULL,
                                 &pChainContext)) {
+      char buffer[STRERROR_LEN];
       failf(data, "schannel: CertGetCertificateChain failed: %s",
-            Curl_sspi_strerror(conn, GetLastError()));
+            Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
       pChainContext = NULL;
       result = CURLE_PEER_FAILED_VERIFICATION;
     }
diff --git a/lib/vtls/darwinssl.c b/lib/vtls/sectransp.c
similarity index 95%
rename from lib/vtls/darwinssl.c
rename to lib/vtls/sectransp.c
index e8116b8..2fdf662 100644
--- a/lib/vtls/darwinssl.c
+++ b/lib/vtls/sectransp.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman at gmail.com>.
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -31,8 +31,9 @@
 #include "urldata.h" /* for the Curl_easy definition */
 #include "curl_base64.h"
 #include "strtok.h"
+#include "multiif.h"
 
-#ifdef USE_DARWINSSL
+#ifdef USE_SECTRANSP
 
 #ifdef __clang__
 #pragma clang diagnostic push
@@ -59,7 +60,7 @@
 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
-#error "The darwinssl back-end requires Leopard or later."
+#error "The Secure Transport back-end requires Leopard or later."
 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
 
 #define CURL_BUILD_IOS 0
@@ -105,7 +106,7 @@
 #define CURL_SUPPORT_MAC_10_9 0
 
 #else
-#error "The darwinssl back-end requires iOS or OS X."
+#error "The Secure Transport back-end requires iOS or macOS."
 #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
 
 #if CURL_BUILD_MAC
@@ -118,7 +119,7 @@
 #include "connect.h"
 #include "select.h"
 #include "vtls.h"
-#include "darwinssl.h"
+#include "sectransp.h"
 #include "curl_printf.h"
 #include "strdup.h"
 
@@ -144,20 +145,20 @@ struct ssl_backend_data {
 /* version 1 supports macOS 10.12+ and iOS 10+ */
 #if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
     (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED  >= 101200))
-#define DARWIN_SSL_PINNEDPUBKEY_V1 1
+#define SECTRANSP_PINNEDPUBKEY_V1 1
 #endif
 
 /* version 2 supports MacOSX 10.7+ */
 #if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
-#define DARWIN_SSL_PINNEDPUBKEY_V2 1
+#define SECTRANSP_PINNEDPUBKEY_V2 1
 #endif
 
-#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2)
+#if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2)
 /* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define DARWIN_SSL_PINNEDPUBKEY 1
-#endif /* DARWIN_SSL_PINNEDPUBKEY */
+#define SECTRANSP_PINNEDPUBKEY 1
+#endif /* SECTRANSP_PINNEDPUBKEY */
 
-#ifdef DARWIN_SSL_PINNEDPUBKEY
+#ifdef SECTRANSP_PINNEDPUBKEY
 /* both new and old APIs return rsa keys missing the spki header (not DER) */
 static const unsigned char rsa4096SpkiHeader[] = {
                                        0x30, 0x82, 0x02, 0x22, 0x30, 0x0d,
@@ -170,7 +171,7 @@ static const unsigned char rsa2048SpkiHeader[] = {
                                        0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
                                        0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
                                        0x00, 0x03, 0x82, 0x01, 0x0f, 0x00};
-#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
+#ifdef SECTRANSP_PINNEDPUBKEY_V1
 /* the *new* version doesn't return DER encoded ecdsa certs like the old... */
 static const unsigned char ecDsaSecp256r1SpkiHeader[] = {
                                        0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
@@ -184,8 +185,8 @@ static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
                                        0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
                                        0x01, 0x06, 0x05, 0x2b, 0x81, 0x04,
                                        0x00, 0x22, 0x03, 0x62, 0x00};
-#endif /* DARWIN_SSL_PINNEDPUBKEY_V1 */
-#endif /* DARWIN_SSL_PINNEDPUBKEY */
+#endif /* SECTRANSP_PINNEDPUBKEY_V1 */
+#endif /* SECTRANSP_PINNEDPUBKEY */
 
 /* The following two functions were ripped from Apple sample code,
  * with some modifications: */
@@ -950,7 +951,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data,
 
   if(!c) {
     failf(data, "SSL: invalid CA certificate subject");
-    return CURLE_SSL_CACERT;
+    return CURLE_PEER_FAILED_VERIFICATION;
   }
 
   /* If the subject is already available as UTF-8 encoded (ie 'direct') then
@@ -970,7 +971,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data,
       if(!CFStringGetCString(c, cbuf, cbuf_size,
                              kCFStringEncodingUTF8)) {
         failf(data, "SSL: invalid CA certificate subject");
-        result = CURLE_SSL_CACERT;
+        result = CURLE_PEER_FAILED_VERIFICATION;
       }
       else
         /* pass back the buffer */
@@ -1242,7 +1243,7 @@ CF_INLINE bool is_file(const char *filename)
 }
 
 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
-static CURLcode darwinssl_version_from_curl(SSLProtocol *darwinver,
+static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver,
                                             long ssl_version)
 {
   switch(ssl_version) {
@@ -1298,7 +1299,6 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
     case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1:
       ssl_version = CURL_SSLVERSION_TLSv1_0;
-      ssl_version_max = max_supported_version_by_os;
       break;
   }
 
@@ -1313,13 +1313,13 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
   if(SSLSetProtocolVersionMax != NULL) {
     SSLProtocol darwin_ver_min = kTLSProtocol1;
     SSLProtocol darwin_ver_max = kTLSProtocol1;
-    CURLcode result = darwinssl_version_from_curl(&darwin_ver_min,
+    CURLcode result = sectransp_version_from_curl(&darwin_ver_min,
                                                   ssl_version);
     if(result) {
       failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
       return result;
     }
-    result = darwinssl_version_from_curl(&darwin_ver_max,
+    result = sectransp_version_from_curl(&darwin_ver_max,
                                          ssl_version_max >> 16);
     if(result) {
       failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
@@ -1362,12 +1362,12 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
 #endif  /* CURL_SUPPORT_MAC_10_8 */
   }
 #endif  /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
-  failf(data, "DarwinSSL: cannot set SSL protocol");
+  failf(data, "Secure Transport: cannot set SSL protocol");
   return CURLE_SSL_CONNECT_ERROR;
 }
 
 
-static CURLcode darwinssl_connect_step1(struct connectdata *conn,
+static CURLcode sectransp_connect_step1(struct connectdata *conn,
                                         int sockindex)
 {
   struct Curl_easy *data = conn->data;
@@ -1430,7 +1430,6 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
   if(SSLSetProtocolVersionMax != NULL) {
     switch(conn->ssl_config.version) {
-    case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1:
       (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1);
 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
@@ -1445,6 +1444,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
 #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
           HAVE_BUILTIN_AVAILABLE == 1 */
       break;
+    case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1_0:
     case CURL_SSLVERSION_TLSv1_1:
     case CURL_SSLVERSION_TLSv1_2:
@@ -1578,7 +1578,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
 
 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
   if(conn->bits.tls_enable_alpn) {
-    if(__builtin_available(macOS 10.13.4, iOS 11, *)) {
+    if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
       CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
                                                        &kCFTypeArrayCallBacks);
 
@@ -1649,7 +1649,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
         }
 
         CFRelease(cert);
-        if(result == CURLE_SSL_CACERT)
+        if(result == CURLE_PEER_FAILED_VERIFICATION)
           return CURLE_SSL_CERTPROBLEM;
         if(result)
           return result;
@@ -1903,7 +1903,6 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   /* We want to enable 1/n-1 when using a CBC cipher unless the user
      specifically doesn't want us doing that: */
   if(SSLSetSessionOption != NULL) {
-    /* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */
     SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
                       !data->set.ssl.enable_beast);
     SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionFalseStart,
@@ -2235,7 +2234,7 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
   }
 }
 
-#ifdef DARWIN_SSL_PINNEDPUBKEY
+#ifdef SECTRANSP_PINNEDPUBKEY
 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
                                     SSLContextRef ctx,
                                     const char *pinnedpubkey)
@@ -2267,14 +2266,14 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
     if(keyRef == NULL)
       break;
 
-#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
+#ifdef SECTRANSP_PINNEDPUBKEY_V1
 
     publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
     CFRelease(keyRef);
     if(publicKeyBits == NULL)
       break;
 
-#elif DARWIN_SSL_PINNEDPUBKEY_V2
+#elif SECTRANSP_PINNEDPUBKEY_V2
 
     OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
                                      &publicKeyBits);
@@ -2282,7 +2281,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
     if(success != errSecSuccess || publicKeyBits == NULL)
       break;
 
-#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */
+#endif /* SECTRANSP_PINNEDPUBKEY_V2 */
 
     pubkeylen = CFDataGetLength(publicKeyBits);
     pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits);
@@ -2296,7 +2295,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
         /* 2048 bit RSA pubkeylen == 270 */
         spkiHeader = rsa2048SpkiHeader;
         break;
-#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
+#ifdef SECTRANSP_PINNEDPUBKEY_V1
       case 65:
         /* ecDSA secp256r1 pubkeylen == 65 */
         spkiHeader = ecDsaSecp256r1SpkiHeader;
@@ -2309,7 +2308,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
         break;
       default:
         infof(data, "SSL: unhandled public key length: %d\n", pubkeylen);
-#elif DARWIN_SSL_PINNEDPUBKEY_V2
+#elif SECTRANSP_PINNEDPUBKEY_V2
       default:
         /* ecDSA secp256r1 pubkeylen == 91 header already included?
          * ecDSA secp384r1 header already included too
@@ -2317,7 +2316,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
          */
         result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey,
                                     pubkeylen);
-#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */
+#endif /* SECTRANSP_PINNEDPUBKEY_V2 */
         continue; /* break from loop */
     }
 
@@ -2340,10 +2339,10 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
 
   return result;
 }
-#endif /* DARWIN_SSL_PINNEDPUBKEY */
+#endif /* SECTRANSP_PINNEDPUBKEY */
 
 static CURLcode
-darwinssl_connect_step2(struct connectdata *conn, int sockindex)
+sectransp_connect_step2(struct connectdata *conn, int sockindex)
 {
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -2377,7 +2376,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
             return res;
         }
         /* the documentation says we need to call SSLHandshake() again */
-        return darwinssl_connect_step2(conn, sockindex);
+        return sectransp_connect_step2(conn, sockindex);
 
       /* Problem with encrypt / decrypt */
       case errSSLPeerDecodeError:
@@ -2429,37 +2428,37 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
       /* These are all certificate problems with the server: */
       case errSSLXCertChainInvalid:
         failf(data, "SSL certificate problem: Invalid certificate chain");
-        return CURLE_SSL_CACERT;
+        return CURLE_PEER_FAILED_VERIFICATION;
       case errSSLUnknownRootCert:
         failf(data, "SSL certificate problem: Untrusted root certificate");
-        return CURLE_SSL_CACERT;
+        return CURLE_PEER_FAILED_VERIFICATION;
       case errSSLNoRootCert:
         failf(data, "SSL certificate problem: No root certificate");
-        return CURLE_SSL_CACERT;
+        return CURLE_PEER_FAILED_VERIFICATION;
       case errSSLCertNotYetValid:
         failf(data, "SSL certificate problem: The certificate chain had a "
                     "certificate that is not yet valid");
-        return CURLE_SSL_CACERT;
+        return CURLE_PEER_FAILED_VERIFICATION;
       case errSSLCertExpired:
       case errSSLPeerCertExpired:
         failf(data, "SSL certificate problem: Certificate chain had an "
               "expired certificate");
-        return CURLE_SSL_CACERT;
+        return CURLE_PEER_FAILED_VERIFICATION;
       case errSSLBadCert:
       case errSSLPeerBadCert:
         failf(data, "SSL certificate problem: Couldn't understand the server "
               "certificate format");
-        return CURLE_SSL_CACERT;
+        return CURLE_PEER_FAILED_VERIFICATION;
       case errSSLPeerUnsupportedCert:
         failf(data, "SSL certificate problem: An unsupported certificate "
                     "format was encountered");
-        return CURLE_SSL_CACERT;
+        return CURLE_PEER_FAILED_VERIFICATION;
       case errSSLPeerCertRevoked:
         failf(data, "SSL certificate problem: The certificate was revoked");
-        return CURLE_SSL_CACERT;
+        return CURLE_PEER_FAILED_VERIFICATION;
       case errSSLPeerCertUnknown:
         failf(data, "SSL certificate problem: The certificate is unknown");
-        return CURLE_SSL_CACERT;
+        return CURLE_PEER_FAILED_VERIFICATION;
 
       /* These are all certificate problems with the client: */
       case errSecAuthFailed:
@@ -2579,7 +2578,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
     /* we have been connected fine, we're not waiting for anything else. */
     connssl->connecting_state = ssl_connect_3;
 
-#ifdef DARWIN_SSL_PINNEDPUBKEY
+#ifdef SECTRANSP_PINNEDPUBKEY
     if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) {
       CURLcode result = pkp_pin_peer_pubkey(data, BACKEND->ssl_ctx,
                             data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
@@ -2588,7 +2587,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
         return result;
       }
     }
-#endif /* DARWIN_SSL_PINNEDPUBKEY */
+#endif /* SECTRANSP_PINNEDPUBKEY */
 
     /* Informational message */
     (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher);
@@ -2629,7 +2628,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
 
 #if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
     if(conn->bits.tls_enable_alpn) {
-      if(__builtin_available(macOS 10.13.4, iOS 11, *)) {
+      if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
         CFArrayRef alpnArr = NULL;
         CFStringRef chosenProtocol = NULL;
         err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr);
@@ -2652,6 +2651,9 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
         else
           infof(data, "ALPN, server did not agree to a protocol\n");
 
+        Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+                            BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+
         /* chosenProtocol is a reference to the string within alpnArr
            and doesn't need to be freed separately */
         if(alpnArr)
@@ -2772,7 +2774,7 @@ show_verbose_server_cert(struct connectdata *conn,
 #endif /* !CURL_DISABLE_VERBOSE_STRINGS */
 
 static CURLcode
-darwinssl_connect_step3(struct connectdata *conn,
+sectransp_connect_step3(struct connectdata *conn,
                         int sockindex)
 {
   struct Curl_easy *data = conn->data;
@@ -2790,11 +2792,11 @@ darwinssl_connect_step3(struct connectdata *conn,
   return CURLE_OK;
 }
 
-static Curl_recv darwinssl_recv;
-static Curl_send darwinssl_send;
+static Curl_recv sectransp_recv;
+static Curl_send sectransp_send;
 
 static CURLcode
-darwinssl_connect_common(struct connectdata *conn,
+sectransp_connect_common(struct connectdata *conn,
                          int sockindex,
                          bool nonblocking,
                          bool *done)
@@ -2822,7 +2824,7 @@ darwinssl_connect_common(struct connectdata *conn,
       return CURLE_OPERATION_TIMEDOUT;
     }
 
-    result = darwinssl_connect_step1(conn, sockindex);
+    result = sectransp_connect_step1(conn, sockindex);
     if(result)
       return result;
   }
@@ -2876,7 +2878,7 @@ darwinssl_connect_common(struct connectdata *conn,
      * before step2 has completed while ensuring that a client using select()
      * or epoll() will always have a valid fdset to wait on.
      */
-    result = darwinssl_connect_step2(conn, sockindex);
+    result = sectransp_connect_step2(conn, sockindex);
     if(result || (nonblocking &&
                   (ssl_connect_2 == connssl->connecting_state ||
                    ssl_connect_2_reading == connssl->connecting_state ||
@@ -2887,15 +2889,15 @@ darwinssl_connect_common(struct connectdata *conn,
 
 
   if(ssl_connect_3 == connssl->connecting_state) {
-    result = darwinssl_connect_step3(conn, sockindex);
+    result = sectransp_connect_step3(conn, sockindex);
     if(result)
       return result;
   }
 
   if(ssl_connect_done == connssl->connecting_state) {
     connssl->state = ssl_connection_complete;
-    conn->recv[sockindex] = darwinssl_recv;
-    conn->send[sockindex] = darwinssl_send;
+    conn->recv[sockindex] = sectransp_recv;
+    conn->send[sockindex] = sectransp_send;
     *done = TRUE;
   }
   else
@@ -2907,18 +2909,18 @@ darwinssl_connect_common(struct connectdata *conn,
   return CURLE_OK;
 }
 
-static CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
+static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn,
                                                    int sockindex, bool *done)
 {
-  return darwinssl_connect_common(conn, sockindex, TRUE, done);
+  return sectransp_connect_common(conn, sockindex, TRUE, done);
 }
 
-static CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex)
+static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode result;
   bool done = FALSE;
 
-  result = darwinssl_connect_common(conn, sockindex, FALSE, &done);
+  result = sectransp_connect_common(conn, sockindex, FALSE, &done);
 
   if(result)
     return result;
@@ -2928,7 +2930,7 @@ static CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex)
   return CURLE_OK;
 }
 
-static void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
+static void Curl_sectransp_close(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
@@ -2949,7 +2951,7 @@ static void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
   BACKEND->ssl_sockfd = 0;
 }
 
-static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct Curl_easy *data = conn->data;
@@ -2961,10 +2963,12 @@ static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
   if(!BACKEND->ssl_ctx)
     return 0;
 
+#ifndef CURL_DISABLE_FTP
   if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
     return 0;
+#endif
 
-  Curl_darwinssl_close(conn, sockindex);
+  Curl_sectransp_close(conn, sockindex);
 
   rc = 0;
 
@@ -3002,20 +3006,20 @@ static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
   return rc;
 }
 
-static void Curl_darwinssl_session_free(void *ptr)
+static void Curl_sectransp_session_free(void *ptr)
 {
   /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
      cached session ID inside the Security framework. There is a private
      function that does this, but I don't want to have to explain to you why I
      got your application rejected from the App Store due to the use of a
      private API, so the best we can do is free up our own char array that we
-     created way back in darwinssl_connect_step1... */
+     created way back in sectransp_connect_step1... */
   Curl_safefree(ptr);
 }
 
-static size_t Curl_darwinssl_version(char *buffer, size_t size)
+static size_t Curl_sectransp_version(char *buffer, size_t size)
 {
-  return snprintf(buffer, size, "SecureTransport");
+  return msnprintf(buffer, size, "SecureTransport");
 }
 
 /*
@@ -3026,7 +3030,7 @@ static size_t Curl_darwinssl_version(char *buffer, size_t size)
  *     0 means the connection has been closed
  *    -1 means the connection status is unknown
  */
-static int Curl_darwinssl_check_cxn(struct connectdata *conn)
+static int Curl_sectransp_check_cxn(struct connectdata *conn)
 {
   struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
   OSStatus err;
@@ -3041,7 +3045,7 @@ static int Curl_darwinssl_check_cxn(struct connectdata *conn)
   return 0;
 }
 
-static bool Curl_darwinssl_data_pending(const struct connectdata *conn,
+static bool Curl_sectransp_data_pending(const struct connectdata *conn,
                                         int connindex)
 {
   const struct ssl_connect_data *connssl = &conn->ssl[connindex];
@@ -3058,7 +3062,7 @@ static bool Curl_darwinssl_data_pending(const struct connectdata *conn,
     return false;
 }
 
-static CURLcode Curl_darwinssl_random(struct Curl_easy *data UNUSED_PARAM,
+static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM,
                                       unsigned char *entropy, size_t length)
 {
   /* arc4random_buf() isn't available on cats older than Lion, so let's
@@ -3078,7 +3082,7 @@ static CURLcode Curl_darwinssl_random(struct Curl_easy *data UNUSED_PARAM,
   return CURLE_OK;
 }
 
-static CURLcode Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
+static CURLcode Curl_sectransp_md5sum(unsigned char *tmp, /* input */
                                       size_t tmplen,
                                       unsigned char *md5sum, /* output */
                                       size_t md5len)
@@ -3088,7 +3092,7 @@ static CURLcode Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
   return CURLE_OK;
 }
 
-static CURLcode Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */
                                      size_t tmplen,
                                      unsigned char *sha256sum, /* output */
                                      size_t sha256len)
@@ -3098,7 +3102,7 @@ static CURLcode Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
   return CURLE_OK;
 }
 
-static bool Curl_darwinssl_false_start(void)
+static bool Curl_sectransp_false_start(void)
 {
 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
   if(SSLSetSessionOption != NULL)
@@ -3107,7 +3111,7 @@ static bool Curl_darwinssl_false_start(void)
   return FALSE;
 }
 
-static ssize_t darwinssl_send(struct connectdata *conn,
+static ssize_t sectransp_send(struct connectdata *conn,
                               int sockindex,
                               const void *mem,
                               size_t len,
@@ -3173,7 +3177,7 @@ static ssize_t darwinssl_send(struct connectdata *conn,
   return (ssize_t)processed;
 }
 
-static ssize_t darwinssl_recv(struct connectdata *conn,
+static ssize_t sectransp_recv(struct connectdata *conn,
                               int num,
                               char *buf,
                               size_t buffersize,
@@ -3213,48 +3217,48 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
   return (ssize_t)processed;
 }
 
-static void *Curl_darwinssl_get_internals(struct ssl_connect_data *connssl,
+static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl,
                                           CURLINFO info UNUSED_PARAM)
 {
   (void)info;
   return BACKEND->ssl_ctx;
 }
 
-const struct Curl_ssl Curl_ssl_darwinssl = {
-  { CURLSSLBACKEND_DARWINSSL, "darwinssl" }, /* info */
+const struct Curl_ssl Curl_ssl_sectransp = {
+  { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */
 
-#ifdef DARWIN_SSL_PINNEDPUBKEY
+#ifdef SECTRANSP_PINNEDPUBKEY
   SSLSUPP_PINNEDPUBKEY,
 #else
   0,
-#endif /* DARWIN_SSL_PINNEDPUBKEY */
+#endif /* SECTRANSP_PINNEDPUBKEY */
 
   sizeof(struct ssl_backend_data),
 
   Curl_none_init,                     /* init */
   Curl_none_cleanup,                  /* cleanup */
-  Curl_darwinssl_version,             /* version */
-  Curl_darwinssl_check_cxn,           /* check_cxn */
-  Curl_darwinssl_shutdown,            /* shutdown */
-  Curl_darwinssl_data_pending,        /* data_pending */
-  Curl_darwinssl_random,              /* random */
+  Curl_sectransp_version,             /* version */
+  Curl_sectransp_check_cxn,           /* check_cxn */
+  Curl_sectransp_shutdown,            /* shutdown */
+  Curl_sectransp_data_pending,        /* data_pending */
+  Curl_sectransp_random,              /* random */
   Curl_none_cert_status_request,      /* cert_status_request */
-  Curl_darwinssl_connect,             /* connect */
-  Curl_darwinssl_connect_nonblocking, /* connect_nonblocking */
-  Curl_darwinssl_get_internals,       /* get_internals */
-  Curl_darwinssl_close,               /* close_one */
+  Curl_sectransp_connect,             /* connect */
+  Curl_sectransp_connect_nonblocking, /* connect_nonblocking */
+  Curl_sectransp_get_internals,       /* get_internals */
+  Curl_sectransp_close,               /* close_one */
   Curl_none_close_all,                /* close_all */
-  Curl_darwinssl_session_free,        /* session_free */
+  Curl_sectransp_session_free,        /* session_free */
   Curl_none_set_engine,               /* set_engine */
   Curl_none_set_engine_default,       /* set_engine_default */
   Curl_none_engines_list,             /* engines_list */
-  Curl_darwinssl_false_start,         /* false_start */
-  Curl_darwinssl_md5sum,              /* md5sum */
-  Curl_darwinssl_sha256sum            /* sha256sum */
+  Curl_sectransp_false_start,         /* false_start */
+  Curl_sectransp_md5sum,              /* md5sum */
+  Curl_sectransp_sha256sum            /* sha256sum */
 };
 
 #ifdef __clang__
 #pragma clang diagnostic pop
 #endif
 
-#endif /* USE_DARWINSSL */
+#endif /* USE_SECTRANSP */
diff --git a/lib/vtls/darwinssl.h b/lib/vtls/sectransp.h
similarity index 80%
rename from lib/vtls/darwinssl.h
rename to lib/vtls/sectransp.h
index 23c7f70..5cec797 100644
--- a/lib/vtls/darwinssl.h
+++ b/lib/vtls/sectransp.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_DARWINSSL_H
-#define HEADER_CURL_DARWINSSL_H
+#ifndef HEADER_CURL_SECTRANSP_H
+#define HEADER_CURL_SECTRANSP_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -8,7 +8,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman at gmail.com>.
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -24,9 +24,9 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
-#ifdef USE_DARWINSSL
+#ifdef USE_SECTRANSP
 
-extern const struct Curl_ssl Curl_ssl_darwinssl;
+extern const struct Curl_ssl Curl_ssl_sectransp;
 
-#endif /* USE_DARWINSSL */
-#endif /* HEADER_CURL_DARWINSSL_H */
+#endif /* USE_SECTRANSP */
+#endif /* HEADER_CURL_SECTRANSP_H */
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 6af39fe..a7452dc 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -248,7 +248,7 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex)
   conn->ssl[sockindex].use = TRUE;
   conn->ssl[sockindex].state = ssl_connection_negotiating;
 
-  result = Curl_ssl->connect(conn, sockindex);
+  result = Curl_ssl->connect_blocking(conn, sockindex);
 
   if(!result)
     Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
@@ -498,9 +498,9 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
 
 void Curl_ssl_close_all(struct Curl_easy *data)
 {
-  size_t i;
   /* kill the session ID cache if not shared */
   if(data->state.session && !SSLSESSION_SHARED(data)) {
+    size_t i;
     for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++)
       /* the single-killer function handles empty table slots */
       Curl_ssl_kill_session(&data->state.session[i]);
@@ -513,7 +513,7 @@ void Curl_ssl_close_all(struct Curl_easy *data)
 }
 
 #if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
-  defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \
+  defined(USE_SECTRANSP) || defined(USE_POLARSSL) || defined(USE_NSS) || \
   defined(USE_MBEDTLS) || defined(USE_CYASSL)
 int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
                      int numsocks)
@@ -546,7 +546,7 @@ int Curl_ssl_getsock(struct connectdata *conn,
   (void)numsocks;
   return GETSOCK_BLANK;
 }
-/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_DARWINSSL || USE_NSS */
+/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */
 #endif
 
 void Curl_ssl_close(struct connectdata *conn, int sockindex)
@@ -557,7 +557,7 @@ void Curl_ssl_close(struct connectdata *conn, int sockindex)
 
 CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
 {
-  if(Curl_ssl->shutdown(conn, sockindex))
+  if(Curl_ssl->shut_down(conn, sockindex))
     return CURLE_SSL_SHUTDOWN_FAILED;
 
   conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
@@ -644,11 +644,11 @@ bool Curl_ssl_data_pending(const struct connectdata *conn,
 
 void Curl_ssl_free_certinfo(struct Curl_easy *data)
 {
-  int i;
   struct curl_certinfo *ci = &data->info.certs;
 
   if(ci->num_of_certs) {
     /* free all individual lists used */
+    int i;
     for(i = 0; i<ci->num_of_certs; i++) {
       curl_slist_free_all(ci->certinfo[i]);
       ci->certinfo[i] = NULL;
@@ -700,7 +700,7 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
     return CURLE_OUT_OF_MEMORY;
 
   /* sprintf the label and colon */
-  snprintf(output, outlen, "%s:", label);
+  msnprintf(output, outlen, "%s:", label);
 
   /* memcpy the value (it might not be zero terminated) */
   memcpy(&output[labellen + 1], value, valuelen);
@@ -808,14 +808,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
 {
   FILE *fp;
   unsigned char *buf = NULL, *pem_ptr = NULL;
-  long filesize;
-  size_t size, pem_len;
-  CURLcode pem_read;
   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-  CURLcode encode;
-  size_t encodedlen, pinkeylen;
-  char *encoded, *pinkeycopy, *begin_pos, *end_pos;
-  unsigned char *sha256sumdigest = NULL;
 
   /* if a path wasn't specified, don't pin */
   if(!pinnedpubkey)
@@ -825,6 +818,11 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
 
   /* only do this if pinnedpubkey starts with "sha256//", length 8 */
   if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
+    CURLcode encode;
+    size_t encodedlen, pinkeylen;
+    char *encoded, *pinkeycopy, *begin_pos, *end_pos;
+    unsigned char *sha256sumdigest;
+
     if(!Curl_ssl->sha256sum) {
       /* without sha256 support, this cannot match */
       return result;
@@ -895,6 +893,10 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
     return result;
 
   do {
+    long filesize;
+    size_t size, pem_len;
+    CURLcode pem_read;
+
     /* Determine the file's size */
     if(fseek(fp, 0, SEEK_END))
       break;
@@ -1114,7 +1116,7 @@ static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex)
 {
   if(multissl_init(NULL))
     return CURLE_FAILED_INIT;
-  return Curl_ssl->connect(conn, sockindex);
+  return Curl_ssl->connect_blocking(conn, sockindex);
 }
 
 static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn,
@@ -1170,12 +1172,10 @@ static const struct Curl_ssl Curl_ssl_multi = {
 const struct Curl_ssl *Curl_ssl =
 #if defined(CURL_WITH_MULTI_SSL)
   &Curl_ssl_multi;
-#elif defined(USE_AXTLS)
-  &Curl_ssl_axtls;
 #elif defined(USE_CYASSL)
   &Curl_ssl_cyassl;
-#elif defined(USE_DARWINSSL)
-  &Curl_ssl_darwinssl;
+#elif defined(USE_SECTRANSP)
+  &Curl_ssl_sectransp;
 #elif defined(USE_GNUTLS)
   &Curl_ssl_gnutls;
 #elif defined(USE_GSKIT)
@@ -1197,14 +1197,11 @@ const struct Curl_ssl *Curl_ssl =
 #endif
 
 static const struct Curl_ssl *available_backends[] = {
-#if defined(USE_AXTLS)
-  &Curl_ssl_axtls,
-#endif
 #if defined(USE_CYASSL)
   &Curl_ssl_cyassl,
 #endif
-#if defined(USE_DARWINSSL)
-  &Curl_ssl_darwinssl,
+#if defined(USE_SECTRANSP)
+  &Curl_ssl_sectransp,
 #endif
 #if defined(USE_GNUTLS)
   &Curl_ssl_gnutls,
@@ -1244,16 +1241,17 @@ static size_t Curl_multissl_version(char *buffer, size_t size)
 
   if(current != selected) {
     char *p = backends;
+    char *end = backends + sizeof(backends);
     int i;
 
     selected = current;
 
-    for(i = 0; available_backends[i]; i++) {
+    for(i = 0; available_backends[i] && p < (end - 4); i++) {
       if(i)
         *(p++) = ' ';
       if(selected != available_backends[i])
         *(p++) = '(';
-      p += available_backends[i]->version(p, backends + sizeof(backends) - p);
+      p += available_backends[i]->version(p, end - p - 2);
       if(selected != available_backends[i])
         *(p++) = ')';
     }
@@ -1261,21 +1259,20 @@ static size_t Curl_multissl_version(char *buffer, size_t size)
     total = p - backends;
   }
 
-  if(size < total)
+  if(size > total)
     memcpy(buffer, backends, total + 1);
   else {
     memcpy(buffer, backends, size - 1);
     buffer[size - 1] = '\0';
   }
 
-  return total;
+  return CURLMIN(size - 1, total);
 }
 
 static int multissl_init(const struct Curl_ssl *backend)
 {
   const char *env;
   char *env_tmp;
-  int i;
 
   if(Curl_ssl != &Curl_ssl_multi)
     return 1;
@@ -1294,6 +1291,7 @@ static int multissl_init(const struct Curl_ssl *backend)
     env = CURL_DEFAULT_SSL_BACKEND;
 #endif
   if(env) {
+    int i;
     for(i = 0; available_backends[i]; i++) {
       if(strcasecompare(env, available_backends[i]->info.name)) {
         Curl_ssl = available_backends[i];
@@ -1318,7 +1316,14 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
     *avail = (const curl_ssl_backend **)&available_backends;
 
   if(Curl_ssl != &Curl_ssl_multi)
-    return id == Curl_ssl->info.id ? CURLSSLSET_OK : CURLSSLSET_TOO_LATE;
+    return id == Curl_ssl->info.id ||
+           (name && strcasecompare(name, Curl_ssl->info.name)) ?
+           CURLSSLSET_OK :
+#if defined(CURL_WITH_MULTI_SSL)
+           CURLSSLSET_TOO_LATE;
+#else
+           CURLSSLSET_UNKNOWN_BACKEND;
+#endif
 
   for(i = 0; available_backends[i]; i++) {
     if(available_backends[i]->info.id == id ||
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index 5cd1160..2a87ca1 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -47,7 +47,7 @@ struct Curl_ssl {
 
   size_t (*version)(char *buffer, size_t size);
   int (*check_cxn)(struct connectdata *cxn);
-  int (*shutdown)(struct connectdata *conn, int sockindex);
+  int (*shut_down)(struct connectdata *conn, int sockindex);
   bool (*data_pending)(const struct connectdata *conn,
                        int connindex);
 
@@ -56,7 +56,7 @@ struct Curl_ssl {
                      size_t length);
   bool (*cert_status_request)(void);
 
-  CURLcode (*connect)(struct connectdata *conn, int sockindex);
+  CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex);
   CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex,
                                   bool *done);
   void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
@@ -103,10 +103,9 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
 #include "nssg.h"           /* NSS versions */
 #include "gskit.h"          /* Global Secure ToolKit versions */
 #include "polarssl.h"       /* PolarSSL versions */
-#include "axtls.h"          /* axTLS versions */
 #include "cyassl.h"         /* CyaSSL versions */
 #include "schannel.h"       /* Schannel SSPI version */
-#include "darwinssl.h"      /* SecureTransport (Darwin) version */
+#include "sectransp.h"      /* SecureTransport (Darwin) version */
 #include "mbedtls.h"        /* mbedTLS versions */
 #include "mesalink.h"       /* MesaLink versions */
 
diff --git a/lib/warnless.c b/lib/warnless.c
index 05d9038..cfd5e8e 100644
--- a/lib/warnless.c
+++ b/lib/warnless.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -401,44 +401,6 @@ unsigned short curlx_uitous(unsigned int uinum)
 }
 
 /*
-** unsigned int to unsigned char
-*/
-
-unsigned char curlx_uitouc(unsigned int uinum)
-{
-#ifdef __INTEL_COMPILER
-#  pragma warning(push)
-#  pragma warning(disable:810) /* conversion may lose significant bits */
-#endif
-
-  DEBUGASSERT(uinum <= (unsigned int) CURL_MASK_UCHAR);
-  return (unsigned char) (uinum & (unsigned int) CURL_MASK_UCHAR);
-
-#ifdef __INTEL_COMPILER
-#  pragma warning(pop)
-#endif
-}
-
-/*
-** unsigned int to signed int
-*/
-
-int curlx_uitosi(unsigned int uinum)
-{
-#ifdef __INTEL_COMPILER
-#  pragma warning(push)
-#  pragma warning(disable:810) /* conversion may lose significant bits */
-#endif
-
-  DEBUGASSERT(uinum <= (unsigned int) CURL_MASK_SINT);
-  return (int) (uinum & (unsigned int) CURL_MASK_SINT);
-
-#ifdef __INTEL_COMPILER
-#  pragma warning(pop)
-#endif
-}
-
-/*
 ** signed int to unsigned size_t
 */
 
diff --git a/lib/warnless.h b/lib/warnless.h
index 284ea1e..ea4c439 100644
--- a/lib/warnless.h
+++ b/lib/warnless.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -57,10 +57,6 @@ int curlx_sztosi(ssize_t sznum);
 
 unsigned short curlx_uitous(unsigned int uinum);
 
-unsigned char curlx_uitouc(unsigned int uinum);
-
-int curlx_uitosi(unsigned int uinum);
-
 size_t curlx_sitouz(int sinum);
 
 #ifdef USE_WINSOCK
diff --git a/lib/wildcard.c b/lib/wildcard.c
index 8ba0989..e94d3c5 100644
--- a/lib/wildcard.c
+++ b/lib/wildcard.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,8 @@
 
 #include "curl_setup.h"
 
+#ifndef CURL_DISABLE_FTP
+
 #include "wildcard.h"
 #include "llist.h"
 #include "fileinfo.h"
@@ -67,3 +69,5 @@ void Curl_wildcard_dtor(struct WildcardData *wc)
   wc->customptr = NULL;
   wc->state = CURLWC_INIT;
 }
+
+#endif /* if disabled */
diff --git a/lib/wildcard.h b/lib/wildcard.h
index b782612..306c8c9 100644
--- a/lib/wildcard.h
+++ b/lib/wildcard.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2010 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,8 +22,9 @@
  *
  ***************************************************************************/
 
-#include <curl/curl.h>
+#include "curl_setup.h"
 
+#ifndef CURL_DISABLE_FTP
 #include "llist.h"
 
 /* list of wildcard process states */
@@ -58,4 +59,9 @@ void Curl_wildcard_dtor(struct WildcardData *wc);
 
 struct Curl_easy;
 
+#else
+/* FTP is disabled */
+#define Curl_wildcard_dtor(x)
+#endif
+
 #endif /* HEADER_CURL_WILDCARD_H */
diff --git a/lib/x509asn1.c b/lib/x509asn1.c
index a576fc7..0c1256b 100644
--- a/lib/x509asn1.c
+++ b/lib/x509asn1.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -120,7 +120,7 @@ static const char *getASN1Element(curl_asn1Element *elem,
      if an error occurs. */
   if(!beg || !end || beg >= end || !*beg ||
      (size_t)(end - beg) > CURL_ASN1_MAX)
-    return (const char *) NULL;
+    return NULL;
 
   /* Process header byte. */
   elem->header = beg;
@@ -129,12 +129,12 @@ static const char *getASN1Element(curl_asn1Element *elem,
   elem->class = (b >> 6) & 3;
   b &= 0x1F;
   if(b == 0x1F)
-    return (const char *) NULL; /* Long tag values not supported here. */
+    return NULL; /* Long tag values not supported here. */
   elem->tag = b;
 
   /* Process length. */
   if(beg >= end)
-    return (const char *) NULL;
+    return NULL;
   b = (unsigned char) *beg++;
   if(!(b & 0x80))
     len = b;
@@ -142,74 +142,77 @@ static const char *getASN1Element(curl_asn1Element *elem,
     /* Unspecified length. Since we have all the data, we can determine the
        effective length by skipping element until an end element is found. */
     if(!elem->constructed)
-      return (const char *) NULL;
+      return NULL;
     elem->beg = beg;
     while(beg < end && *beg) {
       beg = getASN1Element(&lelem, beg, end);
       if(!beg)
-        return (const char *) NULL;
+        return NULL;
     }
     if(beg >= end)
-      return (const char *) NULL;
+      return NULL;
     elem->end = beg;
     return beg + 1;
   }
   else if((unsigned)b > (size_t)(end - beg))
-    return (const char *) NULL; /* Does not fit in source. */
+    return NULL; /* Does not fit in source. */
   else {
     /* Get long length. */
     len = 0;
     do {
       if(len & 0xFF000000L)
-        return (const char *) NULL;  /* Lengths > 32 bits are not supported. */
+        return NULL;  /* Lengths > 32 bits are not supported. */
       len = (len << 8) | (unsigned char) *beg++;
     } while(--b);
   }
   if(len > (size_t)(end - beg))
-    return (const char *) NULL;  /* Element data does not fit in source. */
+    return NULL;  /* Element data does not fit in source. */
   elem->beg = beg;
   elem->end = beg + len;
   return elem->end;
 }
 
+/*
+ * Search the null terminated OID or OID identifier in local table.
+ * Return the table entry pointer or NULL if not found.
+ */
 static const curl_OID * searchOID(const char *oid)
 {
   const curl_OID *op;
-
-  /* Search the null terminated OID or OID identifier in local table.
-     Return the table entry pointer or NULL if not found. */
-
   for(op = OIDtable; op->numoid; op++)
     if(!strcmp(op->numoid, oid) || strcasecompare(op->textoid, oid))
       return op;
 
-  return (const curl_OID *) NULL;
+  return NULL;
 }
 
+/*
+ * Convert an ASN.1 Boolean value into its string representation.  Return the
+ * dynamically allocated string, or NULL if source is not an ASN.1 Boolean
+ * value.
+ */
+
 static const char *bool2str(const char *beg, const char *end)
 {
-  /* Convert an ASN.1 Boolean value into its string representation.
-     Return the dynamically allocated string, or NULL if source is not an
-     ASN.1 Boolean value. */
-
   if(end - beg != 1)
-    return (const char *) NULL;
+    return NULL;
   return strdup(*beg? "TRUE": "FALSE");
 }
 
+/*
+ * Convert an ASN.1 octet string to a printable string.
+ * Return the dynamically allocated string, or NULL if an error occurs.
+ */
 static const char *octet2str(const char *beg, const char *end)
 {
   size_t n = end - beg;
   char *buf = NULL;
 
-  /* Convert an ASN.1 octet string to a printable string.
-     Return the dynamically allocated string, or NULL if an error occurs. */
-
   if(n <= (SIZE_T_MAX - 1) / 3) {
     buf = malloc(3 * n + 1);
     if(buf)
       for(n = 0; beg < end; n += 3)
-        snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
+        msnprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
   }
   return buf;
 }
@@ -220,21 +223,22 @@ static const char *bit2str(const char *beg, const char *end)
      Return the dynamically allocated string, or NULL if an error occurs. */
 
   if(++beg > end)
-    return (const char *) NULL;
+    return NULL;
   return octet2str(beg, end);
 }
 
+/*
+ * Convert an ASN.1 integer value into its string representation.
+ * Return the dynamically allocated string, or NULL if source is not an
+ * ASN.1 integer value.
+ */
 static const char *int2str(const char *beg, const char *end)
 {
   unsigned long val = 0;
   size_t n = end - beg;
 
-  /* Convert an ASN.1 integer value into its string representation.
-     Return the dynamically allocated string, or NULL if source is not an
-     ASN.1 integer value. */
-
   if(!n)
-    return (const char *) NULL;
+    return NULL;
 
   if(n > 4)
     return octet2str(beg, end);
@@ -249,23 +253,22 @@ static const char *int2str(const char *beg, const char *end)
   return curl_maprintf("%s%lx", val >= 10? "0x": "", val);
 }
 
+/*
+ * Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the
+ * destination buffer dynamically. The allocation size will normally be too
+ * large: this is to avoid buffer overflows.
+ * Terminate the string with a nul byte and return the converted
+ * string length.
+ */
 static ssize_t
 utf8asn1str(char **to, int type, const char *from, const char *end)
 {
   size_t inlength = end - from;
   int size = 1;
   size_t outlength;
-  int charsize;
-  unsigned int wc;
   char *buf;
 
-  /* Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the
-     destination buffer dynamically. The allocation size will normally be too
-     large: this is to avoid buffer overflows.
-     Terminate the string with a nul byte and return the converted
-     string length. */
-
-  *to = (char *) NULL;
+  *to = NULL;
   switch(type) {
   case CURL_ASN1_BMP_STRING:
     size = 2;
@@ -300,6 +303,9 @@ utf8asn1str(char **to, int type, const char *from, const char *end)
   }
   else {
     for(outlength = 0; from < end;) {
+      int charsize;
+      unsigned int wc;
+
       wc = 0;
       switch(size) {
       case 4:
@@ -341,96 +347,105 @@ utf8asn1str(char **to, int type, const char *from, const char *end)
   return outlength;
 }
 
+/*
+ * Convert an ASN.1 String into its UTF-8 string representation.
+ * Return the dynamically allocated string, or NULL if an error occurs.
+ */
 static const char *string2str(int type, const char *beg, const char *end)
 {
   char *buf;
-
-  /* Convert an ASN.1 String into its UTF-8 string representation.
-     Return the dynamically allocated string, or NULL if an error occurs. */
-
   if(utf8asn1str(&buf, type, beg, end) < 0)
-    return (const char *) NULL;
+    return NULL;
   return buf;
 }
 
-static int encodeUint(char *buf, int n, unsigned int x)
+/*
+ * Decimal ASCII encode unsigned integer `x' into the buflen sized buffer at
+ * buf.  Return the total number of encoded digits, even if larger than
+ * `buflen'.
+ */
+static size_t encodeUint(char *buf, size_t buflen, unsigned int x)
 {
-  int i = 0;
+  size_t i = 0;
   unsigned int y = x / 10;
 
-  /* Decimal ASCII encode unsigned integer `x' in the `n'-byte buffer at `buf'.
-     Return the total number of encoded digits, even if larger than `n'. */
-
   if(y) {
-    i += encodeUint(buf, n, y);
+    i = encodeUint(buf, buflen, y);
     x -= y * 10;
   }
-  if(i < n)
+  if(i < buflen)
     buf[i] = (char) ('0' + x);
   i++;
-  if(i < n)
+  if(i < buflen)
     buf[i] = '\0';      /* Store a terminator if possible. */
   return i;
 }
 
-static int encodeOID(char *buf, int n, const char *beg, const char *end)
+/*
+ * Convert an ASN.1 OID into its dotted string representation.
+ * Store the result in th `n'-byte buffer at `buf'.
+ * Return the converted string length, or 0 on errors.
+ */
+static size_t encodeOID(char *buf, size_t buflen,
+                        const char *beg, const char *end)
 {
-  int i = 0;
+  size_t i;
   unsigned int x;
   unsigned int y;
 
-  /* Convert an ASN.1 OID into its dotted string representation.
-     Store the result in th `n'-byte buffer at `buf'.
-     Return the converted string length, or -1 if an error occurs. */
-
   /* Process the first two numbers. */
   y = *(const unsigned char *) beg++;
   x = y / 40;
   y -= x * 40;
-  i += encodeUint(buf + i, n - i, x);
-  if(i < n)
+  i = encodeUint(buf, buflen, x);
+  if(i < buflen)
     buf[i] = '.';
   i++;
-  i += encodeUint(buf + i, n - i, y);
+  if(i >= buflen)
+    i += encodeUint(NULL, 0, y);
+  else
+    i += encodeUint(buf + i, buflen - i, y);
 
   /* Process the trailing numbers. */
   while(beg < end) {
-    if(i < n)
+    if(i < buflen)
       buf[i] = '.';
     i++;
     x = 0;
     do {
       if(x & 0xFF000000)
-        return -1;
+        return 0;
       y = *(const unsigned char *) beg++;
       x = (x << 7) | (y & 0x7F);
     } while(y & 0x80);
-    i += encodeUint(buf + i, n - i, x);
+    if(i >= buflen)
+      i += encodeUint(NULL, 0, x);
+    else
+      i += encodeUint(buf + i, buflen - i, x);
   }
-  if(i < n)
+  if(i < buflen)
     buf[i] = '\0';
   return i;
 }
 
+/*
+ * Convert an ASN.1 OID into its dotted or symbolic string representation.
+ * Return the dynamically allocated string, or NULL if an error occurs.
+ */
+
 static const char *OID2str(const char *beg, const char *end, bool symbolic)
 {
-  char *buf = (char *) NULL;
-  const curl_OID * op;
-  int n;
-
-  /* Convert an ASN.1 OID into its dotted or symbolic string representation.
-     Return the dynamically allocated string, or NULL if an error occurs. */
-
+  char *buf = NULL;
   if(beg < end) {
-    n = encodeOID((char *) NULL, -1, beg, end);
-    if(n >= 0) {
-      buf = malloc(n + 1);
+    size_t buflen = encodeOID(NULL, 0, beg, end);
+    if(buflen) {
+      buf = malloc(buflen + 1); /* one extra for the zero byte */
       if(buf) {
-        encodeOID(buf, n, beg, end);
-        buf[n] = '\0';
+        encodeOID(buf, buflen, beg, end);
+        buf[buflen] = '\0';
 
         if(symbolic) {
-          op = searchOID(buf);
+          const curl_OID *op = searchOID(buf);
           if(op) {
             free(buf);
             buf = strdup(op->textoid);
@@ -470,7 +485,7 @@ static const char *GTime2str(const char *beg, const char *end)
     sec2 = fracp[-1];
     break;
   default:
-    return (const char *) NULL;
+    return NULL;
   }
 
   /* Scan for timezone, measure fractional seconds. */
@@ -506,15 +521,16 @@ static const char *GTime2str(const char *beg, const char *end)
                        sep, tzl, tzp);
 }
 
+/*
+ *  Convert an ASN.1 UTC time to a printable string.
+ * Return the dynamically allocated string, or NULL if an error occurs.
+ */
 static const char *UTime2str(const char *beg, const char *end)
 {
   const char *tzp;
   size_t tzl;
   const char *sec;
 
-  /* Convert an ASN.1 UTC time to a printable string.
-     Return the dynamically allocated string, or NULL if an error occurs. */
-
   for(tzp = beg; tzp < end && *tzp >= '0' && *tzp <= '9'; tzp++)
     ;
   /* Get the seconds. */
@@ -525,12 +541,12 @@ static const char *UTime2str(const char *beg, const char *end)
   case 2:
     break;
   default:
-    return (const char *) NULL;
+    return NULL;
   }
 
   /* Process timezone. */
   if(tzp >= end)
-    return (const char *) NULL;
+    return NULL;
   if(*tzp == 'Z') {
     tzp = "GMT";
     end = tzp + 3;
@@ -545,13 +561,14 @@ static const char *UTime2str(const char *beg, const char *end)
                        tzl, tzp);
 }
 
+/*
+ * Convert an ASN.1 element to a printable string.
+ * Return the dynamically allocated string, or NULL if an error occurs.
+ */
 static const char *ASN1tostr(curl_asn1Element *elem, int type)
 {
-  /* Convert an ASN.1 element to a printable string.
-     Return the dynamically allocated string, or NULL if an error occurs. */
-
   if(elem->constructed)
-    return (const char *) NULL; /* No conversion of structured elements. */
+    return NULL; /* No conversion of structured elements. */
 
   if(!type)
     type = elem->tag;   /* Type not forced: use element tag as type. */
@@ -585,10 +602,14 @@ static const char *ASN1tostr(curl_asn1Element *elem, int type)
     return string2str(type, elem->beg, elem->end);
   }
 
-  return (const char *) NULL;   /* Unsupported. */
+  return NULL;   /* Unsupported. */
 }
 
-static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
+/*
+ * ASCII encode distinguished name at `dn' into the `buflen'-sized buffer at
+ * `buf'.  Return the total string length, even if larger than `buflen'.
+ */
+static ssize_t encodeDN(char *buf, size_t buflen, curl_asn1Element *dn)
 {
   curl_asn1Element rdn;
   curl_asn1Element atv;
@@ -600,9 +621,6 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
   const char *p3;
   const char *str;
 
-  /* ASCII encode distinguished name at `dn' into the `n'-byte buffer at `buf'.
-     Return the total string length, even if larger than `n'. */
-
   for(p1 = dn->beg; p1 < dn->end;) {
     p1 = getASN1Element(&rdn, p1, dn->end);
     if(!p1)
@@ -626,7 +644,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
         for(p3 = str; isupper(*p3); p3++)
           ;
         for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) {
-          if(l < n)
+          if(l < buflen)
             buf[l] = *p3;
           l++;
         }
@@ -634,14 +652,14 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
 
       /* Encode attribute name. */
       for(p3 = str; *p3; p3++) {
-        if(l < n)
+        if(l < buflen)
           buf[l] = *p3;
         l++;
       }
       free((char *) str);
 
       /* Generate equal sign. */
-      if(l < n)
+      if(l < buflen)
         buf[l] = '=';
       l++;
 
@@ -650,7 +668,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
       if(!str)
         return -1;
       for(p3 = str; *p3; p3++) {
-        if(l < n)
+        if(l < buflen)
           buf[l] = *p3;
         l++;
       }
@@ -661,28 +679,30 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
   return l;
 }
 
+/*
+ * Convert an ASN.1 distinguished name into a printable string.
+ * Return the dynamically allocated string, or NULL if an error occurs.
+ */
 static const char *DNtostr(curl_asn1Element *dn)
 {
-  char *buf = (char *) NULL;
-  ssize_t n = encodeDN(buf, 0, dn);
-
-  /* Convert an ASN.1 distinguished name into a printable string.
-     Return the dynamically allocated string, or NULL if an error occurs. */
+  char *buf = NULL;
+  ssize_t buflen = encodeDN(NULL, 0, dn);
 
-  if(n >= 0) {
-    buf = malloc(n + 1);
+  if(buflen >= 0) {
+    buf = malloc(buflen + 1);
     if(buf) {
-      encodeDN(buf, n + 1, dn);
-      buf[n] = '\0';
+      encodeDN(buf, buflen + 1, dn);
+      buf[buflen] = '\0';
     }
   }
-  return (const char *) buf;
+  return buf;
 }
 
 /*
- * X509 parser.
+ * ASN.1 parse an X509 certificate into structure subfields.
+ * Syntax is assumed to have already been checked by the SSL backend.
+ * See RFC 5280.
  */
-
 int Curl_parseX509(curl_X509certificate *cert,
                    const char *beg, const char *end)
 {
@@ -691,10 +711,6 @@ int Curl_parseX509(curl_X509certificate *cert,
   const char *ccp;
   static const char defaultVersion = 0;  /* v1. */
 
-  /* ASN.1 parse an X509 certificate into structure subfields.
-     Syntax is assumed to have already been checked by the SSL backend.
-     See RFC 5280. */
-
   cert->certificate.header = NULL;
   cert->certificate.beg = beg;
   cert->certificate.end = end;
@@ -801,13 +817,14 @@ int Curl_parseX509(curl_X509certificate *cert,
   return 0;
 }
 
+
+/*
+ * Copy at most 64-characters, terminate with a newline and returns the
+ * effective number of stored characters.
+ */
 static size_t copySubstring(char *to, const char *from)
 {
   size_t i;
-
-  /* Copy at most 64-characters, terminate with a newline and returns the
-     effective number of stored characters. */
-
   for(i = 0; i < 64; i++) {
     to[i] = *from;
     if(!*from++)
@@ -861,9 +878,6 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
   curl_asn1Element elem;
   curl_asn1Element pk;
   const char *p;
-  const char *q;
-  unsigned long len;
-  unsigned int i;
 
   /* Generate all information records for the public key. */
 
@@ -872,6 +886,9 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
     return;
 
   if(strcasecompare(algo, "rsaEncryption")) {
+    const char *q;
+    unsigned long len;
+
     p = getASN1Element(&elem, pk.beg, pk.end);
     if(!p)
       return;
@@ -880,9 +897,11 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
     for(q = elem.beg; !*q && q < elem.end; q++)
       ;
     len = (unsigned long)((elem.end - q) * 8);
-    if(len)
+    if(len) {
+      unsigned int i;
       for(i = *(unsigned char *) q; !(i & 0x80); i <<= 1)
         len--;
+    }
     if(len > 32)
       elem.beg = q;     /* Strip leading zero bytes. */
     if(!certnum)
@@ -1040,8 +1059,6 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
   do_pubkey(data, certnum, ccp, &param, &cert.subjectPublicKey);
   free((char *) ccp);
 
-/* TODO: extensions. */
-
   /* Signature. */
   ccp = ASN1tostr(&cert.signature, 0);
   if(!ccp)
@@ -1104,15 +1121,15 @@ static const char *checkOID(const char *beg, const char *end,
 
   ccp = getASN1Element(&e, beg, end);
   if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
-    return (const char *) NULL;
+    return NULL;
 
   p = OID2str(e.beg, e.end, FALSE);
   if(!p)
-    return (const char *) NULL;
+    return NULL;
 
   matched = !strcmp(p, oid);
   free((char *) p);
-  return matched? ccp: (const char *) NULL;
+  return matched? ccp: NULL;
 }
 
 CURLcode Curl_verifyhost(struct connectdata *conn,

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2de8af0121c3ca64dcb82a1220d2ba255aab3553
commit 2de8af0121c3ca64dcb82a1220d2ba255aab3553
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed May 22 14:11:29 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed May 22 14:11:29 2019 -0400

    curl: Update script to get curl 7.65.0

diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index fb46052..5c2a331 100755
--- a/Utilities/Scripts/update-curl.bash
+++ b/Utilities/Scripts/update-curl.bash
@@ -8,7 +8,7 @@ readonly name="curl"
 readonly ownership="Curl Upstream <curl-library at cool.haxx.se>"
 readonly subtree="Utilities/cmcurl"
 readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_62_0"
+readonly tag="curl-7_65_0"
 readonly shortlog=false
 readonly paths="
   CMake/*

-----------------------------------------------------------------------

Summary of changes:
 Help/variable/CMAKE_JOB_POOL_LINK.rst              |   2 +-
 Modules/Compiler/ARMClang.cmake                    |   8 +-
 Source/CTest/cmCTestBZR.cxx                        |   3 +-
 Source/CTest/cmCTestBuildHandler.cxx               |   3 +-
 Source/CTest/cmCTestCoverageHandler.cxx            |  16 +-
 Source/CTest/cmCTestCurl.cxx                       |   9 +-
 Source/CTest/cmCTestHG.cxx                         |   3 +-
 Source/CTest/cmCTestMultiProcessHandler.cxx        |  16 +-
 Source/CTest/cmCTestP4.cxx                         |   5 +-
 Source/CTest/cmCTestSVN.cxx                        |   7 +-
 Source/CTest/cmCTestSubmitHandler.cxx              |  21 +-
 Source/CTest/cmProcess.cxx                         |   3 +-
 Source/cmAddLibraryCommand.cxx                     |   3 +-
 Source/cmAddTestCommand.cxx                        |   3 +-
 Source/cmAlgorithms.h                              |  12 +
 Source/cmCTest.cxx                                 |   9 +-
 Source/cmConditionEvaluator.cxx                    |   7 +-
 Source/cmCustomCommand.cxx                         |   9 +-
 Source/cmCustomCommandGenerator.cxx                |  12 +-
 Source/cmDocumentationSection.h                    |   3 +-
 Source/cmELF.cxx                                   |   3 +-
 Source/cmExecuteProcessCommand.cxx                 |   2 +-
 Source/cmExportBuildFileGenerator.h                |   3 +-
 Source/cmExportLibraryDependenciesCommand.cxx      |   3 +-
 Source/cmExtraCodeBlocksGenerator.cxx              |  25 +-
 Source/cmFileAPICodemodel.cxx                      |   4 +-
 Source/cmFileCommand.cxx                           |  15 +-
 Source/cmFindBase.cxx                              |   3 +-
 Source/cmFindCommon.cxx                            |   3 +-
 Source/cmFunctionCommand.cxx                       |   2 +-
 Source/cmGeneratorExpressionParser.cxx             |   5 +-
 Source/cmGlobalGenerator.h                         |   2 +-
 Source/cmGlobalJOMMakefileGenerator.cxx            |   3 +-
 Source/cmGlobalNMakeMakefileGenerator.cxx          |   3 +-
 Source/cmGlobalNinjaGenerator.cxx                  |   5 +-
 Source/cmGlobalUnixMakefileGenerator3.cxx          |   5 +-
 Source/cmGlobalVisualStudio8Generator.cxx          |   6 +-
 Source/cmGlobalXCodeGenerator.cxx                  |   3 +-
 Source/cmIDEOptions.cxx                            |   6 +-
 Source/cmIncludeDirectoryCommand.cxx               |   7 +-
 Source/cmInstallFilesCommand.cxx                   |   4 +-
 Source/cmInstallProgramsCommand.cxx                |   3 +-
 Source/cmInstallTargetsCommand.cxx                 |   4 +-
 Source/cmJsonObjects.cxx                           |   4 +-
 Source/cmLocalGenerator.cxx                        |  13 +-
 Source/cmLocalUnixMakefileGenerator3.cxx           |   4 +-
 Source/cmMacroCommand.cxx                          |   2 +-
 Source/cmMakefile.cxx                              |  11 +-
 Source/cmMakefile.h                                |  17 +-
 Source/cmMakefileExecutableTargetGenerator.cxx     |   6 +-
 Source/cmMakefileLibraryTargetGenerator.cxx        |   8 +-
 Source/cmMakefileTargetGenerator.cxx               |  32 +-
 Source/cmNinjaTargetGenerator.cxx                  |   3 +-
 Source/cmOrderDirectories.cxx                      |   6 +-
 Source/cmOutputRequiredFilesCommand.cxx            |   3 +-
 Source/cmQtAutoGen.cxx                             |   5 +-
 Source/cmQtAutoMocUic.cxx                          |  15 +-
 Source/cmQtAutoRcc.cxx                             |   2 +-
 Source/cmSetTargetPropertiesCommand.cxx            |   3 +-
 Source/cmSetTestsPropertiesCommand.cxx             |   3 +-
 Source/cmStateDirectory.cxx                        |   4 +-
 Source/cmSystemTools.cxx                           |  14 +-
 Source/cmTarget.cxx                                |  38 +-
 Source/cmTarget.h                                  |   3 -
 Source/cmake.cxx                                   |   5 +-
 Source/cmakemain.cxx                               |   2 +-
 Source/cmcmd.cxx                                   |  11 +-
 Utilities/Scripts/update-curl.bash                 |   2 +-
 Utilities/cmcurl/CMake/CurlTests.c                 |  52 +-
 Utilities/cmcurl/CMake/FindGSS.cmake               |   4 +-
 Utilities/cmcurl/CMake/OtherTests.cmake            |  67 +-
 Utilities/cmcurl/CMakeLists.txt                    |  73 +-
 Utilities/cmcurl/COPYING                           |   2 +-
 Utilities/cmcurl/include/curl/curl.h               |  66 +-
 Utilities/cmcurl/include/curl/curlver.h            |  12 +-
 Utilities/cmcurl/include/curl/typecheck-gcc.h      |  14 +-
 Utilities/cmcurl/include/curl/urlapi.h             |   7 +-
 Utilities/cmcurl/lib/Makefile.inc                  |  19 +-
 Utilities/cmcurl/lib/altsvc.c                      | 569 ++++++++++++
 Utilities/cmcurl/lib/altsvc.h                      |  77 ++
 Utilities/cmcurl/lib/amigaos.c                     |  32 +-
 Utilities/cmcurl/lib/amigaos.h                     |  10 +-
 Utilities/cmcurl/lib/asyn-ares.c                   | 157 +++-
 Utilities/cmcurl/lib/asyn-thread.c                 |  70 +-
 Utilities/cmcurl/lib/asyn.h                        |  36 +-
 Utilities/cmcurl/lib/base64.c                      |  33 +-
 Utilities/cmcurl/lib/conncache.c                   |  38 +-
 Utilities/cmcurl/lib/conncache.h                   |   8 +-
 Utilities/cmcurl/lib/connect.c                     | 114 ++-
 Utilities/cmcurl/lib/connect.h                     |   9 +-
 Utilities/cmcurl/lib/cookie.c                      | 202 +++--
 Utilities/cmcurl/lib/cookie.h                      |  13 +-
 Utilities/cmcurl/lib/curl_addrinfo.c               |  32 +-
 Utilities/cmcurl/lib/curl_addrinfo.h               |  13 +-
 Utilities/cmcurl/lib/curl_config.h.cmake           |  10 +-
 Utilities/cmcurl/lib/curl_endian.c                 |  10 +-
 Utilities/cmcurl/lib/curl_fnmatch.c                |  15 +-
 .../cmcurl/lib/{curl_memrchr.c => curl_get_line.c} |  49 +-
 Utilities/cmcurl/lib/{dict.h => curl_get_line.h}   |  14 +-
 Utilities/cmcurl/lib/curl_gssapi.c                 |   6 +-
 Utilities/cmcurl/lib/curl_gssapi.h                 |  16 +-
 Utilities/cmcurl/lib/curl_md4.h                    |   4 +-
 Utilities/cmcurl/lib/curl_md5.h                    |  10 +-
 Utilities/cmcurl/lib/curl_memory.h                 |   4 +-
 Utilities/cmcurl/lib/curl_multibyte.c              |  12 +-
 Utilities/cmcurl/lib/curl_ntlm_core.c              |  69 +-
 Utilities/cmcurl/lib/curl_ntlm_core.h              |   4 +-
 Utilities/cmcurl/lib/curl_ntlm_wb.c                |  86 +-
 Utilities/cmcurl/lib/curl_ntlm_wb.h                |  11 +-
 Utilities/cmcurl/lib/curl_path.c                   |   6 +-
 Utilities/cmcurl/lib/curl_printf.h                 |  16 +-
 Utilities/cmcurl/lib/curl_rtmp.c                   |   9 +-
 Utilities/cmcurl/lib/curl_sasl.c                   |  40 +-
 Utilities/cmcurl/lib/curl_setup.h                  |  29 +-
 Utilities/cmcurl/lib/curlx.h                       |  11 +-
 Utilities/cmcurl/lib/dict.c                        |  11 +-
 Utilities/cmcurl/lib/doh.c                         | 127 ++-
 Utilities/cmcurl/lib/doh.h                         |  10 +-
 Utilities/cmcurl/lib/easy.c                        | 111 +--
 Utilities/cmcurl/lib/escape.c                      |   2 +-
 Utilities/cmcurl/lib/file.c                        |  29 +-
 Utilities/cmcurl/lib/fileinfo.c                    |   5 +-
 Utilities/cmcurl/lib/formdata.c                    |  14 +-
 Utilities/cmcurl/lib/formdata.h                    |  11 +-
 Utilities/cmcurl/lib/ftp.c                         | 103 +--
 Utilities/cmcurl/lib/ftp.h                         |   3 +-
 Utilities/cmcurl/lib/ftplistparser.c               |   7 +-
 Utilities/cmcurl/lib/getinfo.c                     |   8 +-
 Utilities/cmcurl/lib/gopher.c                      |  28 +-
 Utilities/cmcurl/lib/hostasyn.c                    |   8 +-
 Utilities/cmcurl/lib/hostcheck.c                   |  11 +-
 Utilities/cmcurl/lib/hostip.c                      | 153 ++--
 Utilities/cmcurl/lib/hostip.h                      |  19 +-
 Utilities/cmcurl/lib/hostip4.c                     |   4 +-
 Utilities/cmcurl/lib/hostip6.c                     |  14 +-
 Utilities/cmcurl/lib/http.c                        | 492 +++++++----
 Utilities/cmcurl/lib/http.h                        |   9 +-
 Utilities/cmcurl/lib/http2.c                       |  76 +-
 Utilities/cmcurl/lib/http2.h                       |   7 +-
 Utilities/cmcurl/lib/http_digest.c                 |   5 +-
 Utilities/cmcurl/lib/http_digest.h                 |  12 +-
 Utilities/cmcurl/lib/http_negotiate.c              | 132 ++-
 Utilities/cmcurl/lib/http_negotiate.h              |   8 +-
 Utilities/cmcurl/lib/http_ntlm.c                   |  40 +-
 Utilities/cmcurl/lib/http_ntlm.h                   |  10 +-
 Utilities/cmcurl/lib/http_proxy.c                  |   4 +-
 Utilities/cmcurl/lib/if2ip.c                       |  59 +-
 Utilities/cmcurl/lib/if2ip.h                       |   6 +-
 Utilities/cmcurl/lib/imap.c                        |  41 +-
 Utilities/cmcurl/lib/inet_ntop.c                   |  12 +-
 Utilities/cmcurl/lib/inet_pton.c                   |   3 +-
 Utilities/cmcurl/lib/ldap.c                        |  22 +-
 Utilities/cmcurl/lib/libcurl.rc                    |  12 +-
 Utilities/cmcurl/lib/md4.c                         | 114 +--
 Utilities/cmcurl/lib/md5.c                         | 174 ++--
 Utilities/cmcurl/lib/memdebug.c                    | 154 ++--
 Utilities/cmcurl/lib/memdebug.h                    | 123 ++-
 Utilities/cmcurl/lib/mime.c                        |  94 +-
 Utilities/cmcurl/lib/mime.h                        |  27 +-
 Utilities/cmcurl/lib/mprintf.c                     |   2 +-
 Utilities/cmcurl/lib/multi.c                       | 916 +++++++++----------
 Utilities/cmcurl/lib/multihandle.h                 |  48 +-
 Utilities/cmcurl/lib/multiif.h                     |  33 +-
 Utilities/cmcurl/lib/netrc.c                       |  16 +-
 Utilities/cmcurl/lib/netrc.h                       |  11 +-
 Utilities/cmcurl/lib/non-ascii.c                   |   4 +-
 Utilities/cmcurl/lib/openldap.c                    |  13 +-
 Utilities/cmcurl/lib/parsedate.c                   |  41 +-
 Utilities/cmcurl/lib/pingpong.c                    |   9 +-
 Utilities/cmcurl/lib/pingpong.h                    |   7 +-
 Utilities/cmcurl/lib/pipeline.c                    | 404 ---------
 Utilities/cmcurl/lib/pipeline.h                    |  56 --
 Utilities/cmcurl/lib/pop3.c                        |  32 +-
 Utilities/cmcurl/lib/progress.c                    | 150 ++--
 Utilities/cmcurl/lib/rand.h                        |   7 +-
 Utilities/cmcurl/lib/rtsp.c                        |  35 +-
 Utilities/cmcurl/lib/security.c                    |  19 +-
 Utilities/cmcurl/lib/sendf.c                       |  63 +-
 Utilities/cmcurl/lib/setopt.c                      | 358 +++++---
 Utilities/cmcurl/lib/sigpipe.h                     |   5 +-
 Utilities/cmcurl/lib/smb.c                         |   9 +-
 Utilities/cmcurl/lib/smtp.c                        |  33 +-
 Utilities/cmcurl/lib/socks.c                       |  26 +-
 Utilities/cmcurl/lib/socks_gssapi.c                |   6 +-
 Utilities/cmcurl/lib/socks_sspi.c                  |  11 +-
 Utilities/cmcurl/lib/splay.c                       |   4 +-
 Utilities/cmcurl/lib/ssh-libssh.c                  |  90 +-
 Utilities/cmcurl/lib/ssh.c                         |  92 +-
 Utilities/cmcurl/lib/strerror.c                    |  44 +-
 Utilities/cmcurl/lib/strerror.h                    |  11 +-
 Utilities/cmcurl/lib/system_win32.c                |  82 ++
 Utilities/cmcurl/lib/system_win32.h                |   6 +
 Utilities/cmcurl/lib/telnet.c                      |  34 +-
 Utilities/cmcurl/lib/tftp.c                        |  46 +-
 Utilities/cmcurl/lib/timeval.c                     |  46 +-
 Utilities/cmcurl/lib/timeval.h                     |   4 +-
 Utilities/cmcurl/lib/transfer.c                    | 361 +++++---
 Utilities/cmcurl/lib/transfer.h                    |  20 +-
 Utilities/cmcurl/lib/url.c                         | 969 +++++++++------------
 Utilities/cmcurl/lib/url.h                         |  14 +-
 Utilities/cmcurl/lib/urlapi-int.h                  |  12 +-
 Utilities/cmcurl/lib/urlapi.c                      | 230 +++--
 Utilities/cmcurl/lib/urldata.h                     | 634 +++++++-------
 Utilities/cmcurl/lib/vauth/cleartext.c             |  40 +-
 Utilities/cmcurl/lib/vauth/digest.c                |  15 +-
 Utilities/cmcurl/lib/vauth/digest_sspi.c           |   4 +-
 Utilities/cmcurl/lib/vauth/krb5_gssapi.c           |   6 +-
 Utilities/cmcurl/lib/vauth/krb5_sspi.c             |   6 +-
 Utilities/cmcurl/lib/vauth/ntlm.c                  | 262 +++---
 Utilities/cmcurl/lib/vauth/ntlm_sspi.c             |  51 +-
 Utilities/cmcurl/lib/vauth/oauth2.c                |  56 +-
 Utilities/cmcurl/lib/vauth/spnego_gssapi.c         |  14 +-
 Utilities/cmcurl/lib/vauth/spnego_sspi.c           |  56 +-
 Utilities/cmcurl/lib/vauth/vauth.c                 |  42 +-
 Utilities/cmcurl/lib/vauth/vauth.h                 |  20 +-
 Utilities/cmcurl/lib/version.c                     |  55 +-
 Utilities/cmcurl/lib/vtls/axtls.c                  | 741 ----------------
 Utilities/cmcurl/lib/vtls/axtls.h                  |  33 -
 Utilities/cmcurl/lib/vtls/cyassl.c                 |  42 +-
 Utilities/cmcurl/lib/vtls/gskit.c                  |  20 +-
 Utilities/cmcurl/lib/vtls/gtls.c                   |  82 +-
 Utilities/cmcurl/lib/vtls/mbedtls.c                |  45 +-
 Utilities/cmcurl/lib/vtls/mesalink.c               |   8 +-
 Utilities/cmcurl/lib/vtls/nss.c                    |  90 +-
 Utilities/cmcurl/lib/vtls/openssl.c                | 309 ++++---
 Utilities/cmcurl/lib/vtls/polarssl.c               |  17 +-
 Utilities/cmcurl/lib/vtls/polarssl_threadlock.c    |  59 +-
 Utilities/cmcurl/lib/vtls/polarssl_threadlock.h    |   9 +-
 Utilities/cmcurl/lib/vtls/schannel.c               | 345 +++++---
 Utilities/cmcurl/lib/vtls/schannel.h               |   4 +-
 Utilities/cmcurl/lib/vtls/schannel_verify.c        |  55 +-
 .../cmcurl/lib/vtls/{darwinssl.c => sectransp.c}   | 194 +++--
 .../cmcurl/lib/vtls/{darwinssl.h => sectransp.h}   |  14 +-
 Utilities/cmcurl/lib/vtls/vtls.c                   |  67 +-
 Utilities/cmcurl/lib/vtls/vtls.h                   |   9 +-
 Utilities/cmcurl/lib/warnless.c                    |  40 +-
 Utilities/cmcurl/lib/warnless.h                    |   6 +-
 Utilities/cmcurl/lib/wildcard.c                    |   6 +-
 Utilities/cmcurl/lib/wildcard.h                    |  10 +-
 Utilities/cmcurl/lib/x509asn1.c                    | 269 +++---
 240 files changed, 6752 insertions(+), 6325 deletions(-)
 create mode 100644 Utilities/cmcurl/lib/altsvc.c
 create mode 100644 Utilities/cmcurl/lib/altsvc.h
 copy Utilities/cmcurl/lib/{curl_memrchr.c => curl_get_line.c} (62%)
 copy Utilities/cmcurl/lib/{dict.h => curl_get_line.h} (74%)
 delete mode 100644 Utilities/cmcurl/lib/pipeline.c
 delete mode 100644 Utilities/cmcurl/lib/pipeline.h
 delete mode 100644 Utilities/cmcurl/lib/vtls/axtls.c
 delete mode 100644 Utilities/cmcurl/lib/vtls/axtls.h
 rename Utilities/cmcurl/lib/vtls/{darwinssl.c => sectransp.c} (95%)
 rename Utilities/cmcurl/lib/vtls/{darwinssl.h => sectransp.h} (80%)


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list