[Cmake-commits] CMake branch, master, updated. v3.10.2-940-ga24dbba

Kitware Robot kwrobot at kitware.com
Fri Jan 26 08:35:20 EST 2018


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  a24dbba3482d5c5b8542c56047ec78dd40215a06 (commit)
       via  0e793e7bedf78fa639f1cf48900a4932dbfd48de (commit)
       via  f343106b19eec139764dc965f9110f503aafbf9c (commit)
       via  b50fb70be8eb629083eb2ad2e0b413793bbdde06 (commit)
       via  d71be346a4502cb444edc59227675eeb8f41a51b (commit)
       via  234a069de3e365c20bc6ef42e83520a7e2547f95 (commit)
       via  3ec5f7c1a2fbfec42be1012210471f6b532e93a3 (commit)
       via  1ad58d30321757327675451ba6d095b5204b999c (commit)
       via  cd8e31a1bf7429514078c2923a1a9580113f9d4f (commit)
       via  af9e654045f11028e50dac4781e297834129a749 (commit)
       via  e9c8ea75575afdb4e87b262641ee4071ef42b4c6 (commit)
       via  e6a80ccfc440ac8dd5e9e5405744c2423560fc02 (commit)
       via  ff62b00522d1ddaeb88be241ab4a022f935b5c00 (commit)
       via  695951bc46fa4bc4eaf686c4ee6dce24c579bc45 (commit)
      from  9a52b80d066f6c782a28878d3b28ae458f9331b3 (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=a24dbba3482d5c5b8542c56047ec78dd40215a06
commit a24dbba3482d5c5b8542c56047ec78dd40215a06
Merge: 0e793e7 d71be34
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Jan 26 13:28:39 2018 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri Jan 26 08:28:43 2018 -0500

    Merge topic 'test-genex-speedup'
    
    d71be346 Tests: Speed up RunCMake.TargetPropertyGeneratorExpressions
    234a069d Tests: Speed up RunCMake.GeneratorExpression
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1701


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0e793e7bedf78fa639f1cf48900a4932dbfd48de
commit 0e793e7bedf78fa639f1cf48900a4932dbfd48de
Merge: f343106 3ec5f7c
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Jan 26 13:27:34 2018 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri Jan 26 08:28:08 2018 -0500

    Merge topic 'dedup-uv-signal-hack'
    
    3ec5f7c1 De-duplicate cmUVSignalHackRAII
    1ad58d30 cmUVSignalHackRAII: Use nullptr instead of NULL
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1699


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f343106b19eec139764dc965f9110f503aafbf9c
commit f343106b19eec139764dc965f9110f503aafbf9c
Merge: b50fb70 e6a80cc
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Jan 26 13:27:15 2018 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri Jan 26 08:27:37 2018 -0500

    Merge topic 'ctest-chrono'
    
    e6a80ccf Make use of std::chrono throughout every component
    ff62b005 CTest: add safe conversion from cmDuration to integer types
    695951bc CTest: introduce cmDuration
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1592


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b50fb70be8eb629083eb2ad2e0b413793bbdde06
commit b50fb70be8eb629083eb2ad2e0b413793bbdde06
Merge: 9a52b80 cd8e31a
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Jan 26 13:26:52 2018 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Fri Jan 26 08:26:57 2018 -0500

    Merge topic 'update-curl'
    
    cd8e31a1 Merge branch 'upstream-curl' into update-curl
    af9e6540 curl 2018-01-23 (d6c21c8e)
    e9c8ea75 curl: Update script to get curl 7.58.0
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1696


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d71be346a4502cb444edc59227675eeb8f41a51b
commit d71be346a4502cb444edc59227675eeb8f41a51b
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 25 10:49:56 2018 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Jan 25 12:08:13 2018 -0500

    Tests: Speed up RunCMake.TargetPropertyGeneratorExpressions
    
    Consolidate similar test cases.

diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName-result.txt
similarity index 100%
rename from Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-result.txt
rename to Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName-result.txt
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName-stderr.txt
new file mode 100644
index 0000000..6e89104
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName-stderr.txt
@@ -0,0 +1,50 @@
+^(CMake Error at BadInvalidName1/CMakeLists.txt:2 \(include_directories\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:Invali/dTarget,INCLUDE_DIRECTORIES>
+
+  Target name not supported.
++)+(CMake Error at BadInvalidName2/CMakeLists.txt:2 \(include_directories\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:Invali/dTarget,Invali/dProperty>
+
+  Target name and property name not supported.
++)+(CMake Error at BadInvalidName3/CMakeLists.txt:2 \(include_directories\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:Invali/dProperty>
+
+  Property name not supported.
++)+(CMake Error at BadInvalidName4/CMakeLists.txt:2 \(include_directories\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:BadInvalidName4,Invali/dProperty>
+
+  Property name not supported.
++)+(CMake Error at BadInvalidName5/CMakeLists.txt:2 \(include_directories\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:,>
+
+  \$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty target name and
+  property name.
++)+(CMake Error at BadInvalidName6/CMakeLists.txt:2 \(include_directories\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:,ValidProperty>
+
+  \$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty target name.
++)+(CMake Error at BadInvalidName7/CMakeLists.txt:2 \(include_directories\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:BadInvalidName7,>
+
+  \$<TARGET_PROPERTY:...> expression requires a non-empty property name.
++)+(CMake Error at BadInvalidName8/CMakeLists.txt:2 \(include_directories\):
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:>
+
+  \$<TARGET_PROPERTY:...> expression requires a non-empty property name.
+*)+$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName.cmake
new file mode 100644
index 0000000..5f083e2
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName.cmake
@@ -0,0 +1,8 @@
+add_subdirectory(BadInvalidName1)
+add_subdirectory(BadInvalidName2)
+add_subdirectory(BadInvalidName3)
+add_subdirectory(BadInvalidName4)
+add_subdirectory(BadInvalidName5)
+add_subdirectory(BadInvalidName6)
+add_subdirectory(BadInvalidName7)
+add_subdirectory(BadInvalidName8)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt
deleted file mode 100644
index 9c146e0..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-CMake Error at BadInvalidName1.cmake:7 \(include_directories\):
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:Invali/dTarget,INCLUDE_DIRECTORIES>
-
-  Target name not supported.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:8 \(include\)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1.cmake
deleted file mode 100644
index d5f661d..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-include_directories("$<TARGET_PROPERTY:Invali/dTarget,INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1/CMakeLists.txt
new file mode 100644
index 0000000..13e1de7
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadInvalidName1 ../main.cpp)
+include_directories("$<TARGET_PROPERTY:Invali/dTarget,INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt
deleted file mode 100644
index 451888c..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-CMake Error at BadInvalidName2.cmake:7 \(include_directories\):
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:Invali/dTarget,Invali/dProperty>
-
-  Target name and property name not supported.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:8 \(include\)$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2.cmake
deleted file mode 100644
index 6e4c1d0..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-include_directories("$<TARGET_PROPERTY:Invali/dTarget,Invali/dProperty>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2/CMakeLists.txt
new file mode 100644
index 0000000..4b78472
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadInvalidName2 ../main.cpp)
+include_directories("$<TARGET_PROPERTY:Invali/dTarget,Invali/dProperty>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt
deleted file mode 100644
index 39692c4..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-CMake Error at BadInvalidName3.cmake:7 \(include_directories\):
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:Invali/dProperty>
-
-  Property name not supported.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:8 \(include\)$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3.cmake
deleted file mode 100644
index 3f75aa3..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-include_directories("$<TARGET_PROPERTY:Invali/dProperty>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3/CMakeLists.txt
new file mode 100644
index 0000000..516a049
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadInvalidName3 ../main.cpp)
+include_directories("$<TARGET_PROPERTY:Invali/dProperty>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt
deleted file mode 100644
index c3aa1b1..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-CMake Error at BadInvalidName4.cmake:9 \(include_directories\):
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:foo,Invali/dProperty>
-
-  Property name not supported.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:8 \(include\)$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4.cmake
deleted file mode 100644
index b616c31..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4.cmake
+++ /dev/null
@@ -1,9 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(foo "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-include_directories("$<TARGET_PROPERTY:foo,Invali/dProperty>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4/CMakeLists.txt
new file mode 100644
index 0000000..02f2a1a
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadInvalidName4 ../main.cpp)
+include_directories("$<TARGET_PROPERTY:BadInvalidName4,Invali/dProperty>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt
deleted file mode 100644
index 1c6fad4..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-CMake Error at BadInvalidName5.cmake:7 \(include_directories\):
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:,>
-
-  \$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty target name and
-  property name.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:8 \(include\)$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5.cmake
deleted file mode 100644
index 11cb6fa..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-include_directories("$<TARGET_PROPERTY:,>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5/CMakeLists.txt
new file mode 100644
index 0000000..a653583
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadInvalidName5 ../main.cpp)
+include_directories("$<TARGET_PROPERTY:,>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt
deleted file mode 100644
index 8b147dc..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-CMake Error at BadInvalidName6.cmake:7 \(include_directories\):
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:,ValidProperty>
-
-  \$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty target name.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:8 \(include\)$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6.cmake
deleted file mode 100644
index bf868a5..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-include_directories("$<TARGET_PROPERTY:,ValidProperty>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6/CMakeLists.txt
new file mode 100644
index 0000000..614458e
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadInvalidName6 ../main.cpp)
+include_directories("$<TARGET_PROPERTY:,ValidProperty>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt
deleted file mode 100644
index dad6bf8..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-CMake Error at BadInvalidName7.cmake:9 \(include_directories\):
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:foo,>
-
-  \$<TARGET_PROPERTY:...> expression requires a non-empty property name.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:8 \(include\)$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7.cmake
deleted file mode 100644
index 36d1a79..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7.cmake
+++ /dev/null
@@ -1,9 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(foo "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-include_directories("$<TARGET_PROPERTY:foo,>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7/CMakeLists.txt
new file mode 100644
index 0000000..8a9fe80
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadInvalidName7 ../main.cpp)
+include_directories("$<TARGET_PROPERTY:BadInvalidName7,>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt
deleted file mode 100644
index 4e8c14c..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-CMake Error at BadInvalidName8.cmake:7 \(include_directories\):
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:>
-
-  \$<TARGET_PROPERTY:...> expression requires a non-empty property name.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:8 \(include\)$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8.cmake
deleted file mode 100644
index f059288..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-include_directories("$<TARGET_PROPERTY:>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8/CMakeLists.txt
new file mode 100644
index 0000000..b228159
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadInvalidName8 ../main.cpp)
+include_directories("$<TARGET_PROPERTY:>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference-result.txt
similarity index 100%
rename from Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-result.txt
rename to Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference-result.txt
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference-stderr.txt
new file mode 100644
index 0000000..f0f71ec
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference-stderr.txt
@@ -0,0 +1,37 @@
+^(CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>
+
+  Self reference on target "BadSelfReference1".
++)+(CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>
+
+  Self reference on target "BadSelfReference2".
++)+(CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:BadSelfReference3,INCLUDE_DIRECTORIES>
+
+  Self reference on target "BadSelfReference3".
++)+(CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:BadSelfReference4,INCLUDE_DIRECTORIES>
+
+  Self reference on target "BadSelfReference4".
++)+(CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:COMPILE_DEFINITIONS>
+
+  Self reference on target "BadSelfReference5".
++)+(CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_PROPERTY:BadSelfReference6,COMPILE_DEFINITIONS>
+
+  Self reference on target "BadSelfReference6".
+*)+$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference.cmake
new file mode 100644
index 0000000..5a99f7a
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference.cmake
@@ -0,0 +1,6 @@
+add_subdirectory(BadSelfReference1)
+add_subdirectory(BadSelfReference2)
+add_subdirectory(BadSelfReference3)
+add_subdirectory(BadSelfReference4)
+add_subdirectory(BadSelfReference5)
+add_subdirectory(BadSelfReference6)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-stderr.txt
deleted file mode 100644
index 75a729e..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CMake Error:
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>
-
-  Self reference on target "TargetPropertyGeneratorExpressions".
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1.cmake
deleted file mode 100644
index a85731e..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-include_directories("$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1/CMakeLists.txt
new file mode 100644
index 0000000..30c27f5
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadSelfReference1 ../main.cpp)
+include_directories("$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-stderr.txt
deleted file mode 100644
index 75a729e..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CMake Error:
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>
-
-  Self reference on target "TargetPropertyGeneratorExpressions".
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2.cmake
deleted file mode 100644
index f1459b8..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2.cmake
+++ /dev/null
@@ -1,9 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-set_property(TARGET TargetPropertyGeneratorExpressions PROPERTY
-  INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>"
-)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2/CMakeLists.txt
new file mode 100644
index 0000000..c2322f4
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadSelfReference2 ../main.cpp)
+set_property(TARGET BadSelfReference2 PROPERTY INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-stderr.txt
deleted file mode 100644
index f52a27d..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CMake Error:
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>
-
-  Self reference on target "TargetPropertyGeneratorExpressions".
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3.cmake
deleted file mode 100644
index 433b730..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3.cmake
+++ /dev/null
@@ -1,8 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-include_directories(
-  "$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3/CMakeLists.txt
new file mode 100644
index 0000000..3e6c30a
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadSelfReference3 ../main.cpp)
+include_directories("$<TARGET_PROPERTY:BadSelfReference3,INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-stderr.txt
deleted file mode 100644
index f52a27d..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CMake Error:
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>
-
-  Self reference on target "TargetPropertyGeneratorExpressions".
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4.cmake
deleted file mode 100644
index 4b64459..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4.cmake
+++ /dev/null
@@ -1,10 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-set_property(TARGET TargetPropertyGeneratorExpressions PROPERTY
-INCLUDE_DIRECTORIES
-  "$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>"
-)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4/CMakeLists.txt
new file mode 100644
index 0000000..f79727a
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadSelfReference4 ../main.cpp)
+set_property(TARGET BadSelfReference4 PROPERTY INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:BadSelfReference4,INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-stderr.txt
deleted file mode 100644
index d8d12b5..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CMake Error:
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:COMPILE_DEFINITIONS>
-
-  Self reference on target "TargetPropertyGeneratorExpressions".
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5.cmake
deleted file mode 100644
index 74fff67..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5.cmake
+++ /dev/null
@@ -1,10 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-set_property(TARGET TargetPropertyGeneratorExpressions
-PROPERTY
-  COMPILE_DEFINITIONS "$<TARGET_PROPERTY:COMPILE_DEFINITIONS>"
-)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5/CMakeLists.txt
new file mode 100644
index 0000000..c0badbf
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadSelfReference5 ../main.cpp)
+set_property(TARGET BadSelfReference5 PROPERTY COMPILE_DEFINITIONS "$<TARGET_PROPERTY:COMPILE_DEFINITIONS>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-stderr.txt
deleted file mode 100644
index 0b1dd26..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CMake Error:
-  Error evaluating generator expression:
-
-    \$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,COMPILE_DEFINITIONS>
-
-  Self reference on target "TargetPropertyGeneratorExpressions".
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6.cmake
deleted file mode 100644
index d6650d3..0000000
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6.cmake
+++ /dev/null
@@ -1,10 +0,0 @@
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
-           "int main(int, char **) { return 0; }\n")
-
-add_executable(TargetPropertyGeneratorExpressions
-           "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
-set_property(TARGET TargetPropertyGeneratorExpressions PROPERTY
-COMPILE_DEFINITIONS
-  "$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,COMPILE_DEFINITIONS>"
-)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6/CMakeLists.txt
new file mode 100644
index 0000000..fcb6b3c
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(BadSelfReference6 ../main.cpp)
+set_property(TARGET BadSelfReference6 PROPERTY COMPILE_DEFINITIONS "$<TARGET_PROPERTY:BadSelfReference6,COMPILE_DEFINITIONS>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
index 645a57d..4294e9f 100644
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
@@ -1,20 +1,8 @@
 include(RunCMake)
 
-run_cmake(BadSelfReference1)
-run_cmake(BadSelfReference2)
-run_cmake(BadSelfReference3)
-run_cmake(BadSelfReference4)
-run_cmake(BadSelfReference5)
-run_cmake(BadSelfReference6)
+run_cmake(BadSelfReference)
 run_cmake(BadNonTarget)
-run_cmake(BadInvalidName1)
-run_cmake(BadInvalidName2)
-run_cmake(BadInvalidName3)
-run_cmake(BadInvalidName4)
-run_cmake(BadInvalidName5)
-run_cmake(BadInvalidName6)
-run_cmake(BadInvalidName7)
-run_cmake(BadInvalidName8)
+run_cmake(BadInvalidName)
 run_cmake(LinkImplementationCycle1)
 run_cmake(LinkImplementationCycle2)
 run_cmake(LinkImplementationCycle3)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/main.cpp b/Tests/RunCMake/TargetPropertyGeneratorExpressions/main.cpp
new file mode 100644
index 0000000..f8b643a
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/main.cpp
@@ -0,0 +1,4 @@
+int main()
+{
+  return 0;
+}

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=234a069de3e365c20bc6ef42e83520a7e2547f95
commit 234a069de3e365c20bc6ef42e83520a7e2547f95
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 25 10:25:18 2018 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Jan 25 10:50:20 2018 -0500

    Tests: Speed up RunCMake.GeneratorExpression
    
    Avoid enabling languages in cases that do not need them.

diff --git a/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject-stderr.txt b/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject-stderr.txt
index 533d38c..a597d79 100644
--- a/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at BadTargetTypeObject.cmake:3 \(add_custom_target\):
+CMake Error at BadTargetTypeObject.cmake:2 \(add_custom_target\):
   Error evaluating generator expression:
 
     \$<TARGET_FILE:objlib>
@@ -7,7 +7,7 @@ CMake Error at BadTargetTypeObject.cmake:3 \(add_custom_target\):
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
 +
-CMake Error at BadTargetTypeObject.cmake:3 \(add_custom_target\):
+CMake Error at BadTargetTypeObject.cmake:2 \(add_custom_target\):
   Error evaluating generator expression:
 
     \$<TARGET_SONAME_FILE:objlib>
@@ -16,7 +16,7 @@ CMake Error at BadTargetTypeObject.cmake:3 \(add_custom_target\):
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
 +
-CMake Error at BadTargetTypeObject.cmake:3 \(add_custom_target\):
+CMake Error at BadTargetTypeObject.cmake:2 \(add_custom_target\):
   Error evaluating generator expression:
 
     \$<TARGET_LINKER_FILE:objlib>
diff --git a/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject.cmake b/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject.cmake
index c47ee2b..60e2c0d 100644
--- a/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject.cmake
+++ b/Tests/RunCMake/GeneratorExpression/BadTargetTypeObject.cmake
@@ -1,5 +1,4 @@
-enable_language(C)
-add_library(objlib OBJECT empty.c)
+add_library(objlib OBJECT)
 add_custom_target(check ALL COMMAND echo
   $<TARGET_FILE:objlib>
   $<TARGET_SONAME_FILE:objlib>
diff --git a/Tests/RunCMake/GeneratorExpression/CMP0044-WARN.cmake b/Tests/RunCMake/GeneratorExpression/CMP0044-WARN.cmake
index d5b85c9..dfa23e0 100644
--- a/Tests/RunCMake/GeneratorExpression/CMP0044-WARN.cmake
+++ b/Tests/RunCMake/GeneratorExpression/CMP0044-WARN.cmake
@@ -1,5 +1,5 @@
 
-project(CMP0044-WARN)
+enable_language(C)
 
 string(TOLOWER ${CMAKE_C_COMPILER_ID} lc_test)
 if (lc_test STREQUAL CMAKE_C_COMPILER_ID)
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command-stderr.txt
index c8b124a..c8f773a 100644
--- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANGUAGE-add_custom_command.cmake:6 \(add_custom_command\):
+CMake Error at COMPILE_LANGUAGE-add_custom_command.cmake:2 \(add_custom_command\):
   Error evaluating generator expression:
 
     \$<COMPILE_LANGUAGE>
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command.cmake
index f4ba261..c3f051a 100644
--- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command.cmake
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_command.cmake
@@ -1,8 +1,4 @@
-
-enable_language(C)
-
-add_library(empty empty.c)
-
-add_custom_command(TARGET empty PRE_BUILD
+add_custom_target(drive)
+add_custom_command(TARGET drive PRE_BUILD
   COMMAND ${CMAKE_COMMAND} -E echo $<COMPILE_LANGUAGE>
 )
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target-stderr.txt
index e8cefc7..7025838 100644
--- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANGUAGE-add_custom_target.cmake:4 \(add_custom_target\):
+CMake Error at COMPILE_LANGUAGE-add_custom_target.cmake:1 \(add_custom_target\):
   Error evaluating generator expression:
 
     \$<COMPILE_LANGUAGE>
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target.cmake
index 4102623..b826772 100644
--- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target.cmake
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_custom_target.cmake
@@ -1,6 +1,3 @@
-
-enable_language(C)
-
-add_custom_target(empty
+add_custom_target(drive
   COMMAND ${CMAKE_COMMAND} -E echo $<COMPILE_LANGUAGE>
 )
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable-stderr.txt
index 7fa1f25..8d05e59 100644
--- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANGUAGE-add_executable.cmake:4 \(add_executable\):
+CMake Error at COMPILE_LANGUAGE-add_executable.cmake:1 \(add_executable\):
   Error evaluating generator expression:
 
     \$<COMPILE_LANGUAGE>
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable.cmake
index 5c2ff35..ff965a9 100644
--- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable.cmake
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_executable.cmake
@@ -1,4 +1 @@
-
-enable_language(C)
-
 add_executable(empty empty.$<COMPILE_LANGUAGE>)
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library-stderr.txt
index ee60b58..2ac9b76 100644
--- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANGUAGE-add_library.cmake:4 \(add_library\):
+CMake Error at COMPILE_LANGUAGE-add_library.cmake:1 \(add_library\):
   Error evaluating generator expression:
 
     \$<COMPILE_LANGUAGE>
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library.cmake
index dd9f824..dd1b5a2 100644
--- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library.cmake
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-add_library.cmake
@@ -1,4 +1 @@
-
-enable_language(C)
-
 add_library(empty empty.$<COMPILE_LANGUAGE>)
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources-stderr.txt b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources-stderr.txt
index 687d9b7..8e7f881 100644
--- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at COMPILE_LANGUAGE-target_sources.cmake:5 \(target_sources\):
+CMake Error at COMPILE_LANGUAGE-target_sources.cmake:2 \(target_sources\):
   Error evaluating generator expression:
 
     \$<COMPILE_LANGUAGE>
diff --git a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources.cmake b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources.cmake
index 0c78acd..a4a5abb 100644
--- a/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources.cmake
+++ b/Tests/RunCMake/GeneratorExpression/COMPILE_LANGUAGE-target_sources.cmake
@@ -1,5 +1,2 @@
-
-enable_language(C)
-
-add_library(empty empty.c)
+add_library(empty)
 target_sources(empty PRIVATE empty.$<COMPILE_LANGUAGE>)
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_ID-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_ID-stderr.txt
index dd7a183..0c21aa6 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_ID-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_ID-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at NonValidTarget-CXX_COMPILER_ID.cmake:4 \(add_custom_command\):
+CMake Error at NonValidTarget-CXX_COMPILER_ID.cmake:1 \(add_custom_command\):
   Error evaluating generator expression:
 
     \$<CXX_COMPILER_ID>
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_ID.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_ID.cmake
index 7dd38da..a9fb092 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_ID.cmake
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_ID.cmake
@@ -1,8 +1,4 @@
-
-enable_language(CXX)
-
 add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp"
   COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<CXX_COMPILER_ID>.cpp"
 )
-
-add_library(empty "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp")
+add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp")
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_VERSION-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_VERSION-stderr.txt
index d4a064a..fae1bd2 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_VERSION-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_VERSION-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at NonValidTarget-CXX_COMPILER_VERSION.cmake:4 \(add_custom_command\):
+CMake Error at NonValidTarget-CXX_COMPILER_VERSION.cmake:1 \(add_custom_command\):
   Error evaluating generator expression:
 
     \$<CXX_COMPILER_VERSION>
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_VERSION.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_VERSION.cmake
index 1afb2b5..41610c4 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_VERSION.cmake
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-CXX_COMPILER_VERSION.cmake
@@ -1,8 +1,4 @@
-
-enable_language(CXX)
-
 add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp"
   COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<CXX_COMPILER_VERSION>.cpp"
 )
-
-add_library(empty "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp")
+add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp")
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_ID-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_ID-stderr.txt
index b8e53ed..337b299 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_ID-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_ID-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at NonValidTarget-C_COMPILER_ID.cmake:4 \(add_custom_command\):
+CMake Error at NonValidTarget-C_COMPILER_ID.cmake:1 \(add_custom_command\):
   Error evaluating generator expression:
 
     \$<C_COMPILER_ID>
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_ID.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_ID.cmake
index 2d92ee3..1b02431 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_ID.cmake
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_ID.cmake
@@ -1,8 +1,4 @@
-
-enable_language(CXX)
-
-add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp"
-  COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<C_COMPILER_ID>.cpp"
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c"
+  COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.c" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<C_COMPILER_ID>.c"
 )
-
-add_library(empty "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp")
+add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c")
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_VERSION-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_VERSION-stderr.txt
index 551efe9..d8548b5 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_VERSION-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_VERSION-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at NonValidTarget-C_COMPILER_VERSION.cmake:4 \(add_custom_command\):
+CMake Error at NonValidTarget-C_COMPILER_VERSION.cmake:1 \(add_custom_command\):
   Error evaluating generator expression:
 
     \$<C_COMPILER_VERSION>
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_VERSION.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_VERSION.cmake
index 9b8a531..bc1ffe0 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_VERSION.cmake
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-C_COMPILER_VERSION.cmake
@@ -1,8 +1,4 @@
-
-enable_language(CXX)
-
-add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp"
-  COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<C_COMPILER_VERSION>.cpp"
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c"
+  COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.c" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<C_COMPILER_VERSION>.c"
 )
-
-add_library(empty "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp")
+add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.c")
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_POLICY-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_POLICY-stderr.txt
index 0e87538..4babf43 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_POLICY-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_POLICY-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at NonValidTarget-TARGET_POLICY.cmake:4 \(add_custom_command\):
+CMake Error at NonValidTarget-TARGET_POLICY.cmake:1 \(add_custom_command\):
   Error evaluating generator expression:
 
     \$<TARGET_POLICY:CMP0004>
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_POLICY.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_POLICY.cmake
index 10b37b5..55d8a99 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_POLICY.cmake
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_POLICY.cmake
@@ -1,8 +1,4 @@
-
-enable_language(CXX)
-
 add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp"
   COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<TARGET_POLICY:CMP0004>.cpp"
 )
-
-add_library(empty "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp")
+add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp")
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_PROPERTY-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_PROPERTY-stderr.txt
index 08ad3c2..c414947 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_PROPERTY-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_PROPERTY-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at NonValidTarget-TARGET_PROPERTY.cmake:4 \(add_custom_command\):
+CMake Error at NonValidTarget-TARGET_PROPERTY.cmake:1 \(add_custom_command\):
   Error evaluating generator expression:
 
     \$<TARGET_PROPERTY:NotAProperty>
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_PROPERTY.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_PROPERTY.cmake
index 64abc5f..9e246b2 100644
--- a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_PROPERTY.cmake
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_PROPERTY.cmake
@@ -1,8 +1,4 @@
-
-enable_language(CXX)
-
 add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp"
   COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp" "${CMAKE_CURRENT_BINARY_DIR}/copied_file$<TARGET_PROPERTY:NotAProperty>.cpp"
 )
-
-add_library(empty "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp")
+add_custom_target(drive DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/copied_file.cpp")

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3ec5f7c1a2fbfec42be1012210471f6b532e93a3
commit 3ec5f7c1a2fbfec42be1012210471f6b532e93a3
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 25 09:22:47 2018 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Jan 25 09:22:47 2018 -0500

    De-duplicate cmUVSignalHackRAII
    
    This was added separately in `cmCTestMultiProcessHandler` and
    `cmQtAutoGenerator`.  Factor out the duplicate code into a common header
    for re-use.

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index c680fd2..62374c0 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -351,6 +351,7 @@ set(SRCS
   cmUuid.cxx
   cmUVHandlePtr.cxx
   cmUVHandlePtr.h
+  cmUVSignalHackRAII.h
   cmVariableWatch.cxx
   cmVariableWatch.h
   cmVersion.cxx
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 45d5bde..2821ab8 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -11,6 +11,8 @@
 
 #include "cm_uv.h"
 
+#include "cmUVSignalHackRAII.h" // IWYU pragma: keep
+
 #include "cmsys/FStream.hxx"
 #include "cmsys/String.hxx"
 #include "cmsys/SystemInformation.hxx"
@@ -25,43 +27,6 @@
 #include <stdlib.h>
 #include <utility>
 
-#if defined(CMAKE_USE_SYSTEM_LIBUV) && !defined(_WIN32) &&                    \
-  UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR < 19
-#define CMAKE_UV_SIGNAL_HACK
-/*
-   libuv does not use SA_RESTART on its signal handler, but C++ streams
-   depend on it for reliable i/o operations.  This RAII helper convinces
-   libuv to install its handler, and then revises the handler to add the
-   SA_RESTART flag.  We use a distinct uv loop that never runs to avoid
-   ever really getting a callback.  libuv may fill the hack loop's signal
-   pipe and then stop writing, but that won't break any real loops.
- */
-class cmUVSignalHackRAII
-{
-  uv_loop_t HackLoop;
-  cm::uv_signal_ptr HackSignal;
-  static void HackCB(uv_signal_t*, int) {}
-public:
-  cmUVSignalHackRAII()
-  {
-    uv_loop_init(&this->HackLoop);
-    this->HackSignal.init(this->HackLoop);
-    this->HackSignal.start(HackCB, SIGCHLD);
-    struct sigaction hack_sa;
-    sigaction(SIGCHLD, nullptr, &hack_sa);
-    if (!(hack_sa.sa_flags & SA_RESTART)) {
-      hack_sa.sa_flags |= SA_RESTART;
-      sigaction(SIGCHLD, &hack_sa, nullptr);
-    }
-  }
-  ~cmUVSignalHackRAII()
-  {
-    this->HackSignal.stop();
-    uv_loop_close(&this->HackLoop);
-  }
-};
-#endif
-
 class TestComparator
 {
 public:
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
index 6b35234..e029d8d 100644
--- a/Source/cmQtAutoGenerator.h
+++ b/Source/cmQtAutoGenerator.h
@@ -7,6 +7,7 @@
 
 #include "cmQtAutoGen.h"
 #include "cmUVHandlePtr.h"
+#include "cmUVSignalHackRAII.h" // IWYU pragma: keep
 #include "cm_uv.h"
 
 #include <array>
@@ -203,43 +204,6 @@ public:
     PipeT UVPipeErr_;
   };
 
-#if defined(CMAKE_USE_SYSTEM_LIBUV) && !defined(_WIN32) &&                    \
-  UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR < 19
-#define CMAKE_UV_SIGNAL_HACK
-  /*
-     libuv does not use SA_RESTART on its signal handler, but C++ streams
-     depend on it for reliable i/o operations.  This RAII helper convinces
-     libuv to install its handler, and then revises the handler to add the
-     SA_RESTART flag.  We use a distinct uv loop that never runs to avoid
-     ever really getting a callback.  libuv may fill the hack loop's signal
-     pipe and then stop writing, but that won't break any real loops.
-   */
-  class cmUVSignalHackRAII
-  {
-    uv_loop_t HackLoop;
-    cm::uv_signal_ptr HackSignal;
-    static void HackCB(uv_signal_t*, int) {}
-  public:
-    cmUVSignalHackRAII()
-    {
-      uv_loop_init(&this->HackLoop);
-      this->HackSignal.init(this->HackLoop);
-      this->HackSignal.start(HackCB, SIGCHLD);
-      struct sigaction hack_sa;
-      sigaction(SIGCHLD, NULL, &hack_sa);
-      if (!(hack_sa.sa_flags & SA_RESTART)) {
-        hack_sa.sa_flags |= SA_RESTART;
-        sigaction(SIGCHLD, &hack_sa, NULL);
-      }
-    }
-    ~cmUVSignalHackRAII()
-    {
-      this->HackSignal.stop();
-      uv_loop_close(&this->HackLoop);
-    }
-  };
-#endif
-
 public:
   // -- Constructors
   cmQtAutoGenerator();
diff --git a/Source/cmUVSignalHackRAII.h b/Source/cmUVSignalHackRAII.h
new file mode 100644
index 0000000..c019aea
--- /dev/null
+++ b/Source/cmUVSignalHackRAII.h
@@ -0,0 +1,44 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_uv.h"
+
+#if defined(CMAKE_USE_SYSTEM_LIBUV) && !defined(_WIN32) &&                    \
+  UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR < 19
+#define CMAKE_UV_SIGNAL_HACK
+#include "cmUVHandlePtr.h"
+/*
+   libuv does not use SA_RESTART on its signal handler, but C++ streams
+   depend on it for reliable i/o operations.  This RAII helper convinces
+   libuv to install its handler, and then revises the handler to add the
+   SA_RESTART flag.  We use a distinct uv loop that never runs to avoid
+   ever really getting a callback.  libuv may fill the hack loop's signal
+   pipe and then stop writing, but that won't break any real loops.
+ */
+class cmUVSignalHackRAII
+{
+  uv_loop_t HackLoop;
+  cm::uv_signal_ptr HackSignal;
+  static void HackCB(uv_signal_t*, int) {}
+public:
+  cmUVSignalHackRAII()
+  {
+    uv_loop_init(&this->HackLoop);
+    this->HackSignal.init(this->HackLoop);
+    this->HackSignal.start(HackCB, SIGCHLD);
+    struct sigaction hack_sa;
+    sigaction(SIGCHLD, nullptr, &hack_sa);
+    if (!(hack_sa.sa_flags & SA_RESTART)) {
+      hack_sa.sa_flags |= SA_RESTART;
+      sigaction(SIGCHLD, &hack_sa, nullptr);
+    }
+  }
+  ~cmUVSignalHackRAII()
+  {
+    this->HackSignal.stop();
+    uv_loop_close(&this->HackLoop);
+  }
+};
+#endif

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1ad58d30321757327675451ba6d095b5204b999c
commit 1ad58d30321757327675451ba6d095b5204b999c
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 25 09:02:51 2018 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Jan 25 09:21:39 2018 -0500

    cmUVSignalHackRAII: Use nullptr instead of NULL

diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 53c47a2..45d5bde 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -48,10 +48,10 @@ public:
     this->HackSignal.init(this->HackLoop);
     this->HackSignal.start(HackCB, SIGCHLD);
     struct sigaction hack_sa;
-    sigaction(SIGCHLD, NULL, &hack_sa);
+    sigaction(SIGCHLD, nullptr, &hack_sa);
     if (!(hack_sa.sa_flags & SA_RESTART)) {
       hack_sa.sa_flags |= SA_RESTART;
-      sigaction(SIGCHLD, &hack_sa, NULL);
+      sigaction(SIGCHLD, &hack_sa, nullptr);
     }
   }
   ~cmUVSignalHackRAII()

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cd8e31a1bf7429514078c2923a1a9580113f9d4f
commit cd8e31a1bf7429514078c2923a1a9580113f9d4f
Merge: e9c8ea7 af9e654
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Jan 24 14:17:42 2018 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Jan 24 14:18:16 2018 -0500

    Merge branch 'upstream-curl' into update-curl
    
    * upstream-curl:
      curl 2018-01-23 (d6c21c8e)

diff --cc Utilities/cmcurl/CMake/curl-config.cmake
index 0000000,119332c..119332c
mode 000000,100644..100644
--- a/Utilities/cmcurl/CMake/curl-config.cmake
+++ b/Utilities/cmcurl/CMake/curl-config.cmake
diff --cc Utilities/cmcurl/CMakeLists.txt
index a831f7f,0000000..148ca5d
mode 100644,000000..100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@@ -1,1438 -1,0 +1,1463 @@@
 +# 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(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_STATICLIB ON CACHE INTERNAL "Static curl")
 +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 OFF CACHE INTERNAL "No curl IPv6 support")
 +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|XL|VisualAge|SunPro|MIPSpro|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 - 2017, 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.
- cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
++cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
 +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(CURL_STATICLIB "Set to ON to build libcurl with static linking." OFF)
 +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)
 +      # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
 +      # test result in.
 +      CHECK_C_COMPILER_FLAG(${_CCOPT} OPT${_CCOPT})
 +      if(OPT${_CCOPT})
 +        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
 +      endif()
 +    endforeach()
 +  endif(PICKY_COMPILER)
 +endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
 +
 +if (ENABLE_DEBUG)
 +  # DEBUGBUILD will be defined only for Debug builds
 +  if(NOT CMAKE_VERSION VERSION_LESS 3.0)
 +    set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
 +  else()
 +    set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUGBUILD)
 +  endif()
 +  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
 +set(CMAKE_DEBUG_POSTFIX "-d" CACHE STRING "Set debug library postfix")
 +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.
 +CURL_NROFF_CHECK()
 +# Required for building manual, docs, tests
 +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(BORLAND)
 +
 +if(CURL_WERROR)
 +  if(MSVC_VERSION)
 +    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /WX")
 +    set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /WX")
 +  else()
 +    # this assumes clang or gcc style options
 +    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
 +  endif()
 +endif(CURL_WERROR)
 +
 +# If we are on AIX, do the _ALL_SOURCE magic
 +if(${CMAKE_SYSTEM_NAME} MATCHES AIX)
 +  set(_ALL_SOURCE 1)
 +endif(${CMAKE_SYSTEM_NAME} MATCHES AIX)
 +
 +# 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(WIN32)
 +
 +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(BEOS)
 +
 +check_library_exists_concat("network" recv HAVE_LIBNETWORK)
 +
 +if(NOT NOT_NEED_LIBNSL)
 +  check_library_exists_concat("nsl"    gethostbyname  HAVE_LIBNSL)
 +endif(NOT NOT_NEED_LIBNSL)
 +
 +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)
 +endif()
 +
 +# check SSL libraries
 +# TODO support GNUTLS, NSS, POLARSSL, AXTLS, CYASSL
 +
 +if(APPLE)
 +  option(CMAKE_USE_DARWINSSL "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)
 +  set(openssl_default OFF)
 +endif()
 +
 +collect_true(enabled_ssl_options enabled_ssl_options_count
 +  CMAKE_USE_WINSSL
 +  CMAKE_USE_DARWINSSL
 +  CMAKE_USE_OPENSSL
 +  CMAKE_USE_MBEDTLS
 +)
 +if(enabled_ssl_options_count GREATER 1)
 +  message(FATAL_ERROR "Multiple SSL options specified: ${enabled_ssl_options}. Please pick at most one and disable the rest.")
 +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)
 +  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)
 +  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/engine.h" HAVE_OPENSSL_ENGINE_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/pkcs12.h" HAVE_OPENSSL_PKCS12_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)
 +
 +      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(HAVE_ZLIB OFF)
 +if(CURL_ZLIB)
 +  find_package(ZLIB QUIET)
 +  if(ZLIB_FOUND)
 +    set(HAVE_ZLIB_H ON)
 +    set(HAVE_ZLIB ON)
 +    set(HAVE_LIBZ ON)
 +    list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
 +    include_directories(${ZLIB_INCLUDE_DIRS})
 +    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()
 +
 +#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 "")
 +
 +  endif(LIBSSH2_FOUND)
 +endif(CMAKE_USE_LIBSSH2)
 +
 +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})
 +    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()
 +
 +    endif()
 +
 +    include_directories(${GSS_INCLUDE_DIRECTORIES})
 +    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("limits.h"         HAVE_LIMITS_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(HAVE_SIZEOF_LONG_LONG)
 +
 +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(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(NOT HAVE_STRNCMPI)
 +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(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(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
 +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(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_run(${CURL_TEST})
 +  endforeach(CURL_TEST)
 +endif(HAVE_FSETXATTR)
 +
 +# 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(HAVE_SIGNAL_H)
 +
 +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(HAVE_MACRO_SIGSETJMP)
 +  endif(HAVE_SETJMP_H)
 +endif(NOT HAVE_SIGSETJMP)
 +
 +# If there is no stricmp(), do not allow LDAP to parse URLs
 +if(NOT HAVE_STRICMP)
 +  set(HAVE_LDAP_URL_PARSE 1)
 +endif(NOT HAVE_STRICMP)
 +
 +# 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_SOCKLEN_T
 +    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
 +    )
 +  curl_internal_test(${CURL_TEST})
 +endforeach(CURL_TEST)
 +
 +if(HAVE_FILE_OFFSET_BITS)
 +  set(_FILE_OFFSET_BITS 64)
 +  set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
 +endif(HAVE_FILE_OFFSET_BITS)
 +check_type_size("off_t"  SIZEOF_OFF_T)
 +
 +# include this header to get the type
 +set(CMAKE_REQUIRED_INCLUDES "${CURL_SOURCE_DIR}/include")
 +set(CMAKE_EXTRA_INCLUDE_FILES "curl/system.h")
 +check_type_size("curl_off_t"  SIZEOF_CURL_OFF_T)
 +set(CMAKE_EXTRA_INCLUDE_FILES "")
 +
 +set(CMAKE_REQUIRED_FLAGS)
 +
 +foreach(CURL_TEST
 +    HAVE_GLIBC_STRERROR_R
 +    HAVE_POSIX_STRERROR_R
 +    )
 +  curl_internal_test_run(${CURL_TEST})
 +endforeach(CURL_TEST)
 +
 +# 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(${CURL_TEST}_REENTRANT)
 +  endif(NOT ${CURL_TEST})
 +endforeach(CURL_TEST)
 +
 +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(${CURL_TEST}_REENTRANT)
 +  endforeach(CURL_TEST)
 +endif(NEED_REENTRANT)
 +
 +if(HAVE_INET_NTOA_R_DECL_REENTRANT)
 +  set(HAVE_INET_NTOA_R_DECL 1)
 +  set(NEED_REENTRANT 1)
 +endif(HAVE_INET_NTOA_R_DECL_REENTRANT)
 +
 +# Some other minor tests
 +
 +if(NOT HAVE_IN_ADDR_T)
 +  set(in_addr_t "unsigned long")
 +endif(NOT HAVE_IN_ADDR_T)
 +
 +# Fix libz / zlib.h
 +
 +if(NOT CURL_SPECIAL_LIBZ)
 +  if(NOT HAVE_LIBZ)
 +    set(HAVE_ZLIB_H 0)
 +  endif(NOT HAVE_LIBZ)
 +
 +  if(NOT HAVE_ZLIB_H)
 +    set(HAVE_LIBZ 0)
 +  endif(NOT HAVE_ZLIB_H)
 +endif(NOT CURL_SPECIAL_LIBZ)
 +
 +# 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(HAVE_FIONBIO OR
 +  HAVE_IOCTLSOCKET OR
 +  HAVE_IOCTLSOCKET_CASE OR
 +  HAVE_O_NONBLOCK)
 +
 +if(RETSIGTYPE_TEST)
 +  set(RETSIGTYPE void)
 +else(RETSIGTYPE_TEST)
 +  set(RETSIGTYPE int)
 +endif(RETSIGTYPE_TEST)
 +
 +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(MPRINTF_COMPILE_FLAGS)
 +      set(MPRINTF_COMPILE_FLAGS "-Wno-long-double")
 +    endif(MPRINTF_COMPILE_FLAGS)
 +    set_source_files_properties(mprintf.c PROPERTIES
 +      COMPILE_FLAGS ${MPRINTF_COMPILE_FLAGS})
 +  endif(HAVE_C_FLAG_Wno_long_double)
 +endif(CMAKE_COMPILER_IS_GNUCC AND APPLE)
 +
 +if(HAVE_SOCKLEN_T)
 +  set(CURL_HAVE_SOCKLEN_T 1)
 +  set(CURL_TYPEOF_CURL_SOCKLEN_T "socklen_t")
 +  if(WIN32)
 +    set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h;ws2tcpip.h")
 +  elseif(HAVE_SYS_SOCKET_H)
 +    set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
 +  endif()
 +  check_type_size("socklen_t" CURL_SIZEOF_CURL_SOCKLEN_T)
 +  set(CMAKE_EXTRA_INCLUDE_FILES)
 +  if(NOT HAVE_CURL_SIZEOF_CURL_SOCKLEN_T)
 +    message(FATAL_ERROR
 +     "Check for sizeof socklen_t failed, see CMakeFiles/CMakerror.log")
 +  endif()
 +else()
 +  set(CURL_HAVE_SOCKLEN_T 0)
 +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)
 +endif(WIN32)
 +
 +if(MSVC)
 +  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(CMAKE_C_FLAGS MATCHES "/W[0-4]")
 +    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
 +  endif(CMAKE_C_FLAGS MATCHES "/W[0-4]")
 +endif(MSVC)
 +
 +# Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
 +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(WIN32 AND NOT CYGWIN)
++    set(CURL_INSTALL_CMAKE_DIR CMake)
++else()
++    set(CURL_INSTALL_CMAKE_DIR lib/cmake/curl)
++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(LIBCURL curltest.c)
 +target_link_libraries(LIBCURL cmcurl)
 +
 +if(CMAKE_CURL_TEST_URL)
 +  add_test(curl LIBCURL ${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("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))
 +  _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)
 +string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
 +message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
 +
 +# 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}")
 +set(ENABLE_SHARED           "yes")
 +if(CURL_STATICLIB)
 +  set(ENABLE_STATIC         "yes")
 +else()
 +  set(ENABLE_STATIC         "no")
 +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
 +configure_file("${CURL_SOURCE_DIR}/curl-config.in"
 +               "${CURL_BINARY_DIR}/curl-config" @ONLY)
 +install(FILES "${CURL_BINARY_DIR}/curl-config"
 +        DESTINATION bin
 +        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 lib/pkgconfig)
 +
 +# This needs to be run very last so other parts of the scripts can take advantage of this.
 +if(NOT CURL_CONFIG_HAS_BEEN_RUN_BEFORE)
 +  set(CURL_CONFIG_HAS_BEEN_RUN_BEFORE 1 CACHE INTERNAL "Flag to track whether this is the first time running CMake or if CMake has been configured before")
 +endif()
 +
 +# install headers
 +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl"
 +    DESTINATION include
 +    FILES_MATCHING PATTERN "*.h")
 +
++
++include(CMakePackageConfigHelpers)
++write_basic_package_version_file(
++    "${PROJECT_BINARY_DIR}/curl-config-version.cmake"
++    VERSION ${CURL_VERSION}
++    COMPATIBILITY SameMajorVersion
++)
++
++configure_file(CMake/curl-config.cmake
++        "${PROJECT_BINARY_DIR}/curl-config.cmake"
++        COPYONLY
++)
++
++install(
++        FILES ${PROJECT_BINARY_DIR}/curl-config.cmake
++              ${PROJECT_BINARY_DIR}/curl-config-version.cmake
++        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 5b4fd0f,0000000..a96124d
mode 100644,000000..100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@@ -1,2742 -1,0 +1,2753 @@@
 +#ifndef __CURL_CURL_H
 +#define __CURL_CURL_H
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
 + * Copyright (C) 1998 - 2017, 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
 +
 +#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__)
 +#  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_MBEDTLS = 11
 +} curl_sslbackend;
 +
 +/* aliases for library clones and renames */
 +#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
 +#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
 +#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
 +
 +struct curl_httppost {
 +  struct curl_httppost *next;       /* next entry in the list */
 +  char *name;                       /* pointer to allocated name */
 +  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);
 +
 +
 +
 +/* enumeration of file types */
 +typedef enum {
 +  CURLFILETYPE_FILE = 0,
 +  CURLFILETYPE_DIRECTORY,
 +  CURLFILETYPE_SYMLINK,
 +  CURLFILETYPE_DEVICE_BLOCK,
 +  CURLFILETYPE_DEVICE_CHAR,
 +  CURLFILETYPE_NAMEDPIPE,
 +  CURLFILETYPE_SOCKET,
 +  CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
 +
 +  CURLFILETYPE_UNKNOWN /* should never occur */
 +} curlfiletype;
 +
 +#define CURLFINFOFLAG_KNOWN_FILENAME    (1<<0)
 +#define CURLFINFOFLAG_KNOWN_FILETYPE    (1<<1)
 +#define CURLFINFOFLAG_KNOWN_TIME        (1<<2)
 +#define CURLFINFOFLAG_KNOWN_PERM        (1<<3)
 +#define CURLFINFOFLAG_KNOWN_UID         (1<<4)
 +#define CURLFINFOFLAG_KNOWN_GID         (1<<5)
 +#define CURLFINFOFLAG_KNOWN_SIZE        (1<<6)
 +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT  (1<<7)
 +
 +/* Content of this structure depends on information which is known and is
 +   achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
 +   page for callbacks returning this structure -- some fields are mandatory,
 +   some others are optional. The FLAG field has special meaning. */
 +struct curl_fileinfo {
 +  char *filename;
 +  curlfiletype filetype;
 +  time_t time;
 +  unsigned int perm;
 +  int uid;
 +  int gid;
 +  curl_off_t size;
 +  long int hardlinks;
 +
 +  struct {
 +    /* If some of these fields is not NULL, it is a pointer to b_data. */
 +    char *time;
 +    char *perm;
 +    char *user;
 +    char *group;
 +    char *target; /* pointer to the target filename of a symlink */
 +  } strings;
 +
 +  unsigned int flags;
 +
 +  /* used internally */
 +  char *b_data;
 +  size_t b_size;
 +  size_t b_used;
 +};
 +
 +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
 +#define CURL_CHUNK_BGN_FUNC_OK      0
 +#define CURL_CHUNK_BGN_FUNC_FAIL    1 /* tell the lib to end the task */
 +#define CURL_CHUNK_BGN_FUNC_SKIP    2 /* skip this chunk over */
 +
 +/* if splitting of data transfer is enabled, this callback is called before
 +   download of an individual chunk started. Note that parameter "remains" works
 +   only for FTP wildcard downloading (for now), otherwise is not used */
 +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
 +                                        void *ptr,
 +                                        int remains);
 +
 +/* return codes for CURLOPT_CHUNK_END_FUNCTION */
 +#define CURL_CHUNK_END_FUNC_OK      0
 +#define CURL_CHUNK_END_FUNC_FAIL    1 /* tell the lib to end the task */
 +
 +/* If splitting of data transfer is enabled this callback is called after
 +   download of an individual chunk finished.
 +   Note! After this callback was set then it have to be called FOR ALL chunks.
 +   Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
 +   This is the reason why we don't need "transfer_info" parameter in this
 +   callback and we are not interested in "remains" parameter too. */
 +typedef long (*curl_chunk_end_callback)(void *ptr);
 +
 +/* return codes for FNMATCHFUNCTION */
 +#define CURL_FNMATCHFUNC_MATCH    0 /* string corresponds to the pattern */
 +#define CURL_FNMATCHFUNC_NOMATCH  1 /* pattern doesn't match the string */
 +#define CURL_FNMATCHFUNC_FAIL     2 /* an error occurred */
 +
 +/* callback type for wildcard downloading pattern matching. If the
 +   string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
 +typedef int (*curl_fnmatch_callback)(void *ptr,
 +                                     const char *pattern,
 +                                     const char *string);
 +
 +/* These are the return codes for the seek callbacks */
 +#define CURL_SEEKFUNC_OK       0
 +#define CURL_SEEKFUNC_FAIL     1 /* fail the entire transfer */
 +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
 +                                    libcurl might try other means instead */
 +typedef int (*curl_seek_callback)(void *instream,
 +                                  curl_off_t offset,
 +                                  int origin); /* 'whence' */
 +
 +/* This is a return code for the read callback that, when returned, will
 +   signal libcurl to immediately abort the current transfer. */
 +#define CURL_READFUNC_ABORT 0x10000000
 +/* This is a return code for the read callback that, when returned, will
 +   signal libcurl to pause sending data on the current transfer. */
 +#define CURL_READFUNC_PAUSE 0x10000001
 +
 +typedef size_t (*curl_read_callback)(char *buffer,
 +                                      size_t size,
 +                                      size_t nitems,
 +                                      void *instream);
 +
 +typedef enum {
 +  CURLSOCKTYPE_IPCXN,  /* socket created for a specific IP connection */
 +  CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
 +  CURLSOCKTYPE_LAST    /* never use */
 +} curlsocktype;
 +
 +/* The return code from the sockopt_callback can signal information back
 +   to libcurl: */
 +#define CURL_SOCKOPT_OK 0
 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
 +                                CURLE_ABORTED_BY_CALLBACK */
 +#define CURL_SOCKOPT_ALREADY_CONNECTED 2
 +
 +typedef int (*curl_sockopt_callback)(void *clientp,
 +                                     curl_socket_t curlfd,
 +                                     curlsocktype purpose);
 +
 +struct curl_sockaddr {
 +  int family;
 +  int socktype;
 +  int protocol;
 +  unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it
 +                           turned really ugly and painful on the systems that
 +                           lack this type */
 +  struct sockaddr addr;
 +};
 +
 +typedef curl_socket_t
 +(*curl_opensocket_callback)(void *clientp,
 +                            curlsocktype purpose,
 +                            struct curl_sockaddr *address);
 +
 +typedef int
 +(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
 +
 +typedef enum {
 +  CURLIOE_OK,            /* I/O operation successful */
 +  CURLIOE_UNKNOWNCMD,    /* command was unknown to callback */
 +  CURLIOE_FAILRESTART,   /* failed to restart the read */
 +  CURLIOE_LAST           /* never use */
 +} curlioerr;
 +
 +typedef enum {
 +  CURLIOCMD_NOP,         /* no operation */
 +  CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
 +  CURLIOCMD_LAST         /* never use */
 +} curliocmd;
 +
 +typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
 +                                         int cmd,
 +                                         void *clientp);
 +
 +#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_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
 +                                     wasn't verified fine */
 +  CURLE_GOT_NOTHING,             /* 52 - when this is a specific error */
 +  CURLE_SSL_ENGINE_NOTFOUND,     /* 53 - SSL crypto engine not found */
 +  CURLE_SSL_ENGINE_SETFAILED,    /* 54 - can not set SSL crypto engine as
 +                                    default */
 +  CURLE_SEND_ERROR,              /* 55 - failed sending network data */
 +  CURLE_RECV_ERROR,              /* 56 - failure in receiving network data */
 +  CURLE_OBSOLETE57,              /* 57 - NOT IN USE */
 +  CURLE_SSL_CERTPROBLEM,         /* 58 - problem with the local certificate */
 +  CURLE_SSL_CIPHER,              /* 59 - couldn't use specified cipher */
 +  CURLE_SSL_CACERT,              /* 60 - problem with the CA cert (path?) */
 +  CURLE_BAD_CONTENT_ENCODING,    /* 61 - Unrecognized/bad encoding */
 +  CURLE_LDAP_INVALID_URL,        /* 62 - Invalid LDAP URL */
 +  CURLE_FILESIZE_EXCEEDED,       /* 63 - Maximum file size exceeded */
 +  CURLE_USE_SSL_FAILED,          /* 64 - Requested FTP SSL level failed */
 +  CURLE_SEND_FAIL_REWIND,        /* 65 - Sending the data requires a rewind
 +                                    that failed */
 +  CURLE_SSL_ENGINE_INITFAILED,   /* 66 - failed to initialise ENGINE */
 +  CURLE_LOGIN_DENIED,            /* 67 - user, password or similar was not
 +                                    accepted and we failed to login */
 +  CURLE_TFTP_NOTFOUND,           /* 68 - file not found on server */
 +  CURLE_TFTP_PERM,               /* 69 - permission problem on server */
 +  CURLE_REMOTE_DISK_FULL,        /* 70 - out of disk space on server */
 +  CURLE_TFTP_ILLEGAL,            /* 71 - Illegal TFTP operation */
 +  CURLE_TFTP_UNKNOWNID,          /* 72 - Unknown transfer ID */
 +  CURLE_REMOTE_FILE_EXISTS,      /* 73 - File already exists */
 +  CURLE_TFTP_NOSUCHUSER,         /* 74 - No such user */
 +  CURLE_CONV_FAILED,             /* 75 - conversion failed */
 +  CURLE_CONV_REQD,               /* 76 - caller must register conversion
 +                                    callbacks using curl_easy_setopt options
 +                                    CURLOPT_CONV_FROM_NETWORK_FUNCTION,
 +                                    CURLOPT_CONV_TO_NETWORK_FUNCTION, and
 +                                    CURLOPT_CONV_FROM_UTF8_FUNCTION */
 +  CURLE_SSL_CACERT_BADFILE,      /* 77 - could not load CACERT file, missing
 +                                    or wrong format */
 +  CURLE_REMOTE_FILE_NOT_FOUND,   /* 78 - remote file not found */
 +  CURLE_SSH,                     /* 79 - error from the SSH layer, somewhat
 +                                    generic so the error message will be of
 +                                    interest when this has happened */
 +
 +  CURLE_SSL_SHUTDOWN_FAILED,     /* 80 - Failed to shut down the SSL
 +                                    connection */
 +  CURLE_AGAIN,                   /* 81 - socket is not ready for send/recv,
 +                                    wait till it's ready and try again (Added
 +                                    in 7.18.2) */
 +  CURLE_SSL_CRL_BADFILE,         /* 82 - could not load CRL file, missing or
 +                                    wrong format (Added in 7.19.0) */
 +  CURLE_SSL_ISSUER_ERROR,        /* 83 - Issuer check failed.  (Added in
 +                                    7.19.0) */
 +  CURLE_FTP_PRET_FAILED,         /* 84 - a PRET command failed */
 +  CURLE_RTSP_CSEQ_ERROR,         /* 85 - mismatch of RTSP CSeq numbers */
 +  CURLE_RTSP_SESSION_ERROR,      /* 86 - mismatch of RTSP Session Ids */
 +  CURLE_FTP_BAD_FILE_LIST,       /* 87 - unable to parse FTP file list */
 +  CURLE_CHUNK_FAILED,            /* 88 - chunk callback reported error */
 +  CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
 +                                    session will be queued */
 +  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
 +                                    */
 +  CURL_LAST /* never use! */
 +} CURLcode;
 +
 +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
 +                          the obsolete stuff removed! */
 +
 +/* Previously obsolete error code re-used in 7.38.0 */
 +#define CURLE_OBSOLETE16 CURLE_HTTP2
 +
 +/* Previously obsolete error codes re-used in 7.24.0 */
 +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
 +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
 +
 +/*  compatibility with older names */
 +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
 +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
 +
 +/* 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_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_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_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)
 +
 +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
 +                          the obsolete stuff removed! */
 +
 +/* Backwards compatibility with older names */
 +/* These are scheduled to disappear by 2009 */
 +
 +#define CURLFTPSSL_NONE CURLUSESSL_NONE
 +#define CURLFTPSSL_TRY CURLUSESSL_TRY
 +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL
 +#define CURLFTPSSL_ALL CURLUSESSL_ALL
 +#define CURLFTPSSL_LAST CURLUSESSL_LAST
 +#define curl_ftpssl curl_usessl
 +#endif /*!CURL_NO_OLDIES*/
 +
 +/* parameter for the CURLOPT_FTP_SSL_CCC option */
 +typedef enum {
 +  CURLFTPSSL_CCC_NONE,    /* do not send CCC */
 +  CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */
 +  CURLFTPSSL_CCC_ACTIVE,  /* Initiate the shutdown */
 +  CURLFTPSSL_CCC_LAST     /* not an option, never use */
 +} curl_ftpccc;
 +
 +/* parameter for the CURLOPT_FTPSSLAUTH option */
 +typedef enum {
 +  CURLFTPAUTH_DEFAULT, /* let libcurl decide */
 +  CURLFTPAUTH_SSL,     /* use "AUTH SSL" */
 +  CURLFTPAUTH_TLS,     /* use "AUTH TLS" */
 +  CURLFTPAUTH_LAST /* not an option, never use */
 +} curl_ftpauth;
 +
 +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */
 +typedef enum {
 +  CURLFTP_CREATE_DIR_NONE,  /* do NOT create missing dirs! */
 +  CURLFTP_CREATE_DIR,       /* (FTP/SFTP) if CWD fails, try MKD and then CWD
 +                               again if MKD succeeded, for SFTP this does
 +                               similar magic */
 +  CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD
 +                               again even if MKD failed! */
 +  CURLFTP_CREATE_DIR_LAST   /* not an option, never use */
 +} curl_ftpcreatedir;
 +
 +/* parameter for the CURLOPT_FTP_FILEMETHOD option */
 +typedef enum {
 +  CURLFTPMETHOD_DEFAULT,   /* let libcurl pick */
 +  CURLFTPMETHOD_MULTICWD,  /* single CWD operation for each path part */
 +  CURLFTPMETHOD_NOCWD,     /* no CWD at all */
 +  CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
 +  CURLFTPMETHOD_LAST       /* not an option, never use */
 +} curl_ftpmethod;
 +
 +/* bitmask defines for CURLOPT_HEADEROPT */
 +#define CURLHEADER_UNIFIED  0
 +#define CURLHEADER_SEPARATE (1<<0)
 +
 +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
 +#define CURLPROTO_HTTP   (1<<0)
 +#define CURLPROTO_HTTPS  (1<<1)
 +#define CURLPROTO_FTP    (1<<2)
 +#define CURLPROTO_FTPS   (1<<3)
 +#define CURLPROTO_SCP    (1<<4)
 +#define CURLPROTO_SFTP   (1<<5)
 +#define CURLPROTO_TELNET (1<<6)
 +#define CURLPROTO_LDAP   (1<<7)
 +#define CURLPROTO_LDAPS  (1<<8)
 +#define CURLPROTO_DICT   (1<<9)
 +#define CURLPROTO_FILE   (1<<10)
 +#define CURLPROTO_TFTP   (1<<11)
 +#define CURLPROTO_IMAP   (1<<12)
 +#define CURLPROTO_IMAPS  (1<<13)
 +#define CURLPROTO_POP3   (1<<14)
 +#define CURLPROTO_POP3S  (1<<15)
 +#define CURLPROTO_SMTP   (1<<16)
 +#define CURLPROTO_SMTPS  (1<<17)
 +#define CURLPROTO_RTSP   (1<<18)
 +#define CURLPROTO_RTMP   (1<<19)
 +#define CURLPROTO_RTMPT  (1<<20)
 +#define CURLPROTO_RTMPE  (1<<21)
 +#define CURLPROTO_RTMPTE (1<<22)
 +#define CURLPROTO_RTMPS  (1<<23)
 +#define CURLPROTO_RTMPTS (1<<24)
 +#define CURLPROTO_GOPHER (1<<25)
 +#define CURLPROTO_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. If this is not used, error messages go to stderr instead: */
++   * 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 IPv4 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),
 +
 +  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_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! */
 +
 +  CURLINFO_LASTONE          = 49
 +} CURLINFO;
 +
 +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
 +   CURLINFO_HTTP_CODE */
 +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
 +
 +typedef enum {
 +  CURLCLOSEPOLICY_NONE, /* first, never use this */
 +
 +  CURLCLOSEPOLICY_OLDEST,
 +  CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
 +  CURLCLOSEPOLICY_LEAST_TRAFFIC,
 +  CURLCLOSEPOLICY_SLOWEST,
 +  CURLCLOSEPOLICY_CALLBACK,
 +
 +  CURLCLOSEPOLICY_LAST /* last, never use this */
 +} curl_closepolicy;
 +
- #define CURL_GLOBAL_SSL (1<<0)
++#define CURL_GLOBAL_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_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_FOURTH
++#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. */
 +
 + /*
 + * NAME curl_version_info()
 + *
 + * DESCRIPTION
 + *
 + * This function returns a pointer to a static copy of the version info
 + * struct. See above.
 + */
 +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
 +
 +/*
 + * NAME curl_easy_strerror()
 + *
 + * DESCRIPTION
 + *
 + * The curl_easy_strerror function may be used to turn a CURLcode value
 + * into the equivalent human readable error string.  This is useful
 + * for printing meaningful error messages.
 + */
 +CURL_EXTERN const char *curl_easy_strerror(CURLcode);
 +
 +/*
 + * NAME curl_share_strerror()
 + *
 + * DESCRIPTION
 + *
 + * The curl_share_strerror function may be used to turn a CURLSHcode value
 + * into the equivalent human readable error string.  This is useful
 + * for printing meaningful error messages.
 + */
 +CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
 +
 +/*
 + * NAME curl_easy_pause()
 + *
 + * DESCRIPTION
 + *
 + * The curl_easy_pause function pauses or unpauses transfers. Select the new
 + * state by setting the bitmask, use the convenience defines below.
 + *
 + */
 +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
 +
 +#define CURLPAUSE_RECV      (1<<0)
 +#define CURLPAUSE_RECV_CONT (0)
 +
 +#define CURLPAUSE_SEND      (1<<2)
 +#define CURLPAUSE_SEND_CONT (0)
 +
 +#define CURLPAUSE_ALL       (CURLPAUSE_RECV|CURLPAUSE_SEND)
 +#define CURLPAUSE_CONT      (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
 +
 +#ifdef  __cplusplus
 +}
 +#endif
 +
 +/* unfortunately, the easy.h and multi.h include files need options and info
 +  stuff before they can be included! */
 +#include "easy.h" /* nothing in curl is fun without the easy stuff */
 +#include "multi.h"
 +
 +/* the typechecker doesn't work in C++ (yet) */
 +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
 +    ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \
 +    !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK)
 +#include "typecheck-gcc.h"
 +#else
 +#if defined(__STDC__) && (__STDC__ >= 1)
 +#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 18dc356,0000000..a47c454
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 - 2017, 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 - 2017 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.56.0"
++#define LIBCURL_VERSION "7.58.0"
 +
 +/* The numeric version number is also available "in parts" by using these
 +   defines: */
 +#define LIBCURL_VERSION_MAJOR 7
- #define LIBCURL_VERSION_MINOR 56
++#define LIBCURL_VERSION_MINOR 58
 +#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 0x073800
++#define LIBCURL_VERSION_NUM 0x073A00
 +
 +/*
 + * 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_AT_LEAST_VERSION(x,y,z) \
 +  (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
 +
 +#endif /* __CURL_CURLVER_H */
diff --cc Utilities/cmcurl/lib/CMakeLists.txt
index f3d9084,0000000..9f19daa
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/CMakeLists.txt
+++ b/Utilities/cmcurl/lib/CMakeLists.txt
@@@ -1,139 -1,0 +1,156 @@@
 +set(LIB_NAME cmcurl)
 +
 +configure_file(curl_config.h.cmake
 +  ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
 +
 +transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
 +include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake)
 +
 +list(APPEND HHEADERS
 +  ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h
 +  )
 +
 +if(MSVC AND NOT CURL_STATICLIB)
 +  list(APPEND CSOURCES libcurl.rc)
 +  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4127")
 +endif()
 +
 +# SET(CSOURCES
 +# #  memdebug.c -not used
 +# # nwlib.c - Not used
 +# # strtok.c - specify later
 +# # strtoofft.c - specify later
 +# )
 +
 +# # if we have Kerberos 4, right now this is never on
 +# #OPTION(CURL_KRB4 "Use Kerberos 4" OFF)
 +# IF(CURL_KRB4)
 +# SET(CSOURCES ${CSOURCES}
 +# krb4.c
 +# security.c
 +# )
 +# ENDIF(CURL_KRB4)
 +
 +# #OPTION(CURL_MALLOC_DEBUG "Debug mallocs in Curl" OFF)
 +# MARK_AS_ADVANCED(CURL_MALLOC_DEBUG)
 +# IF(CURL_MALLOC_DEBUG)
 +# SET(CSOURCES ${CSOURCES}
 +# memdebug.c
 +# )
 +# ENDIF(CURL_MALLOC_DEBUG)
 +
 +# # only build compat strtoofft if we need to
 +# IF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64)
 +# SET(CSOURCES ${CSOURCES}
 +# strtoofft.c
 +# )
 +# ENDIF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64)
 +
 +
 +# The rest of the build
 +
 +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include)
 +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
 +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
 +include_directories(${CMAKE_CURRENT_BINARY_DIR}/..)
 +include_directories(${CMAKE_CURRENT_SOURCE_DIR})
 +include_directories(${CMAKE_CURRENT_BINARY_DIR})
 +if(USE_ARES)
 +  include_directories(${CARES_INCLUDE_DIR})
 +endif()
 +
 +if(CURL_STATICLIB)
 +  # Static lib
 +  set(CURL_USER_DEFINED_DYNAMIC_OR_STATIC STATIC)
 +else()
 +  # DLL / so dynamic lib
 +  set(CURL_USER_DEFINED_DYNAMIC_OR_STATIC SHARED)
 +endif()
 +
 +# For windows we want to install OPENSSL_LIBRARIES dlls
 +# and also copy them into the build tree so that testing
 +# can find them.
 +if(CMAKE_USE_OPENSSL AND OPENSSL_FOUND AND WIN32)
 +  find_file(CMAKE_EAY_DLL NAME libeay32.dll HINTS ${OPENSSL_INCLUDE_DIR}/..)
 +  find_file(CMAKE_SSL_DLL NAME ssleay32.dll HINTS ${OPENSSL_INCLUDE_DIR}/..)
 +  mark_as_advanced(CMAKE_EAY_DLL CMAKE_SSL_DLL)
 +  if(CMAKE_SSL_DLL AND CMAKE_EAY_DLL)
 +    set(CMAKE_CURL_SSL_DLLS ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/libeay32.dll
 +      ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/ssleay32.dll)
 +    add_custom_command(OUTPUT
 +      ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/libeay32.dll
 +      DEPENDS ${CMAKE_EAY_DLL}
 +      COMMAND ${CMAKE_COMMAND} -E copy  ${CMAKE_EAY_DLL}
 +      ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/libeay32.dll)
 +    add_custom_command(OUTPUT
 +      ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/ssleay32.dll
 +      DEPENDS ${CMAKE_SSL_DLL}
 +      COMMAND ${CMAKE_COMMAND} -E copy  ${CMAKE_SSL_DLL}
 +      ${CMake_BIN_DIR}/${CMAKE_CFG_INTDIR}/ssleay32.dll)
 +    install(PROGRAMS ${CMAKE_EAY_DLL} ${CMAKE_SSL_DLL} DESTINATION bin)
 +  endif()
 +endif()
 +
 +add_library(
 +  ${LIB_NAME}
 +  ${CURL_USER_DEFINED_DYNAMIC_OR_STATIC}
 +  ${HHEADERS} ${CSOURCES}
 +  ${CMAKE_CURL_SSL_DLLS}
 +  )
 +
 +target_link_libraries(${LIB_NAME} ${CURL_LIBS})
 +
 +if(0) # This code not needed for building within CMake.
 +if(WIN32)
 +  add_definitions( -D_USRDLL )
 +endif()
 +endif()
 +
 +set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL)
 +
 +if(0) # This code not needed for building within CMake.
 +if(HIDES_CURL_PRIVATE_SYMBOLS)
 +  set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
 +  set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE})
 +endif()
 +
 +# Remove the "lib" prefix since the library is already named "libcurl".
 +set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
 +set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "")
 +
 +if(WIN32)
 +  if(NOT CURL_STATICLIB)
 +    # Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib"
 +    set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
 +
 +    set_target_properties (${LIB_NAME} PROPERTIES
 +       DEBUG_POSTFIX "-d"
 +       # Note: no postfix for release variants, let user choose what style of release he wants
 +       # MINSIZEREL_POSTFIX "-z"
 +       # RELWITHDEBINFO_POSTFIX "-g"
 +       )
 +  endif()
 +endif()
 +
++target_include_directories(${LIB_NAME} INTERFACE
++	$<INSTALL_INTERFACE:include>)
++
 +install(TARGETS ${LIB_NAME}
++  EXPORT libcurl-target
 +  ARCHIVE DESTINATION lib
 +  LIBRARY DESTINATION lib
-   RUNTIME DESTINATION bin)
++  RUNTIME DESTINATION bin
++)
++
++export(TARGETS ${LIB_NAME}
++       APPEND FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
++       NAMESPACE CURL::
++)
++
++install(EXPORT libcurl-target
++        FILE libcurl-target.cmake
++        NAMESPACE CURL::
++        DESTINATION ${CURL_INSTALL_CMAKE_DIR}
++)
++
 +endif()
diff --cc Utilities/cmcurl/lib/curl_config.h.cmake
index abe9ffe,0000000..1d1e3d7
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@@ -1,1000 -1,0 +1,1000 @@@
 +/* 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 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 `getpwuid' function. */
 +#cmakedefine HAVE_GETPWUID 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
 +
- /* Define to 1 if you have the <limits.h> header file. */
- #cmakedefine HAVE_LIMITS_H 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 `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 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
 +
 +/* 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_path.c
index 0000000,e843dea..e843dea
mode 000000,100644..100644
--- a/Utilities/cmcurl/lib/curl_path.c
+++ b/Utilities/cmcurl/lib/curl_path.c
diff --cc Utilities/cmcurl/lib/curl_setup.h
index 5880dc0,0000000..16e1ccd
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@@ -1,777 -1,0 +1,786 @@@
 +#ifndef HEADER_CURL_SETUP_H
 +#define HEADER_CURL_SETUP_H
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
-  * 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
 + * 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
 +#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 <windows.h>
 +#  ifdef HAVE_WINSOCK2_H
 +#    include <winsock2.h>
 +#    ifdef HAVE_WS2TCPIP_H
 +#      include <ws2tcpip.h>
 +#    endif
 +#  else
 +#    ifdef HAVE_WINSOCK_H
 +#      include <winsock.h>
 +#    endif
 +#  endif
 +#  include <tchar.h>
 +#  ifdef UNICODE
 +     typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
 +#  endif
 +#endif
 +
 +/*
 + * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
 + * define USE_WINSOCK to 1 if we have and use WINSOCK  API, else
 + * undefine USE_WINSOCK.
 + */
 +
 +#undef USE_WINSOCK
 +
 +#ifdef HAVE_WINSOCK2_H
 +#  define USE_WINSOCK 2
 +#else
 +#  ifdef HAVE_WINSOCK_H
 +#    define USE_WINSOCK 1
 +#  endif
 +#endif
 +
 +#ifdef USE_LWIPSOCK
 +#  include <lwip/init.h>
 +#  include <lwip/sockets.h>
 +#  include <lwip/netdb.h>
 +#endif
 +
 +#ifdef HAVE_EXTRA_STRICMP_H
 +#  include <extra/stricmp.h>
 +#endif
 +
 +#ifdef HAVE_EXTRA_STRDUP_H
 +#  include <extra/strdup.h>
 +#endif
 +
 +#ifdef TPF
 +#  include <strings.h>    /* for bzero, strcasecmp, and strncasecmp */
 +#  include <string.h>     /* for strcpy and strlen */
 +#  include <stdlib.h>     /* for rand and srand */
 +#  include <sys/socket.h> /* for select and ioctl*/
 +#  include <netdb.h>      /* for in_addr_t definition */
 +#  include <tpf/sysapi.h> /* for tpf_process_signals */
 +   /* change which select is used for libcurl */
 +#  define select(a,b,c,d,e) tpf_select_libcurl(a,b,c,d,e)
 +#endif
 +
 +#ifdef __VXWORKS__
 +#  include <sockLib.h>    /* for generic BSD socket functions */
 +#  include <ioLib.h>      /* for basic I/O interface functions */
 +#endif
 +
 +#ifdef __AMIGA__
 +#  ifndef __ixemul__
 +#    include <exec/types.h>
 +#    include <exec/execbase.h>
 +#    include <proto/exec.h>
 +#    include <proto/dos.h>
 +#    define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
 +#  endif
 +#endif
 +
 +#include <stdio.h>
 +#ifdef HAVE_ASSERT_H
 +#include <assert.h>
 +#endif
 +
 +#ifdef __TANDEM /* for nsr-tandem-nsk systems */
 +#include <floss.h>
 +#endif
 +
 +#ifndef STDC_HEADERS /* no standard C headers! */
 +#include <curl/stdcheaders.h>
 +#endif
 +
 +#ifdef __POCC__
 +#  include <sys/types.h>
 +#  include <unistd.h>
 +#  define sys_nerr EILSEQ
 +#endif
 +
 +/*
 + * Salford-C kludge section (mostly borrowed from wxWidgets).
 + */
 +#ifdef __SALFORDC__
 +  #pragma suppress 353             /* Possible nested comments */
 +  #pragma suppress 593             /* Define not used */
 +  #pragma suppress 61              /* enum has no name */
 +  #pragma suppress 106             /* unnamed, unused parameter */
 +  #include <clib.h>
 +#endif
 +
 +/* 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
 +
 +/*
 + * 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))
++
 +/*
 + * 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
 +
 +#ifndef SIZEOF_TIME_T
 +/* assume default size of time_t to be 32 bit */
 +#define SIZEOF_TIME_T 4
 +#endif
 +
 +#define LIBIDN_REQUIRED_VERSION "0.4.1"
 +
 +#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
 +    defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_MBEDTLS) || \
 +    defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
 +    defined(USE_DARWINSSL) || defined(USE_GSKIT)
 +#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_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
 +
 +/*
 + * 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_WORKAROUNDS */
 +#  ifdef USE_RECV_BEFORE_SEND_WORKAROUND
 +#    undef USE_RECV_BEFORE_SEND_WORKAROUND
 +#  endif
 +#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
 +
 +/* Detect Windows App environment which has a restricted access
 + * to the Win32 APIs. */
- # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)
++# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
++  defined(WINAPI_FAMILY)
 +#  include <winapifamily.h>
- #  if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
++#  if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) &&  \
 +     !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
 +#    define CURL_WINDOWS_APP
 +#  endif
 +# endif
 +
 +#endif /* HEADER_CURL_SETUP_H */
diff --cc Utilities/cmcurl/lib/ftp.c
index 84ae37b,0000000..d3b0220
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@@ -1,4482 -1,0 +1,4481 @@@
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
 + * Copyright (C) 1998 - 2017, 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_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 /* flags */
++  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 /* flags */
++  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)
 +{
 +  int i;
 +  if(ftpc->dirs) {
 +    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 */
 +    error = data->set.fsockopt(data->set.sockopt_client,
 +                               s,
 +                               CURLSOCKTYPE_ACCEPT);
 +
 +    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 time_t ftp_timeleft_accept(struct Curl_easy *data)
++static timediff_t ftp_timeleft_accept(struct Curl_easy *data)
 +{
-   time_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
-   time_t other;
++  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_tvnow();
++  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_tvdiff(now, data->progress.t_acceptdata);
++    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);
 +  }
 +  else {
 +    /* FTP download: */
 +    Curl_setup_transfer(conn, SECONDARYSOCKET,
 +                        conn->proto.ftpc.retr_size_saved, FALSE,
 +                        ftp->bytecountp, -1, NULL); /* no upload here */
 +  }
 +
 +  conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
 +  state(conn, FTP_STOP);
 +
 +  return CURLE_OK;
 +}
 +
 +/***********************************************************************
 + *
 + * AllowServerConnect()
 + *
 + * When we've issue the PORT command, we have told the server to connect to
 + * us. This function checks whether data connection is established if so it is
 + * accepted.
 + *
 + */
 +static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
 +{
 +  struct 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];
 +  time_t timeout;              /* timeout in milliseconds */
 +  time_t interval_ms;
 +  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 */
 +    timeout = Curl_pp_state_timeout(pp);
 +
 +    if(timeout <= 0) {
 +      failf(data, "FTP response timeout");
 +      return CURLE_OPERATION_TIMEDOUT; /* already too little time */
 +    }
 +
 +    interval_ms = 1000;  /* use 1 second timeout intervals */
 +    if(timeout < interval_ms)
 +      interval_ms = timeout;
 +
 +    /*
 +     * Since this function is blocking, we need to wait here for input on the
 +     * connection and only then we call the response reading function. We do
 +     * timeout at least every second to make the timeout check run.
 +     *
 +     * A caution here is that the ftp_readresp() function has a cache that may
 +     * contain pieces of a response from the previous invoke and we need to
 +     * make sure we don't just wait for input while there is unhandled data in
 +     * that cache. But also, if the cache is there, we call ftp_readresp() and
 +     * the cache wasn't good enough to continue we must not just busy-loop
 +     * around this function.
 +     *
 +     */
 +
 +    if(pp->cache && (cache_skip < 2)) {
 +      /*
 +       * There's a cache left since before. We then skipping the wait for
 +       * socket action, unless this is the same cache like the previous round
 +       * as then the cache was deemed not enough to act on and we then need to
 +       * wait for more data anyway.
 +       */
 +    }
 +    else 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 *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) );
 +      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);
 +  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));
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* step 3, bind to a suitable local address */
 +
 +  memcpy(sa, ai->ai_addr, ai->ai_addrlen);
 +  sslen = ai->ai_addrlen;
 +
 +  for(port = port_min; port <= port_max;) {
 +    if(sa->sa_family == AF_INET)
 +      sa4->sin_port = htons(port);
 +#ifdef ENABLE_IPV6
 +    else
 +      sa6->sin6_port = htons(port);
 +#endif
 +    /* Try binding the given address. */
 +    if(bind(portsock, sa, sslen) ) {
 +      /* It failed. */
 +      error = SOCKERRNO;
 +      if(possibly_non_local && (error == EADDRNOTAVAIL)) {
 +        /* The requested bind address is not local.  Use the address used for
 +         * the control connection instead and restart the port loop
 +         */
 +
 +        infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
 +              Curl_strerror(conn, error) );
 +
 +        sslen = sizeof(ss);
 +        if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
 +          failf(data, "getsockname() failed: %s",
 +                Curl_strerror(conn, SOCKERRNO) );
 +          Curl_closesocket(conn, portsock);
 +          return CURLE_FTP_PORT_FAILED;
 +        }
 +        port = port_min;
 +        possibly_non_local = FALSE; /* don't try this again */
 +        continue;
 +      }
 +      if(error != EADDRINUSE && error != EACCES) {
 +        failf(data, "bind(port=%hu) failed: %s", port,
 +              Curl_strerror(conn, error) );
 +        Curl_closesocket(conn, portsock);
 +        return CURLE_FTP_PORT_FAILED;
 +      }
 +    }
 +    else
 +      break;
 +
 +    port++;
 +  }
 +
 +  /* maybe all ports were in use already*/
 +  if(port > port_max) {
 +    failf(data, "bind() failed, we ran out of ports!");
 +    Curl_closesocket(conn, portsock);
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* get the name again after the bind() so that we can extract the
 +     port number it uses now */
 +  sslen = sizeof(ss);
 +  if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
 +    failf(data, "getsockname() failed: %s",
 +          Curl_strerror(conn, SOCKERRNO) );
 +    Curl_closesocket(conn, portsock);
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* step 4, listen on the socket */
 +
 +  if(listen(portsock, 1)) {
 +    failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO));
 +    Curl_closesocket(conn, portsock);
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* step 5, send the proper FTP command */
 +
 +  /* get a plain printable version of the numerical address to work with
 +     below */
 +  Curl_printable_address(ai, myhost, sizeof(myhost));
 +
 +#ifdef ENABLE_IPV6
 +  if(!conn->bits.ftp_use_eprt && conn->bits.ipv6)
 +    /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the
 +       request and enable EPRT again! */
 +    conn->bits.ftp_use_eprt = TRUE;
 +#endif
 +
 +  for(; fcmd != DONE; fcmd++) {
 +
 +    if(!conn->bits.ftp_use_eprt && (EPRT == fcmd))
 +      /* if disabled, goto next */
 +      continue;
 +
 +    if((PORT == fcmd) && sa->sa_family != AF_INET)
 +      /* PORT is IPv4 only */
 +      continue;
 +
 +    switch(sa->sa_family) {
 +    case AF_INET:
 +      port = ntohs(sa4->sin_port);
 +      break;
 +#ifdef ENABLE_IPV6
 +    case AF_INET6:
 +      port = ntohs(sa6->sin6_port);
 +      break;
 +#endif
 +    default:
 +      continue; /* might as well skip this */
 +    }
 +
 +    if(EPRT == fcmd) {
 +      /*
 +       * Two fine examples from RFC2428;
 +       *
 +       * EPRT |1|132.235.1.2|6275|
 +       *
 +       * EPRT |2|1080::8:800:200C:417A|5282|
 +       */
 +
 +      result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
 +                             sa->sa_family == AF_INET?1:2,
 +                             myhost, port);
 +      if(result) {
 +        failf(data, "Failure sending EPRT command: %s",
 +              curl_easy_strerror(result));
 +        Curl_closesocket(conn, portsock);
 +        /* don't retry using PORT */
 +        ftpc->count1 = PORT;
 +        /* bail out */
 +        state(conn, FTP_STOP);
 +        return result;
 +      }
 +      break;
 +    }
 +    if(PORT == fcmd) {
 +      char *source = myhost;
 +      char *dest = tmp;
 +
 +      /* translate x.x.x.x to x,x,x,x */
 +      while(source && *source) {
 +        if(*source == '.')
 +          *dest = ',';
 +        else
 +          *dest = *source;
 +        dest++;
 +        source++;
 +      }
 +      *dest = 0;
 +      snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
 +
 +      result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
 +      if(result) {
 +        failf(data, "Failure sending PORT command: %s",
 +              curl_easy_strerror(result));
 +        Curl_closesocket(conn, portsock);
 +        /* bail out */
 +        state(conn, FTP_STOP);
 +        return result;
 +      }
 +      break;
 +    }
 +  }
 +
 +  /* store which command was sent */
 +  ftpc->count1 = fcmd;
 +
 +  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;
 +
 +  /* 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 = data->state.path;
 +
 +  lstArg = NULL;
 +  if((data->set.ftp_filemethod == FTPFILE_NOCWD) &&
-      data->state.path &&
-      data->state.path[0] &&
-      strchr(data->state.path, '/')) {
- 
-     lstArg = strdup(data->state.path);
-     if(!lstArg)
-       return CURLE_OUT_OF_MEMORY;
++     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(lstArg[strlen(lstArg) - 1] != '/') {
- 
++    if(inpath[n - 1] != '/') {
 +      /* chop off the file part if format is dir/dir/file */
-       slashPos = strrchr(lstArg, '/');
-       if(slashPos)
-         *(slashPos + 1) = '\0';
++      slashPos = strrchr(inpath, '/');
++      n = slashPos - inpath;
 +    }
++    result = Curl_urldecode(data, inpath, n, &lstArg, NULL, FALSE);
++    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 therefor many servers
 +       may not support it! It is however the only way we have to get a file's
 +       size! */
 +
 +    ftp->transfer = FTPTRANSFER_INFO;
 +    /* this means no actual transfer will be made */
 +
 +    /* Some servers return different sizes for different modes, and thus we
 +       must set the proper type before we check the size */
 +    result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE);
 +    if(result)
 +      return result;
 +  }
 +  else
 +    result = ftp_state_size(conn);
 +
 +  return result;
 +}
 +
 +/* This is called after the CWD commands have been done in the beginning of
 +   the DO phase */
 +static CURLcode ftp_state_mdtm(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct 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;
 +  int seekerr = CURL_SEEKFUNC_OK;
 +
 +  if((data->state.resume_from && !sizechecked) ||
 +     ((data->state.resume_from > 0) && sizechecked)) {
 +    /* we're about to continue the uploading of a file */
 +    /* 1. get already existing file's size. We use the SIZE command for this
 +       which may not exist in the server!  The SIZE command is not in
 +       RFC959. */
 +
 +    /* 2. This used to set REST. But since we can do append, we
 +       don't another ftp command. We just skip the source file
 +       offset and then we APPEND the rest on the file instead */
 +
 +    /* 3. pass file-size number of bytes in the source file */
 +    /* 4. lower the infilesize counter */
 +    /* => transfer as usual */
 +
 +    if(data->state.resume_from < 0) {
 +      /* Got no given size to start from, figure it out */
 +      PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
 +      state(conn, FTP_STOR_SIZE);
 +      return result;
 +    }
 +
 +    /* enable append */
 +    data->set.ftp_append = TRUE;
 +
 +    /* Let's read off the proper amount of bytes from the input. */
 +    if(conn->seek_func) {
 +      seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
 +                                SEEK_SET);
 +    }
 +
 +    if(seekerr != CURL_SEEKFUNC_OK) {
 +      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);
 +
 +        /* 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) {
 +    /* 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 */
-     int ip[4];
-     int port[2];
++    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, "%d,%d,%d,%d,%d,%d",
++      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) {
++    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 %d.%d.%d.%d 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("%d.%d.%d.%d", 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);
 +    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);
 +    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);
 +        /* now, convert this into a time() value: */
 +        data->info.filetime = (long)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 = (time_t)data->info.filetime;
 +        struct tm buffer;
 +        const struct tm *tm = &buffer;
 +
 +        result = Curl_gmtime(filetime, &buffer);
 +        if(result)
 +          return result;
 +
 +        /* format: "Tue, 15 Nov 1994 12:45:26" */
 +        snprintf(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);
 +      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);
 +      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);
++      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;
 +        char *store;
 +        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 */
 +          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);
 +
 +  /* 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);
 +    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;
 +  const char *path_to_use = data->state.path;
 +
 +  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->set.wildcardmatch) {
++  if(data->state.wildcardmatch) {
 +    if(data->set.chunk_end && ftpc->file) {
 +      data->set.chunk_end(data->wildcard.customptr);
 +    }
 +    ftpc->known_filesize = -1;
 +  }
 +
 +  if(!result)
 +    /* get the "raw" path */
 +    result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
 +  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 {
 +        /* we never changed dir */
 +        ftpc->prevpath = strdup("");
 +        free(path);
 +      }
 +      if(ftpc->prevpath)
 +        infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath);
 +    }
 +    else {
 +      ftpc->prevpath = NULL; /* no path */
 +      free(path);
 +    }
 +  }
 +  /* free the dir tree and file parts */
 +  freedirs(ftpc);
 +
 +  /* shut down the socket to inform the server we're done */
 +
 +#ifdef _WIN32_WCE
 +  shutdown(conn->sock[SECONDARYSOCKET], 2);  /* SD_BOTH */
 +#endif
 +
 +  if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
 +    if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
 +      /* partial download completed */
 +      result = Curl_pp_sendf(pp, "%s", "ABOR");
 +      if(result) {
 +        failf(data, "Failure sending ABOR command: %s",
 +              curl_easy_strerror(result));
 +        ftpc->ctl_valid = FALSE; /* mark control connection as bad */
 +        connclose(conn, "ABOR command failed"); /* connection closure */
 +      }
 +    }
 +
 +    if(conn->ssl[SECONDARYSOCKET].use) {
 +      /* The secondary socket is using SSL so we must close down that part
 +         first before we close the socket for real */
 +      Curl_ssl_close(conn, SECONDARYSOCKET);
 +
 +      /* Note that we keep "use" set to TRUE since that (next) connection is
 +         still requested to use SSL */
 +    }
 +    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_tvnow(); /* timeout relative 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->set.crlf &&
 +       (ftp->transfer == FTPTRANSFER_BODY)) {
 +      failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
 +            " out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
 +            *ftp->bytecountp, data->state.infilesize);
 +      result = CURLE_PARTIAL_FILE;
 +    }
 +  }
 +  else {
 +    if((-1 != data->req.size) &&
 +       (data->req.size != *ftp->bytecountp) &&
 +#ifdef CURL_DO_LINEEND_CONV
 +       /* Most FTP servers don't adjust their file SIZE response for CRLFs, so
 +        * we'll check to see if the discrepancy can be explained by the number
 +        * of CRLFs we've changed to LFs.
 +        */
 +       ((data->req.size + data->state.crlf_conversions) !=
 +        *ftp->bytecountp) &&
 +#endif /* CURL_DO_LINEEND_CONV */
 +       (data->req.maxdownload != *ftp->bytecountp)) {
 +      failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
 +            " bytes", *ftp->bytecountp);
 +      result = CURLE_PARTIAL_FILE;
 +    }
 +    else if(!ftpc->dont_check &&
 +            !*ftp->bytecountp &&
 +            (data->req.size>0)) {
 +      failf(data, "No data was received!");
 +      result = CURLE_FTP_COULDNT_RETR_FILE;
 +    }
 +  }
 +
 +  /* clear these for next connection */
 +  ftp->transfer = FTPTRANSFER_BODY;
 +  ftpc->dont_check = FALSE;
 +
 +  /* Send any post-transfer QUOTE strings? */
 +  if(!status && !result && !premature && data->set.postquote)
 +    result = ftp_sendquote(conn, data->set.postquote);
 +
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_sendquote()
 + *
 + * Where a 'quote' means a list of custom commands to send to the server.
 + * The quote list is passed as an argument.
 + *
 + * BLOCKING
 + */
 +
 +static
 +CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
 +{
 +  struct curl_slist *item;
 +  ssize_t nread;
 +  int ftpcode;
 +  CURLcode result;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +
 +  item = quote;
 +  while(item) {
 +    if(item->data) {
 +      char *cmd = item->data;
 +      bool acceptfail = FALSE;
 +
 +      /* if a command starts with an asterisk, which a legal FTP command never
 +         can, the command will be allowed to fail without it causing any
 +         aborts or cancels etc. It will cause libcurl to act as if the command
 +         is successful, whatever the server reponds. */
 +
 +      if(cmd[0] == '*') {
 +        cmd++;
 +        acceptfail = TRUE;
 +      }
 +
 +      PPSENDF(&conn->proto.ftpc.pp, "%s", cmd);
 +
-       pp->response = Curl_tvnow(); /* timeout relative now */
++      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
 +
 +/*
 +  Check if this is a range download, and if so, set the internal variables
 +  properly.
 + */
 +
 +static CURLcode ftp_range(struct connectdata *conn)
 +{
 +  curl_off_t from, to;
 +  char *ptr;
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if(data->state.use_range && data->state.range) {
 +    CURLofft from_t;
 +    CURLofft to_t;
 +    from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
 +    if(from_t == CURL_OFFT_FLOW)
 +      return CURLE_RANGE_ERROR;
 +    while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
 +      ptr++;
 +    to_t = curlx_strtoofft(ptr, NULL, 0, &to);
 +    if(to_t == CURL_OFFT_FLOW)
 +      return CURLE_RANGE_ERROR;
 +    if((to_t == CURL_OFFT_INVAL) && !from_t) {
 +      /* X - */
 +      data->state.resume_from = from;
 +      DEBUGF(infof(conn->data, "FTP RANGE %" CURL_FORMAT_CURL_OFF_T
 +                   " to end of file\n", from));
 +    }
 +    else if(!to_t && (from_t == CURL_OFFT_INVAL)) {
 +      /* -Y */
 +      data->req.maxdownload = to;
 +      data->state.resume_from = -to;
 +      DEBUGF(infof(conn->data, "FTP RANGE the last %" CURL_FORMAT_CURL_OFF_T
 +                   " bytes\n", to));
 +    }
 +    else {
 +      /* X-Y */
 +      data->req.maxdownload = (to - from) + 1; /* include last byte */
 +      data->state.resume_from = from;
 +      DEBUGF(infof(conn->data, "FTP RANGE from %" CURL_FORMAT_CURL_OFF_T
 +                   " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
 +                   from, data->req.maxdownload));
 +    }
 +    DEBUGF(infof(conn->data, "range-download from %" CURL_FORMAT_CURL_OFF_T
 +                 " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
 +                 CURL_FORMAT_CURL_OFF_T " bytes\n",
 +                 from, to, data->req.maxdownload));
 +    ftpc->dont_check = TRUE; /* don't check for successful transfer */
 +  }
 +  else
 +    data->req.maxdownload = -1;
 +  return CURLE_OK;
 +}
 +
 +
 +/*
 + * ftp_do_more()
 + *
 + * This function shall be called when the second FTP (data) connection is
 + * connected.
 + *
 + * 'complete' can return 0 for incomplete, 1 for done and -1 for go back
 + * (which basically is only for when PASV is being sent to retry a failed
 + * EPSV).
 + */
 +
 +static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
 +{
 +  struct 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 */
 +      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 = ftp_range(conn);
 +      if(result)
 +        ;
 +      else if(data->set.ftp_list_only || !ftpc->file) {
 +        /* The specified path ends with a slash, and therefore we think this
 +           is a directory that is requested, use LIST. But before that we
 +           need to set ASCII transfer mode. */
 +
 +        /* But only if a body transfer was requested. */
 +        if(ftp->transfer == FTPTRANSFER_BODY) {
 +          result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE);
 +          if(result)
 +            return result;
 +        }
 +        /* otherwise just fall through */
 +      }
 +      else {
 +        result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE);
 +        if(result)
 +          return result;
 +      }
 +
 +      result = ftp_multi_statemach(conn, &complete);
 +      *completep = (int)complete;
 +    }
 +    return result;
 +  }
 +
 +  if(!result && (ftp->transfer != FTPTRANSFER_BODY))
 +    /* no data to transfer. FIX: it feels like a kludge to have this here
 +       too! */
 +    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
 +
 +  if(!ftpc->wait_data_conn) {
 +    /* no waiting for the data connection so this is now complete */
 +    *completep = 1;
 +    DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result));
 +  }
 +
 +  return result;
 +}
 +
 +
 +
 +/***********************************************************************
 + *
 + * ftp_perform()
 + *
 + * This is the actual DO function for FTP. Get a file/directory according to
 + * the options previously setup.
 + */
 +
 +static
 +CURLcode ftp_perform(struct connectdata *conn,
 +                     bool *connected,  /* connect status after PASV / PORT */
 +                     bool *dophase_done)
 +{
 +  /* this is FTP and no proxy */
 +  CURLcode result = CURLE_OK;
 +
 +  DEBUGF(infof(conn->data, "DO phase starts\n"));
 +
 +  if(conn->data->set.opt_no_body) {
 +    /* requested no body means no transfer... */
 +    struct FTP *ftp = conn->data->req.protop;
 +    ftp->transfer = FTPTRANSFER_INFO;
 +  }
 +
 +  *dophase_done = FALSE; /* not done yet */
 +
 +  /* start the first command in the DO phase */
 +  result = ftp_state_quote(conn, TRUE, FTP_QUOTE);
 +  if(result)
 +    return result;
 +
 +  /* run the state-machine */
 +  result = ftp_multi_statemach(conn, dophase_done);
 +
 +  *connected = conn->bits.tcpconnect[SECONDARYSOCKET];
 +
 +  infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected);
 +
 +  if(*dophase_done) {
 +    DEBUGF(infof(conn->data, "DO phase is complete1\n"));
 +  }
 +
 +  return result;
 +}
 +
 +static void wc_data_dtor(void *ptr)
 +{
 +  struct ftp_wc_tmpdata *tmp = ptr;
 +  if(tmp)
 +    Curl_ftp_parselist_data_free(&tmp->parser);
 +  free(tmp);
 +}
 +
 +static CURLcode init_wc_data(struct connectdata *conn)
 +{
 +  char *last_slash;
 +  char *path = conn->data->state.path;
 +  struct WildcardData *wildcard = &(conn->data->wildcard);
 +  CURLcode result = CURLE_OK;
 +  struct ftp_wc_tmpdata *ftp_tmp;
 +
 +  last_slash = strrchr(conn->data->state.path, '/');
 +  if(last_slash) {
 +    last_slash++;
 +    if(last_slash[0] == '\0') {
 +      wildcard->state = CURLWC_CLEAN;
 +      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 temporary wildcard data */
 +  ftp_tmp = calloc(1, sizeof(struct ftp_wc_tmpdata));
 +  if(!ftp_tmp) {
 +    Curl_safefree(wildcard->pattern);
 +    return CURLE_OUT_OF_MEMORY;
 +  }
 +
 +  /* INITIALIZE parselist structure */
 +  ftp_tmp->parser = Curl_ftp_parselist_data_alloc();
 +  if(!ftp_tmp->parser) {
 +    Curl_safefree(wildcard->pattern);
 +    free(ftp_tmp);
 +    return CURLE_OUT_OF_MEMORY;
 +  }
 +
 +  wildcard->tmp = ftp_tmp; /* put it to the WildcardData tmp pointer */
 +  wildcard->tmp_dtor = wc_data_dtor;
 +
 +  /* wildcard does not support NOCWD option (assert it?) */
 +  if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD)
 +    conn->data->set.ftp_filemethod = FTPFILE_MULTICWD;
 +
 +  /* try to parse ftp url */
 +  result = ftp_parse_url_path(conn);
 +  if(result) {
 +    Curl_safefree(wildcard->pattern);
 +    wildcard->tmp_dtor(wildcard->tmp);
 +    wildcard->tmp_dtor = ZERO_NULL;
 +    wildcard->tmp = NULL;
 +    return result;
 +  }
 +
 +  wildcard->path = strdup(conn->data->state.path);
 +  if(!wildcard->path) {
 +    Curl_safefree(wildcard->pattern);
 +    wildcard->tmp_dtor(wildcard->tmp);
 +    wildcard->tmp_dtor = ZERO_NULL;
 +    wildcard->tmp = NULL;
 +    return CURLE_OUT_OF_MEMORY;
 +  }
 +
 +  /* backup old write_function */
 +  ftp_tmp->backup.write_function = conn->data->set.fwrite_func;
 +  /* parsing write function */
 +  conn->data->set.fwrite_func = Curl_ftp_parselist;
 +  /* backup old file descriptor */
 +  ftp_tmp->backup.file_descriptor = conn->data->set.out;
 +  /* let the writefunc callback know what curl pointer is working with */
 +  conn->data->set.out = conn;
 +
 +  infof(conn->data, "Wildcard - Parsing started\n");
 +  return CURLE_OK;
 +}
 +
 +/* This is called recursively */
 +static CURLcode wc_statemach(struct connectdata *conn)
 +{
 +  struct WildcardData * const wildcard = &(conn->data->wildcard);
 +  CURLcode 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_tmpdata *ftp_tmp = wildcard->tmp;
 +    conn->data->set.fwrite_func = ftp_tmp->backup.write_function;
 +    conn->data->set.out = ftp_tmp->backup.file_descriptor;
 +    ftp_tmp->backup.write_function = ZERO_NULL;
 +    ftp_tmp->backup.file_descriptor = NULL;
 +    wildcard->state = CURLWC_DOWNLOADING;
 +
 +    if(Curl_ftp_parselist_geterror(ftp_tmp->parser)) {
 +      /* error found in LIST parsing */
 +      wildcard->state = CURLWC_CLEAN;
 +      return wc_statemach(conn);
 +    }
 +    if(wildcard->filelist.size == 0) {
 +      /* no corresponding file */
 +      wildcard->state = CURLWC_CLEAN;
 +      return CURLE_REMOTE_FILE_NOT_FOUND;
 +    }
 +    return wc_statemach(conn);
 +  }
 +
 +  case CURLWC_DOWNLOADING: {
 +    /* filelist has at least one file, lets get first one */
 +    struct ftp_conn *ftpc = &conn->proto.ftpc;
 +    struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
 +
 +    char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
 +    if(!tmp_path)
 +      return CURLE_OUT_OF_MEMORY;
 +
 +    /* switch default "state.pathbuffer" and tmp_path, good to see
 +       ftp_parse_url_path function to understand this trick */
 +    Curl_safefree(conn->data->state.pathbuffer);
 +    conn->data->state.pathbuffer = tmp_path;
 +    conn->data->state.path = tmp_path;
 +
 +    infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
 +    if(conn->data->set.chunk_bgn) {
 +      long userresponse = conn->data->set.chunk_bgn(
 +        finfo, wildcard->customptr, (int)wildcard->filelist.size);
 +      switch(userresponse) {
 +      case CURL_CHUNK_BGN_FUNC_SKIP:
 +        infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
 +              finfo->filename);
 +        wildcard->state = CURLWC_SKIP;
 +        return wc_statemach(conn);
 +      case CURL_CHUNK_BGN_FUNC_FAIL:
 +        return CURLE_CHUNK_FAILED;
 +      }
 +    }
 +
 +    if(finfo->filetype != CURLFILETYPE_FILE) {
 +      wildcard->state = CURLWC_SKIP;
 +      return wc_statemach(conn);
 +    }
 +
 +    if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
 +      ftpc->known_filesize = finfo->size;
 +
 +    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)
 +      conn->data->set.chunk_end(conn->data->wildcard.customptr);
 +    Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
 +    wildcard->state = (wildcard->filelist.size == 0) ?
 +                      CURLWC_CLEAN : CURLWC_DOWNLOADING;
 +    return wc_statemach(conn);
 +  }
 +
 +  case CURLWC_CLEAN: {
 +    struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
 +    result = CURLE_OK;
 +    if(ftp_tmp)
 +      result = Curl_ftp_parselist_geterror(ftp_tmp->parser);
 +
 +    wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
 +  } break;
 +
 +  case CURLWC_DONE:
 +  case CURLWC_ERROR:
 +  case CURLWC_CLEAR:
 +    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->set.wildcardmatch) {
++  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
 +
 +  write_len = strlen(cmd);
 +  if(write_len > (sizeof(s) -3))
 +    return CURLE_BAD_FUNCTION_ARGUMENT;
 +
 +  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, conn);
 +
 +    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 = data->state.path;
 +  const char *cur_pos;
 +  const char *filename = NULL;
 +
 +  cur_pos = path_to_use; /* current position in path. point at the begin of
 +                            next path component */
 +
 +  ftpc->ctl_valid = FALSE;
 +  ftpc->cwdfail = FALSE;
 +
 +  switch(data->set.ftp_filemethod) {
 +  case FTPFILE_NOCWD:
 +    /* fastest, but less standard-compliant */
 +
 +    /*
 +      The best time to check whether the path is a file or directory is right
 +      here. so:
 +
 +      the first condition in the if() right here, is there just in case
 +      someone decides to set path to NULL one day
 +   */
 +    if(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,
 +                              FALSE);
 +      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 - data->state.path > 0) &&
 +                                (ftpc->dirdepth == 0))?1:0;
 +
 +        /* seek out the next path component */
 +        if(slash_pos-cur_pos) {
 +          /* we skip empty path components, like "x//y" since the FTP command
 +             CWD requires a parameter and a non-existent parameter a) doesn't
 +             work on many servers and b) has no effect on the others. */
 +          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, data->state.path, 0, &path, &dlen, FALSE);
 +    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);
 +  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;
 +  char command;
 +  struct FTP *ftp;
 +
 +  conn->data->req.protop = ftp = malloc(sizeof(struct FTP));
 +  if(NULL == ftp)
 +    return CURLE_OUT_OF_MEMORY;
 +
 +  data->state.path++;   /* don't include the initial slash */
 +  data->state.slash_removed = TRUE; /* we've skipped the slash */
 +
 +  /* FTP URLs support an extension like ";type=<typecode>" that
 +   * we'll try to get now! */
 +  type = strstr(data->state.path, ";type=");
 +
 +  if(!type)
 +    type = strstr(conn->host.rawalloc, ";type=");
 +
 +  if(type) {
 +    *type = 0;                     /* it was in the middle of the hostname */
 +    command = Curl_raw_toupper(type[6]);
 +    conn->bits.type_set = TRUE;
 +
 +    switch(command) {
 +    case 'A': /* ASCII mode */
 +      data->set.prefer_ascii = TRUE;
 +      break;
 +
 +    case 'D': /* directory mode */
 +      data->set.ftp_list_only = TRUE;
 +      break;
 +
 +    case 'I': /* binary mode */
 +    default:
 +      /* switch off ASCII */
 +      data->set.prefer_ascii = FALSE;
 +      break;
 +    }
 +  }
 +
 +  /* get some initial data into the ftp struct */
 +  ftp->bytecountp = &conn->data->req.bytecount;
 +  ftp->transfer = FTPTRANSFER_BODY;
 +  ftp->downloadsize = 0;
 +
 +  /* No need to duplicate user+password, the connectdata struct won't change
 +     during a session, but we re-init them here since on subsequent inits
 +     since the conn struct may have changed or been replaced.
 +  */
 +  ftp->user = conn->user;
 +  ftp->passwd = conn->passwd;
 +  if(isBadFtpString(ftp->user))
 +    return CURLE_URL_MALFORMAT;
 +  if(isBadFtpString(ftp->passwd))
 +    return CURLE_URL_MALFORMAT;
 +
 +  conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
 +
 +  return CURLE_OK;
 +}
 +
 +#endif /* CURL_DISABLE_FTP */
diff --cc Utilities/cmcurl/lib/select.c
index b8e1868,0000000..0406dd2
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/select.c
+++ b/Utilities/cmcurl/lib/select.c
@@@ -1,583 -1,0 +1,583 @@@
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
 + * Copyright (C) 1998 - 2017, 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"
 +
 +#ifdef HAVE_SYS_SELECT_H
 +#include <sys/select.h>
 +#endif
 +
 +#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
 +#error "We can't compile without select() or poll() support."
 +#endif
 +
 +#if defined(__BEOS__)
 +/* BeOS has FD_SET defined in socket.h */
 +#include <socket.h>
 +#endif
 +
 +#ifdef MSDOS
 +#include <dos.h>  /* delay() */
 +#endif
 +
 +#ifdef __VXWORKS__
 +#include <strings.h>  /* bzero() in FD_SET */
 +#endif
 +
 +#include <curl/curl.h>
 +
 +#include "urldata.h"
 +#include "connect.h"
 +#include "select.h"
 +#include "warnless.h"
 +
 +/* Convenience local macros */
- #define ELAPSED_MS()  (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
++#define ELAPSED_MS() (int)Curl_timediff(Curl_now(), initial_tv)
 +
 +int Curl_ack_eintr = 0;
 +#define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR)
 +
 +/*
 + * Internal function used for waiting a specific amount of ms
 + * in Curl_socket_check() and Curl_poll() when no file descriptor
 + * is provided to wait on, just being used to delay execution.
 + * WinSock select() and poll() timeout mechanisms need a valid
 + * socket descriptor in a not null file descriptor set to work.
 + * Waiting indefinitely with this function is not allowed, a
 + * zero or negative timeout value will return immediately.
 + * Timeout resolution, accuracy, as well as maximum supported
 + * value is system dependent, neither factor is a citical issue
 + * for the intended use of this function in the library.
 + *
 + * Return values:
 + *   -1 = system call error, invalid timeout value, or interrupted
 + *    0 = specified timeout has elapsed
 + */
 +int Curl_wait_ms(int timeout_ms)
 +{
 +#if !defined(MSDOS) && !defined(USE_WINSOCK)
 +#ifndef HAVE_POLL_FINE
 +  struct timeval pending_tv;
 +#endif
 +  struct curltime initial_tv;
 +  int pending_ms;
 +  int error;
 +#endif
 +  int r = 0;
 +
 +  if(!timeout_ms)
 +    return 0;
 +  if(timeout_ms < 0) {
 +    SET_SOCKERRNO(EINVAL);
 +    return -1;
 +  }
 +#if defined(MSDOS)
 +  delay(timeout_ms);
 +#elif defined(USE_WINSOCK)
 +  Sleep(timeout_ms);
 +#else
 +  pending_ms = timeout_ms;
-   initial_tv = curlx_tvnow();
++  initial_tv = Curl_now();
 +  do {
 +#if defined(HAVE_POLL_FINE)
 +    r = poll(NULL, 0, pending_ms);
 +#else
 +    pending_tv.tv_sec = pending_ms / 1000;
 +    pending_tv.tv_usec = (pending_ms % 1000) * 1000;
 +    r = select(0, NULL, NULL, NULL, &pending_tv);
 +#endif /* HAVE_POLL_FINE */
 +    if(r != -1)
 +      break;
 +    error = SOCKERRNO;
 +    if(error && ERROR_NOT_EINTR(error))
 +      break;
 +    pending_ms = timeout_ms - ELAPSED_MS();
 +    if(pending_ms <= 0) {
 +      r = 0;  /* Simulate a "call timed out" case */
 +      break;
 +    }
 +  } while(r == -1);
 +#endif /* USE_WINSOCK */
 +  if(r)
 +    r = -1;
 +  return r;
 +}
 +
 +/*
 + * Wait for read or write events on a set of file descriptors. It uses poll()
 + * when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
 + * otherwise select() is used.  An error is returned if select() is being used
 + * and a file descriptor is too large for FD_SETSIZE.
 + *
 + * A negative timeout value makes this function wait indefinitely,
 + * unless no valid file descriptor is given, when this happens the
 + * negative timeout is ignored and the function times out immediately.
 + *
 + * Return values:
 + *   -1 = system call error or fd >= FD_SETSIZE
 + *    0 = timeout
 + *    [bitmask] = action as described below
 + *
 + * CURL_CSELECT_IN - first socket is readable
 + * CURL_CSELECT_IN2 - second socket is readable
 + * CURL_CSELECT_OUT - write socket is writable
 + * CURL_CSELECT_ERR - an error condition occurred
 + */
 +int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
 +                      curl_socket_t readfd1,
 +                      curl_socket_t writefd, /* socket to write to */
 +                      time_t timeout_ms)     /* milliseconds to wait */
 +{
 +#ifdef HAVE_POLL_FINE
 +  struct pollfd pfd[3];
 +  int num;
 +#else
 +  struct timeval pending_tv;
 +  struct timeval *ptimeout;
 +  fd_set fds_read;
 +  fd_set fds_write;
 +  fd_set fds_err;
 +  curl_socket_t maxfd;
 +#endif
 +  struct curltime initial_tv = {0, 0};
 +  int pending_ms = 0;
 +  int error;
 +  int r;
 +  int ret;
 +
 +#if SIZEOF_TIME_T != SIZEOF_INT
 +  /* wrap-around precaution */
 +  if(timeout_ms >= INT_MAX)
 +    timeout_ms = INT_MAX;
 +#endif
 +
 +  if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
 +     (writefd == CURL_SOCKET_BAD)) {
 +    /* no sockets, just wait */
 +    r = Curl_wait_ms((int)timeout_ms);
 +    return r;
 +  }
 +
-   /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
++  /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
 +     time in this function does not need to be measured. This happens
 +     when function is called with a zero timeout or a negative timeout
 +     value indicating a blocking call should be performed. */
 +
 +  if(timeout_ms > 0) {
 +    pending_ms = (int)timeout_ms;
-     initial_tv = curlx_tvnow();
++    initial_tv = Curl_now();
 +  }
 +
 +#ifdef HAVE_POLL_FINE
 +
 +  num = 0;
 +  if(readfd0 != CURL_SOCKET_BAD) {
 +    pfd[num].fd = readfd0;
 +    pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
 +    pfd[num].revents = 0;
 +    num++;
 +  }
 +  if(readfd1 != CURL_SOCKET_BAD) {
 +    pfd[num].fd = readfd1;
 +    pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
 +    pfd[num].revents = 0;
 +    num++;
 +  }
 +  if(writefd != CURL_SOCKET_BAD) {
 +    pfd[num].fd = writefd;
 +    pfd[num].events = POLLWRNORM|POLLOUT;
 +    pfd[num].revents = 0;
 +    num++;
 +  }
 +
 +  do {
 +    if(timeout_ms < 0)
 +      pending_ms = -1;
 +    else if(!timeout_ms)
 +      pending_ms = 0;
 +    r = poll(pfd, num, pending_ms);
 +    if(r != -1)
 +      break;
 +    error = SOCKERRNO;
 +    if(error && ERROR_NOT_EINTR(error))
 +      break;
 +    if(timeout_ms > 0) {
 +      pending_ms = (int)(timeout_ms - ELAPSED_MS());
 +      if(pending_ms <= 0) {
 +        r = 0;  /* Simulate a "call timed out" case */
 +        break;
 +      }
 +    }
 +  } while(r == -1);
 +
 +  if(r < 0)
 +    return -1;
 +  if(r == 0)
 +    return 0;
 +
 +  ret = 0;
 +  num = 0;
 +  if(readfd0 != CURL_SOCKET_BAD) {
 +    if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
 +      ret |= CURL_CSELECT_IN;
 +    if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
 +      ret |= CURL_CSELECT_ERR;
 +    num++;
 +  }
 +  if(readfd1 != CURL_SOCKET_BAD) {
 +    if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
 +      ret |= CURL_CSELECT_IN2;
 +    if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
 +      ret |= CURL_CSELECT_ERR;
 +    num++;
 +  }
 +  if(writefd != CURL_SOCKET_BAD) {
 +    if(pfd[num].revents & (POLLWRNORM|POLLOUT))
 +      ret |= CURL_CSELECT_OUT;
 +    if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
 +      ret |= CURL_CSELECT_ERR;
 +  }
 +
 +  return ret;
 +
 +#else  /* HAVE_POLL_FINE */
 +
 +  FD_ZERO(&fds_err);
 +  maxfd = (curl_socket_t)-1;
 +
 +  FD_ZERO(&fds_read);
 +  if(readfd0 != CURL_SOCKET_BAD) {
 +    VERIFY_SOCK(readfd0);
 +    FD_SET(readfd0, &fds_read);
 +    FD_SET(readfd0, &fds_err);
 +    maxfd = readfd0;
 +  }
 +  if(readfd1 != CURL_SOCKET_BAD) {
 +    VERIFY_SOCK(readfd1);
 +    FD_SET(readfd1, &fds_read);
 +    FD_SET(readfd1, &fds_err);
 +    if(readfd1 > maxfd)
 +      maxfd = readfd1;
 +  }
 +
 +  FD_ZERO(&fds_write);
 +  if(writefd != CURL_SOCKET_BAD) {
 +    VERIFY_SOCK(writefd);
 +    FD_SET(writefd, &fds_write);
 +    FD_SET(writefd, &fds_err);
 +    if(writefd > maxfd)
 +      maxfd = writefd;
 +  }
 +
 +  ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 +
 +  do {
 +    if(timeout_ms > 0) {
 +      pending_tv.tv_sec = pending_ms / 1000;
 +      pending_tv.tv_usec = (pending_ms % 1000) * 1000;
 +    }
 +    else if(!timeout_ms) {
 +      pending_tv.tv_sec = 0;
 +      pending_tv.tv_usec = 0;
 +    }
 +
 +    /* WinSock select() must not be called with an fd_set that contains zero
 +       fd flags, or it will return WSAEINVAL.  But, it also can't be called
 +       with no fd_sets at all!  From the documentation:
 +
 +         Any two of the parameters, readfds, writefds, or exceptfds, can be
 +         given as null. At least one must be non-null, and any non-null
 +         descriptor set must contain at least one handle to a socket.
 +
 +       We know that we have at least one bit set in at least two fd_sets in
 +       this case, but we may have no bits set in either fds_read or fd_write,
 +       so check for that and handle it.  Luckily, with WinSock, we can _also_
 +       ask how many bits are set on an fd_set.
 +
 +       It is unclear why WinSock doesn't just handle this for us instead of
 +       calling this an error.
 +
 +       Note also that WinSock ignores the first argument, so we don't worry
 +       about the fact that maxfd is computed incorrectly with WinSock (since
 +       curl_socket_t is unsigned in such cases and thus -1 is the largest
 +       value).
 +    */
 +#ifdef USE_WINSOCK
 +    r = select((int)maxfd + 1,
 +               fds_read.fd_count ? &fds_read : NULL,
 +               fds_write.fd_count ? &fds_write : NULL,
 +               &fds_err, ptimeout);
 +#else
 +    r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
 +#endif
 +
 +    if(r != -1)
 +      break;
 +    error = SOCKERRNO;
 +    if(error && ERROR_NOT_EINTR(error))
 +      break;
 +    if(timeout_ms > 0) {
 +      pending_ms = (int)(timeout_ms - ELAPSED_MS());
 +      if(pending_ms <= 0) {
 +        r = 0;  /* Simulate a "call timed out" case */
 +        break;
 +      }
 +    }
 +  } while(r == -1);
 +
 +  if(r < 0)
 +    return -1;
 +  if(r == 0)
 +    return 0;
 +
 +  ret = 0;
 +  if(readfd0 != CURL_SOCKET_BAD) {
 +    if(FD_ISSET(readfd0, &fds_read))
 +      ret |= CURL_CSELECT_IN;
 +    if(FD_ISSET(readfd0, &fds_err))
 +      ret |= CURL_CSELECT_ERR;
 +  }
 +  if(readfd1 != CURL_SOCKET_BAD) {
 +    if(FD_ISSET(readfd1, &fds_read))
 +      ret |= CURL_CSELECT_IN2;
 +    if(FD_ISSET(readfd1, &fds_err))
 +      ret |= CURL_CSELECT_ERR;
 +  }
 +  if(writefd != CURL_SOCKET_BAD) {
 +    if(FD_ISSET(writefd, &fds_write))
 +      ret |= CURL_CSELECT_OUT;
 +    if(FD_ISSET(writefd, &fds_err))
 +      ret |= CURL_CSELECT_ERR;
 +  }
 +
 +  return ret;
 +
 +#endif  /* HAVE_POLL_FINE */
 +
 +}
 +
 +/*
 + * This is a wrapper around poll().  If poll() does not exist, then
 + * select() is used instead.  An error is returned if select() is
 + * being used and a file descriptor is too large for FD_SETSIZE.
 + * A negative timeout value makes this function wait indefinitely,
 + * unless no valid file descriptor is given, when this happens the
 + * negative timeout is ignored and the function times out immediately.
 + *
 + * Return values:
 + *   -1 = system call error or fd >= FD_SETSIZE
 + *    0 = timeout
 + *    N = number of structures with non zero revent fields
 + */
 +int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
 +{
 +#ifndef HAVE_POLL_FINE
 +  struct timeval pending_tv;
 +  struct timeval *ptimeout;
 +  fd_set fds_read;
 +  fd_set fds_write;
 +  fd_set fds_err;
 +  curl_socket_t maxfd;
 +#endif
 +  struct curltime initial_tv = {0, 0};
 +  bool fds_none = TRUE;
 +  unsigned int i;
 +  int pending_ms = 0;
 +  int error;
 +  int r;
 +
 +  if(ufds) {
 +    for(i = 0; i < nfds; i++) {
 +      if(ufds[i].fd != CURL_SOCKET_BAD) {
 +        fds_none = FALSE;
 +        break;
 +      }
 +    }
 +  }
 +  if(fds_none) {
 +    r = Curl_wait_ms(timeout_ms);
 +    return r;
 +  }
 +
-   /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
++  /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
 +     time in this function does not need to be measured. This happens
 +     when function is called with a zero timeout or a negative timeout
 +     value indicating a blocking call should be performed. */
 +
 +  if(timeout_ms > 0) {
 +    pending_ms = timeout_ms;
-     initial_tv = curlx_tvnow();
++    initial_tv = Curl_now();
 +  }
 +
 +#ifdef HAVE_POLL_FINE
 +
 +  do {
 +    if(timeout_ms < 0)
 +      pending_ms = -1;
 +    else if(!timeout_ms)
 +      pending_ms = 0;
 +    r = poll(ufds, nfds, pending_ms);
 +    if(r != -1)
 +      break;
 +    error = SOCKERRNO;
 +    if(error && ERROR_NOT_EINTR(error))
 +      break;
 +    if(timeout_ms > 0) {
 +      pending_ms = (int)(timeout_ms - ELAPSED_MS());
 +      if(pending_ms <= 0) {
 +        r = 0;  /* Simulate a "call timed out" case */
 +        break;
 +      }
 +    }
 +  } while(r == -1);
 +
 +  if(r < 0)
 +    return -1;
 +  if(r == 0)
 +    return 0;
 +
 +  for(i = 0; i < nfds; i++) {
 +    if(ufds[i].fd == CURL_SOCKET_BAD)
 +      continue;
 +    if(ufds[i].revents & POLLHUP)
 +      ufds[i].revents |= POLLIN;
 +    if(ufds[i].revents & POLLERR)
 +      ufds[i].revents |= (POLLIN|POLLOUT);
 +  }
 +
 +#else  /* HAVE_POLL_FINE */
 +
 +  FD_ZERO(&fds_read);
 +  FD_ZERO(&fds_write);
 +  FD_ZERO(&fds_err);
 +  maxfd = (curl_socket_t)-1;
 +
 +  for(i = 0; i < nfds; i++) {
 +    ufds[i].revents = 0;
 +    if(ufds[i].fd == CURL_SOCKET_BAD)
 +      continue;
 +    VERIFY_SOCK(ufds[i].fd);
 +    if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
 +                          POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
 +      if(ufds[i].fd > maxfd)
 +        maxfd = ufds[i].fd;
 +      if(ufds[i].events & (POLLRDNORM|POLLIN))
 +        FD_SET(ufds[i].fd, &fds_read);
 +      if(ufds[i].events & (POLLWRNORM|POLLOUT))
 +        FD_SET(ufds[i].fd, &fds_write);
 +      if(ufds[i].events & (POLLRDBAND|POLLPRI))
 +        FD_SET(ufds[i].fd, &fds_err);
 +    }
 +  }
 +
 +#ifdef USE_WINSOCK
 +  /* WinSock select() can't handle zero events.  See the comment about this in
 +     Curl_check_socket(). */
 +  if(fds_read.fd_count == 0 && fds_write.fd_count == 0
 +     && fds_err.fd_count == 0) {
 +    r = Curl_wait_ms(timeout_ms);
 +    return r;
 +  }
 +#endif
 +
 +  ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 +
 +  do {
 +    if(timeout_ms > 0) {
 +      pending_tv.tv_sec = pending_ms / 1000;
 +      pending_tv.tv_usec = (pending_ms % 1000) * 1000;
 +    }
 +    else if(!timeout_ms) {
 +      pending_tv.tv_sec = 0;
 +      pending_tv.tv_usec = 0;
 +    }
 +
 +#ifdef USE_WINSOCK
 +    r = select((int)maxfd + 1,
 +               /* WinSock select() can't handle fd_sets with zero bits set, so
 +                  don't give it such arguments.  See the comment about this in
 +                  Curl_check_socket().
 +               */
 +               fds_read.fd_count ? &fds_read : NULL,
 +               fds_write.fd_count ? &fds_write : NULL,
 +               fds_err.fd_count ? &fds_err : NULL, ptimeout);
 +#else
 +    r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
 +#endif
 +    if(r != -1)
 +      break;
 +    error = SOCKERRNO;
 +    if(error && ERROR_NOT_EINTR(error))
 +      break;
 +    if(timeout_ms > 0) {
 +      pending_ms = timeout_ms - ELAPSED_MS();
 +      if(pending_ms <= 0) {
 +        r = 0;  /* Simulate a "call timed out" case */
 +        break;
 +      }
 +    }
 +  } while(r == -1);
 +
 +  if(r < 0)
 +    return -1;
 +  if(r == 0)
 +    return 0;
 +
 +  r = 0;
 +  for(i = 0; i < nfds; i++) {
 +    ufds[i].revents = 0;
 +    if(ufds[i].fd == CURL_SOCKET_BAD)
 +      continue;
 +    if(FD_ISSET(ufds[i].fd, &fds_read))
 +      ufds[i].revents |= POLLIN;
 +    if(FD_ISSET(ufds[i].fd, &fds_write))
 +      ufds[i].revents |= POLLOUT;
 +    if(FD_ISSET(ufds[i].fd, &fds_err))
 +      ufds[i].revents |= POLLPRI;
 +    if(ufds[i].revents != 0)
 +      r++;
 +  }
 +
 +#endif  /* HAVE_POLL_FINE */
 +
 +  return r;
 +}
 +
 +#ifdef TPF
 +/*
 + * This is a replacement for select() on the TPF platform.
 + * It is used whenever libcurl calls select().
 + * The call below to tpf_process_signals() is required because
 + * TPF's select calls are not signal interruptible.
 + *
 + * Return values are the same as select's.
 + */
 +int tpf_select_libcurl(int maxfds, fd_set *reads, fd_set *writes,
 +                       fd_set *excepts, struct timeval *tv)
 +{
 +   int rc;
 +
 +   rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
 +   tpf_process_signals();
 +   return rc;
 +}
 +#endif /* TPF */
diff --cc Utilities/cmcurl/lib/setopt.c
index 0000000,a5ef75c..a5ef75c
mode 000000,100644..100644
--- a/Utilities/cmcurl/lib/setopt.c
+++ b/Utilities/cmcurl/lib/setopt.c
diff --cc Utilities/cmcurl/lib/sha256.c
index 0000000,cd81c02..cd81c02
mode 000000,100644..100644
--- a/Utilities/cmcurl/lib/sha256.c
+++ b/Utilities/cmcurl/lib/sha256.c
diff --cc Utilities/cmcurl/lib/ssh-libssh.c
index 0000000,56775d7..56775d7
mode 000000,100644..100644
--- a/Utilities/cmcurl/lib/ssh-libssh.c
+++ b/Utilities/cmcurl/lib/ssh-libssh.c

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=af9e654045f11028e50dac4781e297834129a749
commit af9e654045f11028e50dac4781e297834129a749
Author:     Curl Upstream <curl-library at cool.haxx.se>
AuthorDate: Tue Jan 23 22:49:00 2018 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Jan 24 14:14:23 2018 -0500

    curl 2018-01-23 (d6c21c8e)
    
    Code extracted from:
    
        https://github.com/curl/curl.git
    
    at commit d6c21c8eec597a925d2b647cff3d58ac69de01a0 (curl-7_58_0).

diff --git a/CMake/curl-config.cmake b/CMake/curl-config.cmake
new file mode 100644
index 0000000..119332c
--- /dev/null
+++ b/CMake/curl-config.cmake
@@ -0,0 +1,59 @@
+
+get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+if(NOT CURL_FIND_COMPONENTS)
+    set(CURL_FIND_COMPONENTS curl libcurl)
+    if(CURL_FIND_REQUIRED)
+        set(CURL_FIND_REQUIRED_curl TRUE)
+        set(CURL_FIND_REQUIRED_libcurl TRUE)
+    endif()
+endif()
+
+set(_curl_missing_components)
+foreach(_comp ${CURL_FIND_COMPONENTS})
+    if(EXISTS "${_DIR}/${_comp}-target.cmake")
+        include("${_DIR}/${_comp}-target.cmake")
+        set(CURL_${_comp}_FOUND TRUE)
+    else()
+        set(CURL_${_comp}_FOUND FALSE)
+        if(CURL_FIND_REQUIRED_${_comp})
+            set(CURL_FOUND FALSE)
+            list(APPEND _curl_missing_components ${_comp})
+        endif()
+    endif()
+endforeach()
+
+if(_curl_missing_components)
+    set(CURL_NOT_FOUND_MESSAGE "Following required components not found: " ${_curl_missing_components})
+else()
+    if(TARGET CURL::libcurl)
+        string(TOUPPER "${CMAKE_BUILD_TYPE}" _curl_current_config)
+        if(NOT _curl_current_config)
+            set(_curl_current_config "NOCONFIG")
+        endif()
+        get_target_property(_curl_configurations CURL::libcurl IMPORTED_CONFIGURATIONS)
+        list(FIND _curl_configurations "${_curl_current_config}" _i)
+        if(_i LESS 0)
+            set(_curl_config "RELEASE")
+            list(FIND _curl_configurations "${_curl_current_config}" _i)
+            if(_i LESS 0)
+                set(_curl_config "NOCONFIG")
+                list(FIND _curl_configurations "${_curl_current_config}" _i)
+            endif()
+        endif()
+
+        if(_i LESS 0)
+            set(_curl_current_config "") # let CMake pick config at random
+        else()
+	    set(_curl_current_config "_${_curl_current_config}")
+        endif()
+
+        get_target_property(CURL_INCLUDE_DIRS CURL::libcurl INTERFACE_INCLUDE_DIRECTORIES)
+        get_target_property(CURL_LIBRARIES CURL::libcurl "LOCATION${_curl_current_config}")
+        set(_curl_current_config)
+        set(_curl_configurations)
+        set(_i)
+    endif()
+endif()
+
+unset(_curl_missing_components)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 261baba..490cc19 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,7 +38,7 @@
 # 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.
-cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
+cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
 set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
 include(Utilities)
 include(Macros)
@@ -366,7 +366,6 @@ if(CMAKE_USE_OPENSSL)
   check_include_file("openssl/engine.h" HAVE_OPENSSL_ENGINE_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/pkcs12.h" HAVE_OPENSSL_PKCS12_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)
@@ -738,7 +737,6 @@ 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("limits.h"         HAVE_LIMITS_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)
@@ -875,10 +873,12 @@ check_symbol_exists(ftruncate      "${CURL_INCLUDES}" HAVE_FTRUNCATE)
 check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
 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)
@@ -1131,6 +1131,12 @@ function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
 
 endfunction()
 
+if(WIN32 AND NOT CYGWIN)
+    set(CURL_INSTALL_CMAKE_DIR CMake)
+else()
+    set(CURL_INSTALL_CMAKE_DIR lib/cmake/curl)
+endif()
+
 if(USE_MANUAL)
   add_subdirectory(docs)
 endif()
@@ -1281,6 +1287,25 @@ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl"
     DESTINATION include
     FILES_MATCHING PATTERN "*.h")
 
+
+include(CMakePackageConfigHelpers)
+write_basic_package_version_file(
+    "${PROJECT_BINARY_DIR}/curl-config-version.cmake"
+    VERSION ${CURL_VERSION}
+    COMPATIBILITY SameMajorVersion
+)
+
+configure_file(CMake/curl-config.cmake
+        "${PROJECT_BINARY_DIR}/curl-config.cmake"
+        COPYONLY
+)
+
+install(
+        FILES ${PROJECT_BINARY_DIR}/curl-config.cmake
+              ${PROJECT_BINARY_DIR}/curl-config-version.cmake
+        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)
diff --git a/COPYING b/COPYING
index 1e45a5e..560a49d 100644
--- a/COPYING
+++ b/COPYING
@@ -1,6 +1,6 @@
 COPYRIGHT AND PERMISSION NOTICE
 
-Copyright (c) 1996 - 2017, Daniel Stenberg, <daniel at haxx.se>, and many
+Copyright (c) 1996 - 2018, 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 7139a33..7680acd 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -715,6 +715,7 @@ typedef enum {
 #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) */
@@ -727,7 +728,9 @@ enum curl_khtype {
   CURLKHTYPE_UNKNOWN,
   CURLKHTYPE_RSA1,
   CURLKHTYPE_RSA,
-  CURLKHTYPE_DSS
+  CURLKHTYPE_DSS,
+  CURLKHTYPE_ECDSA,
+  CURLKHTYPE_ED25519
 };
 
 struct curl_khkey {
@@ -935,7 +938,7 @@ typedef enum {
   CINIT(READDATA, OBJECTPOINT, 9),
 
   /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
-   * bytes big. If this is not used, error messages go to stderr instead: */
+   * bytes big. */
   CINIT(ERRORBUFFER, OBJECTPOINT, 10),
 
   /* Function that will be called to store the output (instead of fwrite). The
@@ -2514,7 +2517,7 @@ typedef enum {
   CURLCLOSEPOLICY_LAST /* last, never use this */
 } curl_closepolicy;
 
-#define CURL_GLOBAL_SSL (1<<0)
+#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
@@ -2592,6 +2595,7 @@ typedef enum {
   CURLVERSION_SECOND,
   CURLVERSION_THIRD,
   CURLVERSION_FOURTH,
+  CURLVERSION_FIFTH,
   CURLVERSION_LAST /* never actually use this */
 } CURLversion;
 
@@ -2600,7 +2604,7 @@ typedef enum {
    meant to be a built-in version number for what kind of struct the caller
    expects. If the struct ever changes, we redefine the NOW to another enum
    from above. */
-#define CURLVERSION_NOW CURLVERSION_FOURTH
+#define CURLVERSION_NOW CURLVERSION_FIFTH
 
 typedef struct {
   CURLversion age;          /* age of the returned struct */
@@ -2628,6 +2632,12 @@ typedef struct {
 
   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 */
@@ -2658,6 +2668,7 @@ typedef struct {
                                              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. */
 
  /*
  * NAME curl_version_info()
diff --git a/include/curl/curlver.h b/include/curl/curlver.h
index 8c9fb5e..2ee531d 100644
--- a/include/curl/curlver.h
+++ b/include/curl/curlver.h
@@ -30,12 +30,12 @@
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "7.56.0-DEV"
+#define LIBCURL_VERSION "7.58.0-DEV"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 56
+#define LIBCURL_VERSION_MINOR 58
 #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 0x073800
+#define LIBCURL_VERSION_NUM 0x073A00
 
 /*
  * This is the date and time when the full source package was created. The
diff --git a/include/curl/system.h b/include/curl/system.h
index 39dae75..07bbd9c 100644
--- a/include/curl/system.h
+++ b/include/curl/system.h
@@ -348,7 +348,8 @@
    defined(__ppc__) || defined(__powerpc__) || defined(__arm__) ||      \
    defined(__sparc__) || defined(__mips__) || defined(__sh__) ||        \
    defined(__XTENSA__) ||                                               \
-   (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4))
+   (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4)  ||               \
+   (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L))
 #    define CURL_TYPEOF_CURL_OFF_T     long long
 #    define CURL_FORMAT_CURL_OFF_T     "lld"
 #    define CURL_FORMAT_CURL_OFF_TU    "llu"
@@ -356,7 +357,8 @@
 #    define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  elif defined(__LP64__) || \
         defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
-        (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8)
+        (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
+        (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
 #    define CURL_TYPEOF_CURL_OFF_T     long
 #    define CURL_FORMAT_CURL_OFF_T     "ld"
 #    define CURL_FORMAT_CURL_OFF_TU    "lu"
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index d6c9961..1fabdba 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -108,7 +108,24 @@ if(WIN32)
   endif()
 endif()
 
+target_include_directories(${LIB_NAME} INTERFACE
+	$<INSTALL_INTERFACE:include>)
+
 install(TARGETS ${LIB_NAME}
+  EXPORT libcurl-target
   ARCHIVE DESTINATION lib
   LIBRARY DESTINATION lib
-  RUNTIME DESTINATION bin)
+  RUNTIME DESTINATION bin
+)
+
+export(TARGETS ${LIB_NAME}
+       APPEND FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
+       NAMESPACE CURL::
+)
+
+install(EXPORT libcurl-target
+        FILE libcurl-target.cmake
+        NAMESPACE CURL::
+        DESTINATION ${CURL_INSTALL_CMAKE_DIR}
+)
+
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 5c0b930..61e80cf 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+# Copyright (C) 1998 - 2017, 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,7 +46,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
   http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c    \
   strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c         \
   inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c      \
-  ssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c            \
+  ssh.c ssh-libssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c            \
   curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c    \
   pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c        \
   openldap.c curl_gethostname.c gopher.c idn_win32.c                    \
@@ -54,7 +54,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
   http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c        \
   curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c          \
   x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c      \
-  mime.c
+  mime.c sha256.c setopt.c curl_path.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         \
@@ -73,7 +73,8 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
   curl_sasl.h curl_multibyte.h hostcheck.h conncache.h                  \
   curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h       \
   x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h           \
-  curl_printf.h system_win32.h rand.h mime.h
+  curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h     \
+  curl_path.h
 
 LIB_RCFILES = libcurl.rc
 
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index 87e70b4..aa581a4 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -22,9 +22,15 @@
 
 #include "curl_setup.h"
 
-#ifdef HAVE_LIMITS_H
+/***********************************************************************
+ * Only for ares-enabled builds
+ * And only for functions that fulfill the asynch resolver backend API
+ * as defined in asyn.h, nothing else belongs in this file!
+ **********************************************************************/
+
+#ifdef CURLRES_ARES
+
 #include <limits.h>
-#endif
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -48,14 +54,6 @@
 #define in_addr_t unsigned long
 #endif
 
-/***********************************************************************
- * Only for ares-enabled builds
- * And only for functions that fulfill the asynch resolver backend API
- * as defined in asyn.h, nothing else belongs in this file!
- **********************************************************************/
-
-#ifdef CURLRES_ARES
-
 #include "urldata.h"
 #include "sendf.h"
 #include "hostip.h"
@@ -354,8 +352,8 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
 {
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
-  long timeout;
-  struct curltime now = Curl_tvnow();
+  timediff_t timeout;
+  struct curltime now = Curl_now();
   struct Curl_dns_entry *temp_entry;
 
   if(entry)
@@ -400,8 +398,8 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
     if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
     else {
-      struct curltime now2 = Curl_tvnow();
-      time_t timediff = Curl_tvdiff(now2, now); /* spent time */
+      struct curltime now2 = Curl_now();
+      timediff_t timediff = Curl_timediff(now2, now); /* spent time */
       if(timediff <= 0)
         timeout -= 1; /* always deduct at least 1 */
       else if(timediff > timeout)
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index a867729..1ac3fc8 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -535,7 +535,8 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
   }
   else {
     /* poll for name lookup done with exponential backoff up to 250ms */
-    time_t elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
+    timediff_t elapsed = Curl_timediff(Curl_now(),
+                                       data->progress.t_startsingle);
     if(elapsed < 0)
       elapsed = 0;
 
diff --git a/lib/conncache.c b/lib/conncache.c
index c79d227..b8f5444 100644
--- a/lib/conncache.c
+++ b/lib/conncache.c
@@ -31,11 +31,36 @@
 #include "multiif.h"
 #include "sendf.h"
 #include "conncache.h"
+#include "share.h"
+#include "sigpipe.h"
+#include "connect.h"
+
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
 
+#ifdef CURLDEBUG
+/* the debug versions of these macros make extra certain that the lock is
+   never doubly locked or unlocked */
+#define CONN_LOCK(x) if((x)->share) {                                   \
+    Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \
+    DEBUGASSERT(!(x)->state.conncache_lock);                            \
+    (x)->state.conncache_lock = TRUE;                                   \
+  }
+
+#define CONN_UNLOCK(x) if((x)->share) {                                 \
+    DEBUGASSERT((x)->state.conncache_lock);                             \
+    (x)->state.conncache_lock = FALSE;                                  \
+    Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT);                     \
+  }
+#else
+#define CONN_LOCK(x) if((x)->share)                                     \
+    Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
+#define CONN_UNLOCK(x) if((x)->share)                   \
+    Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
+#endif
+
 static void conn_llist_dtor(void *user, void *element)
 {
   struct connectdata *data = element;
@@ -109,8 +134,23 @@ static void free_bundle_hash_entry(void *freethis)
 
 int Curl_conncache_init(struct conncache *connc, int size)
 {
-  return Curl_hash_init(&connc->hash, size, Curl_hash_str,
-                        Curl_str_key_compare, free_bundle_hash_entry);
+  int rc;
+
+  /* allocate a new easy handle to use when closing cached connections */
+  connc->closure_handle = curl_easy_init();
+  if(!connc->closure_handle)
+    return 1; /* bad */
+
+  rc = Curl_hash_init(&connc->hash, size, Curl_hash_str,
+                      Curl_str_key_compare, free_bundle_hash_entry);
+  if(rc) {
+    Curl_close(connc->closure_handle);
+    connc->closure_handle = NULL;
+  }
+  else
+    connc->closure_handle->state.conn_cache = connc;
+
+  return rc;
 }
 
 void Curl_conncache_destroy(struct conncache *connc)
@@ -140,12 +180,44 @@ static void hashkey(struct connectdata *conn, char *buf,
   snprintf(buf, len, "%ld%s", conn->port, hostname);
 }
 
+void Curl_conncache_unlock(struct connectdata *conn)
+{
+  CONN_UNLOCK(conn->data);
+}
+
+/* Returns number of connections currently held in the connection cache.
+   Locks/unlocks the cache itself!
+*/
+size_t Curl_conncache_size(struct Curl_easy *data)
+{
+  size_t num;
+  CONN_LOCK(data);
+  num = data->state.conn_cache->num_conn;
+  CONN_UNLOCK(data);
+  return num;
+}
+
+/* Returns number of connections currently held in the connections's bundle
+   Locks/unlocks the cache itself!
+*/
+size_t Curl_conncache_bundle_size(struct connectdata *conn)
+{
+  size_t num;
+  CONN_LOCK(conn->data);
+  num = conn->bundle->num_connections;
+  CONN_UNLOCK(conn->data);
+  return num;
+}
+
 /* Look up the bundle with all the connections to the same host this
-   connectdata struct is setup to use. */
+   connectdata struct is setup to use.
+
+   **NOTE**: When it returns, it holds the connection cache lock! */
 struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
                                                  struct conncache *connc)
 {
   struct connectbundle *bundle = NULL;
+  CONN_LOCK(conn->data);
   if(connc) {
     char key[128];
     hashkey(conn, key, sizeof(key));
@@ -196,21 +268,24 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
   struct connectbundle *new_bundle = NULL;
   struct Curl_easy *data = conn->data;
 
+  /* *find_bundle() locks the connection cache */
   bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
   if(!bundle) {
     int rc;
     char key[128];
 
     result = bundle_create(data, &new_bundle);
-    if(result)
-      return result;
+    if(result) {
+      goto unlock;
+    }
 
     hashkey(conn, key, sizeof(key));
     rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
 
     if(!rc) {
       bundle_destroy(new_bundle);
-      return CURLE_OUT_OF_MEMORY;
+      result = CURLE_OUT_OF_MEMORY;
+      goto unlock;
     }
     bundle = new_bundle;
   }
@@ -219,49 +294,64 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
   if(result) {
     if(new_bundle)
       conncache_remove_bundle(data->state.conn_cache, new_bundle);
-    return result;
+    goto unlock;
   }
 
   conn->connection_id = connc->next_connection_id++;
-  connc->num_connections++;
+  connc->num_conn++;
 
   DEBUGF(infof(conn->data, "Added connection %ld. "
                "The cache now contains %" CURL_FORMAT_CURL_OFF_TU " members\n",
-               conn->connection_id, (curl_off_t) connc->num_connections));
+               conn->connection_id, (curl_off_t) connc->num_conn));
 
-  return CURLE_OK;
+  unlock:
+  CONN_UNLOCK(data);
+
+  return result;
 }
 
-void Curl_conncache_remove_conn(struct conncache *connc,
-                                struct connectdata *conn)
+void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
 {
+  struct Curl_easy *data = conn->data;
   struct connectbundle *bundle = conn->bundle;
+  struct conncache *connc = data->state.conn_cache;
 
   /* The bundle pointer can be NULL, since this function can be called
      due to a failed connection attempt, before being added to a bundle */
   if(bundle) {
+    if(lock) {
+      CONN_LOCK(conn->data);
+    }
     bundle_remove_conn(bundle, conn);
-    if(bundle->num_connections == 0) {
+    if(bundle->num_connections == 0)
       conncache_remove_bundle(connc, bundle);
-    }
-
+    conn->bundle = NULL; /* removed from it */
     if(connc) {
-      connc->num_connections--;
-
+      connc->num_conn--;
       DEBUGF(infof(conn->data, "The cache now contains %"
                    CURL_FORMAT_CURL_OFF_TU " members\n",
-                   (curl_off_t) connc->num_connections));
+                   (curl_off_t) connc->num_conn));
+    }
+    if(lock) {
+      CONN_UNLOCK(conn->data);
     }
   }
 }
 
-/* This function iterates the entire connection cache and calls the
-   function func() with the connection pointer as the first argument
-   and the supplied 'param' argument as the other,
+/* This function iterates the entire connection cache and calls the function
+   func() with the connection pointer as the first argument and the supplied
+   'param' argument as the other.
+
+   The conncache lock is still held when the callback is called. It needs it,
+   so that it can safely continue traversing the lists once the callback
+   returns.
+
+   Returns 1 if the loop was aborted due to the callback's return code.
 
    Return 0 from func() to continue the loop, return 1 to abort it.
  */
-void Curl_conncache_foreach(struct conncache *connc,
+bool Curl_conncache_foreach(struct Curl_easy *data,
+                            struct conncache *connc,
                             void *param,
                             int (*func)(struct connectdata *conn, void *param))
 {
@@ -270,8 +360,9 @@ void Curl_conncache_foreach(struct conncache *connc,
   struct curl_hash_element *he;
 
   if(!connc)
-    return;
+    return FALSE;
 
+  CONN_LOCK(data);
   Curl_hash_start_iterate(&connc->hash, &iter);
 
   he = Curl_hash_next_element(&iter);
@@ -288,14 +379,22 @@ void Curl_conncache_foreach(struct conncache *connc,
       struct connectdata *conn = curr->ptr;
       curr = curr->next;
 
-      if(1 == func(conn, param))
-        return;
+      if(1 == func(conn, param)) {
+        CONN_UNLOCK(data);
+        return TRUE;
+      }
     }
   }
+  CONN_UNLOCK(data);
+  return FALSE;
 }
 
 /* Return the first connection found in the cache. Used when closing all
-   connections */
+   connections.
+
+   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)
 {
@@ -321,6 +420,188 @@ Curl_conncache_find_first_connection(struct conncache *connc)
   return NULL;
 }
 
+/*
+ * Give ownership of a connection back to the connection cache. Might
+ * disconnect the oldest existing in there to make space.
+ *
+ * Return TRUE if stored, FALSE if closed.
+ */
+bool Curl_conncache_return_conn(struct connectdata *conn)
+{
+  struct Curl_easy *data = conn->data;
+
+  /* data->multi->maxconnects can be negative, deal with it. */
+  size_t maxconnects =
+    (data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
+    data->multi->maxconnects;
+  struct connectdata *conn_candidate = NULL;
+
+  if(maxconnects > 0 &&
+     Curl_conncache_size(data) > maxconnects) {
+    infof(data, "Connection cache is full, closing the oldest one.\n");
+
+    conn_candidate = Curl_conncache_extract_oldest(data);
+
+    if(conn_candidate) {
+      /* Set the connection's owner correctly */
+      conn_candidate->data = data;
+
+      /* the winner gets the honour of being disconnected */
+      (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
+    }
+  }
+  CONN_LOCK(data);
+  conn->inuse = FALSE; /* Mark the connection unused */
+  CONN_UNLOCK(data);
+
+  return (conn_candidate == conn) ? FALSE : TRUE;
+
+}
+
+/*
+ * This function finds the connection in the connection bundle that has been
+ * unused for the longest time.
+ *
+ * Does not lock the connection cache!
+ *
+ * Returns the pointer to the oldest idle connection, or NULL if none was
+ * found.
+ */
+struct connectdata *
+Curl_conncache_extract_bundle(struct Curl_easy *data,
+                              struct connectbundle *bundle)
+{
+  struct curl_llist_element *curr;
+  timediff_t highscore = -1;
+  timediff_t score;
+  struct curltime now;
+  struct connectdata *conn_candidate = NULL;
+  struct connectdata *conn;
+
+  (void)data;
+
+  now = Curl_now();
+
+  curr = bundle->conn_list.head;
+  while(curr) {
+    conn = curr->ptr;
+
+    if(!conn->inuse) {
+      /* Set higher score for the age passed since the connection was used */
+      score = Curl_timediff(now, conn->now);
+
+      if(score > highscore) {
+        highscore = score;
+        conn_candidate = conn;
+      }
+    }
+    curr = curr->next;
+  }
+  if(conn_candidate) {
+    /* remove it to prevent another thread from nicking it */
+    bundle_remove_conn(bundle, conn_candidate);
+    data->state.conn_cache->num_conn--;
+    DEBUGF(infof(data, "The cache now contains %"
+                 CURL_FORMAT_CURL_OFF_TU " members\n",
+                 (curl_off_t) data->state.conn_cache->num_conn));
+  }
+
+  return conn_candidate;
+}
+
+/*
+ * This function finds the connection in the connection cache that has been
+ * unused for the longest time and extracts that from the bundle.
+ *
+ * Returns the pointer to the connection, or NULL if none was found.
+ */
+struct connectdata *
+Curl_conncache_extract_oldest(struct Curl_easy *data)
+{
+  struct conncache *connc = data->state.conn_cache;
+  struct curl_hash_iterator iter;
+  struct curl_llist_element *curr;
+  struct curl_hash_element *he;
+  timediff_t highscore =- 1;
+  timediff_t score;
+  struct curltime now;
+  struct connectdata *conn_candidate = NULL;
+  struct connectbundle *bundle;
+  struct connectbundle *bundle_candidate = NULL;
+
+  now = Curl_now();
+
+  CONN_LOCK(data);
+  Curl_hash_start_iterate(&connc->hash, &iter);
+
+  he = Curl_hash_next_element(&iter);
+  while(he) {
+    struct connectdata *conn;
+
+    bundle = he->ptr;
+
+    curr = bundle->conn_list.head;
+    while(curr) {
+      conn = curr->ptr;
+
+      if(!conn->inuse) {
+        /* Set higher score for the age passed since the connection was used */
+        score = Curl_timediff(now, conn->now);
+
+        if(score > highscore) {
+          highscore = score;
+          conn_candidate = conn;
+          bundle_candidate = bundle;
+        }
+      }
+      curr = curr->next;
+    }
+
+    he = Curl_hash_next_element(&iter);
+  }
+  if(conn_candidate) {
+    /* remove it to prevent another thread from nicking it */
+    bundle_remove_conn(bundle_candidate, conn_candidate);
+    connc->num_conn--;
+    DEBUGF(infof(data, "The cache now contains %"
+                 CURL_FORMAT_CURL_OFF_TU " members\n",
+                 (curl_off_t) connc->num_conn));
+  }
+  CONN_UNLOCK(data);
+
+  return conn_candidate;
+}
+
+void Curl_conncache_close_all_connections(struct conncache *connc)
+{
+  struct connectdata *conn;
+
+  conn = Curl_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(conn, FALSE);
+    sigpipe_restore(&pipe_st);
+
+    conn = Curl_conncache_find_first_connection(connc);
+  }
+
+  if(connc->closure_handle) {
+    SIGPIPE_VARIABLE(pipe_st);
+    sigpipe_ignore(connc->closure_handle, &pipe_st);
+
+    Curl_hostcache_clean(connc->closure_handle,
+                         connc->closure_handle->dns.hostcache);
+    Curl_close(connc->closure_handle);
+    sigpipe_restore(&pipe_st);
+  }
+}
 
 #if 0
 /* Useful for debugging the connection cache */
diff --git a/lib/conncache.h b/lib/conncache.h
index 14be4e8..d8ad80f 100644
--- a/lib/conncache.h
+++ b/lib/conncache.h
@@ -23,11 +23,19 @@
  *
  ***************************************************************************/
 
+/*
+ * All accesses to struct fields and changing of data in the connection cache
+ * and connectbundles must be done with the conncache LOCKED. The cache might
+ * be shared.
+ */
+
 struct conncache {
   struct curl_hash hash;
-  size_t num_connections;
+  size_t num_conn;
   long next_connection_id;
   struct curltime last_cleanup;
+  /* handle used for closing cached connections */
+  struct Curl_easy *closure_handle;
 };
 
 #define BUNDLE_NO_MULTIUSE -1
@@ -41,21 +49,25 @@ struct connectbundle {
   struct curl_llist conn_list;  /* The connectdata members of the bundle */
 };
 
+/* returns 1 on error, 0 is fine */
 int Curl_conncache_init(struct conncache *, int size);
-
 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);
+/* 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);
 
+bool Curl_conncache_return_conn(struct connectdata *conn);
 CURLcode Curl_conncache_add_conn(struct conncache *connc,
                                  struct connectdata *conn);
-
-void Curl_conncache_remove_conn(struct conncache *connc,
-                                struct connectdata *conn);
-
-void Curl_conncache_foreach(struct conncache *connc,
+void Curl_conncache_remove_conn(struct connectdata *conn,
+                                bool lock);
+bool Curl_conncache_foreach(struct Curl_easy *data,
+                            struct conncache *connc,
                             void *param,
                             int (*func)(struct connectdata *conn,
                                         void *param));
@@ -63,6 +75,12 @@ void Curl_conncache_foreach(struct conncache *connc,
 struct connectdata *
 Curl_conncache_find_first_connection(struct conncache *connc);
 
+struct connectdata *
+Curl_conncache_extract_bundle(struct Curl_easy *data,
+                              struct connectbundle *bundle);
+struct connectdata *
+Curl_conncache_extract_oldest(struct Curl_easy *data);
+void Curl_conncache_close_all_connections(struct conncache *connc);
 void Curl_conncache_print(struct conncache *connc);
 
 #endif /* HEADER_CURL_CONNCACHE_H */
diff --git a/lib/connect.c b/lib/connect.c
index b7d10af..3edb71e 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -28,8 +28,10 @@
 #ifdef HAVE_SYS_UN_H
 #include <sys/un.h> /* for sockaddr_un */
 #endif
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h> /* for TCP_NODELAY */
+#ifdef HAVE_LINUX_TCP_H
+#include <linux/tcp.h>
+#elif defined(HAVE_NETINET_TCP_H)
+#include <netinet/tcp.h>
 #endif
 #ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
@@ -179,12 +181,12 @@ singleipconnect(struct connectdata *conn,
  *
  * @unittest: 1303
  */
-time_t Curl_timeleft(struct Curl_easy *data,
-                     struct curltime *nowp,
-                     bool duringconnect)
+timediff_t Curl_timeleft(struct Curl_easy *data,
+                         struct curltime *nowp,
+                         bool duringconnect)
 {
   int timeout_set = 0;
-  time_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
+  timediff_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
   struct curltime now;
 
   /* if a timeout is set, use the most restrictive one */
@@ -218,17 +220,17 @@ time_t Curl_timeleft(struct Curl_easy *data,
   }
 
   if(!nowp) {
-    now = Curl_tvnow();
+    now = Curl_now();
     nowp = &now;
   }
 
   /* subtract elapsed time */
   if(duringconnect)
     /* since this most recent connect started */
-    timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
+    timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle);
   else
     /* since the entire operation started */
-    timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop);
+    timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop);
   if(!timeout_ms)
     /* avoid returning 0 as that means no timeout! */
     return -1;
@@ -285,6 +287,34 @@ static CURLcode bindlocal(struct connectdata *conn,
 
     /* interface */
     if(!is_host) {
+#ifdef SO_BINDTODEVICE
+      /* I am not sure any other OSs than Linux that provide this feature,
+       * and at the least I cannot test. --Ben
+       *
+       * This feature allows one to tightly bind the local socket to a
+       * particular interface.  This will force even requests to other
+       * local interfaces to go out the external interface.
+       *
+       *
+       * Only bind to the interface when specified as interface, not just
+       * as a hostname or ip address.
+       *
+       * interface might be a VRF, eg: vrf-blue, which means it cannot be
+       * converted to an IP address and would fail Curl_if2ip. Simply try
+       * to use it straight away.
+       */
+      if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
+                    dev, (curl_socklen_t)strlen(dev) + 1) == 0) {
+        /* This is typically "errno 1, error: Operation not permitted" if
+         * you're not running as root or another suitable privileged
+         * user.
+         * If it succeeds it means the parameter was a valid interface and
+         * not an IP address. Return immediately.
+         */
+        return CURLE_OK;
+      }
+#endif
+
       switch(Curl_if2ip(af, scope, conn->scope_id, dev,
                         myhost, sizeof(myhost))) {
         case IF2IP_NOT_FOUND:
@@ -305,30 +335,6 @@ static CURLcode bindlocal(struct connectdata *conn,
           infof(data, "Local Interface %s is ip %s using address family %i\n",
                 dev, myhost, af);
           done = 1;
-
-#ifdef SO_BINDTODEVICE
-          /* I am not sure any other OSs than Linux that provide this feature,
-           * and at the least I cannot test. --Ben
-           *
-           * This feature allows one to tightly bind the local socket to a
-           * particular interface.  This will force even requests to other
-           * local interfaces to go out the external interface.
-           *
-           *
-           * Only bind to the interface when specified as interface, not just
-           * as a hostname or ip address.
-           */
-          if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
-                        dev, (curl_socklen_t)strlen(dev) + 1) != 0) {
-            error = SOCKERRNO;
-            infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
-                  " will do regular bind\n",
-                  dev, error, Curl_strerror(conn, error));
-            /* This is typically "errno 1, error: Operation not permitted" if
-               you're not running as root or another suitable privileged
-               user */
-          }
-#endif
           break;
       }
     }
@@ -408,6 +414,10 @@ static CURLcode bindlocal(struct connectdata *conn,
     }
 
     if(done < 1) {
+      /* errorbuf is set false so failf will overwrite any message already in
+         the error buffer, so the user receives this error message instead of a
+         generic resolve error. */
+      data->state.errorbuf = FALSE;
       failf(data, "Couldn't bind to '%s'", dev);
       return CURLE_INTERFACE_FAILED;
     }
@@ -721,7 +731,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 {
   struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_OK;
-  time_t allow;
+  timediff_t allow;
   int error = 0;
   struct curltime now;
   int rc;
@@ -737,7 +747,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
     return CURLE_OK;
   }
 
-  now = Curl_tvnow();
+  now = Curl_now();
 
   /* figure out how long time we have left to connect */
   allow = Curl_timeleft(data, &now, TRUE);
@@ -765,7 +775,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 
     if(rc == 0) { /* no connection yet */
       error = 0;
-      if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
+      if(Curl_timediff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
         infof(data, "After %ldms connect time, move on!\n",
               conn->timeoutms_per_addr);
         error = ETIMEDOUT;
@@ -773,7 +783,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 
       /* should we try another protocol family? */
       if(i == 0 && conn->tempaddr[1] == NULL &&
-         curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
+         Curl_timediff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
         trynextip(conn, sockindex, 1);
       }
     }
@@ -785,6 +795,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
         conn->sock[sockindex] = conn->tempsock[i];
         conn->ip_addr = conn->tempaddr[i];
         conn->tempsock[i] = CURL_SOCKET_BAD;
+#ifdef ENABLE_IPV6
+        conn->bits.ipv6 = (conn->ip_addr->ai_family == AF_INET6)?TRUE:FALSE;
+#endif
 
         /* close the other socket, if open */
         if(conn->tempsock[other] != CURL_SOCKET_BAD) {
@@ -978,6 +991,9 @@ static CURLcode singleipconnect(struct connectdata *conn,
   char ipaddress[MAX_IPADR_LEN];
   long port;
   bool is_tcp;
+#ifdef TCP_FASTOPEN_CONNECT
+  int optval = 1;
+#endif
 
   *sockp = CURL_SOCKET_BAD;
 
@@ -1051,17 +1067,19 @@ static CURLcode singleipconnect(struct connectdata *conn,
   /* set socket non-blocking */
   (void)curlx_nonblock(sockfd, TRUE);
 
-  conn->connecttime = Curl_tvnow();
+  conn->connecttime = Curl_now();
   if(conn->num_addr > 1)
     Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME);
 
   /* Connect TCP sockets, bind UDP */
   if(!isconnected && (conn->socktype == SOCK_STREAM)) {
     if(conn->bits.tcp_fastopen) {
-#if defined(CONNECT_DATA_IDEMPOTENT) /* OS X */
-#ifdef HAVE_BUILTIN_AVAILABLE
+#if defined(CONNECT_DATA_IDEMPOTENT) /* Darwin */
+#  if defined(HAVE_BUILTIN_AVAILABLE)
+      /* while connectx function is available since macOS 10.11 / iOS 9,
+         it did not have the interface declared correctly until
+         Xcode 9 / macOS SDK 10.13 */
       if(__builtin_available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)) {
-#endif /* HAVE_BUILTIN_AVAILABLE */
         sa_endpoints_t endpoints;
         endpoints.sae_srcif = 0;
         endpoints.sae_srcaddr = NULL;
@@ -1072,13 +1090,22 @@ static CURLcode singleipconnect(struct connectdata *conn,
         rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
                       CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
                       NULL, 0, NULL, NULL);
-#ifdef HAVE_BUILTIN_AVAILABLE
       }
       else {
         rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
       }
-#endif /* HAVE_BUILTIN_AVAILABLE */
-#elif defined(MSG_FASTOPEN) /* Linux */
+#  else
+      rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+#  endif /* HAVE_BUILTIN_AVAILABLE */
+#elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */
+      if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
+                    (void *)&optval, sizeof(optval)) < 0)
+        infof(data, "Failed to enable TCP Fast Open on fd %d\n", sockfd);
+      else
+        infof(data, "TCP_FASTOPEN_CONNECT set\n");
+
+      rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+#elif defined(MSG_FASTOPEN) /* old Linux */
       if(conn->given->flags & PROTOPT_SSL)
         rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
       else
@@ -1097,10 +1124,6 @@ static CURLcode singleipconnect(struct connectdata *conn,
     return CURLE_OK;
   }
 
-#ifdef ENABLE_IPV6
-  conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
-#endif
-
   if(-1 == rc) {
     switch(error) {
     case EINPROGRESS:
@@ -1145,10 +1168,10 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
                           const struct Curl_dns_entry *remotehost)
 {
   struct Curl_easy *data = conn->data;
-  struct curltime before = Curl_tvnow();
+  struct curltime before = Curl_now();
   CURLcode result = CURLE_COULDNT_CONNECT;
 
-  time_t timeout_ms = Curl_timeleft(data, &before, TRUE);
+  timediff_t timeout_ms = Curl_timeleft(data, &before, TRUE);
 
   if(timeout_ms < 0) {
     /* a precaution, no need to continue if time already is up */
@@ -1225,7 +1248,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
     find.tofind = data->state.lastconnect;
     find.found = FALSE;
 
-    Curl_conncache_foreach(data->multi_easy?
+    Curl_conncache_foreach(data, data->multi_easy?
                            &data->multi_easy->conn_cache:
                            &data->multi->conn_cache, &find, conn_is_conn);
 
diff --git a/lib/connect.h b/lib/connect.h
index 3f05c39..3974486 100644
--- a/lib/connect.h
+++ b/lib/connect.h
@@ -25,6 +25,7 @@
 
 #include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */
 #include "sockaddr.h"
+#include "timeval.h"
 
 CURLcode Curl_is_connected(struct connectdata *conn,
                            int sockindex,
@@ -35,9 +36,9 @@ CURLcode Curl_connecthost(struct connectdata *conn,
 
 /* generic function that returns how much time there's left to run, according
    to the timeouts set */
-time_t Curl_timeleft(struct Curl_easy *data,
-                     struct curltime *nowp,
-                     bool duringconnect);
+timediff_t Curl_timeleft(struct Curl_easy *data,
+                         struct curltime *nowp,
+                         bool duringconnect);
 
 #define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
 #define HAPPY_EYEBALLS_TIMEOUT     200 /* milliseconds to wait between
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index 1102260..46bef0c 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -22,22 +22,43 @@
 
 #include "curl_setup.h"
 
-#ifdef HAVE_LIBZ
-
 #include "urldata.h"
 #include <curl/curl.h>
+#include <stddef.h>
+
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#ifdef __SYMBIAN32__
+/* zlib pollutes the namespace with this definition */
+#undef WIN32
+#endif
+#endif
+
+#ifdef HAVE_BROTLI
+#include <brotli/decode.h>
+#endif
+
 #include "sendf.h"
+#include "http.h"
 #include "content_encoding.h"
 #include "strdup.h"
+#include "strcase.h"
 #include "curl_memory.h"
 #include "memdebug.h"
 
+#define CONTENT_ENCODING_DEFAULT  "identity"
+
+#ifndef CURL_DISABLE_HTTP
+
+#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
+
+
+#ifdef HAVE_LIBZ
+
 /* Comment this out if zlib is always going to be at least ver. 1.2.0.4
    (doing so will reduce code size slightly). */
 #define OLD_ZLIB_SUPPORT 1
 
-#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
-
 #define GZIP_MAGIC_0 0x1f
 #define GZIP_MAGIC_1 0x8b
 
@@ -49,6 +70,24 @@
 #define COMMENT      0x10 /* bit 4 set: file comment present */
 #define RESERVED     0xE0 /* bits 5..7: reserved */
 
+typedef enum {
+  ZLIB_UNINIT,          /* uninitialized */
+  ZLIB_INIT,            /* initialized */
+  ZLIB_INFLATING,       /* Inflating started. */
+  ZLIB_GZIP_HEADER,     /* reading gzip header */
+  ZLIB_GZIP_TRAILER,    /* reading gzip trailer */
+  ZLIB_GZIP_INFLATING,  /* inflating gzip stream */
+  ZLIB_INIT_GZIP        /* initialized in transparent gzip mode */
+} zlibInitState;
+
+/* Writer parameters. */
+typedef struct {
+  zlibInitState zlib_init;   /* zlib init state */
+  uInt trailerlen;           /* Remaining trailer byte count. */
+  z_stream z;                /* State structure for zlib. */
+}  zlib_params;
+
+
 static voidpf
 zalloc_cb(voidpf opaque, unsigned int items, unsigned int size)
 {
@@ -79,114 +118,223 @@ process_zlib_error(struct connectdata *conn, z_stream *z)
 }
 
 static CURLcode
-exit_zlib(z_stream *z, zlibInitState *zlib_init, CURLcode result)
+exit_zlib(struct connectdata *conn,
+          z_stream *z, zlibInitState *zlib_init, CURLcode result)
 {
-  inflateEnd(z);
-  *zlib_init = ZLIB_UNINIT;
+  if(*zlib_init == ZLIB_GZIP_HEADER)
+    Curl_safefree(z->next_in);
+
+  if(*zlib_init != ZLIB_UNINIT) {
+    if(inflateEnd(z) != Z_OK && result == CURLE_OK)
+      result = process_zlib_error(conn, z);
+    *zlib_init = ZLIB_UNINIT;
+  }
+
   return result;
 }
 
-static CURLcode
-inflate_stream(struct connectdata *conn,
-               struct SingleRequest *k)
+static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp)
 {
-  int allow_restart = 1;
-  z_stream *z = &k->z;          /* zlib state structure */
+  z_stream *z = &zp->z;
+  CURLcode result = CURLE_OK;
+  uInt len = z->avail_in < zp->trailerlen? z->avail_in: zp->trailerlen;
+
+  /* Consume expected trailer bytes. Terminate stream if exhausted.
+     Issue an error if unexpected bytes follow. */
+
+  zp->trailerlen -= len;
+  z->avail_in -= len;
+  z->next_in += len;
+  if(z->avail_in)
+    result = CURLE_WRITE_ERROR;
+  if(result || !zp->trailerlen)
+    result = exit_zlib(conn, z, &zp->zlib_init, result);
+  else {
+    /* Only occurs for gzip with zlib < 1.2.0.4. */
+    zp->zlib_init = ZLIB_GZIP_TRAILER;
+  }
+  return result;
+}
+
+static CURLcode inflate_stream(struct connectdata *conn,
+                               contenc_writer *writer, zlibInitState started)
+{
+  zlib_params *zp = (zlib_params *) &writer->params;
+  z_stream *z = &zp->z;         /* zlib state structure */
   uInt nread = z->avail_in;
   Bytef *orig_in = z->next_in;
   int status;                   /* zlib status */
+  bool done = FALSE;
   CURLcode result = CURLE_OK;   /* Curl_client_write status */
   char *decomp;                 /* Put the decompressed data here. */
 
+  /* Check state. */
+  if(zp->zlib_init != ZLIB_INIT &&
+     zp->zlib_init != ZLIB_INFLATING &&
+     zp->zlib_init != ZLIB_INIT_GZIP &&
+     zp->zlib_init != ZLIB_GZIP_INFLATING)
+    return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR);
+
   /* Dynamically allocate a buffer for decompression because it's uncommonly
      large to hold on the stack */
   decomp = malloc(DSIZ);
-  if(decomp == NULL) {
-    return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
-  }
+  if(decomp == NULL)
+    return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
 
   /* because the buffer size is fixed, iteratively decompress and transfer to
-     the client via client_write. */
-  for(;;) {
+     the client via downstream_write function. */
+  while(!done) {
+    done = TRUE;
+
     /* (re)set buffer for decompressed output for every iteration */
-    z->next_out = (Bytef *)decomp;
+    z->next_out = (Bytef *) decomp;
     z->avail_out = DSIZ;
 
-    status = inflate(z, Z_SYNC_FLUSH);
-    if(status == Z_OK || status == Z_STREAM_END) {
-      allow_restart = 0;
-      if((DSIZ - z->avail_out) && (!k->ignorebody)) {
-        result = Curl_client_write(conn, CLIENTWRITE_BODY, decomp,
-                                   DSIZ - z->avail_out);
-        /* if !CURLE_OK, clean up, return */
+    status = inflate(z, Z_BLOCK);
+
+    /* Flush output data if some. */
+    if(z->avail_out != DSIZ) {
+      if(status == Z_OK || status == Z_STREAM_END) {
+        zp->zlib_init = started;      /* Data started. */
+        result = Curl_unencode_write(conn, writer->downstream, decomp,
+                                     DSIZ - z->avail_out);
         if(result) {
-          free(decomp);
-          return exit_zlib(z, &k->zlib_init, result);
+          exit_zlib(conn, z, &zp->zlib_init, result);
+          break;
         }
       }
-
-      /* Done? clean up, return */
-      if(status == Z_STREAM_END) {
-        free(decomp);
-        if(inflateEnd(z) == Z_OK)
-          return exit_zlib(z, &k->zlib_init, result);
-        return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
-      }
-
-      /* Done with these bytes, exit */
-
-      /* status is always Z_OK at this point! */
-      if(z->avail_in == 0) {
-        free(decomp);
-        return result;
-      }
     }
-    else if(allow_restart && status == Z_DATA_ERROR) {
+
+    /* Dispatch by inflate() status. */
+    switch(status) {
+    case Z_OK:
+      /* Always loop: there may be unflushed latched data in zlib state. */
+      done = FALSE;
+      break;
+    case Z_BUF_ERROR:
+      /* No more data to flush: just exit loop. */
+      break;
+    case Z_STREAM_END:
+      result = process_trailer(conn, zp);
+      break;
+    case Z_DATA_ERROR:
       /* some servers seem to not generate zlib headers, so this is an attempt
          to fix and continue anyway */
-
-      (void) inflateEnd(z);     /* don't care about the return code */
-      if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
-        free(decomp);
-        return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+      if(zp->zlib_init == ZLIB_INIT) {
+        /* Do not use inflateReset2(): only available since zlib 1.2.3.4. */
+        (void) inflateEnd(z);     /* don't care about the return code */
+        if(inflateInit2(z, -MAX_WBITS) == Z_OK) {
+          z->next_in = orig_in;
+          z->avail_in = nread;
+          zp->zlib_init = ZLIB_INFLATING;
+          done = FALSE;
+          break;
+        }
+        zp->zlib_init = ZLIB_UNINIT;    /* inflateEnd() already called. */
       }
-      z->next_in = orig_in;
-      z->avail_in = nread;
-      allow_restart = 0;
-      continue;
-    }
-    else {                      /* Error; exit loop, handle below */
-      free(decomp);
-      return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+      /* FALLTHROUGH */
+    default:
+      result = exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
+      break;
     }
   }
-  /* Will never get here */
+  free(decomp);
+
+  /* We're about to leave this call so the `nread' data bytes won't be seen
+     again. If we are in a state that would wrongly allow restart in raw mode
+     at the next call, assume output has already started. */
+  if(nread && zp->zlib_init == ZLIB_INIT)
+    zp->zlib_init = started;      /* Cannot restart anymore. */
+
+  return result;
 }
 
-CURLcode
-Curl_unencode_deflate_write(struct connectdata *conn,
-                            struct SingleRequest *k,
-                            ssize_t nread)
+
+/* Deflate handler. */
+static CURLcode deflate_init_writer(struct connectdata *conn,
+                                    contenc_writer *writer)
 {
-  z_stream *z = &k->z;          /* zlib state structure */
+  zlib_params *zp = (zlib_params *) &writer->params;
+  z_stream *z = &zp->z;     /* zlib state structure */
 
-  /* Initialize zlib? */
-  if(k->zlib_init == ZLIB_UNINIT) {
-    memset(z, 0, sizeof(z_stream));
-    z->zalloc = (alloc_func)zalloc_cb;
-    z->zfree = (free_func)zfree_cb;
+  if(!writer->downstream)
+    return CURLE_WRITE_ERROR;
 
-    if(inflateInit(z) != Z_OK)
-      return process_zlib_error(conn, z);
-    k->zlib_init = ZLIB_INIT;
-  }
+  /* Initialize zlib */
+  z->zalloc = (alloc_func) zalloc_cb;
+  z->zfree = (free_func) zfree_cb;
+
+  if(inflateInit(z) != Z_OK)
+    return process_zlib_error(conn, z);
+  zp->zlib_init = ZLIB_INIT;
+  return CURLE_OK;
+}
+
+static CURLcode deflate_unencode_write(struct connectdata *conn,
+                                       contenc_writer *writer,
+                                       const char *buf, size_t nbytes)
+{
+  zlib_params *zp = (zlib_params *) &writer->params;
+  z_stream *z = &zp->z;     /* zlib state structure */
 
   /* Set the compressed input when this function is called */
-  z->next_in = (Bytef *)k->str;
-  z->avail_in = (uInt)nread;
+  z->next_in = (Bytef *) buf;
+  z->avail_in = (uInt) nbytes;
 
   /* Now uncompress the data */
-  return inflate_stream(conn, k);
+  return inflate_stream(conn, writer, ZLIB_INFLATING);
+}
+
+static void deflate_close_writer(struct connectdata *conn,
+                                 contenc_writer *writer)
+{
+  zlib_params *zp = (zlib_params *) &writer->params;
+  z_stream *z = &zp->z;     /* zlib state structure */
+
+  exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
+}
+
+static const content_encoding deflate_encoding = {
+  "deflate",
+  NULL,
+  deflate_init_writer,
+  deflate_unencode_write,
+  deflate_close_writer,
+  sizeof(zlib_params)
+};
+
+
+/* Gzip handler. */
+static CURLcode gzip_init_writer(struct connectdata *conn,
+                                 contenc_writer *writer)
+{
+  zlib_params *zp = (zlib_params *) &writer->params;
+  z_stream *z = &zp->z;     /* zlib state structure */
+
+  if(!writer->downstream)
+    return CURLE_WRITE_ERROR;
+
+  /* Initialize zlib */
+  z->zalloc = (alloc_func) zalloc_cb;
+  z->zfree = (free_func) zfree_cb;
+
+  if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
+    /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
+    if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
+      return process_zlib_error(conn, z);
+    }
+    zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
+  }
+  else {
+    /* we must parse the gzip header and trailer ourselves */
+    if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
+      return process_zlib_error(conn, z);
+    }
+    zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */
+    zp->zlib_init = ZLIB_INIT; /* Initial call state */
+  }
+
+  return CURLE_OK;
 }
 
 #ifdef OLD_ZLIB_SUPPORT
@@ -273,47 +421,25 @@ static enum {
 }
 #endif
 
-CURLcode
-Curl_unencode_gzip_write(struct connectdata *conn,
-                         struct SingleRequest *k,
-                         ssize_t nread)
+static CURLcode gzip_unencode_write(struct connectdata *conn,
+                                    contenc_writer *writer,
+                                    const char *buf, size_t nbytes)
 {
-  z_stream *z = &k->z;          /* zlib state structure */
-
-  /* Initialize zlib? */
-  if(k->zlib_init == ZLIB_UNINIT) {
-    memset(z, 0, sizeof(z_stream));
-    z->zalloc = (alloc_func)zalloc_cb;
-    z->zfree = (free_func)zfree_cb;
-
-    if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
-      /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
-      if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
-        return process_zlib_error(conn, z);
-      }
-      k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
-    }
-    else {
-      /* we must parse the gzip header ourselves */
-      if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
-        return process_zlib_error(conn, z);
-      }
-      k->zlib_init = ZLIB_INIT;   /* Initial call state */
-    }
-  }
+  zlib_params *zp = (zlib_params *) &writer->params;
+  z_stream *z = &zp->z;     /* zlib state structure */
 
-  if(k->zlib_init == ZLIB_INIT_GZIP) {
+  if(zp->zlib_init == ZLIB_INIT_GZIP) {
     /* Let zlib handle the gzip decompression entirely */
-    z->next_in = (Bytef *)k->str;
-    z->avail_in = (uInt)nread;
+    z->next_in = (Bytef *) buf;
+    z->avail_in = (uInt) nbytes;
     /* Now uncompress the data */
-    return inflate_stream(conn, k);
+    return inflate_stream(conn, writer, ZLIB_INIT_GZIP);
   }
 
 #ifndef OLD_ZLIB_SUPPORT
   /* Support for old zlib versions is compiled away and we are running with
      an old version, so return an error. */
-  return exit_zlib(z, &k->zlib_init, CURLE_WRITE_ERROR);
+  return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR);
 
 #else
   /* This next mess is to get around the potential case where there isn't
@@ -326,18 +452,18 @@ Curl_unencode_gzip_write(struct connectdata *conn,
    * can handle the gzip header themselves.
    */
 
-  switch(k->zlib_init) {
+  switch(zp->zlib_init) {
   /* Skip over gzip header? */
   case ZLIB_INIT:
   {
     /* Initial call state */
     ssize_t hlen;
 
-    switch(check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
+    switch(check_gzip_header((unsigned char *) buf, nbytes, &hlen)) {
     case GZIP_OK:
-      z->next_in = (Bytef *)k->str + hlen;
-      z->avail_in = (uInt)(nread - hlen);
-      k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
+      z->next_in = (Bytef *) buf + hlen;
+      z->avail_in = (uInt) (nbytes - hlen);
+      zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
       break;
 
     case GZIP_UNDERFLOW:
@@ -348,19 +474,19 @@ Curl_unencode_gzip_write(struct connectdata *conn,
        * the first place, and it's even more unlikely for a transfer to fail
        * immediately afterwards, it should seldom be a problem.
        */
-      z->avail_in = (uInt)nread;
+      z->avail_in = (uInt) nbytes;
       z->next_in = malloc(z->avail_in);
       if(z->next_in == NULL) {
-        return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
+        return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
       }
-      memcpy(z->next_in, k->str, z->avail_in);
-      k->zlib_init = ZLIB_GZIP_HEADER;   /* Need more gzip header data state */
+      memcpy(z->next_in, buf, z->avail_in);
+      zp->zlib_init = ZLIB_GZIP_HEADER;  /* Need more gzip header data state */
       /* We don't have any data to inflate yet */
       return CURLE_OK;
 
     case GZIP_BAD:
     default:
-      return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+      return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
     }
 
   }
@@ -370,22 +496,22 @@ Curl_unencode_gzip_write(struct connectdata *conn,
   {
     /* Need more gzip header data state */
     ssize_t hlen;
-    z->avail_in += (uInt)nread;
+    z->avail_in += (uInt) nbytes;
     z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
     if(z->next_in == NULL) {
-      return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
+      return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
     }
     /* Append the new block of data to the previous one */
-    memcpy(z->next_in + z->avail_in - nread, k->str, nread);
+    memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes);
 
     switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) {
     case GZIP_OK:
       /* This is the zlib stream data */
       free(z->next_in);
       /* Don't point into the malloced block since we just freed it */
-      z->next_in = (Bytef *)k->str + hlen + nread - z->avail_in;
-      z->avail_in = (uInt)(z->avail_in - hlen);
-      k->zlib_init = ZLIB_GZIP_INFLATING;   /* Inflating stream state */
+      z->next_in = (Bytef *) buf + hlen + nbytes - z->avail_in;
+      z->avail_in = (uInt) (z->avail_in - hlen);
+      zp->zlib_init = ZLIB_GZIP_INFLATING;   /* Inflating stream state */
       break;
 
     case GZIP_UNDERFLOW:
@@ -394,18 +520,22 @@ Curl_unencode_gzip_write(struct connectdata *conn,
 
     case GZIP_BAD:
     default:
-      free(z->next_in);
-      return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+      return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
     }
 
   }
   break;
 
+  case ZLIB_GZIP_TRAILER:
+    z->next_in = (Bytef *) buf;
+    z->avail_in = (uInt) nbytes;
+    return process_trailer(conn, zp);
+
   case ZLIB_GZIP_INFLATING:
   default:
     /* Inflating stream state */
-    z->next_in = (Bytef *)k->str;
-    z->avail_in = (uInt)nread;
+    z->next_in = (Bytef *) buf;
+    z->avail_in = (uInt) nbytes;
     break;
   }
 
@@ -415,17 +545,469 @@ Curl_unencode_gzip_write(struct connectdata *conn,
   }
 
   /* We've parsed the header, now uncompress the data */
-  return inflate_stream(conn, k);
+  return inflate_stream(conn, writer, ZLIB_GZIP_INFLATING);
 #endif
 }
 
+static void gzip_close_writer(struct connectdata *conn,
+                              contenc_writer *writer)
+{
+  zlib_params *zp = (zlib_params *) &writer->params;
+  z_stream *z = &zp->z;     /* zlib state structure */
+
+  exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
+}
+
+static const content_encoding gzip_encoding = {
+  "gzip",
+  "x-gzip",
+  gzip_init_writer,
+  gzip_unencode_write,
+  gzip_close_writer,
+  sizeof(zlib_params)
+};
+
+#endif /* HAVE_LIBZ */
+
+
+#ifdef HAVE_BROTLI
+
+/* Writer parameters. */
+typedef struct {
+  BrotliDecoderState *br;    /* State structure for brotli. */
+}  brotli_params;
+
+
+static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
+{
+  switch(be) {
+  case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE:
+  case BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE:
+  case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET:
+  case BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME:
+  case BROTLI_DECODER_ERROR_FORMAT_CL_SPACE:
+  case BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE:
+  case BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT:
+  case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1:
+  case BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2:
+  case BROTLI_DECODER_ERROR_FORMAT_TRANSFORM:
+  case BROTLI_DECODER_ERROR_FORMAT_DICTIONARY:
+  case BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS:
+  case BROTLI_DECODER_ERROR_FORMAT_PADDING_1:
+  case BROTLI_DECODER_ERROR_FORMAT_PADDING_2:
+#ifdef BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY
+  case BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY:
+#endif
+#ifdef BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET
+  case BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET:
+#endif
+  case BROTLI_DECODER_ERROR_INVALID_ARGUMENTS:
+    return CURLE_BAD_CONTENT_ENCODING;
+  case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES:
+  case BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS:
+  case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP:
+  case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1:
+  case BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2:
+  case BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES:
+    return CURLE_OUT_OF_MEMORY;
+  default:
+    break;
+  }
+  return CURLE_WRITE_ERROR;
+}
+
+static CURLcode brotli_init_writer(struct connectdata *conn,
+                                   contenc_writer *writer)
+{
+  brotli_params *bp = (brotli_params *) &writer->params;
+
+  (void) conn;
+
+  if(!writer->downstream)
+    return CURLE_WRITE_ERROR;
+
+  bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL);
+  return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
+}
+
+static CURLcode brotli_unencode_write(struct connectdata *conn,
+                                      contenc_writer *writer,
+                                      const char *buf, size_t nbytes)
+{
+  brotli_params *bp = (brotli_params *) &writer->params;
+  const uint8_t *src = (const uint8_t *) buf;
+  char *decomp;
+  uint8_t *dst;
+  size_t dstleft;
+  CURLcode result = CURLE_OK;
+  BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
+
+  if(!bp->br)
+    return CURLE_WRITE_ERROR;  /* Stream already ended. */
+
+  decomp = malloc(DSIZ);
+  if(!decomp)
+    return CURLE_OUT_OF_MEMORY;
+
+  while((nbytes || r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) &&
+        result == CURLE_OK) {
+    dst = (uint8_t *) decomp;
+    dstleft = DSIZ;
+    r = BrotliDecoderDecompressStream(bp->br,
+                                      &nbytes, &src, &dstleft, &dst, NULL);
+    result = Curl_unencode_write(conn, writer->downstream,
+                                 decomp, DSIZ - dstleft);
+    if(result)
+      break;
+    switch(r) {
+    case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
+    case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
+      break;
+    case BROTLI_DECODER_RESULT_SUCCESS:
+      BrotliDecoderDestroyInstance(bp->br);
+      bp->br = NULL;
+      if(nbytes)
+        result = CURLE_WRITE_ERROR;
+      break;
+    default:
+      result = brotli_map_error(BrotliDecoderGetErrorCode(bp->br));
+      break;
+    }
+  }
+  free(decomp);
+  return result;
+}
+
+static void brotli_close_writer(struct connectdata *conn,
+                                contenc_writer *writer)
+{
+  brotli_params *bp = (brotli_params *) &writer->params;
+
+  (void) conn;
+
+  if(bp->br) {
+    BrotliDecoderDestroyInstance(bp->br);
+    bp->br = NULL;
+  }
+}
+
+static const content_encoding brotli_encoding = {
+  "br",
+  NULL,
+  brotli_init_writer,
+  brotli_unencode_write,
+  brotli_close_writer,
+  sizeof(brotli_params)
+};
+#endif
+
+
+/* Identity handler. */
+static CURLcode identity_init_writer(struct connectdata *conn,
+                                     contenc_writer *writer)
+{
+  (void) conn;
+  return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
+}
+
+static CURLcode identity_unencode_write(struct connectdata *conn,
+                                        contenc_writer *writer,
+                                        const char *buf, size_t nbytes)
+{
+  return Curl_unencode_write(conn, writer->downstream, buf, nbytes);
+}
+
+static void identity_close_writer(struct connectdata *conn,
+                                  contenc_writer *writer)
+{
+  (void) conn;
+  (void) writer;
+}
+
+static const content_encoding identity_encoding = {
+  "identity",
+  NULL,
+  identity_init_writer,
+  identity_unencode_write,
+  identity_close_writer,
+  0
+};
+
+
+/* supported content encodings table. */
+static const content_encoding * const encodings[] = {
+  &identity_encoding,
+#ifdef HAVE_LIBZ
+  &deflate_encoding,
+  &gzip_encoding,
+#endif
+#ifdef HAVE_BROTLI
+  &brotli_encoding,
+#endif
+  NULL
+};
+
+
+/* Return a list of comma-separated names of supported encodings. */
+char *Curl_all_content_encodings(void)
+{
+  size_t len = 0;
+  const content_encoding * const *cep;
+  const content_encoding *ce;
+  char *ace;
+  char *p;
+
+  for(cep = encodings; *cep; cep++) {
+    ce = *cep;
+    if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT))
+      len += strlen(ce->name) + 2;
+  }
+
+  if(!len)
+    return strdup(CONTENT_ENCODING_DEFAULT);
+
+  ace = malloc(len);
+  if(ace) {
+    p = ace;
+    for(cep = encodings; *cep; cep++) {
+      ce = *cep;
+      if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) {
+        strcpy(p, ce->name);
+        p += strlen(p);
+        *p++ = ',';
+        *p++ = ' ';
+      }
+    }
+    p[-2] = '\0';
+  }
+
+  return ace;
+}
+
+
+/* Real client writer: no downstream. */
+static CURLcode client_init_writer(struct connectdata *conn,
+                                   contenc_writer *writer)
+{
+  (void) conn;
+  return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
+}
+
+static CURLcode client_unencode_write(struct connectdata *conn,
+                                      contenc_writer *writer,
+                                      const char *buf, size_t nbytes)
+{
+  struct Curl_easy *data = conn->data;
+  struct SingleRequest *k = &data->req;
+
+  (void) writer;
+
+  if(!nbytes || k->ignorebody)
+    return CURLE_OK;
+
+  return Curl_client_write(conn, CLIENTWRITE_BODY, (char *) buf, nbytes);
+}
+
+static void client_close_writer(struct connectdata *conn,
+                                contenc_writer *writer)
+{
+  (void) conn;
+  (void) writer;
+}
+
+static const content_encoding client_encoding = {
+  NULL,
+  NULL,
+  client_init_writer,
+  client_unencode_write,
+  client_close_writer,
+  0
+};
+
+
+/* Deferred error dummy writer. */
+static CURLcode error_init_writer(struct connectdata *conn,
+                                  contenc_writer *writer)
+{
+  (void) conn;
+  return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
+}
+
+static CURLcode error_unencode_write(struct connectdata *conn,
+                                     contenc_writer *writer,
+                                     const char *buf, size_t nbytes)
+{
+  char *all = Curl_all_content_encodings();
+
+  (void) writer;
+  (void) buf;
+  (void) nbytes;
+
+  if(!all)
+    return CURLE_OUT_OF_MEMORY;
+  failf(conn->data, "Unrecognized content encoding type. "
+                    "libcurl understands %s content encodings.", all);
+  free(all);
+  return CURLE_BAD_CONTENT_ENCODING;
+}
+
+static void error_close_writer(struct connectdata *conn,
+                               contenc_writer *writer)
+{
+  (void) conn;
+  (void) writer;
+}
+
+static const content_encoding error_encoding = {
+  NULL,
+  NULL,
+  error_init_writer,
+  error_unencode_write,
+  error_close_writer,
+  0
+};
+
+/* Create an unencoding writer stage using the given handler. */
+static contenc_writer *new_unencoding_writer(struct connectdata *conn,
+                                             const content_encoding *handler,
+                                             contenc_writer *downstream)
+{
+  size_t sz = offsetof(contenc_writer, params) + handler->paramsize;
+  contenc_writer *writer = (contenc_writer *) malloc(sz);
+
+  if(writer) {
+    memset(writer, 0, sz);
+    writer->handler = handler;
+    writer->downstream = downstream;
+    if(handler->init_writer(conn, writer)) {
+      free(writer);
+      writer = NULL;
+    }
+  }
+
+  return writer;
+}
+
+/* Write data using an unencoding writer stack. */
+CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer,
+                             const char *buf, size_t nbytes)
+{
+  if(!nbytes)
+    return CURLE_OK;
+  return writer->handler->unencode_write(conn, writer, buf, nbytes);
+}
+
+/* Close and clean-up the connection's writer stack. */
 void Curl_unencode_cleanup(struct connectdata *conn)
 {
   struct Curl_easy *data = conn->data;
   struct SingleRequest *k = &data->req;
-  z_stream *z = &k->z;
-  if(k->zlib_init != ZLIB_UNINIT)
-    (void) exit_zlib(z, &k->zlib_init, CURLE_OK);
+  contenc_writer *writer = k->writer_stack;
+
+  while(writer) {
+    k->writer_stack = writer->downstream;
+    writer->handler->close_writer(conn, writer);
+    free(writer);
+    writer = k->writer_stack;
+  }
 }
 
-#endif /* HAVE_LIBZ */
+/* Find the content encoding by name. */
+static const content_encoding *find_encoding(const char *name, size_t len)
+{
+  const content_encoding * const *cep;
+  const content_encoding *ce;
+
+  for(cep = encodings; *cep; cep++) {
+    ce = *cep;
+    if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
+       (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
+      return ce;
+  }
+  return NULL;
+}
+
+/* Set-up the unencoding stack from the Content-Encoding header value.
+ * See RFC 7231 section 3.1.2.2. */
+CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
+                                     const char *enclist, int maybechunked)
+{
+  struct Curl_easy *data = conn->data;
+  struct SingleRequest *k = &data->req;
+
+  do {
+    const char *name;
+    size_t namelen;
+
+    /* Parse a single encoding name. */
+    while(ISSPACE(*enclist) || *enclist == ',')
+      enclist++;
+
+    name = enclist;
+
+    for(namelen = 0; *enclist && *enclist != ','; enclist++)
+      if(!ISSPACE(*enclist))
+        namelen = enclist - name + 1;
+
+    /* Special case: chunked encoding is handled at the reader level. */
+    if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) {
+      k->chunk = TRUE;             /* chunks coming our way. */
+      Curl_httpchunk_init(conn);   /* init our chunky engine. */
+    }
+    else if(namelen) {
+      const content_encoding *encoding = find_encoding(name, namelen);
+      contenc_writer *writer;
+
+      if(!k->writer_stack) {
+        k->writer_stack = new_unencoding_writer(conn, &client_encoding, NULL);
+
+        if(!k->writer_stack)
+          return CURLE_OUT_OF_MEMORY;
+      }
+
+      if(!encoding)
+        encoding = &error_encoding;  /* Defer error at stack use. */
+
+      /* Stack the unencoding stage. */
+      writer = new_unencoding_writer(conn, encoding, k->writer_stack);
+      if(!writer)
+        return CURLE_OUT_OF_MEMORY;
+      k->writer_stack = writer;
+    }
+  } while(*enclist);
+
+  return CURLE_OK;
+}
+
+#else
+/* Stubs for builds without HTTP. */
+CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
+                                     const char *enclist, int maybechunked)
+{
+  (void) conn;
+  (void) enclist;
+  (void) maybechunked;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer,
+                             const char *buf, size_t nbytes)
+{
+  (void) conn;
+  (void) writer;
+  (void) buf;
+  (void) nbytes;
+  return CURLE_NOT_BUILT_IN;
+}
+
+void Curl_unencode_cleanup(struct connectdata *conn)
+{
+  (void) conn;
+}
+
+char *Curl_all_content_encodings(void)
+{
+  return strdup(CONTENT_ENCODING_DEFAULT);  /* Satisfy caller. */
+}
+
+#endif /* CURL_DISABLE_HTTP */
diff --git a/lib/content_encoding.h b/lib/content_encoding.h
index 3fadd28..4cd52be 100644
--- a/lib/content_encoding.h
+++ b/lib/content_encoding.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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,26 +23,33 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
-/*
- * Comma-separated list all supported Content-Encodings ('identity' is implied)
- */
-#ifdef HAVE_LIBZ
-#define ALL_CONTENT_ENCODINGS "deflate, gzip"
-/* force a cleanup */
-void Curl_unencode_cleanup(struct connectdata *conn);
-#else
-#define ALL_CONTENT_ENCODINGS "identity"
-#define Curl_unencode_cleanup(x) Curl_nop_stmt
-#endif
+/* Decoding writer. */
+typedef struct contenc_writer_s contenc_writer;
+typedef struct content_encoding_s content_encoding;
+
+struct contenc_writer_s {
+  const content_encoding *handler;  /* Encoding handler. */
+  contenc_writer *downstream;  /* Downstream writer. */
+  void *params;  /* Encoding-specific storage (variable length). */
+};
 
-CURLcode Curl_unencode_deflate_write(struct connectdata *conn,
-                                     struct SingleRequest *req,
-                                     ssize_t nread);
+/* Content encoding writer. */
+struct content_encoding_s {
+  const char *name;        /* Encoding name. */
+  const char *alias;       /* Encoding name alias. */
+  CURLcode (*init_writer)(struct connectdata *conn, contenc_writer *writer);
+  CURLcode (*unencode_write)(struct connectdata *conn, contenc_writer *writer,
+                             const char *buf, size_t nbytes);
+  void (*close_writer)(struct connectdata *conn, contenc_writer *writer);
+  size_t paramsize;
+};
 
-CURLcode
-Curl_unencode_gzip_write(struct connectdata *conn,
-                         struct SingleRequest *k,
-                         ssize_t nread);
 
+CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
+                                     const char *enclist, int maybechunked);
+CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer,
+                             const char *buf, size_t nbytes);
+void Curl_unencode_cleanup(struct connectdata *conn);
+char *Curl_all_content_encodings(void);
 
 #endif /* HEADER_CURL_CONTENT_ENCODING_H */
diff --git a/lib/cookie.c b/lib/cookie.c
index 7fb596a..5f0f145 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -309,7 +309,7 @@ static void remove_expired(struct CookieInfo *cookies)
   while(co) {
     nx = co->next;
     if(co->expires && co->expires < now) {
-      if(co == cookies->cookies) {
+      if(!pv) {
         cookies->cookies = co->next;
       }
       else {
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
index 6eb28bb..ec76f75 100644
--- a/lib/curl_addrinfo.c
+++ b/lib/curl_addrinfo.c
@@ -27,6 +27,9 @@
 #ifdef HAVE_NETINET_IN_H
 #  include <netinet/in.h>
 #endif
+#ifdef HAVE_NETINET_IN6_H
+#  include <netinet/in6.h>
+#endif
 #ifdef HAVE_NETDB_H
 #  include <netdb.h>
 #endif
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index c80484f..e640cc6 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -398,9 +398,6 @@
 /* if zlib is available */
 #cmakedefine HAVE_LIBZ 1
 
-/* Define to 1 if you have the <limits.h> header file. */
-#cmakedefine HAVE_LIMITS_H 1
-
 /* if your compiler supports LL */
 #cmakedefine HAVE_LL 1
 
@@ -1000,3 +997,6 @@
 
 /* the signed version of size_t */
 #cmakedefine ssize_t ${ssize_t}
+
+/* Define to 1 if you have the mach_absolute_time function. */
+#cmakedefine HAVE_MACH_ABSOLUTE_TIME 1
diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c
index 631268b..f33bba1 100644
--- a/lib/curl_fnmatch.c
+++ b/lib/curl_fnmatch.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
@@ -133,6 +133,9 @@ static int setcharset(unsigned char **p, unsigned char *charset)
   unsigned char c;
   for(;;) {
     c = **p;
+    if(!c)
+      return SETCHARSET_FAIL;
+
     switch(state) {
     case CURLFNM_SCHS_DEFAULT:
       if(ISALNUM(c)) { /* ASCII value */
@@ -196,9 +199,6 @@ static int setcharset(unsigned char **p, unsigned char *charset)
         else
           return SETCHARSET_FAIL;
       }
-      else if(c == '\0') {
-        return SETCHARSET_FAIL;
-      }
       else {
         charset[c] = 1;
         (*p)++;
@@ -235,15 +235,10 @@ static int setcharset(unsigned char **p, unsigned char *charset)
         return SETCHARSET_FAIL;
       break;
     case CURLFNM_SCHS_MAYRANGE2:
-      if(c == '\\') {
-        c = *(++(*p));
-        if(!ISPRINT(c))
-          return SETCHARSET_FAIL;
-      }
       if(c == ']') {
         return SETCHARSET_OK;
       }
-      if(c == '\\') {
+      else if(c == '\\') {
         c = *(++(*p));
         if(ISPRINT(c)) {
           charset[c] = 1;
@@ -253,7 +248,7 @@ static int setcharset(unsigned char **p, unsigned char *charset)
         else
           return SETCHARSET_FAIL;
       }
-      if(c >= rangestart) {
+      else if(c >= rangestart) {
         if((ISLOWER(c) && ISLOWER(rangestart)) ||
            (ISDIGIT(c) && ISDIGIT(rangestart)) ||
            (ISUPPER(c) && ISUPPER(rangestart))) {
@@ -267,6 +262,8 @@ static int setcharset(unsigned char **p, unsigned char *charset)
         else
           return SETCHARSET_FAIL;
       }
+      else
+        return SETCHARSET_FAIL;
       break;
     case CURLFNM_SCHS_RIGHTBR:
       if(c == '[') {
@@ -277,9 +274,6 @@ static int setcharset(unsigned char **p, unsigned char *charset)
       else if(c == ']') {
         return SETCHARSET_OK;
       }
-      else if(c == '\0') {
-        return SETCHARSET_FAIL;
-      }
       else if(ISPRINT(c)) {
         charset[c] = 1;
         (*p)++;
@@ -307,7 +301,8 @@ fail:
   return SETCHARSET_FAIL;
 }
 
-static int loop(const unsigned char *pattern, const unsigned char *string)
+static int loop(const unsigned char *pattern, const unsigned char *string,
+                int maxstars)
 {
   loop_state state = CURLFNM_LOOP_DEFAULT;
   unsigned char *p = (unsigned char *)pattern;
@@ -319,11 +314,14 @@ static int loop(const unsigned char *pattern, const unsigned char *string)
     switch(state) {
     case CURLFNM_LOOP_DEFAULT:
       if(*p == '*') {
+        if(!maxstars)
+          return CURL_FNMATCH_NOMATCH;
         while(*(p + 1) == '*') /* eliminate multiple stars */
           p++;
         if(*s == '\0' && *(p + 1) == '\0')
           return CURL_FNMATCH_MATCH;
-        rc = loop(p + 1, s); /* *.txt matches .txt <=> .txt matches .txt */
+        rc = loop(p + 1, s, maxstars - 1); /* *.txt matches .txt <=>
+                                              .txt matches .txt */
         if(rc == CURL_FNMATCH_MATCH)
           return CURL_FNMATCH_MATCH;
         if(*s) /* let the star eat up one character */
@@ -382,7 +380,9 @@ static int loop(const unsigned char *pattern, const unsigned char *string)
 
           if(found) {
             p = pp + 1;
-            s++;
+            if(*s)
+              /* don't advance if we're matching on an empty string */
+              s++;
             memset(charset, 0, CURLFNM_CHSET_SIZE);
           }
           else
@@ -420,5 +420,5 @@ int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
   if(!pattern || !string) {
     return CURL_FNMATCH_FAIL;
   }
-  return loop((unsigned char *)pattern, (unsigned char *)string);
+  return loop((unsigned char *)pattern, (unsigned char *)string, 5);
 }
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
index 5154949..e896276 100644
--- a/lib/curl_ntlm_core.c
+++ b/lib/curl_ntlm_core.c
@@ -557,7 +557,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
                                    unsigned char *ntbuffer /* 21 bytes */)
 {
   size_t len = strlen(password);
-  unsigned char *pw = malloc(len * 2);
+  unsigned char *pw = len ? malloc(len * 2) : strdup("");
   CURLcode result;
   if(!pw)
     return CURLE_OUT_OF_MEMORY;
@@ -646,6 +646,15 @@ CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
   return CURLE_OK;
 }
 
+#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
+
 /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
  * (uppercase UserName + Domain) as the data
  */
@@ -655,10 +664,20 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
                                        unsigned char *ntlmv2hash)
 {
   /* Unicode representation */
-  size_t identity_len = (userlen + domlen) * 2;
-  unsigned char *identity = malloc(identity_len);
+  size_t identity_len;
+  unsigned char *identity;
   CURLcode result = CURLE_OK;
 
+  /* we do the length checks below separately to avoid integer overflow risk
+     on extreme data lengths */
+  if((userlen > SIZE_T_MAX/2) ||
+     (domlen > SIZE_T_MAX/2) ||
+     ((userlen + domlen) > SIZE_T_MAX/2))
+    return CURLE_OUT_OF_MEMORY;
+
+  identity_len = (userlen + domlen) * 2;
+  identity = malloc(identity_len);
+
   if(!identity)
     return CURLE_OUT_OF_MEMORY;
 
diff --git a/lib/curl_path.c b/lib/curl_path.c
new file mode 100644
index 0000000..e843dea
--- /dev/null
+++ b/lib/curl_path.c
@@ -0,0 +1,195 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, 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 "curl_memory.h"
+#include "curl_path.h"
+#include "escape.h"
+#include "memdebug.h"
+
+/* figure out the path to work with in this particular request */
+CURLcode Curl_getworkingpath(struct connectdata *conn,
+                             char *homedir,  /* when SFTP is used */
+                             char **path) /* returns the  allocated
+                                             real path to work with */
+{
+  struct Curl_easy *data = conn->data;
+  char *real_path = NULL;
+  char *working_path;
+  size_t working_path_len;
+  CURLcode result =
+    Curl_urldecode(data, data->state.path, 0, &working_path,
+                   &working_path_len, FALSE);
+  if(result)
+    return result;
+
+  /* Check for /~/, indicating relative to the user's home directory */
+  if(conn->handler->protocol & CURLPROTO_SCP) {
+    real_path = malloc(working_path_len + 1);
+    if(real_path == NULL) {
+      free(working_path);
+      return CURLE_OUT_OF_MEMORY;
+    }
+    if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
+      /* It is referenced to the home directory, so strip the leading '/~/' */
+      memcpy(real_path, working_path + 3, 4 + working_path_len-3);
+    else
+      memcpy(real_path, working_path, 1 + working_path_len);
+  }
+  else if(conn->handler->protocol & CURLPROTO_SFTP) {
+    if((working_path_len > 1) && (working_path[1] == '~')) {
+      size_t homelen = strlen(homedir);
+      real_path = malloc(homelen + working_path_len + 1);
+      if(real_path == NULL) {
+        free(working_path);
+        return CURLE_OUT_OF_MEMORY;
+      }
+      /* It is referenced to the home directory, so strip the
+         leading '/' */
+      memcpy(real_path, homedir, homelen);
+      real_path[homelen] = '/';
+      real_path[homelen + 1] = '\0';
+      if(working_path_len > 3) {
+        memcpy(real_path + homelen + 1, working_path + 3,
+               1 + working_path_len -3);
+      }
+    }
+    else {
+      real_path = malloc(working_path_len + 1);
+      if(real_path == NULL) {
+        free(working_path);
+        return CURLE_OUT_OF_MEMORY;
+      }
+      memcpy(real_path, working_path, 1 + working_path_len);
+    }
+  }
+
+  free(working_path);
+
+  /* store the pointer for the caller to receive */
+  *path = real_path;
+
+  return CURLE_OK;
+}
+
+/* The get_pathname() function is being borrowed from OpenSSH sftp.c
+   version 4.6p1. */
+/*
+ * Copyright (c) 2001-2004 Damien Miller <djm at openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
+{
+  const char *cp = *cpp, *end;
+  char quot;
+  unsigned int i, j;
+  size_t fullPathLength, pathLength;
+  bool relativePath = false;
+  static const char WHITESPACE[] = " \t\r\n";
+
+  if(!*cp) {
+    *cpp = NULL;
+    *path = NULL;
+    return CURLE_QUOTE_ERROR;
+  }
+  /* Ignore leading whitespace */
+  cp += strspn(cp, WHITESPACE);
+  /* Allocate enough space for home directory and filename + separator */
+  fullPathLength = strlen(cp) + strlen(homedir) + 2;
+  *path = malloc(fullPathLength);
+  if(*path == NULL)
+    return CURLE_OUT_OF_MEMORY;
+
+  /* Check for quoted filenames */
+  if(*cp == '\"' || *cp == '\'') {
+    quot = *cp++;
+
+    /* Search for terminating quote, unescape some chars */
+    for(i = j = 0; i <= strlen(cp); i++) {
+      if(cp[i] == quot) {  /* Found quote */
+        i++;
+        (*path)[j] = '\0';
+        break;
+      }
+      if(cp[i] == '\0') {  /* End of string */
+        /*error("Unterminated quote");*/
+        goto fail;
+      }
+      if(cp[i] == '\\') {  /* Escaped characters */
+        i++;
+        if(cp[i] != '\'' && cp[i] != '\"' &&
+            cp[i] != '\\') {
+          /*error("Bad escaped character '\\%c'",
+              cp[i]);*/
+          goto fail;
+        }
+      }
+      (*path)[j++] = cp[i];
+    }
+
+    if(j == 0) {
+      /*error("Empty quotes");*/
+      goto fail;
+    }
+    *cpp = cp + i + strspn(cp + i, WHITESPACE);
+  }
+  else {
+    /* Read to end of filename - either to white space or terminator */
+    end = strpbrk(cp, WHITESPACE);
+    if(end == NULL)
+      end = strchr(cp, '\0');
+    /* return pointer to second parameter if it exists */
+    *cpp = end + strspn(end, WHITESPACE);
+    pathLength = 0;
+    relativePath = (cp[0] == '/' && cp[1] == '~' && cp[2] == '/');
+    /* Handling for relative path - prepend home directory */
+    if(relativePath) {
+      strcpy(*path, homedir);
+      pathLength = strlen(homedir);
+      (*path)[pathLength++] = '/';
+      (*path)[pathLength] = '\0';
+      cp += 3;
+    }
+    /* Copy path name up until first "white space" */
+    memcpy(&(*path)[pathLength], cp, (int)(end - cp));
+    pathLength += (int)(end - cp);
+    (*path)[pathLength] = '\0';
+  }
+  return CURLE_OK;
+
+  fail:
+  Curl_safefree(*path);
+  return CURLE_QUOTE_ERROR;
+}
diff --git a/lib/vauth/digest.h b/lib/curl_path.h
similarity index 62%
copy from lib/vauth/digest.h
copy to lib/curl_path.h
index 5722dce..f9d4327 100644
--- a/lib/vauth/digest.h
+++ b/lib/curl_path.h
@@ -1,5 +1,3 @@
-#ifndef HEADER_CURL_DIGEST_H
-#define HEADER_CURL_DIGEST_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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 +20,25 @@
  *
  ***************************************************************************/
 
+#include "curl_setup.h"
 #include <curl/curl.h>
+#include "urldata.h"
 
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
-
-#define DIGEST_MAX_VALUE_LENGTH           256
-#define DIGEST_MAX_CONTENT_LENGTH         1024
-
-enum {
-  CURLDIGESTALGO_MD5,
-  CURLDIGESTALGO_MD5SESS
-};
-
-/* This is used to extract the realm from a challenge message */
-bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
-                               const char **endptr);
+#ifdef WIN32
+#  undef  PATH_MAX
+#  define PATH_MAX MAX_PATH
+#  ifndef R_OK
+#    define R_OK 4
+#  endif
+#endif
 
+#ifndef PATH_MAX
+#define PATH_MAX 1024 /* just an extra precaution since there are systems that
+                         have their definition hidden well */
 #endif
 
-#endif /* HEADER_CURL_DIGEST_H */
+CURLcode Curl_getworkingpath(struct connectdata *conn,
+                             char *homedir,
+                             char **path);
+
+CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir);
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index 402ebc0..609ee9e 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.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
@@ -416,6 +416,14 @@
 #  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))
+
 /*
  * Arg 2 type for gethostname in case it hasn't been defined in config file.
  */
@@ -751,9 +759,10 @@ endings either CRLF or LF so 't' is appropriate.
 
 /* Detect Windows App environment which has a restricted access
  * to the Win32 APIs. */
-# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)
+# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
+  defined(WINAPI_FAMILY)
 #  include <winapifamily.h>
-#  if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
+#  if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) &&  \
      !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
 #    define CURL_WINDOWS_APP
 #  endif
diff --git a/lib/vauth/digest.h b/lib/curl_sha256.h
similarity index 62%
copy from lib/vauth/digest.h
copy to lib/curl_sha256.h
index 5722dce..6db4b04 100644
--- a/lib/vauth/digest.h
+++ b/lib/curl_sha256.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_DIGEST_H
-#define HEADER_CURL_DIGEST_H
+#ifndef HEADER_CURL_SHA256_H
+#define HEADER_CURL_SHA256_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2010, Florin Petriuc, <petriuc.florin at gmail.com>
  *
  * 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,11 @@
  *
  ***************************************************************************/
 
-#include <curl/curl.h>
+#ifndef CURL_DISABLE_CRYPTO_AUTH
 
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
-
-#define DIGEST_MAX_VALUE_LENGTH           256
-#define DIGEST_MAX_CONTENT_LENGTH         1024
-
-enum {
-  CURLDIGESTALGO_MD5,
-  CURLDIGESTALGO_MD5SESS
-};
-
-/* This is used to extract the realm from a challenge message */
-bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
-                               const char **endptr);
+void Curl_sha256it(unsigned char *outbuffer,
+                const unsigned char *input);
 
 #endif
 
-#endif /* HEADER_CURL_DIGEST_H */
+#endif /* HEADER_CURL_SHA256_H */
diff --git a/lib/curlx.h b/lib/curlx.h
index 6168dc1..6e41826 100644
--- a/lib/curlx.h
+++ b/lib/curlx.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@
    curl_off_t number from a given string.
 */
 
-#include "timeval.h"
-/*
-  "timeval.h" sets up a 'struct timeval' even for platforms that otherwise
-  don't have one and has protos for these functions:
-
-  curlx_tvnow()
-  curlx_tvdiff()
-  curlx_tvdiff_secs()
-*/
-
 #include "nonblock.h"
 /* "nonblock.h" provides curlx_nonblock() */
 
diff --git a/lib/easy.c b/lib/easy.c
index 5328f9c..edc716d 100644
--- a/lib/easy.c
+++ b/lib/easy.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
@@ -65,13 +65,15 @@
 #include "sendf.h" /* for failf function prototype */
 #include "connect.h" /* for Curl_getconnectinfo */
 #include "slist.h"
+#include "mime.h"
 #include "amigaos.h"
 #include "non-ascii.h"
 #include "warnless.h"
-#include "conncache.h"
 #include "multiif.h"
 #include "sigpipe.h"
 #include "ssh.h"
+#include "setopt.h"
+
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -214,11 +216,10 @@ static CURLcode global_init(long flags, bool memoryfuncs)
 #endif
   }
 
-  if(flags & CURL_GLOBAL_SSL)
-    if(!Curl_ssl_init()) {
-      DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
-      return CURLE_FAILED_INIT;
-    }
+  if(!Curl_ssl_init()) {
+    DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
+    return CURLE_FAILED_INIT;
+  }
 
   if(flags & CURL_GLOBAL_WIN32)
     if(win32_init()) {
@@ -253,6 +254,13 @@ static CURLcode global_init(long flags, bool memoryfuncs)
   }
 #endif
 
+#if defined(USE_LIBSSH)
+  if(ssh_init()) {
+    DEBUGF(fprintf(stderr, "Error: libssh_init failed\n"));
+    return CURLE_FAILED_INIT;
+  }
+#endif
+
   if(flags & CURL_GLOBAL_ACK_EINTR)
     Curl_ack_eintr = 1;
 
@@ -318,10 +326,7 @@ void curl_global_cleanup(void)
     return;
 
   Curl_global_host_cache_dtor();
-
-  if(init_flags & CURL_GLOBAL_SSL)
-    Curl_ssl_cleanup();
-
+  Curl_ssl_cleanup();
   Curl_resolver_global_cleanup();
 
   if(init_flags & CURL_GLOBAL_WIN32)
@@ -333,6 +338,10 @@ void curl_global_cleanup(void)
   (void)libssh2_exit();
 #endif
 
+#if defined(USE_LIBSSH)
+  (void)ssh_finalize();
+#endif
+
   init_flags  = 0;
 }
 
@@ -365,28 +374,6 @@ struct Curl_easy *curl_easy_init(void)
   return data;
 }
 
-/*
- * curl_easy_setopt() is the external interface for setting options on an
- * easy handle.
- */
-
-#undef curl_easy_setopt
-CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
-{
-  va_list arg;
-  CURLcode result;
-
-  if(!data)
-    return CURLE_BAD_FUNCTION_ARGUMENT;
-
-  va_start(arg, tag);
-
-  result = Curl_setopt(data, tag, arg);
-
-  va_end(arg);
-  return result;
-}
-
 #ifdef CURLDEBUG
 
 struct socketmonitor {
@@ -586,12 +573,12 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
     }
 
     /* get the time stamp to use to figure out how long poll takes */
-    before = curlx_tvnow();
+    before = Curl_now();
 
     /* wait for activity or timeout */
     pollrc = Curl_poll(fds, numfds, (int)ev->ms);
 
-    after = curlx_tvnow();
+    after = Curl_now();
 
     ev->msbump = FALSE; /* reset here */
 
@@ -619,7 +606,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
         /* If nothing updated the timeout, we decrease it by the spent time.
          * If it was updated, it has the new timeout time stored already.
          */
-        time_t timediff = curlx_tvdiff(after, before);
+        timediff_t timediff = Curl_timediff(after, before);
         if(timediff > 0) {
           if(timediff > ev->ms)
             ev->ms = 0;
@@ -680,17 +667,17 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
     int still_running = 0;
     int rc;
 
-    before = curlx_tvnow();
+    before = Curl_now();
     mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc);
 
     if(!mcode) {
       if(!rc) {
-        struct curltime after = curlx_tvnow();
+        struct curltime after = Curl_now();
 
         /* If it returns without any filedescriptor instantly, we need to
            avoid busy-looping during periods where it has nothing particular
            to wait for */
-        if(curlx_tvdiff(after, before) <= 10) {
+        if(Curl_timediff(after, before) <= 10) {
           without_fds++;
           if(without_fds > 2) {
             int sleep_ms = without_fds < 10 ? (1 << (without_fds - 1)) : 1000;
@@ -861,6 +848,44 @@ CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...)
   return result;
 }
 
+static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
+{
+  CURLcode result = CURLE_OK;
+  enum dupstring i;
+
+  /* Copy src->set into dst->set first, then deal with the strings
+     afterwards */
+  dst->set = src->set;
+  Curl_mime_initpart(&dst->set.mimepost, dst);
+
+  /* clear all string pointers first */
+  memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
+
+  /* duplicate all strings */
+  for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
+    result = Curl_setstropt(&dst->set.str[i], src->set.str[i]);
+    if(result)
+      return result;
+  }
+
+  /* duplicate memory areas pointed to */
+  i = STRING_COPYPOSTFIELDS;
+  if(src->set.postfieldsize && src->set.str[i]) {
+    /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
+    dst->set.str[i] = Curl_memdup(src->set.str[i],
+                                  curlx_sotouz(src->set.postfieldsize));
+    if(!dst->set.str[i])
+      return CURLE_OUT_OF_MEMORY;
+    /* point to the new copy */
+    dst->set.postfields = dst->set.str[i];
+  }
+
+  /* Duplicate mime data. */
+  result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost);
+
+  return result;
+}
+
 /*
  * curl_easy_duphandle() is an external interface to allow duplication of a
  * given input easy handle. The returned handle will be a new working handle
@@ -888,7 +913,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
   outcurl->state.headersize = HEADERSIZE;
 
   /* copy all userdefined values */
-  if(Curl_dupset(outcurl, data))
+  if(dupset(outcurl, data))
     goto fail;
 
   /* the connection cache is setup on demand */
@@ -978,7 +1003,7 @@ void curl_easy_reset(struct Curl_easy *data)
   /* zero out UserDefined data: */
   Curl_freeset(data);
   memset(&data->set, 0, sizeof(struct UserDefined));
-  (void)Curl_init_userdefined(&data->set);
+  (void)Curl_init_userdefined(data);
 
   /* zero out Progress data: */
   memset(&data->progress, 0, sizeof(struct Progress));
@@ -1025,6 +1050,8 @@ 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 Curl_easy *saved_data = NULL;
 
     /* copy the structs to allow for immediate re-pausing */
     for(i = 0; i < data->state.tempcount; i++) {
@@ -1033,16 +1060,27 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
     }
     data->state.tempcount = 0;
 
+    /* set the connection's current owner */
+    if(conn->data != data) {
+      saved_data = conn->data;
+      conn->data = data;
+    }
+
     for(i = 0; i < count; i++) {
       /* even if one function returns error, this loops through and frees all
          buffers */
       if(!result)
-        result = Curl_client_chop_write(data->easy_conn,
+        result = Curl_client_chop_write(conn,
                                         writebuf[i].type,
                                         writebuf[i].buf,
                                         writebuf[i].len);
       free(writebuf[i].buf);
     }
+
+    /* recover previous owner of the connection */
+    if(saved_data)
+      conn->data = saved_data;
+
     if(result)
       return result;
   }
diff --git a/lib/file.c b/lib/file.c
index 7cfdab1..0bbc0e1 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -404,7 +404,7 @@ static CURLcode file_upload(struct connectdata *conn)
     if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
     else
-      result = Curl_speedcheck(data, Curl_tvnow());
+      result = Curl_speedcheck(data, Curl_now());
   }
   if(!result && Curl_pgrsUpdate(conn))
     result = CURLE_ABORTED_BY_CALLBACK;
@@ -589,7 +589,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
     if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
     else
-      result = Curl_speedcheck(data, Curl_tvnow());
+      result = Curl_speedcheck(data, Curl_now());
   }
   if(Curl_pgrsUpdate(conn))
     result = CURLE_ABORTED_BY_CALLBACK;
diff --git a/lib/formdata.c b/lib/formdata.c
index 3568ac5..d0579c5 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -907,7 +907,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
         result = curl_mime_headers(part, file->contentheader, 0);
 
       /* Set the content type. */
-      if(!result &&file->contenttype)
+      if(!result && file->contenttype)
         result = curl_mime_type(part, file->contenttype);
 
       /* Set field name. */
diff --git a/lib/ftp.c b/lib/ftp.c
index 54ba405..8042edf 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -182,7 +182,8 @@ const struct Curl_handler Curl_handler_ftp = {
   PORT_FTP,                        /* defport */
   CURLPROTO_FTP,                   /* protocol */
   PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD |
-  PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP /* flags */
+  PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP |
+  PROTOPT_WILDCARD /* flags */
 };
 
 
@@ -210,7 +211,7 @@ const struct Curl_handler Curl_handler_ftps = {
   PORT_FTPS,                       /* defport */
   CURLPROTO_FTPS,                  /* protocol */
   PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
-  PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY /* flags */
+  PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */
 };
 #endif
 
@@ -332,16 +333,16 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
  * Curl_pgrsTime(..., TIMER_STARTACCEPT);
  *
  */
-static time_t ftp_timeleft_accept(struct Curl_easy *data)
+static timediff_t ftp_timeleft_accept(struct Curl_easy *data)
 {
-  time_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
-  time_t other;
+  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_tvnow();
+  now = Curl_now();
 
   /* check if the generic timeout possibly is set shorter */
   other =  Curl_timeleft(data, &now, FALSE);
@@ -351,7 +352,7 @@ static time_t ftp_timeleft_accept(struct Curl_easy *data)
     timeout_ms = other;
   else {
     /* subtract elapsed time */
-    timeout_ms -= Curl_tvdiff(now, data->progress.t_acceptdata);
+    timeout_ms -= Curl_timediff(now, data->progress.t_acceptdata);
     if(!timeout_ms)
       /* avoid returning 0 as that means no timeout! */
       return -1;
@@ -1457,25 +1458,22 @@ static CURLcode ftp_state_list(struct connectdata *conn)
      then just do LIST (in that case: nothing to do here)
   */
   char *cmd, *lstArg, *slashPos;
+  const char *inpath = data->state.path;
 
   lstArg = NULL;
   if((data->set.ftp_filemethod == FTPFILE_NOCWD) &&
-     data->state.path &&
-     data->state.path[0] &&
-     strchr(data->state.path, '/')) {
-
-    lstArg = strdup(data->state.path);
-    if(!lstArg)
-      return CURLE_OUT_OF_MEMORY;
+     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(lstArg[strlen(lstArg) - 1] != '/') {
-
+    if(inpath[n - 1] != '/') {
       /* chop off the file part if format is dir/dir/file */
-      slashPos = strrchr(lstArg, '/');
-      if(slashPos)
-        *(slashPos + 1) = '\0';
+      slashPos = strrchr(inpath, '/');
+      n = slashPos - inpath;
     }
+    result = Curl_urldecode(data, inpath, n, &lstArg, NULL, FALSE);
+    if(result)
+      return result;
   }
 
   cmd = aprintf("%s%s%s",
@@ -1877,8 +1875,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
   else if((ftpc->count1 == 1) &&
           (ftpcode == 227)) {
     /* positive PASV response */
-    int ip[4];
-    int port[2];
+    unsigned int ip[4];
+    unsigned int port[2];
 
     /*
      * Scan for a sequence of six comma-separated numbers and use them as
@@ -1890,14 +1888,15 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
      * "227 Entering passive mode. 127,0,0,1,4,51"
      */
     while(*str) {
-      if(6 == sscanf(str, "%d,%d,%d,%d,%d,%d",
+      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) {
+    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;
     }
@@ -2419,8 +2418,8 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
       char *bytes;
       char *buf = data->state.buffer;
       bytes = strstr(buf, " bytes");
-      if(bytes--) {
-        long in = (long)(bytes-buf);
+      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 */
@@ -3179,7 +3178,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
   /* now store a copy of the directory we are in */
   free(ftpc->prevpath);
 
-  if(data->set.wildcardmatch) {
+  if(data->state.wildcardmatch) {
     if(data->set.chunk_end && ftpc->file) {
       data->set.chunk_end(data->wildcard.customptr);
     }
@@ -3263,7 +3262,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
     long old_time = pp->response_time;
 
     pp->response_time = 60*1000; /* give it only a minute for now */
-    pp->response = Curl_tvnow(); /* timeout relative now */
+    pp->response = Curl_now(); /* timeout relative now */
 
     result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
 
@@ -3383,7 +3382,7 @@ CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
 
       PPSENDF(&conn->proto.ftpc.pp, "%s", cmd);
 
-      pp->response = Curl_tvnow(); /* timeout relative now */
+      pp->response = Curl_now(); /* timeout relative now */
 
       result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
       if(result)
@@ -3964,7 +3963,7 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
   *done = FALSE; /* default to false */
   ftpc->wait_data_conn = FALSE; /* default to no such wait */
 
-  if(conn->data->set.wildcardmatch) {
+  if(conn->data->state.wildcardmatch) {
     result = wc_statemach(conn);
     if(conn->data->wildcard.state == CURLWC_SKIP ||
       conn->data->wildcard.state == CURLWC_DONE) {
diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c
index b2a8c0f..262ac03 100644
--- a/lib/ftplistparser.c
+++ b/lib/ftplistparser.c
@@ -264,16 +264,6 @@ static int ftp_pl_get_permission(const char *str)
   return permissions;
 }
 
-static void PL_ERROR(struct connectdata *conn, CURLcode err)
-{
-  struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
-  struct ftp_parselist_data *parser = tmpdata->parser;
-  if(parser->file_data)
-    Curl_fileinfo_dtor(NULL, parser->file_data);
-  parser->file_data = NULL;
-  parser->error = err;
-}
-
 static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
                                     struct fileinfo *infop)
 {
@@ -338,6 +328,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
   struct curl_fileinfo *finfo;
   unsigned long i = 0;
   CURLcode result;
+  size_t retsize = bufflen;
 
   if(parser->error) { /* error in previous call */
     /* scenario:
@@ -346,7 +337,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
      * 3. (last) call => is skipped RIGHT HERE and the error is hadled later
      *    in wc_statemach()
      */
-    return bufflen;
+    goto fail;
   }
 
   if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) {
@@ -362,12 +353,12 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
       parser->file_data = Curl_fileinfo_alloc();
       if(!parser->file_data) {
         parser->error = CURLE_OUT_OF_MEMORY;
-        return bufflen;
+        goto fail;
       }
       parser->file_data->info.b_data = malloc(FTP_BUFFER_ALLOCSIZE);
       if(!parser->file_data->info.b_data) {
-        PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
-        return bufflen;
+        parser->error = CURLE_OUT_OF_MEMORY;
+        goto fail;
       }
       parser->file_data->info.b_size = FTP_BUFFER_ALLOCSIZE;
       parser->item_offset = 0;
@@ -390,8 +381,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
         Curl_fileinfo_dtor(NULL, parser->file_data);
         parser->file_data = NULL;
         parser->error = CURLE_OUT_OF_MEMORY;
-        PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
-        return bufflen;
+        goto fail;
       }
     }
 
@@ -429,15 +419,15 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
               while(ISDIGIT(*endptr))
                 endptr++;
               if(*endptr != 0) {
-                PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-                return bufflen;
+                parser->error = CURLE_FTP_BAD_FILE_LIST;
+                goto fail;
               }
               parser->state.UNIX.main = PL_UNIX_FILETYPE;
               finfo->b_used = 0;
             }
             else {
-              PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-              return bufflen;
+              parser->error = CURLE_FTP_BAD_FILE_LIST;
+              goto fail;
             }
           }
           break;
@@ -470,8 +460,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
           finfo->filetype = CURLFILETYPE_DOOR;
           break;
         default:
-          PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-          return bufflen;
+          parser->error = CURLE_FTP_BAD_FILE_LIST;
+          goto fail;
         }
         parser->state.UNIX.main = PL_UNIX_PERMISSION;
         parser->item_length = 0;
@@ -481,21 +471,21 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
         parser->item_length++;
         if(parser->item_length <= 9) {
           if(!strchr("rwx-tTsS", c)) {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
         }
         else if(parser->item_length == 10) {
           unsigned int perm;
           if(c != ' ') {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           finfo->b_data[10] = 0; /* terminate permissions */
           perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset);
           if(perm & FTP_LP_MALFORMATED_PERM) {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM;
           parser->file_data->info.perm = perm;
@@ -516,8 +506,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
               parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
             }
             else {
-              PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-              return bufflen;
+              parser->error = CURLE_FTP_BAD_FILE_LIST;
+              goto fail;
             }
           }
           break;
@@ -538,8 +528,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE;
           }
           else if(c < '0' || c > '9') {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           break;
         }
@@ -598,8 +588,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
               parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
             }
             else {
-              PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-              return bufflen;
+              parser->error = CURLE_FTP_BAD_FILE_LIST;
+              goto fail;
             }
           }
           break;
@@ -623,8 +613,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             }
           }
           else if(!ISDIGIT(c)) {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           break;
         }
@@ -639,8 +629,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
               parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
             }
             else {
-              PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-              return bufflen;
+              parser->error = CURLE_FTP_BAD_FILE_LIST;
+              goto fail;
             }
           }
           break;
@@ -650,8 +640,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
           }
           else if(!ISALNUM(c) && c != '.') {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           break;
         case PL_UNIX_TIME_PREPART2:
@@ -661,8 +651,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
               parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
             }
             else {
-              PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-              return bufflen;
+              parser->error = CURLE_FTP_BAD_FILE_LIST;
+              goto fail;
             }
           }
           break;
@@ -672,8 +662,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
           }
           else if(!ISALNUM(c) && c != '.') {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           break;
         case PL_UNIX_TIME_PREPART3:
@@ -683,8 +673,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
               parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
             }
             else {
-              PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-              return bufflen;
+              parser->error = CURLE_FTP_BAD_FILE_LIST;
+              goto fail;
             }
           }
           break;
@@ -708,8 +698,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             }
           }
           else if(!ISALNUM(c) && c != '.' && c != ':') {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           break;
         }
@@ -734,8 +724,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.UNIX.main = PL_UNIX_FILETYPE;
             result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
-              PL_ERROR(conn, result);
-              return bufflen;
+              parser->error = result;
+              goto fail;
             }
           }
           break;
@@ -746,13 +736,13 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.UNIX.main = PL_UNIX_FILETYPE;
             result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
-              PL_ERROR(conn, result);
-              return bufflen;
+              parser->error = result;
+              goto fail;
             }
           }
           else {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           break;
         }
@@ -772,8 +762,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1;
           }
           else if(c == '\r' || c == '\n') {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           break;
         case PL_UNIX_SYMLINK_PRETARGET1:
@@ -782,8 +772,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2;
           }
           else if(c == '\r' || c == '\n') {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           else {
             parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
@@ -795,8 +785,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3;
           }
           else if(c == '\r' || c == '\n') {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           else {
             parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
@@ -813,8 +803,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->item_offset = 0;
           }
           else if(c == '\r' || c == '\n') {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           else {
             parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
@@ -827,8 +817,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->item_length = 1;
           }
           else {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           break;
         case PL_UNIX_SYMLINK_TARGET:
@@ -841,8 +831,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->offsets.symlink_target = parser->item_offset;
             result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
-              PL_ERROR(conn, result);
-              return bufflen;
+              parser->error = result;
+              goto fail;
             }
             parser->state.UNIX.main = PL_UNIX_FILETYPE;
           }
@@ -853,14 +843,14 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->offsets.symlink_target = parser->item_offset;
             result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
-              PL_ERROR(conn, result);
-              return bufflen;
+              parser->error = result;
+              goto fail;
             }
             parser->state.UNIX.main = PL_UNIX_FILETYPE;
           }
           else {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           break;
         }
@@ -873,8 +863,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
         parser->item_length++;
         if(parser->item_length < 9) {
           if(!strchr("0123456789-", c)) { /* only simple control */
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
         }
         else if(parser->item_length == 9) {
@@ -883,13 +873,13 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE;
           }
           else {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
         }
         else {
-          PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-          return bufflen;
+          parser->error = CURLE_FTP_BAD_FILE_LIST;
+          goto fail;
         }
         break;
       case PL_WINNT_TIME:
@@ -909,8 +899,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->item_length = 0;
           }
           else if(!strchr("APM0123456789:", c)) {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           break;
         }
@@ -940,8 +930,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
               if(curlx_strtoofft(finfo->b_data +
                                  parser->item_offset,
                                  &endptr, 10, &finfo->size)) {
-                PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-                return bufflen;
+                parser->error = CURLE_FTP_BAD_FILE_LIST;
+                goto fail;
               }
               /* correct file type */
               parser->file_data->info.filetype = CURLFILETYPE_FILE;
@@ -976,8 +966,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->offsets.filename = parser->item_offset;
             result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
-              PL_ERROR(conn, result);
-              return bufflen;
+              parser->error = result;
+              goto fail;
             }
             parser->state.NT.main = PL_WINNT_DATE;
             parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
@@ -988,15 +978,15 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->offsets.filename = parser->item_offset;
             result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
-              PL_ERROR(conn, result);
-              return bufflen;
+              parser->error = result;
+              goto fail;
             }
             parser->state.NT.main = PL_WINNT_DATE;
             parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
           }
           else {
-            PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-            return bufflen;
+            parser->error = CURLE_FTP_BAD_FILE_LIST;
+            goto fail;
           }
           break;
         }
@@ -1004,13 +994,22 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
       }
       break;
     default:
-      return bufflen + 1;
+      retsize = bufflen + 1;
+      goto fail;
     }
 
     i++;
   }
 
-  return bufflen;
+fail:
+
+  /* Clean up any allocated memory. */
+  if(parser->file_data) {
+    Curl_fileinfo_dtor(NULL, parser->file_data);
+    parser->file_data = NULL;
+  }
+
+  return retsize;
 }
 
 #endif /* CURL_DISABLE_FTP */
diff --git a/lib/hostasyn.c b/lib/hostasyn.c
index 28bdf7a..7b6e856 100644
--- a/lib/hostasyn.c
+++ b/lib/hostasyn.c
@@ -22,6 +22,11 @@
 
 #include "curl_setup.h"
 
+/***********************************************************************
+ * Only for builds using asynchronous name resolves
+ **********************************************************************/
+#ifdef CURLRES_ASYNCH
+
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -51,11 +56,6 @@
 /* The last #include file should be: */
 #include "memdebug.h"
 
-/***********************************************************************
- * Only for builds using asynchronous name resolves
- **********************************************************************/
-#ifdef CURLRES_ASYNCH
-
 /*
  * Curl_addrinfo_callback() gets called by ares, gethostbyname_thread()
  * or getaddrinfo_thread() when we got the name resolved (or not!).
diff --git a/lib/hostcheck.c b/lib/hostcheck.c
index 23dc3d2..37bcc12 100644
--- a/lib/hostcheck.c
+++ b/lib/hostcheck.c
@@ -31,6 +31,9 @@
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
 
 #include "hostcheck.h"
 #include "strcase.h"
diff --git a/lib/hostip.c b/lib/hostip.c
index 1a18a3e..886aeec 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -25,6 +25,9 @@
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif
@@ -688,8 +691,8 @@ clean_up:
      the time we spent until now! */
   if(prev_alarm) {
     /* there was an alarm() set before us, now put it back */
-    unsigned long elapsed_secs = (unsigned long) (Curl_tvdiff(Curl_tvnow(),
-                                   conn->created) / 1000);
+    timediff_t elapsed_secs = Curl_timediff(Curl_now(),
+                                            conn->created) / 1000;
 
     /* the alarm period is counted in even number of seconds */
     unsigned long alarm_set = prev_alarm - elapsed_secs;
@@ -778,7 +781,6 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
 {
   struct curl_slist *hostp;
   char hostname[256];
-  char address[256];
   int port;
 
   for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
@@ -820,6 +822,8 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       Curl_addrinfo *addr;
       char *entry_id;
       size_t entry_len;
+      char buffer[256];
+      char *address = &buffer[0];
 
       if(3 != sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port,
                      address)) {
@@ -828,6 +832,16 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
         continue;
       }
 
+      /* allow IP(v6) address within [brackets] */
+      if(address[0] == '[') {
+        size_t alen = strlen(address);
+        if(address[alen-1] != ']')
+          /* it needs to also end with ] to be valid */
+          continue;
+        address[alen-1] = 0; /* zero terminate there */
+        address++; /* pass the open bracket */
+      }
+
       addr = Curl_str2addr(address, port);
       if(!addr) {
         infof(data, "Address in '%s' found illegal!\n", hostp->data);
@@ -863,9 +877,12 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
           dns->inuse--;
         }
       }
-      else
+      else {
         /* this is a duplicate, free it again */
+        infof(data, "RESOLVE %s:%d is already cached, %s not stored!\n",
+              hostname, port, address);
         Curl_freeaddrinfo(addr);
+      }
 
       if(data->share)
         Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
diff --git a/lib/hostip4.c b/lib/hostip4.c
index 6a7c6e5..9d6f115 100644
--- a/lib/hostip4.c
+++ b/lib/hostip4.c
@@ -22,6 +22,11 @@
 
 #include "curl_setup.h"
 
+/***********************************************************************
+ * Only for plain IPv4 builds
+ **********************************************************************/
+#ifdef CURLRES_IPV4 /* plain IPv4 code coming up */
+
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -53,10 +58,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-/***********************************************************************
- * Only for plain IPv4 builds
- **********************************************************************/
-#ifdef CURLRES_IPV4 /* plain IPv4 code coming up */
 /*
  * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
  * been set and returns TRUE if they are OK.
diff --git a/lib/hostip6.c b/lib/hostip6.c
index edeebec..7c9988f 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -22,6 +22,11 @@
 
 #include "curl_setup.h"
 
+/***********************************************************************
+ * Only for IPv6-enabled builds
+ **********************************************************************/
+#ifdef CURLRES_IPV6
+
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -54,11 +59,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-/***********************************************************************
- * Only for IPv6-enabled builds
- **********************************************************************/
-#ifdef CURLRES_IPV6
-
 #if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
 /* These are strictly for memory tracing and are using the same style as the
  * family otherwise present in memdebug.c. I put these ones here since they
diff --git a/lib/hostsyn.c b/lib/hostsyn.c
index 1a95263..3de6746 100644
--- a/lib/hostsyn.c
+++ b/lib/hostsyn.c
@@ -22,6 +22,11 @@
 
 #include "curl_setup.h"
 
+/***********************************************************************
+ * Only for builds using synchronous name resolves
+ **********************************************************************/
+#ifdef CURLRES_SYNCH
+
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -51,11 +56,6 @@
 /* The last #include file should be: */
 #include "memdebug.h"
 
-/***********************************************************************
- * Only for builds using synchronous name resolves
- **********************************************************************/
-#ifdef CURLRES_SYNCH
-
 /*
  * Function provided by the resolver backend to set DNS servers to use.
  */
diff --git a/lib/http.c b/lib/http.c
index 38227eb..a500767 100644
--- a/lib/http.c
+++ b/lib/http.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
@@ -73,7 +73,6 @@
 #include "http_proxy.h"
 #include "warnless.h"
 #include "non-ascii.h"
-#include "conncache.h"
 #include "pipeline.h"
 #include "http2.h"
 #include "connect.h"
@@ -715,7 +714,7 @@ Curl_http_output_auth(struct connectdata *conn,
   if(!data->state.this_is_a_follow ||
      conn->bits.netrc ||
      !data->state.first_host ||
-     data->set.http_disable_hostname_check_before_authentication ||
+     data->set.allow_auth_to_other_hosts ||
      strcasecompare(data->state.first_host, conn->host.name)) {
     result = output_auth_headers(conn, authhost, request, path, FALSE);
   }
@@ -1637,6 +1636,14 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
                   checkprefix("Transfer-Encoding:", headers->data))
             /* HTTP/2 doesn't support chunked requests */
             ;
+          else if(checkprefix("Authorization:", headers->data) &&
+                  /* be careful of sending this potentially sensitive header to
+                     other hosts */
+                  (data->state.this_is_a_follow &&
+                   data->state.first_host &&
+                   !data->set.allow_auth_to_other_hosts &&
+                   !strcasecompare(data->state.first_host, conn->host.name)))
+            ;
           else {
             CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
                                                headers->data);
@@ -3104,7 +3111,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
            !(conn->handler->protocol & CURLPROTO_RTSP) &&
            data->set.httpreq != HTTPREQ_HEAD) {
           /* On HTTP 1.1, when connection is not to get closed, but no
-             Content-Length nor Content-Encoding chunked have been
+             Content-Length nor Transfer-Encoding chunked have been
              received, according to RFC2616 section 4.4 point 5, we
              assume that the server will close the connection to
              signal the end of the document. */
@@ -3387,12 +3394,14 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         }
       }
       else if(conn->handler->protocol & CURLPROTO_RTSP) {
+        char separator;
         nc = sscanf(HEADER1,
-                    " RTSP/%d.%d %3d",
+                    " RTSP/%1d.%1d%c%3d",
                     &rtspversion_major,
                     &conn->rtspversion,
+                    &separator,
                     &k->httpcode);
-        if(nc == 3) {
+        if((nc == 4) && (' ' == separator)) {
           conn->rtspversion += 10 * rtspversion_major;
           conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
         }
@@ -3504,31 +3513,35 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
     if(!k->ignorecl && !data->set.ignorecl &&
        checkprefix("Content-Length:", k->p)) {
       curl_off_t contentlength;
-      if(!curlx_strtoofft(k->p + 15, NULL, 10, &contentlength)) {
+      CURLofft offt = curlx_strtoofft(k->p + 15, NULL, 10, &contentlength);
+
+      if(offt == CURL_OFFT_OK) {
         if(data->set.max_filesize &&
            contentlength > data->set.max_filesize) {
           failf(data, "Maximum file size exceeded");
           return CURLE_FILESIZE_EXCEEDED;
         }
-        if(contentlength >= 0) {
-          k->size = contentlength;
-          k->maxdownload = k->size;
-          /* we set the progress download size already at this point
-             just to make it easier for apps/callbacks to extract this
-             info as soon as possible */
-          Curl_pgrsSetDownloadSize(data, k->size);
-        }
-        else {
-          /* Negative Content-Length is really odd, and we know it
-             happens for example when older Apache servers send large
-             files */
-          streamclose(conn, "negative content-length");
-          infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
-                ", closing after transfer\n", contentlength);
+        k->size = contentlength;
+        k->maxdownload = k->size;
+        /* we set the progress download size already at this point
+           just to make it easier for apps/callbacks to extract this
+           info as soon as possible */
+        Curl_pgrsSetDownloadSize(data, k->size);
+      }
+      else if(offt == CURL_OFFT_FLOW) {
+        /* out of range */
+        if(data->set.max_filesize) {
+          failf(data, "Maximum file size exceeded");
+          return CURLE_FILESIZE_EXCEEDED;
         }
+        streamclose(conn, "overflow content-length");
+        infof(data, "Overflow Content-Length: value!\n");
+      }
+      else {
+        /* negative or just rubbish - bad HTTP */
+        failf(data, "Invalid Content-Length: value");
+        return CURLE_WEIRD_SERVER_REPLY;
       }
-      else
-        infof(data, "Illegal Content-Length: header\n");
     }
     /* check for Content-Type: header lines to get the MIME-type */
     else if(checkprefix("Content-Type:", k->p)) {
@@ -3612,51 +3625,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
        * of chunks, and a chunk-data set to zero signals the
        * end-of-chunks. */
 
-      char *start;
-
-      /* Find the first non-space letter */
-      start = k->p + 18;
-
-      for(;;) {
-        /* skip whitespaces and commas */
-        while(*start && (ISSPACE(*start) || (*start == ',')))
-          start++;
-
-        if(checkprefix("chunked", start)) {
-          k->chunk = TRUE; /* chunks coming our way */
-
-          /* init our chunky engine */
-          Curl_httpchunk_init(conn);
-
-          start += 7;
-        }
-
-        if(k->auto_decoding)
-          /* TODO: we only support the first mentioned compression for now */
-          break;
-
-        if(checkprefix("identity", start)) {
-          k->auto_decoding = IDENTITY;
-          start += 8;
-        }
-        else if(checkprefix("deflate", start)) {
-          k->auto_decoding = DEFLATE;
-          start += 7;
-        }
-        else if(checkprefix("gzip", start)) {
-          k->auto_decoding = GZIP;
-          start += 4;
-        }
-        else if(checkprefix("x-gzip", start)) {
-          k->auto_decoding = GZIP;
-          start += 6;
-        }
-        else
-          /* unknown! */
-          break;
-
-      }
-
+      result = Curl_build_unencoding_stack(conn, k->p + 18, TRUE);
+      if(result)
+        return result;
     }
     else if(checkprefix("Content-Encoding:", k->p) &&
             data->set.str[STRING_ENCODING]) {
@@ -3667,21 +3638,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
        * 2616). zlib cannot handle compress.  However, errors are
        * handled further down when the response body is processed
        */
-      char *start;
-
-      /* Find the first non-space letter */
-      start = k->p + 17;
-      while(*start && ISSPACE(*start))
-        start++;
-
-      /* Record the content-encoding for later use */
-      if(checkprefix("identity", start))
-        k->auto_decoding = IDENTITY;
-      else if(checkprefix("deflate", start))
-        k->auto_decoding = DEFLATE;
-      else if(checkprefix("gzip", start)
-              || checkprefix("x-gzip", start))
-        k->auto_decoding = GZIP;
+      result = Curl_build_unencoding_stack(conn, k->p + 17, FALSE);
+      if(result)
+        return result;
     }
     else if(checkprefix("Content-Range:", k->p)) {
       /* Content-Range: bytes [num]-
diff --git a/lib/http2.c b/lib/http2.c
index 9a2a1dd..6992879 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -32,7 +32,6 @@
 #include "curl_base64.h"
 #include "strcase.h"
 #include "multiif.h"
-#include "conncache.h"
 #include "url.h"
 #include "connect.h"
 #include "strtoofft.h"
@@ -926,8 +925,8 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
 
   if(stream->bodystarted) {
     /* This is trailer fields. */
-    /* 3 is for ":" and "\r\n". */
-    uint32_t n = (uint32_t)(namelen + valuelen + 3);
+    /* 4 is for ": " and "\r\n". */
+    uint32_t n = (uint32_t)(namelen + valuelen + 4);
 
     DEBUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
                  value));
@@ -1184,14 +1183,17 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
                                          httpc->local_settings_num);
   if(!binlen) {
     failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
+    Curl_add_buffer_free(req);
     return CURLE_FAILED_INIT;
   }
   conn->proto.httpc.binlen = binlen;
 
   result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
                                  &base64, &blen);
-  if(result)
+  if(result) {
+    Curl_add_buffer_free(req);
     return result;
+  }
 
   result = Curl_add_bufferf(req,
                             "Connection: Upgrade, HTTP2-Settings\r\n"
@@ -1846,9 +1848,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
     goto fail;
   }
 
-  hdbuf = end + 1;
-
-  end = line_end;
   nva[2].name = (unsigned char *)":scheme";
   nva[2].namelen = strlen((char *)nva[2].name);
   if(conn->handler->flags & PROTOPT_SSL)
diff --git a/lib/http_chunks.c b/lib/http_chunks.c
index 92d7731..1616429 100644
--- a/lib/http_chunks.c
+++ b/lib/http_chunks.c
@@ -187,49 +187,17 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
       piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
 
       /* Write the data portion available */
-#ifdef HAVE_LIBZ
-      switch(conn->data->set.http_ce_skip?
-             IDENTITY : data->req.auto_decoding) {
-      case IDENTITY:
-#endif
-        if(!k->ignorebody) {
-          if(!data->set.http_te_skip)
-            result = Curl_client_write(conn, CLIENTWRITE_BODY, datap,
-                                       piece);
-          else
-            result = CURLE_OK;
-        }
-#ifdef HAVE_LIBZ
-        break;
-
-      case DEFLATE:
-        /* update data->req.keep.str to point to the chunk data. */
-        data->req.str = datap;
-        result = Curl_unencode_deflate_write(conn, &data->req,
-                                             (ssize_t)piece);
-        break;
-
-      case GZIP:
-        /* update data->req.keep.str to point to the chunk data. */
-        data->req.str = datap;
-        result = Curl_unencode_gzip_write(conn, &data->req,
-                                          (ssize_t)piece);
-        break;
-
-      default:
-        failf(conn->data,
-              "Unrecognized content encoding type. "
-              "libcurl understands `identity', `deflate' and `gzip' "
-              "content encodings.");
-        return CHUNKE_BAD_ENCODING;
+      if(conn->data->set.http_ce_skip || !k->writer_stack) {
+        if(!k->ignorebody)
+          result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece);
       }
-#endif
+      else
+        result = Curl_unencode_write(conn, k->writer_stack, datap, piece);
 
       if(result)
         return CHUNKE_WRITE_ERROR;
 
       *wrote += piece;
-
       ch->datasize -= piece; /* decrease amount left to expect */
       datap += piece;    /* move read pointer forward */
       length -= piece;   /* decrease space left in this round */
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index dff9d23..7f50405 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -167,6 +167,7 @@ static CURLcode connect_init(struct connectdata *conn, bool reinit)
   s->line_start = s->connect_buffer;
   s->ptr = s->line_start;
   s->cl = 0;
+  s->close_connection = FALSE;
   return CURLE_OK;
 }
 
@@ -187,8 +188,7 @@ static CURLcode CONNECT(struct connectdata *conn,
   struct SingleRequest *k = &data->req;
   CURLcode result;
   curl_socket_t tunnelsocket = conn->sock[sockindex];
-  bool closeConnection = FALSE;
-  time_t check;
+  timediff_t check;
   struct http_connect_state *s = conn->connect_state;
 
 #define SELECT_OK      0
@@ -529,7 +529,7 @@ static CURLcode CONNECT(struct connectdata *conn,
           }
         }
         else if(Curl_compareheader(s->line_start, "Connection:", "close"))
-          closeConnection = TRUE;
+          s->close_connection = TRUE;
         else if(checkprefix("Transfer-Encoding:", s->line_start)) {
           if(k->httpcode/100 == 2) {
             /* A client MUST ignore any Content-Length or Transfer-Encoding
@@ -548,7 +548,7 @@ static CURLcode CONNECT(struct connectdata *conn,
         }
         else if(Curl_compareheader(s->line_start,
                                    "Proxy-Connection:", "close"))
-          closeConnection = TRUE;
+          s->close_connection = TRUE;
         else if(2 == sscanf(s->line_start, "HTTP/1.%d %d",
                             &subversion,
                             &k->httpcode)) {
@@ -578,10 +578,10 @@ static CURLcode CONNECT(struct connectdata *conn,
           /* the connection has been marked for closure, most likely in the
              Curl_http_auth_act() function and thus we can kill it at once
              below */
-          closeConnection = TRUE;
+          s->close_connection = TRUE;
       }
 
-      if(closeConnection && data->req.newurl) {
+      if(s->close_connection && data->req.newurl) {
         /* Connection closed by server. Don't use it anymore */
         Curl_closesocket(conn, conn->sock[sockindex]);
         conn->sock[sockindex] = CURL_SOCKET_BAD;
@@ -599,7 +599,7 @@ static CURLcode CONNECT(struct connectdata *conn,
   } while(data->req.newurl);
 
   if(data->info.httpproxycode/100 != 2) {
-    if(closeConnection && data->req.newurl) {
+    if(s->close_connection && data->req.newurl) {
       conn->bits.proxy_connect_closed = TRUE;
       infof(data, "Connect me again please\n");
       connect_done(conn);
diff --git a/lib/imap.c b/lib/imap.c
index 954d18f..cf278a2 100644
--- a/lib/imap.c
+++ b/lib/imap.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
@@ -275,15 +275,15 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
       case IMAP_LIST:
         if((!imap->custom && !imap_matchresp(line, len, "LIST")) ||
           (imap->custom && !imap_matchresp(line, len, imap->custom) &&
-           (strcmp(imap->custom, "STORE") ||
+           (!strcasecompare(imap->custom, "STORE") ||
             !imap_matchresp(line, len, "FETCH")) &&
-           strcmp(imap->custom, "SELECT") &&
-           strcmp(imap->custom, "EXAMINE") &&
-           strcmp(imap->custom, "SEARCH") &&
-           strcmp(imap->custom, "EXPUNGE") &&
-           strcmp(imap->custom, "LSUB") &&
-           strcmp(imap->custom, "UID") &&
-           strcmp(imap->custom, "NOOP")))
+           !strcasecompare(imap->custom, "SELECT") &&
+           !strcasecompare(imap->custom, "EXAMINE") &&
+           !strcasecompare(imap->custom, "SEARCH") &&
+           !strcasecompare(imap->custom, "EXPUNGE") &&
+           !strcasecompare(imap->custom, "LSUB") &&
+           !strcasecompare(imap->custom, "UID") &&
+           !strcasecompare(imap->custom, "NOOP")))
           return FALSE;
         break;
 
@@ -344,23 +344,30 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
  */
 static void imap_get_message(char *buffer, char **outptr)
 {
-  size_t len = 0;
+  size_t len = strlen(buffer);
   char *message = NULL;
 
-  /* Find the start of the message */
-  for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
-    ;
-
-  /* Find the end of the message */
-  for(len = strlen(message); len--;)
-    if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
-        message[len] != '\t')
-      break;
+  if(len > 2) {
+    /* Find the start of the message */
+    len -= 2;
+    for(message = buffer + 2; *message == ' ' || *message == '\t';
+        message++, len--)
+      ;
+
+    /* Find the end of the message */
+    for(; len--;)
+      if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
+         message[len] != '\t')
+        break;
 
-  /* Terminate the message */
-  if(++len) {
-    message[len] = '\0';
+    /* Terminate the message */
+    if(++len) {
+      message[len] = '\0';
+    }
   }
+  else
+    /* junk input => zero length output */
+    message = &buffer[len];
 
   *outptr = message;
 }
@@ -1053,7 +1060,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
   else if(imapcode == IMAP_RESP_OK) {
     /* Check if the UIDVALIDITY has been specified and matches */
     if(imap->uidvalidity && imapc->mailbox_uidvalidity &&
-       strcmp(imap->uidvalidity, imapc->mailbox_uidvalidity)) {
+       !strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity)) {
       failf(conn->data, "Mailbox UIDVALIDITY has changed");
       result = CURLE_REMOTE_FILE_NOT_FOUND;
     }
@@ -1126,6 +1133,11 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
         /* The conversion from curl_off_t to size_t is always fine here */
         chunk = (size_t)size;
 
+      if(!chunk) {
+        /* no size, we're done with the data */
+        state(conn, IMAP_STOP);
+        return CURLE_OK;
+      }
       result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk);
       if(result)
         return result;
@@ -1521,9 +1533,9 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
   /* Determine if the requested mailbox (with the same UIDVALIDITY if set)
      has already been selected on this connection */
   if(imap->mailbox && imapc->mailbox &&
-     !strcmp(imap->mailbox, imapc->mailbox) &&
+     strcasecompare(imap->mailbox, imapc->mailbox) &&
      (!imap->uidvalidity || !imapc->mailbox_uidvalidity ||
-      !strcmp(imap->uidvalidity, imapc->mailbox_uidvalidity)))
+      strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity)))
     selected = TRUE;
 
   /* Start the first command in the DO phase */
diff --git a/lib/krb5.c b/lib/krb5.c
index af25e92..70507df 100644
--- a/lib/krb5.c
+++ b/lib/krb5.c
@@ -2,7 +2,7 @@
  *
  * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
- * Copyright (c) 2004 - 2016 Daniel Stenberg
+ * Copyright (c) 2004 - 2017 Daniel Stenberg
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -282,6 +282,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
           break;
         }
 
+        _gssresp.value = NULL; /* make sure it is initialized */
         p = data->state.buffer + 4;
         p = strstr(p, "ADAT=");
         if(p) {
diff --git a/lib/ldap.c b/lib/ldap.c
index 040641c..89047bc 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -190,9 +190,11 @@ static int ldap_win_bind_auth(LDAP *server, const char *user,
                               const char *passwd, unsigned long authflags)
 {
   ULONG method = 0;
-  SEC_WINNT_AUTH_IDENTITY cred = { 0, };
+  SEC_WINNT_AUTH_IDENTITY cred;
   int rc = LDAP_AUTH_METHOD_NOT_SUPPORTED;
 
+  memset(&cred, 0, sizeof(cred));
+
 #if defined(USE_SPNEGO)
   if(authflags & CURLAUTH_NEGOTIATE) {
     method = LDAP_AUTH_NEGOTIATE;
diff --git a/lib/llist.c b/lib/llist.c
index 4bb0a51..f8769c2 100644
--- a/lib/llist.c
+++ b/lib/llist.c
@@ -106,7 +106,11 @@ Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
       e->next->prev = NULL;
   }
   else {
-    e->prev->next = e->next;
+    if(!e->prev)
+      list->head = e->next;
+    else
+      e->prev->next = e->next;
+
     if(!e->next)
       list->tail = e->prev;
     else
diff --git a/lib/memdebug.c b/lib/memdebug.c
index 0eb249c..2b81c26 100644
--- a/lib/memdebug.c
+++ b/lib/memdebug.c
@@ -343,7 +343,12 @@ curl_socket_t curl_socket(int domain, int type, int protocol,
     "FD %s:%d socket() = %ld\n" :
     "FD %s:%d socket() = %zd\n";
 
-  curl_socket_t sockfd = socket(domain, type, protocol);
+  curl_socket_t sockfd;
+
+  if(countcheck("socket", line, source))
+    return CURL_SOCKET_BAD;
+
+  sockfd = socket(domain, type, protocol);
 
   if(source && (sockfd != CURL_SOCKET_BAD))
     curl_memlog(fmt, source, line, sockfd);
@@ -351,6 +356,35 @@ curl_socket_t curl_socket(int domain, int type, int protocol,
   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 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",
+                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 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",
+                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],
diff --git a/lib/memdebug.h b/lib/memdebug.h
index 835dab3..6fb8b68 100644
--- a/lib/memdebug.h
+++ b/lib/memdebug.h
@@ -8,7 +8,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -66,6 +66,17 @@ CURL_EXTERN int curl_socketpair(int domain, int type, int protocol,
                                 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);
+
 /* FILE functions */
 CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line,
                              const char *source);
@@ -84,6 +95,8 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
 #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__)
 
 #ifdef WIN32
 #  ifdef UNICODE
diff --git a/lib/mime.c b/lib/mime.c
index 496f5e6..e0853a9 100644
--- a/lib/mime.c
+++ b/lib/mime.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
@@ -26,6 +26,8 @@
 
 #include "mime.h"
 #include "non-ascii.h"
+#include "urldata.h"
+#include "sendf.h"
 
 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
     !defined(CURL_DISABLE_IMAP)
@@ -404,7 +406,7 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
 
   while(st->bufbeg < st->bufend) {
     /* Line full ? */
-    if(st->pos >= MAX_ENCODED_LINE_LENGTH - 4) {
+    if(st->pos > MAX_ENCODED_LINE_LENGTH - 4) {
       /* Yes, we need 2 characters for CRLF. */
       if(size < 2)
         break;
@@ -419,7 +421,7 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
     if(size < 4 || st->bufend - st->bufbeg < 3)
       break;
 
-    /* Encode three bytes a four characters. */
+    /* Encode three bytes as four characters. */
     i = st->buf[st->bufbeg++] & 0xFF;
     i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
     i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
@@ -618,14 +620,13 @@ static size_t mime_mem_read(char *buffer, size_t size, size_t nitems,
 {
   curl_mimepart *part = (curl_mimepart *) instream;
   size_t sz = (size_t) part->datasize - part->state.offset;
-
   (void) size;   /* Always 1.*/
 
   if(sz > nitems)
     sz = nitems;
 
   if(sz)
-    memcpy(buffer, (char *) part->data, sz);
+    memcpy(buffer, (char *) &part->data[part->state.offset], sz);
 
   part->state.offset += sz;
   return sz;
@@ -718,8 +719,6 @@ static size_t readback_bytes(mime_state *state,
 {
   size_t sz;
 
-  sz = numbytes - state->offset;
-
   if(numbytes > state->offset) {
     sz = numbytes - state->offset;
     bytes += state->offset;
@@ -1069,13 +1068,6 @@ static int mime_subparts_seek(void *instream, curl_off_t offset, int whence)
   return result;
 }
 
-static void mime_subparts_free(void *ptr)
-{
-  curl_mime *mime = (curl_mime *) ptr;
-  curl_mime_free(mime);
-}
-
-
 /* Release part content. */
 static void cleanup_part_content(curl_mimepart *part)
 {
@@ -1089,11 +1081,34 @@ static void cleanup_part_content(curl_mimepart *part)
   part->data = NULL;
   part->fp = NULL;
   part->datasize = (curl_off_t) 0;    /* No size yet. */
-  part->encoder = NULL;
   cleanup_encoder_state(&part->encstate);
   part->kind = MIMEKIND_NONE;
 }
 
+static void mime_subparts_free(void *ptr)
+{
+  curl_mime *mime = (curl_mime *) ptr;
+
+  if(mime && mime->parent) {
+    mime->parent->freefunc = NULL;  /* Be sure we won't be called again. */
+    cleanup_part_content(mime->parent);  /* Avoid dangling pointer in part. */
+  }
+  curl_mime_free(mime);
+}
+
+/* Do not free subparts: unbind them. This is used for the top level only. */
+static void mime_subparts_unbind(void *ptr)
+{
+  curl_mime *mime = (curl_mime *) ptr;
+
+  if(mime && mime->parent) {
+    mime->parent->freefunc = NULL;  /* Be sure we won't be called again. */
+    cleanup_part_content(mime->parent);  /* Avoid dangling pointer in part. */
+    mime->parent = NULL;
+  }
+}
+
+
 void Curl_mime_cleanpart(curl_mimepart *part)
 {
   cleanup_part_content(part);
@@ -1112,6 +1127,7 @@ void curl_mime_free(curl_mime *mime)
   curl_mimepart *part;
 
   if(mime) {
+    mime_subparts_unbind(mime);  /* Be sure it's not referenced anymore. */
     while(mime->firstpart) {
       part = mime->firstpart;
       mime->firstpart = part->nextpart;
@@ -1124,6 +1140,78 @@ void curl_mime_free(curl_mime *mime)
   }
 }
 
+CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
+{
+  curl_mime *mime;
+  curl_mimepart *d;
+  const curl_mimepart *s;
+  CURLcode res = CURLE_OK;
+
+  /* Duplicate content. */
+  switch(src->kind) {
+  case MIMEKIND_NONE:
+    break;
+  case MIMEKIND_DATA:
+    res = curl_mime_data(dst, src->data, (size_t) src->datasize);
+    break;
+  case MIMEKIND_FILE:
+    res = curl_mime_filedata(dst, src->data);
+    /* Do not abort duplication if file is not readable. */
+    if(res == CURLE_READ_ERROR)
+      res = CURLE_OK;
+    break;
+  case MIMEKIND_CALLBACK:
+    res = curl_mime_data_cb(dst, src->datasize, src->readfunc,
+                            src->seekfunc, src->freefunc, src->arg);
+    break;
+  case MIMEKIND_MULTIPART:
+    /* No one knows about the cloned subparts, thus always attach ownership
+       to the part. */
+    mime = curl_mime_init(dst->easy);
+    res = mime? curl_mime_subparts(dst, mime): CURLE_OUT_OF_MEMORY;
+
+    /* Duplicate subparts. */
+    for(s = ((curl_mime *) src->arg)->firstpart; !res && s; s = s->nextpart) {
+      d = curl_mime_addpart(mime);
+      res = d? Curl_mime_duppart(d, s): CURLE_OUT_OF_MEMORY;
+    }
+    break;
+  default:  /* Invalid kind: should not occur. */
+    res = CURLE_BAD_FUNCTION_ARGUMENT;  /* Internal error? */
+    break;
+  }
+
+  /* Duplicate headers. */
+  if(!res && src->userheaders) {
+    struct curl_slist *hdrs = Curl_slist_duplicate(src->userheaders);
+
+    if(!hdrs)
+      res = CURLE_OUT_OF_MEMORY;
+    else {
+      /* No one but this procedure knows about the new header list,
+         so always take ownership. */
+      res = curl_mime_headers(dst, hdrs, TRUE);
+      if(res)
+        curl_slist_free_all(hdrs);
+    }
+  }
+
+  /* Duplicate other fields. */
+  dst->encoder = src->encoder;
+  if(!res)
+    res = curl_mime_type(dst, src->mimetype);
+  if(!res)
+    res = curl_mime_name(dst, src->name);
+  if(!res)
+    res = curl_mime_filename(dst, src->filename);
+
+  /* If an error occurred, rollback. */
+  if(res)
+    Curl_mime_cleanpart(dst);
+
+  return res;
+}
+
 /*
  * Mime build functions.
  */
@@ -1356,7 +1444,8 @@ CURLcode curl_mime_headers(curl_mimepart *part,
     return CURLE_BAD_FUNCTION_ARGUMENT;
 
   if(part->flags & MIME_USERHEADERS_OWNER) {
-    curl_slist_free_all(part->userheaders);
+    if(part->userheaders != headers)  /* Allow setting twice the same list. */
+      curl_slist_free_all(part->userheaders);
     part->flags &= ~MIME_USERHEADERS_OWNER;
   }
   part->userheaders = headers;
@@ -1389,9 +1478,11 @@ CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize,
 }
 
 /* Set mime part content from subparts. */
-CURLcode curl_mime_subparts(curl_mimepart *part,
-                            curl_mime *subparts)
+CURLcode Curl_mime_set_subparts(curl_mimepart *part,
+                                curl_mime *subparts, int take_ownership)
 {
+  curl_mime *root;
+
   if(!part)
     return CURLE_BAD_FUNCTION_ARGUMENT;
 
@@ -1410,10 +1501,22 @@ CURLcode curl_mime_subparts(curl_mimepart *part,
     if(subparts->parent)
       return CURLE_BAD_FUNCTION_ARGUMENT;
 
+    /* Should not be the part's root. */
+    root = part->parent;
+    if(root) {
+      while(root->parent && root->parent->parent)
+        root = root->parent->parent;
+      if(subparts == root) {
+        if(part->easy)
+          failf(part->easy, "Can't add itself as a subpart!");
+        return CURLE_BAD_FUNCTION_ARGUMENT;
+      }
+    }
+
     subparts->parent = part;
     part->readfunc = mime_subparts_read;
     part->seekfunc = mime_subparts_seek;
-    part->freefunc = mime_subparts_free;
+    part->freefunc = take_ownership? mime_subparts_free: mime_subparts_unbind;
     part->arg = subparts;
     part->datasize = -1;
     part->kind = MIMEKIND_MULTIPART;
@@ -1422,6 +1525,11 @@ CURLcode curl_mime_subparts(curl_mimepart *part,
   return CURLE_OK;
 }
 
+CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts)
+{
+  return Curl_mime_set_subparts(part, subparts, TRUE);
+}
+
 
 /* Readback from top mime. */
 /* Argument is the dummy top part. */
@@ -1485,7 +1593,7 @@ curl_off_t Curl_mime_size(curl_mimepart *part)
 {
   curl_off_t size;
 
-  if(part->datasize < 0 && part->kind == MIMEKIND_MULTIPART)
+  if(part->kind == MIMEKIND_MULTIPART)
     part->datasize = multipart_size(part->arg);
 
   size = part->datasize;
@@ -1581,7 +1689,7 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
 {
   curl_mime *mime = NULL;
   const char *boundary = NULL;
-  char *s;
+  char *customct;
   const char *cte = NULL;
   CURLcode ret = CURLE_OK;
 
@@ -1593,12 +1701,14 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
   if(part->state.state == MIMESTATE_CURLHEADERS)
     mimesetstate(&part->state, MIMESTATE_CURLHEADERS, NULL);
 
-  /* Build the content-type header. */
-  s = search_header(part->userheaders, "Content-Type");
-  if(s)
-    contenttype = s;
-  if(part->mimetype)
-    contenttype = part->mimetype;
+  /* Check if content type is specified. */
+  customct = part->mimetype;
+  if(!customct)
+    customct = search_header(part->userheaders, "Content-Type");
+  if(customct)
+    contenttype = customct;
+
+  /* If content type is not specified, try to determine it. */
   if(!contenttype) {
     switch(part->kind) {
     case MIMEKIND_MULTIPART:
@@ -1622,7 +1732,8 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
     if(mime)
       boundary = mime->boundary;
   }
-  else if(contenttype && strcasecompare(contenttype, "text/plain"))
+  else if(contenttype && !customct &&
+          strcasecompare(contenttype, "text/plain"))
     if(strategy == MIMESTRATEGY_MAIL || !part->filename)
       contenttype = NULL;
 
@@ -1816,6 +1927,22 @@ 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,
diff --git a/lib/mime.h b/lib/mime.h
index a144857..920a8a7 100644
--- a/lib/mime.h
+++ b/lib/mime.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
@@ -122,6 +122,9 @@ struct curl_mimepart_s {
 /* Prototypes. */
 void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy);
 void Curl_mime_cleanpart(curl_mimepart *part);
+CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src);
+CURLcode Curl_mime_set_subparts(curl_mimepart *part,
+                                curl_mime *subparts, int take_ownership);
 CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
                                    const char *contenttype,
                                    const char *disposition,
diff --git a/lib/multi.c b/lib/multi.c
index 70aa6bc..43823cc 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -59,7 +59,9 @@
 #define CURL_SOCKET_HASH_TABLE_SIZE 911
 #endif
 
+#ifndef CURL_CONNECTION_HASH_SIZE
 #define CURL_CONNECTION_HASH_SIZE 97
+#endif
 
 #define CURL_MULTI_HANDLE 0x000bab1e
 
@@ -324,14 +326,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);
 
-  /* allocate a new easy handle to use when closing cached connections */
-  multi->closure_handle = curl_easy_init();
-  if(!multi->closure_handle)
-    goto error;
-
-  multi->closure_handle->multi = multi;
-  multi->closure_handle->state.conn_cache = &multi->conn_cache;
-
   multi->max_pipeline_length = 5;
 
   /* -1 means it not set by user, use the default value */
@@ -343,8 +337,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
   Curl_hash_destroy(&multi->sockhash);
   Curl_hash_destroy(&multi->hostcache);
   Curl_conncache_destroy(&multi->conn_cache);
-  Curl_close(multi->closure_handle);
-  multi->closure_handle = NULL;
   Curl_llist_destroy(&multi->msglist, NULL);
   Curl_llist_destroy(&multi->pending, NULL);
 
@@ -405,8 +397,11 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
     data->dns.hostcachetype = HCACHE_MULTI;
   }
 
-  /* Point to the multi's connection cache */
-  data->state.conn_cache = &multi->conn_cache;
+  /* Point to the shared or multi handle connection cache */
+  if(data->share && (data->share->specifier & (1<< CURL_LOCK_DATA_CONNECT)))
+    data->state.conn_cache = &data->share->conn_cache;
+  else
+    data->state.conn_cache = &multi->conn_cache;
 
   /* 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
@@ -460,8 +455,8 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
      state somewhat we clone the timeouts from each added handle so that the
      closure handle always has the same timeouts as the most recently added
      easy handle. */
-  multi->closure_handle->set.timeout = data->set.timeout;
-  multi->closure_handle->set.server_response_timeout =
+  data->state.conn_cache->closure_handle->set.timeout = data->set.timeout;
+  data->state.conn_cache->closure_handle->set.server_response_timeout =
     data->set.server_response_timeout;
 
   update_timer(multi);
@@ -484,38 +479,6 @@ static void debug_print_sock_hash(void *p)
 }
 #endif
 
-/* Mark the connection as 'idle', or close it if the cache is full.
-   Returns TRUE if the connection is kept, or FALSE if it was closed. */
-static bool
-ConnectionDone(struct Curl_easy *data, struct connectdata *conn)
-{
-  /* data->multi->maxconnects can be negative, deal with it. */
-  size_t maxconnects =
-    (data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
-    data->multi->maxconnects;
-  struct connectdata *conn_candidate = NULL;
-
-  /* Mark the current connection as 'unused' */
-  conn->inuse = FALSE;
-
-  if(maxconnects > 0 &&
-     data->state.conn_cache->num_connections > maxconnects) {
-    infof(data, "Connection cache is full, closing the oldest one.\n");
-
-    conn_candidate = Curl_oldest_idle_connection(data);
-
-    if(conn_candidate) {
-      /* Set the connection's owner correctly */
-      conn_candidate->data = data;
-
-      /* the winner gets the honour of being disconnected */
-      (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
-    }
-  }
-
-  return (conn_candidate == conn) ? FALSE : TRUE;
-}
-
 static CURLcode multi_done(struct connectdata **connp,
                           CURLcode status,  /* an error if this is called
                                                after an error was detected */
@@ -589,6 +552,7 @@ static CURLcode multi_done(struct connectdata **connp,
     Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
     conn->dns_entry = NULL;
   }
+  Curl_hostcache_prune(data);
 
   /* if the transfer was completed in a paused state there can be buffered
      data left to free */
@@ -617,7 +581,8 @@ static CURLcode multi_done(struct connectdata **connp,
       && !(conn->ntlm.state == NTLMSTATE_TYPE2 ||
            conn->proxyntlm.state == NTLMSTATE_TYPE2)
 #endif
-     ) || conn->bits.close || premature) {
+     ) || conn->bits.close
+       || (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
     CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */
 
     /* If we had an error already, make sure we return that one. But
@@ -626,17 +591,21 @@ static CURLcode multi_done(struct connectdata **connp,
       result = res2;
   }
   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);
+
     /* the connection is no longer in use */
-    if(ConnectionDone(data, conn)) {
+    if(Curl_conncache_return_conn(conn)) {
       /* remember the most recently used connection */
       data->state.lastconnect = conn;
-
-      infof(data, "Connection #%ld to host %s left intact\n",
-            conn->connection_id,
-            conn->bits.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);
+      infof(data, "%s\n", buffer);
     }
     else
       data->state.lastconnect = NULL;
@@ -705,12 +674,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
      curl_easy_cleanup is called. */
   Curl_expire_clear(data);
 
-  if(data->dns.hostcachetype == HCACHE_MULTI) {
-    /* stop using the multi handle's DNS cache */
-    data->dns.hostcache = NULL;
-    data->dns.hostcachetype = HCACHE_NONE;
-  }
-
   if(data->easy_conn) {
 
     /* we must call multi_done() here (if we still own the connection) so that
@@ -729,6 +692,13 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
       Curl_getoff_all_pipelines(data, data->easy_conn);
   }
 
+  if(data->dns.hostcachetype == HCACHE_MULTI) {
+    /* stop using the multi handle's DNS cache, *after* the possible
+       multi_done() call above */
+    data->dns.hostcache = NULL;
+    data->dns.hostcachetype = HCACHE_NONE;
+  }
+
   Curl_wildcard_dtor(&data->wildcard);
 
   /* destroy the timeout list that is held in the easy handle, do this *after*
@@ -1315,7 +1285,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
   struct SingleRequest *k;
   time_t timeout_ms;
   time_t recv_timeout_ms;
-  time_t send_timeout_ms;
+  timediff_t send_timeout_ms;
   int control;
 
   if(!GOOD_EASY_HANDLE(data))
@@ -1361,16 +1331,16 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
     }
 
     if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
-       data->mstate < CURLM_STATE_COMPLETED)
+       data->mstate < CURLM_STATE_COMPLETED) {
       /* Make sure we set the connection's current owner */
       data->easy_conn->data = data;
+    }
 
     if(data->easy_conn &&
        (data->mstate >= CURLM_STATE_CONNECT) &&
        (data->mstate < CURLM_STATE_COMPLETED)) {
       /* we need to wait for the connect state as only then is the start time
          stored, but we must not check already completed handles */
-
       timeout_ms = Curl_timeleft(data, &now,
                                  (data->mstate <= CURLM_STATE_WAITDO)?
                                  TRUE:FALSE);
@@ -1379,23 +1349,23 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         /* Handle timed out */
         if(data->mstate == CURLM_STATE_WAITRESOLVE)
           failf(data, "Resolving timed out after %ld milliseconds",
-                Curl_tvdiff(now, data->progress.t_startsingle));
+                Curl_timediff(now, data->progress.t_startsingle));
         else if(data->mstate == CURLM_STATE_WAITCONNECT)
           failf(data, "Connection timed out after %ld milliseconds",
-                Curl_tvdiff(now, data->progress.t_startsingle));
+                Curl_timediff(now, data->progress.t_startsingle));
         else {
           k = &data->req;
           if(k->size != -1) {
             failf(data, "Operation timed out after %ld milliseconds with %"
                   CURL_FORMAT_CURL_OFF_T " out of %"
                   CURL_FORMAT_CURL_OFF_T " bytes received",
-                  Curl_tvdiff(now, data->progress.t_startsingle),
+                  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",
-                  Curl_tvdiff(now, data->progress.t_startsingle),
+                  Curl_timediff(now, data->progress.t_startsingle),
                   k->bytecount);
           }
         }
@@ -1660,7 +1630,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         if(!result) {
           if(!dophase_done) {
             /* some steps needed for wildcard matching */
-            if(data->set.wildcardmatch) {
+            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 */
@@ -1812,7 +1782,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
          (data->easy_conn->writesockfd != CURL_SOCKET_BAD))
         multistate(data, CURLM_STATE_WAITPERFORM);
       else
+      {
+        if(data->state.wildcardmatch &&
+           ((data->easy_conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
+           data->wildcard.state = CURLWC_DONE;
+        }
         multistate(data, CURLM_STATE_DONE);
+      }
       rc = CURLM_CALL_MULTI_PERFORM;
       break;
 
@@ -2029,7 +2005,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           data->easy_conn = NULL;
       }
 
-      if(data->set.wildcardmatch) {
+      if(data->state.wildcardmatch) {
         if(data->wildcard.state != CURLWC_DONE) {
           /* if a wildcard is set and we are not ending -> lets start again
              with CURLM_STATE_INIT */
@@ -2146,7 +2122,7 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
   struct Curl_easy *data;
   CURLMcode returncode = CURLM_OK;
   struct Curl_tree *t;
-  struct curltime now = Curl_tvnow();
+  struct curltime now = Curl_now();
 
   if(!GOOD_MULTI_HANDLE(multi))
     return CURLM_BAD_HANDLE;
@@ -2192,61 +2168,21 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
   return returncode;
 }
 
-static void close_all_connections(struct Curl_multi *multi)
-{
-  struct connectdata *conn;
-
-  conn = Curl_conncache_find_first_connection(&multi->conn_cache);
-  while(conn) {
-    SIGPIPE_VARIABLE(pipe_st);
-    conn->data = multi->closure_handle;
-
-    sigpipe_ignore(conn->data, &pipe_st);
-    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(conn, FALSE);
-    sigpipe_restore(&pipe_st);
-
-    conn = Curl_conncache_find_first_connection(&multi->conn_cache);
-  }
-}
-
 CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
 {
   struct Curl_easy *data;
   struct Curl_easy *nextdata;
 
   if(GOOD_MULTI_HANDLE(multi)) {
-    bool restore_pipe = FALSE;
-    SIGPIPE_VARIABLE(pipe_st);
-
     multi->type = 0; /* not good anymore */
 
-    /* Close all the connections in the connection cache */
-    close_all_connections(multi);
-
-    if(multi->closure_handle) {
-      sigpipe_ignore(multi->closure_handle, &pipe_st);
-      restore_pipe = TRUE;
-
-      multi->closure_handle->dns.hostcache = &multi->hostcache;
-      Curl_hostcache_clean(multi->closure_handle,
-                           multi->closure_handle->dns.hostcache);
-
-      Curl_close(multi->closure_handle);
-    }
-
-    Curl_hash_destroy(&multi->sockhash);
-    Curl_conncache_destroy(&multi->conn_cache);
-    Curl_llist_destroy(&multi->msglist, NULL);
-    Curl_llist_destroy(&multi->pending, NULL);
-
-    /* remove all easy handles */
+    /* Firsrt remove all remaining easy handles */
     data = multi->easyp;
     while(data) {
       nextdata = data->next;
+      if(!data->state.done && data->easy_conn)
+        /* if DONE was never called for this handle */
+        (void)multi_done(&data->easy_conn, 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);
@@ -2261,6 +2197,14 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
       data = nextdata;
     }
 
+    /* Close all the connections in the connection cache */
+    Curl_conncache_close_all_connections(&multi->conn_cache);
+
+    Curl_hash_destroy(&multi->sockhash);
+    Curl_conncache_destroy(&multi->conn_cache);
+    Curl_llist_destroy(&multi->msglist, NULL);
+    Curl_llist_destroy(&multi->pending, NULL);
+
     Curl_hash_destroy(&multi->hostcache);
 
     /* Free the blacklists by setting them to NULL */
@@ -2268,8 +2212,6 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
     Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
 
     free(multi);
-    if(restore_pipe)
-      sigpipe_restore(&pipe_st);
 
     return CURLM_OK;
   }
@@ -2510,9 +2452,9 @@ static CURLMcode add_next_timeout(struct curltime now,
      timeout in *tv */
   for(e = list->head; e;) {
     struct curl_llist_element *n = e->next;
-    time_t diff;
+    timediff_t diff;
     node = (struct time_node *)e->ptr;
-    diff = curlx_tvdiff(node->time, now);
+    diff = Curl_timediff(node->time, now);
     if(diff <= 0)
       /* remove outdated entry */
       Curl_llist_remove(list, e, NULL);
@@ -2549,7 +2491,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
   CURLMcode result = CURLM_OK;
   struct Curl_easy *data = NULL;
   struct Curl_tree *t;
-  struct curltime now = Curl_tvnow();
+  struct curltime now = Curl_now();
 
   if(checkall) {
     /* *perform() deals with running_handles on its own */
@@ -2625,8 +2567,8 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
 
       data = NULL; /* set data to NULL again to avoid calling
                       multi_runsingle() in case there's no need to */
-      now = Curl_tvnow(); /* get a newer time since the multi_runsingle() loop
-                             may have taken some time */
+      now = Curl_now(); /* get a newer time since the multi_runsingle() loop
+                           may have taken some time */
     }
   }
   else {
@@ -2779,15 +2721,15 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
 
   if(multi->timetree) {
     /* we have a tree of expire times */
-    struct curltime now = Curl_tvnow();
+    struct curltime now = Curl_now();
 
     /* splay the lowest to the bottom */
     multi->timetree = Curl_splay(tv_zero, multi->timetree);
 
     if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
       /* some time left before expiration */
-      *timeout_ms = (long)curlx_tvdiff(multi->timetree->key, now);
-      if(!*timeout_ms)
+      timediff_t diff = Curl_timediff(multi->timetree->key, now);
+      if(diff <= 0)
         /*
          * Since we only provide millisecond resolution on the returned value
          * and the diff might be less than one millisecond here, we don't
@@ -2796,6 +2738,10 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
          * millisecond! instead we return 1 until the time is ripe.
          */
         *timeout_ms = 1;
+      else
+        /* this should be safe even on 64 bit archs, as we don't use that
+           overly long timeouts */
+        *timeout_ms = (long)diff;
     }
     else
       /* 0 means immediately */
@@ -2902,7 +2848,7 @@ multi_addtimeout(struct Curl_easy *data,
     /* find the correct spot in the list */
     for(e = timeoutlist->head; e; e = e->next) {
       struct time_node *check = (struct time_node *)e->ptr;
-      time_t diff = curlx_tvdiff(check->time, node->time);
+      timediff_t diff = Curl_timediff(check->time, node->time);
       if(diff > 0)
         break;
       prev = e;
@@ -2941,7 +2887,7 @@ void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
 
   DEBUGASSERT(id < EXPIRE_LAST);
 
-  set = Curl_tvnow();
+  set = Curl_now();
   set.tv_sec += milli/1000;
   set.tv_usec += (unsigned int)(milli%1000)*1000;
 
@@ -2961,7 +2907,7 @@ void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
     /* This means that the struct is added as a node in the splay tree.
        Compare if the new time is earlier, and only remove-old/add-new if it
        is. */
-    time_t diff = curlx_tvdiff(set, *nowp);
+    timediff_t diff = Curl_timediff(set, *nowp);
 
     if(diff > 0) {
       /* The current splay tree entry is sooner than this new expiry time.
diff --git a/lib/multihandle.h b/lib/multihandle.h
index 4057539..de9a7cf 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -114,10 +114,6 @@ struct Curl_multi {
   /* Shared connection cache (bundles)*/
   struct conncache conn_cache;
 
-  /* This handle will be used for closing the cached connections in
-     curl_multi_cleanup() */
-  struct Curl_easy *closure_handle;
-
   long maxconnects; /* if >0, a fixed limit of the maximum number of entries
                        we're allowed to grow the connection cache to */
 
diff --git a/lib/openldap.c b/lib/openldap.c
index f294403..f2ffdfe 100644
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -51,6 +51,25 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+/*
+ * Uncommenting this will enable the built-in debug logging of the openldap
+ * library. The debug log level can be set using the CURL_OPENLDAP_TRACE
+ * environment variable. The debug output is written to stderr.
+ *
+ * The library supports the following debug flags:
+ * LDAP_DEBUG_NONE         0x0000
+ * LDAP_DEBUG_TRACE        0x0001
+ * LDAP_DEBUG_CONSTRUCT    0x0002
+ * LDAP_DEBUG_DESTROY      0x0004
+ * LDAP_DEBUG_PARAMETER    0x0008
+ * LDAP_DEBUG_ANY          0xffff
+ *
+ * For example, use CURL_OPENLDAP_TRACE=0 for no debug,
+ * CURL_OPENLDAP_TRACE=2 for LDAP_DEBUG_CONSTRUCT messages only,
+ * CURL_OPENLDAP_TRACE=65535 for all debug message levels.
+ */
+/* #define CURL_OPENLDAP_DEBUG */
+
 #ifndef _LDAP_PVT_H
 extern int ldap_pvt_url_scheme2proto(const char *);
 extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
@@ -204,6 +223,15 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
   snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
     conn->host.name, conn->remote_port);
 
+#ifdef CURL_OPENLDAP_DEBUG
+  static int do_trace = 0;
+  const char *env = getenv("CURL_OPENLDAP_TRACE");
+  do_trace = (env && strtol(env, NULL, 10) > 0);
+  if(do_trace) {
+    ldap_set_option(li->ld, LDAP_OPT_DEBUG_LEVEL, &do_trace);
+  }
+#endif
+
   rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld);
   if(rc) {
     failf(data, "LDAP local: Cannot connect to %s, %s",
@@ -677,7 +705,7 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
   ber_slen_t ret;
   CURLcode err = CURLE_RECV_ERROR;
 
-  ret = li->recv(conn, FIRSTSOCKET, buf, len, &err);
+  ret = (li->recv)(conn, FIRSTSOCKET, buf, len, &err);
   if(ret < 0 && err == CURLE_AGAIN) {
     SET_SOCKERRNO(EWOULDBLOCK);
   }
@@ -692,7 +720,7 @@ ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
   ber_slen_t ret;
   CURLcode err = CURLE_SEND_ERROR;
 
-  ret = li->send(conn, FIRSTSOCKET, buf, len, &err);
+  ret = (li->send)(conn, FIRSTSOCKET, buf, len, &err);
   if(ret < 0 && err == CURLE_AGAIN) {
     SET_SOCKERRNO(EWOULDBLOCK);
   }
diff --git a/lib/parsedate.c b/lib/parsedate.c
index b82605b..0fabbd2 100644
--- a/lib/parsedate.c
+++ b/lib/parsedate.c
@@ -75,9 +75,7 @@
 
 #include "curl_setup.h"
 
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#endif
 
 #include <curl/curl.h>
 #include "strcase.h"
diff --git a/lib/pingpong.c b/lib/pingpong.c
index b8f2140..438856a 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -61,12 +61,12 @@ time_t Curl_pp_state_timeout(struct pingpong *pp)
   /* Without a requested timeout, we only wait 'response_time' seconds for the
      full response to arrive before we bail out */
   timeout_ms = response_time -
-    Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */
+    Curl_timediff(Curl_now(), pp->response); /* spent time */
 
   if(data->set.timeout) {
     /* if timeout is requested, find out how much remaining time we have */
     timeout2_ms = data->set.timeout - /* timeout time */
-      Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
+      Curl_timediff(Curl_now(), conn->now); /* spent time */
 
     /* pick the lowest number */
     timeout_ms = CURLMIN(timeout_ms, timeout2_ms);
@@ -120,7 +120,7 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
     if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
     else
-      result = Curl_speedcheck(data, Curl_tvnow());
+      result = Curl_speedcheck(data, Curl_now());
 
     if(result)
       return result;
@@ -143,7 +143,7 @@ void Curl_pp_init(struct pingpong *pp)
   pp->nread_resp = 0;
   pp->linestart_resp = conn->data->state.buffer;
   pp->pending_resp = TRUE;
-  pp->response = Curl_tvnow(); /* start response time-out now! */
+  pp->response = Curl_now(); /* start response time-out now! */
 }
 
 
@@ -168,16 +168,22 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
   char *s;
   CURLcode result;
   struct connectdata *conn = pp->conn;
-  struct Curl_easy *data = conn->data;
+  struct Curl_easy *data;
 
 #ifdef HAVE_GSSAPI
-  enum protection_level data_sec = conn->data_prot;
+  enum protection_level data_sec;
 #endif
 
   DEBUGASSERT(pp->sendleft == 0);
   DEBUGASSERT(pp->sendsize == 0);
   DEBUGASSERT(pp->sendthis == NULL);
 
+  if(!conn)
+    /* can't send without a connection! */
+    return CURLE_SEND_ERROR;
+
+  data = conn->data;
+
   fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */
   if(!fmt_crlf)
     return CURLE_OUT_OF_MEMORY;
@@ -205,6 +211,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
   result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
                      &bytes_written);
 #ifdef HAVE_GSSAPI
+  data_sec = conn->data_prot;
   DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
   conn->data_prot = data_sec;
 #endif
@@ -228,7 +235,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
     free(s);
     pp->sendthis = NULL;
     pp->sendleft = pp->sendsize = 0;
-    pp->response = Curl_tvnow();
+    pp->response = Curl_now();
   }
 
   return CURLE_OK;
@@ -492,7 +499,7 @@ CURLcode Curl_pp_flushsend(struct pingpong *pp)
     free(pp->sendthis);
     pp->sendthis = NULL;
     pp->sendleft = pp->sendsize = 0;
-    pp->response = Curl_tvnow();
+    pp->response = Curl_now();
   }
   return CURLE_OK;
 }
diff --git a/lib/pingpong.h b/lib/pingpong.h
index a2c8ff5..5ac8df8 100644
--- a/lib/pingpong.h
+++ b/lib/pingpong.h
@@ -58,8 +58,8 @@ struct pingpong {
                      server */
   size_t sendleft; /* number of bytes left to send from the sendthis buffer */
   size_t sendsize; /* total size of the sendthis buffer */
-  struct curltime response; /* set to Curl_tvnow() when a command has been sent
-                              off, used to time-out response reading */
+  struct curltime response; /* set to Curl_now() when a command has been sent
+                               off, used to time-out response reading */
   long response_time; /* When no timeout is given, this is the amount of
                          milliseconds we await for a server response. */
 
diff --git a/lib/pop3.c b/lib/pop3.c
index 5792a4a..78f6afe 100644
--- a/lib/pop3.c
+++ b/lib/pop3.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
@@ -243,23 +243,30 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
  */
 static void pop3_get_message(char *buffer, char **outptr)
 {
-  size_t len = 0;
+  size_t len = strlen(buffer);
   char *message = NULL;
 
-  /* Find the start of the message */
-  for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
-    ;
-
-  /* Find the end of the message */
-  for(len = strlen(message); len--;)
-    if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
-        message[len] != '\t')
-      break;
-
-  /* Terminate the message */
-  if(++len) {
-    message[len] = '\0';
+  if(len > 2) {
+    /* Find the start of the message */
+    len -= 2;
+    for(message = buffer + 2; *message == ' ' || *message == '\t';
+        message++, len--)
+      ;
+
+    /* Find the end of the message */
+    for(; len--;)
+      if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
+         message[len] != '\t')
+        break;
+
+    /* Terminate the message */
+    if(++len) {
+      message[len] = '\0';
+    }
   }
+  else
+    /* junk input => zero length output */
+    message = &buffer[len];
 
   *outptr = message;
 }
diff --git a/lib/progress.c b/lib/progress.c
index 00609d9..cc5e8be 100644
--- a/lib/progress.c
+++ b/lib/progress.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
@@ -161,7 +161,7 @@ void Curl_pgrsResetTransferSizes(struct Curl_easy *data)
  */
 void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
 {
-  struct curltime now = Curl_tvnow();
+  struct curltime now = Curl_now();
   time_t *delta = NULL;
 
   switch(timer) {
@@ -212,13 +212,13 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
     /* this is the normal end-of-transfer thing */
     break;
   case TIMER_REDIRECT:
-    data->progress.t_redirect = Curl_tvdiff_us(now, data->progress.start);
+    data->progress.t_redirect = Curl_timediff_us(now, data->progress.start);
     break;
   }
   if(delta) {
-    time_t us = Curl_tvdiff_us(now, data->progress.t_startsingle);
-    if(!us)
-      us++; /* make sure at least one microsecond passed */
+    timediff_t us = Curl_timediff_us(now, data->progress.t_startsingle);
+    if(us < 1)
+      us = 1; /* make sure at least one microsecond passed */
     *delta += us;
   }
 }
@@ -226,7 +226,7 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
 void Curl_pgrsStartNow(struct Curl_easy *data)
 {
   data->progress.speeder_c = 0; /* reset the progress meter display */
-  data->progress.start = Curl_tvnow();
+  data->progress.start = Curl_now();
   data->progress.is_t_startransfer_set = false;
   data->progress.ul_limit_start.tv_sec = 0;
   data->progress.ul_limit_start.tv_usec = 0;
@@ -274,7 +274,7 @@ long Curl_pgrsLimitWaitTime(curl_off_t cursize,
     return -1;
 
   minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
-  actual = Curl_tvdiff(now, start);
+  actual = Curl_timediff(now, start);
 
   if(actual < minimum)
     /* this is a conversion on some systems (64bit time_t => 32bit long) */
@@ -285,7 +285,7 @@ long Curl_pgrsLimitWaitTime(curl_off_t cursize,
 
 void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
 {
-  struct curltime now = Curl_tvnow();
+  struct curltime now = Curl_now();
 
   data->progress.downloaded = size;
 
@@ -303,7 +303,7 @@ void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
 
 void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size)
 {
-  struct curltime now = Curl_tvnow();
+  struct curltime now = Curl_now();
 
   data->progress.uploaded = size;
 
@@ -358,6 +358,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
   curl_off_t total_transfer;
   curl_off_t total_expected_transfer;
   curl_off_t timespent;
+  curl_off_t timespent_ms; /* milliseconds */
   struct Curl_easy *data = conn->data;
   int nowindex = data->progress.speeder_c% CURR_TIME;
   int checkindex;
@@ -369,22 +370,27 @@ int Curl_pgrsUpdate(struct connectdata *conn)
   curl_off_t dlestimate = 0;
   curl_off_t total_estimate;
   bool shownow = FALSE;
+  curl_off_t dl = data->progress.downloaded;
+  curl_off_t ul = data->progress.uploaded;
 
-  now = Curl_tvnow(); /* what time is it */
+  now = Curl_now(); /* what time is it */
 
   /* The time spent so far (from the start) */
-  data->progress.timespent = Curl_tvdiff_us(now, data->progress.start);
+  data->progress.timespent = Curl_timediff_us(now, data->progress.start);
   timespent = (curl_off_t)data->progress.timespent/1000000; /* seconds */
+  timespent_ms = (curl_off_t)data->progress.timespent/1000; /* ms */
 
   /* The average download speed this far */
-  data->progress.dlspeed = (curl_off_t)
-    (data->progress.downloaded/
-     (timespent>0?timespent:1));
+  if(dl < CURL_OFF_T_MAX/1000)
+    data->progress.dlspeed = (dl * 1000 / (timespent_ms>0?timespent_ms:1));
+  else
+    data->progress.dlspeed = (dl / (timespent>0?timespent:1));
 
   /* The average upload speed this far */
-  data->progress.ulspeed = (curl_off_t)
-    (data->progress.uploaded/
-     (timespent>0?timespent:1));
+  if(ul < CURL_OFF_T_MAX/1000)
+    data->progress.ulspeed = (ul * 1000 / (timespent_ms>0?timespent_ms:1));
+  else
+    data->progress.ulspeed = (ul / (timespent>0?timespent:1));
 
   /* Calculations done at most once a second, unless end is reached */
   if(data->progress.lastshow != now.tv_sec) {
@@ -413,7 +419,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
 
     /* first of all, we don't do this if there's no counted seconds yet */
     if(countindex) {
-      time_t span_ms;
+      timediff_t span_ms;
 
       /* Get the index position to compare with the 'nowindex' position.
          Get the oldest entry possible. While we have less than CURR_TIME
@@ -422,8 +428,8 @@ int Curl_pgrsUpdate(struct connectdata *conn)
         data->progress.speeder_c%CURR_TIME:0;
 
       /* Figure out the exact time for the time span */
-      span_ms = Curl_tvdiff(now,
-                            data->progress.speeder_time[checkindex]);
+      span_ms = Curl_timediff(now,
+                              data->progress.speeder_time[checkindex]);
       if(0 == span_ms)
         span_ms = 1; /* at least one millisecond MUST have passed */
 
diff --git a/lib/rand.c b/lib/rand.c
index 2713a0a..0769ed1 100644
--- a/lib/rand.c
+++ b/lib/rand.c
@@ -86,7 +86,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
 #endif
 
   if(!seeded) {
-    struct curltime now = curlx_tvnow();
+    struct curltime now = Curl_now();
     infof(data, "WARNING: Using weak random seed\n");
     randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
     randseed = randseed * 1103515245 + 12345;
@@ -157,6 +157,12 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
   unsigned char *bufp = buffer;
   DEBUGASSERT(num > 1);
 
+#ifdef __clang_analyzer__
+  /* This silences a scan-build warning about accesssing this buffer with
+     uninitialized memory. */
+  memset(buffer, 0, sizeof(buffer));
+#endif
+
   if((num/2 >= sizeof(buffer)) || !(num&1))
     /* make sure it fits in the local buffer and that it is an odd number! */
     return CURLE_BAD_FUNCTION_ARGUMENT;
diff --git a/lib/security.c b/lib/security.c
index a2e4a35..d171985 100644
--- a/lib/security.c
+++ b/lib/security.c
@@ -50,9 +50,7 @@
 #include <netdb.h>
 #endif
 
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#endif
 
 #include "urldata.h"
 #include "curl_base64.h"
diff --git a/lib/select.c b/lib/select.c
index f6fecaf..28390a4 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -51,7 +51,7 @@
 #include "warnless.h"
 
 /* Convenience local macros */
-#define ELAPSED_MS()  (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
+#define ELAPSED_MS() (int)Curl_timediff(Curl_now(), initial_tv)
 
 int Curl_ack_eintr = 0;
 #define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR)
@@ -96,7 +96,7 @@ int Curl_wait_ms(int timeout_ms)
   Sleep(timeout_ms);
 #else
   pending_ms = timeout_ms;
-  initial_tv = curlx_tvnow();
+  initial_tv = Curl_now();
   do {
 #if defined(HAVE_POLL_FINE)
     r = poll(NULL, 0, pending_ms);
@@ -177,14 +177,14 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
     return r;
   }
 
-  /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
+  /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
      time in this function does not need to be measured. This happens
      when function is called with a zero timeout or a negative timeout
      value indicating a blocking call should be performed. */
 
   if(timeout_ms > 0) {
     pending_ms = (int)timeout_ms;
-    initial_tv = curlx_tvnow();
+    initial_tv = Curl_now();
   }
 
 #ifdef HAVE_POLL_FINE
@@ -418,14 +418,14 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
     return r;
   }
 
-  /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
+  /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
      time in this function does not need to be measured. This happens
      when function is called with a zero timeout or a negative timeout
      value indicating a blocking call should be performed. */
 
   if(timeout_ms > 0) {
     pending_ms = timeout_ms;
-    initial_tv = curlx_tvnow();
+    initial_tv = Curl_now();
   }
 
 #ifdef HAVE_POLL_FINE
diff --git a/lib/sendf.c b/lib/sendf.c
index 7564cb3..027f97c 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -22,6 +22,14 @@
 
 #include "curl_setup.h"
 
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_LINUX_TCP_H
+#include <linux/tcp.h>
+#endif
+
 #include <curl/curl.h>
 
 #include "urldata.h"
@@ -241,25 +249,25 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
 
 void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
 {
-  va_list ap;
-  size_t len;
-  char error[CURL_ERROR_SIZE + 2];
-  va_start(ap, fmt);
-
-  vsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
-  len = strlen(error);
+  if(data->set.verbose || data->set.errorbuffer) {
+    va_list ap;
+    size_t len;
+    char error[CURL_ERROR_SIZE + 2];
+    va_start(ap, fmt);
+    vsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
+    len = strlen(error);
 
-  if(data->set.errorbuffer && !data->state.errorbuf) {
-    strcpy(data->set.errorbuffer, error);
-    data->state.errorbuf = TRUE; /* wrote error string */
-  }
-  if(data->set.verbose) {
-    error[len] = '\n';
-    error[++len] = '\0';
-    Curl_debug(data, CURLINFO_TEXT, error, len, NULL);
+    if(data->set.errorbuffer && !data->state.errorbuf) {
+      strcpy(data->set.errorbuffer, error);
+      data->state.errorbuf = TRUE; /* wrote error string */
+    }
+    if(data->set.verbose) {
+      error[len] = '\n';
+      error[++len] = '\0';
+      Curl_debug(data, CURLINFO_TEXT, error, len, NULL);
+    }
+    va_end(ap);
   }
-
-  va_end(ap);
 }
 
 /* Curl_sendf() sends formatted data to the server */
@@ -360,7 +368,7 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
      available. */
   pre_receive_plain(conn, num);
 
-#ifdef MSG_FASTOPEN /* Linux */
+#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
   if(conn->bits.tcp_fastopen) {
     bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,
                            conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen);
diff --git a/lib/setopt.c b/lib/setopt.c
new file mode 100644
index 0000000..a5ef75c
--- /dev/null
+++ b/lib/setopt.c
@@ -0,0 +1,2556 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * 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
+ * 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 <limits.h>
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_LINUX_TCP_H
+#include <linux/tcp.h>
+#endif
+
+#include "urldata.h"
+#include "url.h"
+#include "progress.h"
+#include "content_encoding.h"
+#include "strcase.h"
+#include "share.h"
+#include "vtls/vtls.h"
+#include "warnless.h"
+#include "sendf.h"
+#include "http2.h"
+#include "setopt.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+CURLcode Curl_setstropt(char **charp, const char *s)
+{
+  /* Release the previous storage at `charp' and replace by a dynamic storage
+     copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
+
+  Curl_safefree(*charp);
+
+  if(s) {
+    char *str = strdup(s);
+
+    if(!str)
+      return CURLE_OUT_OF_MEMORY;
+
+    *charp = str;
+  }
+
+  return CURLE_OK;
+}
+
+static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
+{
+  CURLcode result = CURLE_OK;
+  char *user = NULL;
+  char *passwd = NULL;
+
+  /* Parse the login details if specified. It not then we treat NULL as a hint
+     to clear the existing data */
+  if(option) {
+    result = Curl_parse_login_details(option, strlen(option),
+                                      (userp ? &user : NULL),
+                                      (passwdp ? &passwd : NULL),
+                                      NULL);
+  }
+
+  if(!result) {
+    /* Store the username part of option if required */
+    if(userp) {
+      if(!user && option && option[0] == ':') {
+        /* Allocate an empty string instead of returning NULL as user name */
+        user = strdup("");
+        if(!user)
+          result = CURLE_OUT_OF_MEMORY;
+      }
+
+      Curl_safefree(*userp);
+      *userp = user;
+    }
+
+    /* Store the password part of option if required */
+    if(passwdp) {
+      Curl_safefree(*passwdp);
+      *passwdp = passwd;
+    }
+  }
+
+  return result;
+}
+
+#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)
+{
+  char *argptr;
+  CURLcode result = CURLE_OK;
+  long arg;
+  curl_off_t bigsize;
+
+  switch(option) {
+  case CURLOPT_DNS_CACHE_TIMEOUT:
+    arg = va_arg(param, long);
+    if(arg < -1)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.dns_cache_timeout = arg;
+    break;
+  case CURLOPT_DNS_USE_GLOBAL_CACHE:
+    /* remember we want this enabled */
+    arg = va_arg(param, long);
+    data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
+    break;
+  case CURLOPT_SSL_CIPHER_LIST:
+    /* set a list of cipher we want to use in the SSL connection */
+    result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
+                            va_arg(param, char *));
+    break;
+  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;
+
+  case CURLOPT_RANDOM_FILE:
+    /*
+     * This is the path name to a file that contains random data to seed
+     * the random SSL stuff with. The file is only used for reading.
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_EGDSOCKET:
+    /*
+     * The Entropy Gathering Daemon socket pathname
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_MAXCONNECTS:
+    /*
+     * Set the absolute number of maximum simultaneous alive connection that
+     * libcurl is allowed to have.
+     */
+    arg = va_arg(param, long);
+    if(arg < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.maxconnects = arg;
+    break;
+  case CURLOPT_FORBID_REUSE:
+    /*
+     * When this transfer is done, it must not be left to be reused by a
+     * subsequent transfer but shall be closed immediately.
+     */
+    data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_FRESH_CONNECT:
+    /*
+     * This transfer shall not use a previously cached connection but
+     * should be made with a fresh new connect!
+     */
+    data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_VERBOSE:
+    /*
+     * Verbose means infof() calls that give a lot of information about
+     * the connection and transfer procedures as well as internal choices.
+     */
+    data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_HEADER:
+    /*
+     * Set to include the header in the general data output stream.
+     */
+    data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_NOPROGRESS:
+    /*
+     * Shut off the internal supported progress meter
+     */
+    data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    if(data->set.hide_progress)
+      data->progress.flags |= PGRS_HIDE;
+    else
+      data->progress.flags &= ~PGRS_HIDE;
+    break;
+  case CURLOPT_NOBODY:
+    /*
+     * Do not include the body part in the output data stream.
+     */
+    data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_FAILONERROR:
+    /*
+     * Don't output the >=400 error code HTML-page, but instead only
+     * return error.
+     */
+    data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_KEEP_SENDING_ON_ERROR:
+    data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
+      TRUE : FALSE;
+    break;
+  case CURLOPT_UPLOAD:
+  case CURLOPT_PUT:
+    /*
+     * We want to sent data to the remote host. If this is HTTP, that equals
+     * using the PUT request.
+     */
+    data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    if(data->set.upload) {
+      /* If this is HTTP, PUT is what's needed to "upload" */
+      data->set.httpreq = HTTPREQ_PUT;
+      data->set.opt_no_body = FALSE; /* this is implied */
+    }
+    else
+      /* In HTTP, the opposite of upload is GET (unless NOBODY is true as
+         then this can be changed to HEAD later on) */
+      data->set.httpreq = HTTPREQ_GET;
+    break;
+  case CURLOPT_REQUEST_TARGET:
+    result = Curl_setstropt(&data->set.str[STRING_TARGET],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_FILETIME:
+    /*
+     * Try to get the file time of the remote document. The time will
+     * later (possibly) become available using curl_easy_getinfo().
+     */
+    data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_FTP_CREATE_MISSING_DIRS:
+    /*
+     * An FTP option that modifies an upload to create missing directories on
+     * the server.
+     */
+    switch(va_arg(param, long)) {
+    case 0:
+      data->set.ftp_create_missing_dirs = 0;
+      break;
+    case 1:
+      data->set.ftp_create_missing_dirs = 1;
+      break;
+    case 2:
+      data->set.ftp_create_missing_dirs = 2;
+      break;
+    default:
+      /* reserve other values for future use */
+      result = CURLE_UNKNOWN_OPTION;
+      break;
+    }
+    break;
+  case CURLOPT_SERVER_RESPONSE_TIMEOUT:
+    /*
+     * Option that specifies how quickly an server response must be obtained
+     * before it is considered failure. For pingpong protocols.
+     */
+    arg = va_arg(param, long);
+    if((arg >= 0) && (arg <= (INT_MAX/1000)))
+      data->set.server_response_timeout = arg * 1000;
+    else
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    break;
+  case CURLOPT_TFTP_NO_OPTIONS:
+    /*
+     * Option that prevents libcurl from sending TFTP option requests to the
+     * server.
+     */
+    data->set.tftp_no_options = va_arg(param, long) != 0;
+    break;
+  case CURLOPT_TFTP_BLKSIZE:
+    /*
+     * TFTP option that specifies the block size to use for data transmission.
+     */
+    arg = va_arg(param, long);
+    if(arg < 0)
+      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;
+  case CURLOPT_NETRC:
+    /*
+     * Parse the $HOME/.netrc file
+     */
+    arg = va_arg(param, long);
+    if((arg < CURL_NETRC_IGNORED) || (arg > CURL_NETRC_REQUIRED))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.use_netrc = (enum CURL_NETRC_OPTION)arg;
+    break;
+  case CURLOPT_NETRC_FILE:
+    /*
+     * Use this file instead of the $HOME/.netrc file
+     */
+    result = Curl_setstropt(&data->set.str[STRING_NETRC_FILE],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_TRANSFERTEXT:
+    /*
+     * This option was previously named 'FTPASCII'. Renamed to work with
+     * more protocols than merely FTP.
+     *
+     * Transfer using ASCII (instead of BINARY).
+     */
+    data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_TIMECONDITION:
+    /*
+     * Set HTTP time condition. This must be one of the defines in the
+     * curl/curl.h header file.
+     */
+    arg = va_arg(param, long);
+    if((arg < CURL_TIMECOND_NONE) || (arg > CURL_TIMECOND_LASTMOD))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.timecondition = (curl_TimeCond)arg;
+    break;
+  case CURLOPT_TIMEVALUE:
+    /*
+     * This is the value to compare with the remote document with the
+     * method set with CURLOPT_TIMECONDITION
+     */
+    data->set.timevalue = (time_t)va_arg(param, long);
+    break;
+
+  case CURLOPT_SSLVERSION:
+  case CURLOPT_PROXY_SSLVERSION:
+    /*
+     * Set explicit SSL version to try to connect with, as some SSL
+     * implementations are lame.
+     */
+#ifdef USE_SSL
+    {
+      long version, version_max;
+      struct ssl_primary_config *primary = (option == CURLOPT_SSLVERSION ?
+                                            &data->set.ssl.primary :
+                                            &data->set.proxy_ssl.primary);
+
+      arg = va_arg(param, long);
+
+      version = C_SSLVERSION_VALUE(arg);
+      version_max = C_SSLVERSION_MAX_VALUE(arg);
+
+      if(version < CURL_SSLVERSION_DEFAULT ||
+         version >= CURL_SSLVERSION_LAST ||
+         version_max < CURL_SSLVERSION_MAX_NONE ||
+         version_max >= CURL_SSLVERSION_MAX_LAST)
+        return CURLE_BAD_FUNCTION_ARGUMENT;
+
+      primary->version = version;
+      primary->version_max = version_max;
+    }
+#else
+    result = CURLE_UNKNOWN_OPTION;
+#endif
+    break;
+
+#ifndef CURL_DISABLE_HTTP
+  case CURLOPT_AUTOREFERER:
+    /*
+     * Switch on automatic referer that gets set if curl follows locations.
+     */
+    data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_ACCEPT_ENCODING:
+    /*
+     * String to use at the value of Accept-Encoding header.
+     *
+     * If the encoding is set to "" we use an Accept-Encoding header that
+     * encompasses all the encodings we support.
+     * If the encoding is set to NULL we don't send an Accept-Encoding header
+     * and ignore an received Content-Encoding header.
+     *
+     */
+    argptr = va_arg(param, char *);
+    if(argptr && !*argptr) {
+      argptr = Curl_all_content_encodings();
+      if(!argptr)
+        result = CURLE_OUT_OF_MEMORY;
+      else {
+        result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
+        free(argptr);
+      }
+    }
+    else
+      result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
+    break;
+
+  case CURLOPT_TRANSFER_ENCODING:
+    data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
+      TRUE : FALSE;
+    break;
+
+  case CURLOPT_FOLLOWLOCATION:
+    /*
+     * Follow Location: header hints on a HTTP-server.
+     */
+    data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_UNRESTRICTED_AUTH:
+    /*
+     * Send authentication (user+password) when following locations, even when
+     * hostname changed.
+     */
+    data->set.allow_auth_to_other_hosts =
+      (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_MAXREDIRS:
+    /*
+     * The maximum amount of hops you allow curl to follow Location:
+     * headers. This should mostly be used to detect never-ending loops.
+     */
+    arg = va_arg(param, long);
+    if(arg < -1)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.maxredirs = arg;
+    break;
+
+  case CURLOPT_POSTREDIR:
+    /*
+     * Set the behaviour of POST when redirecting
+     * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
+     * CURL_REDIR_POST_301 - POST is kept as POST after 301
+     * CURL_REDIR_POST_302 - POST is kept as POST after 302
+     * CURL_REDIR_POST_303 - POST is kept as POST after 303
+     * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
+     * other - POST is kept as POST after 301 and 302
+     */
+    arg = va_arg(param, long);
+    if(arg < CURL_REDIR_GET_ALL)
+      /* no return error on too high numbers since the bitmask could be
+         extended in a future */
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.keep_post = arg & CURL_REDIR_POST_ALL;
+    break;
+
+  case CURLOPT_POST:
+    /* Does this option serve a purpose anymore? Yes it does, when
+       CURLOPT_POSTFIELDS isn't used and the POST data is read off the
+       callback! */
+    if(va_arg(param, long)) {
+      data->set.httpreq = HTTPREQ_POST;
+      data->set.opt_no_body = FALSE; /* this is implied */
+    }
+    else
+      data->set.httpreq = HTTPREQ_GET;
+    break;
+
+  case CURLOPT_COPYPOSTFIELDS:
+    /*
+     * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
+     * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
+     *  CURLOPT_COPYPOSTFIELDS and not altered later.
+     */
+    argptr = va_arg(param, char *);
+
+    if(!argptr || data->set.postfieldsize == -1)
+      result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
+    else {
+      /*
+       *  Check that requested length does not overflow the size_t type.
+       */
+
+      if((data->set.postfieldsize < 0) ||
+         ((sizeof(curl_off_t) != sizeof(size_t)) &&
+          (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
+        result = CURLE_OUT_OF_MEMORY;
+      else {
+        char *p;
+
+        (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+
+        /* Allocate even when size == 0. This satisfies the need of possible
+           later address compare to detect the COPYPOSTFIELDS mode, and
+           to mark that postfields is used rather than read function or
+           form data.
+        */
+        p = malloc((size_t)(data->set.postfieldsize?
+                            data->set.postfieldsize:1));
+
+        if(!p)
+          result = CURLE_OUT_OF_MEMORY;
+        else {
+          if(data->set.postfieldsize)
+            memcpy(p, argptr, (size_t)data->set.postfieldsize);
+
+          data->set.str[STRING_COPYPOSTFIELDS] = p;
+        }
+      }
+    }
+
+    data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
+    data->set.httpreq = HTTPREQ_POST;
+    break;
+
+  case CURLOPT_POSTFIELDS:
+    /*
+     * Like above, but use static data instead of copying it.
+     */
+    data->set.postfields = va_arg(param, void *);
+    /* Release old copied data. */
+    (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+    data->set.httpreq = HTTPREQ_POST;
+    break;
+
+  case CURLOPT_POSTFIELDSIZE:
+    /*
+     * The size of the POSTFIELD data to prevent libcurl to do strlen() to
+     * figure it out. Enables binary posts.
+     */
+    bigsize = va_arg(param, long);
+    if(bigsize < -1)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+
+    if(data->set.postfieldsize < bigsize &&
+       data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
+      /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
+      (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+      data->set.postfields = NULL;
+    }
+
+    data->set.postfieldsize = bigsize;
+    break;
+
+  case CURLOPT_POSTFIELDSIZE_LARGE:
+    /*
+     * The size of the POSTFIELD data to prevent libcurl to do strlen() to
+     * figure it out. Enables binary posts.
+     */
+    bigsize = va_arg(param, curl_off_t);
+    if(bigsize < -1)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+
+    if(data->set.postfieldsize < bigsize &&
+       data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
+      /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
+      (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+      data->set.postfields = NULL;
+    }
+
+    data->set.postfieldsize = bigsize;
+    break;
+
+  case CURLOPT_HTTPPOST:
+    /*
+     * Set to make us do HTTP POST
+     */
+    data->set.httppost = va_arg(param, struct curl_httppost *);
+    data->set.httpreq = HTTPREQ_POST_FORM;
+    data->set.opt_no_body = FALSE; /* this is implied */
+    break;
+#endif   /* CURL_DISABLE_HTTP */
+
+  case CURLOPT_MIMEPOST:
+    /*
+     * Set to make us do MIME/form POST
+     */
+    result = Curl_mime_set_subparts(&data->set.mimepost,
+                                    va_arg(param, curl_mime *), FALSE);
+    if(!result) {
+      data->set.httpreq = HTTPREQ_POST_MIME;
+      data->set.opt_no_body = FALSE; /* this is implied */
+    }
+    break;
+
+  case CURLOPT_REFERER:
+    /*
+     * String to set in the HTTP Referer: field.
+     */
+    if(data->change.referer_alloc) {
+      Curl_safefree(data->change.referer);
+      data->change.referer_alloc = FALSE;
+    }
+    result = Curl_setstropt(&data->set.str[STRING_SET_REFERER],
+                            va_arg(param, char *));
+    data->change.referer = data->set.str[STRING_SET_REFERER];
+    break;
+
+  case CURLOPT_USERAGENT:
+    /*
+     * String to use in the HTTP User-Agent field
+     */
+    result = Curl_setstropt(&data->set.str[STRING_USERAGENT],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_HTTPHEADER:
+    /*
+     * Set a list with HTTP headers to use (or replace internals with)
+     */
+    data->set.headers = va_arg(param, struct curl_slist *);
+    break;
+
+#ifndef CURL_DISABLE_HTTP
+  case CURLOPT_PROXYHEADER:
+    /*
+     * Set a list with proxy headers to use (or replace internals with)
+     *
+     * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
+     * long time we remain doing it this way until CURLOPT_PROXYHEADER is
+     * used. As soon as this option has been used, if set to anything but
+     * NULL, custom headers for proxies are only picked from this list.
+     *
+     * Set this option to NULL to restore the previous behavior.
+     */
+    data->set.proxyheaders = va_arg(param, struct curl_slist *);
+    break;
+
+  case CURLOPT_HEADEROPT:
+    /*
+     * Set header option.
+     */
+    arg = va_arg(param, long);
+    data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
+    break;
+
+  case CURLOPT_HTTP200ALIASES:
+    /*
+     * Set a list of aliases for HTTP 200 in response header
+     */
+    data->set.http200aliases = va_arg(param, struct curl_slist *);
+    break;
+
+#if !defined(CURL_DISABLE_COOKIES)
+  case CURLOPT_COOKIE:
+    /*
+     * Cookie string to send to the remote server in the request.
+     */
+    result = Curl_setstropt(&data->set.str[STRING_COOKIE],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_COOKIEFILE:
+    /*
+     * Set cookie file to read and parse. Can be used multiple times.
+     */
+    argptr = (char *)va_arg(param, void *);
+    if(argptr) {
+      struct curl_slist *cl;
+      /* append the cookie file name to the list of file names, and deal with
+         them later */
+      cl = curl_slist_append(data->change.cookielist, argptr);
+      if(!cl) {
+        curl_slist_free_all(data->change.cookielist);
+        data->change.cookielist = NULL;
+        return CURLE_OUT_OF_MEMORY;
+      }
+      data->change.cookielist = cl; /* store the list for later use */
+    }
+    break;
+
+  case CURLOPT_COOKIEJAR:
+    /*
+     * Set cookie file name to dump all cookies to when we're done.
+     */
+  {
+    struct CookieInfo *newcookies;
+    result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR],
+                            va_arg(param, char *));
+
+    /*
+     * Activate the cookie parser. This may or may not already
+     * have been made.
+     */
+    newcookies = Curl_cookie_init(data, NULL, data->cookies,
+                                  data->set.cookiesession);
+    if(!newcookies)
+      result = CURLE_OUT_OF_MEMORY;
+    data->cookies = newcookies;
+  }
+  break;
+
+  case CURLOPT_COOKIESESSION:
+    /*
+     * Set this option to TRUE to start a new "cookie session". It will
+     * prevent the forthcoming read-cookies-from-file actions to accept
+     * cookies that are marked as being session cookies, as they belong to a
+     * previous session.
+     *
+     * In the original Netscape cookie spec, "session cookies" are cookies
+     * with no expire date set. RFC2109 describes the same action if no
+     * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
+     * a 'Discard' action that can enforce the discard even for cookies that
+     * have a Max-Age.
+     *
+     * We run mostly with the original cookie spec, as hardly anyone implements
+     * anything else.
+     */
+    data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_COOKIELIST:
+    argptr = va_arg(param, char *);
+
+    if(argptr == NULL)
+      break;
+
+    if(strcasecompare(argptr, "ALL")) {
+      /* clear all cookies */
+      Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+      Curl_cookie_clearall(data->cookies);
+      Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+    }
+    else if(strcasecompare(argptr, "SESS")) {
+      /* clear session cookies */
+      Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+      Curl_cookie_clearsess(data->cookies);
+      Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+    }
+    else if(strcasecompare(argptr, "FLUSH")) {
+      /* flush cookies to file, takes care of the locking */
+      Curl_flush_cookies(data, 0);
+    }
+    else if(strcasecompare(argptr, "RELOAD")) {
+      /* reload cookies from file */
+      Curl_cookie_loadfiles(data);
+      break;
+    }
+    else {
+      if(!data->cookies)
+        /* if cookie engine was not running, activate it */
+        data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
+
+      argptr = strdup(argptr);
+      if(!argptr || !data->cookies) {
+        result = CURLE_OUT_OF_MEMORY;
+        free(argptr);
+      }
+      else {
+        Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+
+        if(checkprefix("Set-Cookie:", argptr))
+          /* HTTP Header format line */
+          Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
+
+        else
+          /* Netscape format line */
+          Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
+
+        Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+        free(argptr);
+      }
+    }
+
+    break;
+#endif /* !CURL_DISABLE_COOKIES */
+
+  case CURLOPT_HTTPGET:
+    /*
+     * Set to force us do HTTP GET
+     */
+    if(va_arg(param, long)) {
+      data->set.httpreq = HTTPREQ_GET;
+      data->set.upload = FALSE; /* switch off upload */
+      data->set.opt_no_body = FALSE; /* this is implied */
+    }
+    break;
+
+  case CURLOPT_HTTP_VERSION:
+    /*
+     * This sets a requested HTTP version to be used. The value is one of
+     * the listed enums in curl/curl.h.
+     */
+    arg = va_arg(param, long);
+    if(arg < CURL_HTTP_VERSION_NONE)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+#ifndef USE_NGHTTP2
+    if(arg >= CURL_HTTP_VERSION_2)
+      return CURLE_UNSUPPORTED_PROTOCOL;
+#else
+    if(arg > CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE)
+      return CURLE_UNSUPPORTED_PROTOCOL;
+#endif
+    data->set.httpversion = arg;
+    break;
+
+  case CURLOPT_EXPECT_100_TIMEOUT_MS:
+    /*
+     * Time to wait for a response to a HTTP request containing an
+     * Expect: 100-continue header before sending the data anyway.
+     */
+    arg = va_arg(param, long);
+    if(arg < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.expect_100_timeout = arg;
+    break;
+
+#endif   /* CURL_DISABLE_HTTP */
+
+  case CURLOPT_HTTPAUTH:
+    /*
+     * Set HTTP Authentication type BITMASK.
+     */
+  {
+    int bitcheck;
+    bool authbits;
+    unsigned long auth = va_arg(param, unsigned long);
+
+    if(auth == CURLAUTH_NONE) {
+      data->set.httpauth = auth;
+      break;
+    }
+
+    /* the DIGEST_IE bit is only used to set a special marker, for all the
+       rest we need to handle it as normal DIGEST */
+    data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
+
+    if(auth & CURLAUTH_DIGEST_IE) {
+      auth |= CURLAUTH_DIGEST; /* set standard digest bit */
+      auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
+    }
+
+    /* switch off bits we can't support */
+#ifndef USE_NTLM
+    auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
+    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#elif !defined(NTLM_WB_ENABLED)
+    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#endif
+#ifndef USE_SPNEGO
+    auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
+                                    GSS-API or SSPI */
+#endif
+
+    /* check if any auth bit lower than CURLAUTH_ONLY is still set */
+    bitcheck = 0;
+    authbits = FALSE;
+    while(bitcheck < 31) {
+      if(auth & (1UL << bitcheck++)) {
+        authbits = TRUE;
+        break;
+      }
+    }
+    if(!authbits)
+      return CURLE_NOT_BUILT_IN; /* no supported types left! */
+
+    data->set.httpauth = auth;
+  }
+  break;
+
+  case CURLOPT_CUSTOMREQUEST:
+    /*
+     * Set a custom string to use as request
+     */
+    result = Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST],
+                            va_arg(param, char *));
+
+    /* we don't set
+       data->set.httpreq = HTTPREQ_CUSTOM;
+       here, we continue as if we were using the already set type
+       and this just changes the actual request keyword */
+    break;
+
+#ifndef CURL_DISABLE_PROXY
+  case CURLOPT_HTTPPROXYTUNNEL:
+    /*
+     * Tunnel operations through the proxy instead of normal proxy use
+     */
+    data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
+      TRUE : FALSE;
+    break;
+
+  case CURLOPT_PROXYPORT:
+    /*
+     * Explicitly set HTTP proxy port number.
+     */
+    arg = va_arg(param, long);
+    if((arg < 0) || (arg > 65535))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.proxyport = arg;
+    break;
+
+  case CURLOPT_PROXYAUTH:
+    /*
+     * Set HTTP Authentication type BITMASK.
+     */
+  {
+    int bitcheck;
+    bool authbits;
+    unsigned long auth = va_arg(param, unsigned long);
+
+    if(auth == CURLAUTH_NONE) {
+      data->set.proxyauth = auth;
+      break;
+    }
+
+    /* the DIGEST_IE bit is only used to set a special marker, for all the
+       rest we need to handle it as normal DIGEST */
+    data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
+
+    if(auth & CURLAUTH_DIGEST_IE) {
+      auth |= CURLAUTH_DIGEST; /* set standard digest bit */
+      auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
+    }
+    /* switch off bits we can't support */
+#ifndef USE_NTLM
+    auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
+    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#elif !defined(NTLM_WB_ENABLED)
+    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
+#endif
+#ifndef USE_SPNEGO
+    auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
+                                    GSS-API or SSPI */
+#endif
+
+    /* check if any auth bit lower than CURLAUTH_ONLY is still set */
+    bitcheck = 0;
+    authbits = FALSE;
+    while(bitcheck < 31) {
+      if(auth & (1UL << bitcheck++)) {
+        authbits = TRUE;
+        break;
+      }
+    }
+    if(!authbits)
+      return CURLE_NOT_BUILT_IN; /* no supported types left! */
+
+    data->set.proxyauth = auth;
+  }
+  break;
+
+  case CURLOPT_PROXY:
+    /*
+     * Set proxy server:port to use as proxy.
+     *
+     * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
+     * we explicitly say that we don't want to use a proxy
+     * (even though there might be environment variables saying so).
+     *
+     * Setting it to NULL, means no proxy but allows the environment variables
+     * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
+     */
+    result = Curl_setstropt(&data->set.str[STRING_PROXY],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_PRE_PROXY:
+    /*
+     * Set proxy server:port to use as SOCKS proxy.
+     *
+     * If the proxy is set to "" or NULL we explicitly say that we don't want
+     * to use the socks proxy.
+     */
+    result = Curl_setstropt(&data->set.str[STRING_PRE_PROXY],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_PROXYTYPE:
+    /*
+     * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
+     */
+    arg = va_arg(param, long);
+    if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.proxytype = (curl_proxytype)arg;
+    break;
+
+  case CURLOPT_PROXY_TRANSFER_MODE:
+    /*
+     * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
+     */
+    switch(va_arg(param, long)) {
+    case 0:
+      data->set.proxy_transfer_mode = FALSE;
+      break;
+    case 1:
+      data->set.proxy_transfer_mode = TRUE;
+      break;
+    default:
+      /* reserve other values for future use */
+      result = CURLE_UNKNOWN_OPTION;
+      break;
+    }
+    break;
+#endif   /* CURL_DISABLE_PROXY */
+
+  case CURLOPT_SOCKS5_AUTH:
+    data->set.socks5auth = va_arg(param, unsigned long);
+    if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
+      result = CURLE_NOT_BUILT_IN;
+    break;
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+  case CURLOPT_SOCKS5_GSSAPI_NEC:
+    /*
+     * Set flag for NEC SOCK5 support
+     */
+    data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_SOCKS5_GSSAPI_SERVICE:
+  case CURLOPT_PROXY_SERVICE_NAME:
+    /*
+     * Set proxy authentication service name for Kerberos 5 and SPNEGO
+     */
+    result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
+                            va_arg(param, char *));
+    break;
+#endif
+
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) ||     \
+  defined(USE_SPNEGO)
+  case CURLOPT_SERVICE_NAME:
+    /*
+     * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SERVICE_NAME],
+                            va_arg(param, char *));
+    break;
+
+#endif
+
+  case CURLOPT_HEADERDATA:
+    /*
+     * Custom pointer to pass the header write callback function
+     */
+    data->set.writeheader = (void *)va_arg(param, void *);
+    break;
+  case CURLOPT_ERRORBUFFER:
+    /*
+     * Error buffer provided by the caller to get the human readable
+     * error string in.
+     */
+    data->set.errorbuffer = va_arg(param, char *);
+    break;
+  case CURLOPT_WRITEDATA:
+    /*
+     * FILE pointer to write to. Or possibly
+     * used as argument to the write callback.
+     */
+    data->set.out = va_arg(param, void *);
+    break;
+  case CURLOPT_FTPPORT:
+    /*
+     * Use FTP PORT, this also specifies which IP address to use
+     */
+    result = Curl_setstropt(&data->set.str[STRING_FTPPORT],
+                            va_arg(param, char *));
+    data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_FTP_USE_EPRT:
+    data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_FTP_USE_EPSV:
+    data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_FTP_USE_PRET:
+    data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_FTP_SSL_CCC:
+    arg = va_arg(param, long);
+    if((arg < CURLFTPSSL_CCC_NONE) || (arg > CURLFTPSSL_CCC_ACTIVE))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.ftp_ccc = (curl_ftpccc)arg;
+    break;
+
+  case CURLOPT_FTP_SKIP_PASV_IP:
+    /*
+     * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
+     * bypass of the IP address in PASV responses.
+     */
+    data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_READDATA:
+    /*
+     * FILE pointer to read the file to be uploaded from. Or possibly
+     * used as argument to the read callback.
+     */
+    data->set.in_set = va_arg(param, void *);
+    break;
+  case CURLOPT_INFILESIZE:
+    /*
+     * If known, this should inform curl about the file size of the
+     * to-be-uploaded file.
+     */
+    arg = va_arg(param, long);
+    if(arg < -1)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.filesize = arg;
+    break;
+  case CURLOPT_INFILESIZE_LARGE:
+    /*
+     * If known, this should inform curl about the file size of the
+     * to-be-uploaded file.
+     */
+    bigsize = va_arg(param, curl_off_t);
+    if(bigsize < -1)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.filesize = bigsize;
+    break;
+  case CURLOPT_LOW_SPEED_LIMIT:
+    /*
+     * The low speed limit that if transfers are below this for
+     * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
+     */
+    arg = va_arg(param, long);
+    if(arg < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.low_speed_limit = arg;
+    break;
+  case CURLOPT_MAX_SEND_SPEED_LARGE:
+    /*
+     * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
+     * bytes per second the transfer is throttled..
+     */
+    bigsize = va_arg(param, curl_off_t);
+    if(bigsize < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.max_send_speed = bigsize;
+    break;
+  case CURLOPT_MAX_RECV_SPEED_LARGE:
+    /*
+     * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
+     * second the transfer is throttled..
+     */
+    bigsize = va_arg(param, curl_off_t);
+    if(bigsize < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.max_recv_speed = bigsize;
+    break;
+  case CURLOPT_LOW_SPEED_TIME:
+    /*
+     * The low speed time that if transfers are below the set
+     * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
+     */
+    arg = va_arg(param, long);
+    if(arg < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.low_speed_time = arg;
+    break;
+  case CURLOPT_URL:
+    /*
+     * The URL to fetch.
+     */
+    if(data->change.url_alloc) {
+      /* the already set URL is allocated, free it first! */
+      Curl_safefree(data->change.url);
+      data->change.url_alloc = FALSE;
+    }
+    result = Curl_setstropt(&data->set.str[STRING_SET_URL],
+                            va_arg(param, char *));
+    data->change.url = data->set.str[STRING_SET_URL];
+    break;
+  case CURLOPT_PORT:
+    /*
+     * The port number to use when getting the URL
+     */
+    arg = va_arg(param, long);
+    if((arg < 0) || (arg > 65535))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.use_port = arg;
+    break;
+  case CURLOPT_TIMEOUT:
+    /*
+     * The maximum time you allow curl to use for a single transfer
+     * operation.
+     */
+    arg = va_arg(param, long);
+    if((arg >= 0) && (arg <= (INT_MAX/1000)))
+      data->set.timeout = arg * 1000;
+    else
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    break;
+
+  case CURLOPT_TIMEOUT_MS:
+    arg = va_arg(param, long);
+    if(arg < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.timeout = arg;
+    break;
+
+  case CURLOPT_CONNECTTIMEOUT:
+    /*
+     * The maximum time you allow curl to use to connect.
+     */
+    arg = va_arg(param, long);
+    if((arg >= 0) && (arg <= (INT_MAX/1000)))
+      data->set.connecttimeout = arg * 1000;
+    else
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    break;
+
+  case CURLOPT_CONNECTTIMEOUT_MS:
+    arg = va_arg(param, long);
+    if(arg < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.connecttimeout = arg;
+    break;
+
+  case CURLOPT_ACCEPTTIMEOUT_MS:
+    /*
+     * The maximum time you allow curl to wait for server connect
+     */
+    arg = va_arg(param, long);
+    if(arg < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.accepttimeout = arg;
+    break;
+
+  case CURLOPT_USERPWD:
+    /*
+     * user:password to use in the operation
+     */
+    result = setstropt_userpwd(va_arg(param, char *),
+                               &data->set.str[STRING_USERNAME],
+                               &data->set.str[STRING_PASSWORD]);
+    break;
+
+  case CURLOPT_USERNAME:
+    /*
+     * authentication user name to use in the operation
+     */
+    result = Curl_setstropt(&data->set.str[STRING_USERNAME],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_PASSWORD:
+    /*
+     * authentication password to use in the operation
+     */
+    result = Curl_setstropt(&data->set.str[STRING_PASSWORD],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_LOGIN_OPTIONS:
+    /*
+     * authentication options to use in the operation
+     */
+    result = Curl_setstropt(&data->set.str[STRING_OPTIONS],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_XOAUTH2_BEARER:
+    /*
+     * OAuth 2.0 bearer token to use in the operation
+     */
+    result = Curl_setstropt(&data->set.str[STRING_BEARER],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_POSTQUOTE:
+    /*
+     * List of RAW FTP commands to use after a transfer
+     */
+    data->set.postquote = va_arg(param, struct curl_slist *);
+    break;
+  case CURLOPT_PREQUOTE:
+    /*
+     * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
+     */
+    data->set.prequote = va_arg(param, struct curl_slist *);
+    break;
+  case CURLOPT_QUOTE:
+    /*
+     * List of RAW FTP commands to use before a transfer
+     */
+    data->set.quote = va_arg(param, struct curl_slist *);
+    break;
+  case CURLOPT_RESOLVE:
+    /*
+     * List of NAME:[address] names to populate the DNS cache with
+     * Prefix the NAME with dash (-) to _remove_ the name from the cache.
+     *
+     * Names added with this API will remain in the cache until explicitly
+     * removed or the handle is cleaned up.
+     *
+     * This API can remove any name from the DNS cache, but only entries
+     * that aren't actually in use right now will be pruned immediately.
+     */
+    data->set.resolve = va_arg(param, struct curl_slist *);
+    data->change.resolve = data->set.resolve;
+    break;
+  case CURLOPT_PROGRESSFUNCTION:
+    /*
+     * Progress callback function
+     */
+    data->set.fprogress = va_arg(param, curl_progress_callback);
+    if(data->set.fprogress)
+      data->progress.callback = TRUE; /* no longer internal */
+    else
+      data->progress.callback = FALSE; /* NULL enforces internal */
+    break;
+
+  case CURLOPT_XFERINFOFUNCTION:
+    /*
+     * Transfer info callback function
+     */
+    data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
+    if(data->set.fxferinfo)
+      data->progress.callback = TRUE; /* no longer internal */
+    else
+      data->progress.callback = FALSE; /* NULL enforces internal */
+
+    break;
+
+  case CURLOPT_PROGRESSDATA:
+    /*
+     * Custom client data to pass to the progress callback
+     */
+    data->set.progress_client = va_arg(param, void *);
+    break;
+
+#ifndef CURL_DISABLE_PROXY
+  case CURLOPT_PROXYUSERPWD:
+    /*
+     * user:password needed to use the proxy
+     */
+    result = setstropt_userpwd(va_arg(param, char *),
+                               &data->set.str[STRING_PROXYUSERNAME],
+                               &data->set.str[STRING_PROXYPASSWORD]);
+    break;
+  case CURLOPT_PROXYUSERNAME:
+    /*
+     * authentication user name to use in the operation
+     */
+    result = Curl_setstropt(&data->set.str[STRING_PROXYUSERNAME],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_PROXYPASSWORD:
+    /*
+     * authentication password to use in the operation
+     */
+    result = Curl_setstropt(&data->set.str[STRING_PROXYPASSWORD],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_NOPROXY:
+    /*
+     * proxy exception list
+     */
+    result = Curl_setstropt(&data->set.str[STRING_NOPROXY],
+                            va_arg(param, char *));
+    break;
+#endif
+
+  case CURLOPT_RANGE:
+    /*
+     * What range of the file you want to transfer
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SET_RANGE],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_RESUME_FROM:
+    /*
+     * Resume transfer at the given file position
+     */
+    arg = va_arg(param, long);
+    if(arg < -1)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.set_resume_from = arg;
+    break;
+  case CURLOPT_RESUME_FROM_LARGE:
+    /*
+     * Resume transfer at the given file position
+     */
+    bigsize = va_arg(param, curl_off_t);
+    if(bigsize < -1)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.set_resume_from = bigsize;
+    break;
+  case CURLOPT_DEBUGFUNCTION:
+    /*
+     * stderr write callback.
+     */
+    data->set.fdebug = va_arg(param, curl_debug_callback);
+    /*
+     * if the callback provided is NULL, it'll use the default callback
+     */
+    break;
+  case CURLOPT_DEBUGDATA:
+    /*
+     * Set to a void * that should receive all error writes. This
+     * defaults to CURLOPT_STDERR for normal operations.
+     */
+    data->set.debugdata = va_arg(param, void *);
+    break;
+  case CURLOPT_STDERR:
+    /*
+     * Set to a FILE * that should receive all error writes. This
+     * defaults to stderr for normal operations.
+     */
+    data->set.err = va_arg(param, FILE *);
+    if(!data->set.err)
+      data->set.err = stderr;
+    break;
+  case CURLOPT_HEADERFUNCTION:
+    /*
+     * Set header write callback
+     */
+    data->set.fwrite_header = va_arg(param, curl_write_callback);
+    break;
+  case CURLOPT_WRITEFUNCTION:
+    /*
+     * Set data write callback
+     */
+    data->set.fwrite_func = va_arg(param, curl_write_callback);
+    if(!data->set.fwrite_func) {
+      data->set.is_fwrite_set = 0;
+      /* When set to NULL, reset to our internal default function */
+      data->set.fwrite_func = (curl_write_callback)fwrite;
+    }
+    else
+      data->set.is_fwrite_set = 1;
+    break;
+  case CURLOPT_READFUNCTION:
+    /*
+     * Read data callback
+     */
+    data->set.fread_func_set = va_arg(param, curl_read_callback);
+    if(!data->set.fread_func_set) {
+      data->set.is_fread_set = 0;
+      /* When set to NULL, reset to our internal default function */
+      data->set.fread_func_set = (curl_read_callback)fread;
+    }
+    else
+      data->set.is_fread_set = 1;
+    break;
+  case CURLOPT_SEEKFUNCTION:
+    /*
+     * Seek callback. Might be NULL.
+     */
+    data->set.seek_func = va_arg(param, curl_seek_callback);
+    break;
+  case CURLOPT_SEEKDATA:
+    /*
+     * Seek control callback. Might be NULL.
+     */
+    data->set.seek_client = va_arg(param, void *);
+    break;
+  case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
+    /*
+     * "Convert from network encoding" callback
+     */
+    data->set.convfromnetwork = va_arg(param, curl_conv_callback);
+    break;
+  case CURLOPT_CONV_TO_NETWORK_FUNCTION:
+    /*
+     * "Convert to network encoding" callback
+     */
+    data->set.convtonetwork = va_arg(param, curl_conv_callback);
+    break;
+  case CURLOPT_CONV_FROM_UTF8_FUNCTION:
+    /*
+     * "Convert from UTF-8 encoding" callback
+     */
+    data->set.convfromutf8 = va_arg(param, curl_conv_callback);
+    break;
+  case CURLOPT_IOCTLFUNCTION:
+    /*
+     * I/O control callback. Might be NULL.
+     */
+    data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
+    break;
+  case CURLOPT_IOCTLDATA:
+    /*
+     * I/O control data pointer. Might be NULL.
+     */
+    data->set.ioctl_client = va_arg(param, void *);
+    break;
+  case CURLOPT_SSLCERT:
+    /*
+     * String that holds file name of the SSL certificate to use
+     */
+    result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLCERT:
+    /*
+     * String that holds file name of the SSL certificate to use for proxy
+     */
+    result = Curl_setstropt(&data->set.str[STRING_CERT_PROXY],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_SSLCERTTYPE:
+    /*
+     * String that holds file type of the SSL certificate to use
+     */
+    result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLCERTTYPE:
+    /*
+     * String that holds file type of the SSL certificate to use for proxy
+     */
+    result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_SSLKEY:
+    /*
+     * String that holds file name of the SSL key to use
+     */
+    result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLKEY:
+    /*
+     * String that holds file name of the SSL key to use for proxy
+     */
+    result = Curl_setstropt(&data->set.str[STRING_KEY_PROXY],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_SSLKEYTYPE:
+    /*
+     * String that holds file type of the SSL key to use
+     */
+    result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLKEYTYPE:
+    /*
+     * String that holds file type of the SSL key to use for proxy
+     */
+    result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_KEYPASSWD:
+    /*
+     * String that holds the SSL or SSH private key password.
+     */
+    result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_KEYPASSWD:
+    /*
+     * String that holds the SSL private key password for proxy.
+     */
+    result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_SSLENGINE:
+    /*
+     * String that holds the SSL crypto engine.
+     */
+    argptr = va_arg(param, char *);
+    if(argptr && argptr[0])
+      result = Curl_ssl_set_engine(data, argptr);
+    break;
+
+  case CURLOPT_SSLENGINE_DEFAULT:
+    /*
+     * flag to set engine as default.
+     */
+    result = Curl_ssl_set_engine_default(data);
+    break;
+  case CURLOPT_CRLF:
+    /*
+     * Kludgy option to enable CRLF conversions. Subject for removal.
+     */
+    data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_INTERFACE:
+    /*
+     * Set what interface or address/hostname to bind the socket to when
+     * performing an operation and thus what from-IP your connection will use.
+     */
+    result = Curl_setstropt(&data->set.str[STRING_DEVICE],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_LOCALPORT:
+    /*
+     * Set what local port to bind the socket to when performing an operation.
+     */
+    arg = va_arg(param, long);
+    if((arg < 0) || (arg > 65535))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.localport = curlx_sltous(arg);
+    break;
+  case CURLOPT_LOCALPORTRANGE:
+    /*
+     * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
+     */
+    arg = va_arg(param, long);
+    if((arg < 0) || (arg > 65535))
+      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
+     */
+    arg = va_arg(param, long);
+    if(arg < CURLGSSAPI_DELEGATION_NONE)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.gssapi_delegation = arg;
+    break;
+  case CURLOPT_SSL_VERIFYPEER:
+    /*
+     * Enable peer SSL verifying.
+     */
+    data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
+      TRUE : FALSE;
+
+    /* Update the current connection ssl_config. */
+    if(data->easy_conn) {
+      data->easy_conn->ssl_config.verifypeer =
+        data->set.ssl.primary.verifypeer;
+    }
+    break;
+  case CURLOPT_PROXY_SSL_VERIFYPEER:
+    /*
+     * Enable peer SSL verifying for proxy.
+     */
+    data->set.proxy_ssl.primary.verifypeer =
+      (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 =
+        data->set.proxy_ssl.primary.verifypeer;
+    }
+    break;
+  case CURLOPT_SSL_VERIFYHOST:
+    /*
+     * Enable verification of the host name in the peer certificate
+     */
+    arg = va_arg(param, long);
+
+    /* Obviously people are not reading documentation and too many thought
+       this argument took a boolean when it wasn't and misused it. We thus ban
+       1 as a sensible input and we warn about its use. Then we only have the
+       2 action internally stored as TRUE. */
+
+    if(1 == arg) {
+      failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    }
+
+    data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
+
+    /* Update the current connection ssl_config. */
+    if(data->easy_conn) {
+      data->easy_conn->ssl_config.verifyhost =
+        data->set.ssl.primary.verifyhost;
+    }
+    break;
+  case CURLOPT_PROXY_SSL_VERIFYHOST:
+    /*
+     * Enable verification of the host name in the peer certificate for proxy
+     */
+    arg = va_arg(param, long);
+
+    /* Obviously people are not reading documentation and too many thought
+       this argument took a boolean when it wasn't and misused it. We thus ban
+       1 as a sensible input and we warn about its use. Then we only have the
+       2 action internally stored as TRUE. */
+
+    if(1 == arg) {
+      failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    }
+
+    data->set.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 =
+        data->set.proxy_ssl.primary.verifyhost;
+    }
+    break;
+  case CURLOPT_SSL_VERIFYSTATUS:
+    /*
+     * Enable certificate status verifying.
+     */
+    if(!Curl_ssl_cert_status_request()) {
+      result = CURLE_NOT_BUILT_IN;
+      break;
+    }
+
+    data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
+      TRUE : FALSE;
+
+    /* Update the current connection ssl_config. */
+    if(data->easy_conn) {
+      data->easy_conn->ssl_config.verifystatus =
+        data->set.ssl.primary.verifystatus;
+    }
+    break;
+  case CURLOPT_SSL_CTX_FUNCTION:
+    /*
+     * Set a SSL_CTX callback
+     */
+#ifdef USE_SSL
+    if(Curl_ssl->have_ssl_ctx)
+      data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
+    else
+#endif
+      result = CURLE_NOT_BUILT_IN;
+    break;
+  case CURLOPT_SSL_CTX_DATA:
+    /*
+     * Set a SSL_CTX callback parameter pointer
+     */
+#ifdef USE_SSL
+    if(Curl_ssl->have_ssl_ctx)
+      data->set.ssl.fsslctxp = va_arg(param, void *);
+    else
+#endif
+      result = CURLE_NOT_BUILT_IN;
+    break;
+  case CURLOPT_SSL_FALSESTART:
+    /*
+     * Enable TLS false start.
+     */
+    if(!Curl_ssl_false_start()) {
+      result = CURLE_NOT_BUILT_IN;
+      break;
+    }
+
+    data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_CERTINFO:
+#ifdef USE_SSL
+    if(Curl_ssl->have_certinfo)
+      data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    else
+#endif
+      result = CURLE_NOT_BUILT_IN;
+        break;
+  case CURLOPT_PINNEDPUBLICKEY:
+    /*
+     * Set pinned public key for SSL connection.
+     * Specify file name of the public key in DER format.
+     */
+#ifdef USE_SSL
+    if(Curl_ssl->have_pinnedpubkey)
+      result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
+                              va_arg(param, char *));
+    else
+#endif
+      result = CURLE_NOT_BUILT_IN;
+    break;
+  case CURLOPT_PROXY_PINNEDPUBLICKEY:
+    /*
+     * Set pinned public key for SSL connection.
+     * Specify file name of the public key in DER format.
+     */
+#ifdef USE_SSL
+    if(Curl_ssl->have_pinnedpubkey)
+      result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
+                              va_arg(param, char *));
+    else
+#endif
+      result = CURLE_NOT_BUILT_IN;
+    break;
+  case CURLOPT_CAINFO:
+    /*
+     * Set CA info for SSL connection. Specify file name of the CA certificate
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_CAINFO:
+    /*
+     * Set CA info SSL connection for proxy. Specify file name of the
+     * CA certificate
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_CAPATH:
+    /*
+     * Set CA path info for SSL connection. Specify directory name of the CA
+     * certificates which have been prepared using openssl c_rehash utility.
+     */
+#ifdef USE_SSL
+    if(Curl_ssl->have_ca_path)
+      /* This does not work on windows. */
+      result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
+                              va_arg(param, char *));
+    else
+#endif
+      result = CURLE_NOT_BUILT_IN;
+    break;
+  case CURLOPT_PROXY_CAPATH:
+    /*
+     * Set CA path info for SSL connection proxy. Specify directory name of the
+     * CA certificates which have been prepared using openssl c_rehash utility.
+     */
+#ifdef USE_SSL
+    if(Curl_ssl->have_ca_path)
+      /* This does not work on windows. */
+      result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
+                              va_arg(param, char *));
+    else
+#endif
+      result = CURLE_NOT_BUILT_IN;
+    break;
+  case CURLOPT_CRLFILE:
+    /*
+     * Set CRL file info for SSL connection. Specify file name of the CRL
+     * to check certificates revocation
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_CRLFILE:
+    /*
+     * Set CRL file info for SSL connection for proxy. Specify file name of the
+     * CRL to check certificates revocation
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_ISSUERCERT:
+    /*
+     * Set Issuer certificate file
+     * to check certificates issuer
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_TELNETOPTIONS:
+    /*
+     * Set a linked list of telnet options
+     */
+    data->set.telnet_options = va_arg(param, struct curl_slist *);
+    break;
+
+  case CURLOPT_BUFFERSIZE:
+    /*
+     * The application kindly asks for a differently sized receive buffer.
+     * If it seems reasonable, we'll use it.
+     */
+    arg = va_arg(param, long);
+
+    if(arg > READBUFFER_MAX)
+      arg = READBUFFER_MAX;
+    else if(arg < 1)
+      arg = READBUFFER_SIZE;
+    else if(arg < READBUFFER_MIN)
+      arg = READBUFFER_MIN;
+
+    /* Resize if new size */
+    if(arg != data->set.buffer_size) {
+      char *newbuff = realloc(data->state.buffer, arg + 1);
+      if(!newbuff) {
+        DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
+        result = CURLE_OUT_OF_MEMORY;
+      }
+      else
+        data->state.buffer = newbuff;
+    }
+    data->set.buffer_size = arg;
+
+    break;
+
+  case CURLOPT_NOSIGNAL:
+    /*
+     * The application asks not to set any signal() or alarm() handlers,
+     * even when using a timeout.
+     */
+    data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_SHARE:
+  {
+    struct Curl_share *set;
+    set = va_arg(param, struct Curl_share *);
+
+    /* disconnect from old share, if any */
+    if(data->share) {
+      Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
+
+      if(data->dns.hostcachetype == HCACHE_SHARED) {
+        data->dns.hostcache = NULL;
+        data->dns.hostcachetype = HCACHE_NONE;
+      }
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+      if(data->share->cookies == data->cookies)
+        data->cookies = NULL;
+#endif
+
+      if(data->share->sslsession == data->state.session)
+        data->state.session = NULL;
+
+      data->share->dirty--;
+
+      Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
+      data->share = NULL;
+    }
+
+    /* use new share if it set */
+    data->share = set;
+    if(data->share) {
+
+      Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
+
+      data->share->dirty++;
+
+      if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) {
+        /* use shared host cache */
+        data->dns.hostcache = &data->share->hostcache;
+        data->dns.hostcachetype = HCACHE_SHARED;
+      }
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
+      if(data->share->cookies) {
+        /* use shared cookie list, first free own one if any */
+        Curl_cookie_cleanup(data->cookies);
+        /* enable cookies since we now use a share that uses cookies! */
+        data->cookies = data->share->cookies;
+      }
+#endif   /* CURL_DISABLE_HTTP */
+      if(data->share->sslsession) {
+        data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
+        data->state.session = data->share->sslsession;
+      }
+      Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
+
+    }
+    /* check for host cache not needed,
+     * it will be done by curl_easy_perform */
+  }
+  break;
+
+  case CURLOPT_PRIVATE:
+    /*
+     * Set private data pointer.
+     */
+    data->set.private_data = va_arg(param, void *);
+    break;
+
+  case CURLOPT_MAXFILESIZE:
+    /*
+     * Set the maximum size of a file to download.
+     */
+    arg = va_arg(param, long);
+    if(arg < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.max_filesize = arg;
+    break;
+
+#ifdef USE_SSL
+  case CURLOPT_USE_SSL:
+    /*
+     * Make transfers attempt to use SSL/TLS.
+     */
+    arg = va_arg(param, long);
+    if((arg < CURLUSESSL_NONE) || (arg > CURLUSESSL_ALL))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.use_ssl = (curl_usessl)arg;
+    break;
+
+  case CURLOPT_SSL_OPTIONS:
+    arg = va_arg(param, long);
+    data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+    data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+    break;
+
+  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.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;
+
+  case CURLOPT_IPRESOLVE:
+    arg = va_arg(param, long);
+    if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.ipver = arg;
+    break;
+
+  case CURLOPT_MAXFILESIZE_LARGE:
+    /*
+     * Set the maximum size of a file to download.
+     */
+    bigsize = va_arg(param, curl_off_t);
+    if(bigsize < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.max_filesize = bigsize;
+    break;
+
+  case CURLOPT_TCP_NODELAY:
+    /*
+     * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
+     * algorithm
+     */
+    data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_FTP_ACCOUNT:
+    result = 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;
+
+  case CURLOPT_CONNECT_ONLY:
+    /*
+     * No data transfer, set up connection and let application use the socket
+     */
+    data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_FTP_ALTERNATIVE_TO_USER:
+    result = 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()
+     */
+    data->set.fsockopt = va_arg(param, curl_sockopt_callback);
+    break;
+
+  case CURLOPT_SOCKOPTDATA:
+    /*
+     * socket callback data pointer. Might be NULL.
+     */
+    data->set.sockopt_client = va_arg(param, void *);
+    break;
+
+  case CURLOPT_OPENSOCKETFUNCTION:
+    /*
+     * open/create socket callback function: called instead of socket(),
+     * before connect()
+     */
+    data->set.fopensocket = va_arg(param, curl_opensocket_callback);
+    break;
+
+  case CURLOPT_OPENSOCKETDATA:
+    /*
+     * socket callback data pointer. Might be NULL.
+     */
+    data->set.opensocket_client = va_arg(param, void *);
+    break;
+
+  case CURLOPT_CLOSESOCKETFUNCTION:
+    /*
+     * close socket callback function: called instead of close()
+     * when shutting down a connection
+     */
+    data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
+    break;
+
+  case CURLOPT_CLOSESOCKETDATA:
+    /*
+     * socket callback data pointer. Might be NULL.
+     */
+    data->set.closesocket_client = va_arg(param, void *);
+    break;
+
+  case CURLOPT_SSL_SESSIONID_CACHE:
+    data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
+      TRUE : FALSE;
+    data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
+    break;
+
+#if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
+    /* we only include SSH options if explicitly built to support SSH */
+  case CURLOPT_SSH_AUTH_TYPES:
+    data->set.ssh_auth_types = va_arg(param, long);
+    break;
+
+  case CURLOPT_SSH_PUBLIC_KEYFILE:
+    /*
+     * Use this file instead of the $HOME/.ssh/id_dsa.pub file
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_SSH_PRIVATE_KEYFILE:
+    /*
+     * Use this file instead of the $HOME/.ssh/id_dsa file
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
+    /*
+     * Option to allow for the MD5 of the host public key to be checked
+     * for validation purposes.
+     */
+    result = 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.
+     */
+    result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_SSH_KEYFUNCTION:
+    /* setting to NULL is fine since the ssh.c functions themselves will
+       then rever to use the internal default */
+    data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
+    break;
+
+  case CURLOPT_SSH_KEYDATA:
+    /*
+     * Custom client data to pass to the SSH keyfunc callback
+     */
+    data->set.ssh_keyfunc_userp = va_arg(param, void *);
+    break;
+#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
+#endif /* USE_LIBSSH2 */
+
+  case CURLOPT_HTTP_TRANSFER_DECODING:
+    /*
+     * disable libcurl transfer encoding is used
+     */
+    data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_HTTP_CONTENT_DECODING:
+    /*
+     * raw data passed to the application when content encoding is used
+     */
+    data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_NEW_FILE_PERMS:
+    /*
+     * Uses these permissions instead of 0644
+     */
+    arg = va_arg(param, long);
+    if((arg < 0) || (arg > 0777))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.new_file_perms = arg;
+    break;
+
+  case CURLOPT_NEW_DIRECTORY_PERMS:
+    /*
+     * Uses these permissions instead of 0755
+     */
+    arg = va_arg(param, long);
+    if((arg < 0) || (arg > 0777))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.new_directory_perms = arg;
+    break;
+
+  case CURLOPT_ADDRESS_SCOPE:
+    /*
+     * We always get longs when passed plain numericals, but for this value we
+     * know that an unsigned int will always hold the value so we blindly
+     * typecast to this type
+     */
+    arg = va_arg(param, long);
+    if((arg < 0) || (arg > 0xf))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.scope_id = curlx_sltoui(arg);
+    break;
+
+  case CURLOPT_PROTOCOLS:
+    /* set the bitmask for the protocols that are allowed to be used for the
+       transfer, which thus helps the app which takes URLs from users or other
+       external inputs and want to restrict what protocol(s) to deal
+       with. Defaults to CURLPROTO_ALL. */
+    data->set.allowed_protocols = va_arg(param, long);
+    break;
+
+  case CURLOPT_REDIR_PROTOCOLS:
+    /* set the bitmask for the protocols that libcurl is allowed to follow to,
+       as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
+       to be set in both bitmasks to be allowed to get redirected to. Defaults
+       to all protocols except FILE and SCP. */
+    data->set.redir_protocols = va_arg(param, long);
+    break;
+
+  case CURLOPT_DEFAULT_PROTOCOL:
+    /* Set the protocol to use when the URL doesn't include any protocol */
+    result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_MAIL_FROM:
+    /* Set the SMTP mail originator */
+    result = Curl_setstropt(&data->set.str[STRING_MAIL_FROM],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_MAIL_AUTH:
+    /* Set the SMTP auth originator */
+    result = Curl_setstropt(&data->set.str[STRING_MAIL_AUTH],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_MAIL_RCPT:
+    /* Set the list of mail recipients */
+    data->set.mail_rcpt = va_arg(param, struct curl_slist *);
+    break;
+
+  case CURLOPT_SASL_IR:
+    /* Enable/disable SASL initial response */
+    data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+  case CURLOPT_RTSP_REQUEST:
+  {
+    /*
+     * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
+     * Would this be better if the RTSPREQ_* were just moved into here?
+     */
+    long curl_rtspreq = va_arg(param, long);
+    Curl_RtspReq rtspreq = RTSPREQ_NONE;
+    switch(curl_rtspreq) {
+    case CURL_RTSPREQ_OPTIONS:
+      rtspreq = RTSPREQ_OPTIONS;
+      break;
+
+    case CURL_RTSPREQ_DESCRIBE:
+      rtspreq = RTSPREQ_DESCRIBE;
+      break;
+
+    case CURL_RTSPREQ_ANNOUNCE:
+      rtspreq = RTSPREQ_ANNOUNCE;
+      break;
+
+    case CURL_RTSPREQ_SETUP:
+      rtspreq = RTSPREQ_SETUP;
+      break;
+
+    case CURL_RTSPREQ_PLAY:
+      rtspreq = RTSPREQ_PLAY;
+      break;
+
+    case CURL_RTSPREQ_PAUSE:
+      rtspreq = RTSPREQ_PAUSE;
+      break;
+
+    case CURL_RTSPREQ_TEARDOWN:
+      rtspreq = RTSPREQ_TEARDOWN;
+      break;
+
+    case CURL_RTSPREQ_GET_PARAMETER:
+      rtspreq = RTSPREQ_GET_PARAMETER;
+      break;
+
+    case CURL_RTSPREQ_SET_PARAMETER:
+      rtspreq = RTSPREQ_SET_PARAMETER;
+      break;
+
+    case CURL_RTSPREQ_RECORD:
+      rtspreq = RTSPREQ_RECORD;
+      break;
+
+    case CURL_RTSPREQ_RECEIVE:
+      rtspreq = RTSPREQ_RECEIVE;
+      break;
+    default:
+      rtspreq = RTSPREQ_NONE;
+    }
+
+    data->set.rtspreq = rtspreq;
+    break;
+  }
+
+
+  case CURLOPT_RTSP_SESSION_ID:
+    /*
+     * Set the RTSP Session ID manually. Useful if the application is
+     * resuming a previously established RTSP session
+     */
+    result = Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_RTSP_STREAM_URI:
+    /*
+     * Set the Stream URI for the RTSP request. Unless the request is
+     * for generic server options, the application will need to set this.
+     */
+    result = Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_RTSP_TRANSPORT:
+    /*
+     * The content of the Transport: header for the RTSP request
+     */
+    result = Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
+                            va_arg(param, char *));
+    break;
+
+  case CURLOPT_RTSP_CLIENT_CSEQ:
+    /*
+     * Set the CSEQ number to issue for the next RTSP request. Useful if the
+     * application is resuming a previously broken connection. The CSEQ
+     * will increment from this new number henceforth.
+     */
+    data->state.rtsp_next_client_CSeq = va_arg(param, long);
+    break;
+
+  case CURLOPT_RTSP_SERVER_CSEQ:
+    /* Same as the above, but for server-initiated requests */
+    data->state.rtsp_next_client_CSeq = va_arg(param, long);
+    break;
+
+  case CURLOPT_INTERLEAVEDATA:
+    data->set.rtp_out = va_arg(param, void *);
+    break;
+  case CURLOPT_INTERLEAVEFUNCTION:
+    /* Set the user defined RTP write function */
+    data->set.fwrite_rtp = va_arg(param, curl_write_callback);
+    break;
+
+  case CURLOPT_WILDCARDMATCH:
+    data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_CHUNK_BGN_FUNCTION:
+    data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
+    break;
+  case CURLOPT_CHUNK_END_FUNCTION:
+    data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
+    break;
+  case CURLOPT_FNMATCH_FUNCTION:
+    data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
+    break;
+  case CURLOPT_CHUNK_DATA:
+    data->wildcard.customptr = va_arg(param, void *);
+    break;
+  case CURLOPT_FNMATCH_DATA:
+    data->set.fnmatch_data = va_arg(param, void *);
+    break;
+#ifdef USE_TLS_SRP
+  case CURLOPT_TLSAUTH_USERNAME:
+    result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
+                            va_arg(param, char *));
+    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
+      data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+    break;
+  case CURLOPT_PROXY_TLSAUTH_USERNAME:
+    result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
+                            va_arg(param, char *));
+    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+       !data->set.proxy_ssl.authtype)
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+    break;
+  case CURLOPT_TLSAUTH_PASSWORD:
+    result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
+                            va_arg(param, char *));
+    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
+      data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+    break;
+  case CURLOPT_PROXY_TLSAUTH_PASSWORD:
+    result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
+                            va_arg(param, char *));
+    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+       !data->set.proxy_ssl.authtype)
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+    break;
+  case CURLOPT_TLSAUTH_TYPE:
+    argptr = va_arg(param, char *);
+    if(!argptr ||
+       strncasecompare(argptr, "SRP", strlen("SRP")))
+      data->set.ssl.authtype = CURL_TLSAUTH_SRP;
+    else
+      data->set.ssl.authtype = CURL_TLSAUTH_NONE;
+    break;
+  case CURLOPT_PROXY_TLSAUTH_TYPE:
+    argptr = va_arg(param, char *);
+    if(!argptr ||
+       strncasecompare(argptr, "SRP", strlen("SRP")))
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
+    else
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
+    break;
+#endif
+  case CURLOPT_DNS_SERVERS:
+    result = Curl_set_dns_servers(data, va_arg(param, char *));
+    break;
+  case CURLOPT_DNS_INTERFACE:
+    result = Curl_set_dns_interface(data, va_arg(param, char *));
+    break;
+  case CURLOPT_DNS_LOCAL_IP4:
+    result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
+    break;
+  case CURLOPT_DNS_LOCAL_IP6:
+    result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
+    break;
+
+  case CURLOPT_TCP_KEEPALIVE:
+    data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_TCP_KEEPIDLE:
+    arg = va_arg(param, long);
+    if(arg < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.tcp_keepidle = arg;
+    break;
+  case CURLOPT_TCP_KEEPINTVL:
+    arg = va_arg(param, long);
+    if(arg < 0)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.tcp_keepintvl = arg;
+    break;
+  case CURLOPT_TCP_FASTOPEN:
+#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \
+   defined(TCP_FASTOPEN_CONNECT)
+    data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
+#else
+    result = CURLE_NOT_BUILT_IN;
+#endif
+    break;
+  case CURLOPT_SSL_ENABLE_NPN:
+    data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_SSL_ENABLE_ALPN:
+    data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+
+#ifdef USE_UNIX_SOCKETS
+  case CURLOPT_UNIX_SOCKET_PATH:
+    data->set.abstract_unix_socket = FALSE;
+    result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
+                            va_arg(param, char *));
+    break;
+  case CURLOPT_ABSTRACT_UNIX_SOCKET:
+    data->set.abstract_unix_socket = TRUE;
+    result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
+                            va_arg(param, char *));
+    break;
+#endif
+
+  case CURLOPT_PATH_AS_IS:
+    data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_PIPEWAIT:
+    data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
+  case CURLOPT_STREAM_WEIGHT:
+#ifndef USE_NGHTTP2
+    return CURLE_NOT_BUILT_IN;
+#else
+    arg = va_arg(param, long);
+    if((arg >= 1) && (arg <= 256))
+      data->set.stream_weight = (int)arg;
+    break;
+#endif
+  case CURLOPT_STREAM_DEPENDS:
+  case CURLOPT_STREAM_DEPENDS_E:
+  {
+#ifndef USE_NGHTTP2
+    return CURLE_NOT_BUILT_IN;
+#else
+    struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
+    if(!dep || GOOD_EASY_HANDLE(dep)) {
+      if(data->set.stream_depends_on) {
+        Curl_http2_remove_child(data->set.stream_depends_on, data);
+      }
+      Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
+    }
+    break;
+#endif
+  }
+  case CURLOPT_CONNECT_TO:
+    data->set.connect_to = va_arg(param, struct curl_slist *);
+    break;
+  case CURLOPT_SUPPRESS_CONNECT_HEADERS:
+    data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
+    break;
+  case CURLOPT_SSH_COMPRESSION:
+    data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
+    break;
+  default:
+    /* unknown tag and its companion, just ignore: */
+    result = CURLE_UNKNOWN_OPTION;
+    break;
+  }
+
+  return result;
+}
+
+/*
+ * curl_easy_setopt() is the external interface for setting options on an
+ * easy handle.
+ */
+
+#undef curl_easy_setopt
+CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
+{
+  va_list arg;
+  CURLcode result;
+
+  if(!data)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  va_start(arg, tag);
+
+  result = Curl_vsetopt(data, tag, arg);
+
+  va_end(arg);
+  return result;
+}
diff --git a/lib/vauth/digest.h b/lib/setopt.h
similarity index 62%
copy from lib/vauth/digest.h
copy to lib/setopt.h
index 5722dce..c658e04 100644
--- a/lib/vauth/digest.h
+++ b/lib/setopt.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_DIGEST_H
-#define HEADER_CURL_DIGEST_H
+#ifndef HEADER_CURL_SETOPT_H
+#define HEADER_CURL_SETOPT_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, 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,8 @@
  *
  ***************************************************************************/
 
-#include <curl/curl.h>
+CURLcode Curl_setstropt(char **charp, const char *s);
+CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
+                      va_list arg);
 
-#if !defined(CURL_DISABLE_CRYPTO_AUTH)
-
-#define DIGEST_MAX_VALUE_LENGTH           256
-#define DIGEST_MAX_CONTENT_LENGTH         1024
-
-enum {
-  CURLDIGESTALGO_MD5,
-  CURLDIGESTALGO_MD5SESS
-};
-
-/* This is used to extract the realm from a challenge message */
-bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
-                               const char **endptr);
-
-#endif
-
-#endif /* HEADER_CURL_DIGEST_H */
+#endif /* HEADER_CURL_SETOPT_H */
diff --git a/lib/sha256.c b/lib/sha256.c
new file mode 100644
index 0000000..cd81c02
--- /dev/null
+++ b/lib/sha256.c
@@ -0,0 +1,262 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Florin Petriuc, <petriuc.florin at gmail.com>
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at 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_CRYPTO_AUTH
+
+#include "warnless.h"
+#include "curl_sha256.h"
+
+#if defined(USE_OPENSSL)
+
+/* When OpenSSL is available we use the SHA256-function from OpenSSL */
+#include <openssl/sha.h>
+
+#else
+
+/* When no other crypto library is available we use this code segment */
+
+/* ===== start - public domain SHA256 implementation ===== */
+/* This is based on SHA256 implementation in LibTomCrypt that was released into
+ * public domain by Tom St Denis. */
+
+#define WPA_GET_BE32(a) ((((unsigned long)(a)[0]) << 24) | \
+                         (((unsigned long)(a)[1]) << 16) | \
+                         (((unsigned long)(a)[2]) <<  8) | \
+                          ((unsigned long)(a)[3]))
+#define WPA_PUT_BE32(a, val)                                        \
+do {                                                                \
+  (a)[0] = (unsigned char)((((unsigned long) (val)) >> 24) & 0xff); \
+  (a)[1] = (unsigned char)((((unsigned long) (val)) >> 16) & 0xff); \
+  (a)[2] = (unsigned char)((((unsigned long) (val)) >> 8) & 0xff);  \
+  (a)[3] = (unsigned char)(((unsigned long) (val)) & 0xff);         \
+} while(0)
+
+#ifdef HAVE_LONGLONG
+#define WPA_PUT_BE64(a, val)                                    \
+do {                                                            \
+  (a)[0] = (unsigned char)(((unsigned long long)(val)) >> 56);  \
+  (a)[1] = (unsigned char)(((unsigned long long)(val)) >> 48);  \
+  (a)[2] = (unsigned char)(((unsigned long long)(val)) >> 40);  \
+  (a)[3] = (unsigned char)(((unsigned long long)(val)) >> 32);  \
+  (a)[4] = (unsigned char)(((unsigned long long)(val)) >> 24);  \
+  (a)[5] = (unsigned char)(((unsigned long long)(val)) >> 16);  \
+  (a)[6] = (unsigned char)(((unsigned long long)(val)) >> 8);   \
+  (a)[7] = (unsigned char)(((unsigned long long)(val)) & 0xff); \
+} while(0)
+#else
+#define WPA_PUT_BE64(a, val)                                  \
+do {                                                          \
+  (a)[0] = (unsigned char)(((unsigned __int64)(val)) >> 56);  \
+  (a)[1] = (unsigned char)(((unsigned __int64)(val)) >> 48);  \
+  (a)[2] = (unsigned char)(((unsigned __int64)(val)) >> 40);  \
+  (a)[3] = (unsigned char)(((unsigned __int64)(val)) >> 32);  \
+  (a)[4] = (unsigned char)(((unsigned __int64)(val)) >> 24);  \
+  (a)[5] = (unsigned char)(((unsigned __int64)(val)) >> 16);  \
+  (a)[6] = (unsigned char)(((unsigned __int64)(val)) >> 8);   \
+  (a)[7] = (unsigned char)(((unsigned __int64)(val)) & 0xff); \
+} while(0)
+#endif
+
+typedef struct sha256_state {
+#ifdef HAVE_LONGLONG
+  unsigned long long length;
+#else
+  unsigned __int64 length;
+#endif
+  unsigned long state[8], curlen;
+  unsigned char buf[64];
+} SHA256_CTX;
+/* the K array */
+static const unsigned long K[64] = {
+  0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+  0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+  0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+  0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+  0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+  0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+  0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+  0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+  0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+  0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+  0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+  0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+  0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+/* Various logical functions */
+#define RORc(x, y) \
+(((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \
+   ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL)
+#define Ch(x,y,z)   (z ^ (x & (y ^ z)))
+#define Maj(x,y,z)  (((x | y) & z) | (x & y))
+#define S(x, n)     RORc((x), (n))
+#define R(x, n)     (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0(x)   (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1(x)   (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0(x)   (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1(x)   (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+#ifndef MIN
+#define MIN(x, y)   (((x) < (y)) ? (x) : (y))
+#endif
+/* compress 512-bits */
+static int sha256_compress(struct sha256_state *md,
+                           unsigned char *buf)
+{
+  unsigned long S[8], W[64], t0, t1;
+  unsigned long t;
+  int i;
+  /* copy state into S */
+  for(i = 0; i < 8; i++) {
+    S[i] = md->state[i];
+  }
+  /* copy the state into 512-bits into W[0..15] */
+  for(i = 0; i < 16; i++)
+    W[i] = WPA_GET_BE32(buf + (4 * i));
+  /* fill W[16..63] */
+  for(i = 16; i < 64; i++) {
+    W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
+      W[i - 16];
+  }
+  /* Compress */
+#define RND(a,b,c,d,e,f,g,h,i)                    \
+  t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+  t1 = Sigma0(a) + Maj(a, b, c);                  \
+  d += t0;                                        \
+  h = t0 + t1;
+  for(i = 0; i < 64; ++i) {
+    RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
+    t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
+    S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
+  }
+  /* feedback */
+  for(i = 0; i < 8; i++) {
+    md->state[i] = md->state[i] + S[i];
+  }
+  return 0;
+}
+/* Initialize the hash state */
+static void SHA256_Init(struct sha256_state *md)
+{
+  md->curlen = 0;
+  md->length = 0;
+  md->state[0] = 0x6A09E667UL;
+  md->state[1] = 0xBB67AE85UL;
+  md->state[2] = 0x3C6EF372UL;
+  md->state[3] = 0xA54FF53AUL;
+  md->state[4] = 0x510E527FUL;
+  md->state[5] = 0x9B05688CUL;
+  md->state[6] = 0x1F83D9ABUL;
+  md->state[7] = 0x5BE0CD19UL;
+}
+/**
+   Process a block of memory though the hash
+   @param md     The hash state
+   @param in     The data to hash
+   @param inlen  The length of the data (octets)
+   @return CRYPT_OK if successful
+*/
+static int SHA256_Update(struct sha256_state *md,
+                         const unsigned char *in,
+                         unsigned long inlen)
+{
+  unsigned long n;
+#define block_size 64
+  if(md->curlen > sizeof(md->buf))
+    return -1;
+  while(inlen > 0) {
+    if(md->curlen == 0 && inlen >= block_size) {
+      if(sha256_compress(md, (unsigned char *)in) < 0)
+        return -1;
+      md->length += block_size * 8;
+      in += block_size;
+      inlen -= block_size;
+    }
+    else {
+      n = MIN(inlen, (block_size - md->curlen));
+      memcpy(md->buf + md->curlen, in, n);
+      md->curlen += n;
+      in += n;
+      inlen -= n;
+      if(md->curlen == block_size) {
+        if(sha256_compress(md, md->buf) < 0)
+          return -1;
+        md->length += 8 * block_size;
+        md->curlen = 0;
+      }
+    }
+  }
+  return 0;
+}
+/**
+   Terminate the hash to get the digest
+   @param md  The hash state
+   @param out [out] The destination of the hash (32 bytes)
+   @return CRYPT_OK if successful
+*/
+static int SHA256_Final(unsigned char *out,
+                        struct sha256_state *md)
+{
+  int i;
+  if(md->curlen >= sizeof(md->buf))
+    return -1;
+  /* increase the length of the message */
+  md->length += md->curlen * 8;
+  /* append the '1' bit */
+  md->buf[md->curlen++] = (unsigned char)0x80;
+  /* if the length is currently above 56 bytes we append zeros
+   * then compress.  Then we can fall back to padding zeros and length
+   * encoding like normal.
+   */
+  if(md->curlen > 56) {
+    while(md->curlen < 64) {
+      md->buf[md->curlen++] = (unsigned char)0;
+    }
+    sha256_compress(md, md->buf);
+    md->curlen = 0;
+  }
+  /* pad upto 56 bytes of zeroes */
+  while(md->curlen < 56) {
+    md->buf[md->curlen++] = (unsigned char)0;
+  }
+  /* store length */
+  WPA_PUT_BE64(md->buf + 56, md->length);
+  sha256_compress(md, md->buf);
+  /* copy output */
+  for(i = 0; i < 8; i++)
+    WPA_PUT_BE32(out + (4 * i), md->state[i]);
+  return 0;
+}
+/* ===== end - public domain SHA256 implementation ===== */
+
+#endif
+
+void Curl_sha256it(unsigned char *outbuffer, /* 32 unsigned chars */
+                   const unsigned char *input)
+{
+  SHA256_CTX ctx;
+  SHA256_Init(&ctx);
+  SHA256_Update(&ctx, input, curlx_uztoui(strlen((char *)input)));
+  SHA256_Final(outbuffer, &ctx);
+}
+
+#endif /* CURL_DISABLE_CRYPTO_AUTH */
diff --git a/lib/share.c b/lib/share.c
index 5b3957f..870b191 100644
--- a/lib/share.c
+++ b/lib/share.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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,6 +102,8 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
       break;
 
     case CURL_LOCK_DATA_CONNECT:     /* not supported (yet) */
+      if(Curl_conncache_init(&share->conn_cache, 103))
+        res = CURLSHE_NOMEM;
       break;
 
     default:
@@ -186,6 +188,8 @@ curl_share_cleanup(struct Curl_share *share)
     return CURLSHE_IN_USE;
   }
 
+  Curl_conncache_close_all_connections(&share->conn_cache);
+  Curl_conncache_destroy(&share->conn_cache);
   Curl_hash_destroy(&share->hostcache);
 
 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
diff --git a/lib/share.h b/lib/share.h
index c039a16..4b13406 100644
--- a/lib/share.h
+++ b/lib/share.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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,6 +26,7 @@
 #include <curl/curl.h>
 #include "cookie.h"
 #include "urldata.h"
+#include "conncache.h"
 
 /* SalfordC says "A structure member may not be volatile". Hence:
  */
@@ -43,7 +44,7 @@ struct Curl_share {
   curl_lock_function lockfunc;
   curl_unlock_function unlockfunc;
   void *clientdata;
-
+  struct conncache conn_cache;
   struct curl_hash hostcache;
 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
   struct CookieInfo *cookies;
diff --git a/lib/smb.c b/lib/smb.c
index 13dfd51..6cb4083 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2014, Bill Nagel <wnagel at tycoint.com>, Exacq Technologies
- * Copyright (C) 2016-2017, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2016-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
@@ -146,19 +146,12 @@ static unsigned int smb_swap32(unsigned int x)
     ((x >> 24) & 0xff);
 }
 
-#ifdef HAVE_LONGLONG
-static unsigned long long smb_swap64(unsigned long long x)
+static curl_off_t smb_swap64(curl_off_t x)
 {
-  return ((unsigned long long) smb_swap32((unsigned int) x) << 32) |
+  return ((curl_off_t) smb_swap32((unsigned int) x) << 32) |
     smb_swap32((unsigned int) (x >> 32));
 }
-#else
-static unsigned __int64 smb_swap64(unsigned __int64 x)
-{
-  return ((unsigned __int64) smb_swap32((unsigned int) x) << 32) |
-    smb_swap32((unsigned int) (x >> 32));
-}
-#endif
+
 #else
 #  define smb_swap16(x) (x)
 #  define smb_swap32(x) (x)
@@ -648,7 +641,7 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
   if(smbc->state == SMB_CONNECTING) {
 #ifdef USE_SSL
     if((conn->handler->flags & PROTOPT_SSL)) {
-      bool ssl_done;
+      bool ssl_done = FALSE;
       result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &ssl_done);
       if(result && result != CURLE_AGAIN)
         return result;
@@ -719,17 +712,11 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
  * Convert a timestamp from the Windows world (100 nsec units from
  * 1 Jan 1601) to Posix time.
  */
-static void get_posix_time(long *_out, const void *_in)
+static void get_posix_time(long *out, curl_off_t timestamp)
 {
-#ifdef HAVE_LONGLONG
-  long long timestamp = *(long long *) _in;
-#else
-  unsigned __int64 timestamp = *(unsigned __int64 *) _in;
-#endif
-
-  timestamp -= 116444736000000000ULL;
+  timestamp -= 116444736000000000;
   timestamp /= 10000000;
-  *_out = (long) timestamp;
+  *out = (long) timestamp;
 }
 
 static CURLcode smb_request_state(struct connectdata *conn, bool *done)
@@ -798,7 +785,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
       conn->data->req.size = smb_swap64(smb_m->end_of_file);
       Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
       if(conn->data->set.get_filetime)
-        get_posix_time(&conn->data->info.filetime, &smb_m->last_change_time);
+        get_posix_time(&conn->data->info.filetime, smb_m->last_change_time);
       next_state = SMB_DOWNLOAD;
     }
     break;
diff --git a/lib/smb.h b/lib/smb.h
index 1a4f66e..c3ee7ae 100644
--- a/lib/smb.h
+++ b/lib/smb.h
@@ -8,6 +8,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2014, Bill Nagel <wnagel at tycoint.com>, Exacq Technologies
+ * Copyright (C) 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
@@ -165,11 +166,7 @@ struct smb_nt_create {
   unsigned int flags;
   unsigned int root_fid;
   unsigned int access;
-#ifdef HAVE_LONGLONG
-  unsigned long long allocation_size;
-#else
-  unsigned __int64 allocation_size;
-#endif
+  curl_off_t allocation_size;
   unsigned int ext_file_attributes;
   unsigned int share_access;
   unsigned int create_disposition;
@@ -187,25 +184,15 @@ struct smb_nt_create_response {
   unsigned char op_lock_level;
   unsigned short fid;
   unsigned int create_disposition;
-#ifdef HAVE_LONGLONG
-  unsigned long long create_time;
-  unsigned long long last_access_time;
-  unsigned long long last_write_time;
-  unsigned long long last_change_time;
-#else
-  unsigned __int64 create_time;
-  unsigned __int64 last_access_time;
-  unsigned __int64 last_write_time;
-  unsigned __int64 last_change_time;
-#endif
+
+  curl_off_t create_time;
+  curl_off_t last_access_time;
+  curl_off_t last_write_time;
+  curl_off_t last_change_time;
   unsigned int ext_file_attributes;
-#ifdef HAVE_LONGLONG
-  unsigned long long allocation_size;
-  unsigned long long end_of_file;
-#else
-  unsigned __int64 allocation_size;
-  unsigned __int64 end_of_file;
-#endif
+  curl_off_t allocation_size;
+  curl_off_t end_of_file;
+
 } PACK;
 
 struct smb_read {
diff --git a/lib/smtp.c b/lib/smtp.c
index de2dd33..d9f1a85 100644
--- a/lib/smtp.c
+++ b/lib/smtp.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
@@ -232,23 +232,30 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
  */
 static void smtp_get_message(char *buffer, char **outptr)
 {
-  size_t len = 0;
+  size_t len = strlen(buffer);
   char *message = NULL;
 
-  /* Find the start of the message */
-  for(message = buffer + 4; *message == ' ' || *message == '\t'; message++)
-    ;
-
-  /* Find the end of the message */
-  for(len = strlen(message); len--;)
-    if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
-       message[len] != '\t')
-      break;
-
-  /* Terminate the message */
-  if(++len) {
-    message[len] = '\0';
+  if(len > 4) {
+    /* Find the start of the message */
+    len -= 4;
+    for(message = buffer + 4; *message == ' ' || *message == '\t';
+        message++, len--)
+      ;
+
+    /* Find the end of the message */
+    for(; len--;)
+      if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
+         message[len] != '\t')
+        break;
+
+    /* Terminate the message */
+    if(++len) {
+      message[len] = '\0';
+    }
   }
+  else
+    /* junk input => zero length output */
+    message = &buffer[len];
 
   *outptr = message;
 }
@@ -1188,6 +1195,9 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
   if(!smtp || !pp->conn)
     return CURLE_OK;
 
+  /* Cleanup our per-request based variables */
+  Curl_safefree(smtp->custom);
+
   if(status) {
     connclose(conn, "SMTP done with bad status"); /* marked for closure */
     result = status;         /* use the already set error code */
@@ -1230,7 +1240,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
     }
     else {
       /* Successfully sent so adjust the response timeout relative to now */
-      pp->response = Curl_tvnow();
+      pp->response = Curl_now();
 
       free(eob);
     }
@@ -1246,9 +1256,6 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
     result = smtp_block_statemach(conn);
   }
 
-  /* Cleanup our per-request based variables */
-  Curl_safefree(smtp->custom);
-
   /* Clear the transfer mode for the next request */
   smtp->transfer = FTPTRANSFER_BODY;
 
diff --git a/lib/socks.c b/lib/socks.c
index e64cb98..ac4270e 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -57,7 +57,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
   ssize_t nread;
   ssize_t allread = 0;
   int result;
-  time_t timeleft;
+  timediff_t timeleft;
   *n = 0;
   for(;;) {
     timeleft = Curl_timeleft(conn->data, NULL, TRUE);
@@ -382,7 +382,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
   CURLcode code;
   curl_socket_t sock = conn->sock[sockindex];
   struct Curl_easy *data = conn->data;
-  time_t timeout;
+  timediff_t timeout;
   bool socks5_resolve_local =
     (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
   const size_t hostname_len = strlen(hostname);
diff --git a/lib/speedcheck.c b/lib/speedcheck.c
index fe669f1..3aeea91 100644
--- a/lib/speedcheck.c
+++ b/lib/speedcheck.c
@@ -46,7 +46,7 @@ CURLcode Curl_speedcheck(struct Curl_easy *data,
         data->state.keeps_speed = now;
       else {
         /* how long has it been under the limit */
-        time_t howlong = Curl_tvdiff(now, data->state.keeps_speed);
+        timediff_t howlong = Curl_timediff(now, data->state.keeps_speed);
 
         if(howlong >= data->set.low_speed_time * 1000) {
           /* too long */
diff --git a/lib/ssh-libssh.c b/lib/ssh-libssh.c
new file mode 100644
index 0000000..56775d7
--- /dev/null
+++ b/lib/ssh-libssh.c
@@ -0,0 +1,2733 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
+ *          Robert Kolcun, Andreas Schneider
+ *
+ * This software 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"
+
+#ifdef USE_LIBSSH
+
+#include <limits.h>
+
+#include <libssh/libssh.h>
+#include <libssh/sftp.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#undef in_addr_t
+#define in_addr_t unsigned long
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "progress.h"
+#include "transfer.h"
+#include "escape.h"
+#include "http.h"               /* for HTTP proxy tunnel stuff */
+#include "ssh.h"
+#include "url.h"
+#include "speedcheck.h"
+#include "getinfo.h"
+#include "strdup.h"
+#include "strcase.h"
+#include "vtls/vtls.h"
+#include "connect.h"
+#include "strerror.h"
+#include "inet_ntop.h"
+#include "parsedate.h"          /* for the week day and month names */
+#include "sockaddr.h"           /* required for Curl_sockaddr_storage */
+#include "strtoofft.h"
+#include "multiif.h"
+#include "select.h"
+#include "warnless.h"
+
+/* for permission and open flags */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+#include "curl_path.h"
+
+/* Local functions: */
+static CURLcode myssh_connect(struct connectdata *conn, bool *done);
+static CURLcode myssh_multi_statemach(struct connectdata *conn,
+                                      bool *done);
+static CURLcode myssh_do_it(struct connectdata *conn, bool *done);
+
+static CURLcode scp_done(struct connectdata *conn,
+                         CURLcode, bool premature);
+static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done);
+static CURLcode scp_disconnect(struct connectdata *conn,
+                               bool dead_connection);
+
+static CURLcode sftp_done(struct connectdata *conn,
+                          CURLcode, bool premature);
+static CURLcode sftp_doing(struct connectdata *conn,
+                           bool *dophase_done);
+static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
+static
+CURLcode sftp_perform(struct connectdata *conn,
+                      bool *connected,
+                      bool *dophase_done);
+
+static void sftp_quote(struct connectdata *conn);
+static void sftp_quote_stat(struct connectdata *conn);
+
+static int myssh_getsock(struct connectdata *conn, curl_socket_t *sock,
+                         int numsocks);
+
+static int myssh_perform_getsock(const struct connectdata *conn,
+                                 curl_socket_t *sock,
+                                 int numsocks);
+
+static CURLcode myssh_setup_connection(struct connectdata *conn);
+
+/*
+ * SCP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_scp = {
+  "SCP",                        /* scheme */
+  myssh_setup_connection,       /* setup_connection */
+  myssh_do_it,                  /* do_it */
+  scp_done,                     /* done */
+  ZERO_NULL,                    /* do_more */
+  myssh_connect,                /* connect_it */
+  myssh_multi_statemach,        /* connecting */
+  scp_doing,                    /* doing */
+  myssh_getsock,                /* proto_getsock */
+  myssh_getsock,                /* doing_getsock */
+  ZERO_NULL,                    /* domore_getsock */
+  myssh_perform_getsock,        /* perform_getsock */
+  scp_disconnect,               /* disconnect */
+  ZERO_NULL,                    /* readwrite */
+  ZERO_NULL,                    /* connection_check */
+  PORT_SSH,                     /* defport */
+  CURLPROTO_SCP,                /* protocol */
+  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY    /* flags */
+};
+
+/*
+ * SFTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_sftp = {
+  "SFTP",                               /* scheme */
+  myssh_setup_connection,               /* setup_connection */
+  myssh_do_it,                          /* do_it */
+  sftp_done,                            /* done */
+  ZERO_NULL,                            /* do_more */
+  myssh_connect,                        /* connect_it */
+  myssh_multi_statemach,                /* connecting */
+  sftp_doing,                           /* doing */
+  myssh_getsock,                        /* proto_getsock */
+  myssh_getsock,                        /* doing_getsock */
+  ZERO_NULL,                            /* domore_getsock */
+  myssh_perform_getsock,                /* perform_getsock */
+  sftp_disconnect,                      /* disconnect */
+  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* connection_check */
+  PORT_SSH,                             /* defport */
+  CURLPROTO_SFTP,                       /* protocol */
+  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
+  | PROTOPT_NOURLQUERY                  /* flags */
+};
+
+static CURLcode sftp_error_to_CURLE(int err)
+{
+  switch(err) {
+    case SSH_FX_OK:
+      return CURLE_OK;
+
+    case SSH_FX_NO_SUCH_FILE:
+    case SSH_FX_NO_SUCH_PATH:
+      return CURLE_REMOTE_FILE_NOT_FOUND;
+
+    case SSH_FX_PERMISSION_DENIED:
+    case SSH_FX_WRITE_PROTECT:
+      return CURLE_REMOTE_ACCESS_DENIED;
+
+    case SSH_FX_FILE_ALREADY_EXISTS:
+      return CURLE_REMOTE_FILE_EXISTS;
+
+    default:
+      break;
+  }
+
+  return CURLE_SSH;
+}
+
+/*
+ * SSH State machine related code
+ */
+/* This is the ONLY way to change SSH state! */
+static void state(struct connectdata *conn, sshstate nowstate)
+{
+  struct ssh_conn *sshc = &conn->proto.sshc;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+  /* for debug purposes */
+  static const char *const names[] = {
+    "SSH_STOP",
+    "SSH_INIT",
+    "SSH_S_STARTUP",
+    "SSH_HOSTKEY",
+    "SSH_AUTHLIST",
+    "SSH_AUTH_PKEY_INIT",
+    "SSH_AUTH_PKEY",
+    "SSH_AUTH_PASS_INIT",
+    "SSH_AUTH_PASS",
+    "SSH_AUTH_AGENT_INIT",
+    "SSH_AUTH_AGENT_LIST",
+    "SSH_AUTH_AGENT",
+    "SSH_AUTH_HOST_INIT",
+    "SSH_AUTH_HOST",
+    "SSH_AUTH_KEY_INIT",
+    "SSH_AUTH_KEY",
+    "SSH_AUTH_GSSAPI",
+    "SSH_AUTH_DONE",
+    "SSH_SFTP_INIT",
+    "SSH_SFTP_REALPATH",
+    "SSH_SFTP_QUOTE_INIT",
+    "SSH_SFTP_POSTQUOTE_INIT",
+    "SSH_SFTP_QUOTE",
+    "SSH_SFTP_NEXT_QUOTE",
+    "SSH_SFTP_QUOTE_STAT",
+    "SSH_SFTP_QUOTE_SETSTAT",
+    "SSH_SFTP_QUOTE_SYMLINK",
+    "SSH_SFTP_QUOTE_MKDIR",
+    "SSH_SFTP_QUOTE_RENAME",
+    "SSH_SFTP_QUOTE_RMDIR",
+    "SSH_SFTP_QUOTE_UNLINK",
+    "SSH_SFTP_QUOTE_STATVFS",
+    "SSH_SFTP_GETINFO",
+    "SSH_SFTP_FILETIME",
+    "SSH_SFTP_TRANS_INIT",
+    "SSH_SFTP_UPLOAD_INIT",
+    "SSH_SFTP_CREATE_DIRS_INIT",
+    "SSH_SFTP_CREATE_DIRS",
+    "SSH_SFTP_CREATE_DIRS_MKDIR",
+    "SSH_SFTP_READDIR_INIT",
+    "SSH_SFTP_READDIR",
+    "SSH_SFTP_READDIR_LINK",
+    "SSH_SFTP_READDIR_BOTTOM",
+    "SSH_SFTP_READDIR_DONE",
+    "SSH_SFTP_DOWNLOAD_INIT",
+    "SSH_SFTP_DOWNLOAD_STAT",
+    "SSH_SFTP_CLOSE",
+    "SSH_SFTP_SHUTDOWN",
+    "SSH_SCP_TRANS_INIT",
+    "SSH_SCP_UPLOAD_INIT",
+    "SSH_SCP_DOWNLOAD_INIT",
+    "SSH_SCP_DOWNLOAD",
+    "SSH_SCP_DONE",
+    "SSH_SCP_SEND_EOF",
+    "SSH_SCP_WAIT_EOF",
+    "SSH_SCP_WAIT_CLOSE",
+    "SSH_SCP_CHANNEL_FREE",
+    "SSH_SESSION_DISCONNECT",
+    "SSH_SESSION_FREE",
+    "QUIT"
+  };
+
+
+  if(sshc->state != nowstate) {
+    infof(conn->data, "SSH %p state change from %s to %s\n",
+          (void *) sshc, names[sshc->state], names[nowstate]);
+  }
+#endif
+
+  sshc->state = nowstate;
+}
+
+/* Multiple options:
+ * 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5
+ *    hash (90s style auth, not sure we should have it here)
+ * 2. data->set.ssh_keyfunc callback is set. Then we do trust on first
+ *    use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE
+ *    is returned by it.
+ * 3. none of the above. We only accept if it is present on known hosts.
+ *
+ * Returns SSH_OK or SSH_ERROR.
+ */
+static int myssh_is_known(struct connectdata *conn)
+{
+  int rc;
+  struct Curl_easy *data = conn->data;
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  ssh_key pubkey;
+  size_t hlen;
+  unsigned char *hash = NULL;
+  char *base64 = NULL;
+  int vstate;
+  enum curl_khmatch keymatch;
+  struct curl_khkey foundkey;
+  curl_sshkeycallback func =
+    data->set.ssh_keyfunc;
+
+  rc = ssh_get_publickey(sshc->ssh_session, &pubkey);
+  if(rc != SSH_OK)
+    return rc;
+
+  if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
+    rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5,
+                                &hash, &hlen);
+    if(rc != SSH_OK)
+      goto cleanup;
+
+    if(hlen != strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) ||
+       memcmp(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], hash, hlen)) {
+      rc = SSH_ERROR;
+      goto cleanup;
+    }
+
+    rc = SSH_OK;
+    goto cleanup;
+  }
+
+  if(data->set.ssl.primary.verifyhost != TRUE) {
+    rc = SSH_OK;
+    goto cleanup;
+  }
+
+  vstate = ssh_is_server_known(sshc->ssh_session);
+  switch(vstate) {
+    case SSH_SERVER_KNOWN_OK:
+      keymatch = CURLKHMATCH_OK;
+      break;
+    case SSH_SERVER_FILE_NOT_FOUND:
+      /* fallthrough */
+    case SSH_SERVER_NOT_KNOWN:
+      keymatch = CURLKHMATCH_MISSING;
+      break;
+  default:
+      keymatch = CURLKHMATCH_MISMATCH;
+      break;
+  }
+
+  if(func) { /* use callback to determine action */
+    rc = ssh_pki_export_pubkey_base64(pubkey, &base64);
+    if(rc != SSH_OK)
+      goto cleanup;
+
+    foundkey.key = base64;
+    foundkey.len = strlen(base64);
+
+    switch(ssh_key_type(pubkey)) {
+      case SSH_KEYTYPE_RSA:
+        foundkey.keytype = CURLKHTYPE_RSA;
+        break;
+      case SSH_KEYTYPE_RSA1:
+        foundkey.keytype = CURLKHTYPE_RSA1;
+        break;
+      case SSH_KEYTYPE_ECDSA:
+        foundkey.keytype = CURLKHTYPE_ECDSA;
+        break;
+#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,7,0)
+      case SSH_KEYTYPE_ED25519:
+        foundkey.keytype = CURLKHTYPE_ED25519;
+        break;
+#endif
+      case SSH_KEYTYPE_DSS:
+        foundkey.keytype = CURLKHTYPE_DSS;
+        break;
+      default:
+        rc = SSH_ERROR;
+        goto cleanup;
+    }
+
+    /* we don't have anything equivalent to knownkey. Always NULL */
+    rc = func(data, NULL, &foundkey, /* from the remote host */
+              keymatch, data->set.ssh_keyfunc_userp);
+
+    switch(rc) {
+      case CURLKHSTAT_FINE_ADD_TO_FILE:
+        rc = ssh_write_knownhost(sshc->ssh_session);
+        if(rc != SSH_OK) {
+          goto cleanup;
+        }
+        break;
+      case CURLKHSTAT_FINE:
+        break;
+      default: /* REJECT/DEFER */
+        rc = SSH_ERROR;
+        goto cleanup;
+    }
+  }
+  else {
+    if(keymatch != CURLKHMATCH_OK) {
+      rc = SSH_ERROR;
+      goto cleanup;
+    }
+  }
+  rc = SSH_OK;
+
+cleanup:
+  if(hash)
+    ssh_clean_pubkey_hash(&hash);
+  ssh_key_free(pubkey);
+  return rc;
+}
+
+#define MOVE_TO_ERROR_STATE(_r) { \
+  state(conn, SSH_SESSION_FREE); \
+  sshc->actualcode = _r; \
+  rc = SSH_ERROR; \
+  break; \
+}
+
+#define MOVE_TO_SFTP_CLOSE_STATE() { \
+  state(conn, SSH_SFTP_CLOSE); \
+  sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
+  rc = SSH_ERROR; \
+  break; \
+}
+
+#define MOVE_TO_LAST_AUTH \
+  if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
+    rc = SSH_OK; \
+    state(conn, SSH_AUTH_PASS_INIT); \
+    break; \
+  } \
+  else { \
+    MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \
+  }
+
+#define MOVE_TO_TERTIARY_AUTH \
+  if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
+    rc = SSH_OK; \
+    state(conn, SSH_AUTH_KEY_INIT); \
+    break; \
+  } \
+  else { \
+    MOVE_TO_LAST_AUTH; \
+  }
+
+#define MOVE_TO_SECONDARY_AUTH \
+  if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
+    rc = SSH_OK; \
+    state(conn, SSH_AUTH_GSSAPI); \
+    break; \
+  } \
+  else { \
+    MOVE_TO_TERTIARY_AUTH; \
+  }
+
+static
+int myssh_auth_interactive(struct connectdata *conn)
+{
+  int rc;
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  int nprompts;
+
+restart:
+  switch(sshc->kbd_state) {
+    case 0:
+      rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
+      if(rc == SSH_AUTH_AGAIN)
+        return SSH_AGAIN;
+
+      if(rc != SSH_AUTH_INFO)
+        return SSH_ERROR;
+
+      nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session);
+      if(nprompts == SSH_ERROR || nprompts != 1)
+        return SSH_ERROR;
+
+      rc = ssh_userauth_kbdint_setanswer(sshc->ssh_session, 0, conn->passwd);
+      if(rc < 0)
+        return SSH_ERROR;
+
+    /* fallthrough */
+    case 1:
+      sshc->kbd_state = 1;
+
+      rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
+      if(rc == SSH_AUTH_AGAIN)
+        return SSH_AGAIN;
+      else if(rc == SSH_AUTH_SUCCESS)
+        rc = SSH_OK;
+      else if(rc == SSH_AUTH_INFO) {
+        nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session);
+        if(nprompts != 0)
+          return SSH_ERROR;
+
+        sshc->kbd_state = 2;
+        goto restart;
+      }
+      else
+        rc = SSH_ERROR;
+      break;
+    case 2:
+      sshc->kbd_state = 2;
+
+      rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
+      if(rc == SSH_AUTH_AGAIN)
+        return SSH_AGAIN;
+      else if(rc == SSH_AUTH_SUCCESS)
+        rc = SSH_OK;
+      else
+        rc = SSH_ERROR;
+
+      break;
+    default:
+      return SSH_ERROR;
+  }
+
+  sshc->kbd_state = 0;
+  return rc;
+}
+
+/*
+ * ssh_statemach_act() runs the SSH state machine as far as it can without
+ * blocking and without reaching the end.  The data the pointer 'block' points
+ * to will be set to TRUE if the libssh function returns SSH_AGAIN
+ * meaning it wants to be called again when the socket is ready
+ */
+static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
+{
+  CURLcode result = CURLE_OK;
+  struct Curl_easy *data = conn->data;
+  struct SSHPROTO *protop = data->req.protop;
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  int rc = SSH_NO_ERROR, err;
+  char *new_readdir_line;
+  int seekerr = CURL_SEEKFUNC_OK;
+  const char *err_msg;
+  *block = 0;                   /* we're not blocking by default */
+
+  do {
+
+    switch(sshc->state) {
+    case SSH_INIT:
+      sshc->secondCreateDirs = 0;
+      sshc->nextstate = SSH_NO_STATE;
+      sshc->actualcode = CURLE_OK;
+
+#if 0
+      ssh_set_log_level(SSH_LOG_PROTOCOL);
+#endif
+
+      /* Set libssh to non-blocking, since everything internally is
+         non-blocking */
+      ssh_set_blocking(sshc->ssh_session, 0);
+
+      state(conn, SSH_S_STARTUP);
+      /* fall-through */
+
+    case SSH_S_STARTUP:
+      rc = ssh_connect(sshc->ssh_session);
+      if(rc == SSH_AGAIN)
+        break;
+
+      if(rc != SSH_OK) {
+        failf(data, "Failure establishing ssh session");
+        MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
+      }
+
+      state(conn, SSH_HOSTKEY);
+
+      /* fall-through */
+    case SSH_HOSTKEY:
+
+      rc = myssh_is_known(conn);
+      if(rc != SSH_OK) {
+        MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
+      }
+
+      state(conn, SSH_AUTHLIST);
+      /* fall through */
+    case SSH_AUTHLIST:{
+        sshc->authed = FALSE;
+
+        rc = ssh_userauth_none(sshc->ssh_session, NULL);
+        if(rc == SSH_AUTH_AGAIN) {
+          rc = SSH_AGAIN;
+          break;
+        }
+
+        if(rc == SSH_AUTH_SUCCESS) {
+          sshc->authed = TRUE;
+          infof(data, "Authenticated with none\n");
+          state(conn, SSH_AUTH_DONE);
+          break;
+        }
+        else if(rc == SSH_AUTH_ERROR) {
+          MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
+        }
+
+        sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
+        if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
+          state(conn, SSH_AUTH_PKEY_INIT);
+        }
+        else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
+          state(conn, SSH_AUTH_GSSAPI);
+        }
+        else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
+          state(conn, SSH_AUTH_KEY_INIT);
+        }
+        else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
+          state(conn, SSH_AUTH_PASS_INIT);
+        }
+        else {                  /* unsupported authentication method */
+          MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
+        }
+
+        break;
+      }
+    case SSH_AUTH_PKEY_INIT:
+      if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) {
+        MOVE_TO_SECONDARY_AUTH;
+      }
+
+      /* Two choices, (1) private key was given on CMD,
+       * (2) use the "default" keys. */
+      if(data->set.str[STRING_SSH_PRIVATE_KEY]) {
+        if(sshc->pubkey && !data->set.ssl.key_passwd) {
+          rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL,
+                                          sshc->pubkey);
+          if(rc == SSH_AUTH_AGAIN) {
+            rc = SSH_AGAIN;
+            break;
+          }
+
+          if(rc != SSH_OK) {
+            MOVE_TO_SECONDARY_AUTH;
+          }
+        }
+
+        rc = ssh_pki_import_privkey_file(data->
+                                         set.str[STRING_SSH_PRIVATE_KEY],
+                                         data->set.ssl.key_passwd, NULL,
+                                         NULL, &sshc->privkey);
+        if(rc != SSH_OK) {
+          failf(data, "Could not load private key file %s",
+                data->set.str[STRING_SSH_PRIVATE_KEY]);
+          break;
+        }
+
+        state(conn, SSH_AUTH_PKEY);
+        break;
+
+      }
+      else {
+        infof(data, "Authentication using SSH public key file\n");
+
+        rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
+                                         data->set.ssl.key_passwd);
+        if(rc == SSH_AUTH_AGAIN) {
+          rc = SSH_AGAIN;
+          break;
+        }
+        if(rc == SSH_AUTH_SUCCESS) {
+          rc = SSH_OK;
+          sshc->authed = TRUE;
+          infof(data, "Completed public key authentication\n");
+          state(conn, SSH_AUTH_DONE);
+          break;
+        }
+
+        MOVE_TO_SECONDARY_AUTH;
+      }
+      break;
+    case SSH_AUTH_PKEY:
+      rc = ssh_userauth_publickey(sshc->ssh_session, NULL, sshc->privkey);
+      if(rc == SSH_AUTH_AGAIN) {
+        rc = SSH_AGAIN;
+        break;
+      }
+
+      if(rc == SSH_AUTH_SUCCESS) {
+        sshc->authed = TRUE;
+        infof(data, "Completed public key authentication\n");
+        state(conn, SSH_AUTH_DONE);
+        break;
+      }
+      else {
+        infof(data, "Failed public key authentication (rc: %d)\n", rc);
+        MOVE_TO_SECONDARY_AUTH;
+      }
+      break;
+
+    case SSH_AUTH_GSSAPI:
+      if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) {
+        MOVE_TO_TERTIARY_AUTH;
+      }
+
+      rc = ssh_userauth_gssapi(sshc->ssh_session);
+      if(rc == SSH_AUTH_AGAIN) {
+        rc = SSH_AGAIN;
+        break;
+      }
+
+      if(rc == SSH_AUTH_SUCCESS) {
+        rc = SSH_OK;
+        sshc->authed = TRUE;
+        infof(data, "Completed gssapi authentication\n");
+        state(conn, SSH_AUTH_DONE);
+        break;
+      }
+
+      MOVE_TO_TERTIARY_AUTH;
+      break;
+
+    case SSH_AUTH_KEY_INIT:
+      if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) {
+        state(conn, SSH_AUTH_KEY);
+      }
+      else {
+        MOVE_TO_LAST_AUTH;
+      }
+      break;
+
+    case SSH_AUTH_KEY:
+
+      /* Authentication failed. Continue with keyboard-interactive now. */
+      rc = myssh_auth_interactive(conn);
+      if(rc == SSH_AGAIN) {
+        break;
+      }
+      if(rc == SSH_OK) {
+        sshc->authed = TRUE;
+        infof(data, "completed keyboard interactive authentication\n");
+      }
+      state(conn, SSH_AUTH_DONE);
+      break;
+
+    case SSH_AUTH_PASS_INIT:
+      if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) {
+        /* Host key authentication is intentionally not implemented */
+        MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
+      }
+      state(conn, SSH_AUTH_PASS);
+      /* fall through */
+
+    case SSH_AUTH_PASS:
+      rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
+      if(rc == SSH_AUTH_AGAIN) {
+        rc = SSH_AGAIN;
+        break;
+      }
+
+      if(rc == SSH_AUTH_SUCCESS) {
+        sshc->authed = TRUE;
+        infof(data, "Completed password authentication\n");
+        state(conn, SSH_AUTH_DONE);
+      }
+      else {
+        MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
+      }
+      break;
+
+    case SSH_AUTH_DONE:
+      if(!sshc->authed) {
+        failf(data, "Authentication failure");
+        MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
+        break;
+      }
+
+      /*
+       * At this point we have an authenticated ssh session.
+       */
+      infof(data, "Authentication complete\n");
+
+      Curl_pgrsTime(conn->data, TIMER_APPCONNECT);      /* SSH is connected */
+
+      conn->sockfd = ssh_get_fd(sshc->ssh_session);
+      conn->writesockfd = CURL_SOCKET_BAD;
+
+      if(conn->handler->protocol == CURLPROTO_SFTP) {
+        state(conn, SSH_SFTP_INIT);
+        break;
+      }
+      infof(data, "SSH CONNECT phase done\n");
+      state(conn, SSH_STOP);
+      break;
+
+    case SSH_SFTP_INIT:
+      ssh_set_blocking(sshc->ssh_session, 1);
+
+      sshc->sftp_session = sftp_new(sshc->ssh_session);
+      if(!sshc->sftp_session) {
+        failf(data, "Failure initializing sftp session: %s",
+              ssh_get_error(sshc->ssh_session));
+        MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
+        break;
+      }
+
+      rc = sftp_init(sshc->sftp_session);
+      if(rc != SSH_OK) {
+        rc = sftp_get_error(sshc->sftp_session);
+        failf(data, "Failure initializing sftp session: %s",
+              ssh_get_error(sshc->ssh_session));
+        MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
+        break;
+      }
+      state(conn, SSH_SFTP_REALPATH);
+      /* fall through */
+    case SSH_SFTP_REALPATH:
+      /*
+       * Get the "home" directory
+       */
+      sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, ".");
+      if(sshc->homedir == NULL) {
+        MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
+      }
+      conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
+
+      /* This is the last step in the SFTP connect phase. Do note that while
+         we get the homedir here, we get the "workingpath" in the DO action
+         since the homedir will remain the same between request but the
+         working path will not. */
+      DEBUGF(infof(data, "SSH CONNECT phase done\n"));
+      state(conn, SSH_STOP);
+      break;
+
+    case SSH_SFTP_QUOTE_INIT:
+
+      result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
+      if(result) {
+        sshc->actualcode = result;
+        state(conn, SSH_STOP);
+        break;
+      }
+
+      if(data->set.quote) {
+        infof(data, "Sending quote commands\n");
+        sshc->quote_item = data->set.quote;
+        state(conn, SSH_SFTP_QUOTE);
+      }
+      else {
+        state(conn, SSH_SFTP_GETINFO);
+      }
+      break;
+
+    case SSH_SFTP_POSTQUOTE_INIT:
+      if(data->set.postquote) {
+        infof(data, "Sending quote commands\n");
+        sshc->quote_item = data->set.postquote;
+        state(conn, SSH_SFTP_QUOTE);
+      }
+      else {
+        state(conn, SSH_STOP);
+      }
+      break;
+
+    case SSH_SFTP_QUOTE:
+      /* Send any quote commands */
+      sftp_quote(conn);
+      break;
+
+    case SSH_SFTP_NEXT_QUOTE:
+      Curl_safefree(sshc->quote_path1);
+      Curl_safefree(sshc->quote_path2);
+
+      sshc->quote_item = sshc->quote_item->next;
+
+      if(sshc->quote_item) {
+        state(conn, SSH_SFTP_QUOTE);
+      }
+      else {
+        if(sshc->nextstate != SSH_NO_STATE) {
+          state(conn, sshc->nextstate);
+          sshc->nextstate = SSH_NO_STATE;
+        }
+        else {
+          state(conn, SSH_SFTP_GETINFO);
+        }
+      }
+      break;
+
+    case SSH_SFTP_QUOTE_STAT:
+      sftp_quote_stat(conn);
+      break;
+
+    case SSH_SFTP_QUOTE_SETSTAT:
+      rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
+                        sshc->quote_attrs);
+      if(rc != 0 && !sshc->acceptfail) {
+        Curl_safefree(sshc->quote_path1);
+        Curl_safefree(sshc->quote_path2);
+        failf(data, "Attempt to set SFTP stats failed: %s",
+              ssh_get_error(sshc->ssh_session));
+        state(conn, SSH_SFTP_CLOSE);
+        sshc->nextstate = SSH_NO_STATE;
+        sshc->actualcode = CURLE_QUOTE_ERROR;
+        /* sshc->actualcode = sftp_error_to_CURLE(err);
+         * we do not send the actual error; we return
+         * the error the libssh2 backend is returning */
+        break;
+      }
+      state(conn, SSH_SFTP_NEXT_QUOTE);
+      break;
+
+    case SSH_SFTP_QUOTE_SYMLINK:
+      rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2,
+                        sshc->quote_path1);
+      if(rc != 0 && !sshc->acceptfail) {
+        Curl_safefree(sshc->quote_path1);
+        Curl_safefree(sshc->quote_path2);
+        failf(data, "symlink command failed: %s",
+              ssh_get_error(sshc->ssh_session));
+        state(conn, SSH_SFTP_CLOSE);
+        sshc->nextstate = SSH_NO_STATE;
+        sshc->actualcode = CURLE_QUOTE_ERROR;
+        break;
+      }
+      state(conn, SSH_SFTP_NEXT_QUOTE);
+      break;
+
+    case SSH_SFTP_QUOTE_MKDIR:
+      rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1,
+                      (mode_t)data->set.new_directory_perms);
+      if(rc != 0 && !sshc->acceptfail) {
+        Curl_safefree(sshc->quote_path1);
+        failf(data, "mkdir command failed: %s",
+              ssh_get_error(sshc->ssh_session));
+        state(conn, SSH_SFTP_CLOSE);
+        sshc->nextstate = SSH_NO_STATE;
+        sshc->actualcode = CURLE_QUOTE_ERROR;
+        break;
+      }
+      state(conn, SSH_SFTP_NEXT_QUOTE);
+      break;
+
+    case SSH_SFTP_QUOTE_RENAME:
+      rc = sftp_rename(sshc->sftp_session, sshc->quote_path1,
+                       sshc->quote_path2);
+      if(rc != 0 && !sshc->acceptfail) {
+        Curl_safefree(sshc->quote_path1);
+        Curl_safefree(sshc->quote_path2);
+        failf(data, "rename command failed: %s",
+              ssh_get_error(sshc->ssh_session));
+        state(conn, SSH_SFTP_CLOSE);
+        sshc->nextstate = SSH_NO_STATE;
+        sshc->actualcode = CURLE_QUOTE_ERROR;
+        break;
+      }
+      state(conn, SSH_SFTP_NEXT_QUOTE);
+      break;
+
+    case SSH_SFTP_QUOTE_RMDIR:
+      rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
+      if(rc != 0 && !sshc->acceptfail) {
+        Curl_safefree(sshc->quote_path1);
+        failf(data, "rmdir command failed: %s",
+              ssh_get_error(sshc->ssh_session));
+        state(conn, SSH_SFTP_CLOSE);
+        sshc->nextstate = SSH_NO_STATE;
+        sshc->actualcode = CURLE_QUOTE_ERROR;
+        break;
+      }
+      state(conn, SSH_SFTP_NEXT_QUOTE);
+      break;
+
+    case SSH_SFTP_QUOTE_UNLINK:
+      rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1);
+      if(rc != 0 && !sshc->acceptfail) {
+        Curl_safefree(sshc->quote_path1);
+        failf(data, "rm command failed: %s",
+              ssh_get_error(sshc->ssh_session));
+        state(conn, SSH_SFTP_CLOSE);
+        sshc->nextstate = SSH_NO_STATE;
+        sshc->actualcode = CURLE_QUOTE_ERROR;
+        break;
+      }
+      state(conn, SSH_SFTP_NEXT_QUOTE);
+      break;
+
+    case SSH_SFTP_QUOTE_STATVFS:
+    {
+      sftp_statvfs_t statvfs;
+
+      statvfs = sftp_statvfs(sshc->sftp_session, sshc->quote_path1);
+      if(!statvfs && !sshc->acceptfail) {
+        Curl_safefree(sshc->quote_path1);
+        failf(data, "statvfs command failed: %s",
+              ssh_get_error(sshc->ssh_session));
+        state(conn, SSH_SFTP_CLOSE);
+        sshc->nextstate = SSH_NO_STATE;
+        sshc->actualcode = CURLE_QUOTE_ERROR;
+        break;
+      }
+      else if(statvfs) {
+        char *tmp = aprintf("statvfs:\n"
+                            "f_bsize: %llu\n" "f_frsize: %llu\n"
+                            "f_blocks: %llu\n" "f_bfree: %llu\n"
+                            "f_bavail: %llu\n" "f_files: %llu\n"
+                            "f_ffree: %llu\n" "f_favail: %llu\n"
+                            "f_fsid: %llu\n" "f_flag: %llu\n"
+                            "f_namemax: %llu\n",
+                            statvfs->f_bsize, statvfs->f_frsize,
+                            statvfs->f_blocks, statvfs->f_bfree,
+                            statvfs->f_bavail, statvfs->f_files,
+                            statvfs->f_ffree, statvfs->f_favail,
+                            statvfs->f_fsid, statvfs->f_flag,
+                            statvfs->f_namemax);
+        sftp_statvfs_free(statvfs);
+
+        if(!tmp) {
+          result = CURLE_OUT_OF_MEMORY;
+          state(conn, SSH_SFTP_CLOSE);
+          sshc->nextstate = SSH_NO_STATE;
+          break;
+        }
+
+        result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+        free(tmp);
+        if(result) {
+          state(conn, SSH_SFTP_CLOSE);
+          sshc->nextstate = SSH_NO_STATE;
+          sshc->actualcode = result;
+        }
+      }
+      state(conn, SSH_SFTP_NEXT_QUOTE);
+      break;
+    }
+
+    case SSH_SFTP_GETINFO:
+      if(data->set.get_filetime) {
+        state(conn, SSH_SFTP_FILETIME);
+      }
+      else {
+        state(conn, SSH_SFTP_TRANS_INIT);
+      }
+      break;
+
+    case SSH_SFTP_FILETIME:
+    {
+      sftp_attributes attrs;
+
+      attrs = sftp_stat(sshc->sftp_session, protop->path);
+      if(attrs != 0) {
+        data->info.filetime = (long)attrs->mtime;
+        sftp_attributes_free(attrs);
+      }
+
+      state(conn, SSH_SFTP_TRANS_INIT);
+      break;
+    }
+
+    case SSH_SFTP_TRANS_INIT:
+      if(data->set.upload)
+        state(conn, SSH_SFTP_UPLOAD_INIT);
+      else {
+        if(protop->path[strlen(protop->path)-1] == '/')
+          state(conn, SSH_SFTP_READDIR_INIT);
+        else
+          state(conn, SSH_SFTP_DOWNLOAD_INIT);
+      }
+      break;
+
+    case SSH_SFTP_UPLOAD_INIT:
+    {
+      int flags;
+
+      if(data->state.resume_from != 0) {
+        sftp_attributes attrs;
+
+        if(data->state.resume_from < 0) {
+          attrs = sftp_stat(sshc->sftp_session, protop->path);
+          if(attrs != 0) {
+            curl_off_t size = attrs->size;
+            if(size < 0) {
+              failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
+              MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
+            }
+            data->state.resume_from = attrs->size;
+
+            sftp_attributes_free(attrs);
+          }
+          else {
+            data->state.resume_from = 0;
+          }
+        }
+      }
+
+      if(data->set.ftp_append)
+        /* Try to open for append, but create if nonexisting */
+        flags = O_WRONLY|O_CREAT|O_APPEND;
+      else if(data->state.resume_from > 0)
+        /* If we have restart position then open for append */
+        flags = O_WRONLY|O_APPEND;
+      else
+        /* Clear file before writing (normal behaviour) */
+        flags = O_WRONLY|O_APPEND|O_CREAT|O_TRUNC;
+
+      if(sshc->sftp_file)
+        sftp_close(sshc->sftp_file);
+      sshc->sftp_file =
+        sftp_open(sshc->sftp_session, protop->path,
+                  flags, (mode_t)data->set.new_file_perms);
+      if(!sshc->sftp_file) {
+        err = sftp_get_error(sshc->sftp_session);
+
+        if(((err == SSH_FX_NO_SUCH_FILE || err == SSH_FX_FAILURE ||
+             err == SSH_FX_NO_SUCH_PATH)) &&
+             (data->set.ftp_create_missing_dirs &&
+             (strlen(protop->path) > 1))) {
+               /* try to create the path remotely */
+               rc = 0;
+               sshc->secondCreateDirs = 1;
+               state(conn, SSH_SFTP_CREATE_DIRS_INIT);
+               break;
+        }
+        else {
+          MOVE_TO_SFTP_CLOSE_STATE();
+        }
+      }
+
+      /* If we have a restart point then we need to seek to the correct
+         position. */
+      if(data->state.resume_from > 0) {
+        /* Let's read off the proper amount of bytes from the input. */
+        if(conn->seek_func) {
+          seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
+                                    SEEK_SET);
+        }
+
+        if(seekerr != CURL_SEEKFUNC_OK) {
+          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");
+              MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST);
+            }
+          } while(passed < data->state.resume_from);
+        }
+
+        /* now, decrease the size of the read */
+        if(data->state.infilesize > 0) {
+          data->state.infilesize -= data->state.resume_from;
+          data->req.size = data->state.infilesize;
+          Curl_pgrsSetUploadSize(data, data->state.infilesize);
+        }
+
+        rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
+        if(rc != 0) {
+          MOVE_TO_SFTP_CLOSE_STATE();
+        }
+      }
+      if(data->state.infilesize > 0) {
+        data->req.size = data->state.infilesize;
+        Curl_pgrsSetUploadSize(data, data->state.infilesize);
+      }
+      /* upload data */
+      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+
+      /* not set by Curl_setup_transfer to preserve keepon bits */
+      conn->sockfd = conn->writesockfd;
+
+      /* store this original bitmask setup to use later on if we can't
+         figure out a "real" bitmask */
+      sshc->orig_waitfor = data->req.keepon;
+
+      /* we want to use the _sending_ function even when the socket turns
+         out readable as the underlying libssh sftp send function will deal
+         with both accordingly */
+      conn->cselect_bits = CURL_CSELECT_OUT;
+
+      /* since we don't really wait for anything at this point, we want the
+         state machine to move on as soon as possible so we set a very short
+         timeout here */
+      Curl_expire(data, 0, EXPIRE_RUN_NOW);
+
+      state(conn, SSH_STOP);
+      break;
+    }
+
+    case SSH_SFTP_CREATE_DIRS_INIT:
+      if(strlen(protop->path) > 1) {
+        sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */
+        state(conn, SSH_SFTP_CREATE_DIRS);
+      }
+      else {
+        state(conn, SSH_SFTP_UPLOAD_INIT);
+      }
+      break;
+
+    case SSH_SFTP_CREATE_DIRS:
+      sshc->slash_pos = strchr(sshc->slash_pos, '/');
+      if(sshc->slash_pos) {
+        *sshc->slash_pos = 0;
+
+        infof(data, "Creating directory '%s'\n", protop->path);
+        state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
+        break;
+      }
+      state(conn, SSH_SFTP_UPLOAD_INIT);
+      break;
+
+    case SSH_SFTP_CREATE_DIRS_MKDIR:
+      /* 'mode' - parameter is preliminary - default to 0644 */
+      rc = sftp_mkdir(sshc->sftp_session, protop->path,
+                      (mode_t)data->set.new_directory_perms);
+      *sshc->slash_pos = '/';
+      ++sshc->slash_pos;
+      if(rc < 0) {
+        /*
+         * Abort if failure wasn't that the dir already exists or the
+         * permission was denied (creation might succeed further down the
+         * path) - retry on unspecific FAILURE also
+         */
+        err = sftp_get_error(sshc->sftp_session);
+        if((err != SSH_FX_FILE_ALREADY_EXISTS) &&
+           (err != SSH_FX_FAILURE) &&
+           (err != SSH_FX_PERMISSION_DENIED)) {
+          MOVE_TO_SFTP_CLOSE_STATE();
+        }
+        rc = 0; /* clear rc and continue */
+      }
+      state(conn, SSH_SFTP_CREATE_DIRS);
+      break;
+
+    case SSH_SFTP_READDIR_INIT:
+      Curl_pgrsSetDownloadSize(data, -1);
+      if(data->set.opt_no_body) {
+        state(conn, SSH_STOP);
+        break;
+      }
+
+      /*
+       * This is a directory that we are trying to get, so produce a directory
+       * listing
+       */
+      sshc->sftp_dir = sftp_opendir(sshc->sftp_session,
+                                    protop->path);
+      if(!sshc->sftp_dir) {
+        failf(data, "Could not open directory for reading: %s",
+              ssh_get_error(sshc->ssh_session));
+        MOVE_TO_SFTP_CLOSE_STATE();
+      }
+      state(conn, SSH_SFTP_READDIR);
+      break;
+
+    case SSH_SFTP_READDIR:
+
+      if(sshc->readdir_attrs)
+        sftp_attributes_free(sshc->readdir_attrs);
+
+      sshc->readdir_attrs = sftp_readdir(sshc->sftp_session, sshc->sftp_dir);
+      if(sshc->readdir_attrs) {
+        sshc->readdir_filename = sshc->readdir_attrs->name;
+        sshc->readdir_longentry = sshc->readdir_attrs->longname;
+        sshc->readdir_len = (int)strlen(sshc->readdir_filename);
+
+        if(data->set.ftp_list_only) {
+          char *tmpLine;
+
+          tmpLine = aprintf("%s\n", sshc->readdir_filename);
+          if(tmpLine == NULL) {
+            state(conn, SSH_SFTP_CLOSE);
+            sshc->actualcode = CURLE_OUT_OF_MEMORY;
+            break;
+          }
+          result = Curl_client_write(conn, CLIENTWRITE_BODY,
+                                     tmpLine, sshc->readdir_len + 1);
+          free(tmpLine);
+
+          if(result) {
+            state(conn, SSH_STOP);
+            break;
+          }
+          /* since this counts what we send to the client, we include the
+             newline in this counter */
+          data->req.bytecount += sshc->readdir_len + 1;
+
+          /* output debug output if that is requested */
+          if(data->set.verbose) {
+            Curl_debug(data, CURLINFO_DATA_OUT,
+                       (char *)sshc->readdir_filename,
+                       sshc->readdir_len, conn);
+          }
+        }
+        else {
+          sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
+          sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
+          sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
+          if(!sshc->readdir_line) {
+            state(conn, SSH_SFTP_CLOSE);
+            sshc->actualcode = CURLE_OUT_OF_MEMORY;
+            break;
+          }
+
+          memcpy(sshc->readdir_line, sshc->readdir_longentry,
+                 sshc->readdir_currLen);
+          if((sshc->readdir_attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
+             ((sshc->readdir_attrs->permissions & S_IFMT) ==
+              S_IFLNK)) {
+            sshc->readdir_linkPath = malloc(PATH_MAX + 1);
+            if(sshc->readdir_linkPath == NULL) {
+              state(conn, SSH_SFTP_CLOSE);
+              sshc->actualcode = CURLE_OUT_OF_MEMORY;
+              break;
+            }
+
+            snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
+                     sshc->readdir_filename);
+
+            state(conn, SSH_SFTP_READDIR_LINK);
+            break;
+          }
+          state(conn, SSH_SFTP_READDIR_BOTTOM);
+          break;
+        }
+      }
+      else if(sshc->readdir_attrs == NULL && sftp_dir_eof(sshc->sftp_dir)) {
+        state(conn, SSH_SFTP_READDIR_DONE);
+        break;
+      }
+      else {
+        failf(data, "Could not open remote file for reading: %s",
+              ssh_get_error(sshc->ssh_session));
+        MOVE_TO_SFTP_CLOSE_STATE();
+        break;
+      }
+      break;
+
+    case SSH_SFTP_READDIR_LINK:
+      if(sshc->readdir_link_attrs)
+        sftp_attributes_free(sshc->readdir_link_attrs);
+
+      sshc->readdir_link_attrs = sftp_lstat(sshc->sftp_session,
+                                            sshc->readdir_linkPath);
+      if(sshc->readdir_link_attrs == 0) {
+        failf(data, "Could not read symlink for reading: %s",
+              ssh_get_error(sshc->ssh_session));
+        MOVE_TO_SFTP_CLOSE_STATE();
+      }
+
+      if(sshc->readdir_link_attrs->name == NULL) {
+        sshc->readdir_tmp = sftp_readlink(sshc->sftp_session,
+                                          sshc->readdir_linkPath);
+        if(sshc->readdir_filename == NULL)
+          sshc->readdir_len = 0;
+        else
+          sshc->readdir_len = (int)strlen(sshc->readdir_tmp);
+        sshc->readdir_longentry = NULL;
+        sshc->readdir_filename = sshc->readdir_tmp;
+      }
+      else {
+        sshc->readdir_len = (int)strlen(sshc->readdir_link_attrs->name);
+        sshc->readdir_filename = sshc->readdir_link_attrs->name;
+        sshc->readdir_longentry = sshc->readdir_link_attrs->longname;
+      }
+
+      Curl_safefree(sshc->readdir_linkPath);
+
+      /* get room for the filename and extra output */
+      sshc->readdir_totalLen += 4 + sshc->readdir_len;
+      new_readdir_line = Curl_saferealloc(sshc->readdir_line,
+                                          sshc->readdir_totalLen);
+      if(!new_readdir_line) {
+        sshc->readdir_line = NULL;
+        state(conn, SSH_SFTP_CLOSE);
+        sshc->actualcode = CURLE_OUT_OF_MEMORY;
+        break;
+      }
+      sshc->readdir_line = new_readdir_line;
+
+      sshc->readdir_currLen += snprintf(sshc->readdir_line +
+                                        sshc->readdir_currLen,
+                                        sshc->readdir_totalLen -
+                                        sshc->readdir_currLen,
+                                        " -> %s",
+                                        sshc->readdir_filename);
+
+      sftp_attributes_free(sshc->readdir_link_attrs);
+      sshc->readdir_link_attrs = NULL;
+      sshc->readdir_filename = NULL;
+      sshc->readdir_longentry = NULL;
+
+      state(conn, SSH_SFTP_READDIR_BOTTOM);
+      /* fall through */
+    case SSH_SFTP_READDIR_BOTTOM:
+      sshc->readdir_currLen += snprintf(sshc->readdir_line +
+                                        sshc->readdir_currLen,
+                                        sshc->readdir_totalLen -
+                                        sshc->readdir_currLen, "\n");
+      result = Curl_client_write(conn, CLIENTWRITE_BODY,
+                                 sshc->readdir_line,
+                                 sshc->readdir_currLen);
+
+      if(!result) {
+
+        /* output debug output if that is requested */
+        if(data->set.verbose) {
+          Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
+                     sshc->readdir_currLen, conn);
+        }
+        data->req.bytecount += sshc->readdir_currLen;
+      }
+      Curl_safefree(sshc->readdir_line);
+      ssh_string_free_char(sshc->readdir_tmp);
+      sshc->readdir_tmp = NULL;
+
+      if(result) {
+        state(conn, SSH_STOP);
+      }
+      else
+        state(conn, SSH_SFTP_READDIR);
+      break;
+
+    case SSH_SFTP_READDIR_DONE:
+      sftp_closedir(sshc->sftp_dir);
+      sshc->sftp_dir = NULL;
+
+      /* no data to transfer */
+      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      state(conn, SSH_STOP);
+      break;
+
+    case SSH_SFTP_DOWNLOAD_INIT:
+      /*
+       * Work on getting the specified file
+       */
+      if(sshc->sftp_file)
+        sftp_close(sshc->sftp_file);
+
+      sshc->sftp_file = sftp_open(sshc->sftp_session, protop->path,
+                                  O_RDONLY, (mode_t)data->set.new_file_perms);
+      if(!sshc->sftp_file) {
+        failf(data, "Could not open remote file for reading: %s",
+              ssh_get_error(sshc->ssh_session));
+
+        MOVE_TO_SFTP_CLOSE_STATE();
+      }
+
+      state(conn, SSH_SFTP_DOWNLOAD_STAT);
+      break;
+
+    case SSH_SFTP_DOWNLOAD_STAT:
+    {
+      sftp_attributes attrs;
+      curl_off_t size;
+
+      attrs = sftp_fstat(sshc->sftp_file);
+      if(!attrs ||
+              !(attrs->flags & SSH_FILEXFER_ATTR_SIZE) ||
+              (attrs->size == 0)) {
+        /*
+         * sftp_fstat didn't return an error, so maybe the server
+         * just doesn't support stat()
+         * OR the server doesn't return a file size with a stat()
+         * OR file size is 0
+         */
+        data->req.size = -1;
+        data->req.maxdownload = -1;
+        Curl_pgrsSetDownloadSize(data, -1);
+        size = 0;
+      }
+      else {
+        size = attrs->size;
+
+        sftp_attributes_free(attrs);
+
+        if(size < 0) {
+          failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
+          return CURLE_BAD_DOWNLOAD_RESUME;
+        }
+        if(conn->data->state.use_range) {
+          curl_off_t from, to;
+          char *ptr;
+          char *ptr2;
+          CURLofft to_t;
+          CURLofft from_t;
+
+          from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
+          if(from_t == CURL_OFFT_FLOW) {
+            return CURLE_RANGE_ERROR;
+          }
+          while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+            ptr++;
+          to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
+          if(to_t == CURL_OFFT_FLOW) {
+            return CURLE_RANGE_ERROR;
+          }
+          if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
+             || (to >= size)) {
+            to = size - 1;
+          }
+          if(from_t) {
+            /* from is relative to end of file */
+            from = size - to;
+            to = size - 1;
+          }
+          if(from > size) {
+            failf(data, "Offset (%"
+                  CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
+                  CURL_FORMAT_CURL_OFF_T ")", from, size);
+            return CURLE_BAD_DOWNLOAD_RESUME;
+          }
+          if(from > to) {
+            from = to;
+            size = 0;
+          }
+          else {
+            size = to - from + 1;
+          }
+
+          rc = sftp_seek64(sshc->sftp_file, from);
+          if(rc != 0) {
+            MOVE_TO_SFTP_CLOSE_STATE();
+          }
+        }
+        data->req.size = size;
+        data->req.maxdownload = size;
+        Curl_pgrsSetDownloadSize(data, size);
+      }
+
+      /* We can resume if we can seek to the resume position */
+      if(data->state.resume_from) {
+        if(data->state.resume_from < 0) {
+          /* We're supposed to download the last abs(from) bytes */
+          if((curl_off_t)size < -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, size);
+            return CURLE_BAD_DOWNLOAD_RESUME;
+          }
+          /* download from where? */
+          data->state.resume_from += size;
+        }
+        else {
+          if((curl_off_t)size < 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, size);
+            return CURLE_BAD_DOWNLOAD_RESUME;
+          }
+        }
+        /* Does a completed file need to be seeked and started or closed ? */
+        /* Now store the number of bytes we are expected to download */
+        data->req.size = size - data->state.resume_from;
+        data->req.maxdownload = size - data->state.resume_from;
+        Curl_pgrsSetDownloadSize(data,
+                                 size - data->state.resume_from);
+
+        rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
+        if(rc != 0) {
+          MOVE_TO_SFTP_CLOSE_STATE();
+        }
+      }
+    }
+
+    /* Setup the actual download */
+    if(data->req.size == 0) {
+      /* no data to transfer */
+      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      infof(data, "File already completely downloaded\n");
+      state(conn, SSH_STOP);
+      break;
+    }
+    Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
+                        FALSE, NULL, -1, NULL);
+
+    /* not set by Curl_setup_transfer to preserve keepon bits */
+    conn->writesockfd = conn->sockfd;
+
+    /* we want to use the _receiving_ function even when the socket turns
+       out writableable as the underlying libssh recv function will deal
+       with both accordingly */
+    conn->cselect_bits = CURL_CSELECT_IN;
+
+    if(result) {
+      /* this should never occur; the close state should be entered
+         at the time the error occurs */
+      state(conn, SSH_SFTP_CLOSE);
+      sshc->actualcode = result;
+    }
+    else {
+      sshc->sftp_recv_state = 0;
+      state(conn, SSH_STOP);
+    }
+    break;
+
+    case SSH_SFTP_CLOSE:
+      if(sshc->sftp_file) {
+        sftp_close(sshc->sftp_file);
+        sshc->sftp_file = NULL;
+      }
+      Curl_safefree(protop->path);
+
+      DEBUGF(infof(data, "SFTP DONE done\n"));
+
+      /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
+         After nextstate is executed, the control should come back to
+         SSH_SFTP_CLOSE to pass the correct result back  */
+      if(sshc->nextstate != SSH_NO_STATE &&
+         sshc->nextstate != SSH_SFTP_CLOSE) {
+        state(conn, sshc->nextstate);
+        sshc->nextstate = SSH_SFTP_CLOSE;
+      }
+      else {
+        state(conn, SSH_STOP);
+        result = sshc->actualcode;
+      }
+      break;
+
+    case SSH_SFTP_SHUTDOWN:
+      /* during times we get here due to a broken transfer and then the
+         sftp_handle might not have been taken down so make sure that is done
+         before we proceed */
+
+      if(sshc->sftp_file) {
+        sftp_close(sshc->sftp_file);
+        sshc->sftp_file = NULL;
+      }
+
+      if(sshc->sftp_session) {
+        sftp_free(sshc->sftp_session);
+        sshc->sftp_session = NULL;
+      }
+
+      Curl_safefree(sshc->homedir);
+      conn->data->state.most_recent_ftp_entrypath = NULL;
+
+      state(conn, SSH_SESSION_DISCONNECT);
+      break;
+
+
+    case SSH_SCP_TRANS_INIT:
+      result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
+      if(result) {
+        sshc->actualcode = result;
+        state(conn, SSH_STOP);
+        break;
+      }
+
+      /* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */
+      ssh_set_blocking(sshc->ssh_session, 1);
+
+      if(data->set.upload) {
+        if(data->state.infilesize < 0) {
+          failf(data, "SCP requires a known file size for upload");
+          sshc->actualcode = CURLE_UPLOAD_FAILED;
+          MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
+        }
+
+        sshc->scp_session =
+          ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path);
+        state(conn, SSH_SCP_UPLOAD_INIT);
+      }
+      else {
+        sshc->scp_session =
+          ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path);
+        state(conn, SSH_SCP_DOWNLOAD_INIT);
+      }
+
+      if(!sshc->scp_session) {
+        err_msg = ssh_get_error(sshc->ssh_session);
+        failf(conn->data, "%s", err_msg);
+        MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
+      }
+
+      break;
+
+    case SSH_SCP_UPLOAD_INIT:
+
+      rc = ssh_scp_init(sshc->scp_session);
+      if(rc != SSH_OK) {
+        err_msg = ssh_get_error(sshc->ssh_session);
+        failf(conn->data, "%s", err_msg);
+        MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
+      }
+
+      rc = ssh_scp_push_file(sshc->scp_session, protop->path,
+                             data->state.infilesize,
+                             (int)data->set.new_file_perms);
+      if(rc != SSH_OK) {
+        err_msg = ssh_get_error(sshc->ssh_session);
+        failf(conn->data, "%s", err_msg);
+        MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
+      }
+
+      /* upload data */
+      Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
+                          FIRSTSOCKET, NULL);
+
+      /* not set by Curl_setup_transfer to preserve keepon bits */
+      conn->sockfd = conn->writesockfd;
+
+      /* store this original bitmask setup to use later on if we can't
+         figure out a "real" bitmask */
+      sshc->orig_waitfor = data->req.keepon;
+
+      /* we want to use the _sending_ function even when the socket turns
+         out readable as the underlying libssh scp send function will deal
+         with both accordingly */
+      conn->cselect_bits = CURL_CSELECT_OUT;
+
+      state(conn, SSH_STOP);
+
+      break;
+
+    case SSH_SCP_DOWNLOAD_INIT:
+
+      rc = ssh_scp_init(sshc->scp_session);
+      if(rc != SSH_OK) {
+        err_msg = ssh_get_error(sshc->ssh_session);
+        failf(conn->data, "%s", err_msg);
+        MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
+      }
+      state(conn, SSH_SCP_DOWNLOAD);
+      /* fall through */
+
+    case SSH_SCP_DOWNLOAD:{
+        curl_off_t bytecount;
+
+        rc = ssh_scp_pull_request(sshc->scp_session);
+        if(rc != SSH_SCP_REQUEST_NEWFILE) {
+          err_msg = ssh_get_error(sshc->ssh_session);
+          failf(conn->data, "%s", err_msg);
+          MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND);
+          break;
+        }
+
+        /* 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);
+
+        /* not set by Curl_setup_transfer to preserve keepon bits */
+        conn->writesockfd = conn->sockfd;
+
+        /* we want to use the _receiving_ function even when the socket turns
+           out writableable as the underlying libssh recv function will deal
+           with both accordingly */
+        conn->cselect_bits = CURL_CSELECT_IN;
+
+        state(conn, SSH_STOP);
+        break;
+      }
+    case SSH_SCP_DONE:
+      if(data->set.upload)
+        state(conn, SSH_SCP_SEND_EOF);
+      else
+        state(conn, SSH_SCP_CHANNEL_FREE);
+      break;
+
+    case SSH_SCP_SEND_EOF:
+      if(sshc->scp_session) {
+        rc = ssh_scp_close(sshc->scp_session);
+        if(rc == SSH_AGAIN) {
+          /* Currently the ssh_scp_close handles waiting for EOF in
+           * blocking way.
+           */
+          break;
+        }
+        if(rc != SSH_OK) {
+          infof(data, "Failed to close libssh scp channel: %s\n",
+                ssh_get_error(sshc->ssh_session));
+        }
+      }
+
+      state(conn, SSH_SCP_CHANNEL_FREE);
+      break;
+
+    case SSH_SCP_CHANNEL_FREE:
+      if(sshc->scp_session) {
+        ssh_scp_free(sshc->scp_session);
+        sshc->scp_session = NULL;
+      }
+      DEBUGF(infof(data, "SCP DONE phase complete\n"));
+
+      ssh_set_blocking(sshc->ssh_session, 0);
+
+      state(conn, SSH_SESSION_DISCONNECT);
+      /* fall through */
+
+    case SSH_SESSION_DISCONNECT:
+      /* during weird times when we've been prematurely aborted, the channel
+         is still alive when we reach this state and we MUST kill the channel
+         properly first */
+      if(sshc->scp_session) {
+        ssh_scp_free(sshc->scp_session);
+        sshc->scp_session = NULL;
+      }
+
+      ssh_disconnect(sshc->ssh_session);
+
+      Curl_safefree(sshc->homedir);
+      conn->data->state.most_recent_ftp_entrypath = NULL;
+
+      state(conn, SSH_SESSION_FREE);
+      /* fall through */
+    case SSH_SESSION_FREE:
+      if(sshc->ssh_session) {
+        ssh_free(sshc->ssh_session);
+        sshc->ssh_session = NULL;
+      }
+
+      /* worst-case scenario cleanup */
+
+      DEBUGASSERT(sshc->ssh_session == NULL);
+      DEBUGASSERT(sshc->scp_session == NULL);
+
+      if(sshc->readdir_tmp) {
+        ssh_string_free_char(sshc->readdir_tmp);
+        sshc->readdir_tmp = NULL;
+      }
+
+      if(sshc->quote_attrs)
+        sftp_attributes_free(sshc->quote_attrs);
+
+      if(sshc->readdir_attrs)
+        sftp_attributes_free(sshc->readdir_attrs);
+
+      if(sshc->readdir_link_attrs)
+        sftp_attributes_free(sshc->readdir_link_attrs);
+
+      if(sshc->privkey)
+        ssh_key_free(sshc->privkey);
+      if(sshc->pubkey)
+        ssh_key_free(sshc->pubkey);
+
+      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);
+
+      /* the code we are about to return */
+      result = sshc->actualcode;
+
+      memset(sshc, 0, sizeof(struct ssh_conn));
+
+      connclose(conn, "SSH session free");
+      sshc->state = SSH_SESSION_FREE;   /* current */
+      sshc->nextstate = SSH_NO_STATE;
+      state(conn, SSH_STOP);
+      break;
+
+    case SSH_QUIT:
+      /* fallthrough, just stop! */
+    default:
+      /* internal error */
+      sshc->nextstate = SSH_NO_STATE;
+      state(conn, SSH_STOP);
+      break;
+
+    }
+  } while(!rc && (sshc->state != SSH_STOP));
+
+
+  if(rc == SSH_AGAIN) {
+    /* we would block, we need to wait for the socket to be ready (in the
+       right direction too)! */
+    *block = TRUE;
+  }
+
+  return result;
+}
+
+
+/* called by the multi interface to figure out what socket(s) to wait for and
+   for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
+static int myssh_perform_getsock(const struct connectdata *conn,
+                                 curl_socket_t *sock,  /* points to numsocks
+                                                          number of sockets */
+                                 int numsocks)
+{
+  int bitmap = GETSOCK_BLANK;
+  (void) numsocks;
+
+  sock[0] = conn->sock[FIRSTSOCKET];
+
+  if(conn->waitfor & KEEP_RECV)
+    bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
+
+  if(conn->waitfor & KEEP_SEND)
+    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
+
+  return bitmap;
+}
+
+/* Generic function called by the multi interface to figure out what socket(s)
+   to wait for and for what actions during the DOING and PROTOCONNECT states*/
+static int myssh_getsock(struct connectdata *conn,
+                         curl_socket_t *sock,  /* points to numsocks
+                                                   number of sockets */
+                         int numsocks)
+{
+  /* if we know the direction we can use the generic *_getsock() function even
+     for the protocol_connect and doing states */
+  return myssh_perform_getsock(conn, sock, numsocks);
+}
+
+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);
+    if(dir & SSH_READ_PENDING) {
+      /* translate the libssh define bits into our own bit defines */
+      conn->waitfor = KEEP_RECV;
+    }
+    else if(dir & SSH_WRITE_PENDING) {
+      conn->waitfor = KEEP_SEND;
+    }
+  }
+}
+
+/* called repeatedly until done from multi.c */
+static CURLcode myssh_multi_statemach(struct connectdata *conn,
+                                      bool *done)
+{
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  CURLcode result = CURLE_OK;
+  bool block;    /* we store the status and use that to provide a ssh_getsock()
+                    implementation */
+
+  result = myssh_statemach_act(conn, &block);
+  *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
+  myssh_block2waitfor(conn, block);
+
+  return result;
+}
+
+static CURLcode myssh_block_statemach(struct connectdata *conn,
+                                      bool disconnect)
+{
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  CURLcode result = CURLE_OK;
+  struct Curl_easy *data = conn->data;
+
+  while((sshc->state != SSH_STOP) && !result) {
+    bool block;
+    timediff_t left = 1000;
+    struct curltime now = Curl_now();
+
+    result = myssh_statemach_act(conn, &block);
+    if(result)
+      break;
+
+    if(!disconnect) {
+      if(Curl_pgrsUpdate(conn))
+        return CURLE_ABORTED_BY_CALLBACK;
+
+      result = Curl_speedcheck(data, now);
+      if(result)
+        break;
+
+      left = Curl_timeleft(data, NULL, FALSE);
+      if(left < 0) {
+        failf(data, "Operation timed out");
+        return CURLE_OPERATION_TIMEDOUT;
+      }
+    }
+
+    if(!result && block) {
+      curl_socket_t sock = conn->sock[FIRSTSOCKET];
+      curl_socket_t fd_read = CURL_SOCKET_BAD;
+      fd_read = sock;
+      /* wait for the socket to become ready */
+      (void) Curl_socket_check(fd_read, CURL_SOCKET_BAD,
+                               CURL_SOCKET_BAD, left > 1000 ? 1000 : left);
+    }
+
+  }
+
+  return result;
+}
+
+/*
+ * SSH setup connection
+ */
+static CURLcode myssh_setup_connection(struct connectdata *conn)
+{
+  struct SSHPROTO *ssh;
+
+  conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+  if(!ssh)
+    return CURLE_OUT_OF_MEMORY;
+
+  return CURLE_OK;
+}
+
+static Curl_recv scp_recv, sftp_recv;
+static Curl_send scp_send, sftp_send;
+
+/*
+ * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
+ * do protocol-specific actions at connect-time.
+ */
+static CURLcode myssh_connect(struct connectdata *conn, bool *done)
+{
+  struct ssh_conn *ssh;
+  CURLcode result;
+  struct Curl_easy *data = conn->data;
+  int rc;
+
+  /* initialize per-handle data if not already */
+  if(!data->req.protop)
+    myssh_setup_connection(conn);
+
+  /* We default to persistent connections. We set this already in this connect
+     function to make the re-use checks properly be able to check this bit. */
+  connkeep(conn, "SSH default");
+
+  if(conn->handler->protocol & CURLPROTO_SCP) {
+    conn->recv[FIRSTSOCKET] = scp_recv;
+    conn->send[FIRSTSOCKET] = scp_send;
+  }
+  else {
+    conn->recv[FIRSTSOCKET] = sftp_recv;
+    conn->send[FIRSTSOCKET] = sftp_send;
+  }
+
+  ssh = &conn->proto.sshc;
+
+  ssh->ssh_session = ssh_new();
+  if(ssh->ssh_session == NULL) {
+    failf(data, "Failure initialising ssh session");
+    return CURLE_FAILED_INIT;
+  }
+
+  if(conn->user) {
+    infof(data, "User: %s\n", conn->user);
+    ssh_options_set(ssh->ssh_session, SSH_OPTIONS_USER, conn->user);
+  }
+
+  if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
+    infof(data, "Known hosts: %s\n", data->set.str[STRING_SSH_KNOWNHOSTS]);
+    ssh_options_set(ssh->ssh_session, SSH_OPTIONS_KNOWNHOSTS,
+                    data->set.str[STRING_SSH_KNOWNHOSTS]);
+  }
+
+  ssh_options_set(ssh->ssh_session, SSH_OPTIONS_HOST, conn->host.name);
+  if(conn->remote_port)
+    ssh_options_set(ssh->ssh_session, SSH_OPTIONS_PORT,
+                    &conn->remote_port);
+
+  if(data->set.ssh_compression) {
+    ssh_options_set(ssh->ssh_session, SSH_OPTIONS_COMPRESSION,
+                    "zlib,zlib at openssh.com,none");
+  }
+
+  ssh->privkey = NULL;
+  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);
+    if(rc != SSH_OK) {
+      failf(data, "Could not load public key file");
+      /* ignore */
+    }
+  }
+
+  /* we do not verify here, we do it at the state machine,
+   * after connection */
+
+  state(conn, SSH_INIT);
+
+  result = myssh_multi_statemach(conn, done);
+
+  return result;
+}
+
+/* called from multi.c while DOing */
+static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done)
+{
+  CURLcode result;
+
+  result = myssh_multi_statemach(conn, dophase_done);
+
+  if(*dophase_done) {
+    DEBUGF(infof(conn->data, "DO phase is complete\n"));
+  }
+  return result;
+}
+
+/*
+ ***********************************************************************
+ *
+ * scp_perform()
+ *
+ * This is the actual DO function for SCP. Get a file according to
+ * the options previously setup.
+ */
+
+static
+CURLcode scp_perform(struct connectdata *conn,
+                     bool *connected, bool *dophase_done)
+{
+  CURLcode result = CURLE_OK;
+
+  DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+  *dophase_done = FALSE;        /* not done yet */
+
+  /* start the first command in the DO phase */
+  state(conn, SSH_SCP_TRANS_INIT);
+
+  result = myssh_multi_statemach(conn, dophase_done);
+
+  *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+  if(*dophase_done) {
+    DEBUGF(infof(conn->data, "DO phase is complete\n"));
+  }
+
+  return result;
+}
+
+static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
+{
+  CURLcode result;
+  bool connected = 0;
+  struct Curl_easy *data = conn->data;
+  struct ssh_conn *sshc = &conn->proto.sshc;
+
+  *done = FALSE;                /* default to false */
+
+  data->req.size = -1;          /* make sure this is unknown at this point */
+
+  sshc->actualcode = CURLE_OK;  /* reset error code */
+  sshc->secondCreateDirs = 0;   /* reset the create dir attempt state
+                                   variable */
+
+  Curl_pgrsSetUploadCounter(data, 0);
+  Curl_pgrsSetDownloadCounter(data, 0);
+  Curl_pgrsSetUploadSize(data, -1);
+  Curl_pgrsSetDownloadSize(data, -1);
+
+  if(conn->handler->protocol & CURLPROTO_SCP)
+    result = scp_perform(conn, &connected, done);
+  else
+    result = sftp_perform(conn, &connected, done);
+
+  return result;
+}
+
+/* BLOCKING, but the function is using the state machine so the only reason
+   this is still blocking is that the multi interface code has no support for
+   disconnecting operations that takes a while */
+static CURLcode scp_disconnect(struct connectdata *conn,
+                               bool dead_connection)
+{
+  CURLcode result = CURLE_OK;
+  struct ssh_conn *ssh = &conn->proto.sshc;
+  (void) dead_connection;
+
+  if(ssh->ssh_session) {
+    /* only if there's a session still around to use! */
+
+    state(conn, SSH_SESSION_DISCONNECT);
+
+    result = myssh_block_statemach(conn, TRUE);
+  }
+
+  return result;
+}
+
+/* generic done function for both SCP and SFTP called from their specific
+   done functions */
+static CURLcode myssh_done(struct connectdata *conn, CURLcode status)
+{
+  CURLcode result = CURLE_OK;
+  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!
+     */
+    result = myssh_block_statemach(conn, FALSE);
+  }
+  else
+    result = status;
+
+  if(protop)
+    Curl_safefree(protop->path);
+  if(Curl_pgrsDone(conn))
+    return CURLE_ABORTED_BY_CALLBACK;
+
+  conn->data->req.keepon = 0;   /* clear all bits */
+  return result;
+}
+
+
+static CURLcode scp_done(struct connectdata *conn, CURLcode status,
+                         bool premature)
+{
+  (void) premature;             /* not used */
+
+  if(!status)
+    state(conn, SSH_SCP_DONE);
+
+  return myssh_done(conn, status);
+
+}
+
+static ssize_t scp_send(struct connectdata *conn, int sockindex,
+                        const void *mem, size_t len, CURLcode *err)
+{
+  int rc;
+  (void) sockindex; /* we only support SCP on the fixed known primary socket */
+  (void) err;
+
+  rc = ssh_scp_write(conn->proto.sshc.scp_session, mem, len);
+
+#if 0
+  /* The following code is misleading, mostly added as wishful thinking
+   * that libssh at some point will implement non-blocking ssh_scp_write/read.
+   * Currently rc can only be number of bytes read or SSH_ERROR. */
+  myssh_block2waitfor(conn, (rc == SSH_AGAIN) ? TRUE : FALSE);
+
+  if(rc == SSH_AGAIN) {
+    *err = CURLE_AGAIN;
+    return 0;
+  }
+  else
+#endif
+  if(rc != SSH_OK) {
+    *err = CURLE_SSH;
+    return -1;
+  }
+
+  return len;
+}
+
+static ssize_t scp_recv(struct connectdata *conn, int sockindex,
+                        char *mem, size_t len, CURLcode *err)
+{
+  ssize_t nread;
+  (void) err;
+  (void) sockindex; /* we only support SCP on the fixed known primary socket */
+
+  /* libssh returns int */
+  nread = ssh_scp_read(conn->proto.sshc.scp_session, mem, len);
+
+#if 0
+  /* The following code is misleading, mostly added as wishful thinking
+   * that libssh at some point will implement non-blocking ssh_scp_write/read.
+   * Currently rc can only be SSH_OK or SSH_ERROR. */
+
+  myssh_block2waitfor(conn, (nread == SSH_AGAIN) ? TRUE : FALSE);
+  if(nread == SSH_AGAIN) {
+    *err = CURLE_AGAIN;
+    nread = -1;
+  }
+#endif
+
+  return nread;
+}
+
+/*
+ * =============== SFTP ===============
+ */
+
+/*
+ ***********************************************************************
+ *
+ * sftp_perform()
+ *
+ * This is the actual DO function for SFTP. Get a file/directory according to
+ * the options previously setup.
+ */
+
+static
+CURLcode sftp_perform(struct connectdata *conn,
+                      bool *connected,
+                      bool *dophase_done)
+{
+  CURLcode result = CURLE_OK;
+
+  DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+  *dophase_done = FALSE; /* not done yet */
+
+  /* start the first command in the DO phase */
+  state(conn, SSH_SFTP_QUOTE_INIT);
+
+  /* run the state-machine */
+  result = myssh_multi_statemach(conn, dophase_done);
+
+  *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+  if(*dophase_done) {
+    DEBUGF(infof(conn->data, "DO phase is complete\n"));
+  }
+
+  return result;
+}
+
+/* called from multi.c while DOing */
+static CURLcode sftp_doing(struct connectdata *conn,
+                           bool *dophase_done)
+{
+  CURLcode result = myssh_multi_statemach(conn, dophase_done);
+  if(*dophase_done) {
+    DEBUGF(infof(conn->data, "DO phase is complete\n"));
+  }
+  return result;
+}
+
+/* BLOCKING, but the function is using the state machine so the only reason
+   this is still blocking is that the multi interface code has no support for
+   disconnecting operations that takes a while */
+static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+  CURLcode result = CURLE_OK;
+  (void) dead_connection;
+
+  DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+
+  if(conn->proto.sshc.ssh_session) {
+    /* only if there's a session still around to use! */
+    state(conn, SSH_SFTP_SHUTDOWN);
+    result = myssh_block_statemach(conn, TRUE);
+  }
+
+  DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+
+  return result;
+
+}
+
+static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
+                               bool premature)
+{
+  struct ssh_conn *sshc = &conn->proto.sshc;
+
+  if(!status) {
+    /* Post quote commands are executed after the SFTP_CLOSE state to avoid
+       errors that could happen due to open file handles during POSTQUOTE
+       operation */
+    if(!status && !premature && conn->data->set.postquote) {
+      sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
+      state(conn, SSH_SFTP_CLOSE);
+    }
+    else
+      state(conn, SSH_SFTP_CLOSE);
+  }
+  return myssh_done(conn, status);
+}
+
+/* return number of sent bytes */
+static ssize_t sftp_send(struct connectdata *conn, int sockindex,
+                         const void *mem, size_t len, CURLcode *err)
+{
+  ssize_t nwrite;
+  (void)sockindex;
+
+  nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
+
+  myssh_block2waitfor(conn, FALSE);
+
+#if 0 /* not returned by libssh on write */
+  if(nwrite == SSH_AGAIN) {
+    *err = CURLE_AGAIN;
+    nwrite = 0;
+  }
+  else
+#endif
+  if(nwrite < 0) {
+    *err = CURLE_SSH;
+    nwrite = -1;
+  }
+
+  return nwrite;
+}
+
+/*
+ * Return number of received (decrypted) bytes
+ * or <0 on error
+ */
+static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
+                         char *mem, size_t len, CURLcode *err)
+{
+  ssize_t nread;
+  (void)sockindex;
+
+  if(len >= (size_t)1<<32)
+    len = (size_t)(1<<31)-1;
+
+  switch(conn->proto.sshc.sftp_recv_state) {
+    case 0:
+      conn->proto.sshc.sftp_file_index =
+            sftp_async_read_begin(conn->proto.sshc.sftp_file,
+                                  (uint32_t)len);
+      if(conn->proto.sshc.sftp_file_index < 0) {
+        *err = CURLE_RECV_ERROR;
+        return -1;
+      }
+
+      /* fall-through */
+    case 1:
+      conn->proto.sshc.sftp_recv_state = 1;
+
+      nread = sftp_async_read(conn->proto.sshc.sftp_file,
+                              mem, (uint32_t)len,
+                              conn->proto.sshc.sftp_file_index);
+
+      myssh_block2waitfor(conn, (nread == SSH_AGAIN)?TRUE:FALSE);
+
+      if(nread == SSH_AGAIN) {
+        *err = CURLE_AGAIN;
+        return -1;
+      }
+      else if(nread < 0) {
+        *err = CURLE_RECV_ERROR;
+        return -1;
+      }
+
+      conn->proto.sshc.sftp_recv_state = 0;
+      return nread;
+
+    default:
+      /* we never reach here */
+      return -1;
+  }
+}
+
+static void sftp_quote(struct connectdata *conn)
+{
+  const char *cp;
+  struct Curl_easy *data = conn->data;
+  struct SSHPROTO *protop = data->req.protop;
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  CURLcode result;
+
+  /*
+   * Support some of the "FTP" commands
+   */
+  char *cmd = sshc->quote_item->data;
+  sshc->acceptfail = FALSE;
+
+  /* if a command starts with an asterisk, which a legal SFTP command never
+     can, the command will be allowed to fail without it causing any
+     aborts or cancels etc. It will cause libcurl to act as if the command
+     is successful, whatever the server reponds. */
+
+  if(cmd[0] == '*') {
+    cmd++;
+    sshc->acceptfail = TRUE;
+  }
+
+  if(strcasecompare("pwd", cmd)) {
+    /* output debug output if that is requested */
+    char *tmp = aprintf("257 \"%s\" is current directory.\n",
+                        protop->path);
+    if(!tmp) {
+      sshc->actualcode = CURLE_OUT_OF_MEMORY;
+      state(conn, SSH_SFTP_CLOSE);
+      sshc->nextstate = SSH_NO_STATE;
+      return;
+    }
+    if(data->set.verbose) {
+      Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4, conn);
+      Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
+    }
+    /* this sends an FTP-like "header" to the header callback so that the
+       current directory can be read very similar to how it is read when
+       using ordinary FTP. */
+    result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+    free(tmp);
+    if(result) {
+      state(conn, SSH_SFTP_CLOSE);
+      sshc->nextstate = SSH_NO_STATE;
+      sshc->actualcode = result;
+    }
+    else
+      state(conn, SSH_SFTP_NEXT_QUOTE);
+    return;
+  }
+
+  /*
+   * the arguments following the command must be separated from the
+   * command with a space so we can check for it unconditionally
+   */
+  cp = strchr(cmd, ' ');
+  if(cp == NULL) {
+    failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
+    state(conn, SSH_SFTP_CLOSE);
+    sshc->nextstate = SSH_NO_STATE;
+    sshc->actualcode = CURLE_QUOTE_ERROR;
+    return;
+  }
+
+  /*
+   * also, every command takes at least one argument so we get that
+   * first argument right now
+   */
+  result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
+  if(result) {
+    if(result == CURLE_OUT_OF_MEMORY)
+      failf(data, "Out of memory");
+    else
+      failf(data, "Syntax error: Bad first parameter");
+    state(conn, SSH_SFTP_CLOSE);
+    sshc->nextstate = SSH_NO_STATE;
+    sshc->actualcode = result;
+    return;
+  }
+
+  /*
+   * SFTP is a binary protocol, so we don't send text commands
+   * to the server. Instead, we scan for commands used by
+   * OpenSSH's sftp program and call the appropriate libssh
+   * functions.
+   */
+  if(strncasecompare(cmd, "chgrp ", 6) ||
+     strncasecompare(cmd, "chmod ", 6) ||
+     strncasecompare(cmd, "chown ", 6)) {
+    /* attribute change */
+
+    /* sshc->quote_path1 contains the mode to set */
+    /* get the destination */
+    result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
+    if(result) {
+      if(result == CURLE_OUT_OF_MEMORY)
+        failf(data, "Out of memory");
+      else
+        failf(data, "Syntax error in chgrp/chmod/chown: "
+              "Bad second parameter");
+      Curl_safefree(sshc->quote_path1);
+      state(conn, SSH_SFTP_CLOSE);
+      sshc->nextstate = SSH_NO_STATE;
+      sshc->actualcode = result;
+      return;
+    }
+    sshc->quote_attrs = NULL;
+    state(conn, SSH_SFTP_QUOTE_STAT);
+    return;
+  }
+  if(strncasecompare(cmd, "ln ", 3) ||
+     strncasecompare(cmd, "symlink ", 8)) {
+    /* symbolic linking */
+    /* sshc->quote_path1 is the source */
+    /* get the destination */
+    result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
+    if(result) {
+      if(result == CURLE_OUT_OF_MEMORY)
+        failf(data, "Out of memory");
+      else
+        failf(data, "Syntax error in ln/symlink: Bad second parameter");
+      Curl_safefree(sshc->quote_path1);
+      state(conn, SSH_SFTP_CLOSE);
+      sshc->nextstate = SSH_NO_STATE;
+      sshc->actualcode = result;
+      return;
+    }
+    state(conn, SSH_SFTP_QUOTE_SYMLINK);
+    return;
+  }
+  else if(strncasecompare(cmd, "mkdir ", 6)) {
+    /* create dir */
+    state(conn, SSH_SFTP_QUOTE_MKDIR);
+    return;
+  }
+  else if(strncasecompare(cmd, "rename ", 7)) {
+    /* rename file */
+    /* first param is the source path */
+    /* second param is the dest. path */
+    result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
+    if(result) {
+      if(result == CURLE_OUT_OF_MEMORY)
+        failf(data, "Out of memory");
+      else
+        failf(data, "Syntax error in rename: Bad second parameter");
+      Curl_safefree(sshc->quote_path1);
+      state(conn, SSH_SFTP_CLOSE);
+      sshc->nextstate = SSH_NO_STATE;
+      sshc->actualcode = result;
+      return;
+    }
+    state(conn, SSH_SFTP_QUOTE_RENAME);
+    return;
+  }
+  else if(strncasecompare(cmd, "rmdir ", 6)) {
+    /* delete dir */
+    state(conn, SSH_SFTP_QUOTE_RMDIR);
+    return;
+  }
+  else if(strncasecompare(cmd, "rm ", 3)) {
+    state(conn, SSH_SFTP_QUOTE_UNLINK);
+    return;
+  }
+#ifdef HAS_STATVFS_SUPPORT
+  else if(strncasecompare(cmd, "statvfs ", 8)) {
+    state(conn, SSH_SFTP_QUOTE_STATVFS);
+    return;
+  }
+#endif
+
+  failf(data, "Unknown SFTP command");
+  Curl_safefree(sshc->quote_path1);
+  Curl_safefree(sshc->quote_path2);
+  state(conn, SSH_SFTP_CLOSE);
+  sshc->nextstate = SSH_NO_STATE;
+  sshc->actualcode = CURLE_QUOTE_ERROR;
+}
+
+static void sftp_quote_stat(struct connectdata *conn)
+{
+  struct Curl_easy *data = conn->data;
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  char *cmd = sshc->quote_item->data;
+  sshc->acceptfail = FALSE;
+
+  /* if a command starts with an asterisk, which a legal SFTP command never
+     can, the command will be allowed to fail without it causing any
+     aborts or cancels etc. It will cause libcurl to act as if the command
+     is successful, whatever the server reponds. */
+
+  if(cmd[0] == '*') {
+    cmd++;
+    sshc->acceptfail = TRUE;
+  }
+
+  /* We read the file attributes, store them in sshc->quote_attrs
+   * and modify them accordingly to command. Then we switch to
+   * QUOTE_SETSTAT state to write new ones.
+   */
+
+  if(sshc->quote_attrs)
+    sftp_attributes_free(sshc->quote_attrs);
+  sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2);
+  if(sshc->quote_attrs == NULL) {
+    Curl_safefree(sshc->quote_path1);
+    Curl_safefree(sshc->quote_path2);
+    failf(data, "Attempt to get SFTP stats failed: %d",
+          sftp_get_error(sshc->sftp_session));
+    state(conn, SSH_SFTP_CLOSE);
+    sshc->nextstate = SSH_NO_STATE;
+    sshc->actualcode = CURLE_QUOTE_ERROR;
+    return;
+  }
+
+  /* Now set the new attributes... */
+  if(strncasecompare(cmd, "chgrp", 5)) {
+    sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
+    if(sshc->quote_attrs->gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+        !sshc->acceptfail) {
+      Curl_safefree(sshc->quote_path1);
+      Curl_safefree(sshc->quote_path2);
+      failf(data, "Syntax error: chgrp gid not a number");
+      state(conn, SSH_SFTP_CLOSE);
+      sshc->nextstate = SSH_NO_STATE;
+      sshc->actualcode = CURLE_QUOTE_ERROR;
+      return;
+    }
+    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
+  }
+  else if(strncasecompare(cmd, "chmod", 5)) {
+    mode_t perms;
+    perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8);
+    /* permissions are octal */
+    if(perms == 0 && !ISDIGIT(sshc->quote_path1[0])) {
+      Curl_safefree(sshc->quote_path1);
+      Curl_safefree(sshc->quote_path2);
+      failf(data, "Syntax error: chmod permissions not a number");
+      state(conn, SSH_SFTP_CLOSE);
+      sshc->nextstate = SSH_NO_STATE;
+      sshc->actualcode = CURLE_QUOTE_ERROR;
+      return;
+    }
+    sshc->quote_attrs->permissions = perms;
+    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
+  }
+  else if(strncasecompare(cmd, "chown", 5)) {
+    sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
+    if(sshc->quote_attrs->uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+        !sshc->acceptfail) {
+      Curl_safefree(sshc->quote_path1);
+      Curl_safefree(sshc->quote_path2);
+      failf(data, "Syntax error: chown uid not a number");
+      state(conn, SSH_SFTP_CLOSE);
+      sshc->nextstate = SSH_NO_STATE;
+      sshc->actualcode = CURLE_QUOTE_ERROR;
+      return;
+    }
+    sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
+  }
+
+  /* Now send the completed structure... */
+  state(conn, SSH_SFTP_QUOTE_SETSTAT);
+  return;
+}
+
+
+#endif                          /* USE_LIBSSH */
diff --git a/lib/ssh.c b/lib/ssh.c
index 5406bf0..a86ed70 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -26,9 +26,7 @@
 
 #ifdef USE_LIBSSH2
 
-#ifdef HAVE_LIMITS_H
-#  include <limits.h>
-#endif
+#include <limits.h>
 
 #include <libssh2.h>
 #include <libssh2_sftp.h>
@@ -87,21 +85,9 @@
 /* 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"
 
-#ifdef WIN32
-#  undef  PATH_MAX
-#  define PATH_MAX MAX_PATH
-#  ifndef R_OK
-#    define R_OK 4
-#  endif
-#endif
-
-#ifndef PATH_MAX
-#define PATH_MAX 1024 /* just an extra precaution since there are systems that
-                         have their definition hidden well */
-#endif
-
 #if LIBSSH2_VERSION_NUM >= 0x010206
 /* libssh2_sftp_statvfs and friends were added in 1.2.6 */
 #define HAS_STATVFS_SUPPORT 1
@@ -120,16 +106,10 @@ static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
 static LIBSSH2_FREE_FUNC(my_libssh2_free);
 
-static CURLcode get_pathname(const char **cpp, char **path);
-
 static CURLcode ssh_connect(struct connectdata *conn, bool *done);
 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
 static CURLcode ssh_do(struct connectdata *conn, bool *done);
 
-static CURLcode ssh_getworkingpath(struct connectdata *conn,
-                                   char *homedir, /* when SFTP is used */
-                                   char **path);
-
 static CURLcode scp_done(struct connectdata *conn,
                          CURLcode, bool premature);
 static CURLcode scp_doing(struct connectdata *conn,
@@ -279,6 +259,11 @@ static CURLcode libssh2_session_error_to_CURLE(int err)
     case LIBSSH2_ERROR_NONE:
       return CURLE_OK;
 
+    /* This is the error returned by libssh2_scp_recv2
+     * on unknown file */
+    case LIBSSH2_ERROR_SCP_PROTOCOL:
+      return CURLE_REMOTE_FILE_NOT_FOUND;
+
     case LIBSSH2_ERROR_SOCKET_NONE:
       return CURLE_COULDNT_CONNECT;
 
@@ -410,70 +395,6 @@ static void state(struct connectdata *conn, sshstate nowstate)
   sshc->state = nowstate;
 }
 
-/* figure out the path to work with in this particular request */
-static CURLcode ssh_getworkingpath(struct connectdata *conn,
-                                   char *homedir,  /* when SFTP is used */
-                                   char **path) /* returns the  allocated
-                                                   real path to work with */
-{
-  struct Curl_easy *data = conn->data;
-  char *real_path = NULL;
-  char *working_path;
-  size_t working_path_len;
-  CURLcode result =
-    Curl_urldecode(data, data->state.path, 0, &working_path,
-                   &working_path_len, FALSE);
-  if(result)
-    return result;
-
-  /* Check for /~/, indicating relative to the user's home directory */
-  if(conn->handler->protocol & CURLPROTO_SCP) {
-    real_path = malloc(working_path_len + 1);
-    if(real_path == NULL) {
-      free(working_path);
-      return CURLE_OUT_OF_MEMORY;
-    }
-    if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
-      /* It is referenced to the home directory, so strip the leading '/~/' */
-      memcpy(real_path, working_path + 3, 4 + working_path_len-3);
-    else
-      memcpy(real_path, working_path, 1 + working_path_len);
-  }
-  else if(conn->handler->protocol & CURLPROTO_SFTP) {
-    if((working_path_len > 1) && (working_path[1] == '~')) {
-      size_t homelen = strlen(homedir);
-      real_path = malloc(homelen + working_path_len + 1);
-      if(real_path == NULL) {
-        free(working_path);
-        return CURLE_OUT_OF_MEMORY;
-      }
-      /* It is referenced to the home directory, so strip the
-         leading '/' */
-      memcpy(real_path, homedir, homelen);
-      real_path[homelen] = '/';
-      real_path[homelen + 1] = '\0';
-      if(working_path_len > 3) {
-        memcpy(real_path + homelen + 1, working_path + 3,
-               1 + working_path_len -3);
-      }
-    }
-    else {
-      real_path = malloc(working_path_len + 1);
-      if(real_path == NULL) {
-        free(working_path);
-        return CURLE_OUT_OF_MEMORY;
-      }
-      memcpy(real_path, working_path, 1 + working_path_len);
-    }
-  }
-
-  free(working_path);
-
-  /* store the pointer for the caller to receive */
-  *path = real_path;
-
-  return CURLE_OK;
-}
 
 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
 static int sshkeycallback(struct Curl_easy *easy,
@@ -1034,11 +955,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
                                     sshc->sshagent_identity);
 
         if(rc < 0) {
-          if(rc != LIBSSH2_ERROR_EAGAIN)
+          if(rc != LIBSSH2_ERROR_EAGAIN) {
             /* tried and failed? go to next identity */
             sshc->sshagent_prev_identity = sshc->sshagent_identity;
-          else
-            break;
+          }
+          break;
         }
       }
 
@@ -1184,7 +1105,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
 
     case SSH_SFTP_QUOTE_INIT:
 
-      result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+      result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
       if(result) {
         sshc->actualcode = result;
         state(conn, SSH_STOP);
@@ -1219,6 +1140,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
 
       /*
        * Support some of the "FTP" commands
+       *
+       * 'sshc->quote_item' is already verified to be non-NULL before it
+       * switched to this state.
        */
       char *cmd = sshc->quote_item->data;
       sshc->acceptfail = FALSE;
@@ -1261,7 +1185,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           state(conn, SSH_SFTP_NEXT_QUOTE);
         break;
       }
-      if(cmd) {
+      {
         /*
          * the arguments following the command must be separated from the
          * command with a space so we can check for it unconditionally
@@ -1279,7 +1203,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
          * also, every command takes at least one argument so we get that
          * first argument right now
          */
-        result = get_pathname(&cp, &sshc->quote_path1);
+        result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
         if(result) {
           if(result == CURLE_OUT_OF_MEMORY)
             failf(data, "Out of memory");
@@ -1304,7 +1228,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
 
           /* sshc->quote_path1 contains the mode to set */
           /* get the destination */
-          result = get_pathname(&cp, &sshc->quote_path2);
+          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
           if(result) {
             if(result == CURLE_OUT_OF_MEMORY)
               failf(data, "Out of memory");
@@ -1326,7 +1250,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           /* symbolic linking */
           /* sshc->quote_path1 is the source */
           /* get the destination */
-          result = get_pathname(&cp, &sshc->quote_path2);
+          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
           if(result) {
             if(result == CURLE_OUT_OF_MEMORY)
               failf(data, "Out of memory");
@@ -1351,7 +1275,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           /* rename file */
           /* first param is the source path */
           /* second param is the dest. path */
-          result = get_pathname(&cp, &sshc->quote_path2);
+          result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
           if(result) {
             if(result == CURLE_OUT_OF_MEMORY)
               failf(data, "Out of memory");
@@ -1391,9 +1315,6 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         break;
       }
     }
-    if(!sshc->quote_item) {
-      state(conn, SSH_SFTP_GETINFO);
-    }
     break;
 
     case SSH_SFTP_NEXT_QUOTE:
@@ -2347,8 +2268,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         }
         sshc->sftp_handle = NULL;
       }
-      if(sftp_scp)
-        Curl_safefree(sftp_scp->path);
+
+      Curl_safefree(sftp_scp->path);
 
       DEBUGF(infof(data, "SFTP DONE done\n"));
 
@@ -2399,7 +2320,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       break;
 
     case SSH_SCP_TRANS_INIT:
-      result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+      result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
       if(result) {
         sshc->actualcode = result;
         state(conn, SSH_STOP);
@@ -2445,6 +2366,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         failf(conn->data, "%s", err_msg);
         state(conn, SSH_SCP_CHANNEL_FREE);
         sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
+        /* Map generic errors to upload failed */
+        if(sshc->actualcode == CURLE_SSH ||
+           sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND)
+          sshc->actualcode = CURLE_UPLOAD_FAILED;
         break;
       }
 
@@ -2833,8 +2758,8 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
 
   while((sshc->state != SSH_STOP) && !result) {
     bool block;
-    time_t left = 1000;
-    struct curltime now = Curl_tvnow();
+    timediff_t left = 1000;
+    struct curltime now = Curl_now();
 
     result = ssh_statemach_act(conn, &block);
     if(result)
@@ -3307,93 +3232,6 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
   return nread;
 }
 
-/* The get_pathname() function is being borrowed from OpenSSH sftp.c
-   version 4.6p1. */
-/*
- * Copyright (c) 2001-2004 Damien Miller <djm at openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-static CURLcode
-get_pathname(const char **cpp, char **path)
-{
-  const char *cp = *cpp, *end;
-  char quot;
-  unsigned int i, j;
-  static const char WHITESPACE[] = " \t\r\n";
-
-  cp += strspn(cp, WHITESPACE);
-  if(!*cp) {
-    *cpp = cp;
-    *path = NULL;
-    return CURLE_QUOTE_ERROR;
-  }
-
-  *path = malloc(strlen(cp) + 1);
-  if(*path == NULL)
-    return CURLE_OUT_OF_MEMORY;
-
-  /* Check for quoted filenames */
-  if(*cp == '\"' || *cp == '\'') {
-    quot = *cp++;
-
-    /* Search for terminating quote, unescape some chars */
-    for(i = j = 0; i <= strlen(cp); i++) {
-      if(cp[i] == quot) {  /* Found quote */
-        i++;
-        (*path)[j] = '\0';
-        break;
-      }
-      if(cp[i] == '\0') {  /* End of string */
-        /*error("Unterminated quote");*/
-        goto fail;
-      }
-      if(cp[i] == '\\') {  /* Escaped characters */
-        i++;
-        if(cp[i] != '\'' && cp[i] != '\"' &&
-            cp[i] != '\\') {
-          /*error("Bad escaped character '\\%c'",
-              cp[i]);*/
-          goto fail;
-        }
-      }
-      (*path)[j++] = cp[i];
-    }
-
-    if(j == 0) {
-      /*error("Empty quotes");*/
-      goto fail;
-    }
-    *cpp = cp + i + strspn(cp + i, WHITESPACE);
-  }
-  else {
-    /* Read to end of filename */
-    end = strpbrk(cp, WHITESPACE);
-    if(end == NULL)
-      end = strchr(cp, '\0');
-    *cpp = end + strspn(end, WHITESPACE);
-
-    memcpy(*path, cp, end - cp);
-    (*path)[end - cp] = '\0';
-  }
-  return CURLE_OK;
-
-  fail:
-  Curl_safefree(*path);
-  return CURLE_QUOTE_ERROR;
-}
-
-
 static const char *sftp_libssh2_strerror(int err)
 {
   switch(err) {
diff --git a/lib/ssh.h b/lib/ssh.h
index b350dcf..1c13550 100644
--- a/lib/ssh.h
+++ b/lib/ssh.h
@@ -24,9 +24,12 @@
 
 #include "curl_setup.h"
 
-#ifdef HAVE_LIBSSH2_H
+#if defined(HAVE_LIBSSH2_H)
 #include <libssh2.h>
 #include <libssh2_sftp.h>
+#elif defined(HAVE_LIBSSH_LIBSSH_H)
+#include <libssh/libssh.h>
+#include <libssh/sftp.h>
 #endif /* HAVE_LIBSSH2_H */
 
 /****************************************************************************
@@ -51,6 +54,7 @@ typedef enum {
   SSH_AUTH_HOST,
   SSH_AUTH_KEY_INIT,
   SSH_AUTH_KEY,
+  SSH_AUTH_GSSAPI,
   SSH_AUTH_DONE,
   SSH_SFTP_INIT,
   SSH_SFTP_REALPATH,   /* Last state in SSH-CONNECT */
@@ -86,6 +90,7 @@ typedef enum {
   SSH_SCP_TRANS_INIT, /* First state in SCP-DO */
   SSH_SCP_UPLOAD_INIT,
   SSH_SCP_DOWNLOAD_INIT,
+  SSH_SCP_DOWNLOAD,
   SSH_SCP_DONE,
   SSH_SCP_SEND_EOF,
   SSH_SCP_WAIT_EOF,
@@ -109,7 +114,8 @@ struct SSHPROTO {
    struct */
 struct ssh_conn {
   const char *authlist;       /* List of auth. methods, managed by libssh2 */
-#ifdef USE_LIBSSH2
+
+  /* common */
   const char *passphrase;     /* pass-phrase to use */
   char *rsa_pub;              /* path name */
   char *rsa;                  /* path name */
@@ -120,16 +126,11 @@ struct ssh_conn {
   struct curl_slist *quote_item; /* for the quote option */
   char *quote_path1;          /* two generic pointers for the QUOTE stuff */
   char *quote_path2;
-  LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
+
   bool acceptfail;            /* used by the SFTP_QUOTE (continue if
                                  quote command fails) */
   char *homedir;              /* when doing SFTP we figure out home dir in the
                                  connect phase */
-
-  /* Here's a set of struct members used by the SFTP_READDIR state */
-  LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
-  char *readdir_filename;
-  char *readdir_longentry;
   int readdir_len, readdir_totalLen, readdir_currLen;
   char *readdir_line;
   char *readdir_linkPath;
@@ -139,11 +140,42 @@ struct ssh_conn {
                                    second attempt has been made to change
                                    to/create a directory */
   char *slash_pos;              /* used by the SFTP_CREATE_DIRS state */
+
+  int orig_waitfor;             /* default READ/WRITE bits wait for */
+
+#if defined(USE_LIBSSH)
+/* our variables */
+  unsigned kbd_state; /* 0 or 1 */
+  ssh_key privkey;
+  ssh_key pubkey;
+  int auth_methods;
+  ssh_session ssh_session;
+  ssh_scp scp_session;
+  sftp_session sftp_session;
+  sftp_file sftp_file;
+  sftp_dir sftp_dir;
+
+  unsigned sftp_recv_state; /* 0 or 1 */
+  int sftp_file_index; /* for async read */
+  sftp_attributes readdir_attrs; /* used by the SFTP readdir actions */
+  sftp_attributes readdir_link_attrs; /* used by the SFTP readdir actions */
+  sftp_attributes quote_attrs; /* used by the SFTP_QUOTE state */
+
+  const char *readdir_filename; /* points within readdir_attrs */
+  const char *readdir_longentry;
+  char *readdir_tmp;
+#elif defined(USE_LIBSSH2)
+  char *readdir_filename;
+  char *readdir_longentry;
+
+  LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
+
+  /* Here's a set of struct members used by the SFTP_READDIR state */
+  LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
   LIBSSH2_SESSION *ssh_session; /* Secure Shell session */
   LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
   LIBSSH2_SFTP *sftp_session;   /* SFTP handle */
   LIBSSH2_SFTP_HANDLE *sftp_handle;
-  int orig_waitfor;             /* default READ/WRITE bits wait for */
 
 #ifdef HAVE_LIBSSH2_AGENT_API
   LIBSSH2_AGENT *ssh_agent;     /* proxy to ssh-agent/pageant */
@@ -156,10 +188,17 @@ struct ssh_conn {
 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
   LIBSSH2_KNOWNHOSTS *kh;
 #endif
-#endif /* USE_LIBSSH2 */
+#endif /* USE_LIBSSH */
 };
 
-#ifdef USE_LIBSSH2
+#if defined(USE_LIBSSH)
+
+#define CURL_LIBSSH_VERSION ssh_version(0)
+
+extern const struct Curl_handler Curl_handler_scp;
+extern const struct Curl_handler Curl_handler_sftp;
+
+#elif defined(USE_LIBSSH2)
 
 /* Feature detection based on version numbers to better work with
    non-configure platforms */
@@ -190,6 +229,14 @@ struct ssh_conn {
 #define HAVE_LIBSSH2_SESSION_HANDSHAKE 1
 #endif
 
+#ifdef HAVE_LIBSSH2_VERSION
+/* get it run-time if possible */
+#define CURL_LIBSSH2_VERSION libssh2_version(0)
+#else
+/* use build-time if run-time not possible */
+#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION
+#endif
+
 extern const struct Curl_handler Curl_handler_scp;
 extern const struct Curl_handler Curl_handler_sftp;
 
diff --git a/lib/strtoofft.c b/lib/strtoofft.c
index 807fc54..3636477 100644
--- a/lib/strtoofft.c
+++ b/lib/strtoofft.c
@@ -219,7 +219,10 @@ CURLofft curlx_strtoofft(const char *str, char **endp, int base,
   curl_off_t number;
   errno = 0;
   *num = 0; /* clear by default */
-  while(str && *str && ISSPACE(*str))
+
+  DEBUGASSERT(str);
+
+  while(*str && ISSPACE(*str))
     str++;
   if('-' == *str) {
     if(endp)
diff --git a/lib/strtoofft.h b/lib/strtoofft.h
index 244411a..be19cd7 100644
--- a/lib/strtoofft.h
+++ b/lib/strtoofft.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
@@ -40,14 +40,6 @@
  * of 'long' the conversion function to use is strtol().
  */
 
-#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))
-
 typedef enum {
   CURL_OFFT_OK,    /* parsed fine */
   CURL_OFFT_FLOW,  /* over or underflow */
diff --git a/lib/telnet.c b/lib/telnet.c
index a7bed3d..48b134e 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -1560,8 +1560,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
     }
 
     if(data->set.timeout) {
-      now = Curl_tvnow();
-      if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
+      now = Curl_now();
+      if(Curl_timediff(now, conn->created) >= data->set.timeout) {
         failf(data, "Time-out");
         result = CURLE_OPERATION_TIMEDOUT;
         keepon = FALSE;
@@ -1678,8 +1678,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
     } /* poll switch statement */
 
     if(data->set.timeout) {
-      now = Curl_tvnow();
-      if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
+      now = Curl_now();
+      if(Curl_timediff(now, conn->created) >= data->set.timeout) {
         failf(data, "Time-out");
         result = CURLE_OPERATION_TIMEDOUT;
         keepon = FALSE;
diff --git a/lib/tftp.c b/lib/tftp.c
index 4e599fd..20dc600 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -200,7 +200,7 @@ const struct Curl_handler Curl_handler_tftp = {
 static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
 {
   time_t maxtime, timeout;
-  time_t timeout_ms;
+  timediff_t timeout_ms;
   bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE;
 
   time(&state->start_time);
@@ -1293,7 +1293,7 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
     if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
     else
-      result = Curl_speedcheck(conn->data, Curl_tvnow());
+      result = Curl_speedcheck(conn->data, Curl_now());
   }
   return result;
 }
diff --git a/lib/timeval.c b/lib/timeval.c
index d7207b3..66f923a 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -24,7 +24,7 @@
 
 #if defined(WIN32) && !defined(MSDOS)
 
-struct curltime curlx_tvnow(void)
+struct curltime Curl_now(void)
 {
   /*
   ** GetTickCount() is available on _all_ Windows versions from W95 up
@@ -48,7 +48,7 @@ struct curltime curlx_tvnow(void)
 
 #elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
 
-struct curltime curlx_tvnow(void)
+struct curltime Curl_now(void)
 {
   /*
   ** clock_gettime() is granted to be increased monotonically when the
@@ -84,9 +84,40 @@ struct curltime curlx_tvnow(void)
   return cnow;
 }
 
+#elif defined(HAVE_MACH_ABSOLUTE_TIME)
+
+#include <stdint.h>
+#include <mach/mach_time.h>
+
+struct curltime Curl_now(void)
+{
+  /*
+  ** Monotonic timer on Mac OS is provided by mach_absolute_time(), which
+  ** returns time in Mach "absolute time units," which are platform-dependent.
+  ** To convert to nanoseconds, one must use conversion factors specified by
+  ** mach_timebase_info().
+  */
+  static mach_timebase_info_data_t timebase;
+  struct curltime cnow;
+  uint64_t usecs;
+
+  if(0 == timebase.denom)
+    (void) mach_timebase_info(&timebase);
+
+  usecs = mach_absolute_time();
+  usecs *= timebase.numer;
+  usecs /= timebase.denom;
+  usecs /= 1000;
+
+  cnow.tv_sec = usecs / 1000000;
+  cnow.tv_usec = usecs % 1000000;
+
+  return cnow;
+}
+
 #elif defined(HAVE_GETTIMEOFDAY)
 
-struct curltime curlx_tvnow(void)
+struct curltime Curl_now(void)
 {
   /*
   ** gettimeofday() is not granted to be increased monotonically, due to
@@ -103,7 +134,7 @@ struct curltime curlx_tvnow(void)
 
 #else
 
-struct curltime curlx_tvnow(void)
+struct curltime Curl_now(void)
 {
   /*
   ** time() returns the value of time in seconds since the Epoch.
@@ -116,47 +147,40 @@ struct curltime curlx_tvnow(void)
 
 #endif
 
+#if SIZEOF_TIME_T < 8
+#define TIME_MAX INT_MAX
+#define TIME_MIN INT_MIN
+#else
+#define TIME_MAX 9223372036854775807LL
+#define TIME_MIN -9223372036854775807LL
+#endif
+
 /*
- * Make sure that the first argument is the more recent time, as otherwise
- * we'll get a weird negative time-diff back...
- *
- * Returns: the time difference in number of milliseconds. For large diffs it
- * returns 0x7fffffff on 32bit time_t systems.
+ * Returns: time difference in number of milliseconds. For too large diffs it
+ * returns max value.
  *
  * @unittest: 1323
  */
-time_t curlx_tvdiff(struct curltime newer, struct curltime older)
+timediff_t Curl_timediff(struct curltime newer, struct curltime older)
 {
-#if SIZEOF_TIME_T < 8
-  /* for 32bit time_t systems, add a precaution to avoid overflow for really
-     big time differences */
-  time_t diff = newer.tv_sec-older.tv_sec;
-  if(diff >= (0x7fffffff/1000))
-    return 0x7fffffff;
-#endif
-  return (newer.tv_sec-older.tv_sec)*1000+
-    (int)(newer.tv_usec-older.tv_usec)/1000;
+  timediff_t diff = newer.tv_sec-older.tv_sec;
+  if(diff >= (TIME_MAX/1000))
+    return TIME_MAX;
+  else if(diff <= (TIME_MIN/1000))
+    return TIME_MIN;
+  return diff * 1000 + (newer.tv_usec-older.tv_usec)/1000;
 }
 
 /*
- * Make sure that the first argument is the more recent time, as otherwise
- * we'll get a weird negative time-diff back...
- *
- * Returns: the time difference in number of microseconds. For too large diffs
- * it returns max value.
+ * Returns: time difference in number of microseconds. For too large diffs it
+ * returns max value.
  */
-time_t Curl_tvdiff_us(struct curltime newer, struct curltime older)
+timediff_t Curl_timediff_us(struct curltime newer, struct curltime older)
 {
-  time_t diff = newer.tv_sec-older.tv_sec;
-#if SIZEOF_TIME_T < 8
-  /* for 32bit time_t systems */
-  if(diff >= (0x7fffffff/1000000))
-    return 0x7fffffff;
-#else
-  /* for 64bit time_t systems */
-  if(diff >= (0x7fffffffffffffffLL/1000000))
-    return 0x7fffffffffffffffLL;
-#endif
-  return (newer.tv_sec-older.tv_sec)*1000000+
-    (int)(newer.tv_usec-older.tv_usec);
+  timediff_t diff = newer.tv_sec-older.tv_sec;
+  if(diff >= (TIME_MAX/1000000))
+    return TIME_MAX;
+  else if(diff <= (TIME_MIN/1000000))
+    return TIME_MIN;
+  return diff * 1000000 + newer.tv_usec-older.tv_usec;
 }
diff --git a/lib/timeval.h b/lib/timeval.h
index 1ee4b30..fb3f680 100644
--- a/lib/timeval.h
+++ b/lib/timeval.h
@@ -22,19 +22,20 @@
  *
  ***************************************************************************/
 
-/*
- * CAUTION: this header is designed to work when included by the app-side
- * as well as the library. Do not mix with library internals!
- */
-
 #include "curl_setup.h"
 
+#if SIZEOF_TIME_T < 8
+typedef int timediff_t;
+#else
+typedef curl_off_t timediff_t;
+#endif
+
 struct curltime {
-  time_t       tv_sec;     /* seconds */
-  unsigned int tv_usec;    /* microseconds */
+  time_t tv_sec; /* seconds */
+  int tv_usec;   /* microseconds */
 };
 
-struct curltime curlx_tvnow(void);
+struct curltime Curl_now(void);
 
 /*
  * Make sure that the first argument (t1) is the more recent time and t2 is
@@ -42,7 +43,7 @@ struct curltime curlx_tvnow(void);
  *
  * Returns: the time difference in number of milliseconds.
  */
-time_t curlx_tvdiff(struct curltime t1, struct curltime t2);
+timediff_t Curl_timediff(struct curltime t1, struct curltime t2);
 
 /*
  * Make sure that the first argument (t1) is the more recent time and t2 is
@@ -50,12 +51,6 @@ time_t curlx_tvdiff(struct curltime t1, struct curltime t2);
  *
  * Returns: the time difference in number of microseconds.
  */
-time_t Curl_tvdiff_us(struct curltime newer, struct curltime older);
-
-/* These two defines below exist to provide the older API for library
-   internals only. */
-#define Curl_tvnow() curlx_tvnow()
-#define Curl_tvdiff(x,y) curlx_tvdiff(x,y)
+timediff_t Curl_timediff_us(struct curltime newer, struct curltime older);
 
 #endif /* HEADER_CURL_TIMEVAL_H */
-
diff --git a/lib/transfer.c b/lib/transfer.c
index 8e66d0d..8f15b1a 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -238,9 +238,11 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
     }
 #endif /* CURL_DOES_CONVERSIONS */
 
-    if((nread - hexlen) == 0)
+    if((nread - hexlen) == 0) {
       /* 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 += (int)strlen(endofline_native); /* for the added end of line */
   }
@@ -490,7 +492,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
       Curl_pgrsTime(data, TIMER_STARTTRANSFER);
       if(k->exp100 > EXP100_SEND_DATA)
         /* set time stamp to compare with when waiting for the 100 */
-        k->start100 = Curl_tvnow();
+        k->start100 = Curl_now();
     }
 
     *didwhat |= KEEP_RECV;
@@ -777,48 +779,19 @@ static CURLcode readwrite_data(struct Curl_easy *data,
              in http_chunks.c.
              Make sure that ALL_CONTENT_ENCODINGS contains all the
              encodings handled here. */
-#ifdef HAVE_LIBZ
-          switch(conn->data->set.http_ce_skip ?
-                 IDENTITY : k->auto_decoding) {
-          case IDENTITY:
-#endif
-            /* This is the default when the server sends no
-               Content-Encoding header. See Curl_readwrite_init; the
-               memset() call initializes k->auto_decoding to zero. */
+          if(conn->data->set.http_ce_skip || !k->writer_stack) {
             if(!k->ignorebody) {
-
 #ifndef CURL_DISABLE_POP3
-              if(conn->handler->protocol&PROTO_FAMILY_POP3)
+              if(conn->handler->protocol & PROTO_FAMILY_POP3)
                 result = Curl_pop3_write(conn, k->str, nread);
               else
 #endif /* CURL_DISABLE_POP3 */
-
                 result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str,
                                            nread);
             }
-#ifdef HAVE_LIBZ
-            break;
-
-          case DEFLATE:
-            /* Assume CLIENTWRITE_BODY; headers are not encoded. */
-            if(!k->ignorebody)
-              result = Curl_unencode_deflate_write(conn, k, nread);
-            break;
-
-          case GZIP:
-            /* Assume CLIENTWRITE_BODY; headers are not encoded. */
-            if(!k->ignorebody)
-              result = Curl_unencode_gzip_write(conn, k, nread);
-            break;
-
-          default:
-            failf(data, "Unrecognized content encoding type. "
-                  "libcurl understands `identity', `deflate' and `gzip' "
-                  "content encodings.");
-            result = CURLE_BAD_CONTENT_ENCODING;
-            break;
           }
-#endif
+          else
+            result = Curl_unencode_write(conn, k->writer_stack, k->str, nread);
         }
         k->badheader = HEADER_NORMAL; /* taken care of now */
 
@@ -925,7 +898,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
              go into the Expect: 100 state and await such a header */
           k->exp100 = EXP100_AWAITING_CONTINUE; /* wait for the header */
           k->keepon &= ~KEEP_SEND;         /* disable writing */
-          k->start100 = Curl_tvnow();       /* timeout count starts now */
+          k->start100 = Curl_now();       /* timeout count starts now */
           *didwhat &= ~KEEP_SEND;  /* we didn't write anything actually */
 
           /* set a timeout for the multi interface */
@@ -1046,7 +1019,8 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
 
     k->writebytecount += bytes_written;
 
-    if(k->writebytecount == data->state.infilesize) {
+    if((!k->upload_chunky || k->forbidchunk) &&
+       (k->writebytecount == data->state.infilesize)) {
       /* we have sent all data we were supposed to */
       k->upload_done = TRUE;
       infof(data, "We are completely uploaded and fine\n");
@@ -1150,7 +1124,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
       return result;
   }
 
-  k->now = Curl_tvnow();
+  k->now = Curl_now();
   if(didwhat) {
     /* Update read/write counters */
     if(k->bytecountp)
@@ -1174,7 +1148,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
 
       */
 
-      time_t ms = Curl_tvdiff(k->now, k->start100);
+      timediff_t ms = Curl_timediff(k->now, k->start100);
       if(ms >= data->set.expect_100_timeout) {
         /* we've waited long enough, continue anyway */
         k->exp100 = EXP100_SEND_DATA;
@@ -1198,13 +1172,14 @@ CURLcode Curl_readwrite(struct connectdata *conn,
         failf(data, "Operation timed out after %ld milliseconds with %"
               CURL_FORMAT_CURL_OFF_T " out of %"
               CURL_FORMAT_CURL_OFF_T " bytes received",
-              Curl_tvdiff(k->now, data->progress.t_startsingle), k->bytecount,
-              k->size);
+              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",
-              Curl_tvdiff(k->now, data->progress.t_startsingle), k->bytecount);
+              Curl_timediff(k->now, data->progress.t_startsingle),
+              k->bytecount);
       }
       return CURLE_OPERATION_TIMEDOUT;
     }
@@ -1343,6 +1318,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
   if(result)
     return result;
 
+  data->state.wildcardmatch = data->set.wildcard_enabled;
   data->set.followlocation = 0; /* reset the location-follow counter */
   data->state.this_is_a_follow = FALSE; /* reset this */
   data->state.errorbuf = FALSE; /* no error has occurred */
@@ -1400,7 +1376,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
     data->state.authhost.picked &= data->state.authhost.want;
     data->state.authproxy.picked &= data->state.authproxy.want;
 
-    if(data->set.wildcardmatch) {
+    if(data->state.wildcardmatch) {
       struct WildcardData *wc = &data->wildcard;
       if(wc->state < CURLWC_INIT) {
         result = Curl_wildcard_init(wc); /* init wildcard structures */
@@ -2049,7 +2025,7 @@ Curl_setup_transfer(
          (http->sending == HTTPSEND_BODY)) {
         /* wait with write until we either got 100-continue or a timeout */
         k->exp100 = EXP100_AWAITING_CONTINUE;
-        k->start100 = Curl_tvnow();
+        k->start100 = Curl_now();
 
         /* Set a timeout for the multi interface. Add the inaccuracy margin so
            that we don't fire slightly too early and get denied to run. */
diff --git a/lib/url.c b/lib/url.c
index 584635b..74813e8 100644
--- a/lib/url.c
+++ b/lib/url.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
@@ -55,9 +55,7 @@
 #error "We can't compile without socket() support!"
 #endif
 
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#endif
 
 #ifdef USE_LIBIDN2
 #include <idn2.h>
@@ -120,15 +118,13 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
 #include "pipeline.h"
 #include "dotdot.h"
 #include "strdup.h"
+#include "setopt.h"
+
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
 
-/* Local static prototypes */
-static struct connectdata *
-find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
-                                      struct connectbundle *bundle);
 static void conn_free(struct connectdata *conn);
 static void free_fixed_hostname(struct hostname *host);
 static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
@@ -136,15 +132,8 @@ static CURLcode parse_url_login(struct Curl_easy *data,
                                 struct connectdata *conn,
                                 char **userptr, char **passwdptr,
                                 char **optionsptr);
-static CURLcode parse_login_details(const char *login, const size_t len,
-                                    char **userptr, char **passwdptr,
-                                    char **optionsptr);
 static unsigned int get_protocol_family(unsigned int protocol);
 
-#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
-#define READBUFFER_MAX  CURL_MAX_READ_SIZE
-#define READBUFFER_MIN  1024
-
 /* Some parts of the code (e.g. chunked encoding) assume this buffer has at
  * more than just a few bytes to play with. Don't let it become too small or
  * bad things will happen.
@@ -201,8 +190,11 @@ static const struct Curl_handler * const protocols[] = {
   &Curl_handler_tftp,
 #endif
 
-#ifdef USE_LIBSSH2
+#if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
   &Curl_handler_scp,
+#endif
+
+#if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
   &Curl_handler_sftp,
 #endif
 
@@ -299,98 +291,8 @@ void Curl_freeset(struct Curl_easy *data)
     data->change.url_alloc = FALSE;
   }
   data->change.url = NULL;
-}
-
-static CURLcode setstropt(char **charp, const char *s)
-{
-  /* Release the previous storage at `charp' and replace by a dynamic storage
-     copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
-
-  Curl_safefree(*charp);
-
-  if(s) {
-    char *str = strdup(s);
-
-    if(!str)
-      return CURLE_OUT_OF_MEMORY;
-
-    *charp = str;
-  }
-
-  return CURLE_OK;
-}
-
-static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
-{
-  CURLcode result = CURLE_OK;
-  char *user = NULL;
-  char *passwd = NULL;
-
-  /* Parse the login details if specified. It not then we treat NULL as a hint
-     to clear the existing data */
-  if(option) {
-    result = parse_login_details(option, strlen(option),
-                                 (userp ? &user : NULL),
-                                 (passwdp ? &passwd : NULL),
-                                 NULL);
-  }
-
-  if(!result) {
-    /* Store the username part of option if required */
-    if(userp) {
-      if(!user && option && option[0] == ':') {
-        /* Allocate an empty string instead of returning NULL as user name */
-        user = strdup("");
-        if(!user)
-          result = CURLE_OUT_OF_MEMORY;
-      }
-
-      Curl_safefree(*userp);
-      *userp = user;
-    }
-
-    /* Store the password part of option if required */
-    if(passwdp) {
-      Curl_safefree(*passwdp);
-      *passwdp = passwd;
-    }
-  }
-
-  return result;
-}
-
-CURLcode Curl_dupset(struct Curl_easy *dst, struct Curl_easy *src)
-{
-  CURLcode result = CURLE_OK;
-  enum dupstring i;
-
-  /* Copy src->set into dst->set first, then deal with the strings
-     afterwards */
-  dst->set = src->set;
-
-  /* clear all string pointers first */
-  memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
-
-  /* duplicate all strings */
-  for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
-    result = setstropt(&dst->set.str[i], src->set.str[i]);
-    if(result)
-      return result;
-  }
-
-  /* duplicate memory areas pointed to */
-  i = STRING_COPYPOSTFIELDS;
-  if(src->set.postfieldsize && src->set.str[i]) {
-    /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
-    dst->set.str[i] = Curl_memdup(src->set.str[i],
-                                  curlx_sotouz(src->set.postfieldsize));
-    if(!dst->set.str[i])
-      return CURLE_OUT_OF_MEMORY;
-    /* point to the new copy */
-    dst->set.postfields = dst->set.str[i];
-  }
 
-  return CURLE_OK;
+  Curl_mime_cleanpart(&data->set.mimepost);
 }
 
 /*
@@ -480,8 +382,6 @@ CURLcode Curl_close(struct Curl_easy *data)
   Curl_http2_cleanup_dependencies(data);
   Curl_convert_close(data);
 
-  Curl_mime_cleanpart(&data->set.mimepost);
-
   /* No longer a dirty share, if it exists */
   if(data->share) {
     Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
@@ -489,12 +389,8 @@ CURLcode Curl_close(struct Curl_easy *data)
     Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
   }
 
-  if(data->set.wildcardmatch) {
-    /* destruct wildcard structures if it is needed */
-    struct WildcardData *wc = &data->wildcard;
-    Curl_wildcard_dtor(wc);
-  }
-
+  /* destruct wildcard structures if it is needed */
+  Curl_wildcard_dtor(&data->wildcard);
   Curl_freeset(data);
   free(data);
   return CURLE_OK;
@@ -504,8 +400,9 @@ CURLcode Curl_close(struct Curl_easy *data)
  * Initialize the UserDefined fields within a Curl_easy.
  * This may be safely called on a new or existing Curl_easy.
  */
-CURLcode Curl_init_userdefined(struct UserDefined *set)
+CURLcode Curl_init_userdefined(struct Curl_easy *data)
 {
+  struct UserDefined *set = &data->set;
   CURLcode result = CURLE_OK;
 
   set->out = stdout; /* default output to stdout */
@@ -555,6 +452,8 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
   /* make libcurl quiet by default: */
   set->hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */
 
+  Curl_mime_initpart(&set->mimepost, data);
+
   /*
    * libcurl 7.10 introduced SSL verification *by default*! This needs to be
    * switched off unless wanted.
@@ -591,25 +490,25 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
 
   /* This is our preferred CA cert bundle/path since install time */
 #if defined(CURL_CA_BUNDLE)
-  result = setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
+  result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
   if(result)
     return result;
 
-  result = setstropt(&set->str[STRING_SSL_CAFILE_PROXY], CURL_CA_BUNDLE);
+  result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY], CURL_CA_BUNDLE);
   if(result)
     return result;
 #endif
 #if defined(CURL_CA_PATH)
-  result = setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
+  result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
   if(result)
     return result;
 
-  result = setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
+  result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
   if(result)
     return result;
 #endif
 
-  set->wildcardmatch  = FALSE;
+  set->wildcard_enabled = FALSE;
   set->chunk_bgn      = ZERO_NULL;
   set->chunk_end      = ZERO_NULL;
 
@@ -644,2333 +543,67 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
 CURLcode Curl_open(struct Curl_easy **curl)
 {
   CURLcode result;
-  struct Curl_easy *data;
-
-  /* Very simple start-up: alloc the struct, init it with zeroes and return */
-  data = calloc(1, sizeof(struct Curl_easy));
-  if(!data) {
-    /* this is a very serious error */
-    DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
-    return CURLE_OUT_OF_MEMORY;
-  }
-
-  data->magic = CURLEASY_MAGIC_NUMBER;
-
-  result = Curl_resolver_init(&data->state.resolver);
-  if(result) {
-    DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
-    free(data);
-    return result;
-  }
-
-  /* We do some initial setup here, all those fields that can't be just 0 */
-
-  data->state.buffer = malloc(READBUFFER_SIZE + 1);
-  if(!data->state.buffer) {
-    DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n"));
-    result = CURLE_OUT_OF_MEMORY;
-  }
-
-  Curl_mime_initpart(&data->set.mimepost, data);
-
-  data->state.headerbuff = malloc(HEADERSIZE);
-  if(!data->state.headerbuff) {
-    DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
-    result = CURLE_OUT_OF_MEMORY;
-  }
-  else {
-    result = Curl_init_userdefined(&data->set);
-
-    data->state.headersize = HEADERSIZE;
-
-    Curl_convert_init(data);
-
-    Curl_initinfo(data);
-
-    /* most recent connection is not yet defined */
-    data->state.lastconnect = NULL;
-
-    data->progress.flags |= PGRS_HIDE;
-    data->state.current_speed = -1; /* init to negative == impossible */
-    data->set.fnmatch = ZERO_NULL;
-    data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
-
-    Curl_http2_init_state(&data->state);
-  }
-
-  if(result) {
-    Curl_resolver_cleanup(data->state.resolver);
-    free(data->state.buffer);
-    free(data->state.headerbuff);
-    Curl_freeset(data);
-    free(data);
-    data = NULL;
-  }
-  else
-    *curl = data;
-
-  return result;
-}
-
-#define C_SSLVERSION_VALUE(x) (x & 0xffff)
-#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
-
-CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
-                     va_list param)
-{
-  char *argptr;
-  CURLcode result = CURLE_OK;
-  long arg;
-#ifndef CURL_DISABLE_HTTP
-  curl_off_t bigsize;
-#endif
-
-  switch(option) {
-  case CURLOPT_DNS_CACHE_TIMEOUT:
-    data->set.dns_cache_timeout = va_arg(param, long);
-    break;
-  case CURLOPT_DNS_USE_GLOBAL_CACHE:
-    /* remember we want this enabled */
-    arg = va_arg(param, long);
-    data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
-    break;
-  case CURLOPT_SSL_CIPHER_LIST:
-    /* set a list of cipher we want to use in the SSL connection */
-    result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_SSL_CIPHER_LIST:
-    /* set a list of cipher we want to use in the SSL connection for proxy */
-    result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_RANDOM_FILE:
-    /*
-     * This is the path name to a file that contains random data to seed
-     * the random SSL stuff with. The file is only used for reading.
-     */
-    result = setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_EGDSOCKET:
-    /*
-     * The Entropy Gathering Daemon socket pathname
-     */
-    result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_MAXCONNECTS:
-    /*
-     * Set the absolute number of maximum simultaneous alive connection that
-     * libcurl is allowed to have.
-     */
-    data->set.maxconnects = va_arg(param, long);
-    break;
-  case CURLOPT_FORBID_REUSE:
-    /*
-     * When this transfer is done, it must not be left to be reused by a
-     * subsequent transfer but shall be closed immediately.
-     */
-    data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_FRESH_CONNECT:
-    /*
-     * This transfer shall not use a previously cached connection but
-     * should be made with a fresh new connect!
-     */
-    data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_VERBOSE:
-    /*
-     * Verbose means infof() calls that give a lot of information about
-     * the connection and transfer procedures as well as internal choices.
-     */
-    data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_HEADER:
-    /*
-     * Set to include the header in the general data output stream.
-     */
-    data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_NOPROGRESS:
-    /*
-     * Shut off the internal supported progress meter
-     */
-    data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    if(data->set.hide_progress)
-      data->progress.flags |= PGRS_HIDE;
-    else
-      data->progress.flags &= ~PGRS_HIDE;
-    break;
-  case CURLOPT_NOBODY:
-    /*
-     * Do not include the body part in the output data stream.
-     */
-    data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_FAILONERROR:
-    /*
-     * Don't output the >=400 error code HTML-page, but instead only
-     * return error.
-     */
-    data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_KEEP_SENDING_ON_ERROR:
-    data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
-                                           TRUE : FALSE;
-    break;
-  case CURLOPT_UPLOAD:
-  case CURLOPT_PUT:
-    /*
-     * We want to sent data to the remote host. If this is HTTP, that equals
-     * using the PUT request.
-     */
-    data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    if(data->set.upload) {
-      /* If this is HTTP, PUT is what's needed to "upload" */
-      data->set.httpreq = HTTPREQ_PUT;
-      data->set.opt_no_body = FALSE; /* this is implied */
-    }
-    else
-      /* In HTTP, the opposite of upload is GET (unless NOBODY is true as
-         then this can be changed to HEAD later on) */
-      data->set.httpreq = HTTPREQ_GET;
-    break;
-  case CURLOPT_REQUEST_TARGET:
-    result = setstropt(&data->set.str[STRING_TARGET],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_FILETIME:
-    /*
-     * Try to get the file time of the remote document. The time will
-     * later (possibly) become available using curl_easy_getinfo().
-     */
-    data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_FTP_CREATE_MISSING_DIRS:
-    /*
-     * An FTP option that modifies an upload to create missing directories on
-     * the server.
-     */
-    switch(va_arg(param, long)) {
-    case 0:
-      data->set.ftp_create_missing_dirs = 0;
-      break;
-    case 1:
-      data->set.ftp_create_missing_dirs = 1;
-      break;
-    case 2:
-      data->set.ftp_create_missing_dirs = 2;
-      break;
-    default:
-      /* reserve other values for future use */
-      result = CURLE_UNKNOWN_OPTION;
-      break;
-    }
-    break;
-  case CURLOPT_SERVER_RESPONSE_TIMEOUT:
-    /*
-     * Option that specifies how quickly an server response must be obtained
-     * before it is considered failure. For pingpong protocols.
-     */
-    data->set.server_response_timeout = va_arg(param, long) * 1000;
-    break;
-  case CURLOPT_TFTP_NO_OPTIONS:
-    /*
-     * Option that prevents libcurl from sending TFTP option requests to the
-     * server.
-     */
-    data->set.tftp_no_options = va_arg(param, long) != 0;
-    break;
-  case CURLOPT_TFTP_BLKSIZE:
-    /*
-     * TFTP option that specifies the block size to use for data transmission.
-     */
-    data->set.tftp_blksize = va_arg(param, long);
-    break;
-  case CURLOPT_DIRLISTONLY:
-    /*
-     * An option that changes the command to one that asks for a list
-     * only, no file info details.
-     */
-    data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_APPEND:
-    /*
-     * We want to upload and append to an existing file.
-     */
-    data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_FTP_FILEMETHOD:
-    /*
-     * How do access files over FTP.
-     */
-    data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long);
-    break;
-  case CURLOPT_NETRC:
-    /*
-     * Parse the $HOME/.netrc file
-     */
-    data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
-    break;
-  case CURLOPT_NETRC_FILE:
-    /*
-     * Use this file instead of the $HOME/.netrc file
-     */
-    result = setstropt(&data->set.str[STRING_NETRC_FILE],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_TRANSFERTEXT:
-    /*
-     * This option was previously named 'FTPASCII'. Renamed to work with
-     * more protocols than merely FTP.
-     *
-     * Transfer using ASCII (instead of BINARY).
-     */
-    data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_TIMECONDITION:
-    /*
-     * Set HTTP time condition. This must be one of the defines in the
-     * curl/curl.h header file.
-     */
-    data->set.timecondition = (curl_TimeCond)va_arg(param, long);
-    break;
-  case CURLOPT_TIMEVALUE:
-    /*
-     * This is the value to compare with the remote document with the
-     * method set with CURLOPT_TIMECONDITION
-     */
-    data->set.timevalue = (time_t)va_arg(param, long);
-    break;
-  case CURLOPT_SSLVERSION:
-    /*
-     * Set explicit SSL version to try to connect with, as some SSL
-     * implementations are lame.
-     */
-#ifdef USE_SSL
-    arg = va_arg(param, long);
-    data->set.ssl.primary.version = C_SSLVERSION_VALUE(arg);
-    data->set.ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg);
-#else
-    result = CURLE_UNKNOWN_OPTION;
-#endif
-    break;
-  case CURLOPT_PROXY_SSLVERSION:
-    /*
-     * Set explicit SSL version to try to connect with for proxy, as some SSL
-     * implementations are lame.
-     */
-#ifdef USE_SSL
-    arg = va_arg(param, long);
-    data->set.proxy_ssl.primary.version = C_SSLVERSION_VALUE(arg);
-    data->set.proxy_ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg);
-#else
-    result = CURLE_UNKNOWN_OPTION;
-#endif
-    break;
-
-#ifndef CURL_DISABLE_HTTP
-  case CURLOPT_AUTOREFERER:
-    /*
-     * Switch on automatic referer that gets set if curl follows locations.
-     */
-    data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_ACCEPT_ENCODING:
-    /*
-     * String to use at the value of Accept-Encoding header.
-     *
-     * If the encoding is set to "" we use an Accept-Encoding header that
-     * encompasses all the encodings we support.
-     * If the encoding is set to NULL we don't send an Accept-Encoding header
-     * and ignore an received Content-Encoding header.
-     *
-     */
-    argptr = va_arg(param, char *);
-    result = setstropt(&data->set.str[STRING_ENCODING],
-                       (argptr && !*argptr)?
-                       ALL_CONTENT_ENCODINGS: argptr);
-    break;
-
-  case CURLOPT_TRANSFER_ENCODING:
-    data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
-                                       TRUE : FALSE;
-    break;
-
-  case CURLOPT_FOLLOWLOCATION:
-    /*
-     * Follow Location: header hints on a HTTP-server.
-     */
-    data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_UNRESTRICTED_AUTH:
-    /*
-     * Send authentication (user+password) when following locations, even when
-     * hostname changed.
-     */
-    data->set.http_disable_hostname_check_before_authentication =
-      (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_MAXREDIRS:
-    /*
-     * The maximum amount of hops you allow curl to follow Location:
-     * headers. This should mostly be used to detect never-ending loops.
-     */
-    data->set.maxredirs = va_arg(param, long);
-    break;
-
-  case CURLOPT_POSTREDIR:
-  {
-    /*
-     * Set the behaviour of POST when redirecting
-     * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
-     * CURL_REDIR_POST_301 - POST is kept as POST after 301
-     * CURL_REDIR_POST_302 - POST is kept as POST after 302
-     * CURL_REDIR_POST_303 - POST is kept as POST after 303
-     * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
-     * other - POST is kept as POST after 301 and 302
-     */
-    arg = va_arg(param, long);
-    data->set.keep_post = arg & CURL_REDIR_POST_ALL;
-  }
-  break;
-
-  case CURLOPT_POST:
-    /* Does this option serve a purpose anymore? Yes it does, when
-       CURLOPT_POSTFIELDS isn't used and the POST data is read off the
-       callback! */
-    if(va_arg(param, long)) {
-      data->set.httpreq = HTTPREQ_POST;
-      data->set.opt_no_body = FALSE; /* this is implied */
-    }
-    else
-      data->set.httpreq = HTTPREQ_GET;
-    break;
-
-  case CURLOPT_COPYPOSTFIELDS:
-    /*
-     * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
-     * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
-     *  CURLOPT_COPYPOSTFIELDS and not altered later.
-     */
-    argptr = va_arg(param, char *);
-
-    if(!argptr || data->set.postfieldsize == -1)
-      result = setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
-    else {
-      /*
-       *  Check that requested length does not overflow the size_t type.
-       */
-
-      if((data->set.postfieldsize < 0) ||
-         ((sizeof(curl_off_t) != sizeof(size_t)) &&
-          (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
-        result = CURLE_OUT_OF_MEMORY;
-      else {
-        char *p;
-
-        (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
-
-        /* Allocate even when size == 0. This satisfies the need of possible
-           later address compare to detect the COPYPOSTFIELDS mode, and
-           to mark that postfields is used rather than read function or
-           form data.
-        */
-        p = malloc((size_t)(data->set.postfieldsize?
-                            data->set.postfieldsize:1));
-
-        if(!p)
-          result = CURLE_OUT_OF_MEMORY;
-        else {
-          if(data->set.postfieldsize)
-            memcpy(p, argptr, (size_t)data->set.postfieldsize);
-
-          data->set.str[STRING_COPYPOSTFIELDS] = p;
-        }
-      }
-    }
-
-    data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
-    data->set.httpreq = HTTPREQ_POST;
-    break;
-
-  case CURLOPT_POSTFIELDS:
-    /*
-     * Like above, but use static data instead of copying it.
-     */
-    data->set.postfields = va_arg(param, void *);
-    /* Release old copied data. */
-    (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
-    data->set.httpreq = HTTPREQ_POST;
-    break;
-
-  case CURLOPT_POSTFIELDSIZE:
-    /*
-     * The size of the POSTFIELD data to prevent libcurl to do strlen() to
-     * figure it out. Enables binary posts.
-     */
-    bigsize = va_arg(param, long);
-
-    if(data->set.postfieldsize < bigsize &&
-       data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
-      /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
-      (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
-      data->set.postfields = NULL;
-    }
-
-    data->set.postfieldsize = bigsize;
-    break;
-
-  case CURLOPT_POSTFIELDSIZE_LARGE:
-    /*
-     * The size of the POSTFIELD data to prevent libcurl to do strlen() to
-     * figure it out. Enables binary posts.
-     */
-    bigsize = va_arg(param, curl_off_t);
-
-    if(data->set.postfieldsize < bigsize &&
-       data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
-      /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
-      (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
-      data->set.postfields = NULL;
-    }
-
-    data->set.postfieldsize = bigsize;
-    break;
-
-  case CURLOPT_HTTPPOST:
-    /*
-     * Set to make us do HTTP POST
-     */
-    data->set.httppost = va_arg(param, struct curl_httppost *);
-    data->set.httpreq = HTTPREQ_POST_FORM;
-    data->set.opt_no_body = FALSE; /* this is implied */
-    break;
-#endif   /* CURL_DISABLE_HTTP */
-
-  case CURLOPT_MIMEPOST:
-    /*
-     * Set to make us do MIME/form POST
-     */
-    result = curl_mime_subparts(&data->set.mimepost,
-                                va_arg(param, curl_mime *));
-    if(!result) {
-      data->set.mimepost.freefunc = NULL; /* Avoid free upon easy cleanup. */
-      data->set.httpreq = HTTPREQ_POST_MIME;
-      data->set.opt_no_body = FALSE; /* this is implied */
-    }
-    break;
-
-  case CURLOPT_REFERER:
-    /*
-     * String to set in the HTTP Referer: field.
-     */
-    if(data->change.referer_alloc) {
-      Curl_safefree(data->change.referer);
-      data->change.referer_alloc = FALSE;
-    }
-    result = setstropt(&data->set.str[STRING_SET_REFERER],
-                       va_arg(param, char *));
-    data->change.referer = data->set.str[STRING_SET_REFERER];
-    break;
-
-  case CURLOPT_USERAGENT:
-    /*
-     * String to use in the HTTP User-Agent field
-     */
-    result = setstropt(&data->set.str[STRING_USERAGENT],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_HTTPHEADER:
-    /*
-     * Set a list with HTTP headers to use (or replace internals with)
-     */
-    data->set.headers = va_arg(param, struct curl_slist *);
-    break;
-
-#ifndef CURL_DISABLE_HTTP
-  case CURLOPT_PROXYHEADER:
-    /*
-     * Set a list with proxy headers to use (or replace internals with)
-     *
-     * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
-     * long time we remain doing it this way until CURLOPT_PROXYHEADER is
-     * used. As soon as this option has been used, if set to anything but
-     * NULL, custom headers for proxies are only picked from this list.
-     *
-     * Set this option to NULL to restore the previous behavior.
-     */
-    data->set.proxyheaders = va_arg(param, struct curl_slist *);
-    break;
-
-  case CURLOPT_HEADEROPT:
-    /*
-     * Set header option.
-     */
-    arg = va_arg(param, long);
-    data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
-    break;
-
-  case CURLOPT_HTTP200ALIASES:
-    /*
-     * Set a list of aliases for HTTP 200 in response header
-     */
-    data->set.http200aliases = va_arg(param, struct curl_slist *);
-    break;
-
-#if !defined(CURL_DISABLE_COOKIES)
-  case CURLOPT_COOKIE:
-    /*
-     * Cookie string to send to the remote server in the request.
-     */
-    result = setstropt(&data->set.str[STRING_COOKIE],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_COOKIEFILE:
-    /*
-     * Set cookie file to read and parse. Can be used multiple times.
-     */
-    argptr = (char *)va_arg(param, void *);
-    if(argptr) {
-      struct curl_slist *cl;
-      /* append the cookie file name to the list of file names, and deal with
-         them later */
-      cl = curl_slist_append(data->change.cookielist, argptr);
-      if(!cl) {
-        curl_slist_free_all(data->change.cookielist);
-        data->change.cookielist = NULL;
-        return CURLE_OUT_OF_MEMORY;
-      }
-      data->change.cookielist = cl; /* store the list for later use */
-    }
-    break;
-
-  case CURLOPT_COOKIEJAR:
-    /*
-     * Set cookie file name to dump all cookies to when we're done.
-     */
-  {
-    struct CookieInfo *newcookies;
-    result = setstropt(&data->set.str[STRING_COOKIEJAR],
-                       va_arg(param, char *));
-
-    /*
-     * Activate the cookie parser. This may or may not already
-     * have been made.
-     */
-    newcookies = Curl_cookie_init(data, NULL, data->cookies,
-                                  data->set.cookiesession);
-    if(!newcookies)
-      result = CURLE_OUT_OF_MEMORY;
-    data->cookies = newcookies;
-  }
-    break;
-
-  case CURLOPT_COOKIESESSION:
-    /*
-     * Set this option to TRUE to start a new "cookie session". It will
-     * prevent the forthcoming read-cookies-from-file actions to accept
-     * cookies that are marked as being session cookies, as they belong to a
-     * previous session.
-     *
-     * In the original Netscape cookie spec, "session cookies" are cookies
-     * with no expire date set. RFC2109 describes the same action if no
-     * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
-     * a 'Discard' action that can enforce the discard even for cookies that
-     * have a Max-Age.
-     *
-     * We run mostly with the original cookie spec, as hardly anyone implements
-     * anything else.
-     */
-    data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_COOKIELIST:
-    argptr = va_arg(param, char *);
-
-    if(argptr == NULL)
-      break;
-
-    if(strcasecompare(argptr, "ALL")) {
-      /* clear all cookies */
-      Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
-      Curl_cookie_clearall(data->cookies);
-      Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
-    }
-    else if(strcasecompare(argptr, "SESS")) {
-      /* clear session cookies */
-      Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
-      Curl_cookie_clearsess(data->cookies);
-      Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
-    }
-    else if(strcasecompare(argptr, "FLUSH")) {
-      /* flush cookies to file, takes care of the locking */
-      Curl_flush_cookies(data, 0);
-    }
-    else if(strcasecompare(argptr, "RELOAD")) {
-      /* reload cookies from file */
-      Curl_cookie_loadfiles(data);
-      break;
-    }
-    else {
-      if(!data->cookies)
-        /* if cookie engine was not running, activate it */
-        data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
-
-      argptr = strdup(argptr);
-      if(!argptr || !data->cookies) {
-        result = CURLE_OUT_OF_MEMORY;
-        free(argptr);
-      }
-      else {
-        Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
-
-        if(checkprefix("Set-Cookie:", argptr))
-          /* HTTP Header format line */
-          Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
-
-        else
-          /* Netscape format line */
-          Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
-
-        Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
-        free(argptr);
-      }
-    }
-
-    break;
-#endif /* !CURL_DISABLE_COOKIES */
-
-  case CURLOPT_HTTPGET:
-    /*
-     * Set to force us do HTTP GET
-     */
-    if(va_arg(param, long)) {
-      data->set.httpreq = HTTPREQ_GET;
-      data->set.upload = FALSE; /* switch off upload */
-      data->set.opt_no_body = FALSE; /* this is implied */
-    }
-    break;
-
-  case CURLOPT_HTTP_VERSION:
-    /*
-     * This sets a requested HTTP version to be used. The value is one of
-     * the listed enums in curl/curl.h.
-     */
-    arg = va_arg(param, long);
-#ifndef USE_NGHTTP2
-    if(arg >= CURL_HTTP_VERSION_2)
-      return CURLE_UNSUPPORTED_PROTOCOL;
-#endif
-    data->set.httpversion = arg;
-    break;
-
-  case CURLOPT_EXPECT_100_TIMEOUT_MS:
-    /*
-     * Time to wait for a response to a HTTP request containing an
-     * Expect: 100-continue header before sending the data anyway.
-     */
-    data->set.expect_100_timeout = va_arg(param, long);
-    break;
-
-#endif   /* CURL_DISABLE_HTTP */
-
-  case CURLOPT_HTTPAUTH:
-    /*
-     * Set HTTP Authentication type BITMASK.
-     */
-  {
-    int bitcheck;
-    bool authbits;
-    unsigned long auth = va_arg(param, unsigned long);
-
-    if(auth == CURLAUTH_NONE) {
-      data->set.httpauth = auth;
-      break;
-    }
-
-    /* the DIGEST_IE bit is only used to set a special marker, for all the
-       rest we need to handle it as normal DIGEST */
-    data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
-
-    if(auth & CURLAUTH_DIGEST_IE) {
-      auth |= CURLAUTH_DIGEST; /* set standard digest bit */
-      auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
-    }
-
-    /* switch off bits we can't support */
-#ifndef USE_NTLM
-    auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
-    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
-#elif !defined(NTLM_WB_ENABLED)
-    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
-#endif
-#ifndef USE_SPNEGO
-    auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
-                                    GSS-API or SSPI */
-#endif
-
-    /* check if any auth bit lower than CURLAUTH_ONLY is still set */
-    bitcheck = 0;
-    authbits = FALSE;
-    while(bitcheck < 31) {
-      if(auth & (1UL << bitcheck++)) {
-        authbits = TRUE;
-        break;
-      }
-    }
-    if(!authbits)
-      return CURLE_NOT_BUILT_IN; /* no supported types left! */
-
-    data->set.httpauth = auth;
-  }
-  break;
-
-  case CURLOPT_CUSTOMREQUEST:
-    /*
-     * Set a custom string to use as request
-     */
-    result = setstropt(&data->set.str[STRING_CUSTOMREQUEST],
-                       va_arg(param, char *));
-
-    /* we don't set
-       data->set.httpreq = HTTPREQ_CUSTOM;
-       here, we continue as if we were using the already set type
-       and this just changes the actual request keyword */
-    break;
-
-#ifndef CURL_DISABLE_PROXY
-  case CURLOPT_HTTPPROXYTUNNEL:
-    /*
-     * Tunnel operations through the proxy instead of normal proxy use
-     */
-    data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
-                                      TRUE : FALSE;
-    break;
-
-  case CURLOPT_PROXYPORT:
-    /*
-     * Explicitly set HTTP proxy port number.
-     */
-    data->set.proxyport = va_arg(param, long);
-    break;
-
-  case CURLOPT_PROXYAUTH:
-    /*
-     * Set HTTP Authentication type BITMASK.
-     */
-  {
-    int bitcheck;
-    bool authbits;
-    unsigned long auth = va_arg(param, unsigned long);
-
-    if(auth == CURLAUTH_NONE) {
-      data->set.proxyauth = auth;
-      break;
-    }
-
-    /* the DIGEST_IE bit is only used to set a special marker, for all the
-       rest we need to handle it as normal DIGEST */
-    data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
-
-    if(auth & CURLAUTH_DIGEST_IE) {
-      auth |= CURLAUTH_DIGEST; /* set standard digest bit */
-      auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
-    }
-    /* switch off bits we can't support */
-#ifndef USE_NTLM
-    auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
-    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
-#elif !defined(NTLM_WB_ENABLED)
-    auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
-#endif
-#ifndef USE_SPNEGO
-    auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
-                                    GSS-API or SSPI */
-#endif
-
-    /* check if any auth bit lower than CURLAUTH_ONLY is still set */
-    bitcheck = 0;
-    authbits = FALSE;
-    while(bitcheck < 31) {
-      if(auth & (1UL << bitcheck++)) {
-        authbits = TRUE;
-        break;
-      }
-    }
-    if(!authbits)
-      return CURLE_NOT_BUILT_IN; /* no supported types left! */
-
-    data->set.proxyauth = auth;
-  }
-  break;
-
-  case CURLOPT_PROXY:
-    /*
-     * Set proxy server:port to use as proxy.
-     *
-     * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
-     * we explicitly say that we don't want to use a proxy
-     * (even though there might be environment variables saying so).
-     *
-     * Setting it to NULL, means no proxy but allows the environment variables
-     * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
-     */
-    result = setstropt(&data->set.str[STRING_PROXY],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_PRE_PROXY:
-    /*
-     * Set proxy server:port to use as SOCKS proxy.
-     *
-     * If the proxy is set to "" or NULL we explicitly say that we don't want
-     * to use the socks proxy.
-     */
-    result = setstropt(&data->set.str[STRING_PRE_PROXY],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_PROXYTYPE:
-    /*
-     * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
-     */
-    data->set.proxytype = (curl_proxytype)va_arg(param, long);
-    break;
-
-  case CURLOPT_PROXY_TRANSFER_MODE:
-    /*
-     * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
-     */
-    switch(va_arg(param, long)) {
-    case 0:
-      data->set.proxy_transfer_mode = FALSE;
-      break;
-    case 1:
-      data->set.proxy_transfer_mode = TRUE;
-      break;
-    default:
-      /* reserve other values for future use */
-      result = CURLE_UNKNOWN_OPTION;
-      break;
-    }
-    break;
-#endif   /* CURL_DISABLE_PROXY */
-
-  case CURLOPT_SOCKS5_AUTH:
-    data->set.socks5auth = va_arg(param, unsigned long);
-    if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
-      result = CURLE_NOT_BUILT_IN;
-    break;
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-  case CURLOPT_SOCKS5_GSSAPI_NEC:
-    /*
-     * Set flag for NEC SOCK5 support
-     */
-    data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_SOCKS5_GSSAPI_SERVICE:
-  case CURLOPT_PROXY_SERVICE_NAME:
-    /*
-     * Set proxy authentication service name for Kerberos 5 and SPNEGO
-     */
-    result = setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
-                       va_arg(param, char *));
-    break;
-#endif
-
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
-    defined(USE_SPNEGO)
-  case CURLOPT_SERVICE_NAME:
-    /*
-     * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
-     */
-    result = setstropt(&data->set.str[STRING_SERVICE_NAME],
-                       va_arg(param, char *));
-    break;
-
-#endif
-
-  case CURLOPT_HEADERDATA:
-    /*
-     * Custom pointer to pass the header write callback function
-     */
-    data->set.writeheader = (void *)va_arg(param, void *);
-    break;
-  case CURLOPT_ERRORBUFFER:
-    /*
-     * Error buffer provided by the caller to get the human readable
-     * error string in.
-     */
-    data->set.errorbuffer = va_arg(param, char *);
-    break;
-  case CURLOPT_WRITEDATA:
-    /*
-     * FILE pointer to write to. Or possibly
-     * used as argument to the write callback.
-     */
-    data->set.out = va_arg(param, void *);
-    break;
-  case CURLOPT_FTPPORT:
-    /*
-     * Use FTP PORT, this also specifies which IP address to use
-     */
-    result = setstropt(&data->set.str[STRING_FTPPORT],
-                       va_arg(param, char *));
-    data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_FTP_USE_EPRT:
-    data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_FTP_USE_EPSV:
-    data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_FTP_USE_PRET:
-    data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_FTP_SSL_CCC:
-    data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long);
-    break;
-
-  case CURLOPT_FTP_SKIP_PASV_IP:
-    /*
-     * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
-     * bypass of the IP address in PASV responses.
-     */
-    data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_READDATA:
-    /*
-     * FILE pointer to read the file to be uploaded from. Or possibly
-     * used as argument to the read callback.
-     */
-    data->set.in_set = va_arg(param, void *);
-    break;
-  case CURLOPT_INFILESIZE:
-    /*
-     * If known, this should inform curl about the file size of the
-     * to-be-uploaded file.
-     */
-    data->set.filesize = va_arg(param, long);
-    break;
-  case CURLOPT_INFILESIZE_LARGE:
-    /*
-     * If known, this should inform curl about the file size of the
-     * to-be-uploaded file.
-     */
-    data->set.filesize = va_arg(param, curl_off_t);
-    break;
-  case CURLOPT_LOW_SPEED_LIMIT:
-    /*
-     * The low speed limit that if transfers are below this for
-     * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
-     */
-    data->set.low_speed_limit = va_arg(param, long);
-    break;
-  case CURLOPT_MAX_SEND_SPEED_LARGE:
-    /*
-     * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
-     * bytes per second the transfer is throttled..
-     */
-    data->set.max_send_speed = va_arg(param, curl_off_t);
-    break;
-  case CURLOPT_MAX_RECV_SPEED_LARGE:
-    /*
-     * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
-     * second the transfer is throttled..
-     */
-    data->set.max_recv_speed = va_arg(param, curl_off_t);
-    break;
-  case CURLOPT_LOW_SPEED_TIME:
-    /*
-     * The low speed time that if transfers are below the set
-     * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
-     */
-    data->set.low_speed_time = va_arg(param, long);
-    break;
-  case CURLOPT_URL:
-    /*
-     * The URL to fetch.
-     */
-    if(data->change.url_alloc) {
-      /* the already set URL is allocated, free it first! */
-      Curl_safefree(data->change.url);
-      data->change.url_alloc = FALSE;
-    }
-    result = setstropt(&data->set.str[STRING_SET_URL],
-                       va_arg(param, char *));
-    data->change.url = data->set.str[STRING_SET_URL];
-    break;
-  case CURLOPT_PORT:
-    /*
-     * The port number to use when getting the URL
-     */
-    data->set.use_port = va_arg(param, long);
-    break;
-  case CURLOPT_TIMEOUT:
-    /*
-     * The maximum time you allow curl to use for a single transfer
-     * operation.
-     */
-    data->set.timeout = va_arg(param, long) * 1000L;
-    break;
-
-  case CURLOPT_TIMEOUT_MS:
-    data->set.timeout = va_arg(param, long);
-    break;
-
-  case CURLOPT_CONNECTTIMEOUT:
-    /*
-     * The maximum time you allow curl to use to connect.
-     */
-    data->set.connecttimeout = va_arg(param, long) * 1000L;
-    break;
-
-  case CURLOPT_CONNECTTIMEOUT_MS:
-    data->set.connecttimeout = va_arg(param, long);
-    break;
-
-  case CURLOPT_ACCEPTTIMEOUT_MS:
-    /*
-     * The maximum time you allow curl to wait for server connect
-     */
-    data->set.accepttimeout = va_arg(param, long);
-    break;
-
-  case CURLOPT_USERPWD:
-    /*
-     * user:password to use in the operation
-     */
-    result = setstropt_userpwd(va_arg(param, char *),
-                               &data->set.str[STRING_USERNAME],
-                               &data->set.str[STRING_PASSWORD]);
-    break;
-
-  case CURLOPT_USERNAME:
-    /*
-     * authentication user name to use in the operation
-     */
-    result = setstropt(&data->set.str[STRING_USERNAME],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_PASSWORD:
-    /*
-     * authentication password to use in the operation
-     */
-    result = setstropt(&data->set.str[STRING_PASSWORD],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_LOGIN_OPTIONS:
-    /*
-     * authentication options to use in the operation
-     */
-    result = setstropt(&data->set.str[STRING_OPTIONS],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_XOAUTH2_BEARER:
-    /*
-     * OAuth 2.0 bearer token to use in the operation
-     */
-    result = setstropt(&data->set.str[STRING_BEARER],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_POSTQUOTE:
-    /*
-     * List of RAW FTP commands to use after a transfer
-     */
-    data->set.postquote = va_arg(param, struct curl_slist *);
-    break;
-  case CURLOPT_PREQUOTE:
-    /*
-     * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
-     */
-    data->set.prequote = va_arg(param, struct curl_slist *);
-    break;
-  case CURLOPT_QUOTE:
-    /*
-     * List of RAW FTP commands to use before a transfer
-     */
-    data->set.quote = va_arg(param, struct curl_slist *);
-    break;
-  case CURLOPT_RESOLVE:
-    /*
-     * List of NAME:[address] names to populate the DNS cache with
-     * Prefix the NAME with dash (-) to _remove_ the name from the cache.
-     *
-     * Names added with this API will remain in the cache until explicitly
-     * removed or the handle is cleaned up.
-     *
-     * This API can remove any name from the DNS cache, but only entries
-     * that aren't actually in use right now will be pruned immediately.
-     */
-    data->set.resolve = va_arg(param, struct curl_slist *);
-    data->change.resolve = data->set.resolve;
-    break;
-  case CURLOPT_PROGRESSFUNCTION:
-    /*
-     * Progress callback function
-     */
-    data->set.fprogress = va_arg(param, curl_progress_callback);
-    if(data->set.fprogress)
-      data->progress.callback = TRUE; /* no longer internal */
-    else
-      data->progress.callback = FALSE; /* NULL enforces internal */
-    break;
-
-  case CURLOPT_XFERINFOFUNCTION:
-    /*
-     * Transfer info callback function
-     */
-    data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
-    if(data->set.fxferinfo)
-      data->progress.callback = TRUE; /* no longer internal */
-    else
-      data->progress.callback = FALSE; /* NULL enforces internal */
-
-    break;
-
-  case CURLOPT_PROGRESSDATA:
-    /*
-     * Custom client data to pass to the progress callback
-     */
-    data->set.progress_client = va_arg(param, void *);
-    break;
-
-#ifndef CURL_DISABLE_PROXY
-  case CURLOPT_PROXYUSERPWD:
-    /*
-     * user:password needed to use the proxy
-     */
-    result = setstropt_userpwd(va_arg(param, char *),
-                               &data->set.str[STRING_PROXYUSERNAME],
-                               &data->set.str[STRING_PROXYPASSWORD]);
-    break;
-  case CURLOPT_PROXYUSERNAME:
-    /*
-     * authentication user name to use in the operation
-     */
-    result = setstropt(&data->set.str[STRING_PROXYUSERNAME],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXYPASSWORD:
-    /*
-     * authentication password to use in the operation
-     */
-    result = setstropt(&data->set.str[STRING_PROXYPASSWORD],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_NOPROXY:
-    /*
-     * proxy exception list
-     */
-    result = setstropt(&data->set.str[STRING_NOPROXY],
-                       va_arg(param, char *));
-    break;
-#endif
-
-  case CURLOPT_RANGE:
-    /*
-     * What range of the file you want to transfer
-     */
-    result = setstropt(&data->set.str[STRING_SET_RANGE],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_RESUME_FROM:
-    /*
-     * Resume transfer at the given file position
-     */
-    data->set.set_resume_from = va_arg(param, long);
-    break;
-  case CURLOPT_RESUME_FROM_LARGE:
-    /*
-     * Resume transfer at the given file position
-     */
-    data->set.set_resume_from = va_arg(param, curl_off_t);
-    break;
-  case CURLOPT_DEBUGFUNCTION:
-    /*
-     * stderr write callback.
-     */
-    data->set.fdebug = va_arg(param, curl_debug_callback);
-    /*
-     * if the callback provided is NULL, it'll use the default callback
-     */
-    break;
-  case CURLOPT_DEBUGDATA:
-    /*
-     * Set to a void * that should receive all error writes. This
-     * defaults to CURLOPT_STDERR for normal operations.
-     */
-    data->set.debugdata = va_arg(param, void *);
-    break;
-  case CURLOPT_STDERR:
-    /*
-     * Set to a FILE * that should receive all error writes. This
-     * defaults to stderr for normal operations.
-     */
-    data->set.err = va_arg(param, FILE *);
-    if(!data->set.err)
-      data->set.err = stderr;
-    break;
-  case CURLOPT_HEADERFUNCTION:
-    /*
-     * Set header write callback
-     */
-    data->set.fwrite_header = va_arg(param, curl_write_callback);
-    break;
-  case CURLOPT_WRITEFUNCTION:
-    /*
-     * Set data write callback
-     */
-    data->set.fwrite_func = va_arg(param, curl_write_callback);
-    if(!data->set.fwrite_func) {
-      data->set.is_fwrite_set = 0;
-      /* When set to NULL, reset to our internal default function */
-      data->set.fwrite_func = (curl_write_callback)fwrite;
-    }
-    else
-      data->set.is_fwrite_set = 1;
-    break;
-  case CURLOPT_READFUNCTION:
-    /*
-     * Read data callback
-     */
-    data->set.fread_func_set = va_arg(param, curl_read_callback);
-    if(!data->set.fread_func_set) {
-      data->set.is_fread_set = 0;
-      /* When set to NULL, reset to our internal default function */
-      data->set.fread_func_set = (curl_read_callback)fread;
-    }
-    else
-      data->set.is_fread_set = 1;
-    break;
-  case CURLOPT_SEEKFUNCTION:
-    /*
-     * Seek callback. Might be NULL.
-     */
-    data->set.seek_func = va_arg(param, curl_seek_callback);
-    break;
-  case CURLOPT_SEEKDATA:
-    /*
-     * Seek control callback. Might be NULL.
-     */
-    data->set.seek_client = va_arg(param, void *);
-    break;
-  case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
-    /*
-     * "Convert from network encoding" callback
-     */
-    data->set.convfromnetwork = va_arg(param, curl_conv_callback);
-    break;
-  case CURLOPT_CONV_TO_NETWORK_FUNCTION:
-    /*
-     * "Convert to network encoding" callback
-     */
-    data->set.convtonetwork = va_arg(param, curl_conv_callback);
-    break;
-  case CURLOPT_CONV_FROM_UTF8_FUNCTION:
-    /*
-     * "Convert from UTF-8 encoding" callback
-     */
-    data->set.convfromutf8 = va_arg(param, curl_conv_callback);
-    break;
-  case CURLOPT_IOCTLFUNCTION:
-    /*
-     * I/O control callback. Might be NULL.
-     */
-    data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
-    break;
-  case CURLOPT_IOCTLDATA:
-    /*
-     * I/O control data pointer. Might be NULL.
-     */
-    data->set.ioctl_client = va_arg(param, void *);
-    break;
-  case CURLOPT_SSLCERT:
-    /*
-     * String that holds file name of the SSL certificate to use
-     */
-    result = setstropt(&data->set.str[STRING_CERT_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_SSLCERT:
-    /*
-     * String that holds file name of the SSL certificate to use for proxy
-     */
-    result = setstropt(&data->set.str[STRING_CERT_PROXY],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_SSLCERTTYPE:
-    /*
-     * String that holds file type of the SSL certificate to use
-     */
-    result = setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_SSLCERTTYPE:
-    /*
-     * String that holds file type of the SSL certificate to use for proxy
-     */
-    result = setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_SSLKEY:
-    /*
-     * String that holds file name of the SSL key to use
-     */
-    result = setstropt(&data->set.str[STRING_KEY_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_SSLKEY:
-    /*
-     * String that holds file name of the SSL key to use for proxy
-     */
-    result = setstropt(&data->set.str[STRING_KEY_PROXY],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_SSLKEYTYPE:
-    /*
-     * String that holds file type of the SSL key to use
-     */
-    result = setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_SSLKEYTYPE:
-    /*
-     * String that holds file type of the SSL key to use for proxy
-     */
-    result = setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_KEYPASSWD:
-    /*
-     * String that holds the SSL or SSH private key password.
-     */
-    result = setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_KEYPASSWD:
-    /*
-     * String that holds the SSL private key password for proxy.
-     */
-    result = setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_SSLENGINE:
-    /*
-     * String that holds the SSL crypto engine.
-     */
-    argptr = va_arg(param, char *);
-    if(argptr && argptr[0])
-      result = Curl_ssl_set_engine(data, argptr);
-    break;
-
-  case CURLOPT_SSLENGINE_DEFAULT:
-    /*
-     * flag to set engine as default.
-     */
-    result = Curl_ssl_set_engine_default(data);
-    break;
-  case CURLOPT_CRLF:
-    /*
-     * Kludgy option to enable CRLF conversions. Subject for removal.
-     */
-    data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_INTERFACE:
-    /*
-     * Set what interface or address/hostname to bind the socket to when
-     * performing an operation and thus what from-IP your connection will use.
-     */
-    result = setstropt(&data->set.str[STRING_DEVICE],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_LOCALPORT:
-    /*
-     * Set what local port to bind the socket to when performing an operation.
-     */
-    arg = va_arg(param, long);
-    if((arg < 0) || (arg > 65535))
-      return CURLE_BAD_FUNCTION_ARGUMENT;
-    data->set.localport = curlx_sltous(arg);
-    break;
-  case CURLOPT_LOCALPORTRANGE:
-    /*
-     * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
-     */
-    arg = va_arg(param, long);
-    if((arg < 0) || (arg > 65535))
-      return CURLE_BAD_FUNCTION_ARGUMENT;
-    data->set.localportrange = curlx_sltosi(arg);
-    break;
-  case CURLOPT_KRBLEVEL:
-    /*
-     * A string that defines the kerberos security level.
-     */
-    result = setstropt(&data->set.str[STRING_KRB_LEVEL],
-                       va_arg(param, char *));
-    data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
-    break;
-  case CURLOPT_GSSAPI_DELEGATION:
-    /*
-     * GSS-API credential delegation
-     */
-    data->set.gssapi_delegation = va_arg(param, long);
-    break;
-  case CURLOPT_SSL_VERIFYPEER:
-    /*
-     * Enable peer SSL verifying.
-     */
-    data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
-                                       TRUE : FALSE;
-    break;
-  case CURLOPT_PROXY_SSL_VERIFYPEER:
-    /*
-     * Enable peer SSL verifying for proxy.
-     */
-    data->set.proxy_ssl.primary.verifypeer =
-      (0 != va_arg(param, long))?TRUE:FALSE;
-    break;
-  case CURLOPT_SSL_VERIFYHOST:
-    /*
-     * Enable verification of the host name in the peer certificate
-     */
-    arg = va_arg(param, long);
-
-    /* Obviously people are not reading documentation and too many thought
-       this argument took a boolean when it wasn't and misused it. We thus ban
-       1 as a sensible input and we warn about its use. Then we only have the
-       2 action internally stored as TRUE. */
-
-    if(1 == arg) {
-      failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
-      return CURLE_BAD_FUNCTION_ARGUMENT;
-    }
-
-    data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
-    break;
-  case CURLOPT_PROXY_SSL_VERIFYHOST:
-    /*
-     * Enable verification of the host name in the peer certificate for proxy
-     */
-    arg = va_arg(param, long);
-
-    /* Obviously people are not reading documentation and too many thought
-       this argument took a boolean when it wasn't and misused it. We thus ban
-       1 as a sensible input and we warn about its use. Then we only have the
-       2 action internally stored as TRUE. */
-
-    if(1 == arg) {
-      failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
-      return CURLE_BAD_FUNCTION_ARGUMENT;
-    }
-
-    data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
-    break;
-  case CURLOPT_SSL_VERIFYSTATUS:
-    /*
-     * Enable certificate status verifying.
-     */
-    if(!Curl_ssl_cert_status_request()) {
-      result = CURLE_NOT_BUILT_IN;
-      break;
-    }
-
-    data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
-                                         TRUE : FALSE;
-    break;
-  case CURLOPT_SSL_CTX_FUNCTION:
-    /*
-     * Set a SSL_CTX callback
-     */
-#ifdef USE_SSL
-    if(Curl_ssl->have_ssl_ctx)
-      data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
-    else
-#endif
-      result = CURLE_NOT_BUILT_IN;
-    break;
-  case CURLOPT_SSL_CTX_DATA:
-    /*
-     * Set a SSL_CTX callback parameter pointer
-     */
-#ifdef USE_SSL
-    if(Curl_ssl->have_ssl_ctx)
-      data->set.ssl.fsslctxp = va_arg(param, void *);
-    else
-#endif
-      result = CURLE_NOT_BUILT_IN;
-    break;
-  case CURLOPT_SSL_FALSESTART:
-    /*
-     * Enable TLS false start.
-     */
-    if(!Curl_ssl_false_start()) {
-      result = CURLE_NOT_BUILT_IN;
-      break;
-    }
-
-    data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_CERTINFO:
-#ifdef USE_SSL
-    if(Curl_ssl->have_certinfo)
-      data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    else
-#endif
-      result = CURLE_NOT_BUILT_IN;
-    break;
-  case CURLOPT_PINNEDPUBLICKEY:
-    /*
-     * Set pinned public key for SSL connection.
-     * Specify file name of the public key in DER format.
-     */
-#ifdef USE_SSL
-    if(Curl_ssl->have_pinnedpubkey)
-      result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
-                         va_arg(param, char *));
-    else
-#endif
-      result = CURLE_NOT_BUILT_IN;
-    break;
-  case CURLOPT_PROXY_PINNEDPUBLICKEY:
-    /*
-     * Set pinned public key for SSL connection.
-     * Specify file name of the public key in DER format.
-     */
-#ifdef USE_SSL
-    if(Curl_ssl->have_pinnedpubkey)
-      result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
-                         va_arg(param, char *));
-    else
-#endif
-      result = CURLE_NOT_BUILT_IN;
-    break;
-  case CURLOPT_CAINFO:
-    /*
-     * Set CA info for SSL connection. Specify file name of the CA certificate
-     */
-    result = setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_CAINFO:
-    /*
-     * Set CA info SSL connection for proxy. Specify file name of the
-     * CA certificate
-     */
-    result = setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_CAPATH:
-    /*
-     * Set CA path info for SSL connection. Specify directory name of the CA
-     * certificates which have been prepared using openssl c_rehash utility.
-     */
-#ifdef USE_SSL
-    if(Curl_ssl->have_ca_path)
-      /* This does not work on windows. */
-      result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
-                         va_arg(param, char *));
-    else
-#endif
-      result = CURLE_NOT_BUILT_IN;
-    break;
-  case CURLOPT_PROXY_CAPATH:
-    /*
-     * Set CA path info for SSL connection proxy. Specify directory name of the
-     * CA certificates which have been prepared using openssl c_rehash utility.
-     */
-#ifdef USE_SSL
-    if(Curl_ssl->have_ca_path)
-      /* This does not work on windows. */
-      result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
-                         va_arg(param, char *));
-    else
-#endif
-      result = CURLE_NOT_BUILT_IN;
-    break;
-  case CURLOPT_CRLFILE:
-    /*
-     * Set CRL file info for SSL connection. Specify file name of the CRL
-     * to check certificates revocation
-     */
-    result = setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_CRLFILE:
-    /*
-     * Set CRL file info for SSL connection for proxy. Specify file name of the
-     * CRL to check certificates revocation
-     */
-    result = setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_ISSUERCERT:
-    /*
-     * Set Issuer certificate file
-     * to check certificates issuer
-     */
-    result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_TELNETOPTIONS:
-    /*
-     * Set a linked list of telnet options
-     */
-    data->set.telnet_options = va_arg(param, struct curl_slist *);
-    break;
-
-  case CURLOPT_BUFFERSIZE:
-    /*
-     * The application kindly asks for a differently sized receive buffer.
-     * If it seems reasonable, we'll use it.
-     */
-    arg = va_arg(param, long);
-
-    if(arg > READBUFFER_MAX)
-      arg = READBUFFER_MAX;
-    else if(arg < 1)
-      arg = READBUFFER_SIZE;
-    else if(arg < READBUFFER_MIN)
-      arg = READBUFFER_MIN;
-
-    /* Resize if new size */
-    if(arg != data->set.buffer_size) {
-      char *newbuff = realloc(data->state.buffer, arg + 1);
-      if(!newbuff) {
-        DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
-        result = CURLE_OUT_OF_MEMORY;
-      }
-      else
-        data->state.buffer = newbuff;
-    }
-    data->set.buffer_size = arg;
-
-    break;
-
-  case CURLOPT_NOSIGNAL:
-    /*
-     * The application asks not to set any signal() or alarm() handlers,
-     * even when using a timeout.
-     */
-    data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_SHARE:
-  {
-    struct Curl_share *set;
-    set = va_arg(param, struct Curl_share *);
-
-    /* disconnect from old share, if any */
-    if(data->share) {
-      Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
-
-      if(data->dns.hostcachetype == HCACHE_SHARED) {
-        data->dns.hostcache = NULL;
-        data->dns.hostcachetype = HCACHE_NONE;
-      }
-
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
-      if(data->share->cookies == data->cookies)
-        data->cookies = NULL;
-#endif
-
-      if(data->share->sslsession == data->state.session)
-        data->state.session = NULL;
-
-      data->share->dirty--;
-
-      Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
-      data->share = NULL;
-    }
-
-    /* use new share if it set */
-    data->share = set;
-    if(data->share) {
-
-      Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
-
-      data->share->dirty++;
-
-      if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) {
-        /* use shared host cache */
-        data->dns.hostcache = &data->share->hostcache;
-        data->dns.hostcachetype = HCACHE_SHARED;
-      }
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
-      if(data->share->cookies) {
-        /* use shared cookie list, first free own one if any */
-        Curl_cookie_cleanup(data->cookies);
-        /* enable cookies since we now use a share that uses cookies! */
-        data->cookies = data->share->cookies;
-      }
-#endif   /* CURL_DISABLE_HTTP */
-      if(data->share->sslsession) {
-        data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
-        data->state.session = data->share->sslsession;
-      }
-      Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
-
-    }
-    /* check for host cache not needed,
-     * it will be done by curl_easy_perform */
-  }
-  break;
-
-  case CURLOPT_PRIVATE:
-    /*
-     * Set private data pointer.
-     */
-    data->set.private_data = va_arg(param, void *);
-    break;
-
-  case CURLOPT_MAXFILESIZE:
-    /*
-     * Set the maximum size of a file to download.
-     */
-    data->set.max_filesize = va_arg(param, long);
-    break;
-
-#ifdef USE_SSL
-  case CURLOPT_USE_SSL:
-    /*
-     * Make transfers attempt to use SSL/TLS.
-     */
-    data->set.use_ssl = (curl_usessl)va_arg(param, long);
-    break;
-
-  case CURLOPT_SSL_OPTIONS:
-    arg = va_arg(param, long);
-    data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
-    data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
-    break;
-
-  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.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
-    break;
-
-#endif
-  case CURLOPT_FTPSSLAUTH:
-    /*
-     * Set a specific auth for FTP-SSL transfers.
-     */
-    data->set.ftpsslauth = (curl_ftpauth)va_arg(param, long);
-    break;
-
-  case CURLOPT_IPRESOLVE:
-    data->set.ipver = va_arg(param, long);
-    break;
-
-  case CURLOPT_MAXFILESIZE_LARGE:
-    /*
-     * Set the maximum size of a file to download.
-     */
-    data->set.max_filesize = va_arg(param, curl_off_t);
-    break;
-
-  case CURLOPT_TCP_NODELAY:
-    /*
-     * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
-     * algorithm
-     */
-    data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_FTP_ACCOUNT:
-    result = setstropt(&data->set.str[STRING_FTP_ACCOUNT],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_IGNORE_CONTENT_LENGTH:
-    data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_CONNECT_ONLY:
-    /*
-     * No data transfer, set up connection and let application use the socket
-     */
-    data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_FTP_ALTERNATIVE_TO_USER:
-    result = setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_SOCKOPTFUNCTION:
-    /*
-     * socket callback function: called after socket() but before connect()
-     */
-    data->set.fsockopt = va_arg(param, curl_sockopt_callback);
-    break;
-
-  case CURLOPT_SOCKOPTDATA:
-    /*
-     * socket callback data pointer. Might be NULL.
-     */
-    data->set.sockopt_client = va_arg(param, void *);
-    break;
-
-  case CURLOPT_OPENSOCKETFUNCTION:
-    /*
-     * open/create socket callback function: called instead of socket(),
-     * before connect()
-     */
-    data->set.fopensocket = va_arg(param, curl_opensocket_callback);
-    break;
-
-  case CURLOPT_OPENSOCKETDATA:
-    /*
-     * socket callback data pointer. Might be NULL.
-     */
-    data->set.opensocket_client = va_arg(param, void *);
-    break;
-
-  case CURLOPT_CLOSESOCKETFUNCTION:
-    /*
-     * close socket callback function: called instead of close()
-     * when shutting down a connection
-     */
-    data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
-    break;
-
-  case CURLOPT_CLOSESOCKETDATA:
-    /*
-     * socket callback data pointer. Might be NULL.
-     */
-    data->set.closesocket_client = va_arg(param, void *);
-    break;
-
-  case CURLOPT_SSL_SESSIONID_CACHE:
-    data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
-                                      TRUE : FALSE;
-    data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
-    break;
-
-#ifdef USE_LIBSSH2
-    /* we only include SSH options if explicitly built to support SSH */
-  case CURLOPT_SSH_AUTH_TYPES:
-    data->set.ssh_auth_types = va_arg(param, long);
-    break;
-
-  case CURLOPT_SSH_PUBLIC_KEYFILE:
-    /*
-     * Use this file instead of the $HOME/.ssh/id_dsa.pub file
-     */
-    result = setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_SSH_PRIVATE_KEYFILE:
-    /*
-     * Use this file instead of the $HOME/.ssh/id_dsa file
-     */
-    result = setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
-    /*
-     * Option to allow for the MD5 of the host public key to be checked
-     * for validation purposes.
-     */
-    result = setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
-                       va_arg(param, char *));
-    break;
-#ifdef HAVE_LIBSSH2_KNOWNHOST_API
-  case CURLOPT_SSH_KNOWNHOSTS:
-    /*
-     * Store the file name to read known hosts from.
-     */
-    result = setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_SSH_KEYFUNCTION:
-    /* setting to NULL is fine since the ssh.c functions themselves will
-       then rever to use the internal default */
-    data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
-    break;
-
-  case CURLOPT_SSH_KEYDATA:
-    /*
-     * Custom client data to pass to the SSH keyfunc callback
-     */
-    data->set.ssh_keyfunc_userp = va_arg(param, void *);
-    break;
-#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
-
-#endif /* USE_LIBSSH2 */
-
-  case CURLOPT_HTTP_TRANSFER_DECODING:
-    /*
-     * disable libcurl transfer encoding is used
-     */
-    data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_HTTP_CONTENT_DECODING:
-    /*
-     * raw data passed to the application when content encoding is used
-     */
-    data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_NEW_FILE_PERMS:
-    /*
-     * Uses these permissions instead of 0644
-     */
-    data->set.new_file_perms = va_arg(param, long);
-    break;
-
-  case CURLOPT_NEW_DIRECTORY_PERMS:
-    /*
-     * Uses these permissions instead of 0755
-     */
-    data->set.new_directory_perms = va_arg(param, long);
-    break;
-
-  case CURLOPT_ADDRESS_SCOPE:
-    /*
-     * We always get longs when passed plain numericals, but for this value we
-     * know that an unsigned int will always hold the value so we blindly
-     * typecast to this type
-     */
-    arg = va_arg(param, long);
-    if((arg < 0) || (arg > 0xf))
-      return CURLE_BAD_FUNCTION_ARGUMENT;
-    data->set.scope_id = curlx_sltoui(arg);
-    break;
-
-  case CURLOPT_PROTOCOLS:
-    /* set the bitmask for the protocols that are allowed to be used for the
-       transfer, which thus helps the app which takes URLs from users or other
-       external inputs and want to restrict what protocol(s) to deal
-       with. Defaults to CURLPROTO_ALL. */
-    data->set.allowed_protocols = va_arg(param, long);
-    break;
-
-  case CURLOPT_REDIR_PROTOCOLS:
-    /* set the bitmask for the protocols that libcurl is allowed to follow to,
-       as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
-       to be set in both bitmasks to be allowed to get redirected to. Defaults
-       to all protocols except FILE and SCP. */
-    data->set.redir_protocols = va_arg(param, long);
-    break;
-
-  case CURLOPT_DEFAULT_PROTOCOL:
-    /* Set the protocol to use when the URL doesn't include any protocol */
-    result = setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_MAIL_FROM:
-    /* Set the SMTP mail originator */
-    result = setstropt(&data->set.str[STRING_MAIL_FROM],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_MAIL_AUTH:
-    /* Set the SMTP auth originator */
-    result = setstropt(&data->set.str[STRING_MAIL_AUTH],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_MAIL_RCPT:
-    /* Set the list of mail recipients */
-    data->set.mail_rcpt = va_arg(param, struct curl_slist *);
-    break;
-
-  case CURLOPT_SASL_IR:
-    /* Enable/disable SASL initial response */
-    data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-
-  case CURLOPT_RTSP_REQUEST:
-    {
-      /*
-       * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
-       * Would this be better if the RTSPREQ_* were just moved into here?
-       */
-      long curl_rtspreq = va_arg(param, long);
-      Curl_RtspReq rtspreq = RTSPREQ_NONE;
-      switch(curl_rtspreq) {
-        case CURL_RTSPREQ_OPTIONS:
-          rtspreq = RTSPREQ_OPTIONS;
-          break;
-
-        case CURL_RTSPREQ_DESCRIBE:
-          rtspreq = RTSPREQ_DESCRIBE;
-          break;
-
-        case CURL_RTSPREQ_ANNOUNCE:
-          rtspreq = RTSPREQ_ANNOUNCE;
-          break;
-
-        case CURL_RTSPREQ_SETUP:
-          rtspreq = RTSPREQ_SETUP;
-          break;
-
-        case CURL_RTSPREQ_PLAY:
-          rtspreq = RTSPREQ_PLAY;
-          break;
-
-        case CURL_RTSPREQ_PAUSE:
-          rtspreq = RTSPREQ_PAUSE;
-          break;
-
-        case CURL_RTSPREQ_TEARDOWN:
-          rtspreq = RTSPREQ_TEARDOWN;
-          break;
-
-        case CURL_RTSPREQ_GET_PARAMETER:
-          rtspreq = RTSPREQ_GET_PARAMETER;
-          break;
-
-        case CURL_RTSPREQ_SET_PARAMETER:
-          rtspreq = RTSPREQ_SET_PARAMETER;
-          break;
-
-        case CURL_RTSPREQ_RECORD:
-          rtspreq = RTSPREQ_RECORD;
-          break;
-
-        case CURL_RTSPREQ_RECEIVE:
-          rtspreq = RTSPREQ_RECEIVE;
-          break;
-        default:
-          rtspreq = RTSPREQ_NONE;
-      }
-
-      data->set.rtspreq = rtspreq;
-    break;
-    }
-
-
-  case CURLOPT_RTSP_SESSION_ID:
-    /*
-     * Set the RTSP Session ID manually. Useful if the application is
-     * resuming a previously established RTSP session
-     */
-    result = setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
-                       va_arg(param, char *));
-    break;
-
-  case CURLOPT_RTSP_STREAM_URI:
-    /*
-     * Set the Stream URI for the RTSP request. Unless the request is
-     * for generic server options, the application will need to set this.
-     */
-    result = setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
-                       va_arg(param, char *));
-    break;
+  struct Curl_easy *data;
 
-  case CURLOPT_RTSP_TRANSPORT:
-    /*
-     * The content of the Transport: header for the RTSP request
-     */
-    result = setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
-                       va_arg(param, char *));
-    break;
+  /* Very simple start-up: alloc the struct, init it with zeroes and return */
+  data = calloc(1, sizeof(struct Curl_easy));
+  if(!data) {
+    /* this is a very serious error */
+    DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
+    return CURLE_OUT_OF_MEMORY;
+  }
 
-  case CURLOPT_RTSP_CLIENT_CSEQ:
-    /*
-     * Set the CSEQ number to issue for the next RTSP request. Useful if the
-     * application is resuming a previously broken connection. The CSEQ
-     * will increment from this new number henceforth.
-     */
-    data->state.rtsp_next_client_CSeq = va_arg(param, long);
-    break;
+  data->magic = CURLEASY_MAGIC_NUMBER;
 
-  case CURLOPT_RTSP_SERVER_CSEQ:
-    /* Same as the above, but for server-initiated requests */
-    data->state.rtsp_next_client_CSeq = va_arg(param, long);
-    break;
+  result = Curl_resolver_init(&data->state.resolver);
+  if(result) {
+    DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
+    free(data);
+    return result;
+  }
 
-  case CURLOPT_INTERLEAVEDATA:
-    data->set.rtp_out = va_arg(param, void *);
-    break;
-  case CURLOPT_INTERLEAVEFUNCTION:
-    /* Set the user defined RTP write function */
-    data->set.fwrite_rtp = va_arg(param, curl_write_callback);
-    break;
+  /* We do some initial setup here, all those fields that can't be just 0 */
 
-  case CURLOPT_WILDCARDMATCH:
-    data->set.wildcardmatch = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_CHUNK_BGN_FUNCTION:
-    data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
-    break;
-  case CURLOPT_CHUNK_END_FUNCTION:
-    data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
-    break;
-  case CURLOPT_FNMATCH_FUNCTION:
-    data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
-    break;
-  case CURLOPT_CHUNK_DATA:
-    data->wildcard.customptr = va_arg(param, void *);
-    break;
-  case CURLOPT_FNMATCH_DATA:
-    data->set.fnmatch_data = va_arg(param, void *);
-    break;
-#ifdef USE_TLS_SRP
-  case CURLOPT_TLSAUTH_USERNAME:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
-                       va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
-      data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
-    break;
-  case CURLOPT_PROXY_TLSAUTH_USERNAME:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
-                       va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
-       !data->set.proxy_ssl.authtype)
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
-    break;
-  case CURLOPT_TLSAUTH_PASSWORD:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
-                       va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
-      data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
-    break;
-  case CURLOPT_PROXY_TLSAUTH_PASSWORD:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
-                       va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
-       !data->set.proxy_ssl.authtype)
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
-    break;
-  case CURLOPT_TLSAUTH_TYPE:
-    argptr = va_arg(param, char *);
-    if(!argptr ||
-       strncasecompare(argptr, "SRP", strlen("SRP")))
-      data->set.ssl.authtype = CURL_TLSAUTH_SRP;
-    else
-      data->set.ssl.authtype = CURL_TLSAUTH_NONE;
-    break;
-  case CURLOPT_PROXY_TLSAUTH_TYPE:
-    argptr = va_arg(param, char *);
-    if(!argptr ||
-       strncasecompare(argptr, "SRP", strlen("SRP")))
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
-    else
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
-    break;
-#endif
-  case CURLOPT_DNS_SERVERS:
-    result = Curl_set_dns_servers(data, va_arg(param, char *));
-    break;
-  case CURLOPT_DNS_INTERFACE:
-    result = Curl_set_dns_interface(data, va_arg(param, char *));
-    break;
-  case CURLOPT_DNS_LOCAL_IP4:
-    result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
-    break;
-  case CURLOPT_DNS_LOCAL_IP6:
-    result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
-    break;
+  data->state.buffer = malloc(READBUFFER_SIZE + 1);
+  if(!data->state.buffer) {
+    DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n"));
+    result = CURLE_OUT_OF_MEMORY;
+  }
+  else {
+    data->state.headerbuff = malloc(HEADERSIZE);
+    if(!data->state.headerbuff) {
+      DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
+      result = CURLE_OUT_OF_MEMORY;
+    }
+    else {
+      result = Curl_init_userdefined(data);
 
-  case CURLOPT_TCP_KEEPALIVE:
-    data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_TCP_KEEPIDLE:
-    data->set.tcp_keepidle = va_arg(param, long);
-    break;
-  case CURLOPT_TCP_KEEPINTVL:
-    data->set.tcp_keepintvl = va_arg(param, long);
-    break;
-  case CURLOPT_TCP_FASTOPEN:
-#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN)
-    data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
-#else
-    result = CURLE_NOT_BUILT_IN;
-#endif
-    break;
-  case CURLOPT_SSL_ENABLE_NPN:
-    data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_SSL_ENABLE_ALPN:
-    data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
+      data->state.headersize = HEADERSIZE;
+      Curl_convert_init(data);
+      Curl_initinfo(data);
 
-#ifdef USE_UNIX_SOCKETS
-  case CURLOPT_UNIX_SOCKET_PATH:
-    data->set.abstract_unix_socket = FALSE;
-    result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_ABSTRACT_UNIX_SOCKET:
-    data->set.abstract_unix_socket = TRUE;
-    result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
-                       va_arg(param, char *));
-    break;
-#endif
+      /* most recent connection is not yet defined */
+      data->state.lastconnect = NULL;
 
-  case CURLOPT_PATH_AS_IS:
-    data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_PIPEWAIT:
-    data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
-    break;
-  case CURLOPT_STREAM_WEIGHT:
-#ifndef USE_NGHTTP2
-    return CURLE_NOT_BUILT_IN;
-#else
-    arg = va_arg(param, long);
-    if((arg >= 1) && (arg <= 256))
-      data->set.stream_weight = (int)arg;
-    break;
-#endif
-  case CURLOPT_STREAM_DEPENDS:
-  case CURLOPT_STREAM_DEPENDS_E:
-  {
-#ifndef USE_NGHTTP2
-    return CURLE_NOT_BUILT_IN;
-#else
-    struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
-    if(!dep || GOOD_EASY_HANDLE(dep)) {
-      if(data->set.stream_depends_on) {
-        Curl_http2_remove_child(data->set.stream_depends_on, data);
-      }
-      Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
+      data->progress.flags |= PGRS_HIDE;
+      data->state.current_speed = -1; /* init to negative == impossible */
+      data->set.fnmatch = ZERO_NULL;
+      data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
+
+      Curl_http2_init_state(&data->state);
     }
-    break;
-#endif
   }
-  case CURLOPT_CONNECT_TO:
-    data->set.connect_to = va_arg(param, struct curl_slist *);
-    break;
-  case CURLOPT_SUPPRESS_CONNECT_HEADERS:
-    data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
-    break;
-  case CURLOPT_SSH_COMPRESSION:
-    data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
-    break;
-  default:
-    /* unknown tag and its companion, just ignore: */
-    result = CURLE_UNKNOWN_OPTION;
-    break;
+
+  if(result) {
+    Curl_resolver_cleanup(data->state.resolver);
+    free(data->state.buffer);
+    free(data->state.headerbuff);
+    Curl_freeset(data);
+    free(data);
+    data = NULL;
   }
+  else
+    *curl = data;
 
   return result;
 }
@@ -3081,6 +714,9 @@ static void conn_free(struct connectdata *conn)
   Curl_safefree(conn->unix_domain_socket);
 #endif
 
+#ifdef USE_SSL
+  Curl_safefree(conn->ssl_extra);
+#endif
   free(conn); /* free all the connection oriented data */
 }
 
@@ -3135,7 +771,7 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
 
     /* unlink ourselves! */
   infof(data, "Closing connection %ld\n", conn->connection_id);
-  Curl_conncache_remove_conn(data->state.conn_cache, conn);
+  Curl_conncache_remove_conn(conn, TRUE);
 
   free_fixed_hostname(&conn->host);
   free_fixed_hostname(&conn->conn_to_host);
@@ -3289,58 +925,6 @@ static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
   }
 }
 
-/*
- * This function finds the connection in the connection
- * cache that has been unused for the longest time.
- *
- * Returns the pointer to the oldest idle connection, or NULL if none was
- * found.
- */
-struct connectdata *
-Curl_oldest_idle_connection(struct Curl_easy *data)
-{
-  struct conncache *bc = data->state.conn_cache;
-  struct curl_hash_iterator iter;
-  struct curl_llist_element *curr;
-  struct curl_hash_element *he;
-  time_t highscore =- 1;
-  time_t score;
-  struct curltime now;
-  struct connectdata *conn_candidate = NULL;
-  struct connectbundle *bundle;
-
-  now = Curl_tvnow();
-
-  Curl_hash_start_iterate(&bc->hash, &iter);
-
-  he = Curl_hash_next_element(&iter);
-  while(he) {
-    struct connectdata *conn;
-
-    bundle = he->ptr;
-
-    curr = bundle->conn_list.head;
-    while(curr) {
-      conn = curr->ptr;
-
-      if(!conn->inuse) {
-        /* Set higher score for the age passed since the connection was used */
-        score = Curl_tvdiff(now, conn->now);
-
-        if(score > highscore) {
-          highscore = score;
-          conn_candidate = conn;
-        }
-      }
-      curr = curr->next;
-    }
-
-    he = Curl_hash_next_element(&iter);
-  }
-
-  return conn_candidate;
-}
-
 static bool
 proxy_info_matches(const struct proxy_info* data,
                    const struct proxy_info* needle)
@@ -3353,56 +937,17 @@ proxy_info_matches(const struct proxy_info* data,
   return FALSE;
 }
 
-
 /*
- * This function finds the connection in the connection
- * bundle that has been unused for the longest time.
+ * This function checks if the given connection is dead and extracts it from
+ * the connection cache if so.
  *
- * Returns the pointer to the oldest idle connection, or NULL if none was
- * found.
- */
-static struct connectdata *
-find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
-                                      struct connectbundle *bundle)
-{
-  struct curl_llist_element *curr;
-  time_t highscore = -1;
-  time_t score;
-  struct curltime now;
-  struct connectdata *conn_candidate = NULL;
-  struct connectdata *conn;
-
-  (void)data;
-
-  now = Curl_tvnow();
-
-  curr = bundle->conn_list.head;
-  while(curr) {
-    conn = curr->ptr;
-
-    if(!conn->inuse) {
-      /* Set higher score for the age passed since the connection was used */
-      score = Curl_tvdiff(now, conn->now);
-
-      if(score > highscore) {
-        highscore = score;
-        conn_candidate = conn;
-      }
-    }
-    curr = curr->next;
-  }
-
-  return conn_candidate;
-}
-
-/*
- * This function checks if given connection is dead and disconnects if so.
- * (That also removes it from the connection cache.)
+ * When this is called as a Curl_conncache_foreach() callback, the connection
+ * cache lock is held!
  *
- * Returns TRUE if the connection actually was dead and disconnected.
+ * Returns TRUE if the connection was dead and extracted.
  */
-static bool disconnect_if_dead(struct connectdata *conn,
-                               struct Curl_easy *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) {
@@ -3427,25 +972,30 @@ static bool disconnect_if_dead(struct connectdata *conn,
     if(dead) {
       conn->data = data;
       infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
-
-      /* disconnect resources */
-      Curl_disconnect(conn, /* dead_connection */TRUE);
+      Curl_conncache_remove_conn(conn, FALSE);
       return TRUE;
     }
   }
   return FALSE;
 }
 
+struct prunedead {
+  struct Curl_easy *data;
+  struct connectdata *extracted;
+};
+
 /*
- * Wrapper to use disconnect_if_dead() function in Curl_conncache_foreach()
+ * Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
  *
- * Returns always 0.
  */
-static int call_disconnect_if_dead(struct connectdata *conn,
-                                      void *param)
+static int call_extract_if_dead(struct connectdata *conn, void *param)
 {
-  struct Curl_easy* data = (struct Curl_easy*)param;
-  disconnect_if_dead(conn, data);
+  struct prunedead *p = (struct prunedead *)param;
+  if(extract_if_dead(conn, p->data)) {
+    /* stop the iteration here, pass back the connection that was extracted */
+    p->extracted = conn;
+    return 1;
+  }
   return 0; /* continue iteration */
 }
 
@@ -3456,12 +1006,18 @@ static int call_disconnect_if_dead(struct connectdata *conn,
  */
 static void prune_dead_connections(struct Curl_easy *data)
 {
-  struct curltime now = Curl_tvnow();
-  time_t elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
+  struct curltime now = Curl_now();
+  time_t elapsed = Curl_timediff(now, data->state.conn_cache->last_cleanup);
 
   if(elapsed >= 1000L) {
-    Curl_conncache_foreach(data->state.conn_cache, data,
-                           call_disconnect_if_dead);
+    struct prunedead prune;
+    prune.data = data;
+    prune.extracted = NULL;
+    while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
+                                 call_extract_if_dead)) {
+      /* disconnect it */
+      (void)Curl_disconnect(prune.extracted, /* dead_connection */TRUE);
+    }
     data->state.conn_cache->last_cleanup = now;
   }
 }
@@ -3516,8 +1072,8 @@ ConnectionExists(struct Curl_easy *data,
      Curl_pipeline_site_blacklisted(data, needle))
     canpipe &= ~ CURLPIPE_HTTP1;
 
-  /* Look up the bundle with all the connections to this
-     particular host */
+  /* 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 */
@@ -3540,6 +1096,7 @@ ConnectionExists(struct Curl_easy *data,
         if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) {
           infof(data, "Server doesn't support multi-use yet, wait\n");
           *waitpipe = TRUE;
+          Curl_conncache_unlock(needle);
           return FALSE; /* no re-use */
         }
 
@@ -3571,8 +1128,11 @@ ConnectionExists(struct Curl_easy *data,
       check = curr->ptr;
       curr = curr->next;
 
-      if(disconnect_if_dead(check, data))
+      if(extract_if_dead(check, data)) {
+        /* disconnect it */
+        (void)Curl_disconnect(check, /* dead_connection */TRUE);
         continue;
+      }
 
       pipeLen = check->send_pipe.size + check->recv_pipe.size;
 
@@ -3703,6 +1263,11 @@ ConnectionExists(struct Curl_easy *data,
            already in use so we skip it */
         continue;
 
+      if((check->inuse) && (check->data->multi != needle->data->multi))
+        /* this could be subject for pipeline/multiplex use, but only
+           if they belong to the same multi handle */
+        continue;
+
       if(needle->localdev || needle->localport) {
         /* If we are bound to a specific local end (IP+port), we must not
            re-use a random other one, although if we didn't ask for a
@@ -3889,9 +1454,13 @@ ConnectionExists(struct Curl_easy *data,
   }
 
   if(chosen) {
+    /* mark it as used before releasing the lock */
+    chosen->inuse = TRUE;
+    Curl_conncache_unlock(needle);
     *usethis = chosen;
     return TRUE; /* yes, we found one to use! */
   }
+  Curl_conncache_unlock(needle);
 
   if(foundPendingCandidate && data->set.pipewait) {
     infof(data,
@@ -4104,7 +1673,7 @@ static bool is_ASCII_name(const char *hostname)
 /*
  * Perform any necessary IDN conversion of hostname
  */
-static void fix_hostname(struct connectdata *conn, struct hostname *host)
+static CURLcode fix_hostname(struct connectdata *conn, struct hostname *host)
 {
   size_t len;
   struct Curl_easy *data = conn->data;
@@ -4144,9 +1713,11 @@ static void fix_hostname(struct connectdata *conn, struct hostname *host)
         /* change the name pointer to point to the encoded hostname */
         host->name = host->encalloc;
       }
-      else
-        infof(data, "Failed to convert %s to ACE; %s\n", host->name,
+      else {
+        failf(data, "Failed to convert %s to ACE; %s\n", host->name,
               idn2_strerror(rc));
+        return CURLE_URL_MALFORMAT;
+      }
     }
 #elif defined(USE_WIN32_IDN)
     char *ace_hostname = NULL;
@@ -4156,12 +1727,24 @@ static void fix_hostname(struct connectdata *conn, struct hostname *host)
       /* change the name pointer to point to the encoded hostname */
       host->name = host->encalloc;
     }
-    else
-      infof(data, "Failed to convert %s to ACE;\n", host->name);
+    else {
+      failf(data, "Failed to convert %s to ACE;\n", host->name);
+      return CURLE_URL_MALFORMAT;
+    }
 #else
     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;
 }
 
 /*
@@ -4196,15 +1779,30 @@ static void llist_dtor(void *user, void *element)
  */
 static struct connectdata *allocate_conn(struct Curl_easy *data)
 {
-#ifdef USE_SSL
-#define SSL_EXTRA + 4 * Curl_ssl->sizeof_ssl_backend_data - sizeof(long long)
-#else
-#define SSL_EXTRA 0
-#endif
-  struct connectdata *conn = calloc(1, sizeof(struct connectdata) + SSL_EXTRA);
+  struct connectdata *conn = calloc(1, sizeof(struct connectdata));
   if(!conn)
     return NULL;
 
+#ifdef USE_SSL
+  /* The SSL backend-specific data (ssl_backend_data) objects are allocated as
+     a separate array to ensure suitable alignment.
+     Note that these backend pointers can be swapped by vtls (eg ssl backend
+     data becomes proxy backend data). */
+  {
+    size_t sslsize = Curl_ssl->sizeof_ssl_backend_data;
+    char *ssl = calloc(4, sslsize);
+    if(!ssl) {
+      free(conn);
+      return NULL;
+    }
+    conn->ssl_extra = ssl;
+    conn->ssl[0].backend = (void *)ssl;
+    conn->ssl[1].backend = (void *)(ssl + sslsize);
+    conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize);
+    conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize);
+  }
+#endif
+
   conn->handler = &Curl_handler_dummy;  /* Be sure we have a handler defined
                                            already from start to avoid NULL
                                            situations and checks */
@@ -4229,7 +1827,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   connclose(conn, "Default to force-close");
 
   /* Store creation time to help future close decision making */
-  conn->created = Curl_tvnow();
+  conn->created = Curl_now();
 
   conn->data = data; /* Setup the association between this connection
                         and the Curl_easy */
@@ -4284,23 +1882,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
 
   conn->ip_version = data->set.ipver;
 
-#ifdef USE_SSL
-  /*
-   * To save on malloc()s, the SSL backend-specific data has been allocated
-   * at the end of the connectdata struct.
-   */
-  {
-    char *p = (char *)&conn->align_data__do_not_use;
-    conn->ssl[0].backend = (struct ssl_backend_data *)p;
-    conn->ssl[1].backend =
-      (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data);
-    conn->proxy_ssl[0].backend =
-      (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data * 2);
-    conn->proxy_ssl[1].backend =
-      (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data * 3);
-  }
-#endif
-
 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
     defined(NTLM_WB_ENABLED)
   conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
@@ -4347,6 +1928,9 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
 
   free(conn->master_buffer);
   free(conn->localdev);
+#ifdef USE_SSL
+  free(conn->ssl_extra);
+#endif
   free(conn);
   return NULL;
 }
@@ -4442,6 +2026,14 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
     ('A' <= str[0] && str[0] <= 'Z')) && \
    (str[1] == ':'))
 
+  /* MSDOS/Windows style drive prefix, optionally with
+   * a '|' instead of ':', followed by a slash or NUL */
+#define STARTS_WITH_URL_DRIVE_PREFIX(str) \
+  ((('a' <= (str)[0] && (str)[0] <= 'z') || \
+    ('A' <= (str)[0] && (str)[0] <= 'Z')) && \
+   ((str)[1] == ':' || (str)[1] == '|') && \
+   ((str)[2] == '/' || (str)[2] == '\\' || (str)[2] == 0))
+
   /* Don't mistake a drive letter for a scheme if the default protocol is file.
      curld --proto-default file c:/foo/bar.txt */
   if(STARTS_WITH_DRIVE_PREFIX(data->change.url) &&
@@ -4474,63 +2066,90 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
       return CURLE_URL_MALFORMAT;
     }
 
-    if(url_has_scheme && path[0] == '/' && path[1] == '/') {
-      /* Allow omitted hostname (e.g. file:/<path>).  This is not strictly
-       * speaking a valid file: URL by RFC 1738, but treating file:/<path> as
-       * file://localhost/<path> is similar to how other schemes treat missing
-       * hostnames.  See RFC 1808. */
-
-      /* This cannot be done with strcpy() in a portable manner, since the
-         memory areas overlap! */
-      memmove(path, path + 2, strlen(path + 2) + 1);
+    if(url_has_scheme && path[0] == '/' && path[1] == '/' &&
+       path[2] == '/' && path[3] == '/') {
+      /* This appears to be a UNC string (usually indicating a SMB share).
+       * We don't do SMB in file: URLs. (TODO?)
+       */
+      failf(data, "SMB shares are not supported in file: URLs.");
+      return CURLE_URL_MALFORMAT;
     }
 
-    /*
-     * we deal with file://<host>/<path> differently since it supports no
-     * hostname other than "localhost" and "127.0.0.1", which is unique among
-     * the URL protocols specified in RFC 1738
+    /* Extra handling URLs with an authority component (i.e. that start with
+     * "file://")
+     *
+     * We allow omitted hostname (e.g. file:/<path>) -- valid according to
+     * RFC 8089, but not the (current) WHAT-WG URL spec.
      */
-    if(path[0] != '/' && !STARTS_WITH_DRIVE_PREFIX(path)) {
-      /* the URL includes a host name, it must match "localhost" or
-         "127.0.0.1" to be valid */
-      char *ptr;
-      if(!checkprefix("localhost/", path) &&
-         !checkprefix("127.0.0.1/", path)) {
-        failf(data, "Invalid file://hostname/, "
-                    "expected localhost or 127.0.0.1 or none");
-        return CURLE_URL_MALFORMAT;
-      }
-      ptr = &path[9]; /* now points to the slash after the host */
-
-      /* there was a host name and slash present
-
-         RFC1738 (section 3.1, page 5) says:
-
-         The rest of the locator consists of data specific to the scheme,
-         and is known as the "url-path". It supplies the details of how the
-         specified resource can be accessed. Note that the "/" between the
-         host (or port) and the url-path is NOT part of the url-path.
+    if(url_has_scheme && path[0] == '/' && path[1] == '/') {
+      /* swallow the two slashes */
+      char *ptr = &path[2];
 
-         As most agents use file://localhost/foo to get '/foo' although the
-         slash preceding foo is a separator and not a slash for the path,
-         a URL as file://localhost//foo must be valid as well, to refer to
-         the same file with an absolute path.
-      */
+      /*
+       * According to RFC 8089, a file: URL can be reliably dereferenced if:
+       *
+       *  o it has no/blank hostname, or
+       *
+       *  o the hostname matches "localhost" (case-insensitively), or
+       *
+       *  o the hostname is a FQDN that resolves to this machine.
+       *
+       * For brevity, we only consider URLs with empty, "localhost", or
+       * "127.0.0.1" hostnames as local.
+       *
+       * Additionally, there is an exception for URLs with a Windows drive
+       * letter in the authority (which was accidentally omitted from RFC 8089
+       * Appendix E, but believe me, it was meant to be there. --MK)
+       */
+      if(ptr[0] != '/' && !STARTS_WITH_URL_DRIVE_PREFIX(ptr)) {
+        /* the URL includes a host name, it must match "localhost" or
+           "127.0.0.1" to be valid */
+        if(!checkprefix("localhost/", ptr) &&
+           !checkprefix("127.0.0.1/", ptr)) {
+          failf(data, "Invalid file://hostname/, "
+                      "expected localhost or 127.0.0.1 or none");
+          return CURLE_URL_MALFORMAT;
+        }
+        ptr += 9; /* now points to the slash after the host */
+      }
 
-      if('/' == ptr[1])
-        /* if there was two slashes, we skip the first one as that is then
-           used truly as a separator */
+      /*
+       * RFC 8089, Appendix D, Section D.1, says:
+       *
+       * > In a POSIX file system, the root of the file system is represented
+       * > as a directory with a zero-length name, usually written as "/"; the
+       * > presence of this root in a file URI can be taken as given by the
+       * > initial slash in the "path-absolute" rule.
+       *
+       * i.e. the first slash is part of the path.
+       *
+       * However in RFC 1738 the "/" between the host (or port) and the
+       * URL-path was NOT part of the URL-path.  Any agent that followed the
+       * older spec strictly, and wanted to refer to a file with an absolute
+       * path, would have included a second slash.  So if there are two
+       * slashes, swallow one.
+       */
+      if('/' == ptr[1]) /* note: the only way ptr[0]!='/' is if ptr[1]==':' */
         ptr++;
 
-      /* This cannot be made with strcpy, as the memory chunks overlap! */
+      /* This cannot be done with strcpy, as the memory chunks overlap! */
       memmove(path, ptr, strlen(ptr) + 1);
     }
 
 #if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
-    if(STARTS_WITH_DRIVE_PREFIX(path)) {
+    /* Don't allow Windows drive letters when not in Windows.
+     * This catches both "file:/c:" and "file:c:" */
+    if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
+       STARTS_WITH_URL_DRIVE_PREFIX(path)) {
       failf(data, "File drive letters are only accepted in MSDOS/Windows.");
       return CURLE_URL_MALFORMAT;
     }
+#else
+    /* If the path starts with a slash and a drive letter, ditch the slash */
+    if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) {
+      /* This cannot be done with strcpy, as the memory chunks overlap! */
+      memmove(path, &path[1], strlen(&path[1]) + 1);
+    }
 #endif
 
     protop = "file"; /* protocol string */
@@ -5142,8 +2761,8 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   atsign = strchr(proxyptr, '@');
   if(atsign) {
     CURLcode result =
-      parse_login_details(proxyptr, atsign - proxyptr,
-                              &proxyuser, &proxypasswd, NULL);
+      Curl_parse_login_details(proxyptr, atsign - proxyptr,
+                               &proxyuser, &proxypasswd, NULL);
     if(result)
       return result;
     proxyptr = atsign + 1;
@@ -5534,10 +3153,11 @@ static CURLcode parse_url_login(struct Curl_easy *data,
 
   /* We could use the login information in the URL so extract it. Only parse
      options if the handler says we should. */
-  result = parse_login_details(login, ptr - login - 1,
-                               &userp, &passwdp,
-                               (conn->handler->flags & PROTOPT_URLOPTIONS)?
-                               &optionsp:NULL);
+  result =
+    Curl_parse_login_details(login, ptr - login - 1,
+                             &userp, &passwdp,
+                             (conn->handler->flags & PROTOPT_URLOPTIONS)?
+                             &optionsp:NULL);
   if(result)
     goto out;
 
@@ -5593,7 +3213,7 @@ static CURLcode parse_url_login(struct Curl_easy *data,
 }
 
 /*
- * parse_login_details()
+ * Curl_parse_login_details()
  *
  * This is used to parse a login string for user name, password and options in
  * the following formats:
@@ -5621,9 +3241,9 @@ static CURLcode parse_url_login(struct Curl_easy *data,
  *
  * Returns CURLE_OK on success.
  */
-static CURLcode parse_login_details(const char *login, const size_t len,
-                                    char **userp, char **passwdp,
-                                    char **optionsp)
+CURLcode Curl_parse_login_details(const char *login, const size_t len,
+                                  char **userp, char **passwdp,
+                                  char **optionsp)
 {
   CURLcode result = CURLE_OK;
   char *ubuf = NULL;
@@ -5752,7 +3372,13 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
     portptr = strchr(conn->host.name, ']');
     if(portptr) {
       *portptr++ = '\0'; /* zero terminate, killing the bracket */
-      if(':' != *portptr)
+      if(*portptr) {
+        if (*portptr != ':') {
+          failf(data, "IPv6 closing bracket followed by '%c'", *portptr);
+          return CURLE_URL_MALFORMAT;
+        }
+      }
+      else
         portptr = NULL; /* no port number available */
     }
   }
@@ -5986,6 +3612,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
 
   /* detect and extract RFC6874-style IPv6-addresses */
   if(*hostptr == '[') {
+#ifdef ENABLE_IPV6
     char *ptr = ++hostptr; /* advance beyond the initial bracket */
     while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
       ptr++;
@@ -6009,6 +3636,11 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
      * hostptr first, but I can't see anything wrong with that as no host
      * name nor a numeric can legally start with a bracket.
      */
+#else
+    failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in!");
+    free(host_dup);
+    return CURLE_NOT_BUILT_IN;
+#endif
   }
 
   /* Get port number off server.com:1080 */
@@ -6171,7 +3803,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
                                bool *async)
 {
   CURLcode result = CURLE_OK;
-  time_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
+  timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
 
   /*************************************************************
    * Resolve the name of the server or proxy
@@ -6588,13 +4220,24 @@ static CURLcode create_conn(struct Curl_easy *data,
   /*************************************************************
    * IDN-fix the hostnames
    *************************************************************/
-  fix_hostname(conn, &conn->host);
-  if(conn->bits.conn_to_host)
-    fix_hostname(conn, &conn->conn_to_host);
-  if(conn->bits.httpproxy)
-    fix_hostname(conn, &conn->http_proxy.host);
-  if(conn->bits.socksproxy)
-    fix_hostname(conn, &conn->socks_proxy.host);
+  result = fix_hostname(conn, &conn->host);
+  if(result)
+    goto out;
+  if(conn->bits.conn_to_host) {
+    result = fix_hostname(conn, &conn->conn_to_host);
+    if(result)
+      goto out;
+  }
+  if(conn->bits.httpproxy) {
+    result = fix_hostname(conn, &conn->http_proxy.host);
+    if(result)
+      goto out;
+  }
+  if(conn->bits.socksproxy) {
+    result = fix_hostname(conn, &conn->socks_proxy.host);
+    if(result)
+      goto out;
+  }
 
   /*************************************************************
    * Check whether the host and the "connect to host" are equal.
@@ -6751,20 +4394,21 @@ static CURLcode create_conn(struct Curl_easy *data,
   else
     reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
 
-  /* If we found a reusable connection, we may still want to
-     open a new connection if we are pipelining. */
+  /* 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);
 
-      if(conn_temp->bundle->num_connections < max_host_connections &&
-         data->state.conn_cache->num_connections < max_total_connections) {
+      if(Curl_conncache_bundle_size(conn_temp) < max_host_connections &&
+         Curl_conncache_size(data) < max_total_connections) {
         /* We want a new connection anyway */
         reuse = FALSE;
 
         infof(data, "We can reuse, but we want a new connection anyway\n");
+        Curl_conncache_return_conn(conn_temp);
       }
     }
   }
@@ -6776,9 +4420,10 @@ static CURLcode create_conn(struct Curl_easy *data,
      * just allocated before we can move along and use the previously
      * existing one.
      */
-    conn_temp->inuse = TRUE; /* mark this as being in use so that no other
-                                handle in a multi stack may nick it */
     reuse_conn(conn, conn_temp);
+#ifdef USE_SSL
+    free(conn->ssl_extra);
+#endif
     free(conn);          /* we don't need this anymore */
     conn = conn_temp;
     *in_connect = conn;
@@ -6794,7 +4439,6 @@ static CURLcode create_conn(struct Curl_easy *data,
     /* We have decided that we want a new connection. However, we may not
        be able to do that if we have reached the limit of how many
        connections we are allowed to open. */
-    struct connectbundle *bundle = NULL;
 
     if(conn->handler->flags & PROTOPT_ALPN_NPN) {
       /* The protocol wants it, so set the bits if enabled in the easy handle
@@ -6809,35 +4453,42 @@ static CURLcode create_conn(struct Curl_easy *data,
       /* There is a connection that *might* become usable for pipelining
          "soon", and we wait for that */
       connections_available = FALSE;
-    else
-      bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
-
-    if(max_host_connections > 0 && bundle &&
-       (bundle->num_connections >= max_host_connections)) {
-      struct connectdata *conn_candidate;
-
-      /* The bundle is full. Let's see if we can kill a connection. */
-      conn_candidate = find_oldest_idle_connection_in_bundle(data, bundle);
-
-      if(conn_candidate) {
-        /* Set the connection's owner correctly, then kill it */
-        conn_candidate->data = data;
-        (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
-      }
-      else {
-        infof(data, "No more connections allowed to host: %d\n",
-              max_host_connections);
-        connections_available = FALSE;
+    else {
+      /* this gets a lock on the conncache */
+      struct connectbundle *bundle =
+        Curl_conncache_find_bundle(conn, data->state.conn_cache);
+
+      if(max_host_connections > 0 && bundle &&
+         (bundle->num_connections >= max_host_connections)) {
+        struct connectdata *conn_candidate;
+
+        /* The bundle is full. Extract the oldest connection. */
+        conn_candidate = Curl_conncache_extract_bundle(data, bundle);
+        Curl_conncache_unlock(conn);
+
+        if(conn_candidate) {
+          /* Set the connection's owner correctly, then kill it */
+          conn_candidate->data = data;
+          (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
+        }
+        else {
+          infof(data, "No more connections allowed to host: %d\n",
+                max_host_connections);
+          connections_available = FALSE;
+        }
       }
+      else
+        Curl_conncache_unlock(conn);
+
     }
 
     if(connections_available &&
        (max_total_connections > 0) &&
-       (data->state.conn_cache->num_connections >= max_total_connections)) {
+       (Curl_conncache_size(data) >= max_total_connections)) {
       struct connectdata *conn_candidate;
 
       /* The cache is full. Let's see if we can kill a connection. */
-      conn_candidate = Curl_oldest_idle_connection(data);
+      conn_candidate = Curl_conncache_extract_oldest(data);
 
       if(conn_candidate) {
         /* Set the connection's owner correctly, then kill it */
@@ -6860,6 +4511,9 @@ static CURLcode create_conn(struct Curl_easy *data,
       goto out;
     }
     else {
+      /* Mark the connection as used, before we add it */
+      conn->inuse = TRUE;
+
       /*
        * This is a brand new connection, so let's store it in the connection
        * cache of ours!
@@ -6887,9 +4541,6 @@ static CURLcode create_conn(struct Curl_easy *data,
 #endif
   }
 
-  /* Mark the connection as used */
-  conn->inuse = TRUE;
-
   /* Setup and init stuff before DO starts, in preparing for the transfer. */
   Curl_init_do(data, conn);
 
@@ -6972,7 +4623,7 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
 
   /* set start time here for timeout purposes in the connect procedure, it
      is later set again for the progress meter purpose */
-  conn->now = Curl_tvnow();
+  conn->now = Curl_now();
 
   if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
     conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
@@ -6989,22 +4640,8 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
     Curl_verboseconnect(conn);
   }
 
-  conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
-                               set this here perhaps a second time */
-
-#ifdef __EMX__
-  /*
-   * This check is quite a hack. We're calling _fsetmode to fix the problem
-   * with fwrite converting newline characters (you get mangled text files,
-   * and corrupted binary files when you download to stdout and redirect it to
-   * a file).
-   */
-
-  if((data->set.out)->_handle == NULL) {
-    _fsetmode(stdout, "b");
-  }
-#endif
-
+  conn->now = Curl_now(); /* time this *after* the connect is done, we set
+                             this here perhaps a second time */
   return result;
 }
 
@@ -7062,13 +4699,17 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
 {
   struct SingleRequest *k = &data->req;
 
-  if(conn)
-    conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
-                                 * use */
+  conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
+                                 use */
 
   data->state.done = FALSE; /* *_done() is not called yet */
   data->state.expect100header = FALSE;
 
+  /* if the protocol used doesn't support wildcards, switch it off */
+  if(data->state.wildcardmatch &&
+     !(conn->handler->flags & PROTOPT_WILDCARD))
+    data->state.wildcardmatch = FALSE;
+
   if(data->set.opt_no_body)
     /* in HTTP lingo, no body means using the HEAD request... */
     data->set.httpreq = HTTPREQ_HEAD;
@@ -7080,7 +4721,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
        HTTP. */
     data->set.httpreq = HTTPREQ_GET;
 
-  k->start = Curl_tvnow(); /* start time */
+  k->start = Curl_now(); /* start time */
   k->now = k->start;   /* current time is now */
   k->header = TRUE; /* assume header */
 
diff --git a/lib/url.h b/lib/url.h
index f13c8e6..a70bd54 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, 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,15 +23,17 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
+#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
+#define READBUFFER_MAX  CURL_MAX_READ_SIZE
+#define READBUFFER_MIN  1024
+
 /*
  * Prototypes for library-wide functions provided by url.c
  */
 
 CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn);
 CURLcode Curl_open(struct Curl_easy **curl);
-CURLcode Curl_init_userdefined(struct UserDefined *set);
-CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
-                     va_list arg);
+CURLcode Curl_init_userdefined(struct Curl_easy *data);
 CURLcode Curl_dupset(struct Curl_easy * dst, struct Curl_easy * src);
 void Curl_freeset(struct Curl_easy * data);
 CURLcode Curl_close(struct Curl_easy *data); /* opposite of curl_open() */
@@ -51,14 +53,14 @@ int Curl_protocol_getsock(struct connectdata *conn,
 int Curl_doing_getsock(struct connectdata *conn,
                        curl_socket_t *socks,
                        int numsocks);
-
+CURLcode Curl_parse_login_details(const char *login, const size_t len,
+                                  char **userptr, char **passwdptr,
+                                  char **optionsptr);
 bool Curl_isPipeliningEnabled(const struct Curl_easy *handle);
 CURLcode Curl_addHandleToPipeline(struct Curl_easy *handle,
                                   struct curl_llist *pipeline);
 int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
                                   struct curl_llist *pipeline);
-struct connectdata *
-Curl_oldest_idle_connection(struct Curl_easy *data);
 /* remove the specified connection from all (possible) pipelines and related
    queues */
 void Curl_getoff_all_pipelines(struct Curl_easy *data,
diff --git a/lib/urldata.h b/lib/urldata.h
index 66e4596..5c04ad1 100644
--- a/lib/urldata.h
+++ b/lib/urldata.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
@@ -85,17 +85,12 @@
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
 
 #include "timeval.h"
 
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>               /* for content-encoding */
-#ifdef __SYMBIAN32__
-/* zlib pollutes the namespace with this definition */
-#undef WIN32
-#endif
-#endif
-
 #include <curl/curl.h>
 
 #include "http_chunks.h" /* for the structs and enum stuff */
@@ -286,6 +281,7 @@ struct digestdata {
   char *qop;
   char *algorithm;
   int nc; /* nounce count */
+  bool userhash;
 #endif
 };
 
@@ -463,16 +459,6 @@ struct hostname {
 #define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
 
 
-#ifdef HAVE_LIBZ
-typedef enum {
-  ZLIB_UNINIT,          /* uninitialized */
-  ZLIB_INIT,            /* initialized */
-  ZLIB_GZIP_HEADER,     /* reading gzip header */
-  ZLIB_GZIP_INFLATING,  /* inflating gzip stream */
-  ZLIB_INIT_GZIP        /* initialized in transparent gzip mode */
-} zlibInitState;
-#endif
-
 #ifdef CURLRES_ASYNCH
 struct Curl_async {
   char *hostname;
@@ -560,18 +546,8 @@ struct SingleRequest {
   enum expect100 exp100;        /* expect 100 continue state */
   enum upgrade101 upgr101;      /* 101 upgrade state */
 
-  int auto_decoding;            /* What content encoding. sec 3.5, RFC2616. */
-
-#define IDENTITY 0              /* No encoding */
-#define DEFLATE 1               /* zlib deflate [RFC 1950 & 1951] */
-#define GZIP 2                  /* gzip algorithm [RFC 1952] */
-
-#ifdef HAVE_LIBZ
-  zlibInitState zlib_init;      /* possible zlib init state;
-                                   undefined if Content-Encoding header. */
-  z_stream z;                   /* State structure for zlib. */
-#endif
-
+  struct contenc_writer_s *writer_stack;  /* Content unencoding stack. */
+                                          /* See sec 3.5, RFC2616. */
   time_t timeofdoc;
   long bodywrites;
 
@@ -719,6 +695,7 @@ struct Curl_handler {
 #define PROTOPT_PROXY_AS_HTTP (1<<11) /* allow this non-HTTP scheme over a
                                          HTTP proxy as HTTP proxies may know
                                          this protocol and act as a gateway */
+#define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */
 
 #define CONNCHECK_NONE 0                 /* No checks */
 #define CONNCHECK_ISDEAD (1<<0)          /* Check if the connection is dead. */
@@ -778,6 +755,7 @@ struct http_connect_state {
     TUNNEL_CONNECT, /* CONNECT has been sent off */
     TUNNEL_COMPLETE /* CONNECT response received completely */
   } tunnel_state;
+  bool close_connection;
 };
 
 /*
@@ -801,9 +779,10 @@ struct connectdata {
   void *closesocket_client;
 
   bool inuse; /* This is a marker for the connection cache logic. If this is
-                 TRUE this handle is being used by an easy handle and cannot
-                 be used by any other easy handle without careful
-                 consideration (== only for pipelining). */
+                 TRUE this handle is being 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! */
 
   /**** Fields set when inited and not modified again */
   long connection_id; /* Contains a unique number to make it easier to
@@ -886,6 +865,9 @@ struct connectdata {
 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
   struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
   struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */
+#ifdef USE_SSL
+  void *ssl_extra; /* separately allocated backend-specific data */
+#endif
   struct ssl_primary_config ssl_config;
   struct ssl_primary_config proxy_ssl_config;
   bool tls_upgraded;
@@ -1030,16 +1012,6 @@ struct connectdata {
   char *unix_domain_socket;
   bool abstract_unix_socket;
 #endif
-
-#ifdef USE_SSL
-  /*
-   * To avoid multiple malloc() calls, the ssl_connect_data structures
-   * associated with a connectdata struct are allocated in the same block
-   * as the latter. This field forces alignment to an 8-byte boundary so
-   * that this all works.
-   */
-  long long *align_data__do_not_use;
-#endif
 };
 
 /* The end of connectdata. */
@@ -1308,7 +1280,7 @@ struct UrlState {
 
   /* 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 */
@@ -1358,6 +1330,9 @@ struct UrlState {
   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
 };
 
 
@@ -1443,7 +1418,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 */
-#ifdef USE_LIBSSH2
+#if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
   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 */
@@ -1453,7 +1428,7 @@ enum dupstring {
   STRING_PROXY_SERVICE_NAME, /* Proxy service name */
 #endif
 #if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
-    defined(USE_SPNEGO)
+  defined(USE_SPNEGO) || defined(HAVE_GSSAPI)
   STRING_SERVICE_NAME,    /* Service name */
 #endif
   STRING_MAIL_FROM,
@@ -1624,7 +1599,7 @@ struct UserDefined {
   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 http_disable_hostname_check_before_authentication;
+  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: */
@@ -1672,7 +1647,7 @@ struct UserDefined {
   /* Common RTSP header options */
   Curl_RtspReq rtspreq; /* RTSP request type */
   long rtspversion; /* like httpversion, for RTSP */
-  bool wildcardmatch; /* enable wildcard matching */
+  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
diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c
index 185098e..131d9da 100644
--- a/lib/vauth/digest.c
+++ b/lib/vauth/digest.c
@@ -19,6 +19,7 @@
  * KIND, either express or implied.
  *
  * RFC2831 DIGEST-MD5 authentication
+ * RFC7616 DIGEST-SHA256, DIGEST-SHA512-256 authentication
  *
  ***************************************************************************/
 
@@ -34,6 +35,7 @@
 #include "curl_base64.h"
 #include "curl_hmac.h"
 #include "curl_md5.h"
+#include "curl_sha256.h"
 #include "vtls/vtls.h"
 #include "warnless.h"
 #include "strtok.h"
@@ -144,6 +146,15 @@ static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */
     snprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
 }
 
+/* Convert sha256 chunk to RFC7616 -suitable ascii string*/
+static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */
+                                     unsigned char *dest) /* 65 bytes */
+{
+  int i;
+  for(i = 0; i < 32; i++)
+    snprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
+}
+
 /* Perform quoted-string escaping as described in RFC2616 and its errata */
 static char *auth_digest_string_quoted(const char *source)
 {
@@ -602,9 +613,22 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
           digest->algo = CURLDIGESTALGO_MD5SESS;
         else if(strcasecompare(content, "MD5"))
           digest->algo = CURLDIGESTALGO_MD5;
+        else if(strcasecompare(content, "SHA-256"))
+          digest->algo = CURLDIGESTALGO_SHA256;
+        else if(strcasecompare(content, "SHA-256-SESS"))
+          digest->algo = CURLDIGESTALGO_SHA256SESS;
+        else if(strcasecompare(content, "SHA-512-256"))
+          digest->algo = CURLDIGESTALGO_SHA512_256;
+        else if(strcasecompare(content, "SHA-512-256-SESS"))
+          digest->algo = CURLDIGESTALGO_SHA512_256SESS;
         else
           return CURLE_BAD_CONTENT_ENCODING;
       }
+      else if(strcasecompare(value, "userhash")) {
+        if(strcasecompare(content, "true")) {
+          digest->userhash = TRUE;
+        }
+      }
       else {
         /* Unknown specifier, ignore it! */
       }
@@ -635,7 +659,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
 }
 
 /*
- * Curl_auth_create_digest_http_message()
+ * _Curl_auth_create_digest_http_message()
  *
  * This is used to generate a HTTP DIGEST response message ready for sending
  * to the recipient.
@@ -654,20 +678,24 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
  *
  * Returns CURLE_OK on success.
  */
-CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
-                                              const char *userp,
-                                              const char *passwdp,
-                                              const unsigned char *request,
-                                              const unsigned char *uripath,
-                                              struct digestdata *digest,
-                                              char **outptr, size_t *outlen)
+static CURLcode _Curl_auth_create_digest_http_message(
+                  struct Curl_easy *data,
+                  const char *userp,
+                  const char *passwdp,
+                  const unsigned char *request,
+                  const unsigned char *uripath,
+                  struct digestdata *digest,
+                  char **outptr, size_t *outlen,
+                  void (*convert_to_ascii)(unsigned char *, unsigned char *),
+                  void (*hash)(unsigned char *, const unsigned char *))
 {
   CURLcode result;
-  unsigned char md5buf[16]; /* 16 bytes/128 bits */
-  unsigned char request_digest[33];
-  unsigned char *md5this;
-  unsigned char ha1[33];    /* 32 digits and 1 zero byte */
-  unsigned char ha2[33];    /* 32 digits and 1 zero byte */
+  unsigned char hashbuf[32]; /* 32 bytes/256 bits */
+  unsigned char request_digest[65];
+  unsigned char *hashthis;
+  unsigned char ha1[65];    /* 64 digits and 1 zero byte */
+  unsigned char ha2[65];    /* 64 digits and 1 zero byte */
+  char userh[65];
   char cnoncebuf[33];
   char *cnonce = NULL;
   size_t cnonce_sz = 0;
@@ -692,6 +720,17 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
     digest->cnonce = cnonce;
   }
 
+  if(digest->userhash) {
+    hashthis = (unsigned char *) aprintf("%s:%s", userp, digest->realm);
+    if(!hashthis)
+      return CURLE_OUT_OF_MEMORY;
+
+    CURL_OUTPUT_DIGEST_CONV(data, hashthis);
+    hash(hashbuf, hashthis);
+    free(hashthis);
+    convert_to_ascii(hashbuf, (unsigned char *)userh);
+  }
+
   /*
     If the algorithm is "MD5" or unspecified (which then defaults to MD5):
 
@@ -703,26 +742,29 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
            unq(nonce-value) ":" unq(cnonce-value)
   */
 
-  md5this = (unsigned char *)
-    aprintf("%s:%s:%s", userp, digest->realm, passwdp);
-  if(!md5this)
+  hashthis = (unsigned char *)
+    aprintf("%s:%s:%s", digest->userhash ? userh : userp,
+                                    digest->realm, passwdp);
+  if(!hashthis)
     return CURLE_OUT_OF_MEMORY;
 
-  CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
-  Curl_md5it(md5buf, md5this);
-  free(md5this);
-  auth_digest_md5_to_ascii(md5buf, ha1);
+  CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */
+  hash(hashbuf, hashthis);
+  free(hashthis);
+  convert_to_ascii(hashbuf, ha1);
 
-  if(digest->algo == CURLDIGESTALGO_MD5SESS) {
+  if(digest->algo == CURLDIGESTALGO_MD5SESS ||
+     digest->algo == CURLDIGESTALGO_SHA256SESS ||
+     digest->algo == CURLDIGESTALGO_SHA512_256SESS) {
     /* nonce and cnonce are OUTSIDE the hash */
     tmp = aprintf("%s:%s:%s", ha1, digest->nonce, digest->cnonce);
     if(!tmp)
       return CURLE_OUT_OF_MEMORY;
 
     CURL_OUTPUT_DIGEST_CONV(data, tmp); /* Convert on non-ASCII machines */
-    Curl_md5it(md5buf, (unsigned char *) tmp);
+    hash(hashbuf, (unsigned char *) tmp);
     free(tmp);
-    auth_digest_md5_to_ascii(md5buf, ha1);
+    convert_to_ascii(hashbuf, ha1);
   }
 
   /*
@@ -738,27 +780,32 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
     5.1.1 of RFC 2616)
   */
 
-  md5this = (unsigned char *) aprintf("%s:%s", request, uripath);
+  hashthis = (unsigned char *) aprintf("%s:%s", request, uripath);
 
   if(digest->qop && strcasecompare(digest->qop, "auth-int")) {
     /* We don't support auth-int for PUT or POST at the moment.
-       TODO: replace md5 of empty string with entity-body for PUT/POST */
-    unsigned char *md5this2 = (unsigned char *)
-      aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e");
-    free(md5this);
-    md5this = md5this2;
+       TODO: replace hash of empty string with entity-body for PUT/POST */
+    char hashed[65];
+    unsigned char *hashthis2;
+
+    hash(hashbuf, (const unsigned char *)"");
+    convert_to_ascii(hashbuf, (unsigned char *)hashed);
+
+    hashthis2 = (unsigned char *)aprintf("%s:%s", hashthis, hashed);
+    free(hashthis);
+    hashthis = hashthis2;
   }
 
-  if(!md5this)
+  if(!hashthis)
     return CURLE_OUT_OF_MEMORY;
 
-  CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
-  Curl_md5it(md5buf, md5this);
-  free(md5this);
-  auth_digest_md5_to_ascii(md5buf, ha2);
+  CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */
+  hash(hashbuf, hashthis);
+  free(hashthis);
+  convert_to_ascii(hashbuf, ha2);
 
   if(digest->qop) {
-    md5this = (unsigned char *) aprintf("%s:%s:%08x:%s:%s:%s",
+    hashthis = (unsigned char *) aprintf("%s:%s:%08x:%s:%s:%s",
                                         ha1,
                                         digest->nonce,
                                         digest->nc,
@@ -767,19 +814,19 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
                                         ha2);
   }
   else {
-    md5this = (unsigned char *) aprintf("%s:%s:%s",
+    hashthis = (unsigned char *) aprintf("%s:%s:%s",
                                         ha1,
                                         digest->nonce,
                                         ha2);
   }
 
-  if(!md5this)
+  if(!hashthis)
     return CURLE_OUT_OF_MEMORY;
 
-  CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
-  Curl_md5it(md5buf, md5this);
-  free(md5this);
-  auth_digest_md5_to_ascii(md5buf, request_digest);
+  CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */
+  hash(hashbuf, hashthis);
+  free(hashthis);
+  convert_to_ascii(hashbuf, request_digest);
 
   /* For test case 64 (snooped from a Mozilla 1.3a request)
 
@@ -794,7 +841,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
      characters.  algorithm and qop with standard values only contain web-safe
      characters.
   */
-  userp_quoted = auth_digest_string_quoted(userp);
+  userp_quoted = auth_digest_string_quoted(digest->userhash ? userh : userp);
   if(!userp_quoted)
     return CURLE_OUT_OF_MEMORY;
 
@@ -858,6 +905,16 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
     response = tmp;
   }
 
+  if(digest->userhash) {
+    /* Append the userhash */
+    tmp = aprintf("%s, userhash=true", response);
+    free(response);
+    if(!tmp)
+      return CURLE_OUT_OF_MEMORY;
+
+    response = tmp;
+  }
+
   /* Return the output */
   *outptr = response;
   *outlen = strlen(response);
@@ -866,6 +923,58 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
 }
 
 /*
+ * Curl_auth_create_digest_http_message()
+ *
+ * This is used to generate a HTTP DIGEST response message ready for sending
+ * to the recipient.
+ *
+ * Parameters:
+ *
+ * data    [in]     - The session handle.
+ * userp   [in]     - The user name.
+ * passdwp [in]     - The user's password.
+ * request [in]     - The HTTP request.
+ * uripath [in]     - The path of the HTTP uri.
+ * digest  [in/out] - The digest data struct being used and modified.
+ * outptr  [in/out] - The address where a pointer to newly allocated memory
+ *                    holding the result will be stored upon completion.
+ * outlen  [out]    - The length of the output message.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
+                                              const char *userp,
+                                              const char *passwdp,
+                                              const unsigned char *request,
+                                              const unsigned char *uripath,
+                                              struct digestdata *digest,
+                                              char **outptr, size_t *outlen)
+{
+  switch(digest->algo) {
+  case CURLDIGESTALGO_MD5:
+  case CURLDIGESTALGO_MD5SESS:
+    return _Curl_auth_create_digest_http_message(data, userp, passwdp,
+                                                 request, uripath, digest,
+                                                 outptr, outlen,
+                                                 auth_digest_md5_to_ascii,
+                                                 Curl_md5it);
+
+  case CURLDIGESTALGO_SHA256:
+  case CURLDIGESTALGO_SHA256SESS:
+  case CURLDIGESTALGO_SHA512_256:
+  case CURLDIGESTALGO_SHA512_256SESS:
+    return _Curl_auth_create_digest_http_message(data, userp, passwdp,
+                                                 request, uripath, digest,
+                                                 outptr, outlen,
+                                                 auth_digest_sha256_to_ascii,
+                                                 Curl_sha256it);
+
+  default:
+    return CURLE_UNSUPPORTED_PROTOCOL;
+  }
+}
+
+/*
  * Curl_auth_digest_cleanup()
  *
  * This is used to clean up the digest specific data.
@@ -887,6 +996,7 @@ void Curl_auth_digest_cleanup(struct digestdata *digest)
   digest->nc = 0;
   digest->algo = CURLDIGESTALGO_MD5; /* default algorithm */
   digest->stale = FALSE; /* default means normal, not stale */
+  digest->userhash = FALSE;
 }
 #endif  /* !USE_WINDOWS_SSPI */
 
diff --git a/lib/vauth/digest.h b/lib/vauth/digest.h
index 5722dce..8686c44 100644
--- a/lib/vauth/digest.h
+++ b/lib/vauth/digest.h
@@ -31,7 +31,11 @@
 
 enum {
   CURLDIGESTALGO_MD5,
-  CURLDIGESTALGO_MD5SESS
+  CURLDIGESTALGO_MD5SESS,
+  CURLDIGESTALGO_SHA256,
+  CURLDIGESTALGO_SHA256SESS,
+  CURLDIGESTALGO_SHA512_256,
+  CURLDIGESTALGO_SHA512_256SESS
 };
 
 /* This is used to extract the realm from a challenge message */
diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c
index 50d9222..1e0d479 100644
--- a/lib/vauth/ntlm.c
+++ b/lib/vauth/ntlm.c
@@ -543,8 +543,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
   else
     user = userp;
 
-  if(user)
-    userlen = strlen(user);
+  userlen = strlen(user);
 
   /* Get the machine's un-qualified host name as NTLM doesn't like the fully
      qualified domain name */
diff --git a/lib/version.c b/lib/version.c
index ebd6006..1752e14 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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,6 +26,7 @@
 #include "urldata.h"
 #include "vtls/vtls.h"
 #include "http2.h"
+#include "ssh.h"
 #include "curl_printf.h"
 
 #ifdef USE_ARES
@@ -64,6 +65,18 @@
 #define CURL_LIBSSH2_VERSION LIBSSH2_VERSION
 #endif
 
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#ifdef __SYMBIAN32__
+/* zlib pollutes the namespace with this definition */
+#undef WIN32
+#endif
+#endif
+
+#ifdef HAVE_BROTLI
+#include <brotli/decode.h>
+#endif
+
 void Curl_version_init(void);
 
 /* For thread safety purposes this function is called by global_init so that
@@ -74,6 +87,18 @@ void Curl_version_init(void)
   curl_version_info(CURLVERSION_NOW);
 }
 
+#ifdef HAVE_BROTLI
+static size_t brotli_version(char *buf, size_t bufsz)
+{
+  uint32_t brotli_version = BrotliDecoderVersion();
+  unsigned int major = brotli_version >> 24;
+  unsigned int minor = (brotli_version & 0x00FFFFFF) >> 12;
+  unsigned int patch = brotli_version & 0x00000FFF;
+
+  return snprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
+}
+#endif
+
 char *curl_version(void)
 {
   static bool initialized;
@@ -105,6 +130,14 @@ char *curl_version(void)
   left -= len;
   ptr += len;
 #endif
+#ifdef HAVE_BROTLI
+  len = snprintf(ptr, left, "%s", " brotli/");
+  left -= len;
+  ptr += len;
+  len = brotli_version(ptr, left);
+  left -= len;
+  ptr += len;
+#endif
 #ifdef USE_ARES
   /* this function is only present in c-ares, not in the original ares */
   len = snprintf(ptr, left, " c-ares/%s", ares_version(NULL));
@@ -144,6 +177,11 @@ char *curl_version(void)
   left -= len;
   ptr += len;
 #endif
+#ifdef USE_LIBSSH
+  len = snprintf(ptr, left, " libssh/%s", CURL_LIBSSH_VERSION);
+  left -= len;
+  ptr += len;
+#endif
 #ifdef USE_NGHTTP2
   len = Curl_http2_ver(ptr, left);
   left -= len;
@@ -232,10 +270,8 @@ static const char * const protocols[] = {
 #ifndef CURL_DISABLE_RTSP
   "rtsp",
 #endif
-#ifdef USE_LIBSSH2
+#if defined(USE_LIBSSH) || defined(USE_LIBSSH2)
   "scp",
-#endif
-#ifdef USE_LIBSSH2
   "sftp",
 #endif
 #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
@@ -327,6 +363,9 @@ static curl_version_info_data version_info = {
 #if defined(CURL_WITH_MULTI_SSL)
   | CURL_VERSION_MULTI_SSL
 #endif
+#if defined(HAVE_BROTLI)
+  | CURL_VERSION_BROTLI
+#endif
   ,
   NULL, /* ssl_version */
   0,    /* ssl_version_num, this is kept at zero */
@@ -337,17 +376,22 @@ static curl_version_info_data version_info = {
   NULL, /* libidn version */
   0,    /* iconv version */
   NULL, /* ssh lib version */
+  0,    /* brotli_ver_num */
+  NULL, /* brotli version */
 };
 
 curl_version_info_data *curl_version_info(CURLversion stamp)
 {
   static bool initialized;
-#ifdef USE_LIBSSH2
+#if defined(USE_LIBSSH) || defined(USE_LIBSSH2)
   static char ssh_buffer[80];
 #endif
 #ifdef USE_SSL
   static char ssl_buffer[80];
 #endif
+#ifdef HAVE_BROTLI
+  static char brotli_buffer[80];
+#endif
 
   if(initialized)
     return &version_info;
@@ -391,9 +435,18 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
 #endif /* _LIBICONV_VERSION */
 #endif
 
-#ifdef USE_LIBSSH2
+#if defined(USE_LIBSSH2)
   snprintf(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);
+  version_info.libssh_version = ssh_buffer;
+#endif
+
+#ifdef HAVE_BROTLI
+  version_info.brotli_ver_num = BrotliDecoderVersion();
+  brotli_version(brotli_buffer, sizeof brotli_buffer);
+  version_info.brotli_version = brotli_buffer;
 #endif
 
   (void)stamp; /* avoid compiler warnings, we don't use this */
diff --git a/lib/vtls/axtls.c b/lib/vtls/axtls.c
index 6b42708..9294f49 100644
--- a/lib/vtls/axtls.c
+++ b/lib/vtls/axtls.c
@@ -728,7 +728,7 @@ const struct Curl_ssl Curl_ssl_axtls = {
   Curl_axtls_connect,             /* connect */
   Curl_axtls_connect_nonblocking, /* connect_nonblocking */
   Curl_axtls_get_internals,       /* get_internals */
-  Curl_axtls_close,               /* close */
+  Curl_axtls_close,               /* close_one */
   Curl_none_close_all,            /* close_all */
   Curl_axtls_session_free,        /* session_free */
   Curl_none_set_engine,           /* set_engine */
diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c
index ba5ee15..46b71bf 100644
--- a/lib/vtls/cyassl.c
+++ b/lib/vtls/cyassl.c
@@ -76,9 +76,7 @@ and that's a problem since options.h hasn't been included yet. */
 #endif
 #endif
 
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#endif
 
 #include "urldata.h"
 #include "sendf.h"
@@ -1003,7 +1001,7 @@ const struct Curl_ssl Curl_ssl_cyassl = {
   Curl_cyassl_connect,             /* connect */
   Curl_cyassl_connect_nonblocking, /* connect_nonblocking */
   Curl_cyassl_get_internals,       /* get_internals */
-  Curl_cyassl_close,               /* close */
+  Curl_cyassl_close,               /* close_one */
   Curl_none_close_all,             /* close_all */
   Curl_cyassl_session_free,        /* session_free */
   Curl_none_set_engine,            /* set_engine */
diff --git a/lib/vtls/darwinssl.c b/lib/vtls/darwinssl.c
index a98f433..53a7ec3 100644
--- a/lib/vtls/darwinssl.c
+++ b/lib/vtls/darwinssl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman at gmail.com>.
+ * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman at gmail.com>.
  * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
@@ -22,7 +22,7 @@
  ***************************************************************************/
 
 /*
- * Source file for all iOS and Mac OS X SecureTransport-specific code for the
+ * Source file for all iOS and macOS SecureTransport-specific code for the
  * TLS/SSL layer. No code but vtls.c should ever call or use these functions.
  */
 
@@ -39,9 +39,7 @@
 #pragma clang diagnostic ignored "-Wtautological-pointer-compare"
 #endif /* __clang__ */
 
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#endif
 
 #include <Security/Security.h>
 /* For some reason, when building for iOS, the omnibus header above does
@@ -50,12 +48,14 @@
 #include <CoreFoundation/CoreFoundation.h>
 #include <CommonCrypto/CommonDigest.h>
 
-/* The Security framework has changed greatly between iOS and different OS X
+/* The Security framework has changed greatly between iOS and different macOS
    versions, and we will try to support as many of them as we can (back to
    Leopard and iOS 5) by using macros and weak-linking.
 
-   IMPORTANT: If TLS 1.1 and 1.2 support are important for you on OS X, then
-   you must build this project against the 10.8 SDK or later. */
+   In general, you want to build this using the most recent OS SDK, since some
+   features require curl to be built against the latest SDK. TLS 1.1 and 1.2
+   support, for instance, require the macOS 10.8 SDK or later. TLS 1.3
+   requires the macOS 10.13 or iOS 11 SDK or later. */
 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
@@ -64,6 +64,7 @@
 
 #define CURL_BUILD_IOS 0
 #define CURL_BUILD_IOS_7 0
+#define CURL_BUILD_IOS_11 0
 #define CURL_BUILD_MAC 1
 /* This is the maximum API level we are allowed to use when building: */
 #define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
@@ -71,10 +72,11 @@
 #define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
 #define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
 #define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
+#define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
 /* These macros mean "the following code is present to allow runtime backward
    compatibility with at least this cat or earlier":
-   (You set this at build-time by setting the MACOSX_DEPLOYMENT_TARGET
-   environmental variable.) */
+   (You set this at build-time using the compiler command line option
+   "-mmacos-version-min.") */
 #define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
 #define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
 #define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
@@ -84,11 +86,14 @@
 #elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
 #define CURL_BUILD_IOS 1
 #define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
+#define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
 #define CURL_BUILD_MAC 0
 #define CURL_BUILD_MAC_10_5 0
 #define CURL_BUILD_MAC_10_6 0
 #define CURL_BUILD_MAC_10_7 0
 #define CURL_BUILD_MAC_10_8 0
+#define CURL_BUILD_MAC_10_9 0
+#define CURL_BUILD_MAC_10_13 0
 #define CURL_SUPPORT_MAC_10_5 0
 #define CURL_SUPPORT_MAC_10_6 0
 #define CURL_SUPPORT_MAC_10_7 0
@@ -838,6 +843,30 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
       return "TLS_RSA_PSK_WITH_NULL_SHA384";
       break;
 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
+#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+    /* New ChaCha20+Poly1305 cipher-suites used by TLS 1.3: */
+    case TLS_AES_128_GCM_SHA256:
+      return "TLS_AES_128_GCM_SHA256";
+      break;
+    case TLS_AES_256_GCM_SHA384:
+      return "TLS_AES_256_GCM_SHA384";
+      break;
+    case TLS_CHACHA20_POLY1305_SHA256:
+      return "TLS_CHACHA20_POLY1305_SHA256";
+      break;
+    case TLS_AES_128_CCM_SHA256:
+      return "TLS_AES_128_CCM_SHA256";
+      break;
+    case TLS_AES_128_CCM_8_SHA256:
+      return "TLS_AES_128_CCM_8_SHA256";
+      break;
+    case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+      return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
+      break;
+    case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+      return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256";
+      break;
+#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
   }
   return "TLS_NULL_WITH_NULL_NULL";
 }
@@ -1171,6 +1200,15 @@ static CURLcode darwinssl_version_from_curl(SSLProtocol *darwinver,
       *darwinver = kTLSProtocol12;
       return CURLE_OK;
     case CURL_SSLVERSION_TLSv1_3:
+      /* TLS 1.3 support first appeared in iOS 11 and macOS 10.13 */
+#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+      /* We can assume __builtin_available() will always work in the
+         10.13/11.0 SDK: */
+      if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
+        *darwinver = kTLSProtocol13;
+        return CURLE_OK;
+      }
+#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
       break;
   }
   return CURLE_SSL_CONNECT_ERROR;
@@ -1184,12 +1222,27 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   long ssl_version = SSL_CONN_CONFIG(version);
   long ssl_version_max = SSL_CONN_CONFIG(version_max);
+  long max_supported_version_by_os;
+
+  /* macOS 10.5-10.7 supported TLS 1.0 only.
+     macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2.
+     macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */
+#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+  if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
+    max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3;
+  }
+  else {
+    max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
+  }
+#else
+  max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
+#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
 
   switch(ssl_version) {
     case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1:
       ssl_version = CURL_SSLVERSION_TLSv1_0;
-      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+      ssl_version_max = max_supported_version_by_os;
       break;
   }
 
@@ -1198,7 +1251,7 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
       ssl_version_max = ssl_version << 16;
       break;
     case CURL_SSLVERSION_MAX_DEFAULT:
-      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+      ssl_version_max = max_supported_version_by_os;
       break;
   }
 
@@ -1247,7 +1300,7 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
                                             true);
           break;
         case CURL_SSLVERSION_TLSv1_3:
-          failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
+          failf(data, "Your version of the OS does not support TLSv1.3");
           return CURLE_SSL_CONNECT_ERROR;
       }
     }
@@ -1326,7 +1379,16 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
     case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1:
       (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1);
+#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+      if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
+        (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol13);
+      }
+      else {
+        (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12);
+      }
+#else
       (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12);
+#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
       break;
     case CURL_SSLVERSION_TLSv1_0:
     case CURL_SSLVERSION_TLSv1_1:
@@ -2341,7 +2403,13 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
         infof(data, "TLS 1.2 connection using %s\n",
               TLSCipherNameForNumber(cipher));
         break;
-#endif
+#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+      case kTLSProtocol13:
+        infof(data, "TLS 1.3 connection using %s\n",
+              TLSCipherNameForNumber(cipher));
+        break;
+#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
       default:
         infof(data, "Unknown protocol connection\n");
         break;
@@ -2932,7 +3000,7 @@ const struct Curl_ssl Curl_ssl_darwinssl = {
   Curl_darwinssl_connect,             /* connect */
   Curl_darwinssl_connect_nonblocking, /* connect_nonblocking */
   Curl_darwinssl_get_internals,       /* get_internals */
-  Curl_darwinssl_close,               /* close */
+  Curl_darwinssl_close,               /* close_one */
   Curl_none_close_all,                /* close_all */
   Curl_darwinssl_session_free,        /* session_free */
   Curl_none_set_engine,               /* set_engine */
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index ba5faef..8f0cc0b 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -61,9 +61,7 @@
 #endif
 
 
-#ifdef HAVE_LIMITS_H
-#  include <limits.h>
-#endif
+#include <limits.h>
 
 #include <curl/curl.h>
 #include "urldata.h"
@@ -1375,7 +1373,7 @@ const struct Curl_ssl Curl_ssl_gskit = {
   Curl_gskit_connect,             /* connect */
   Curl_gskit_connect_nonblocking, /* connect_nonblocking */
   Curl_gskit_get_internals,       /* get_internals */
-  Curl_gskit_close,               /* close */
+  Curl_gskit_close,               /* close_one */
   Curl_none_close_all,            /* close_all */
   /* No session handling for GSKit */
   Curl_none_session_free,         /* session_free */
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index a844915..30b255b 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -1827,7 +1827,7 @@ const struct Curl_ssl Curl_ssl_gnutls = {
   Curl_gtls_connect,             /* connect */
   Curl_gtls_connect_nonblocking, /* connect_nonblocking */
   Curl_gtls_get_internals,       /* get_internals */
-  Curl_gtls_close,               /* close */
+  Curl_gtls_close,               /* close_one */
   Curl_none_close_all,           /* close_all */
   Curl_gtls_session_free,        /* session_free */
   Curl_none_set_engine,          /* set_engine */
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index ce1f8eb..28251a3 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -1061,7 +1061,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
   Curl_mbedtls_connect,             /* connect */
   Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */
   Curl_mbedtls_get_internals,       /* get_internals */
-  Curl_mbedtls_close,               /* close */
+  Curl_mbedtls_close,               /* close_one */
   Curl_mbedtls_close_all,           /* close_all */
   Curl_mbedtls_session_free,        /* session_free */
   Curl_none_set_engine,             /* set_engine */
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index c0b7e63..a3ef37a 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -2365,7 +2365,7 @@ const struct Curl_ssl Curl_ssl_nss = {
   Curl_nss_connect,             /* connect */
   Curl_nss_connect_nonblocking, /* connect_nonblocking */
   Curl_nss_get_internals,       /* get_internals */
-  Curl_nss_close,               /* close */
+  Curl_nss_close,               /* close_one */
   Curl_none_close_all,          /* close_all */
   /* NSS has its own session ID cache */
   Curl_none_session_free,       /* session_free */
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 4253160..93faa6f 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.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
@@ -34,9 +34,7 @@
 
 #ifdef USE_OPENSSL
 
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#endif
 
 #include "urldata.h"
 #include "sendf.h"
@@ -68,10 +66,7 @@
 #include <openssl/rsa.h>
 #include <openssl/bio.h>
 #include <openssl/buffer.h>
-
-#ifdef HAVE_OPENSSL_PKCS12_H
 #include <openssl/pkcs12.h>
-#endif
 
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
 #include <openssl/ocsp.h>
@@ -151,14 +146,13 @@ static unsigned long OpenSSL_version_num(void)
 /*
  * Whether SSL_CTX_set_keylog_callback is available.
  * OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
- * BoringSSL: supported since d28f59c27bac (committed 2015-11-19), the
- *            BORINGSSL_201512 macro from 2016-01-21 should be close enough.
+ * BoringSSL: supported since d28f59c27bac (committed 2015-11-19)
  * LibreSSL: unsupported in at least 2.5.1 (explicitly check for it since it
  *           lies and pretends to be OpenSSL 2.0.0).
  */
 #if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
      !defined(LIBRESSL_VERSION_NUMBER)) || \
-    defined(BORINGSSL_201512)
+    defined(OPENSSL_IS_BORINGSSL)
 #define HAVE_KEYLOG_CALLBACK
 #endif
 
@@ -181,6 +175,8 @@ static unsigned long OpenSSL_version_num(void)
   "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
 #endif
 
+#define ENABLE_SSLKEYLOGFILE
+
 #ifdef ENABLE_SSLKEYLOGFILE
 typedef struct ssl_tap_state {
   int master_key_length;
@@ -263,11 +259,11 @@ static void tap_ssl_key(const SSL *ssl, ssl_tap_state_t *state)
   if(!session || !keylog_file_fp)
     return;
 
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
   /* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that
    * we have a valid SSL context if we have a non-NULL session. */
   SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE);
-  master_key_length =
+  master_key_length = (int)
     SSL_SESSION_get_master_key(session, master_key, SSL_MAX_MASTER_KEY_LENGTH);
 #else
   if(ssl->s3 && session->master_key_length > 0) {
@@ -445,14 +441,14 @@ static CURLcode Curl_ossl_seed(struct Curl_easy *data)
     size_t len = sizeof(randb);
     size_t i, i_max;
     for(i = 0, i_max = len / sizeof(struct curltime); i < i_max; ++i) {
-      struct curltime tv = curlx_tvnow();
+      struct curltime tv = Curl_now();
       Curl_wait_ms(1);
       tv.tv_sec *= i + 1;
       tv.tv_usec *= (unsigned int)i + 2;
-      tv.tv_sec ^= ((curlx_tvnow().tv_sec + curlx_tvnow().tv_usec) *
+      tv.tv_sec ^= ((Curl_now().tv_sec + Curl_now().tv_usec) *
                     (i + 3)) << 8;
-      tv.tv_usec ^= (unsigned int) ((curlx_tvnow().tv_sec +
-                                     curlx_tvnow().tv_usec) *
+      tv.tv_usec ^= (unsigned int) ((Curl_now().tv_sec +
+                                     Curl_now().tv_usec) *
                                     (i + 4)) << 16;
       memcpy(&randb[i * sizeof(struct curltime)], &tv,
              sizeof(struct curltime));
@@ -653,7 +649,6 @@ int cert_stuff(struct connectdata *conn,
 
     case SSL_FILETYPE_PKCS12:
     {
-#ifdef HAVE_OPENSSL_PKCS12_H
       FILE *f;
       PKCS12 *p12;
       EVP_PKEY *pri;
@@ -740,10 +735,6 @@ int cert_stuff(struct connectdata *conn,
       if(!cert_done)
         return 0; /* failure! */
       break;
-#else
-      failf(data, "file type P12 for certificate not supported");
-      return 0;
-#endif
     }
     default:
       failf(data, "not supported file type '%s' for certificate", cert_type);
@@ -837,12 +828,18 @@ int cert_stuff(struct connectdata *conn,
       EVP_PKEY_free(pktmp);
     }
 
-#ifndef OPENSSL_NO_RSA
+#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_IS_BORINGSSL)
     {
       /* If RSA is used, don't check the private key if its flags indicate
        * it doesn't support it. */
       EVP_PKEY *priv_key = SSL_get_privatekey(ssl);
-      if(EVP_PKEY_id(priv_key) == EVP_PKEY_RSA) {
+      int pktype;
+#ifdef HAVE_OPAQUE_EVP_PKEY
+      pktype = EVP_PKEY_id(priv_key);
+#else
+      pktype = priv_key->type;
+#endif
+      if(pktype == EVP_PKEY_RSA) {
         RSA *rsa = EVP_PKEY_get1_RSA(priv_key);
         if(RSA_flags(rsa) & RSA_METHOD_FLAG_NO_CHECK)
           check_privkey = FALSE;
@@ -907,7 +904,7 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
 static int Curl_ossl_init(void)
 {
 #ifdef ENABLE_SSLKEYLOGFILE
-  const char *keylog_file_name;
+  char *keylog_file_name;
 #endif
 
   OPENSSL_load_builtin_modules();
@@ -947,14 +944,22 @@ static int Curl_ossl_init(void)
 #endif
 
 #ifdef ENABLE_SSLKEYLOGFILE
-  keylog_file_name = curl_getenv("SSLKEYLOGFILE");
-  if(keylog_file_name && !keylog_file_fp) {
-    keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
-    if(keylog_file_fp) {
-      if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096)) {
-        fclose(keylog_file_fp);
-        keylog_file_fp = NULL;
+  if(!keylog_file_fp) {
+    keylog_file_name = curl_getenv("SSLKEYLOGFILE");
+    if(keylog_file_name) {
+      keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
+      if(keylog_file_fp) {
+#ifdef WIN32
+        if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
+#else
+        if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
+#endif
+        {
+          fclose(keylog_file_fp);
+          keylog_file_fp = NULL;
+        }
       }
+      Curl_safefree(keylog_file_name);
     }
   }
 #endif
@@ -2408,8 +2413,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 
   /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */
 #if defined(ENABLE_SSLKEYLOGFILE) && defined(HAVE_KEYLOG_CALLBACK)
-  if(keylog_file) {
-    SSL_CTX_set_keylog_callback(connssl->ctx, ossl_keylog_callback);
+  if(keylog_file_fp) {
+    SSL_CTX_set_keylog_callback(BACKEND->ctx, ossl_keylog_callback);
   }
 #endif
 
@@ -3060,12 +3065,12 @@ static CURLcode servercert(struct connectdata *conn,
   ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert));
   len = BIO_get_mem_data(mem, (char **) &ptr);
   infof(data, " start date: %.*s\n", len, ptr);
-  rc = BIO_reset(mem);
+  (void)BIO_reset(mem);
 
   ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert));
   len = BIO_get_mem_data(mem, (char **) &ptr);
   infof(data, " expire date: %.*s\n", len, ptr);
-  rc = BIO_reset(mem);
+  (void)BIO_reset(mem);
 
   BIO_free(mem);
 
@@ -3386,12 +3391,13 @@ static bool Curl_ossl_data_pending(const struct connectdata *conn,
 {
   const struct ssl_connect_data *connssl = &conn->ssl[connindex];
   const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex];
-  if(BACKEND->handle)
-    /* SSL is in use */
-    return (0 != SSL_pending(BACKEND->handle) ||
-           (proxyssl->backend->handle &&
-            0 != SSL_pending(proxyssl->backend->handle))) ?
-           TRUE : FALSE;
+
+  if(connssl->backend->handle && SSL_pending(connssl->backend->handle))
+    return TRUE;
+
+  if(proxyssl->backend->handle && SSL_pending(proxyssl->backend->handle))
+    return TRUE;
+
   return FALSE;
 }
 
@@ -3636,7 +3642,7 @@ const struct Curl_ssl Curl_ssl_openssl = {
   Curl_ossl_connect,             /* connect */
   Curl_ossl_connect_nonblocking, /* connect_nonblocking */
   Curl_ossl_get_internals,       /* get_internals */
-  Curl_ossl_close,               /* close */
+  Curl_ossl_close,               /* close_one */
   Curl_ossl_close_all,           /* close_all */
   Curl_ossl_session_free,        /* session_free */
   Curl_ossl_set_engine,          /* set_engine */
diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
index fc0644f..df29fa9 100644
--- a/lib/vtls/polarssl.c
+++ b/lib/vtls/polarssl.c
@@ -923,7 +923,7 @@ const struct Curl_ssl Curl_ssl_polarssl = {
   Curl_polarssl_connect,             /* connect */
   Curl_polarssl_connect_nonblocking, /* connect_nonblocking */
   Curl_polarssl_get_internals,       /* get_internals */
-  Curl_polarssl_close,               /* close */
+  Curl_polarssl_close,               /* close_one */
   Curl_none_close_all,               /* close_all */
   Curl_polarssl_session_free,        /* session_free */
   Curl_none_set_engine,              /* set_engine */
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 9ca1431..85c64cf 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -1838,7 +1838,7 @@ const struct Curl_ssl Curl_ssl_schannel = {
   Curl_schannel_connect,             /* connect */
   Curl_schannel_connect_nonblocking, /* connect_nonblocking */
   Curl_schannel_get_internals,       /* get_internals */
-  Curl_schannel_close,               /* close */
+  Curl_schannel_close,               /* close_one */
   Curl_none_close_all,               /* close_all */
   Curl_schannel_session_free,        /* session_free */
   Curl_none_set_engine,              /* set_engine */
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index bb8fda4..def1d30 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -549,7 +549,7 @@ int Curl_ssl_getsock(struct connectdata *conn,
 void Curl_ssl_close(struct connectdata *conn, int sockindex)
 {
   DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
-  Curl_ssl->close(conn, sockindex);
+  Curl_ssl->close_one(conn, sockindex);
 }
 
 CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
@@ -1059,6 +1059,7 @@ bool Curl_none_false_start(void)
   return FALSE;
 }
 
+#ifndef CURL_DISABLE_CRYPTO_AUTH
 CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
                           unsigned char *md5sum, size_t md5len UNUSED_PARAM)
 {
@@ -1073,6 +1074,19 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
   Curl_MD5_final(MD5pw, md5sum);
   return CURLE_OK;
 }
+#else
+CURLcode Curl_none_md5sum(unsigned char *input UNUSED_PARAM,
+                          size_t inputlen UNUSED_PARAM,
+                          unsigned char *md5sum UNUSED_PARAM,
+                          size_t md5len UNUSED_PARAM)
+{
+  (void)input;
+  (void)inputlen;
+  (void)md5sum;
+  (void)md5len;
+  return CURLE_NOT_BUILT_IN;
+}
+#endif
 
 static int Curl_multissl_init(void)
 {
@@ -1108,7 +1122,7 @@ static void Curl_multissl_close(struct connectdata *conn, int sockindex)
 {
   if(multissl_init(NULL))
     return;
-  Curl_ssl->close(conn, sockindex);
+  Curl_ssl->close_one(conn, sockindex);
 }
 
 static const struct Curl_ssl Curl_ssl_multi = {
@@ -1133,7 +1147,7 @@ static const struct Curl_ssl Curl_ssl_multi = {
   Curl_multissl_connect,             /* connect */
   Curl_multissl_connect_nonblocking, /* connect_nonblocking */
   Curl_multissl_get_internals,       /* get_internals */
-  Curl_multissl_close,               /* close */
+  Curl_multissl_close,               /* close_one */
   Curl_none_close_all,               /* close_all */
   Curl_none_session_free,            /* session_free */
   Curl_none_set_engine,              /* set_engine */
@@ -1246,6 +1260,7 @@ static size_t Curl_multissl_version(char *buffer, size_t size)
 static int multissl_init(const struct Curl_ssl *backend)
 {
   const char *env;
+  char *env_tmp;
   int i;
 
   if(Curl_ssl != &Curl_ssl_multi)
@@ -1259,7 +1274,7 @@ static int multissl_init(const struct Curl_ssl *backend)
   if(!available_backends[0])
     return 1;
 
-  env = getenv("CURL_SSL_BACKEND");
+  env = env_tmp = curl_getenv("CURL_SSL_BACKEND");
 #ifdef CURL_DEFAULT_SSL_BACKEND
   if(!env)
     env = CURL_DEFAULT_SSL_BACKEND;
@@ -1268,6 +1283,7 @@ static int multissl_init(const struct Curl_ssl *backend)
     for(i = 0; available_backends[i]; i++) {
       if(strcasecompare(env, available_backends[i]->info.name)) {
         Curl_ssl = available_backends[i];
+        curl_free(env_tmp);
         return 0;
       }
     }
@@ -1275,6 +1291,7 @@ static int multissl_init(const struct Curl_ssl *backend)
 
   /* Fall back to first available backend */
   Curl_ssl = available_backends[0];
+  curl_free(env_tmp);
   return 0;
 }
 
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index f1a11ea..c5f9d4a 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -60,7 +60,7 @@ struct Curl_ssl {
   CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex,
                                   bool *done);
   void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
-  void (*close)(struct connectdata *conn, int sockindex);
+  void (*close_one)(struct connectdata *conn, int sockindex);
   void (*close_all)(struct Curl_easy *data);
   void (*session_free)(void *ptr);
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e9c8ea75575afdb4e87b262641ee4071ef42b4c6
commit e9c8ea75575afdb4e87b262641ee4071ef42b4c6
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Jan 24 14:14:04 2018 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Jan 24 14:14:04 2018 -0500

    curl: Update script to get curl 7.58.0

diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index b244827..28803cb 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_56_0"
+readonly tag="curl-7_58_0"
 readonly shortlog=false
 readonly paths="
   CMake/*

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e6a80ccfc440ac8dd5e9e5405744c2423560fc02
commit e6a80ccfc440ac8dd5e9e5405744c2423560fc02
Author:     Wouter Klouwen <wouter.klouwen at youview.com>
AuthorDate: Sat Jan 20 15:13:21 2018 +0000
Commit:     Wouter Klouwen <wouter.klouwen at youview.com>
CommitDate: Tue Jan 23 18:56:42 2018 +0000

    Make use of std::chrono throughout every component
    
    This commit continues the changes made in CTest to support std::chrono
    by
    applying it throughout every component where a duration was used.
    
    No functional change intended.

diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
index 86c6981..9f1a15e 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -9,6 +9,7 @@
 #include "cmCPackIFWPackage.h"
 #include "cmCPackIFWRepository.h"
 #include "cmCPackLog.h" // IWYU pragma: keep
+#include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 
@@ -84,9 +85,9 @@ int cmCPackIFWGenerator::PackageFiles()
     std::string output;
     int retVal = 1;
     cmCPackIFWLogger(OUTPUT, "- Generate repository" << std::endl);
-    bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output,
-                                               &output, &retVal, nullptr,
-                                               this->GeneratorVerbose, 0);
+    bool res = cmSystemTools::RunSingleCommand(
+      ifwCmd.c_str(), &output, &output, &retVal, nullptr,
+      this->GeneratorVerbose, cmDuration::zero());
     if (!res || retVal) {
       cmGeneratedFileStream ofs(ifwTmpFile.c_str());
       ofs << "# Run command: " << ifwCmd << std::endl
@@ -194,9 +195,9 @@ int cmCPackIFWGenerator::PackageFiles()
     std::string output;
     int retVal = 1;
     cmCPackIFWLogger(OUTPUT, "- Generate package" << std::endl);
-    bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output,
-                                               &output, &retVal, nullptr,
-                                               this->GeneratorVerbose, 0);
+    bool res = cmSystemTools::RunSingleCommand(
+      ifwCmd.c_str(), &output, &output, &retVal, nullptr,
+      this->GeneratorVerbose, cmDuration::zero());
     if (!res || retVal) {
       cmGeneratedFileStream ofs(ifwTmpFile.c_str());
       ofs << "# Run command: " << ifwCmd << std::endl
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index bb35623..e95b96df 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -4,6 +4,7 @@
 
 #include "cmCPackGenerator.h"
 #include "cmCPackLog.h"
+#include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 
@@ -242,9 +243,9 @@ bool cmCPackDragNDropGenerator::RunCommand(std::ostringstream& command,
 {
   int exit_code = 1;
 
-  bool result = cmSystemTools::RunSingleCommand(command.str().c_str(), output,
-                                                output, &exit_code, nullptr,
-                                                this->GeneratorVerbose, 0);
+  bool result = cmSystemTools::RunSingleCommand(
+    command.str().c_str(), output, output, &exit_code, nullptr,
+    this->GeneratorVerbose, cmDuration::zero());
 
   if (!result || exit_code) {
     cmCPackLogger(cmCPackLog::LOG_ERROR, "Error executing: " << command.str()
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index ea0e899..9590aa2 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -12,6 +12,7 @@
 #include "cmCPackComponentGroup.h"
 #include "cmCPackLog.h"
 #include "cmCryptoHash.h"
+#include "cmDuration.h"
 #include "cmFSPermissions.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGlobalGenerator.h"
@@ -277,9 +278,9 @@ int cmCPackGenerator::InstallProjectViaInstallCommands(
       cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ic << std::endl);
       std::string output;
       int retVal = 1;
-      bool resB =
-        cmSystemTools::RunSingleCommand(ic.c_str(), &output, &output, &retVal,
-                                        nullptr, this->GeneratorVerbose, 0);
+      bool resB = cmSystemTools::RunSingleCommand(
+        ic.c_str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+        cmDuration::zero());
       if (!resB || retVal) {
         std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
         tmpFile += "/InstallOutput.log";
@@ -601,7 +602,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
         int retVal = 1;
         bool resB = cmSystemTools::RunSingleCommand(
           buildCommand.c_str(), &output, &output, &retVal,
-          installDirectory.c_str(), this->GeneratorVerbose, 0);
+          installDirectory.c_str(), this->GeneratorVerbose,
+          cmDuration::zero());
         if (!resB || retVal) {
           std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
           tmpFile += "/PreinstallOutput.log";
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index ddf104c..965283d 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -5,6 +5,7 @@
 #include "cmCPackComponentGroup.h"
 #include "cmCPackGenerator.h"
 #include "cmCPackLog.h"
+#include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 
@@ -301,9 +302,9 @@ int cmCPackNSISGenerator::PackageFiles()
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << nsisCmd << std::endl);
   std::string output;
   int retVal = 1;
-  bool res =
-    cmSystemTools::RunSingleCommand(nsisCmd.c_str(), &output, &output, &retVal,
-                                    nullptr, this->GeneratorVerbose, 0);
+  bool res = cmSystemTools::RunSingleCommand(
+    nsisCmd.c_str(), &output, &output, &retVal, nullptr,
+    this->GeneratorVerbose, cmDuration::zero());
   if (!res || retVal) {
     cmGeneratedFileStream ofs(tmpFile.c_str());
     ofs << "# Run command: " << nsisCmd << std::endl
@@ -400,9 +401,9 @@ int cmCPackNSISGenerator::InitializeInternal()
                                                                << std::endl);
   std::string output;
   int retVal = 1;
-  bool resS =
-    cmSystemTools::RunSingleCommand(nsisCmd.c_str(), &output, &output, &retVal,
-                                    nullptr, this->GeneratorVerbose, 0);
+  bool resS = cmSystemTools::RunSingleCommand(
+    nsisCmd.c_str(), &output, &output, &retVal, nullptr,
+    this->GeneratorVerbose, cmDuration::zero());
   cmsys::RegularExpression versionRex("v([0-9]+.[0-9]+)");
   cmsys::RegularExpression versionRexCVS("v(.*)\\.cvs");
   if (!resS || retVal ||
@@ -737,9 +738,9 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
                                       zipListFileName.c_str());
     std::string output;
     int retVal = -1;
-    int res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output, &output,
-                                              &retVal, dirName.c_str(),
-                                              cmSystemTools::OUTPUT_NONE, 0);
+    int res = cmSystemTools::RunSingleCommand(
+      cmd.c_str(), &output, &output, &retVal, dirName.c_str(),
+      cmSystemTools::OUTPUT_NONE, cmDuration::zero());
     if (!res || retVal) {
       std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
       tmpFile += "/CompressZip.log";
diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx
index 8d3c40c..e750de3 100644
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ b/Source/CPack/cmCPackOSXX11Generator.cxx
@@ -6,6 +6,7 @@
 
 #include "cmCPackGenerator.h"
 #include "cmCPackLog.h"
+#include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 #include "cm_sys_stat.h"
@@ -154,9 +155,9 @@ int cmCPackOSXX11Generator::PackageFiles()
   int numTries = 10;
   bool res = false;
   while (numTries > 0) {
-    res = cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output,
-                                          &output, &retVal, nullptr,
-                                          this->GeneratorVerbose, 0);
+    res = cmSystemTools::RunSingleCommand(
+      dmgCmd.str().c_str(), &output, &output, &retVal, nullptr,
+      this->GeneratorVerbose, cmDuration::zero());
     if (res && !retVal) {
       numTries = -1;
       break;
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index dbcb022..c515b85 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -13,6 +13,7 @@
 
 #include "cmCPackComponentGroup.h"
 #include "cmCPackLog.h"
+#include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
@@ -295,9 +296,9 @@ int cmCPackPackageMakerGenerator::PackageFiles()
   int numTries = 10;
   bool res = false;
   while (numTries > 0) {
-    res = cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output,
-                                          &output, &retVal, nullptr,
-                                          this->GeneratorVerbose, 0);
+    res = cmSystemTools::RunSingleCommand(
+      dmgCmd.str().c_str(), &output, &output, &retVal, nullptr,
+      this->GeneratorVerbose, cmDuration::zero());
     if (res && !retVal) {
       numTries = -1;
       break;
@@ -467,7 +468,8 @@ bool cmCPackPackageMakerGenerator::RunPackageMaker(const char* command,
   std::string output;
   int retVal = 1;
   bool res = cmSystemTools::RunSingleCommand(
-    command, &output, &output, &retVal, nullptr, this->GeneratorVerbose, 0);
+    command, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+    cmDuration::zero());
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running package maker"
                   << std::endl);
   if (!res || retVal) {
diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx
index 6a6dc82..57cf7ea 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.cxx
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -8,6 +8,7 @@
 
 #include "cmCPackComponentGroup.h"
 #include "cmCPackLog.h"
+#include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 
@@ -145,9 +146,9 @@ bool cmCPackProductBuildGenerator::RunProductBuild(const std::string& command)
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
   std::string output, error_output;
   int retVal = 1;
-  bool res = cmSystemTools::RunSingleCommand(command.c_str(), &output,
-                                             &error_output, &retVal, nullptr,
-                                             this->GeneratorVerbose, 0);
+  bool res = cmSystemTools::RunSingleCommand(
+    command.c_str(), &output, &error_output, &retVal, nullptr,
+    this->GeneratorVerbose, cmDuration::zero());
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running command" << std::endl);
   if (!res || retVal) {
     cmGeneratedFileStream ofs(tmpFile.c_str());
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index 3383c9d..81089ca 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -251,7 +251,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
     int retVal = cm.GetGlobalGenerator()->Build(
       this->SourceDir, this->BinaryDir, this->BuildProject, tar, output,
       this->BuildMakeProgram, config, !this->BuildNoClean, false, false,
-      remainingTime.count());
+      remainingTime);
     out << output;
     // if the build failed then return
     if (retVal) {
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 15a81f2..78ab5ff 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -27,6 +27,7 @@
 #include "cmCTestTestCommand.h"
 #include "cmCTestUpdateCommand.h"
 #include "cmCTestUploadCommand.h"
+#include "cmDuration.h"
 #include "cmFunctionBlocker.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGlobalGenerator.h"
@@ -206,7 +207,8 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
   std::vector<char> out;
   std::vector<char> err;
   std::string line;
-  int pipe = cmSystemTools::WaitForLine(cp, line, 100.0, out, err);
+  int pipe =
+    cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out, err);
   while (pipe != cmsysProcess_Pipe_None) {
     cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Output: " << line
                                                                << "\n");
@@ -215,7 +217,8 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
     } else if (pipe == cmsysProcess_Pipe_STDOUT) {
       cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, line << "\n");
     }
-    pipe = cmSystemTools::WaitForLine(cp, line, 100, out, err);
+    pipe = cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out,
+                                      err);
   }
 
   // Properly handle output of the build command
@@ -601,7 +604,8 @@ int cmCTestScriptHandler::CheckOutSourceDir()
                "Run cvs: " << this->CVSCheckOut << std::endl);
     res = cmSystemTools::RunSingleCommand(
       this->CVSCheckOut.c_str(), &output, &output, &retVal,
-      this->CTestRoot.c_str(), this->HandlerVerbose, 0 /*this->TimeOut*/);
+      this->CTestRoot.c_str(), this->HandlerVerbose,
+      cmDuration::zero() /*this->TimeOut*/);
     if (!res || retVal != 0) {
       cmSystemTools::Error("Unable to perform cvs checkout:\n",
                            output.c_str());
@@ -668,7 +672,7 @@ int cmCTestScriptHandler::PerformExtraUpdates()
                  "Run Update: " << fullCommand << std::endl);
       res = cmSystemTools::RunSingleCommand(
         fullCommand.c_str(), &output, &output, &retVal, cvsArgs[0].c_str(),
-        this->HandlerVerbose, 0 /*this->TimeOut*/);
+        this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
       if (!res || retVal != 0) {
         cmSystemTools::Error("Unable to perform extra updates:\n", eu.c_str(),
                              "\nWith output:\n", output.c_str());
@@ -772,7 +776,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
                "Run cmake command: " << command << std::endl);
     res = cmSystemTools::RunSingleCommand(
       command.c_str(), &output, &output, &retVal, this->BinaryDir.c_str(),
-      this->HandlerVerbose, 0 /*this->TimeOut*/);
+      this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
 
     if (!this->CMOutFile.empty()) {
       std::string cmakeOutputFile = this->CMOutFile;
@@ -811,7 +815,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
                "Run ctest command: " << command << std::endl);
     res = cmSystemTools::RunSingleCommand(
       command.c_str(), &output, &output, &retVal, this->BinaryDir.c_str(),
-      this->HandlerVerbose, 0 /*this->TimeOut*/);
+      this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
 
     // did something critical fail in ctest
     if (!res || cmakeFailed || retVal & cmCTest::BUILD_ERRORS) {
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 47a9390..59158b0 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -21,6 +21,7 @@
 #include "cmComputeTargetDepends.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandLines.h"
+#include "cmDuration.h"
 #include "cmExportBuildFileGenerator.h"
 #include "cmExternalMakefileProjectGenerator.h"
 #include "cmGeneratedFileStream.h"
@@ -87,7 +88,7 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm)
   this->InstallTargetEnabled = false;
 
   // how long to let try compiles run
-  this->TryCompileTimeout = 0;
+  this->TryCompileTimeout = cmDuration::zero();
 
   this->ExtraGenerator = nullptr;
   this->CurrentConfigureMakefile = nullptr;
@@ -1801,7 +1802,7 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
                              const std::string& target, std::string& output,
                              const std::string& makeCommandCSTR,
                              const std::string& config, bool clean, bool fast,
-                             bool verbose, double timeout,
+                             bool verbose, cmDuration timeout,
                              cmSystemTools::OutputOption outputflag,
                              std::vector<std::string> const& nativeOptions)
 {
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 3ebff82..34ed5b0 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "cmCustomCommandLines.h"
+#include "cmDuration.h"
 #include "cmExportSetMap.h"
 #include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
@@ -160,8 +161,8 @@ public:
             const std::string& projectName, const std::string& targetName,
             std::string& output, const std::string& makeProgram,
             const std::string& config, bool clean, bool fast, bool verbose,
-            double timeout, cmSystemTools::OutputOption outputflag =
-                              cmSystemTools::OUTPUT_NONE,
+            cmDuration timeout, cmSystemTools::OutputOption outputflag =
+                                  cmSystemTools::OUTPUT_NONE,
             std::vector<std::string> const& nativeOptions =
               std::vector<std::string>());
 
@@ -233,7 +234,7 @@ public:
 
   void EnableInstallTarget();
 
-  int TryCompileTimeout;
+  cmDuration TryCompileTimeout;
 
   bool GetForceUnixPaths() const { return this->ForceUnixPaths; }
   bool GetToolSupportsColor() const { return this->ToolSupportsColor; }
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 0b67981..d845e8b 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -6,6 +6,7 @@
 #include "cmAlgorithms.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandLines.h"
+#include "cmDuration.h"
 #include "cmFilePathChecksum.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
@@ -410,7 +411,7 @@ void cmQtAutoGenInitializer::InitCustomTargets()
       int retVal = 0;
       bool result = cmSystemTools::RunSingleCommand(
         command, &rccStdOut, &rccStdErr, &retVal, nullptr,
-        cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
+        cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
       if (result && retVal == 0 &&
           rccStdOut.find("--list") != std::string::npos) {
         this->RccListOptions.push_back("--list");
@@ -1417,7 +1418,7 @@ bool cmQtAutoGenInitializer::RccListInputs(std::string const& fileName,
       cmd.push_back(fileNameName);
       result = cmSystemTools::RunSingleCommand(
         cmd, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
-        cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
+        cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
     }
     if (!result || retVal) {
       error = "rcc list process failed for:\n  ";
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index c321236..d7ff58c 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -3,6 +3,7 @@
 #include "cmSystemTools.h"
 
 #include "cmAlgorithms.h"
+#include "cmDuration.h"
 #include "cmProcessOutput.h"
 #include "cm_sys_stat.h"
 
@@ -699,7 +700,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
                                      std::string* captureStdOut,
                                      std::string* captureStdErr, int* retVal,
                                      const char* dir, OutputOption outputflag,
-                                     double timeout, Encoding encoding)
+                                     cmDuration timeout, Encoding encoding)
 {
   std::vector<const char*> argv;
   argv.reserve(command.size() + 1);
@@ -727,7 +728,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
   }
   assert(!captureStdErr || captureStdErr != captureStdOut);
 
-  cmsysProcess_SetTimeout(cp, timeout);
+  cmsysProcess_SetTimeout(cp, timeout.count());
   cmsysProcess_Execute(cp);
 
   std::vector<char> tempStdOut;
@@ -840,7 +841,7 @@ bool cmSystemTools::RunSingleCommand(const char* command,
                                      std::string* captureStdOut,
                                      std::string* captureStdErr, int* retVal,
                                      const char* dir, OutputOption outputflag,
-                                     double timeout)
+                                     cmDuration timeout)
 {
   if (s_DisableRunCommandOutput) {
     outputflag = OUTPUT_NONE;
@@ -1811,7 +1812,7 @@ bool cmSystemTools::ListTar(const char* outFileName, bool verbose)
 }
 
 int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
-                               double timeout, std::vector<char>& out,
+                               cmDuration timeout, std::vector<char>& out,
                                std::vector<char>& err)
 {
   line.clear();
@@ -1859,7 +1860,9 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
     // No newlines found.  Wait for more data from the process.
     int length;
     char* data;
-    int pipe = cmsysProcess_WaitForData(process, &data, &length, &timeout);
+    double timeoutAsDbl = timeout.count();
+    int pipe =
+      cmsysProcess_WaitForData(process, &data, &length, &timeoutAsDbl);
     if (pipe == cmsysProcess_Pipe_Timeout) {
       // Timeout has been exceeded.
       return pipe;
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index d29ba56..77e34b4 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -6,6 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCryptoHash.h"
+#include "cmDuration.h"
 #include "cmProcessOutput.h"
 #include "cmsys/Process.h"
 #include "cmsys/SystemTools.hxx" // IWYU pragma: export
@@ -225,7 +226,7 @@ public:
                                int* retVal = nullptr,
                                const char* dir = nullptr,
                                OutputOption outputflag = OUTPUT_MERGE,
-                               double timeout = 0.0);
+                               cmDuration timeout = cmDuration::zero());
   /**
    * In this version of RunSingleCommand, command[0] should be
    * the command to run, and each argument to the command should
@@ -237,7 +238,7 @@ public:
                                int* retVal = nullptr,
                                const char* dir = nullptr,
                                OutputOption outputflag = OUTPUT_MERGE,
-                               double timeout = 0.0,
+                               cmDuration timeout = cmDuration::zero(),
                                Encoding encoding = cmProcessOutput::Auto);
 
   static std::string PrintSingleCommand(std::vector<std::string> const&);
@@ -343,7 +344,7 @@ public:
 
   /** a general output handler for cmsysProcess  */
   static int WaitForLine(cmsysProcess* process, std::string& line,
-                         double timeout, std::vector<char>& out,
+                         cmDuration timeout, std::vector<char>& out,
                          std::vector<char>& err);
 
   /** Split a string on its newlines into multiple lines.  Returns
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index 932b976..94edf93 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -5,6 +5,7 @@
 #include "cmsys/FStream.hxx"
 #include <stdio.h>
 
+#include "cmDuration.h"
 #include "cmMakefile.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
@@ -185,10 +186,9 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs,
   if (!runArgs.empty()) {
     finalCommand += runArgs;
   }
-  int timeout = 0;
   bool worked = cmSystemTools::RunSingleCommand(
     finalCommand.c_str(), out, out, &retVal, nullptr,
-    cmSystemTools::OUTPUT_NONE, timeout);
+    cmSystemTools::OUTPUT_NONE, cmDuration::zero());
   // set the run var
   char retChar[16];
   const char* retStr;
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 480646e..48e3ddf 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -7,6 +7,7 @@
 #include "cmDocumentation.h"
 #include "cmDocumentationEntry.h"
 #include "cmDocumentationFormatter.h"
+#include "cmDuration.h"
 #include "cmExternalMakefileProjectGenerator.h"
 #include "cmFileTimeComparison.h"
 #include "cmGeneratorTarget.h"
@@ -2475,8 +2476,8 @@ int cmake::Build(const std::string& dir, const std::string& target,
 #endif
 
   return gen->Build("", dir, projName, target, output, "", config, clean,
-                    false, verbose, 0, cmSystemTools::OUTPUT_PASSTHROUGH,
-                    nativeOptions);
+                    false, verbose, cmDuration::zero(),
+                    cmSystemTools::OUTPUT_PASSTHROUGH, nativeOptions);
 }
 
 bool cmake::Open(const std::string& dir, bool dryRun)
diff --git a/Source/cmakexbuild.cxx b/Source/cmakexbuild.cxx
index 20ead47..2951945 100644
--- a/Source/cmakexbuild.cxx
+++ b/Source/cmakexbuild.cxx
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include "cmDuration.h"
 #include "cmSystemTools.h"
 
 // This is a wrapper program for xcodebuild
@@ -27,7 +28,8 @@ int RunXCode(std::vector<const char*>& argv, bool& hitbug)
   std::vector<char> out;
   std::vector<char> err;
   std::string line;
-  int pipe = cmSystemTools::WaitForLine(cp, line, 100.0, out, err);
+  int pipe =
+    cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out, err);
   while (pipe != cmsysProcess_Pipe_None) {
     if (line.find("/bin/sh: bad interpreter: Text file busy") !=
         std::string::npos) {
@@ -45,7 +47,8 @@ int RunXCode(std::vector<const char*>& argv, bool& hitbug)
         std::cout << line << "\n";
       }
     }
-    pipe = cmSystemTools::WaitForLine(cp, line, 100, out, err);
+    pipe = cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out,
+                                      err);
   }
   cmsysProcess_WaitForExit(cp, nullptr);
   if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 2c3bda2..70e4fde 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -3,6 +3,7 @@
 #include "cmcmd.h"
 
 #include "cmAlgorithms.h"
+#include "cmDuration.h"
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
@@ -797,10 +798,9 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
       std::string command =
         cmWrap('"', cmMakeRange(args).advance(3), '"', " ");
       int retval = 0;
-      int timeout = 0;
       if (cmSystemTools::RunSingleCommand(
             command.c_str(), nullptr, nullptr, &retval, directory.c_str(),
-            cmSystemTools::OUTPUT_PASSTHROUGH, timeout)) {
+            cmSystemTools::OUTPUT_PASSTHROUGH, cmDuration::zero())) {
         return retval;
       }
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ff62b00522d1ddaeb88be241ab4a022f935b5c00
commit ff62b00522d1ddaeb88be241ab4a022f935b5c00
Author:     Wouter Klouwen <wouter.klouwen at youview.com>
AuthorDate: Tue Dec 12 21:59:43 2017 +0000
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Jan 23 10:05:12 2018 -0500

    CTest: add safe conversion from cmDuration to integer types
    
    A problem area by recent refactoring of time to std::chrono has been the
    unsafe conversion from duration<double> to std::chrono::seconds, which
    is of an unspecified integer type.
    
    This commit adds a template function that for a given type provides a
    safe conversion, effectively clamping a duration<double> into what fits
    safely in that type. A specialisation for int and unsigned int are
    provided.
    
    It changes the protential problem areas to use this safe function.

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index cd1287c..da5dc60 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -602,6 +602,9 @@ set(SRCS
   cm_codecvt.hxx
   cm_codecvt.cxx
   cm_thread.hxx
+
+  cmDuration.h
+  cmDuration.cxx
   )
 
 SET_PROPERTY(SOURCE cmProcessOutput.cxx APPEND PROPERTY COMPILE_DEFINITIONS
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 6b6c337..c3fbc0d 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -3,6 +3,7 @@
 #include "cmCTestMemCheckHandler.h"
 
 #include "cmCTest.h"
+#include "cmDuration.h"
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 #include "cmXMLWriter.h"
@@ -920,12 +921,11 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
       break; // stop the copy of output if we are full
     }
   }
-  cmCTestOptionalLog(this->CTest, DEBUG, "End test (elapsed: "
-                       << std::chrono::duration_cast<std::chrono::seconds>(
-                            std::chrono::steady_clock::now() - sttime)
-                            .count()
-                       << "s)" << std::endl,
-                     this->Quiet);
+  cmCTestOptionalLog(
+    this->CTest, DEBUG, "End test (elapsed: "
+      << cmDurationTo<unsigned int>(std::chrono::steady_clock::now() - sttime)
+      << "s)" << std::endl,
+    this->Quiet);
   log = ostr.str();
   this->DefectCount += defects;
   return defects == 0;
@@ -966,12 +966,11 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
     results[err]++;
     defects++;
   }
-  cmCTestOptionalLog(this->CTest, DEBUG, "End test (elapsed: "
-                       << std::chrono::duration_cast<std::chrono::seconds>(
-                            std::chrono::steady_clock::now() - sttime)
-                            .count()
-                       << "s)" << std::endl,
-                     this->Quiet);
+  cmCTestOptionalLog(
+    this->CTest, DEBUG, "End test (elapsed: "
+      << cmDurationTo<unsigned int>(std::chrono::steady_clock::now() - sttime)
+      << "s)" << std::endl,
+    this->Quiet);
   if (defects) {
     // only put the output of Bounds Checker if there were
     // errors or leaks detected
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index a5ec93d..8d602fa 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -621,17 +621,11 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
   if (testTimeOut == cmDuration::zero() && explicitTimeout) {
     timeout = cmDuration::zero();
   }
-  cmCTestOptionalLog(
-    this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
-      << ": "
-      << "Test timeout computed to be: "
-      << (timeout == cmCTest::MaxDuration()
-            ? std::string("infinite")
-            : std::to_string(
-                std::chrono::duration_cast<std::chrono::seconds>(timeout)
-                  .count()))
-      << "\n",
-    this->TestHandler->GetQuiet());
+  cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
+                       << ": "
+                       << "Test timeout computed to be: "
+                       << cmDurationTo<unsigned int>(timeout) << "\n",
+                     this->TestHandler->GetQuiet());
 
   this->TestProcess->SetTimeout(timeout);
 
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index d5faeb5..15a81f2 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -159,9 +159,9 @@ void cmCTestScriptHandler::UpdateElapsedTime()
 {
   if (this->Makefile) {
     // set the current elapsed time
-    auto itime = std::chrono::duration_cast<std::chrono::seconds>(
-      std::chrono::steady_clock::now() - this->ScriptStartTime);
-    auto timeString = std::to_string(itime.count());
+    auto itime = cmDurationTo<unsigned int>(std::chrono::steady_clock::now() -
+                                            this->ScriptStartTime);
+    auto timeString = std::to_string(itime);
     this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString.c_str());
   }
 }
@@ -569,10 +569,9 @@ int cmCTestScriptHandler::RunCurrentScript()
       auto interval = std::chrono::steady_clock::now() - startOfInterval;
       auto minimumInterval = cmDuration(this->MinimumInterval);
       if (interval < minimumInterval) {
-        auto sleepTime = std::chrono::duration_cast<std::chrono::seconds>(
-                           minimumInterval - interval)
-                           .count();
-        this->SleepInSeconds(static_cast<unsigned int>(sleepTime));
+        auto sleepTime =
+          cmDurationTo<unsigned int>(minimumInterval - interval);
+        this->SleepInSeconds(sleepTime);
       }
       if (this->EmptyBinDirOnce) {
         this->EmptyBinDir = false;
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 4be02ed..9e76480 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -1092,14 +1092,11 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
   if (timeout <= cmDuration::zero()) {
     timeout = std::chrono::seconds(1);
   }
-  cmCTestLog(
-    this, HANDLER_VERBOSE_OUTPUT, "Test timeout computed to be: "
-      << (timeout == cmCTest::MaxDuration()
-            ? std::string("infinite")
-            : std::to_string(
-                std::chrono::duration_cast<std::chrono::seconds>(timeout)
-                  .count()))
-      << "\n");
+  cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Test timeout computed to be: "
+               << (timeout == cmCTest::MaxDuration()
+                     ? std::string("infinite")
+                     : std::to_string(cmDurationTo<unsigned int>(timeout)))
+               << "\n");
   if (cmSystemTools::SameFile(argv[0], cmSystemTools::GetCTestCommand()) &&
       !this->ForceNewCTestProcess) {
     cmCTest inst;
@@ -1121,8 +1118,7 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
             timeout > cmDuration::zero()) {
           args.push_back("--test-timeout");
           std::ostringstream msg;
-          msg << std::chrono::duration_cast<std::chrono::seconds>(timeout)
-                   .count();
+          msg << cmDurationTo<unsigned int>(timeout);
           args.push_back(msg.str());
         }
         args.push_back(i);
diff --git a/Source/cmDuration.cxx b/Source/cmDuration.cxx
new file mode 100644
index 0000000..8ca5d8d
--- /dev/null
+++ b/Source/cmDuration.cxx
@@ -0,0 +1,27 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#define CMDURATION_CPP
+#include "cmDuration.h"
+
+template <typename T>
+T cmDurationTo(const cmDuration& duration)
+{
+  /* This works because the comparison operators for duration rely on
+   * std::common_type.
+   * So for example duration<int>::max() gets promoted to a duration<double>,
+   * which can then be safely compared.
+   */
+  if (duration >= std::chrono::duration<T>::max()) {
+    return std::chrono::duration<T>::max().count();
+  }
+  if (duration <= std::chrono::duration<T>::min()) {
+    return std::chrono::duration<T>::min().count();
+  }
+  // Ensure number of seconds by defining ratio<1>
+  return std::chrono::duration_cast<std::chrono::duration<T, std::ratio<1>>>(
+           duration)
+    .count();
+}
+
+template int cmDurationTo<int>(const cmDuration&);
+template unsigned int cmDurationTo<unsigned int>(const cmDuration&);
diff --git a/Source/cmDuration.h b/Source/cmDuration.h
index 5f73585..6df1455 100644
--- a/Source/cmDuration.h
+++ b/Source/cmDuration.h
@@ -6,3 +6,19 @@
 #include <ratio>
 
 typedef std::chrono::duration<double, std::ratio<1>> cmDuration;
+
+/*
+ * This function will return number of seconds in the requested type T.
+ *
+ * A duration_cast from duration<double> to duration<T> will not yield what
+ * one might expect if the double representation does not fit into type T.
+ * This function aims to safely convert, by clamping the double value between
+ * the permissible valid values for T.
+ */
+template <typename T>
+T cmDurationTo(const cmDuration& duration);
+
+#ifndef CMDURATION_CPP
+extern template int cmDurationTo<int>(const cmDuration&);
+extern template unsigned int cmDurationTo<unsigned int>(const cmDuration&);
+#endif

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=695951bc46fa4bc4eaf686c4ee6dce24c579bc45
commit 695951bc46fa4bc4eaf686c4ee6dce24c579bc45
Author:     Wouter Klouwen <wouter.klouwen at youview.com>
AuthorDate: Tue Dec 12 20:54:01 2017 +0000
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Jan 23 10:04:38 2018 -0500

    CTest: introduce cmDuration
    
    This commit introduces cmDuration as a typedef for
    std::chrono::duration<double, std::ratio<1>>. It is less verbose and
    provides for a point to put future common functionality for durations.
    
    No functional change intended.

diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index 85d98d0..3383c9d 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -19,7 +19,7 @@ cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler()
   this->BuildTwoConfig = false;
   this->BuildNoClean = false;
   this->BuildNoCMake = false;
-  this->Timeout = std::chrono::duration<double>::zero();
+  this->Timeout = cmDuration::zero();
 }
 
 void cmCTestBuildAndTestHandler::Initialize()
@@ -224,8 +224,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
     this->BuildTargets.push_back("");
   }
   for (std::string const& tar : this->BuildTargets) {
-    std::chrono::duration<double> remainingTime = std::chrono::seconds(0);
-    if (this->Timeout > std::chrono::duration<double>::zero()) {
+    cmDuration remainingTime = std::chrono::seconds(0);
+    if (this->Timeout > cmDuration::zero()) {
       remainingTime =
         this->Timeout - (std::chrono::steady_clock::now() - clock_start);
       if (remainingTime <= std::chrono::seconds(0)) {
@@ -323,8 +323,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
   out << "\n";
 
   // how much time is remaining
-  std::chrono::duration<double> remainingTime = std::chrono::seconds(0);
-  if (this->Timeout > std::chrono::duration<double>::zero()) {
+  cmDuration remainingTime = std::chrono::seconds(0);
+  if (this->Timeout > cmDuration::zero()) {
     remainingTime =
       this->Timeout - (std::chrono::steady_clock::now() - clock_start);
     if (remainingTime <= std::chrono::seconds(0)) {
@@ -395,7 +395,7 @@ int cmCTestBuildAndTestHandler::ProcessCommandLineArguments(
   }
   if (currentArg.find("--test-timeout", 0) == 0 && idx < allArgs.size() - 1) {
     idx++;
-    this->Timeout = std::chrono::duration<double>(atof(allArgs[idx].c_str()));
+    this->Timeout = cmDuration(atof(allArgs[idx].c_str()));
   }
   if (currentArg == "--build-generator" && idx < allArgs.size() - 1) {
     idx++;
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h
index f8a9ed7..5e6d0aa 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.h
+++ b/Source/CTest/cmCTestBuildAndTestHandler.h
@@ -6,8 +6,8 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
 
-#include <chrono>
 #include <sstream>
 #include <stddef.h>
 #include <string>
@@ -68,7 +68,7 @@ protected:
   std::vector<std::string> TestCommandArgs;
   std::vector<std::string> BuildTargets;
   bool BuildNoCMake;
-  std::chrono::duration<double> Timeout;
+  cmDuration Timeout;
 };
 
 #endif
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index ef4d3c6..2acf5e8 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -4,6 +4,7 @@
 
 #include "cmAlgorithms.h"
 #include "cmCTest.h"
+#include "cmDuration.h"
 #include "cmFileTimeComparison.h"
 #include "cmGeneratedFileStream.h"
 #include "cmMakefile.h"
@@ -633,8 +634,8 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml)
   }
 }
 
-void cmCTestBuildHandler::GenerateXMLFooter(
-  cmXMLWriter& xml, std::chrono::duration<double> elapsed_build_time)
+void cmCTestBuildHandler::GenerateXMLFooter(cmXMLWriter& xml,
+                                            cmDuration elapsed_build_time)
 {
   xml.StartElement("Log");
   xml.Attribute("Encoding", "base64");
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index d1b9b2e..a9b121b 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -7,6 +7,7 @@
 
 #include "cmCTestGenericHandler.h"
 
+#include "cmDuration.h"
 #include "cmProcessOutput.h"
 #include "cmsys/RegularExpression.hxx"
 #include <chrono>
@@ -87,8 +88,7 @@ private:
   void GenerateXMLHeader(cmXMLWriter& xml);
   void GenerateXMLLaunched(cmXMLWriter& xml);
   void GenerateXMLLogScraped(cmXMLWriter& xml);
-  void GenerateXMLFooter(cmXMLWriter& xml,
-                         std::chrono::duration<double> elapsed_build_time);
+  void GenerateXMLFooter(cmXMLWriter& xml, cmDuration elapsed_build_time);
   bool IsLaunchedErrorFile(const char* fname);
   bool IsLaunchedWarningFile(const char* fname);
 
diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx
index eb067e5..821a94a 100644
--- a/Source/CTest/cmCTestConfigureHandler.cxx
+++ b/Source/CTest/cmCTestConfigureHandler.cxx
@@ -3,6 +3,7 @@
 #include "cmCTestConfigureHandler.h"
 
 #include "cmCTest.h"
+#include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
 #include "cmXMLWriter.h"
 
@@ -62,9 +63,9 @@ int cmCTestConfigureHandler::ProcessHandler()
     cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                        "Configure with command: " << cCommand << std::endl,
                        this->Quiet);
-    res = this->CTest->RunMakeCommand(
-      cCommand.c_str(), output, &retVal, buildDirectory.c_str(),
-      std::chrono::duration<double>::zero(), ofs);
+    res = this->CTest->RunMakeCommand(cCommand.c_str(), output, &retVal,
+                                      buildDirectory.c_str(),
+                                      cmDuration::zero(), ofs);
 
     if (ofs) {
       ofs.close();
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 2a9fd72..856421f 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -3,6 +3,7 @@
 #include "cmCTestCoverageHandler.h"
 
 #include "cmCTest.h"
+#include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
 #include "cmParseBlanketJSCoverage.h"
 #include "cmParseCacheCoverage.h"
@@ -40,7 +41,7 @@ public:
   {
     this->Process = cmsysProcess_New();
     this->PipeState = -1;
-    this->TimeOut = std::chrono::duration<double>(-1);
+    this->TimeOut = cmDuration(-1);
   }
   ~cmCTestRunProcess()
   {
@@ -64,7 +65,7 @@ public:
     }
   }
   void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; }
-  void SetTimeout(std::chrono::duration<double> t) { this->TimeOut = t; }
+  void SetTimeout(cmDuration t) { this->TimeOut = t; }
   bool StartProcess()
   {
     std::vector<const char*> args;
@@ -79,7 +80,7 @@ public:
     }
 
     cmsysProcess_SetOption(this->Process, cmsysProcess_Option_HideWindow, 1);
-    if (this->TimeOut >= std::chrono::duration<double>::zero()) {
+    if (this->TimeOut >= cmDuration::zero()) {
       cmsysProcess_SetTimeout(this->Process, this->TimeOut.count());
     }
     cmsysProcess_Execute(this->Process);
@@ -108,7 +109,7 @@ private:
   cmsysProcess* Process;
   std::vector<std::string> CommandLineStrings;
   std::string WorkingDirectory;
-  std::chrono::duration<double> TimeOut;
+  cmDuration TimeOut;
 };
 
 cmCTestCoverageHandler::cmCTestCoverageHandler()
@@ -1022,9 +1023,9 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
     int retVal = 0;
     *cont->OFS << "* Run coverage for: " << fileDir << std::endl;
     *cont->OFS << "  Command: " << command << std::endl;
-    int res = this->CTest->RunCommand(
-      covargs, &output, &errors, &retVal, tempDir.c_str(),
-      std::chrono::duration<double>::zero() /*this->TimeOut*/);
+    int res = this->CTest->RunCommand(covargs, &output, &errors, &retVal,
+                                      tempDir.c_str(),
+                                      cmDuration::zero() /*this->TimeOut*/);
 
     *cont->OFS << "  Output: " << output << std::endl;
     *cont->OFS << "  Errors: " << errors << std::endl;
@@ -1387,9 +1388,9 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
     int retVal = 0;
     *cont->OFS << "* Run coverage for: " << fileDir << std::endl;
     *cont->OFS << "  Command: " << command << std::endl;
-    int res = this->CTest->RunCommand(
-      covargs, &output, &errors, &retVal, fileDir.c_str(),
-      std::chrono::duration<double>::zero() /*this->TimeOut*/);
+    int res = this->CTest->RunCommand(covargs, &output, &errors, &retVal,
+                                      fileDir.c_str(),
+                                      cmDuration::zero() /*this->TimeOut*/);
 
     *cont->OFS << "  Output: " << output << std::endl;
     *cont->OFS << "  Errors: " << errors << std::endl;
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index baf894e..a5ec93d 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -25,7 +25,7 @@ cmCTestRunTest::cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler)
 {
   this->CTest = multiHandler.CTest;
   this->TestHandler = multiHandler.TestHandler;
-  this->TestResult.ExecutionTime = std::chrono::duration<double>::zero();
+  this->TestResult.ExecutionTime = cmDuration::zero();
   this->TestResult.ReturnValue = 0;
   this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
   this->TestResult.TestCount = 0;
@@ -400,7 +400,7 @@ bool cmCTestRunTest::StartTest(size_t total)
   // Return immediately if test is disabled
   if (this->TestProperties->Disabled) {
     this->TestResult.Properties = this->TestProperties;
-    this->TestResult.ExecutionTime = std::chrono::duration<double>::zero();
+    this->TestResult.ExecutionTime = cmDuration::zero();
     this->TestResult.CompressOutput = false;
     this->TestResult.ReturnValue = -1;
     this->TestResult.CompletionStatus = "Disabled";
@@ -415,7 +415,7 @@ bool cmCTestRunTest::StartTest(size_t total)
   }
 
   this->TestResult.Properties = this->TestProperties;
-  this->TestResult.ExecutionTime = std::chrono::duration<double>::zero();
+  this->TestResult.ExecutionTime = cmDuration::zero();
   this->TestResult.CompressOutput = false;
   this->TestResult.ReturnValue = -1;
   this->TestResult.CompletionStatus = "Failed to start";
@@ -590,8 +590,7 @@ void cmCTestRunTest::DartProcessing()
   }
 }
 
-bool cmCTestRunTest::ForkProcess(std::chrono::duration<double> testTimeOut,
-                                 bool explicitTimeout,
+bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
                                  std::vector<std::string>* environment)
 {
   this->TestProcess = cm::make_unique<cmProcess>(*this);
@@ -602,27 +601,25 @@ bool cmCTestRunTest::ForkProcess(std::chrono::duration<double> testTimeOut,
   this->TestProcess->SetCommandArguments(this->Arguments);
 
   // determine how much time we have
-  std::chrono::duration<double> timeout =
-    this->CTest->GetRemainingTimeAllowed();
+  cmDuration timeout = this->CTest->GetRemainingTimeAllowed();
   if (timeout != cmCTest::MaxDuration()) {
     timeout -= std::chrono::minutes(2);
   }
-  if (this->CTest->GetTimeOut() > std::chrono::duration<double>::zero() &&
+  if (this->CTest->GetTimeOut() > cmDuration::zero() &&
       this->CTest->GetTimeOut() < timeout) {
     timeout = this->CTest->GetTimeOut();
   }
-  if (testTimeOut > std::chrono::duration<double>::zero() &&
+  if (testTimeOut > cmDuration::zero() &&
       testTimeOut < this->CTest->GetRemainingTimeAllowed()) {
     timeout = testTimeOut;
   }
   // always have at least 1 second if we got to here
-  if (timeout <= std::chrono::duration<double>::zero()) {
+  if (timeout <= cmDuration::zero()) {
     timeout = std::chrono::seconds(1);
   }
   // handle timeout explicitly set to 0
-  if (testTimeOut == std::chrono::duration<double>::zero() &&
-      explicitTimeout) {
-    timeout = std::chrono::duration<double>::zero();
+  if (testTimeOut == cmDuration::zero() && explicitTimeout) {
+    timeout = cmDuration::zero();
   }
   cmCTestOptionalLog(
     this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index fbc202f..4d57357 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -5,13 +5,13 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <chrono>
 #include <set>
 #include <stddef.h>
 #include <string>
 #include <vector>
 
 #include "cmCTestTestHandler.h"
+#include "cmDuration.h"
 #include "cmProcess.h" // IWYU pragma: keep (for unique_ptr)
 
 class cmCTest;
@@ -82,8 +82,7 @@ private:
   bool NeedsToRerun();
   void DartProcessing();
   void ExeNotFound(std::string exe);
-  bool ForkProcess(std::chrono::duration<double> testTimeOut,
-                   bool explicitTimeout,
+  bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
                    std::vector<std::string>* environment);
   void WriteLogOutputTop(size_t completed, size_t total);
   // Run post processing of the process output for MemCheck
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 716ea10..d5faeb5 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -558,8 +558,8 @@ int cmCTestScriptHandler::RunCurrentScript()
   // for a continuous, do we ned to run it more than once?
   if (this->ContinuousDuration >= 0) {
     this->UpdateElapsedTime();
-    auto ending_time = std::chrono::steady_clock::now() +
-      std::chrono::duration<double>(this->ContinuousDuration);
+    auto ending_time =
+      std::chrono::steady_clock::now() + cmDuration(this->ContinuousDuration);
     if (this->EmptyBinDirOnce) {
       this->EmptyBinDir = true;
     }
@@ -567,8 +567,7 @@ int cmCTestScriptHandler::RunCurrentScript()
       auto startOfInterval = std::chrono::steady_clock::now();
       result = this->RunConfigurationDashboard();
       auto interval = std::chrono::steady_clock::now() - startOfInterval;
-      auto minimumInterval =
-        std::chrono::duration<double>(this->MinimumInterval);
+      auto minimumInterval = cmDuration(this->MinimumInterval);
       if (interval < minimumInterval) {
         auto sleepTime = std::chrono::duration_cast<std::chrono::seconds>(
                            minimumInterval - interval)
@@ -960,7 +959,7 @@ bool cmCTestScriptHandler::TryToRemoveBinaryDirectoryOnce(
   return cmSystemTools::RemoveADirectory(directoryPath);
 }
 
-std::chrono::duration<double> cmCTestScriptHandler::GetRemainingTimeAllowed()
+cmDuration cmCTestScriptHandler::GetRemainingTimeAllowed()
 {
   if (!this->Makefile) {
     return cmCTest::MaxDuration();
@@ -972,9 +971,9 @@ std::chrono::duration<double> cmCTestScriptHandler::GetRemainingTimeAllowed()
     return cmCTest::MaxDuration();
   }
 
-  auto timelimit = std::chrono::duration<double>(atof(timelimitS));
+  auto timelimit = cmDuration(atof(timelimitS));
 
-  auto duration = std::chrono::duration_cast<std::chrono::duration<double>>(
+  auto duration = std::chrono::duration_cast<cmDuration>(
     std::chrono::steady_clock::now() - this->ScriptStartTime);
   return (timelimit - duration);
 }
diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h
index 9b7fa75..ea5d5af 100644
--- a/Source/CTest/cmCTestScriptHandler.h
+++ b/Source/CTest/cmCTestScriptHandler.h
@@ -6,6 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
 
 #include <chrono>
 #include <string>
@@ -96,7 +97,7 @@ public:
    * seconds if the user has set the variable CTEST_TIME_LIMIT. If that has
    * not been set it returns a very large value.
    */
-  std::chrono::duration<double> GetRemainingTimeAllowed();
+  cmDuration GetRemainingTimeAllowed();
 
   cmCTestScriptHandler();
   ~cmCTestScriptHandler() override;
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 86fee7a..1ce2b6f 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -16,6 +16,7 @@
 #include "cmCTestScriptHandler.h"
 #include "cmCryptoHash.h"
 #include "cmCurl.h"
+#include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
 #include "cmProcessOutput.h"
 #include "cmState.h"
@@ -497,7 +498,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
           ? ""
           : this->GetOption("RetryCount");
 
-        auto delay = std::chrono::duration<double>(
+        auto delay = cmDuration(
           retryDelay.empty()
             ? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryDelay")
                      .c_str())
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 232bd58..daedf62 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -4,6 +4,7 @@
 
 #include "cmCTest.h"
 #include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
 
@@ -37,12 +38,12 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
   const char* ctestTimeout =
     this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT");
 
-  std::chrono::duration<double> timeout;
+  cmDuration timeout;
   if (ctestTimeout) {
-    timeout = std::chrono::duration<double>(atof(ctestTimeout));
+    timeout = cmDuration(atof(ctestTimeout));
   } else {
     timeout = this->CTest->GetTimeOut();
-    if (timeout <= std::chrono::duration<double>::zero()) {
+    if (timeout <= cmDuration::zero()) {
       // By default use timeout of 10 minutes
       timeout = std::chrono::minutes(10);
     }
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 4c7cefb..ce7c194 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -21,6 +21,7 @@
 #include "cmCTest.h"
 #include "cmCTestMultiProcessHandler.h"
 #include "cmCommand.h"
+#include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
@@ -346,7 +347,7 @@ void cmCTestTestHandler::Initialize()
 {
   this->Superclass::Initialize();
 
-  this->ElapsedTestingTime = std::chrono::duration<double>();
+  this->ElapsedTestingTime = cmDuration();
 
   this->TestResults.clear();
 
@@ -539,7 +540,7 @@ int cmCTestTestHandler::ProcessHandler()
       this->PrintLabelOrSubprojectSummary(false);
     }
     char realBuf[1024];
-    std::chrono::duration<double> durationInSecs = clock_finish - clock_start;
+    cmDuration durationInSecs = clock_finish - clock_start;
     sprintf(realBuf, "%6.2f sec", durationInSecs.count());
     cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
                        "\nTotal Test time (real) = " << realBuf << "\n",
@@ -1235,9 +1236,8 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed,
       p.Cost = static_cast<float>(rand());
     }
 
-    if (p.Timeout == std::chrono::duration<double>::zero() &&
-        this->CTest->GetGlobalTimeout() !=
-          std::chrono::duration<double>::zero()) {
+    if (p.Timeout == cmDuration::zero() &&
+        this->CTest->GetGlobalTimeout() != cmDuration::zero()) {
       p.Timeout = this->CTest->GetGlobalTimeout();
     }
 
@@ -2140,7 +2140,7 @@ bool cmCTestTestHandler::SetTestsProperties(
             rt.FixturesRequired.insert(lval.begin(), lval.end());
           }
           if (key == "TIMEOUT") {
-            rt.Timeout = std::chrono::duration<double>(atof(val.c_str()));
+            rt.Timeout = cmDuration(atof(val.c_str()));
             rt.ExplicitTimeout = true;
           }
           if (key == "COST") {
@@ -2220,8 +2220,7 @@ bool cmCTestTestHandler::SetTestsProperties(
                          "TIMEOUT_AFTER_MATCH expects two arguments, found "
                            << propArgs.size() << std::endl);
             } else {
-              rt.AlternateTimeout =
-                std::chrono::duration<double>(atof(propArgs[0].c_str()));
+              rt.AlternateTimeout = cmDuration(atof(propArgs[0].c_str()));
               std::vector<std::string> lval;
               cmSystemTools::ExpandListArgument(propArgs[1], lval);
               for (std::string const& cr : lval) {
@@ -2339,7 +2338,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
   test.WillFail = false;
   test.Disabled = false;
   test.RunSerial = false;
-  test.Timeout = std::chrono::duration<double>::zero();
+  test.Timeout = cmDuration::zero();
   test.ExplicitTimeout = false;
   test.Cost = 0;
   test.Processors = 1;
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 4fb067a..f4978b6 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -6,6 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
 
 #include "cmsys/RegularExpression.hxx"
 #include <chrono>
@@ -123,9 +124,9 @@ public:
     float Cost;
     int PreviousRuns;
     bool RunSerial;
-    std::chrono::duration<double> Timeout;
+    cmDuration Timeout;
     bool ExplicitTimeout;
-    std::chrono::duration<double> AlternateTimeout;
+    cmDuration AlternateTimeout;
     int Index;
     // Requested number of process slots
     int Processors;
@@ -146,7 +147,7 @@ public:
     std::string Path;
     std::string Reason;
     std::string FullCommandLine;
-    std::chrono::duration<double> ExecutionTime;
+    cmDuration ExecutionTime;
     int ReturnValue;
     int Status;
     std::string ExceptionStatus;
@@ -198,7 +199,7 @@ protected:
   //! Clean test output to specified length
   bool CleanTestOutput(std::string& output, size_t length);
 
-  std::chrono::duration<double> ElapsedTestingTime;
+  cmDuration ElapsedTestingTime;
 
   typedef std::vector<cmCTestTestResult> TestResultsVector;
   TestResultsVector TestResults;
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index e332a77..09ed0a9 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -62,8 +62,8 @@ cmProcess::cmProcess(cmCTestRunTest& runner)
   : Runner(runner)
   , Conv(cmProcessOutput::UTF8, CM_PROCESS_BUF_SIZE)
 {
-  this->Timeout = std::chrono::duration<double>::zero();
-  this->TotalTime = std::chrono::duration<double>::zero();
+  this->Timeout = cmDuration::zero();
+  this->TotalTime = cmDuration::zero();
   this->ExitValue = 0;
   this->Id = 0;
   this->StartTime = std::chrono::steady_clock::time_point();
@@ -344,8 +344,8 @@ void cmProcess::OnExit(int64_t exit_status, int term_signal)
   // negative. If someone changed the system clock while the process was
   // running this may be even more. Make sure not to report a negative
   // duration here.
-  if (this->TotalTime <= std::chrono::duration<double>::zero()) {
-    this->TotalTime = std::chrono::duration<double>::zero();
+  if (this->TotalTime <= cmDuration::zero()) {
+    this->TotalTime = cmDuration::zero();
   }
 
   this->ProcessHandleClosed = true;
@@ -360,7 +360,7 @@ cmProcess::State cmProcess::GetProcessStatus()
   return this->ProcessState;
 }
 
-void cmProcess::ChangeTimeout(std::chrono::duration<double> t)
+void cmProcess::ChangeTimeout(cmDuration t)
 {
   this->Timeout = t;
   this->StartTimer();
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index 633be24..20e24b9 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -4,6 +4,7 @@
 #define cmProcess_h
 
 #include "cmConfigure.h" // IWYU pragma: keep
+#include "cmDuration.h"
 
 #include "cmProcessOutput.h"
 #include "cmUVHandlePtr.h"
@@ -31,8 +32,8 @@ public:
   void SetCommand(const char* command);
   void SetCommandArguments(std::vector<std::string> const& arg);
   void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; }
-  void SetTimeout(std::chrono::duration<double> t) { this->Timeout = t; }
-  void ChangeTimeout(std::chrono::duration<double> t);
+  void SetTimeout(cmDuration t) { this->Timeout = t; }
+  void ChangeTimeout(cmDuration t);
   void ResetStartTime();
   // Return true if the process starts
   bool StartProcess(uv_loop_t& loop);
@@ -53,7 +54,7 @@ public:
   int GetId() { return this->Id; }
   void SetId(int id) { this->Id = id; }
   int GetExitValue() { return this->ExitValue; }
-  std::chrono::duration<double> GetTotalTime() { return this->TotalTime; }
+  cmDuration GetTotalTime() { return this->TotalTime; }
 
   enum class Exception
   {
@@ -69,9 +70,9 @@ public:
   std::string GetExitExceptionString();
 
 private:
-  std::chrono::duration<double> Timeout;
+  cmDuration Timeout;
   std::chrono::steady_clock::time_point StartTime;
-  std::chrono::duration<double> TotalTime;
+  cmDuration TotalTime;
   bool ReadHandleClosed = false;
   bool ProcessHandleClosed = false;
 
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index fd7c5e8..4be02ed 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -277,8 +277,8 @@ cmCTest::cmCTest()
   this->TestModel = cmCTest::EXPERIMENTAL;
   this->MaxTestNameWidth = 30;
   this->InteractiveDebugMode = true;
-  this->TimeOut = std::chrono::duration<double>::zero();
-  this->GlobalTimeout = std::chrono::duration<double>::zero();
+  this->TimeOut = cmDuration::zero();
+  this->GlobalTimeout = cmDuration::zero();
   this->CompressXMLFiles = false;
   this->ScheduleType.clear();
   this->OutputLogFile = nullptr;
@@ -954,8 +954,7 @@ int cmCTest::GetTestModelFromString(const char* str)
 //######################################################################
 
 int cmCTest::RunMakeCommand(const char* command, std::string& output,
-                            int* retVal, const char* dir,
-                            std::chrono::duration<double> timeout,
+                            int* retVal, const char* dir, cmDuration timeout,
                             std::ostream& ofs, Encoding encoding)
 {
   // First generate the command and arguments
@@ -1071,28 +1070,26 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output,
 //######################################################################
 
 int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
-                     int* retVal, std::ostream* log,
-                     std::chrono::duration<double> testTimeOut,
+                     int* retVal, std::ostream* log, cmDuration testTimeOut,
                      std::vector<std::string>* environment, Encoding encoding)
 {
   bool modifyEnv = (environment && !environment->empty());
 
   // determine how much time we have
-  std::chrono::duration<double> timeout = this->GetRemainingTimeAllowed();
+  cmDuration timeout = this->GetRemainingTimeAllowed();
   if (timeout != cmCTest::MaxDuration()) {
     timeout -= std::chrono::minutes(2);
   }
-  if (this->TimeOut > std::chrono::duration<double>::zero() &&
-      this->TimeOut < timeout) {
+  if (this->TimeOut > cmDuration::zero() && this->TimeOut < timeout) {
     timeout = this->TimeOut;
   }
-  if (testTimeOut > std::chrono::duration<double>::zero() &&
+  if (testTimeOut > cmDuration::zero() &&
       testTimeOut < this->GetRemainingTimeAllowed()) {
     timeout = testTimeOut;
   }
 
   // always have at least 1 second if we got to here
-  if (timeout <= std::chrono::duration<double>::zero()) {
+  if (timeout <= cmDuration::zero()) {
     timeout = std::chrono::seconds(1);
   }
   cmCTestLog(
@@ -1121,7 +1118,7 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
         // good place to check for it, and to add the arguments in
         if (strcmp(i, "--build-generator") == 0 &&
             timeout != cmCTest::MaxDuration() &&
-            timeout > std::chrono::duration<double>::zero()) {
+            timeout > cmDuration::zero()) {
           args.push_back("--test-timeout");
           std::ostringstream msg;
           msg << std::chrono::duration_cast<std::chrono::seconds>(timeout)
@@ -1772,7 +1769,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
 
   if (this->CheckArgument(arg, "--timeout") && i < args.size() - 1) {
     i++;
-    auto timeout = std::chrono::duration<double>(atof(args[i].c_str()));
+    auto timeout = cmDuration(atof(args[i].c_str()));
     this->GlobalTimeout = timeout;
   }
 
@@ -2575,8 +2572,7 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable(
 
 bool cmCTest::RunCommand(std::vector<std::string> const& args,
                          std::string* stdOut, std::string* stdErr, int* retVal,
-                         const char* dir,
-                         std::chrono::duration<double> timeout,
+                         const char* dir, cmDuration timeout,
                          Encoding encoding)
 {
   std::vector<const char*> argv;
@@ -2788,7 +2784,7 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg,
   }
 }
 
-std::chrono::duration<double> cmCTest::GetRemainingTimeAllowed()
+cmDuration cmCTest::GetRemainingTimeAllowed()
 {
   if (!this->GetHandler("script")) {
     return cmCTest::MaxDuration();
@@ -2800,9 +2796,9 @@ std::chrono::duration<double> cmCTest::GetRemainingTimeAllowed()
   return ch->GetRemainingTimeAllowed();
 }
 
-std::chrono::duration<double> cmCTest::MaxDuration()
+cmDuration cmCTest::MaxDuration()
 {
-  return std::chrono::duration<double>(1.0e7);
+  return cmDuration(1.0e7);
 }
 
 void cmCTest::OutputTestErrors(std::vector<char> const& process_output)
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 61487f1..a4d9a86 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cmDuration.h"
 #include "cmProcessOutput.h"
 #include "cmsys/String.hxx"
 #include <chrono>
@@ -140,13 +141,10 @@ public:
 
   /** what is the configuraiton type, e.g. Debug, Release etc. */
   std::string const& GetConfigType();
-  std::chrono::duration<double> GetTimeOut() { return this->TimeOut; }
-  void SetTimeOut(std::chrono::duration<double> t) { this->TimeOut = t; }
+  cmDuration GetTimeOut() { return this->TimeOut; }
+  void SetTimeOut(cmDuration t) { this->TimeOut = t; }
 
-  std::chrono::duration<double> GetGlobalTimeout()
-  {
-    return this->GlobalTimeout;
-  }
+  cmDuration GetGlobalTimeout() { return this->GlobalTimeout; }
 
   /** how many test to run at the same time */
   int GetParallelLevel() { return this->ParallelLevel; }
@@ -206,9 +204,9 @@ public:
    * seconds if the user has set the variable CTEST_TIME_LIMIT. If that has
    * not been set it returns a very large duration.
    */
-  std::chrono::duration<double> GetRemainingTimeAllowed();
+  cmDuration GetRemainingTimeAllowed();
 
-  static std::chrono::duration<double> MaxDuration();
+  static cmDuration MaxDuration();
 
   /**
    * Open file in the output directory and set the stream
@@ -258,8 +256,7 @@ public:
   bool RunCommand(std::vector<std::string> const& args, std::string* stdOut,
                   std::string* stdErr, int* retVal = nullptr,
                   const char* dir = nullptr,
-                  std::chrono::duration<double> timeout =
-                    std::chrono::duration<double>::zero(),
+                  cmDuration timeout = cmDuration::zero(),
                   Encoding encoding = cmProcessOutput::Auto);
 
   /**
@@ -279,8 +276,7 @@ public:
    * and retVal is return value or exception.
    */
   int RunMakeCommand(const char* command, std::string& output, int* retVal,
-                     const char* dir, std::chrono::duration<double> timeout,
-                     std::ostream& ofs,
+                     const char* dir, cmDuration timeout, std::ostream& ofs,
                      Encoding encoding = cmProcessOutput::Auto);
 
   /** Return the current tag */
@@ -327,7 +323,7 @@ public:
    * environment variables are restored to their previous values.
    */
   int RunTest(std::vector<const char*> args, std::string* output, int* retVal,
-              std::ostream* logfile, std::chrono::duration<double> testTimeOut,
+              std::ostream* logfile, cmDuration testTimeOut,
               std::vector<std::string>* environment,
               Encoding encoding = cmProcessOutput::Auto);
 
@@ -508,9 +504,9 @@ private:
   int TestModel;
   std::string SpecificTrack;
 
-  std::chrono::duration<double> TimeOut;
+  cmDuration TimeOut;
 
-  std::chrono::duration<double> GlobalTimeout;
+  cmDuration GlobalTimeout;
 
   int MaxTestNameWidth;
 
diff --git a/Source/cmDuration.h b/Source/cmDuration.h
new file mode 100644
index 0000000..5f73585
--- /dev/null
+++ b/Source/cmDuration.h
@@ -0,0 +1,8 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#pragma once
+
+#include <chrono>
+#include <ratio>
+
+typedef std::chrono::duration<double, std::ratio<1>> cmDuration;

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

Summary of changes:
 Source/CMakeLists.txt                              |    4 +
 Source/CPack/IFW/cmCPackIFWGenerator.cxx           |   13 +-
 Source/CPack/cmCPackDragNDropGenerator.cxx         |    7 +-
 Source/CPack/cmCPackGenerator.cxx                  |   10 +-
 Source/CPack/cmCPackNSISGenerator.cxx              |   19 +-
 Source/CPack/cmCPackOSXX11Generator.cxx            |    7 +-
 Source/CPack/cmCPackPackageMakerGenerator.cxx      |   10 +-
 Source/CPack/cmCPackProductBuildGenerator.cxx      |    7 +-
 Source/CTest/cmCTestBuildAndTestHandler.cxx        |   14 +-
 Source/CTest/cmCTestBuildAndTestHandler.h          |    4 +-
 Source/CTest/cmCTestBuildHandler.cxx               |    5 +-
 Source/CTest/cmCTestBuildHandler.h                 |    4 +-
 Source/CTest/cmCTestConfigureHandler.cxx           |    7 +-
 Source/CTest/cmCTestCoverageHandler.cxx            |   21 +-
 Source/CTest/cmCTestMemCheckHandler.cxx            |   23 +-
 Source/CTest/cmCTestMultiProcessHandler.cxx        |   39 +-
 Source/CTest/cmCTestRunTest.cxx                    |   41 +-
 Source/CTest/cmCTestRunTest.h                      |    5 +-
 Source/CTest/cmCTestScriptHandler.cxx              |   42 +-
 Source/CTest/cmCTestScriptHandler.h                |    3 +-
 Source/CTest/cmCTestSubmitHandler.cxx              |    3 +-
 Source/CTest/cmCTestTestCommand.cxx                |    7 +-
 Source/CTest/cmCTestTestHandler.cxx                |   17 +-
 Source/CTest/cmCTestTestHandler.h                  |    9 +-
 Source/CTest/cmProcess.cxx                         |   10 +-
 Source/CTest/cmProcess.h                           |   11 +-
 Source/cmCTest.cxx                                 |   48 +-
 Source/cmCTest.h                                   |   26 +-
 Source/cmDuration.cxx                              |   27 +
 Source/cmDuration.h                                |   24 +
 Source/cmGlobalGenerator.cxx                       |    5 +-
 Source/cmGlobalGenerator.h                         |    7 +-
 Source/cmQtAutoGenInitializer.cxx                  |    5 +-
 Source/cmQtAutoGenerator.h                         |   38 +-
 Source/cmSystemTools.cxx                           |   13 +-
 Source/cmSystemTools.h                             |    7 +-
 Source/cmTryRunCommand.cxx                         |    4 +-
 Source/cmUVSignalHackRAII.h                        |   44 +
 Source/cmake.cxx                                   |    5 +-
 Source/cmakexbuild.cxx                             |    7 +-
 Source/cmcmd.cxx                                   |    4 +-
 .../BadTargetTypeObject-stderr.txt                 |    6 +-
 .../GeneratorExpression/BadTargetTypeObject.cmake  |    3 +-
 .../GeneratorExpression/CMP0044-WARN.cmake         |    2 +-
 .../COMPILE_LANGUAGE-add_custom_command-stderr.txt |    2 +-
 .../COMPILE_LANGUAGE-add_custom_command.cmake      |    8 +-
 .../COMPILE_LANGUAGE-add_custom_target-stderr.txt  |    2 +-
 .../COMPILE_LANGUAGE-add_custom_target.cmake       |    5 +-
 .../COMPILE_LANGUAGE-add_executable-stderr.txt     |    2 +-
 .../COMPILE_LANGUAGE-add_executable.cmake          |    3 -
 .../COMPILE_LANGUAGE-add_library-stderr.txt        |    2 +-
 .../COMPILE_LANGUAGE-add_library.cmake             |    3 -
 .../COMPILE_LANGUAGE-target_sources-stderr.txt     |    2 +-
 .../COMPILE_LANGUAGE-target_sources.cmake          |    5 +-
 .../NonValidTarget-CXX_COMPILER_ID-stderr.txt      |    2 +-
 .../NonValidTarget-CXX_COMPILER_ID.cmake           |    6 +-
 .../NonValidTarget-CXX_COMPILER_VERSION-stderr.txt |    2 +-
 .../NonValidTarget-CXX_COMPILER_VERSION.cmake      |    6 +-
 .../NonValidTarget-C_COMPILER_ID-stderr.txt        |    2 +-
 .../NonValidTarget-C_COMPILER_ID.cmake             |   10 +-
 .../NonValidTarget-C_COMPILER_VERSION-stderr.txt   |    2 +-
 .../NonValidTarget-C_COMPILER_VERSION.cmake        |   10 +-
 .../NonValidTarget-TARGET_POLICY-stderr.txt        |    2 +-
 .../NonValidTarget-TARGET_POLICY.cmake             |    6 +-
 .../NonValidTarget-TARGET_PROPERTY-stderr.txt      |    2 +-
 .../NonValidTarget-TARGET_PROPERTY.cmake           |    6 +-
 .../BadInvalidName-result.txt}                     |    0
 .../BadInvalidName-stderr.txt                      |   50 +
 .../BadInvalidName.cmake                           |    8 +
 .../BadInvalidName1-result.txt                     |    1 -
 .../BadInvalidName1-stderr.txt                     |    8 -
 .../BadInvalidName1.cmake                          |    7 -
 .../BadInvalidName1/CMakeLists.txt                 |    2 +
 .../BadInvalidName2-result.txt                     |    1 -
 .../BadInvalidName2-stderr.txt                     |    8 -
 .../BadInvalidName2.cmake                          |    7 -
 .../BadInvalidName2/CMakeLists.txt                 |    2 +
 .../BadInvalidName3-result.txt                     |    1 -
 .../BadInvalidName3-stderr.txt                     |    8 -
 .../BadInvalidName3.cmake                          |    7 -
 .../BadInvalidName3/CMakeLists.txt                 |    2 +
 .../BadInvalidName4-result.txt                     |    1 -
 .../BadInvalidName4-stderr.txt                     |    8 -
 .../BadInvalidName4.cmake                          |    9 -
 .../BadInvalidName4/CMakeLists.txt                 |    2 +
 .../BadInvalidName5-result.txt                     |    1 -
 .../BadInvalidName5-stderr.txt                     |    9 -
 .../BadInvalidName5.cmake                          |    7 -
 .../BadInvalidName5/CMakeLists.txt                 |    2 +
 .../BadInvalidName6-result.txt                     |    1 -
 .../BadInvalidName6-stderr.txt                     |    8 -
 .../BadInvalidName6.cmake                          |    7 -
 .../BadInvalidName6/CMakeLists.txt                 |    2 +
 .../BadInvalidName7-result.txt                     |    1 -
 .../BadInvalidName7-stderr.txt                     |    8 -
 .../BadInvalidName7.cmake                          |    9 -
 .../BadInvalidName7/CMakeLists.txt                 |    2 +
 .../BadInvalidName8-result.txt                     |    1 -
 .../BadInvalidName8-stderr.txt                     |    8 -
 .../BadInvalidName8.cmake                          |    7 -
 .../BadInvalidName8/CMakeLists.txt                 |    2 +
 .../BadSelfReference-result.txt}                   |    0
 .../BadSelfReference-stderr.txt                    |   37 +
 .../BadSelfReference.cmake                         |    6 +
 .../BadSelfReference1-result.txt                   |    1 -
 .../BadSelfReference1-stderr.txt                   |    6 -
 .../BadSelfReference1.cmake                        |    7 -
 .../BadSelfReference1/CMakeLists.txt               |    2 +
 .../BadSelfReference2-result.txt                   |    1 -
 .../BadSelfReference2-stderr.txt                   |    6 -
 .../BadSelfReference2.cmake                        |    9 -
 .../BadSelfReference2/CMakeLists.txt               |    2 +
 .../BadSelfReference3-result.txt                   |    1 -
 .../BadSelfReference3-stderr.txt                   |    6 -
 .../BadSelfReference3.cmake                        |    8 -
 .../BadSelfReference3/CMakeLists.txt               |    2 +
 .../BadSelfReference4-result.txt                   |    1 -
 .../BadSelfReference4-stderr.txt                   |    6 -
 .../BadSelfReference4.cmake                        |   10 -
 .../BadSelfReference4/CMakeLists.txt               |    2 +
 .../BadSelfReference5-result.txt                   |    1 -
 .../BadSelfReference5-stderr.txt                   |    6 -
 .../BadSelfReference5.cmake                        |   10 -
 .../BadSelfReference5/CMakeLists.txt               |    2 +
 .../BadSelfReference6-result.txt                   |    1 -
 .../BadSelfReference6-stderr.txt                   |    6 -
 .../BadSelfReference6.cmake                        |   10 -
 .../BadSelfReference6/CMakeLists.txt               |    2 +
 .../RunCMakeTest.cmake                             |   16 +-
 .../TargetPropertyGeneratorExpressions/main.cpp    |    0
 Utilities/Scripts/update-curl.bash                 |    2 +-
 Utilities/cmcurl/CMake/curl-config.cmake           |   59 +
 Utilities/cmcurl/CMakeLists.txt                    |   31 +-
 Utilities/cmcurl/COPYING                           |    2 +-
 Utilities/cmcurl/include/curl/curl.h               |   19 +-
 Utilities/cmcurl/include/curl/curlver.h            |    6 +-
 Utilities/cmcurl/include/curl/system.h             |    6 +-
 Utilities/cmcurl/lib/CMakeLists.txt                |   19 +-
 Utilities/cmcurl/lib/Makefile.inc                  |    9 +-
 Utilities/cmcurl/lib/asyn-ares.c                   |   26 +-
 Utilities/cmcurl/lib/asyn-thread.c                 |    3 +-
 Utilities/cmcurl/lib/conncache.c                   |  333 ++-
 Utilities/cmcurl/lib/conncache.h                   |   32 +-
 Utilities/cmcurl/lib/connect.c                     |  125 +-
 Utilities/cmcurl/lib/connect.h                     |    7 +-
 Utilities/cmcurl/lib/content_encoding.c            |  846 +++++-
 Utilities/cmcurl/lib/content_encoding.h            |   45 +-
 Utilities/cmcurl/lib/cookie.c                      |    2 +-
 Utilities/cmcurl/lib/curl_addrinfo.c               |    3 +
 Utilities/cmcurl/lib/curl_config.h.cmake           |    6 +-
 Utilities/cmcurl/lib/curl_fnmatch.c                |   36 +-
 Utilities/cmcurl/lib/curl_ntlm_core.c              |   25 +-
 Utilities/cmcurl/lib/curl_path.c                   |  195 ++
 .../cmcurl/lib/{vauth/digest.h => curl_path.h}     |   35 +-
 Utilities/cmcurl/lib/curl_setup.h                  |   15 +-
 .../cmcurl/lib/{vauth/digest.h => curl_sha256.h}   |   25 +-
 Utilities/cmcurl/lib/curlx.h                       |   12 +-
 Utilities/cmcurl/lib/easy.c                        |  122 +-
 Utilities/cmcurl/lib/file.c                        |    4 +-
 Utilities/cmcurl/lib/formdata.c                    |    2 +-
 Utilities/cmcurl/lib/ftp.c                         |   57 +-
 Utilities/cmcurl/lib/ftplistparser.c               |  175 +-
 Utilities/cmcurl/lib/hostasyn.c                    |   10 +-
 Utilities/cmcurl/lib/hostcheck.c                   |    3 +
 Utilities/cmcurl/lib/hostip.c                      |   25 +-
 Utilities/cmcurl/lib/hostip4.c                     |    9 +-
 Utilities/cmcurl/lib/hostip6.c                     |   10 +-
 Utilities/cmcurl/lib/hostsyn.c                     |   10 +-
 Utilities/cmcurl/lib/http.c                        |  127 +-
 Utilities/cmcurl/lib/http2.c                       |   13 +-
 Utilities/cmcurl/lib/http_chunks.c                 |   42 +-
 Utilities/cmcurl/lib/http_proxy.c                  |   14 +-
 Utilities/cmcurl/lib/imap.c                        |   62 +-
 Utilities/cmcurl/lib/krb5.c                        |    3 +-
 Utilities/cmcurl/lib/ldap.c                        |    4 +-
 Utilities/cmcurl/lib/llist.c                       |    6 +-
 Utilities/cmcurl/lib/memdebug.c                    |   36 +-
 Utilities/cmcurl/lib/memdebug.h                    |   15 +-
 Utilities/cmcurl/lib/mime.c                        |  183 +-
 Utilities/cmcurl/lib/mime.h                        |    5 +-
 Utilities/cmcurl/lib/multi.c                       |  202 +-
 Utilities/cmcurl/lib/multihandle.h                 |    4 -
 Utilities/cmcurl/lib/openldap.c                    |   32 +-
 Utilities/cmcurl/lib/parsedate.c                   |    2 -
 Utilities/cmcurl/lib/pingpong.c                    |   23 +-
 Utilities/cmcurl/lib/pingpong.h                    |    4 +-
 Utilities/cmcurl/lib/pop3.c                        |   37 +-
 Utilities/cmcurl/lib/progress.c                    |   48 +-
 Utilities/cmcurl/lib/rand.c                        |    8 +-
 Utilities/cmcurl/lib/security.c                    |    2 -
 Utilities/cmcurl/lib/select.c                      |   12 +-
 Utilities/cmcurl/lib/sendf.c                       |   44 +-
 Utilities/cmcurl/lib/setopt.c                      | 2556 +++++++++++++++++
 Utilities/cmcurl/lib/{vauth/digest.h => setopt.h}  |   28 +-
 Utilities/cmcurl/lib/sha256.c                      |  262 ++
 Utilities/cmcurl/lib/share.c                       |    6 +-
 Utilities/cmcurl/lib/share.h                       |    5 +-
 Utilities/cmcurl/lib/smb.c                         |   31 +-
 Utilities/cmcurl/lib/smb.h                         |   33 +-
 Utilities/cmcurl/lib/smtp.c                        |   45 +-
 Utilities/cmcurl/lib/socks.c                       |    4 +-
 Utilities/cmcurl/lib/speedcheck.c                  |    2 +-
 Utilities/cmcurl/lib/ssh-libssh.c                  | 2733 ++++++++++++++++++
 Utilities/cmcurl/lib/ssh.c                         |  218 +-
 Utilities/cmcurl/lib/ssh.h                         |   69 +-
 Utilities/cmcurl/lib/strtoofft.c                   |    5 +-
 Utilities/cmcurl/lib/strtoofft.h                   |   10 +-
 Utilities/cmcurl/lib/telnet.c                      |    8 +-
 Utilities/cmcurl/lib/tftp.c                        |    4 +-
 Utilities/cmcurl/lib/timeval.c                     |   98 +-
 Utilities/cmcurl/lib/timeval.h                     |   27 +-
 Utilities/cmcurl/lib/transfer.c                    |   64 +-
 Utilities/cmcurl/lib/url.c                         | 3029 +++-----------------
 Utilities/cmcurl/lib/url.h                         |   16 +-
 Utilities/cmcurl/lib/urldata.h                     |   73 +-
 Utilities/cmcurl/lib/vauth/digest.c                |  194 +-
 Utilities/cmcurl/lib/vauth/digest.h                |    6 +-
 Utilities/cmcurl/lib/vauth/ntlm.c                  |    3 +-
 Utilities/cmcurl/lib/version.c                     |   65 +-
 Utilities/cmcurl/lib/vtls/axtls.c                  |    2 +-
 Utilities/cmcurl/lib/vtls/cyassl.c                 |    4 +-
 Utilities/cmcurl/lib/vtls/darwinssl.c              |   96 +-
 Utilities/cmcurl/lib/vtls/gskit.c                  |    6 +-
 Utilities/cmcurl/lib/vtls/gtls.c                   |    2 +-
 Utilities/cmcurl/lib/vtls/mbedtls.c                |    2 +-
 Utilities/cmcurl/lib/vtls/nss.c                    |    2 +-
 Utilities/cmcurl/lib/vtls/openssl.c                |   88 +-
 Utilities/cmcurl/lib/vtls/polarssl.c               |    2 +-
 Utilities/cmcurl/lib/vtls/schannel.c               |    2 +-
 Utilities/cmcurl/lib/vtls/vtls.c                   |   25 +-
 Utilities/cmcurl/lib/vtls/vtls.h                   |    2 +-
 231 files changed, 9374 insertions(+), 4813 deletions(-)
 create mode 100644 Source/cmDuration.cxx
 create mode 100644 Source/cmDuration.h
 create mode 100644 Source/cmUVSignalHackRAII.h
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => TargetPropertyGeneratorExpressions/BadInvalidName-result.txt} (100%)
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName-stderr.txt
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName.cmake
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName1/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName2/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName3/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName4/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName5/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName6/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName7/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadInvalidName8/CMakeLists.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => TargetPropertyGeneratorExpressions/BadSelfReference-result.txt} (100%)
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference-stderr.txt
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference.cmake
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5/CMakeLists.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-result.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-stderr.txt
 delete mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6.cmake
 create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6/CMakeLists.txt
 copy Modules/DummyCXXFile.cxx => Tests/RunCMake/TargetPropertyGeneratorExpressions/main.cpp (100%)
 create mode 100644 Utilities/cmcurl/CMake/curl-config.cmake
 create mode 100644 Utilities/cmcurl/lib/curl_path.c
 copy Utilities/cmcurl/lib/{vauth/digest.h => curl_path.h} (62%)
 copy Utilities/cmcurl/lib/{vauth/digest.h => curl_sha256.h} (62%)
 create mode 100644 Utilities/cmcurl/lib/setopt.c
 copy Utilities/cmcurl/lib/{vauth/digest.h => setopt.h} (62%)
 create mode 100644 Utilities/cmcurl/lib/sha256.c
 create mode 100644 Utilities/cmcurl/lib/ssh-libssh.c


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list