From 449c158f801ff95fa8f722c916f0387b2ba39b0b Mon Sep 17 00:00:00 2001 From: lampysprites Date: Tue, 28 Sep 2021 14:44:38 +0700 Subject: [PATCH 01/32] Implement enabledness check for script commands --- src/app/script/plugin_class.cpp | 42 +++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/app/script/plugin_class.cpp b/src/app/script/plugin_class.cpp index 8d40ea2dc..18e85ea66 100644 --- a/src/app/script/plugin_class.cpp +++ b/src/app/script/plugin_class.cpp @@ -31,10 +31,13 @@ class PluginCommand : public Command { public: PluginCommand(const std::string& id, const std::string& title, - int onclickRef) + int onclickRef, + int onenabledRef) : Command(id.c_str(), CmdUIOnlyFlag) , m_title(title) - , m_onclickRef(onclickRef) { + , m_onclickRef(onclickRef) + , m_onenabledRef(onenabledRef) + { } ~PluginCommand() { @@ -69,8 +72,30 @@ protected: } } + bool onEnabled(Context* context) override { + if (m_onenabledRef) { + script::Engine* engine = App::instance()->scriptEngine(); + lua_State* L = engine->luaState(); + + lua_rawgeti(L, LUA_REGISTRYINDEX, m_onenabledRef); + if (lua_pcall(L, 0, 1, 0)) { + if (const char* s = lua_tostring(L, -1)) { + Console().printf("Error: %s", s); + return false; + } + } + else { + bool ret = lua_toboolean(L, -1); + lua_pop(L, 1); + return ret; + } + } + return true; + } + std::string m_title; int m_onclickRef; + int m_onenabledRef; }; void deleteCommandIfExistent(Extension* ext, const std::string& id) @@ -94,6 +119,7 @@ int Plugin_newCommand(lua_State* L) auto plugin = get_obj(L, 1); if (lua_istable(L, 2)) { std::string id, title, group; + int onenabledRef = 0; lua_getfield(L, 2, "id"); if (const char* s = lua_tostring(L, -1)) { @@ -115,8 +141,16 @@ int Plugin_newCommand(lua_State* L) group = s; } lua_pop(L, 1); + + int type = lua_getfield(L, 2, "onenabled"); + if (type == LUA_TFUNCTION) { + onenabledRef = luaL_ref(L, LUA_REGISTRYINDEX); // does a pop + } + else { + lua_pop(L, 1); + } - int type = lua_getfield(L, 2, "onclick"); + type = lua_getfield(L, 2, "onclick"); if (type == LUA_TFUNCTION) { int onclickRef = luaL_ref(L, LUA_REGISTRYINDEX); @@ -124,7 +158,7 @@ int Plugin_newCommand(lua_State* L) // overwriting a previous registered command) deleteCommandIfExistent(plugin->ext, id); - auto cmd = new PluginCommand(id, title, onclickRef); + auto cmd = new PluginCommand(id, title, onclickRef, onenabledRef); Commands::instance()->add(cmd); plugin->ext->addCommand(id); From 85f3164e21014a7697f29ddb91e32307f7c96cb6 Mon Sep 17 00:00:00 2001 From: lampysprites Date: Wed, 29 Sep 2021 22:39:01 +0700 Subject: [PATCH 02/32] Expose DocObserver to the scripts --- src/app/script/sprite_class.cpp | 72 +++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/app/script/sprite_class.cpp b/src/app/script/sprite_class.cpp index ee9c16390..4c7ec610a 100644 --- a/src/app/script/sprite_class.cpp +++ b/src/app/script/sprite_class.cpp @@ -27,11 +27,14 @@ #include "app/color_spaces.h" #include "app/commands/commands.h" #include "app/commands/params.h" +#include "app/console.h" #include "app/context.h" #include "app/doc.h" #include "app/doc_access.h" #include "app/doc_api.h" #include "app/doc_range.h" +#include "app/doc_undo.h" +#include "app/doc_undo_observer.h" #include "app/file/palette_file.h" #include "app/script/docobj.h" #include "app/script/engine.h" @@ -57,6 +60,43 @@ namespace script { namespace { +class ScriptDocObserver : public DocUndoObserver { +public: + ScriptDocObserver(int callbackRef) + : DocUndoObserver(), + m_callbackRef(callbackRef) + { } + + void onAddUndoState(DocUndo* history) { callback(); } + void onDeleteUndoState(DocUndo* history, undo::UndoState* state) { } + void onCurrentUndoStateChange(DocUndo* history) { callback(); } + void onClearRedo(DocUndo* history) { } + void onTotalUndoSizeChange(DocUndo* history) { } + +private: + void callback() { + script::Engine* engine = App::instance()->scriptEngine(); + lua_State* L = engine->luaState(); + + lua_rawgeti(L, LUA_REGISTRYINDEX, m_callbackRef); + if (lua_pcall(L, 0, 0, 0)) { + if (const char* s = lua_tostring(L, -1)) { + Console().printf("Error: %s", s); + } + } + } + + int m_callbackRef; +}; + +const luaL_Reg ScriptDocObserver_methods[] = { + { nullptr, nullptr } +}; + +const Property ScriptDocObserver_properties[] = { + { nullptr, nullptr, nullptr } +}; + int Sprite_new(lua_State* L) { std::unique_ptr doc; @@ -589,6 +629,32 @@ int Sprite_deleteSlice(lua_State* L) } } +int Sprite_watch(lua_State* L) +{ + auto sprite = get_docobj(L, 1); + auto doc = static_cast(sprite->document()); + ScriptDocObserver* obs; + + if (lua_isfunction(L, 2)) { + int callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); + obs = push_new(L, callbackRef); + doc->undoHistory()->add_observer(obs); + return 1; + } + return 0; +} + +int Sprite_unwatch(lua_State* L) +{ + if (auto obs = may_get_obj(L, 2)) { + auto sprite = get_docobj(L, 1); + auto doc = static_cast(sprite->document()); + + doc->undoHistory()->remove_observer(obs); + } + return 0; +} + int Sprite_get_filename(lua_State* L) { auto sprite = get_docobj(L, 1); @@ -821,6 +887,9 @@ const luaL_Reg Sprite_methods[] = { // Slices { "newSlice", Sprite_newSlice }, { "deleteSlice", Sprite_deleteSlice }, + // Observer + { "watch", Sprite_watch }, + { "unwatch", Sprite_unwatch }, { nullptr, nullptr } }; @@ -849,6 +918,7 @@ const Property Sprite_properties[] = { } // anonymous namespace DEF_MTNAME(doc::Sprite); +DEF_MTNAME(ScriptDocObserver); void register_sprite_class(lua_State* L) { @@ -856,6 +926,8 @@ void register_sprite_class(lua_State* L) REG_CLASS(L, Sprite); REG_CLASS_NEW(L, Sprite); REG_CLASS_PROPERTIES(L, Sprite); + + REG_CLASS(L, ScriptDocObserver); } } // namespace script From e6aeee64009e5c65b897e7e64d8e8b469e0634f8 Mon Sep 17 00:00:00 2001 From: lampysprites Date: Thu, 30 Sep 2021 13:13:43 +0700 Subject: [PATCH 03/32] Add IXWEbSocket library --- .gitmodules | 3 +++ src/app/CMakeLists.txt | 2 +- third_party/CMakeLists.txt | 4 ++++ third_party/IXWebSocket | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) create mode 160000 third_party/IXWebSocket diff --git a/.gitmodules b/.gitmodules index 780aaf1c3..3609f710a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -66,3 +66,6 @@ [submodule "src/tga"] path = src/tga url = https://github.com/aseprite/tga.git +[submodule "third_party/IXWebSocket"] + path = third_party/IXWebSocket + url = https://github.com/machinezone/IXWebSocket diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index ecda68224..64598f68e 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -673,7 +673,7 @@ if(REQUIRE_CURL) endif() if(ENABLE_SCRIPTING) - target_link_libraries(app-lib lua lauxlib lualib) + target_link_libraries(app-lib lua lauxlib lualib ixwebsocket) endif() if(ENABLE_UPDATER) diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index dad788916..4592f5518 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -159,4 +159,8 @@ if(ENABLE_SCRIPTING) target_include_directories(lauxlib PUBLIC lua) target_include_directories(lualib PUBLIC lua) target_link_libraries(lauxlib lua) + +# ixwebsocket +add_subdirectory(ixwebsocket) +target_include_directories(ixwebsocket PUBLIC) endif() diff --git a/third_party/IXWebSocket b/third_party/IXWebSocket new file mode 160000 index 000000000..9bbd1f1b3 --- /dev/null +++ b/third_party/IXWebSocket @@ -0,0 +1 @@ +Subproject commit 9bbd1f1b30bfa6fb52bf1388ab336ef39d0faead From 89904afa821738de19cf8f5b3287d96f0501a253 Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 30 Sep 2021 14:06:25 -0300 Subject: [PATCH 04/32] Simplify app::Job implementation * Remove pointers to base::thread/mutex * Use std::thread/mutex as values --- src/app/job.cpp | 25 ++++++++----------------- src/app/job.h | 11 ++++------- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/app/job.cpp b/src/app/job.cpp index d09014ff3..756d477b3 100644 --- a/src/app/job.cpp +++ b/src/app/job.cpp @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2021 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -12,10 +13,10 @@ #include "app/app.h" #include "app/console.h" +#include "app/context.h" #include "app/i18n/strings.h" #include "base/mutex.h" #include "base/scoped_lock.h" -#include "base/thread.h" #include "fmt/format.h" #include "ui/alert.h" #include "ui/widget.h" @@ -36,14 +37,10 @@ int Job::runningJobs() Job::Job(const char* jobName) { - m_mutex = NULL; - m_thread = NULL; m_last_progress = 0.0; m_done_flag = false; m_canceled_flag = false; - m_mutex = new base::mutex(); - if (App::instance()->isGui()) { m_alert_window = ui::Alert::create( fmt::format(Strings::alerts_job_working(), jobName)); @@ -59,19 +56,15 @@ Job::~Job() { if (App::instance()->isGui()) { ASSERT(!m_timer->isRunning()); - ASSERT(m_thread == NULL); if (m_alert_window) m_alert_window->closeWindow(NULL); } - - if (m_mutex) - delete m_mutex; } void Job::startJob() { - m_thread = new base::thread(&Job::thread_proc, this); + m_thread = std::thread(&Job::thread_proc, this); ++g_runningJobs; if (m_alert_window) { @@ -79,7 +72,7 @@ void Job::startJob() // The job was canceled by the user? { - base::scoped_lock hold(*m_mutex); + std::unique_lock hold(m_mutex); if (!m_done_flag) m_canceled_flag = true; } @@ -107,10 +100,8 @@ void Job::waitJob() if (m_timer && m_timer->isRunning()) m_timer->stop(); - if (m_thread) { - m_thread->join(); - delete m_thread; - m_thread = nullptr; + if (m_thread.joinable()) { + m_thread.join(); --g_runningJobs; } @@ -128,7 +119,7 @@ bool Job::isCanceled() void Job::onMonitoringTick() { - base::scoped_lock hold(*m_mutex); + std::unique_lock hold(m_mutex); // update progress m_alert_window->setProgress(m_last_progress); @@ -142,7 +133,7 @@ void Job::onMonitoringTick() void Job::done() { - base::scoped_lock hold(*m_mutex); + std::unique_lock hold(m_mutex); m_done_flag = true; } diff --git a/src/app/job.h b/src/app/job.h index e01d184a7..0adc9a169 100644 --- a/src/app/job.h +++ b/src/app/job.h @@ -14,11 +14,8 @@ #include #include - -namespace base { - class thread; - class mutex; -} +#include +#include namespace app { @@ -62,9 +59,9 @@ namespace app { static void monitor_proc(void* data); static void monitor_free(void* data); - base::thread* m_thread; + std::thread m_thread; std::unique_ptr m_timer; - base::mutex* m_mutex; + std::mutex m_mutex; ui::AlertPtr m_alert_window; std::atomic m_last_progress; bool m_done_flag; From 1e92f66ff25f971a489c69d7c6e80189781b8dae Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 30 Sep 2021 14:22:21 -0300 Subject: [PATCH 05/32] Remove trailing whitespace --- src/app/script/plugin_class.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/script/plugin_class.cpp b/src/app/script/plugin_class.cpp index 18e85ea66..857a94b42 100644 --- a/src/app/script/plugin_class.cpp +++ b/src/app/script/plugin_class.cpp @@ -141,7 +141,7 @@ int Plugin_newCommand(lua_State* L) group = s; } lua_pop(L, 1); - + int type = lua_getfield(L, 2, "onenabled"); if (type == LUA_TFUNCTION) { onenabledRef = luaL_ref(L, LUA_REGISTRYINDEX); // does a pop From b5d230d52f2c8240f747f03837bc6de29645f764 Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 30 Sep 2021 15:01:57 -0300 Subject: [PATCH 06/32] Increment Lua API version --- src/app/script/api_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/script/api_version.h b/src/app/script/api_version.h index a9b9cd620..52e90c167 100644 --- a/src/app/script/api_version.h +++ b/src/app/script/api_version.h @@ -10,6 +10,6 @@ // Increment this value if the scripting API is modified between two // released Aseprite versions. -#define API_VERSION 14 +#define API_VERSION 15 #endif From b0f10ee276403e3ab2966946b28009e9c716077d Mon Sep 17 00:00:00 2001 From: lampysprites Date: Thu, 30 Sep 2021 22:13:16 +0700 Subject: [PATCH 07/32] Add Websocket client API --- src/app/CMakeLists.txt | 1 + src/app/script/engine.cpp | 2 + src/app/script/websocket_class.cpp | 180 +++++++++++++++++++++++++++++ 3 files changed, 183 insertions(+) create mode 100644 src/app/script/websocket_class.cpp diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 64598f68e..de55dae70 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -189,6 +189,7 @@ if(ENABLE_SCRIPTING) script/tool_class.cpp script/values.cpp script/version_class.cpp + script/websocket_class.cpp shell.cpp ${scripting_files_ui}) endif() diff --git a/src/app/script/engine.cpp b/src/app/script/engine.cpp index ce1cfc655..5417bb435 100644 --- a/src/app/script/engine.cpp +++ b/src/app/script/engine.cpp @@ -180,6 +180,7 @@ void register_tag_class(lua_State* L); void register_tags_class(lua_State* L); void register_tool_class(lua_State* L); void register_version_class(lua_State* L); +void register_websocket_class(lua_State* L); void set_app_params(lua_State* L, const Params& params); @@ -411,6 +412,7 @@ Engine::Engine() register_tags_class(L); register_tool_class(L); register_version_class(L); + register_websocket_class(L); // Check that we have a clean start (without dirty in the stack) ASSERT(lua_gettop(L) == top); diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp new file mode 100644 index 000000000..118970c5a --- /dev/null +++ b/src/app/script/websocket_class.cpp @@ -0,0 +1,180 @@ +// Aseprite +// Copyright (C) 2018-2020 Igara Studio S.A. +// Copyright (C) 2018 David Capello +// +// This program is distributed under the terms of +// the End-User License Agreement for Aseprite. + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "app/app.h" +#include "app/console.h" +#include "app/script/docobj.h" +#include "app/script/engine.h" +#include "app/script/luacpp.h" + +#include +#include +#include + +namespace app { +namespace script { + +namespace { +// additional "enum" value to make message callback simpler +#define MESSAGE_TYPE_BINARY (int)ix::WebSocketMessageType::Fragment + 10 + +int WebSocket_new(lua_State* L) +{ + static std::once_flag f; + std::call_once(f, &ix::initNetSystem); + + auto ws = new ix::WebSocket(); + + push_ptr(L, ws); + + if (lua_istable(L, 1)) { + lua_getfield(L, 1, "url"); + if (const char* s = lua_tostring(L, -1)) { + ws->setUrl(s); + } + lua_pop(L, 1); + + int type = lua_getfield(L, 1, "onreceive"); + if (type == LUA_TFUNCTION) { + int onreceiveRef = luaL_ref(L, LUA_REGISTRYINDEX); + + ws->setOnMessageCallback([L, ws, onreceiveRef](const ix::WebSocketMessagePtr& msg) { + lua_rawgeti(L, LUA_REGISTRYINDEX, onreceiveRef); + lua_pushnumber(L, (msg->binary ? MESSAGE_TYPE_BINARY : static_cast(msg->type))); + lua_pushlstring(L, msg->str.c_str(), msg->str.length()); + + if (lua_pcall(L, 2, 0, 0)) { + if (const char* s = lua_tostring(L, -1)) { + App::instance()->scriptEngine()->consolePrint(s); + ws->disableAutomaticReconnection(); + ws->close(); + } + } + }); + } + else { + lua_pop(L, 1); + } + } + + return 1; +} + +int WebSocket_gc(lua_State* L) +{ + auto ws = get_ptr(L, 1); + ws->stop(); + delete ws; + return 0; +} + +int WebSocket_sendText(lua_State* L) +{ + auto ws = get_ptr(L, 1); + std::stringstream data; + int argc = lua_gettop(L); + + for (int i = 2; i <= argc; i++) { + size_t bufLen; + const char* buf = lua_tolstring(L, i, &bufLen); + data.write(buf, bufLen); + } + lua_pop(L, argc); + + ws->sendText(data.str()); + return 0; +} + +int WebSocket_sendBinary(lua_State* L) +{ + auto ws = get_ptr(L, 1); + std::stringstream data; + int argc = lua_gettop(L); + + for (int i = 2; i <= argc; i++) { + size_t bufLen; + const char* buf = lua_tolstring(L, i, &bufLen); + data.write(buf, bufLen); + } + lua_pop(L, argc); + + ws->sendBinary(data.str()); + return 0; +} + +int WebSocket_connect(lua_State* L) +{ + auto ws = get_ptr(L, 1); + lua_pop(L, 1); + ws->enableAutomaticReconnection(); + ws->start(); + return 0; +} + +int WebSocket_close(lua_State* L) +{ + auto ws = get_ptr(L, 1); + lua_pop(L, 1); + ws->disableAutomaticReconnection(); + ws->close(); + return 0; +} + +int WebSocket_get_url(lua_State* L) +{ + auto ws = get_ptr(L, 1); + lua_pop(L, 1); + lua_pushstring(L, ws->getUrl().c_str()); + return 1; +} + +const luaL_Reg WebSocket_methods[] = { + { "__gc", WebSocket_gc }, + { "close", WebSocket_close }, + { "connect", WebSocket_connect }, + { "sendText", WebSocket_sendText }, + { "sendBinary", WebSocket_sendBinary }, + { nullptr, nullptr } +}; + +const Property WebSocket_properties[] = { + { "url", WebSocket_get_url, nullptr }, + { nullptr, nullptr, nullptr } +}; + +} // namespace { } + +using WebSocket = ix::WebSocket; +DEF_MTNAME(WebSocket); + +void register_websocket_class(lua_State* L) +{ + REG_CLASS(L, WebSocket); + REG_CLASS_NEW(L, WebSocket); + REG_CLASS_PROPERTIES(L, WebSocket); + + // message type enum + lua_newtable(L); + lua_pushvalue(L, -1); + lua_setglobal(L, "MessageType"); + setfield_integer(L, "Text", (int)ix::WebSocketMessageType::Message); + setfield_integer(L, "Binary", MESSAGE_TYPE_BINARY); + setfield_integer(L, "Open", (int)ix::WebSocketMessageType::Open); + setfield_integer(L, "Close", (int)ix::WebSocketMessageType::Close); + setfield_integer(L, "Error", (int)ix::WebSocketMessageType::Error); + setfield_integer(L, "Ping", (int)ix::WebSocketMessageType::Ping); + setfield_integer(L, "Pong", (int)ix::WebSocketMessageType::Pong); + setfield_integer(L, "Fragment", (int)ix::WebSocketMessageType::Fragment); + lua_pop(L, 1); +} + +} // namespace script +} // namespace app \ No newline at end of file From f8ef06a86ebf6b0ae731086c81b2ab9ae4439995 Mon Sep 17 00:00:00 2001 From: lampysprites Date: Sat, 2 Oct 2021 14:05:13 +0700 Subject: [PATCH 08/32] Lua API Image:bytes - convert lua Image to data string and back --- src/app/script/image_class.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/app/script/image_class.cpp b/src/app/script/image_class.cpp index a8ca8e416..8bdf4e4e9 100644 --- a/src/app/script/image_class.cpp +++ b/src/app/script/image_class.cpp @@ -483,6 +483,30 @@ int Image_resize(lua_State* L) return 0; } +int Image_get_bytes(lua_State* L) +{ + const auto img = get_obj(L, 1)->image(L); + lua_pushlstring(L, (const char*)img->getPixelAddress(0, 0), img->getRowStrideSize() * img->height()); + return 1; +} + +int Image_set_bytes(lua_State* L) +{ + const auto img = get_obj(L, 1)->image(L); + size_t bytes_size, bytes_needed = img->getRowStrideSize() * img->height(); + const char* bytes = lua_tolstring(L, 2, &bytes_size); + + if (bytes_size == bytes_needed) { + memcpy_s(img->getPixelAddress(0, 0), bytes_needed, bytes, bytes_size); + } + else { + lua_pushfstring(L, "Data size does not match: given %d, needed %d.", bytes_size, bytes_needed); + lua_error(L); + } + + return 0; +} + int Image_get_width(lua_State* L) { const auto obj = get_obj(L, 1); @@ -537,6 +561,7 @@ const luaL_Reg Image_methods[] = { }; const Property Image_properties[] = { + { "bytes", Image_get_bytes, Image_set_bytes }, { "width", Image_get_width, nullptr }, { "height", Image_get_height, nullptr }, { "colorMode", Image_get_colorMode, nullptr }, From 22e3e6244a83dbc2ba8bf74cee1e700c176a46a3 Mon Sep 17 00:00:00 2001 From: lampysprites Date: Sat, 2 Oct 2021 16:22:31 +0700 Subject: [PATCH 09/32] Simplify user API for Sprite observers --- src/app/script/sprite_class.cpp | 69 ++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/src/app/script/sprite_class.cpp b/src/app/script/sprite_class.cpp index 4c7ec610a..373664fcd 100644 --- a/src/app/script/sprite_class.cpp +++ b/src/app/script/sprite_class.cpp @@ -59,7 +59,7 @@ namespace app { namespace script { namespace { - +// in lua, observers become `Sprite.onChange` class ScriptDocObserver : public DocUndoObserver { public: ScriptDocObserver(int callbackRef) @@ -73,6 +73,9 @@ public: void onClearRedo(DocUndo* history) { } void onTotalUndoSizeChange(DocUndo* history) { } + int callbackRef() { return m_callbackRef; } + void setCallbackRef(int callbackRef) { m_callbackRef = callbackRef; } + private: void callback() { script::Engine* engine = App::instance()->scriptEngine(); @@ -89,13 +92,8 @@ private: int m_callbackRef; }; -const luaL_Reg ScriptDocObserver_methods[] = { - { nullptr, nullptr } -}; - -const Property ScriptDocObserver_properties[] = { - { nullptr, nullptr, nullptr } -}; +// used to maintain one-to-one relation between sprites and observers +std::map script_observers; int Sprite_new(lua_State* L) { @@ -629,28 +627,42 @@ int Sprite_deleteSlice(lua_State* L) } } -int Sprite_watch(lua_State* L) +int Sprite_get_onChange(lua_State* L) +{ + auto sprite = get_docobj(L, 1); + ScriptDocObserver* obs = script_observers[sprite->id()]; + + if (obs) { + lua_rawgeti(L, LUA_REGISTRYINDEX, obs->callbackRef()); + } + else { + lua_pushnil(L); + } + return 1; +} + +int Sprite_set_onChange(lua_State* L) { auto sprite = get_docobj(L, 1); auto doc = static_cast(sprite->document()); - ScriptDocObserver* obs; - - if (lua_isfunction(L, 2)) { - int callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); - obs = push_new(L, callbackRef); - doc->undoHistory()->add_observer(obs); - return 1; - } - return 0; -} - -int Sprite_unwatch(lua_State* L) -{ - if (auto obs = may_get_obj(L, 2)) { - auto sprite = get_docobj(L, 1); - auto doc = static_cast(sprite->document()); + ScriptDocObserver* obs = script_observers[sprite->id()]; + if (lua_isnil(L, 2) && obs) { doc->undoHistory()->remove_observer(obs); + script_observers.erase(sprite->id()); + luaL_unref(L, LUA_REGISTRYINDEX, obs->callbackRef()); + delete obs; + } + else if (lua_isfunction(L, 2)) { + int callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (obs) { + obs->setCallbackRef(callbackRef); + } + else { + obs = new ScriptDocObserver(callbackRef); + doc->undoHistory()->add_observer(obs); + script_observers[sprite->id()] = obs; + } } return 0; } @@ -887,9 +899,6 @@ const luaL_Reg Sprite_methods[] = { // Slices { "newSlice", Sprite_newSlice }, { "deleteSlice", Sprite_deleteSlice }, - // Observer - { "watch", Sprite_watch }, - { "unwatch", Sprite_unwatch }, { nullptr, nullptr } }; @@ -912,13 +921,13 @@ const Property Sprite_properties[] = { { "bounds", Sprite_get_bounds, nullptr }, { "gridBounds", Sprite_get_gridBounds, Sprite_set_gridBounds }, { "pixelRatio", Sprite_get_pixelRatio, Sprite_set_pixelRatio }, + { "onChange", Sprite_get_onChange, Sprite_set_onChange }, { nullptr, nullptr, nullptr } }; } // anonymous namespace DEF_MTNAME(doc::Sprite); -DEF_MTNAME(ScriptDocObserver); void register_sprite_class(lua_State* L) { @@ -926,8 +935,6 @@ void register_sprite_class(lua_State* L) REG_CLASS(L, Sprite); REG_CLASS_NEW(L, Sprite); REG_CLASS_PROPERTIES(L, Sprite); - - REG_CLASS(L, ScriptDocObserver); } } // namespace script From 2aa3fdbd9530b28d2cf92c69a3fe6c76cd704ec7 Mon Sep 17 00:00:00 2001 From: lampysprites Date: Sat, 2 Oct 2021 18:34:17 +0700 Subject: [PATCH 10/32] Execute websocket callbacks in the ui thread --- src/app/script/websocket_class.cpp | 36 +++++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index 118970c5a..1869fd40b 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -11,9 +11,9 @@ #include "app/app.h" #include "app/console.h" -#include "app/script/docobj.h" #include "app/script/engine.h" #include "app/script/luacpp.h" +#include "ui/system.h" #include #include @@ -46,19 +46,25 @@ int WebSocket_new(lua_State* L) if (type == LUA_TFUNCTION) { int onreceiveRef = luaL_ref(L, LUA_REGISTRYINDEX); - ws->setOnMessageCallback([L, ws, onreceiveRef](const ix::WebSocketMessagePtr& msg) { - lua_rawgeti(L, LUA_REGISTRYINDEX, onreceiveRef); - lua_pushnumber(L, (msg->binary ? MESSAGE_TYPE_BINARY : static_cast(msg->type))); - lua_pushlstring(L, msg->str.c_str(), msg->str.length()); + ws->setOnMessageCallback( + [L, ws, onreceiveRef](const ix::WebSocketMessagePtr& msg) { + int msgType = + (msg->binary ? MESSAGE_TYPE_BINARY : static_cast(msg->type)); + std::string msgData = msg->str; - if (lua_pcall(L, 2, 0, 0)) { - if (const char* s = lua_tostring(L, -1)) { - App::instance()->scriptEngine()->consolePrint(s); - ws->disableAutomaticReconnection(); - ws->close(); - } - } - }); + ui::execute_from_ui_thread([=]() { + lua_rawgeti(L, LUA_REGISTRYINDEX, onreceiveRef); + lua_pushinteger(L, msgType); + lua_pushlstring(L, msgData.c_str(), msgData.length()); + + if (lua_pcall(L, 2, 0, 0)) { + if (const char* s = lua_tostring(L, -1)) { + App::instance()->scriptEngine()->consolePrint(s); + ws->stop(); + } + } + }); + }); } else { lua_pop(L, 1); @@ -114,7 +120,6 @@ int WebSocket_connect(lua_State* L) { auto ws = get_ptr(L, 1); lua_pop(L, 1); - ws->enableAutomaticReconnection(); ws->start(); return 0; } @@ -123,8 +128,7 @@ int WebSocket_close(lua_State* L) { auto ws = get_ptr(L, 1); lua_pop(L, 1); - ws->disableAutomaticReconnection(); - ws->close(); + ws->stop(); return 0; } From 83c03a31584a475077be4c8f97911dc03e8bb843 Mon Sep 17 00:00:00 2001 From: lampysprites Date: Sat, 2 Oct 2021 20:09:35 +0700 Subject: [PATCH 11/32] Expose site observer to lua API --- src/app/script/site_class.cpp | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/app/script/site_class.cpp b/src/app/script/site_class.cpp index 985d3c990..4a73fe7bc 100644 --- a/src/app/script/site_class.cpp +++ b/src/app/script/site_class.cpp @@ -9,6 +9,10 @@ #include "config.h" #endif +#include "app/app.h" +#include "app/console.h" +#include "app/context.h" +#include "app/context_observer.h" #include "app/script/docobj.h" #include "app/script/engine.h" #include "app/script/luacpp.h" @@ -22,6 +26,47 @@ namespace script { namespace { +class ScriptSiteObserver : public ContextObserver { +public: + static ScriptSiteObserver* instance() { + static ScriptSiteObserver instance; + return &instance; + } + + void onActiveSiteChange(const Site& site) { + if (m_onchangeRef == 0) + return; + + script::Engine* engine = App::instance()->scriptEngine(); + lua_State* L = engine->luaState(); + + lua_rawgeti(L, LUA_REGISTRYINDEX, m_onchangeRef); + if (lua_pcall(L, 0, 0, 0)) { + if (const char* s = lua_tostring(L, -1)) { + Console().printf("Error: %s", s); + } + } + } + + int callbackRef() { + return m_onchangeRef; + } + + void setCallbackRef(int onchangeRef) { + m_onchangeRef = onchangeRef; + } + +private: + ScriptSiteObserver() + : ContextObserver(), + m_onchangeRef(0) + { } + + ~ScriptSiteObserver() { } + + int m_onchangeRef; +}; + int Site_get_sprite(lua_State* L) { auto site = get_obj(L, 1); @@ -79,6 +124,33 @@ int Site_get_image(lua_State* L) return 1; } +int Site_get_onChange(lua_State* L) +{ + lua_rawgeti(L, LUA_REGISTRYINDEX, ScriptSiteObserver::instance()->callbackRef()); + return 1; +} + +int Site_set_onChange(lua_State* L) +{ + auto site = get_obj(L, 1); + auto obs = ScriptSiteObserver::instance(); + + if (lua_isnil(L, 2) && obs->callbackRef()) { + luaL_unref(L, LUA_REGISTRYINDEX, obs->callbackRef()); + obs->setCallbackRef(0); + App::instance()->context()->remove_observer(obs); + } + else if (lua_isfunction(L, 2)) { + int onchangeRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (!obs->callbackRef()) { + App::instance()->context()->add_observer(obs); + } + obs->setCallbackRef(onchangeRef); + } + + return 0; +} + const luaL_Reg Site_methods[] = { { nullptr, nullptr } }; @@ -90,6 +162,7 @@ const Property Site_properties[] = { { "frame", Site_get_frame, nullptr }, { "frameNumber", Site_get_frameNumber, nullptr }, { "image", Site_get_image, nullptr }, + { "onChange", Site_get_onChange, Site_set_onChange }, { nullptr, nullptr, nullptr } }; From 28595a410d20bfc83a739562cafafd63af14f095 Mon Sep 17 00:00:00 2001 From: lampysprites Date: Sat, 2 Oct 2021 22:10:25 +0700 Subject: [PATCH 12/32] Clean up sprite observers on lua GC --- src/app/script/sprite_class.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/app/script/sprite_class.cpp b/src/app/script/sprite_class.cpp index 373664fcd..ad54e89ba 100644 --- a/src/app/script/sprite_class.cpp +++ b/src/app/script/sprite_class.cpp @@ -172,6 +172,18 @@ int Sprite_new(lua_State* L) return 1; } +int Sprite_gc(lua_State* L) +{ + auto sprite = get_docobj(L, 1); + auto doc = static_cast(sprite->document()); + + if (ScriptDocObserver* obs = script_observers[sprite->id()]) { + doc->undoHistory()->remove_observer(obs); + script_observers.erase(sprite->id()); + } + return 0; +} + int Sprite_eq(lua_State* L) { const auto a = get_docobj(L, 1); @@ -871,6 +883,7 @@ int Sprite_set_pixelRatio(lua_State* L) } const luaL_Reg Sprite_methods[] = { + { "__gc", Sprite_gc }, { "__eq", Sprite_eq }, { "resize", Sprite_resize }, { "crop", Sprite_crop }, From 711741a35880bbf6ba7ff066a2d9cf2cbcbce4b0 Mon Sep 17 00:00:00 2001 From: lampysprites Date: Sun, 3 Oct 2021 02:22:15 +0700 Subject: [PATCH 13/32] Remove unneeded lua stack pops --- src/app/script/websocket_class.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index 1869fd40b..c7743916c 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -93,7 +93,6 @@ int WebSocket_sendText(lua_State* L) const char* buf = lua_tolstring(L, i, &bufLen); data.write(buf, bufLen); } - lua_pop(L, argc); ws->sendText(data.str()); return 0; @@ -110,7 +109,6 @@ int WebSocket_sendBinary(lua_State* L) const char* buf = lua_tolstring(L, i, &bufLen); data.write(buf, bufLen); } - lua_pop(L, argc); ws->sendBinary(data.str()); return 0; @@ -119,7 +117,6 @@ int WebSocket_sendBinary(lua_State* L) int WebSocket_connect(lua_State* L) { auto ws = get_ptr(L, 1); - lua_pop(L, 1); ws->start(); return 0; } @@ -127,7 +124,6 @@ int WebSocket_connect(lua_State* L) int WebSocket_close(lua_State* L) { auto ws = get_ptr(L, 1); - lua_pop(L, 1); ws->stop(); return 0; } @@ -135,7 +131,6 @@ int WebSocket_close(lua_State* L) int WebSocket_get_url(lua_State* L) { auto ws = get_ptr(L, 1); - lua_pop(L, 1); lua_pushstring(L, ws->getUrl().c_str()); return 1; } From 4354be1d7a3f1c3edc9807a745cc7316a9070a9e Mon Sep 17 00:00:00 2001 From: lampysprites Date: Sun, 3 Oct 2021 12:40:29 +0700 Subject: [PATCH 14/32] Add CMake option to disable websockets --- CMakeLists.txt | 1 + src/CMakeLists.txt | 5 +++++ src/app/CMakeLists.txt | 12 ++++++++++-- src/app/script/engine.cpp | 2 ++ third_party/CMakeLists.txt | 9 ++++++--- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3af0bd074..5ce626045 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ option(ENABLE_MEMLEAK "Enable memory-leaks detector (only for developers)" option(ENABLE_NEWS "Enable the news in Home tab" on) option(ENABLE_UPDATER "Enable automatic check for updates" on) option(ENABLE_SCRIPTING "Compile with scripting support" on) +option(ENABLE_WEBSOCKET "Compile with websocket support" on) option(ENABLE_TESTS "Compile unit tests" off) option(ENABLE_BENCHMARKS "Compile benchmarks" off) option(ENABLE_TRIAL_MODE "Compile the trial version" off) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dfc2fefbd..cb25aeac6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -74,6 +74,11 @@ if(ENABLE_SCRIPTING) add_definitions(-DENABLE_SCRIPTING) endif() +if(ENABLE_WEBSOCKET) + # Needed for "app" and "main" + add_definitions(-DENABLE_WEBSOCKET) +endif() + ###################################################################### # Aseprite Libraries (in preferred order to be built) diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index de55dae70..9f2e07549 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -147,6 +147,10 @@ if(ENABLE_SCRIPTING) commands/cmd_open_script_folder.cpp ui/devconsole_view.cpp) endif() + if(ENABLE_WEBSOCKET) + set(scripting_files_ws + script/websocket_class.cpp) + endif() set(scripting_files commands/cmd_run_script.cpp script/app_command_object.cpp @@ -189,8 +193,8 @@ if(ENABLE_SCRIPTING) script/tool_class.cpp script/values.cpp script/version_class.cpp - script/websocket_class.cpp shell.cpp + ${scripting_files_ws} ${scripting_files_ui}) endif() @@ -674,7 +678,11 @@ if(REQUIRE_CURL) endif() if(ENABLE_SCRIPTING) - target_link_libraries(app-lib lua lauxlib lualib ixwebsocket) + target_link_libraries(app-lib lua lauxlib lualib) + + if(ENABLE_WEBSOCKET) + target_link_libraries(app-lib ixwebsocket) + endif() endif() if(ENABLE_UPDATER) diff --git a/src/app/script/engine.cpp b/src/app/script/engine.cpp index 5417bb435..cf6c7f7b5 100644 --- a/src/app/script/engine.cpp +++ b/src/app/script/engine.cpp @@ -412,7 +412,9 @@ Engine::Engine() register_tags_class(L); register_tool_class(L); register_version_class(L); +#if ENABLE_WEBSOCKET register_websocket_class(L); + #endif // Check that we have a clean start (without dirty in the stack) ASSERT(lua_gettop(L) == top); diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 4592f5518..8e5428f1c 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -160,7 +160,10 @@ if(ENABLE_SCRIPTING) target_include_directories(lualib PUBLIC lua) target_link_libraries(lauxlib lua) -# ixwebsocket -add_subdirectory(ixwebsocket) -target_include_directories(ixwebsocket PUBLIC) + # ixwebsocket + if(ENABLE_WEBSOCKET) + add_subdirectory(IXWebSocket) + target_include_directories(ixwebsocket PUBLIC) + endif() + endif() From a90853f7653287894287f23402e5f445780457ba Mon Sep 17 00:00:00 2001 From: lampysprites Date: Sun, 3 Oct 2021 12:52:26 +0700 Subject: [PATCH 15/32] Extend WebSocket API --- src/app/script/websocket_class.cpp | 34 ++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index c7743916c..e743ffd5e 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -42,6 +42,15 @@ int WebSocket_new(lua_State* L) } lua_pop(L, 1); + lua_getfield(L, 1, "deflate"); + if (lua_toboolean(L, -1)) { + ws->enablePerMessageDeflate(); + } + else { + ws->disablePerMessageDeflate(); + } + lua_pop(L, 1); + int type = lua_getfield(L, 1, "onreceive"); if (type == LUA_TFUNCTION) { int onreceiveRef = luaL_ref(L, LUA_REGISTRYINDEX); @@ -94,7 +103,10 @@ int WebSocket_sendText(lua_State* L) data.write(buf, bufLen); } - ws->sendText(data.str()); + if (!ws->sendText(data.str()).success) { + lua_pushstring(L, "Websocket error"); + lua_error(L); + } return 0; } @@ -110,7 +122,24 @@ int WebSocket_sendBinary(lua_State* L) data.write(buf, bufLen); } - ws->sendBinary(data.str()); + if (!ws->sendBinary(data.str()).success) { + lua_pushstring(L, "Websocket error"); + lua_error(L); + } + return 0; +} + +int WebSocket_sendPing(lua_State* L) +{ + auto ws = get_ptr(L, 1); + size_t bufLen; + const char* buf = lua_tolstring(L, 2, &bufLen); + std::string data(buf, bufLen); + + if (!ws->ping(data).success) { + lua_pushstring(L, "Websocket error"); + lua_error(L); + } return 0; } @@ -141,6 +170,7 @@ const luaL_Reg WebSocket_methods[] = { { "connect", WebSocket_connect }, { "sendText", WebSocket_sendText }, { "sendBinary", WebSocket_sendBinary }, + { "sendPing", WebSocket_sendPing }, { nullptr, nullptr } }; From bf53fa26cd9891d6915e9f3dcceace127e0b74fe Mon Sep 17 00:00:00 2001 From: lampysprites Date: Mon, 4 Oct 2021 12:17:25 +0700 Subject: [PATCH 16/32] Make onChange callbacks more predictable --- src/app/script/site_class.cpp | 12 ++++++------ src/app/script/sprite_class.cpp | 20 ++++++++------------ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/app/script/site_class.cpp b/src/app/script/site_class.cpp index 4a73fe7bc..bed17f91f 100644 --- a/src/app/script/site_class.cpp +++ b/src/app/script/site_class.cpp @@ -135,18 +135,18 @@ int Site_set_onChange(lua_State* L) auto site = get_obj(L, 1); auto obs = ScriptSiteObserver::instance(); - if (lua_isnil(L, 2) && obs->callbackRef()) { - luaL_unref(L, LUA_REGISTRYINDEX, obs->callbackRef()); - obs->setCallbackRef(0); - App::instance()->context()->remove_observer(obs); - } - else if (lua_isfunction(L, 2)) { + if (lua_isfunction(L, 2)) { int onchangeRef = luaL_ref(L, LUA_REGISTRYINDEX); if (!obs->callbackRef()) { App::instance()->context()->add_observer(obs); } obs->setCallbackRef(onchangeRef); } + else if (obs->callbackRef()) { + luaL_unref(L, LUA_REGISTRYINDEX, obs->callbackRef()); + obs->setCallbackRef(0); + App::instance()->context()->remove_observer(obs); + } return 0; } diff --git a/src/app/script/sprite_class.cpp b/src/app/script/sprite_class.cpp index ad54e89ba..4c7a46bd6 100644 --- a/src/app/script/sprite_class.cpp +++ b/src/app/script/sprite_class.cpp @@ -176,11 +176,6 @@ int Sprite_gc(lua_State* L) { auto sprite = get_docobj(L, 1); auto doc = static_cast(sprite->document()); - - if (ScriptDocObserver* obs = script_observers[sprite->id()]) { - doc->undoHistory()->remove_observer(obs); - script_observers.erase(sprite->id()); - } return 0; } @@ -659,13 +654,7 @@ int Sprite_set_onChange(lua_State* L) auto doc = static_cast(sprite->document()); ScriptDocObserver* obs = script_observers[sprite->id()]; - if (lua_isnil(L, 2) && obs) { - doc->undoHistory()->remove_observer(obs); - script_observers.erase(sprite->id()); - luaL_unref(L, LUA_REGISTRYINDEX, obs->callbackRef()); - delete obs; - } - else if (lua_isfunction(L, 2)) { + if (lua_isfunction(L, 2)) { int callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); if (obs) { obs->setCallbackRef(callbackRef); @@ -676,6 +665,13 @@ int Sprite_set_onChange(lua_State* L) script_observers[sprite->id()] = obs; } } + else if (obs) { + doc->undoHistory()->remove_observer(obs); + script_observers.erase(sprite->id()); + luaL_unref(L, LUA_REGISTRYINDEX, obs->callbackRef()); + delete obs; + } + return 0; } From 2628afdfceb50e052d3e1be347a62269c01cdf60 Mon Sep 17 00:00:00 2001 From: lampysprites Date: Mon, 4 Oct 2021 23:15:55 +0700 Subject: [PATCH 17/32] Remove unneeded Sprite.__gc --- src/app/script/sprite_class.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/app/script/sprite_class.cpp b/src/app/script/sprite_class.cpp index 4c7a46bd6..cfcdbdd5f 100644 --- a/src/app/script/sprite_class.cpp +++ b/src/app/script/sprite_class.cpp @@ -172,13 +172,6 @@ int Sprite_new(lua_State* L) return 1; } -int Sprite_gc(lua_State* L) -{ - auto sprite = get_docobj(L, 1); - auto doc = static_cast(sprite->document()); - return 0; -} - int Sprite_eq(lua_State* L) { const auto a = get_docobj(L, 1); @@ -879,7 +872,6 @@ int Sprite_set_pixelRatio(lua_State* L) } const luaL_Reg Sprite_methods[] = { - { "__gc", Sprite_gc }, { "__eq", Sprite_eq }, { "resize", Sprite_resize }, { "crop", Sprite_crop }, From f8dabfa294b147afbb245588f964ce94d12ea7cd Mon Sep 17 00:00:00 2001 From: David Capello Date: Mon, 4 Oct 2021 18:06:40 -0300 Subject: [PATCH 18/32] Use portable memcpy instead of memcpy_s --- src/app/script/image_class.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/script/image_class.cpp b/src/app/script/image_class.cpp index 8bdf4e4e9..cd694194a 100644 --- a/src/app/script/image_class.cpp +++ b/src/app/script/image_class.cpp @@ -33,6 +33,7 @@ #include "render/render.h" #include +#include #include namespace app { @@ -497,7 +498,7 @@ int Image_set_bytes(lua_State* L) const char* bytes = lua_tolstring(L, 2, &bytes_size); if (bytes_size == bytes_needed) { - memcpy_s(img->getPixelAddress(0, 0), bytes_needed, bytes, bytes_size); + std::memcpy(img->getPixelAddress(0, 0), bytes, std::min(bytes_needed, bytes_size)); } else { lua_pushfstring(L, "Data size does not match: given %d, needed %d.", bytes_size, bytes_needed); From b6d7c1e2614fa81717e2246743634dd4187388ce Mon Sep 17 00:00:00 2001 From: David Capello Date: Mon, 4 Oct 2021 18:07:28 -0300 Subject: [PATCH 19/32] Avoid error running cmake when entering IXWebSocket subdirectory I don't know why it fails, but it looks like the commands specified to install the IXWebSocket library are problematic. (And anyway we don't want to install the library after the compilation process.) --- third_party/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 8e5428f1c..e4457eb24 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -162,6 +162,7 @@ if(ENABLE_SCRIPTING) # ixwebsocket if(ENABLE_WEBSOCKET) + set(IXWEBSOCKET_INSTALL OFF CACHE BOOL "Install IXWebSocket") add_subdirectory(IXWebSocket) target_include_directories(ixwebsocket PUBLIC) endif() From e0a747cad778b7f19602523965a212186dc5de72 Mon Sep 17 00:00:00 2001 From: Jeremy Behreandt Date: Wed, 6 Oct 2021 14:04:54 -0500 Subject: [PATCH 20/32] Expose Layer Is Reference Exposes a getter for layer is reference in the Lua scripting API. --- src/app/script/layer_class.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/app/script/layer_class.cpp b/src/app/script/layer_class.cpp index 8a4bb06d9..5e60fc328 100644 --- a/src/app/script/layer_class.cpp +++ b/src/app/script/layer_class.cpp @@ -201,6 +201,13 @@ int Layer_get_isExpanded(lua_State* L) return 1; } +int Layer_get_isReference(lua_State* L) +{ + auto layer = get_docobj(L, 1); + lua_pushboolean(L, layer->isReference()); + return 1; +} + int Layer_get_cels(lua_State* L) { auto layer = get_docobj(L, 1); @@ -377,6 +384,7 @@ const Property Layer_properties[] = { { "isContinuous", Layer_get_isContinuous, Layer_set_isContinuous }, { "isCollapsed", Layer_get_isCollapsed, Layer_set_isCollapsed }, { "isExpanded", Layer_get_isExpanded, Layer_set_isExpanded }, + { "isReference", Layer_get_isReference, nullptr }, { "cels", Layer_get_cels, nullptr }, { "color", UserData_get_color, UserData_set_color }, { "data", UserData_get_text, UserData_set_text }, From bf60bb895345a82d63d3e61ce78bb8235783e75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Capello?= Date: Wed, 6 Oct 2021 16:06:40 -0300 Subject: [PATCH 21/32] Replace the curl directory by a submodule --- .gitmodules | 3 + third_party/curl | 1 + .../curl/CMake/CMakeConfigurableFile.in | 1 - .../curl/CMake/CurlCheckCSourceCompiles.cmake | 75 - .../curl/CMake/CurlCheckCSourceRuns.cmake | 83 - third_party/curl/CMake/CurlTests.c | 711 --- third_party/curl/CMake/FindOpenSSL.cmake | 19 - third_party/curl/CMake/FindZLIB.cmake | 8 - third_party/curl/CMake/OtherTests.cmake | 249 - .../curl/CMake/Platforms/WindowsCache.cmake | 120 - third_party/curl/CMake/Utilities.cmake | 31 - third_party/curl/CMakeLists.txt | 846 --- third_party/curl/COPYING | 21 - third_party/curl/README | 49 - third_party/curl/RELEASE-NOTES | 32 - third_party/curl/include/README | 55 - third_party/curl/include/curl/curl.h | 2166 ------- third_party/curl/include/curl/curlbuild.h | 583 -- .../curl/include/curl/curlbuild.h.cmake | 180 - third_party/curl/include/curl/curlrules.h | 261 - third_party/curl/include/curl/curlver.h | 69 - third_party/curl/include/curl/easy.h | 102 - third_party/curl/include/curl/mprintf.h | 81 - third_party/curl/include/curl/multi.h | 345 -- third_party/curl/include/curl/stdcheaders.h | 33 - third_party/curl/include/curl/typecheck-gcc.h | 584 -- third_party/curl/include/curl/types.h | 1 - third_party/curl/lib/CMakeLists.txt | 124 - third_party/curl/lib/Makefile.inc | 40 - third_party/curl/lib/README.ares | 69 - third_party/curl/lib/README.curl_off_t | 68 - third_party/curl/lib/README.curlx | 61 - third_party/curl/lib/README.encoding | 60 - third_party/curl/lib/README.hostip | 35 - third_party/curl/lib/README.httpauth | 74 - third_party/curl/lib/README.memoryleak | 55 - third_party/curl/lib/README.multi_socket | 53 - third_party/curl/lib/README.pingpong | 30 - third_party/curl/lib/README.pipelining | 51 - third_party/curl/lib/amigaos.c | 80 - third_party/curl/lib/amigaos.h | 56 - third_party/curl/lib/arpa_telnet.h | 102 - third_party/curl/lib/axtls.c | 500 -- third_party/curl/lib/axtls.h | 62 - third_party/curl/lib/base64.c | 222 - third_party/curl/lib/connect.c | 1159 ---- third_party/curl/lib/connect.h | 74 - third_party/curl/lib/content_encoding.c | 426 -- third_party/curl/lib/content_encoding.h | 48 - third_party/curl/lib/cookie.c | 1168 ---- third_party/curl/lib/cookie.h | 112 - third_party/curl/lib/curl_addrinfo.c | 529 -- third_party/curl/lib/curl_addrinfo.h | 100 - third_party/curl/lib/curl_base64.h | 31 - third_party/curl/lib/curl_config.h.cmake | 953 --- third_party/curl/lib/curl_fnmatch.c | 424 -- third_party/curl/lib/curl_fnmatch.h | 44 - third_party/curl/lib/curl_gethostname.c | 81 - third_party/curl/lib/curl_gethostname.h | 27 - third_party/curl/lib/curl_hmac.h | 67 - third_party/curl/lib/curl_ldap.h | 35 - third_party/curl/lib/curl_md4.h | 33 - third_party/curl/lib/curl_md5.h | 34 - third_party/curl/lib/curl_memory.h | 49 - third_party/curl/lib/curl_memrchr.c | 62 - third_party/curl/lib/curl_memrchr.h | 44 - third_party/curl/lib/curl_rand.c | 60 - third_party/curl/lib/curl_rand.h | 29 - third_party/curl/lib/curl_rtmp.c | 292 - third_party/curl/lib/curl_rtmp.h | 33 - third_party/curl/lib/curl_sspi.c | 121 - third_party/curl/lib/curl_sspi.h | 73 - third_party/curl/lib/curl_threads.c | 127 - third_party/curl/lib/curl_threads.h | 57 - third_party/curl/lib/curlx.h | 118 - third_party/curl/lib/cyassl.c | 571 -- third_party/curl/lib/cyassl.h | 63 - third_party/curl/lib/dict.c | 301 - third_party/curl/lib/dict.h | 29 - third_party/curl/lib/easy.c | 930 --- third_party/curl/lib/easyif.h | 32 - third_party/curl/lib/escape.c | 196 - third_party/curl/lib/escape.h | 29 - third_party/curl/lib/file.c | 591 -- third_party/curl/lib/file.h | 40 - third_party/curl/lib/fileinfo.c | 75 - third_party/curl/lib/fileinfo.h | 33 - third_party/curl/lib/formdata.c | 1701 ------ third_party/curl/lib/formdata.h | 98 - third_party/curl/lib/ftp.c | 4230 ------------- third_party/curl/lib/ftp.h | 153 - third_party/curl/lib/ftplistparser.c | 1046 ---- third_party/curl/lib/ftplistparser.h | 39 - third_party/curl/lib/getenv.c | 65 - third_party/curl/lib/getinfo.c | 283 - third_party/curl/lib/getinfo.h | 27 - third_party/curl/lib/gopher.c | 210 - third_party/curl/lib/gopher.h | 29 - third_party/curl/lib/gtls.c | 1026 ---- third_party/curl/lib/gtls.h | 63 - third_party/curl/lib/hash.c | 339 -- third_party/curl/lib/hash.h | 92 - third_party/curl/lib/hmac.c | 131 - third_party/curl/lib/hostares.c | 439 -- third_party/curl/lib/hostasyn.c | 205 - third_party/curl/lib/hostip.c | 722 --- third_party/curl/lib/hostip.h | 234 - third_party/curl/lib/hostip4.c | 319 - third_party/curl/lib/hostip6.c | 235 - third_party/curl/lib/hostsyn.c | 123 - third_party/curl/lib/hostthre.c | 566 -- third_party/curl/lib/http.c | 3365 ---------- third_party/curl/lib/http.h | 176 - third_party/curl/lib/http_chunks.c | 402 -- third_party/curl/lib/http_chunks.h | 107 - third_party/curl/lib/http_digest.c | 580 -- third_party/curl/lib/http_digest.h | 57 - third_party/curl/lib/http_negotiate.c | 369 -- third_party/curl/lib/http_negotiate.h | 42 - third_party/curl/lib/http_negotiate_sspi.c | 293 - third_party/curl/lib/http_ntlm.c | 1295 ---- third_party/curl/lib/http_ntlm.h | 149 - third_party/curl/lib/http_proxy.c | 513 -- third_party/curl/lib/http_proxy.h | 33 - third_party/curl/lib/idn_win32.c | 127 - third_party/curl/lib/if2ip.c | 160 - third_party/curl/lib/if2ip.h | 65 - third_party/curl/lib/imap.c | 1073 ---- third_party/curl/lib/imap.h | 57 - third_party/curl/lib/inet_ntop.c | 216 - third_party/curl/lib/inet_ntop.h | 37 - third_party/curl/lib/inet_pton.c | 239 - third_party/curl/lib/inet_pton.h | 36 - third_party/curl/lib/krb4.c | 431 -- third_party/curl/lib/krb4.h | 55 - third_party/curl/lib/krb5.c | 349 -- third_party/curl/lib/ldap.c | 724 --- third_party/curl/lib/libcurl.rc | 63 - third_party/curl/lib/llist.c | 198 - third_party/curl/lib/llist.h | 56 - third_party/curl/lib/md4.c | 281 - third_party/curl/lib/md5.c | 395 -- third_party/curl/lib/memdebug.c | 394 -- third_party/curl/lib/memdebug.h | 139 - third_party/curl/lib/mprintf.c | 1246 ---- third_party/curl/lib/multi.c | 2805 --------- third_party/curl/lib/multiif.h | 53 - third_party/curl/lib/netrc.c | 197 - third_party/curl/lib/netrc.h | 40 - third_party/curl/lib/non-ascii.c | 339 -- third_party/curl/lib/non-ascii.h | 60 - third_party/curl/lib/nonblock.c | 101 - third_party/curl/lib/nonblock.h | 30 - third_party/curl/lib/nss.c | 1510 ----- third_party/curl/lib/nssg.h | 71 - third_party/curl/lib/nwlib.c | 327 - third_party/curl/lib/nwos.c | 95 - third_party/curl/lib/openldap.c | 647 -- third_party/curl/lib/parsedate.c | 542 -- third_party/curl/lib/parsedate.h | 48 - third_party/curl/lib/pingpong.c | 535 -- third_party/curl/lib/pingpong.h | 147 - third_party/curl/lib/polarssl.c | 378 -- third_party/curl/lib/polarssl.h | 57 - third_party/curl/lib/pop3.c | 1063 ---- third_party/curl/lib/pop3.h | 63 - third_party/curl/lib/progress.c | 454 -- third_party/curl/lib/progress.h | 70 - third_party/curl/lib/qssl.c | 501 -- third_party/curl/lib/qssl.h | 59 - third_party/curl/lib/rawstr.c | 142 - third_party/curl/lib/rawstr.h | 44 - third_party/curl/lib/rtsp.c | 788 --- third_party/curl/lib/rtsp.h | 87 - third_party/curl/lib/security.c | 591 -- third_party/curl/lib/select.c | 506 -- third_party/curl/lib/select.h | 97 - third_party/curl/lib/sendf.c | 699 --- third_party/curl/lib/sendf.h | 90 - third_party/curl/lib/setup-os400.h | 140 - third_party/curl/lib/setup.h | 586 -- third_party/curl/lib/setup_once.h | 491 -- third_party/curl/lib/share.c | 216 - third_party/curl/lib/share.h | 55 - third_party/curl/lib/slist.c | 134 - third_party/curl/lib/slist.h | 32 - third_party/curl/lib/smtp.c | 1554 ----- third_party/curl/lib/smtp.h | 85 - third_party/curl/lib/sockaddr.h | 37 - third_party/curl/lib/socks.c | 732 --- third_party/curl/lib/socks.h | 77 - third_party/curl/lib/socks_gssapi.c | 546 -- third_party/curl/lib/socks_sspi.c | 696 --- third_party/curl/lib/speedcheck.c | 74 - third_party/curl/lib/speedcheck.h | 33 - third_party/curl/lib/splay.c | 438 -- third_party/curl/lib/splay.h | 65 - third_party/curl/lib/ssh.c | 3157 ---------- third_party/curl/lib/ssh.h | 171 - third_party/curl/lib/sslgen.c | 481 -- third_party/curl/lib/sslgen.h | 92 - third_party/curl/lib/ssluse.c | 2719 --------- third_party/curl/lib/ssluse.h | 84 - third_party/curl/lib/strdup.c | 49 - third_party/curl/lib/strdup.h | 30 - third_party/curl/lib/strequal.c | 121 - third_party/curl/lib/strequal.h | 35 - third_party/curl/lib/strerror.c | 778 --- third_party/curl/lib/strerror.h | 33 - third_party/curl/lib/strtok.c | 67 - third_party/curl/lib/strtok.h | 34 - third_party/curl/lib/strtoofft.c | 191 - third_party/curl/lib/strtoofft.h | 68 - third_party/curl/lib/telnet.c | 1559 ----- third_party/curl/lib/telnet.h | 28 - third_party/curl/lib/tftp.c | 1509 ----- third_party/curl/lib/tftp.h | 28 - third_party/curl/lib/timeval.c | 131 - third_party/curl/lib/timeval.h | 57 - third_party/curl/lib/transfer.c | 2384 -------- third_party/curl/lib/transfer.h | 68 - third_party/curl/lib/url.c | 5394 ----------------- third_party/curl/lib/url.h | 96 - third_party/curl/lib/urldata.h | 1568 ----- third_party/curl/lib/version.c | 334 - third_party/curl/lib/warnless.c | 253 - third_party/curl/lib/warnless.h | 41 - third_party/curl/lib/wildcard.c | 76 - third_party/curl/lib/wildcard.h | 58 - 229 files changed, 4 insertions(+), 84765 deletions(-) create mode 160000 third_party/curl delete mode 100644 third_party/curl/CMake/CMakeConfigurableFile.in delete mode 100644 third_party/curl/CMake/CurlCheckCSourceCompiles.cmake delete mode 100644 third_party/curl/CMake/CurlCheckCSourceRuns.cmake delete mode 100644 third_party/curl/CMake/CurlTests.c delete mode 100644 third_party/curl/CMake/FindOpenSSL.cmake delete mode 100644 third_party/curl/CMake/FindZLIB.cmake delete mode 100644 third_party/curl/CMake/OtherTests.cmake delete mode 100644 third_party/curl/CMake/Platforms/WindowsCache.cmake delete mode 100644 third_party/curl/CMake/Utilities.cmake delete mode 100644 third_party/curl/CMakeLists.txt delete mode 100644 third_party/curl/COPYING delete mode 100644 third_party/curl/README delete mode 100644 third_party/curl/RELEASE-NOTES delete mode 100644 third_party/curl/include/README delete mode 100644 third_party/curl/include/curl/curl.h delete mode 100644 third_party/curl/include/curl/curlbuild.h delete mode 100644 third_party/curl/include/curl/curlbuild.h.cmake delete mode 100644 third_party/curl/include/curl/curlrules.h delete mode 100644 third_party/curl/include/curl/curlver.h delete mode 100644 third_party/curl/include/curl/easy.h delete mode 100644 third_party/curl/include/curl/mprintf.h delete mode 100644 third_party/curl/include/curl/multi.h delete mode 100644 third_party/curl/include/curl/stdcheaders.h delete mode 100644 third_party/curl/include/curl/typecheck-gcc.h delete mode 100644 third_party/curl/include/curl/types.h delete mode 100644 third_party/curl/lib/CMakeLists.txt delete mode 100644 third_party/curl/lib/Makefile.inc delete mode 100644 third_party/curl/lib/README.ares delete mode 100644 third_party/curl/lib/README.curl_off_t delete mode 100644 third_party/curl/lib/README.curlx delete mode 100644 third_party/curl/lib/README.encoding delete mode 100644 third_party/curl/lib/README.hostip delete mode 100644 third_party/curl/lib/README.httpauth delete mode 100644 third_party/curl/lib/README.memoryleak delete mode 100644 third_party/curl/lib/README.multi_socket delete mode 100644 third_party/curl/lib/README.pingpong delete mode 100644 third_party/curl/lib/README.pipelining delete mode 100644 third_party/curl/lib/amigaos.c delete mode 100644 third_party/curl/lib/amigaos.h delete mode 100644 third_party/curl/lib/arpa_telnet.h delete mode 100644 third_party/curl/lib/axtls.c delete mode 100644 third_party/curl/lib/axtls.h delete mode 100644 third_party/curl/lib/base64.c delete mode 100644 third_party/curl/lib/connect.c delete mode 100644 third_party/curl/lib/connect.h delete mode 100644 third_party/curl/lib/content_encoding.c delete mode 100644 third_party/curl/lib/content_encoding.h delete mode 100644 third_party/curl/lib/cookie.c delete mode 100644 third_party/curl/lib/cookie.h delete mode 100644 third_party/curl/lib/curl_addrinfo.c delete mode 100644 third_party/curl/lib/curl_addrinfo.h delete mode 100644 third_party/curl/lib/curl_base64.h delete mode 100644 third_party/curl/lib/curl_config.h.cmake delete mode 100644 third_party/curl/lib/curl_fnmatch.c delete mode 100644 third_party/curl/lib/curl_fnmatch.h delete mode 100644 third_party/curl/lib/curl_gethostname.c delete mode 100644 third_party/curl/lib/curl_gethostname.h delete mode 100644 third_party/curl/lib/curl_hmac.h delete mode 100644 third_party/curl/lib/curl_ldap.h delete mode 100644 third_party/curl/lib/curl_md4.h delete mode 100644 third_party/curl/lib/curl_md5.h delete mode 100644 third_party/curl/lib/curl_memory.h delete mode 100644 third_party/curl/lib/curl_memrchr.c delete mode 100644 third_party/curl/lib/curl_memrchr.h delete mode 100644 third_party/curl/lib/curl_rand.c delete mode 100644 third_party/curl/lib/curl_rand.h delete mode 100644 third_party/curl/lib/curl_rtmp.c delete mode 100644 third_party/curl/lib/curl_rtmp.h delete mode 100644 third_party/curl/lib/curl_sspi.c delete mode 100644 third_party/curl/lib/curl_sspi.h delete mode 100644 third_party/curl/lib/curl_threads.c delete mode 100644 third_party/curl/lib/curl_threads.h delete mode 100644 third_party/curl/lib/curlx.h delete mode 100644 third_party/curl/lib/cyassl.c delete mode 100644 third_party/curl/lib/cyassl.h delete mode 100644 third_party/curl/lib/dict.c delete mode 100644 third_party/curl/lib/dict.h delete mode 100644 third_party/curl/lib/easy.c delete mode 100644 third_party/curl/lib/easyif.h delete mode 100644 third_party/curl/lib/escape.c delete mode 100644 third_party/curl/lib/escape.h delete mode 100644 third_party/curl/lib/file.c delete mode 100644 third_party/curl/lib/file.h delete mode 100644 third_party/curl/lib/fileinfo.c delete mode 100644 third_party/curl/lib/fileinfo.h delete mode 100644 third_party/curl/lib/formdata.c delete mode 100644 third_party/curl/lib/formdata.h delete mode 100644 third_party/curl/lib/ftp.c delete mode 100644 third_party/curl/lib/ftp.h delete mode 100644 third_party/curl/lib/ftplistparser.c delete mode 100644 third_party/curl/lib/ftplistparser.h delete mode 100644 third_party/curl/lib/getenv.c delete mode 100644 third_party/curl/lib/getinfo.c delete mode 100644 third_party/curl/lib/getinfo.h delete mode 100644 third_party/curl/lib/gopher.c delete mode 100644 third_party/curl/lib/gopher.h delete mode 100644 third_party/curl/lib/gtls.c delete mode 100644 third_party/curl/lib/gtls.h delete mode 100644 third_party/curl/lib/hash.c delete mode 100644 third_party/curl/lib/hash.h delete mode 100644 third_party/curl/lib/hmac.c delete mode 100644 third_party/curl/lib/hostares.c delete mode 100644 third_party/curl/lib/hostasyn.c delete mode 100644 third_party/curl/lib/hostip.c delete mode 100644 third_party/curl/lib/hostip.h delete mode 100644 third_party/curl/lib/hostip4.c delete mode 100644 third_party/curl/lib/hostip6.c delete mode 100644 third_party/curl/lib/hostsyn.c delete mode 100644 third_party/curl/lib/hostthre.c delete mode 100644 third_party/curl/lib/http.c delete mode 100644 third_party/curl/lib/http.h delete mode 100644 third_party/curl/lib/http_chunks.c delete mode 100644 third_party/curl/lib/http_chunks.h delete mode 100644 third_party/curl/lib/http_digest.c delete mode 100644 third_party/curl/lib/http_digest.h delete mode 100644 third_party/curl/lib/http_negotiate.c delete mode 100644 third_party/curl/lib/http_negotiate.h delete mode 100644 third_party/curl/lib/http_negotiate_sspi.c delete mode 100644 third_party/curl/lib/http_ntlm.c delete mode 100644 third_party/curl/lib/http_ntlm.h delete mode 100644 third_party/curl/lib/http_proxy.c delete mode 100644 third_party/curl/lib/http_proxy.h delete mode 100644 third_party/curl/lib/idn_win32.c delete mode 100644 third_party/curl/lib/if2ip.c delete mode 100644 third_party/curl/lib/if2ip.h delete mode 100644 third_party/curl/lib/imap.c delete mode 100644 third_party/curl/lib/imap.h delete mode 100644 third_party/curl/lib/inet_ntop.c delete mode 100644 third_party/curl/lib/inet_ntop.h delete mode 100644 third_party/curl/lib/inet_pton.c delete mode 100644 third_party/curl/lib/inet_pton.h delete mode 100644 third_party/curl/lib/krb4.c delete mode 100644 third_party/curl/lib/krb4.h delete mode 100644 third_party/curl/lib/krb5.c delete mode 100644 third_party/curl/lib/ldap.c delete mode 100644 third_party/curl/lib/libcurl.rc delete mode 100644 third_party/curl/lib/llist.c delete mode 100644 third_party/curl/lib/llist.h delete mode 100644 third_party/curl/lib/md4.c delete mode 100644 third_party/curl/lib/md5.c delete mode 100644 third_party/curl/lib/memdebug.c delete mode 100644 third_party/curl/lib/memdebug.h delete mode 100644 third_party/curl/lib/mprintf.c delete mode 100644 third_party/curl/lib/multi.c delete mode 100644 third_party/curl/lib/multiif.h delete mode 100644 third_party/curl/lib/netrc.c delete mode 100644 third_party/curl/lib/netrc.h delete mode 100644 third_party/curl/lib/non-ascii.c delete mode 100644 third_party/curl/lib/non-ascii.h delete mode 100644 third_party/curl/lib/nonblock.c delete mode 100644 third_party/curl/lib/nonblock.h delete mode 100644 third_party/curl/lib/nss.c delete mode 100644 third_party/curl/lib/nssg.h delete mode 100644 third_party/curl/lib/nwlib.c delete mode 100644 third_party/curl/lib/nwos.c delete mode 100644 third_party/curl/lib/openldap.c delete mode 100644 third_party/curl/lib/parsedate.c delete mode 100644 third_party/curl/lib/parsedate.h delete mode 100644 third_party/curl/lib/pingpong.c delete mode 100644 third_party/curl/lib/pingpong.h delete mode 100644 third_party/curl/lib/polarssl.c delete mode 100644 third_party/curl/lib/polarssl.h delete mode 100644 third_party/curl/lib/pop3.c delete mode 100644 third_party/curl/lib/pop3.h delete mode 100644 third_party/curl/lib/progress.c delete mode 100644 third_party/curl/lib/progress.h delete mode 100644 third_party/curl/lib/qssl.c delete mode 100644 third_party/curl/lib/qssl.h delete mode 100644 third_party/curl/lib/rawstr.c delete mode 100644 third_party/curl/lib/rawstr.h delete mode 100644 third_party/curl/lib/rtsp.c delete mode 100644 third_party/curl/lib/rtsp.h delete mode 100644 third_party/curl/lib/security.c delete mode 100644 third_party/curl/lib/select.c delete mode 100644 third_party/curl/lib/select.h delete mode 100644 third_party/curl/lib/sendf.c delete mode 100644 third_party/curl/lib/sendf.h delete mode 100644 third_party/curl/lib/setup-os400.h delete mode 100644 third_party/curl/lib/setup.h delete mode 100644 third_party/curl/lib/setup_once.h delete mode 100644 third_party/curl/lib/share.c delete mode 100644 third_party/curl/lib/share.h delete mode 100644 third_party/curl/lib/slist.c delete mode 100644 third_party/curl/lib/slist.h delete mode 100644 third_party/curl/lib/smtp.c delete mode 100644 third_party/curl/lib/smtp.h delete mode 100644 third_party/curl/lib/sockaddr.h delete mode 100644 third_party/curl/lib/socks.c delete mode 100644 third_party/curl/lib/socks.h delete mode 100644 third_party/curl/lib/socks_gssapi.c delete mode 100644 third_party/curl/lib/socks_sspi.c delete mode 100644 third_party/curl/lib/speedcheck.c delete mode 100644 third_party/curl/lib/speedcheck.h delete mode 100644 third_party/curl/lib/splay.c delete mode 100644 third_party/curl/lib/splay.h delete mode 100644 third_party/curl/lib/ssh.c delete mode 100644 third_party/curl/lib/ssh.h delete mode 100644 third_party/curl/lib/sslgen.c delete mode 100644 third_party/curl/lib/sslgen.h delete mode 100644 third_party/curl/lib/ssluse.c delete mode 100644 third_party/curl/lib/ssluse.h delete mode 100644 third_party/curl/lib/strdup.c delete mode 100644 third_party/curl/lib/strdup.h delete mode 100644 third_party/curl/lib/strequal.c delete mode 100644 third_party/curl/lib/strequal.h delete mode 100644 third_party/curl/lib/strerror.c delete mode 100644 third_party/curl/lib/strerror.h delete mode 100644 third_party/curl/lib/strtok.c delete mode 100644 third_party/curl/lib/strtok.h delete mode 100644 third_party/curl/lib/strtoofft.c delete mode 100644 third_party/curl/lib/strtoofft.h delete mode 100644 third_party/curl/lib/telnet.c delete mode 100644 third_party/curl/lib/telnet.h delete mode 100644 third_party/curl/lib/tftp.c delete mode 100644 third_party/curl/lib/tftp.h delete mode 100644 third_party/curl/lib/timeval.c delete mode 100644 third_party/curl/lib/timeval.h delete mode 100644 third_party/curl/lib/transfer.c delete mode 100644 third_party/curl/lib/transfer.h delete mode 100644 third_party/curl/lib/url.c delete mode 100644 third_party/curl/lib/url.h delete mode 100644 third_party/curl/lib/urldata.h delete mode 100644 third_party/curl/lib/version.c delete mode 100644 third_party/curl/lib/warnless.c delete mode 100644 third_party/curl/lib/warnless.h delete mode 100644 third_party/curl/lib/wildcard.c delete mode 100644 third_party/curl/lib/wildcard.h diff --git a/.gitmodules b/.gitmodules index 780aaf1c3..ab0c20cf0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -66,3 +66,6 @@ [submodule "src/tga"] path = src/tga url = https://github.com/aseprite/tga.git +[submodule "third_party/curl"] + path = third_party/curl + url = https://github.com/aseprite/curl.git diff --git a/third_party/curl b/third_party/curl new file mode 160000 index 000000000..09cf6fd70 --- /dev/null +++ b/third_party/curl @@ -0,0 +1 @@ +Subproject commit 09cf6fd7009a98377db655c15e7ae5088e952f9a diff --git a/third_party/curl/CMake/CMakeConfigurableFile.in b/third_party/curl/CMake/CMakeConfigurableFile.in deleted file mode 100644 index df2c382e9..000000000 --- a/third_party/curl/CMake/CMakeConfigurableFile.in +++ /dev/null @@ -1 +0,0 @@ -@CMAKE_CONFIGURABLE_FILE_CONTENT@ diff --git a/third_party/curl/CMake/CurlCheckCSourceCompiles.cmake b/third_party/curl/CMake/CurlCheckCSourceCompiles.cmake deleted file mode 100644 index b63276809..000000000 --- a/third_party/curl/CMake/CurlCheckCSourceCompiles.cmake +++ /dev/null @@ -1,75 +0,0 @@ -# - Check if the source code provided in the SOURCE argument compiles. -# CURL_CHECK_C_SOURCE_COMPILES(SOURCE VAR) -# - macro which checks if the source code compiles -# SOURCE - source code to try to compile -# VAR - variable to store whether the source code compiled -# -# The following variables may be set before calling this macro to -# modify the way the check is run: -# -# CMAKE_REQUIRED_FLAGS = string of compile command line flags -# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) -# CMAKE_REQUIRED_INCLUDES = list of include directories -# CMAKE_REQUIRED_LIBRARIES = list of libraries to link - -macro(CURL_CHECK_C_SOURCE_COMPILES SOURCE VAR) - if("${VAR}" MATCHES "^${VAR}$" OR "${VAR}" MATCHES "UNKNOWN") - set(message "${VAR}") - # If the number of arguments is greater than 2 (SOURCE VAR) - if(${ARGC} GREATER 2) - # then add the third argument as a message - set(message "${ARGV2} (${VAR})") - endif(${ARGC} GREATER 2) - set(MACRO_CHECK_FUNCTION_DEFINITIONS - "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") - if(CMAKE_REQUIRED_LIBRARIES) - set(CURL_CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") - else(CMAKE_REQUIRED_LIBRARIES) - set(CURL_CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES) - endif(CMAKE_REQUIRED_LIBRARIES) - if(CMAKE_REQUIRED_INCLUDES) - set(CURL_CHECK_C_SOURCE_COMPILES_ADD_INCLUDES - "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") - else(CMAKE_REQUIRED_INCLUDES) - set(CURL_CHECK_C_SOURCE_COMPILES_ADD_INCLUDES) - endif(CMAKE_REQUIRED_INCLUDES) - set(src "") - foreach(def ${EXTRA_DEFINES}) - set(src "${src}#define ${def} 1\n") - endforeach(def) - foreach(inc ${HEADER_INCLUDES}) - set(src "${src}#include <${inc}>\n") - endforeach(inc) - - set(src "${src}\nint main() { ${SOURCE} ; return 0; }") - set(CMAKE_CONFIGURABLE_FILE_CONTENT "${src}") - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMake/CMakeConfigurableFile.in - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c" - IMMEDIATE) - message(STATUS "Performing Test ${message}") - try_compile(${VAR} - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c - COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} - CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} - "${CURL_CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}" - "${CURL_CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}" - OUTPUT_VARIABLE OUTPUT) - if(${VAR}) - set(${VAR} 1 CACHE INTERNAL "Test ${message}") - message(STATUS "Performing Test ${message} - Success") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Performing C SOURCE FILE Test ${message} succeded with the following output:\n" - "${OUTPUT}\n" - "Source file was:\n${src}\n") - else(${VAR}) - message(STATUS "Performing Test ${message} - Failed") - set(${VAR} "" CACHE INTERNAL "Test ${message}") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Performing C SOURCE FILE Test ${message} failed with the following output:\n" - "${OUTPUT}\n" - "Source file was:\n${src}\n") - endif(${VAR}) - endif("${VAR}" MATCHES "^${VAR}$" OR "${VAR}" MATCHES "UNKNOWN") -endmacro(CURL_CHECK_C_SOURCE_COMPILES) diff --git a/third_party/curl/CMake/CurlCheckCSourceRuns.cmake b/third_party/curl/CMake/CurlCheckCSourceRuns.cmake deleted file mode 100644 index 6b14af80d..000000000 --- a/third_party/curl/CMake/CurlCheckCSourceRuns.cmake +++ /dev/null @@ -1,83 +0,0 @@ -# - Check if the source code provided in the SOURCE argument compiles and runs. -# CURL_CHECK_C_SOURCE_RUNS(SOURCE VAR) -# - macro which checks if the source code runs -# SOURCE - source code to try to compile -# VAR - variable to store size if the type exists. -# -# The following variables may be set before calling this macro to -# modify the way the check is run: -# -# CMAKE_REQUIRED_FLAGS = string of compile command line flags -# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) -# CMAKE_REQUIRED_INCLUDES = list of include directories -# CMAKE_REQUIRED_LIBRARIES = list of libraries to link - -macro(CURL_CHECK_C_SOURCE_RUNS SOURCE VAR) - if("${VAR}" MATCHES "^${VAR}$" OR "${VAR}" MATCHES "UNKNOWN") - set(message "${VAR}") - # If the number of arguments is greater than 2 (SOURCE VAR) - if(${ARGC} GREATER 2) - # then add the third argument as a message - set(message "${ARGV2} (${VAR})") - endif(${ARGC} GREATER 2) - set(MACRO_CHECK_FUNCTION_DEFINITIONS - "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") - if(CMAKE_REQUIRED_LIBRARIES) - set(CURL_CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") - else(CMAKE_REQUIRED_LIBRARIES) - set(CURL_CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES) - endif(CMAKE_REQUIRED_LIBRARIES) - if(CMAKE_REQUIRED_INCLUDES) - set(CURL_CHECK_C_SOURCE_COMPILES_ADD_INCLUDES - "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") - else(CMAKE_REQUIRED_INCLUDES) - set(CURL_CHECK_C_SOURCE_COMPILES_ADD_INCLUDES) - endif(CMAKE_REQUIRED_INCLUDES) - set(src "") - foreach(def ${EXTRA_DEFINES}) - set(src "${src}#define ${def} 1\n") - endforeach(def) - foreach(inc ${HEADER_INCLUDES}) - set(src "${src}#include <${inc}>\n") - endforeach(inc) - - set(src "${src}\nint main() { ${SOURCE} ; return 0; }") - set(CMAKE_CONFIGURABLE_FILE_CONTENT "${src}") - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMake/CMakeConfigurableFile.in - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c" - IMMEDIATE) - message(STATUS "Performing Test ${message}") - try_run(${VAR} ${VAR}_COMPILED - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c - COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} - CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} - "${CURL_CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}" - "${CURL_CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}" - OUTPUT_VARIABLE OUTPUT) - # if it did not compile make the return value fail code of 1 - if(NOT ${VAR}_COMPILED) - set(${VAR} 1) - endif(NOT ${VAR}_COMPILED) - # if the return value was 0 then it worked - set(result_var ${${VAR}}) - if("${result_var}" EQUAL 0) - set(${VAR} 1 CACHE INTERNAL "Test ${message}") - message(STATUS "Performing Test ${message} - Success") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Performing C SOURCE FILE Test ${message} succeded with the following output:\n" - "${OUTPUT}\n" - "Return value: ${${VAR}}\n" - "Source file was:\n${src}\n") - else("${result_var}" EQUAL 0) - message(STATUS "Performing Test ${message} - Failed") - set(${VAR} "" CACHE INTERNAL "Test ${message}") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Performing C SOURCE FILE Test ${message} failed with the following output:\n" - "${OUTPUT}\n" - "Return value: ${result_var}\n" - "Source file was:\n${src}\n") - endif("${result_var}" EQUAL 0) - endif("${VAR}" MATCHES "^${VAR}$" OR "${VAR}" MATCHES "UNKNOWN") -endmacro(CURL_CHECK_C_SOURCE_RUNS) diff --git a/third_party/curl/CMake/CurlTests.c b/third_party/curl/CMake/CurlTests.c deleted file mode 100644 index 199871aa6..000000000 --- a/third_party/curl/CMake/CurlTests.c +++ /dev/null @@ -1,711 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#ifdef TIME_WITH_SYS_TIME -/* Time with sys/time test */ - -#include -#include -#include - -int -main () -{ -if ((struct tm *) 0) -return 0; - ; - return 0; -} - -#endif - -#ifdef HAVE_FCNTL_O_NONBLOCK - -/* headers for FCNTL_O_NONBLOCK test */ -#include -#include -#include -/* */ -#if defined(sun) || defined(__sun__) || \ - defined(__SUNPRO_C) || defined(__SUNPRO_CC) -# if defined(__SVR4) || defined(__srv4__) -# define PLATFORM_SOLARIS -# else -# define PLATFORM_SUNOS4 -# endif -#endif -#if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX41) -# define PLATFORM_AIX_V3 -#endif -/* */ -#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3) || defined(__BEOS__) -#error "O_NONBLOCK does not work on this platform" -#endif - -int -main () -{ - /* O_NONBLOCK source test */ - int flags = 0; - if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK)) - return 1; - return 0; -} -#endif - -#ifdef HAVE_GETHOSTBYADDR_R_5 -#include -#include -int -main () -{ - -char * address; -int length; -int type; -struct hostent h; -struct hostent_data hdata; -int rc; -#ifndef gethostbyaddr_r - (void)gethostbyaddr_r; -#endif -rc = gethostbyaddr_r(address, length, type, &h, &hdata); - ; - return 0; -} -#endif -#ifdef HAVE_GETHOSTBYADDR_R_5_REENTRANT -#define _REENTRANT -#include -#include -int -main () -{ - -char * address; -int length;q -int type; -struct hostent h; -struct hostent_data hdata; -int rc; -#ifndef gethostbyaddr_r - (void)gethostbyaddr_r; -#endif -rc = gethostbyaddr_r(address, length, type, &h, &hdata); - ; - return 0; -} -#endif -#ifdef HAVE_GETHOSTBYADDR_R_7 -#include -#include -int -main () -{ - -char * address; -int length; -int type; -struct hostent h; -char buffer[8192]; -int h_errnop; -struct hostent * hp; - -#ifndef gethostbyaddr_r - (void)gethostbyaddr_r; -#endif -hp = gethostbyaddr_r(address, length, type, &h, - buffer, 8192, &h_errnop); - ; - return 0; -} -#endif -#ifdef HAVE_GETHOSTBYADDR_R_7_REENTRANT -#define _REENTRANT -#include -#include -int -main () -{ - -char * address; -int length; -int type; -struct hostent h; -char buffer[8192]; -int h_errnop; -struct hostent * hp; - -#ifndef gethostbyaddr_r - (void)gethostbyaddr_r; -#endif -hp = gethostbyaddr_r(address, length, type, &h, - buffer, 8192, &h_errnop); - ; - return 0; -} -#endif -#ifdef HAVE_GETHOSTBYADDR_R_8 -#include -#include -int -main () -{ - -char * address; -int length; -int type; -struct hostent h; -char buffer[8192]; -int h_errnop; -struct hostent * hp; -int rc; - -#ifndef gethostbyaddr_r - (void)gethostbyaddr_r; -#endif -rc = gethostbyaddr_r(address, length, type, &h, - buffer, 8192, &hp, &h_errnop); - ; - return 0; -} -#endif -#ifdef HAVE_GETHOSTBYADDR_R_8_REENTRANT -#define _REENTRANT -#include -#include -int -main () -{ - -char * address; -int length; -int type; -struct hostent h; -char buffer[8192]; -int h_errnop; -struct hostent * hp; -int rc; - -#ifndef gethostbyaddr_r - (void)gethostbyaddr_r; -#endif -rc = gethostbyaddr_r(address, length, type, &h, - buffer, 8192, &hp, &h_errnop); - ; - return 0; -} -#endif -#ifdef HAVE_GETHOSTBYNAME_R_3 -#include -#include -#include -#undef NULL -#define NULL (void *)0 - -int -main () -{ - -struct hostent_data data; -#ifndef gethostbyname_r - (void)gethostbyname_r; -#endif -gethostbyname_r(NULL, NULL, NULL); - ; - return 0; -} -#endif -#ifdef HAVE_GETHOSTBYNAME_R_3_REENTRANT -#define _REENTRANT -#include -#include -#include -#undef NULL -#define NULL (void *)0 - -int -main () -{ - -struct hostent_data data; -#ifndef gethostbyname_r - (void)gethostbyname_r; -#endif -gethostbyname_r(NULL, NULL, NULL); - ; - return 0; -} -#endif -#ifdef HAVE_GETHOSTBYNAME_R_5 -#include -#include -#include -#undef NULL -#define NULL (void *)0 - -int -main () -{ -#ifndef gethostbyname_r - (void)gethostbyname_r; -#endif -gethostbyname_r(NULL, NULL, NULL, 0, NULL); - ; - return 0; -} -#endif -#ifdef HAVE_GETHOSTBYNAME_R_5_REENTRANT -#define _REENTRANT -#include -#include -#undef NULL -#define NULL (void *)0 - -int -main () -{ - -#ifndef gethostbyname_r - (void)gethostbyname_r; -#endif -gethostbyname_r(NULL, NULL, NULL, 0, NULL); - ; - return 0; -} -#endif -#ifdef HAVE_GETHOSTBYNAME_R_6 -#include -#include -#undef NULL -#define NULL (void *)0 - -int -main () -{ - -#ifndef gethostbyname_r - (void)gethostbyname_r; -#endif -gethostbyname_r(NULL, NULL, NULL, 0, NULL, NULL); - ; - return 0; -} -#endif -#ifdef HAVE_GETHOSTBYNAME_R_6_REENTRANT -#define _REENTRANT -#include -#include -#undef NULL -#define NULL (void *)0 - -int -main () -{ - -#ifndef gethostbyname_r - (void)gethostbyname_r; -#endif -gethostbyname_r(NULL, NULL, NULL, 0, NULL, NULL); - ; - return 0; -} -#endif -#ifdef HAVE_SOCKLEN_T -#ifdef _WIN32 -#include -#else -#include -#include -#endif -int -main () -{ -if ((socklen_t *) 0) - return 0; -if (sizeof (socklen_t)) - return 0; - ; - return 0; -} -#endif -#ifdef HAVE_IN_ADDR_T -#include -#include -#include - -int -main () -{ -if ((in_addr_t *) 0) - return 0; -if (sizeof (in_addr_t)) - return 0; - ; - return 0; -} -#endif - -#ifdef HAVE_BOOL_T -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_STDBOOL_H -#include -#endif -int -main () -{ -if (sizeof (bool *) ) - return 0; - ; - return 0; -} -#endif - -#ifdef STDC_HEADERS -#include -#include -#include -#include -int main() { return 0; } -#endif -#ifdef RETSIGTYPE_TEST -#include -#include -#ifdef signal -# undef signal -#endif -#ifdef __cplusplus -extern "C" void (*signal (int, void (*)(int)))(int); -#else -void (*signal ()) (); -#endif - -int -main () -{ - return 0; -} -#endif -#ifdef HAVE_INET_NTOA_R_DECL -#include - -typedef void (*func_type)(); - -int main() -{ -#ifndef inet_ntoa_r - func_type func; - func = (func_type)inet_ntoa_r; -#endif - return 0; -} -#endif -#ifdef HAVE_INET_NTOA_R_DECL_REENTRANT -#define _REENTRANT -#include - -typedef void (*func_type)(); - -int main() -{ -#ifndef inet_ntoa_r - func_type func; - func = (func_type)&inet_ntoa_r; -#endif - return 0; -} -#endif -#ifdef HAVE_GETADDRINFO -#include -#include -#include - -int main(void) { - struct addrinfo hints, *ai; - int error; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; -#ifndef getaddrinfo - (void)getaddrinfo; -#endif - error = getaddrinfo("127.0.0.1", "8080", &hints, &ai); - if (error) { - return 1; - } - return 0; -} -#endif -#ifdef HAVE_FILE_OFFSET_BITS -#ifdef _FILE_OFFSET_BITS -#undef _FILE_OFFSET_BITS -#endif -#define _FILE_OFFSET_BITS 64 -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; -int main () { ; return 0; } -#endif -#ifdef HAVE_IOCTLSOCKET -/* includes start */ -#ifdef HAVE_WINDOWS_H -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# ifdef HAVE_WINSOCK2_H -# include -# else -# ifdef HAVE_WINSOCK_H -# include -# endif -# endif -#endif - -int -main () -{ - -/* ioctlsocket source code */ - int socket; - unsigned long flags = ioctlsocket(socket, FIONBIO, &flags); - - ; - return 0; -} - -#endif -#ifdef HAVE_IOCTLSOCKET_CAMEL -/* includes start */ -#ifdef HAVE_WINDOWS_H -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# ifdef HAVE_WINSOCK2_H -# include -# else -# ifdef HAVE_WINSOCK_H -# include -# endif -# endif -#endif - -int -main () -{ - -/* IoctlSocket source code */ - if(0 != IoctlSocket(0, 0, 0)) - return 1; - ; - return 0; -} -#endif -#ifdef HAVE_IOCTLSOCKET_CAMEL_FIONBIO -/* includes start */ -#ifdef HAVE_WINDOWS_H -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# ifdef HAVE_WINSOCK2_H -# include -# else -# ifdef HAVE_WINSOCK_H -# include -# endif -# endif -#endif - -int -main () -{ - -/* IoctlSocket source code */ - long flags = 0; - if(0 != ioctlsocket(0, FIONBIO, &flags)) - return 1; - ; - return 0; -} -#endif -#ifdef HAVE_IOCTLSOCKET_FIONBIO -/* includes start */ -#ifdef HAVE_WINDOWS_H -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# ifdef HAVE_WINSOCK2_H -# include -# else -# ifdef HAVE_WINSOCK_H -# include -# endif -# endif -#endif - -int -main () -{ - - int flags = 0; - if(0 != ioctlsocket(0, FIONBIO, &flags)) - return 1; - - ; - return 0; -} -#endif -#ifdef HAVE_IOCTL_FIONBIO -/* headers for FIONBIO test */ -/* includes start */ -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif -#ifdef HAVE_STROPTS_H -# include -#endif - -int -main () -{ - - int flags = 0; - if(0 != ioctl(0, FIONBIO, &flags)) - return 1; - - ; - return 0; -} -#endif -#ifdef HAVE_IOCTL_SIOCGIFADDR -/* headers for FIONBIO test */ -/* includes start */ -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif -#ifdef HAVE_STROPTS_H -# include -#endif -#include - -int -main () -{ - struct ifreq ifr; - if(0 != ioctl(0, SIOCGIFADDR, &ifr)) - return 1; - - ; - return 0; -} -#endif -#ifdef HAVE_SETSOCKOPT_SO_NONBLOCK -/* includes start */ -#ifdef HAVE_WINDOWS_H -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# ifdef HAVE_WINSOCK2_H -# include -# else -# ifdef HAVE_WINSOCK_H -# include -# endif -# endif -#endif -/* includes start */ -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -/* includes end */ - -int -main () -{ - if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0)) - return 1; - ; - return 0; -} -#endif -#ifdef HAVE_GLIBC_STRERROR_R -#include -#include -int -main () { - char buffer[1024]; /* big enough to play with */ - char *string = - strerror_r(EACCES, buffer, sizeof(buffer)); - /* this should've returned a string */ - if(!string || !string[0]) - return 99; - return 0; -} -#endif -#ifdef HAVE_POSIX_STRERROR_R -#include -#include -int -main () { - char buffer[1024]; /* big enough to play with */ - int error = - strerror_r(EACCES, buffer, sizeof(buffer)); - /* This should've returned zero, and written an error string in the - buffer.*/ - if(!buffer[0] || error) - return 99; - return 0; -} -#endif diff --git a/third_party/curl/CMake/FindOpenSSL.cmake b/third_party/curl/CMake/FindOpenSSL.cmake deleted file mode 100644 index 63a9d6062..000000000 --- a/third_party/curl/CMake/FindOpenSSL.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Extension of the standard FindOpenSSL.cmake -# Adds OPENSSL_INCLUDE_DIRS and libeay32 -include("${CMAKE_ROOT}/Modules/FindOpenSSL.cmake") - -# Bill Hoffman told that libeay32 is necessary for him: -find_library(SSL_LIBEAY NAMES libeay32) - -if(OPENSSL_FOUND) - if(SSL_LIBEAY) - list(APPEND OPENSSL_LIBRARIES ${SSL_LIBEAY}) - else() - set(OPENSSL_FOUND FALSE) - endif() -endif() - - -if(OPENSSL_FOUND) - set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR}) -endif() diff --git a/third_party/curl/CMake/FindZLIB.cmake b/third_party/curl/CMake/FindZLIB.cmake deleted file mode 100644 index 87f1d4fe8..000000000 --- a/third_party/curl/CMake/FindZLIB.cmake +++ /dev/null @@ -1,8 +0,0 @@ -# Locate zlib -include("${CMAKE_ROOT}/Modules/FindZLIB.cmake") - -find_library(ZLIB_LIBRARY_DEBUG NAMES zd zlibd zdlld zlib1d ) - -if(ZLIB_FOUND AND ZLIB_LIBRARY_DEBUG) - set( ZLIB_LIBRARIES optimized "${ZLIB_LIBRARY}" debug ${ZLIB_LIBRARY_DEBUG}) -endif() diff --git a/third_party/curl/CMake/OtherTests.cmake b/third_party/curl/CMake/OtherTests.cmake deleted file mode 100644 index 48e328336..000000000 --- a/third_party/curl/CMake/OtherTests.cmake +++ /dev/null @@ -1,249 +0,0 @@ -include(CurlCheckCSourceCompiles) -set(EXTRA_DEFINES "__unused1\n#undef inline\n#define __unused2") -set(HEADER_INCLUDES) -set(headers_hack) - -macro(add_header_include check header) - if(${check}) - set(headers_hack - "${headers_hack}\n#include <${header}>") - #SET(HEADER_INCLUDES - # ${HEADER_INCLUDES} - # "${header}") - endif(${check}) -endmacro(add_header_include) - -set(signature_call_conv) -if(HAVE_WINDOWS_H) - add_header_include(HAVE_WINDOWS_H "windows.h") - add_header_include(HAVE_WINSOCK2_H "winsock2.h") - add_header_include(HAVE_WINSOCK_H "winsock.h") - set(EXTRA_DEFINES ${EXTRA_DEFINES} - "__unused7\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#define __unused3") - set(signature_call_conv "PASCAL") -else(HAVE_WINDOWS_H) - add_header_include(HAVE_SYS_TYPES_H "sys/types.h") - add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h") -endif(HAVE_WINDOWS_H) - -set(EXTRA_DEFINES_BACKUP "${EXTRA_DEFINES}") -set(EXTRA_DEFINES "${EXTRA_DEFINES_BACKUP}\n${headers_hack}\n${extern_line}\n#define __unused5") -curl_check_c_source_compiles("recv(0, 0, 0, 0)" curl_cv_recv) -if(curl_cv_recv) - # AC_CACHE_CHECK([types of arguments and return type for recv], - #[curl_cv_func_recv_args], [ - #SET(curl_cv_func_recv_args "unknown") - #for recv_retv in 'int' 'ssize_t'; do - if(NOT DEFINED curl_cv_func_recv_args OR "${curl_cv_func_recv_args}" STREQUAL "unknown") - foreach(recv_retv "int" "ssize_t" ) - foreach(recv_arg1 "int" "ssize_t" "SOCKET") - foreach(recv_arg2 "void *" "char *") - foreach(recv_arg3 "size_t" "int" "socklen_t" "unsigned int") - foreach(recv_arg4 "int" "unsigned int") - if(NOT curl_cv_func_recv_done) - set(curl_cv_func_recv_test "UNKNOWN") - set(extern_line "extern ${recv_retv} ${signature_call_conv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})\;") - set(EXTRA_DEFINES "${EXTRA_DEFINES_BACKUP}\n${headers_hack}\n${extern_line}\n#define __unused5") - curl_check_c_source_compiles(" - ${recv_arg1} s=0; - ${recv_arg2} buf=0; - ${recv_arg3} len=0; - ${recv_arg4} flags=0; - ${recv_retv} res = recv(s, buf, len, flags)" - curl_cv_func_recv_test - "${recv_retv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})") - if(curl_cv_func_recv_test) - set(curl_cv_func_recv_args - "${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}") - set(RECV_TYPE_ARG1 "${recv_arg1}") - set(RECV_TYPE_ARG2 "${recv_arg2}") - set(RECV_TYPE_ARG3 "${recv_arg3}") - set(RECV_TYPE_ARG4 "${recv_arg4}") - set(RECV_TYPE_RETV "${recv_retv}") - set(HAVE_RECV 1) - set(curl_cv_func_recv_done 1) - endif(curl_cv_func_recv_test) - endif(NOT curl_cv_func_recv_done) - endforeach(recv_arg4) - endforeach(recv_arg3) - endforeach(recv_arg2) - endforeach(recv_arg1) - endforeach(recv_retv) - else(NOT DEFINED curl_cv_func_recv_args OR "${curl_cv_func_recv_args}" STREQUAL "unknown") - string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG1 "${curl_cv_func_recv_args}") - string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG2 "${curl_cv_func_recv_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG3 "${curl_cv_func_recv_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" RECV_TYPE_ARG4 "${curl_cv_func_recv_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" RECV_TYPE_RETV "${curl_cv_func_recv_args}") - #MESSAGE("RECV_TYPE_ARG1 ${RECV_TYPE_ARG1}") - #MESSAGE("RECV_TYPE_ARG2 ${RECV_TYPE_ARG2}") - #MESSAGE("RECV_TYPE_ARG3 ${RECV_TYPE_ARG3}") - #MESSAGE("RECV_TYPE_ARG4 ${RECV_TYPE_ARG4}") - #MESSAGE("RECV_TYPE_RETV ${RECV_TYPE_RETV}") - endif(NOT DEFINED curl_cv_func_recv_args OR "${curl_cv_func_recv_args}" STREQUAL "unknown") - - if("${curl_cv_func_recv_args}" STREQUAL "unknown") - message(FATAL_ERROR "Cannot find proper types to use for recv args") - endif("${curl_cv_func_recv_args}" STREQUAL "unknown") -else(curl_cv_recv) - message(FATAL_ERROR "Unable to link function recv") -endif(curl_cv_recv) -set(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv") -set(HAVE_RECV 1) - -curl_check_c_source_compiles("send(0, 0, 0, 0)" curl_cv_send) -if(curl_cv_send) - # AC_CACHE_CHECK([types of arguments and return type for send], - #[curl_cv_func_send_args], [ - #SET(curl_cv_func_send_args "unknown") - #for send_retv in 'int' 'ssize_t'; do - if(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown") - foreach(send_retv "int" "ssize_t" ) - foreach(send_arg1 "int" "ssize_t" "SOCKET") - foreach(send_arg2 "const void *" "void *" "char *" "const char *") - foreach(send_arg3 "size_t" "int" "socklen_t" "unsigned int") - foreach(send_arg4 "int" "unsigned int") - if(NOT curl_cv_func_send_done) - set(curl_cv_func_send_test "UNKNOWN") - set(extern_line "extern ${send_retv} ${signature_call_conv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})\;") - set(EXTRA_DEFINES "${EXTRA_DEFINES_BACKUP}\n${headers_hack}\n${extern_line}\n#define __unused5") - curl_check_c_source_compiles(" - ${send_arg1} s=0; - ${send_arg2} buf=0; - ${send_arg3} len=0; - ${send_arg4} flags=0; - ${send_retv} res = send(s, buf, len, flags)" - curl_cv_func_send_test - "${send_retv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})") - if(curl_cv_func_send_test) - #MESSAGE("Found arguments: ${curl_cv_func_send_test}") - string(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}") - string(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}") - set(curl_cv_func_send_args - "${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}") - set(SEND_TYPE_ARG1 "${send_arg1}") - set(SEND_TYPE_ARG2 "${send_arg2}") - set(SEND_TYPE_ARG3 "${send_arg3}") - set(SEND_TYPE_ARG4 "${send_arg4}") - set(SEND_TYPE_RETV "${send_retv}") - set(HAVE_SEND 1) - set(curl_cv_func_send_done 1) - endif(curl_cv_func_send_test) - endif(NOT curl_cv_func_send_done) - endforeach(send_arg4) - endforeach(send_arg3) - endforeach(send_arg2) - endforeach(send_arg1) - endforeach(send_retv) - else(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown") - string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG1 "${curl_cv_func_send_args}") - string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG2 "${curl_cv_func_send_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG3 "${curl_cv_func_send_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG4 "${curl_cv_func_send_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" SEND_TYPE_RETV "${curl_cv_func_send_args}") - string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" SEND_QUAL_ARG2 "${curl_cv_func_send_args}") - #MESSAGE("SEND_TYPE_ARG1 ${SEND_TYPE_ARG1}") - #MESSAGE("SEND_TYPE_ARG2 ${SEND_TYPE_ARG2}") - #MESSAGE("SEND_TYPE_ARG3 ${SEND_TYPE_ARG3}") - #MESSAGE("SEND_TYPE_ARG4 ${SEND_TYPE_ARG4}") - #MESSAGE("SEND_TYPE_RETV ${SEND_TYPE_RETV}") - #MESSAGE("SEND_QUAL_ARG2 ${SEND_QUAL_ARG2}") - endif(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown") - - if("${curl_cv_func_send_args}" STREQUAL "unknown") - message(FATAL_ERROR "Cannot find proper types to use for send args") - endif("${curl_cv_func_send_args}" STREQUAL "unknown") - set(SEND_QUAL_ARG2 "const") -else(curl_cv_send) - message(FATAL_ERROR "Unable to link function send") -endif(curl_cv_send) -set(curl_cv_func_send_args "${curl_cv_func_send_args}" CACHE INTERNAL "Arguments for send") -set(HAVE_SEND 1) - -set(EXTRA_DEFINES "${EXTRA_DEFINES}\n${headers_hack}\n#define __unused5") -curl_check_c_source_compiles("int flag = MSG_NOSIGNAL" HAVE_MSG_NOSIGNAL) - -set(EXTRA_DEFINES "__unused1\n#undef inline\n#define __unused2") -set(HEADER_INCLUDES) -set(headers_hack) - -macro(add_header_include check header) - if(${check}) - set(headers_hack - "${headers_hack}\n#include <${header}>") - #SET(HEADER_INCLUDES - # ${HEADER_INCLUDES} - # "${header}") - endif(${check}) -endmacro(add_header_include header) - -if(HAVE_WINDOWS_H) - set(EXTRA_DEFINES ${EXTRA_DEFINES} - "__unused7\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#define __unused3") - add_header_include(HAVE_WINDOWS_H "windows.h") - add_header_include(HAVE_WINSOCK2_H "winsock2.h") - add_header_include(HAVE_WINSOCK_H "winsock.h") -else(HAVE_WINDOWS_H) - add_header_include(HAVE_SYS_TYPES_H "sys/types.h") - add_header_include(HAVE_SYS_TIME_H "sys/time.h") - add_header_include(TIME_WITH_SYS_TIME "time.h") - add_header_include(HAVE_TIME_H "time.h") -endif(HAVE_WINDOWS_H) -set(EXTRA_DEFINES "${EXTRA_DEFINES}\n${headers_hack}\n#define __unused5") -curl_check_c_source_compiles("struct timeval ts;\nts.tv_sec = 0;\nts.tv_usec = 0" HAVE_STRUCT_TIMEVAL) - - -include(CurlCheckCSourceRuns) -set(EXTRA_DEFINES) -set(HEADER_INCLUDES) -if(HAVE_SYS_POLL_H) - set(HEADER_INCLUDES "sys/poll.h") -endif(HAVE_SYS_POLL_H) -curl_check_c_source_runs("return poll((void *)0, 0, 10 /*ms*/)" HAVE_POLL_FINE) - -set(HAVE_SIG_ATOMIC_T 1) -set(EXTRA_DEFINES) -set(HEADER_INCLUDES) -if(HAVE_SIGNAL_H) - set(HEADER_INCLUDES "signal.h") - set(CMAKE_EXTRA_INCLUDE_FILES "signal.h") -endif(HAVE_SIGNAL_H) -check_type_size("sig_atomic_t" SIZEOF_SIG_ATOMIC_T) -if(HAVE_SIZEOF_SIG_ATOMIC_T) - curl_check_c_source_compiles("static volatile sig_atomic_t dummy = 0" HAVE_SIG_ATOMIC_T_NOT_VOLATILE) - if(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE) - set(HAVE_SIG_ATOMIC_T_VOLATILE 1) - endif(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE) -endif(HAVE_SIZEOF_SIG_ATOMIC_T) - -set(CHECK_TYPE_SIZE_PREINCLUDE - "#undef inline") - -if(HAVE_WINDOWS_H) - set(CHECK_TYPE_SIZE_PREINCLUDE "${CHECK_TYPE_SIZE_PREINCLUDE} - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #include ") - if(HAVE_WINSOCK2_H) - set(CHECK_TYPE_SIZE_PREINCLUDE "${CHECK_TYPE_SIZE_PREINCLUDE}\n#include ") - endif(HAVE_WINSOCK2_H) -else(HAVE_WINDOWS_H) - if(HAVE_SYS_SOCKET_H) - set(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} - "sys/socket.h") - endif(HAVE_SYS_SOCKET_H) - if(HAVE_NETINET_IN_H) - set(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} - "netinet/in.h") - endif(HAVE_NETINET_IN_H) - if(HAVE_ARPA_INET_H) - set(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} - "arpa/inet.h") - endif(HAVE_ARPA_INET_H) -endif(HAVE_WINDOWS_H) - -check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE) -if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE) - set(HAVE_STRUCT_SOCKADDR_STORAGE 1) -endif(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE) diff --git a/third_party/curl/CMake/Platforms/WindowsCache.cmake b/third_party/curl/CMake/Platforms/WindowsCache.cmake deleted file mode 100644 index faf6bdfb2..000000000 --- a/third_party/curl/CMake/Platforms/WindowsCache.cmake +++ /dev/null @@ -1,120 +0,0 @@ -if(NOT UNIX) - if(WIN32) - set(HAVE_LIBDL 0) - set(HAVE_LIBUCB 0) - set(HAVE_LIBSOCKET 0) - set(NOT_NEED_LIBNSL 0) - set(HAVE_LIBNSL 0) - set(HAVE_LIBZ 0) - set(HAVE_LIBCRYPTO 0) - - set(HAVE_DLOPEN 0) - - set(HAVE_ALLOCA_H 0) - set(HAVE_ARPA_INET_H 0) - set(HAVE_DLFCN_H 0) - set(HAVE_FCNTL_H 1) - set(HAVE_FEATURES_H 0) - set(HAVE_INTTYPES_H 0) - set(HAVE_IO_H 1) - set(HAVE_MALLOC_H 1) - set(HAVE_MEMORY_H 1) - set(HAVE_NETDB_H 0) - set(HAVE_NETINET_IF_ETHER_H 0) - set(HAVE_NETINET_IN_H 0) - set(HAVE_NET_IF_H 0) - set(HAVE_PROCESS_H 1) - set(HAVE_PWD_H 0) - set(HAVE_SETJMP_H 1) - set(HAVE_SGTTY_H 0) - set(HAVE_SIGNAL_H 1) - set(HAVE_SOCKIO_H 0) - set(HAVE_STDINT_H 0) - set(HAVE_STDLIB_H 1) - set(HAVE_STRINGS_H 0) - set(HAVE_STRING_H 1) - set(HAVE_SYS_PARAM_H 0) - set(HAVE_SYS_POLL_H 0) - set(HAVE_SYS_SELECT_H 0) - set(HAVE_SYS_SOCKET_H 0) - set(HAVE_SYS_SOCKIO_H 0) - set(HAVE_SYS_STAT_H 1) - set(HAVE_SYS_TIME_H 0) - set(HAVE_SYS_TYPES_H 1) - set(HAVE_SYS_UTIME_H 1) - set(HAVE_TERMIOS_H 0) - set(HAVE_TERMIO_H 0) - set(HAVE_TIME_H 1) - set(HAVE_UNISTD_H 0) - set(HAVE_UTIME_H 0) - set(HAVE_X509_H 0) - set(HAVE_ZLIB_H 0) - - set(HAVE_SIZEOF_LONG_DOUBLE 1) - set(SIZEOF_LONG_DOUBLE 8) - - set(HAVE_SOCKET 1) - set(HAVE_POLL 0) - set(HAVE_SELECT 1) - set(HAVE_STRDUP 1) - set(HAVE_STRSTR 1) - set(HAVE_STRTOK_R 0) - set(HAVE_STRFTIME 1) - set(HAVE_UNAME 0) - set(HAVE_STRCASECMP 0) - set(HAVE_STRICMP 1) - set(HAVE_STRCMPI 1) - set(HAVE_GETHOSTBYADDR 1) - set(HAVE_GETTIMEOFDAY 0) - set(HAVE_INET_ADDR 1) - set(HAVE_INET_NTOA 1) - set(HAVE_INET_NTOA_R 0) - set(HAVE_TCGETATTR 0) - set(HAVE_TCSETATTR 0) - set(HAVE_PERROR 1) - set(HAVE_CLOSESOCKET 1) - set(HAVE_SETVBUF 0) - set(HAVE_SIGSETJMP 0) - set(HAVE_GETPASS_R 0) - set(HAVE_STRLCAT 0) - set(HAVE_GETPWUID 0) - set(HAVE_GETEUID 0) - set(HAVE_UTIME 1) - set(HAVE_RAND_EGD 0) - set(HAVE_RAND_SCREEN 0) - set(HAVE_RAND_STATUS 0) - set(HAVE_GMTIME_R 0) - set(HAVE_LOCALTIME_R 0) - set(HAVE_GETHOSTBYADDR_R 0) - set(HAVE_GETHOSTBYNAME_R 0) - set(HAVE_SIGNAL_FUNC 1) - set(HAVE_SIGNAL_MACRO 0) - - set(HAVE_GETHOSTBYADDR_R_5 0) - set(HAVE_GETHOSTBYADDR_R_5_REENTRANT 0) - set(HAVE_GETHOSTBYADDR_R_7 0) - set(HAVE_GETHOSTBYADDR_R_7_REENTRANT 0) - set(HAVE_GETHOSTBYADDR_R_8 0) - set(HAVE_GETHOSTBYADDR_R_8_REENTRANT 0) - set(HAVE_GETHOSTBYNAME_R_3 0) - set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0) - set(HAVE_GETHOSTBYNAME_R_5 0) - set(HAVE_GETHOSTBYNAME_R_5_REENTRANT 0) - set(HAVE_GETHOSTBYNAME_R_6 0) - set(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0) - - set(TIME_WITH_SYS_TIME 0) - set(HAVE_O_NONBLOCK 0) - set(HAVE_IN_ADDR_T 0) - set(HAVE_INET_NTOA_R_DECL 0) - set(HAVE_INET_NTOA_R_DECL_REENTRANT 0) - set(HAVE_GETADDRINFO 0) - set(STDC_HEADERS 1) - set(RETSIGTYPE_TEST 1) - - set(HAVE_SIGACTION 0) - set(HAVE_MACRO_SIGSETJMP 0) - else(WIN32) - message("This file should be included on Windows platform only") - endif(WIN32) -endif(NOT UNIX) diff --git a/third_party/curl/CMake/Utilities.cmake b/third_party/curl/CMake/Utilities.cmake deleted file mode 100644 index 37cdfe3bf..000000000 --- a/third_party/curl/CMake/Utilities.cmake +++ /dev/null @@ -1,31 +0,0 @@ -# File containing various utilities - -# Converts a CMake list to a string containing elements separated by spaces -function(TO_LIST_SPACES _LIST_NAME OUTPUT_VAR) - set(NEW_LIST_SPACE) - foreach(ITEM ${${_LIST_NAME}}) - set(NEW_LIST_SPACE "${NEW_LIST_SPACE} ${ITEM}") - endforeach() - string(STRIP ${NEW_LIST_SPACE} NEW_LIST_SPACE) - set(${OUTPUT_VAR} "${NEW_LIST_SPACE}" PARENT_SCOPE) -endfunction() - -# Appends a lis of item to a string which is a space-separated list, if they don't already exist. -function(LIST_SPACES_APPEND_ONCE LIST_NAME) - string(REPLACE " " ";" _LIST ${${LIST_NAME}}) - list(APPEND _LIST ${ARGN}) - list(REMOVE_DUPLICATES _LIST) - to_list_spaces(_LIST NEW_LIST_SPACE) - set(${LIST_NAME} "${NEW_LIST_SPACE}" PARENT_SCOPE) -endfunction() - -# Convinience function that does the same as LIST(FIND ...) but with a TRUE/FALSE return value. -# Ex: IN_STR_LIST(MY_LIST "Searched item" WAS_FOUND) -function(IN_STR_LIST LIST_NAME ITEM_SEARCHED RETVAL) - list(FIND ${LIST_NAME} ${ITEM_SEARCHED} FIND_POS) - if(${FIND_POS} EQUAL -1) - set(${RETVAL} FALSE PARENT_SCOPE) - else() - set(${RETVAL} TRUE PARENT_SCOPE) - endif() -endfunction() diff --git a/third_party/curl/CMakeLists.txt b/third_party/curl/CMakeLists.txt deleted file mode 100644 index 07635799f..000000000 --- a/third_party/curl/CMakeLists.txt +++ /dev/null @@ -1,846 +0,0 @@ -# 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.6.2 FATAL_ERROR) -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}") -include(Utilities) - -project( CURL C ) - - -file (READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS) -string (REGEX MATCH "LIBCURL_VERSION_MAJOR[ \t]+([0-9]+)" - LIBCURL_VERSION_MJ ${CURL_VERSION_H_CONTENTS}) -string (REGEX MATCH "([0-9]+)" - LIBCURL_VERSION_MJ ${LIBCURL_VERSION_MJ}) -string (REGEX MATCH - "LIBCURL_VERSION_MINOR[ \t]+([0-9]+)" - LIBCURL_VERSION_MI ${CURL_VERSION_H_CONTENTS}) -string (REGEX MATCH "([0-9]+)" LIBCURL_VERSION_MI ${LIBCURL_VERSION_MI}) -string (REGEX MATCH - "LIBCURL_VERSION_PATCH[ \t]+([0-9]+)" - LIBCURL_VERSION_PT ${CURL_VERSION_H_CONTENTS}) -string (REGEX MATCH "([0-9]+)" LIBCURL_VERSION_PT ${LIBCURL_VERSION_PT}) -set (CURL_MAJOR_VERSION ${LIBCURL_VERSION_MJ}) -set (CURL_MINOR_VERSION ${LIBCURL_VERSION_MI}) -set (CURL_PATCH_VERSION ${LIBCURL_VERSION_PT}) - -include_regular_expression("^.*$") # Sukender: Is it necessary? - -# Setup package meta-data -# SET(PACKAGE "curl") -set(CURL_VERSION ${CURL_MAJOR_VERSION}.${CURL_MINOR_VERSION}.${CURL_PATCH_VERSION}) -message(STATUS "curl version=[${CURL_VERSION}]") -# SET(PACKAGE_TARNAME "curl") -# SET(PACKAGE_NAME "curl") -# SET(PACKAGE_VERSION "-") -# SET(PACKAGE_STRING "curl-") -# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => http://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 ) - -if(WIN32) - set(NATIVE_WINDOWS ON) -endif() - -option(CURL_STATICLIB "Set to ON to build libcurl with static linking." ON) -option(CURL_USE_ARES "Set to ON to enable c-ares support" OFF) -# initialize CURL_LIBS -set(CURL_LIBS "") - -if(CURL_USE_ARES) - set(USE_ARES ${CURL_USE_ARES}) - find_package(CARES REQUIRED) - list(APPEND CURL_LIBS ${CARES_LIBRARY} ) - set(CURL_LIBS ${CURL_LIBS} ${CARES_LIBRARY}) -endif() - -option(BUILD_DASHBOARD_REPORTS "Set to ON to activate reporting of cURL builds here http://www.cdash.org/CDashPublic/index.php?project=CURL" OFF) -if(BUILD_DASHBOARD_REPORTS) - #INCLUDE(Dart) - include(CTest) -endif(BUILD_DASHBOARD_REPORTS) - -if(MSVC) - option(BUILD_RELEASE_DEBUG_DIRS "Set OFF to build each configuration to a separate directory" OFF) - mark_as_advanced(BUILD_RELEASE_DEBUG_DIRS) -endif() - -option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON) -mark_as_advanced(CURL_HIDDEN_SYMBOLS) - -# IF(WIN32) -# OPTION(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without openssl" ON) -# MARK_AS_ADVANCED(CURL_WINDOWS_SSPI) -# ENDIF() - -option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" ON) -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) -if(WIN32) - set(CURL_DEFAULT_DISABLE_LDAP OFF) - # some windows compilers do not have wldap32 - if( NOT HAVE_WLDAP32) - set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE) - message(STATUS "wldap32 not found CURL_DISABLE_LDAP set ON") - option(CURL_LDAP_WIN "Use Windows LDAP implementation" OFF) - else() - option(CURL_LDAP_WIN "Use Windows LDAP implementation" ON) - endif() - mark_as_advanced(CURL_LDAP_WIN) -endif() - -if(HTTP_ONLY) - set(CURL_DISABLE_FTP ON) - set(CURL_DISABLE_LDAP ON) - set(CURL_DISABLE_TELNET ON) - set(CURL_DISABLE_DICT ON) - set(CURL_DISABLE_FILE ON) - set(CURL_DISABLE_TFTP 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(DISABLED_THREADSAFE "Set to explicitly specify we don't want to use thread-safe functions" OFF) -mark_as_advanced(DISABLED_THREADSAFE) -option(ENABLE_IPV6 "Define if you want to enable IPv6 support" OFF) -mark_as_advanced(ENABLE_IPV6) - -if(WIN32) - list_spaces_append_once(CMAKE_C_STANDARD_LIBRARIES wsock32.lib ws2_32.lib) # bufferoverflowu.lib - if(CURL_DISABLE_LDAP) - # Remove wldap32.lib from space-separated list - string(REPLACE " " ";" _LIST ${CMAKE_C_STANDARD_LIBRARIES}) - list(REMOVE_ITEM _LIST "wldap32.lib") - to_list_spaces(_LIST CMAKE_C_STANDARD_LIBRARIES) - else() - # Append wldap32.lib - list_spaces_append_once(CMAKE_C_STANDARD_LIBRARIES wldap32.lib) - endif() - set(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES}" CACHE STRING "" FORCE) -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}) - -# Disable warnings on Borland to avoid changing 3rd party code. -if(BORLAND) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-") -endif(BORLAND) - -# 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) - -# On windows preload settings -if(WIN32) - include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake) -endif(WIN32) - -# This macro checks if the symbol exists in the library and if it -# does, it appends library to the list. -macro(CHECK_LIBRARY_EXISTS_CONCAT LIBRARY SYMBOL VARIABLE) - check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "" - ${VARIABLE}) - if(${VARIABLE}) - set(CURL_LIBS ${CURL_LIBS} ${LIBRARY}) - endif(${VARIABLE}) -endmacro(CHECK_LIBRARY_EXISTS_CONCAT) - -# Check for all needed libraries -check_library_exists_concat("dl" dlopen HAVE_LIBDL) -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) - -if(NOT NOT_NEED_LIBNSL) - check_library_exists_concat("nsl" gethostbyname HAVE_LIBNSL) -endif(NOT NOT_NEED_LIBNSL) - -check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32) -check_library_exists_concat("winmm" getch HAVE_LIBWINMM) -check_library_exists("wldap32" cldap_open "" HAVE_WLDAP32) - -# IF(NOT CURL_SPECIAL_LIBZ) -# CHECK_LIBRARY_EXISTS_CONCAT("z" inflateEnd HAVE_LIBZ) -# ENDIF(NOT CURL_SPECIAL_LIBZ) - -option(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ON) -mark_as_advanced(CMAKE_USE_OPENSSL) -if(CMAKE_USE_OPENSSL) - if(WIN32) - find_package(OpenSSL) - if(OPENSSL_FOUND) - set(USE_SSLEAY TRUE) - set(USE_OPENSSL TRUE) - list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES} ) - else() - set(CMAKE_USE_OPENSSL FALSE) - message(STATUS "OpenSSL NOT Found, disabling CMAKE_USE_OPENSSL") - endif() - else(WIN32) - check_library_exists_concat("crypto" CRYPTO_lock HAVE_LIBCRYPTO) - check_library_exists_concat("ssl" SSL_connect HAVE_LIBSSL) - endif(WIN32) -endif(CMAKE_USE_OPENSSL) - -# Check for idn -check_library_exists_concat("idn" idna_to_ascii_lz HAVE_LIBIDN) - -# Check for LDAP -check_library_exists_concat("ldap" ldap_init HAVE_LIBLDAP) -# if(NOT HAVE_LIBLDAP) -# SET(CURL_DISABLE_LDAP ON) -# endif(NOT HAVE_LIBLDAP) - -# Check for symbol dlopen (same as HAVE_LIBDL) -check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN) - -# For other tests to use the same libraries -set(CMAKE_REQUIRED_LIBRARIES ${CURL_LIBS}) - -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) # AND CURL_CONFIG_HAS_BEEN_RUN_BEFORE - find_package(ZLIB QUIET) - if(ZLIB_FOUND) - set(HAVE_ZLIB_H ON) - set(HAVE_ZLIB ON) - set(HAVE_LIBZ ON) - endif() -endif() - -# If we have features.h, then do the _BSD_SOURCE magic -check_include_file("features.h" HAVE_FEATURES_H) - -# Check if header file exists and add it to the list. -macro(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE) - check_include_files("${CURL_INCLUDES};${FILE}" ${VARIABLE}) - if(${VARIABLE}) - set(CURL_INCLUDES ${CURL_INCLUDES} ${FILE}) - set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${VARIABLE}") - endif(${VARIABLE}) -endmacro(CHECK_INCLUDE_FILE_CONCAT) - - -# Check for header files -if(NOT UNIX) - check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H) - check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H) -endif(NOT UNIX) -check_include_file_concat("stdio.h" HAVE_STDIO_H) -if(NOT UNIX) - check_include_file_concat("windows.h" HAVE_WINDOWS_H) - check_include_file_concat("winsock.h" HAVE_WINSOCK_H) -endif(NOT UNIX) - -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("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("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) -check_include_file_concat("idn-free.h" HAVE_IDN_FREE_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("libssh2.h" HAVE_LIBSSH2_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("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H) -check_include_file_concat("openssl/engine.h" HAVE_OPENSSL_ENGINE_H) -check_include_file_concat("openssl/err.h" HAVE_OPENSSL_ERR_H) -check_include_file_concat("openssl/pem.h" HAVE_OPENSSL_PEM_H) -check_include_file_concat("openssl/pkcs12.h" HAVE_OPENSSL_PKCS12_H) -check_include_file_concat("openssl/rsa.h" HAVE_OPENSSL_RSA_H) -check_include_file_concat("openssl/ssl.h" HAVE_OPENSSL_SSL_H) -check_include_file_concat("openssl/x509.h" HAVE_OPENSSL_X509_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("tld.h" HAVE_TLD_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("ldap.h" HAVE_LDAP_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_include_file_concat("idna.h" HAVE_IDNA_H) - -if(CMAKE_USE_OPENSSL) - check_include_file_concat("openssl/rand.h" HAVE_OPENSSL_RAND_H) -endif(CMAKE_USE_OPENSSL) - -if(NOT HAVE_LDAP_H) - message(STATUS "LDAP_H not found CURL_DISABLE_LDAP set ON") - set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE) -endif() - - -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("long double" SIZEOF_LONG_DOUBLE) -check_type_size("time_t" SIZEOF_TIME_T) -if(NOT HAVE_SIZEOF_SSIZE_T) - if(SIZEOF_LONG EQUAL SIZEOF_SIZE_T) - set(ssize_t long) - endif(SIZEOF_LONG EQUAL SIZEOF_SIZE_T) - if(NOT ssize_t AND SIZEOF___INT64 EQUAL SIZEOF_SIZE_T) - set(ssize_t __int64) - endif(NOT ssize_t AND SIZEOF___INT64 EQUAL SIZEOF_SIZE_T) -endif(NOT HAVE_SIZEOF_SSIZE_T) - -# Different sizeofs, etc. - -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL - -set(CURL_SIZEOF_LONG ${SIZEOF_LONG}) - -if(SIZEOF_LONG EQUAL 8) - set(CURL_TYPEOF_CURL_OFF_T long) - set(CURL_SIZEOF_CURL_OFF_T 8) - set(CURL_FORMAT_CURL_OFF_T "ld") - set(CURL_FORMAT_CURL_OFF_TU "lu") - set(CURL_FORMAT_OFF_T "%ld") - set(CURL_SUFFIX_CURL_OFF_T L) - set(CURL_SUFFIX_CURL_OFF_TU LU) -endif(SIZEOF_LONG EQUAL 8) - -if(SIZEOF_LONG_LONG EQUAL 8) - set(CURL_TYPEOF_CURL_OFF_T "long long") - set(CURL_SIZEOF_CURL_OFF_T 8) - set(CURL_FORMAT_CURL_OFF_T "lld") - set(CURL_FORMAT_CURL_OFF_TU "llu") - set(CURL_FORMAT_OFF_T "%lld") - set(CURL_SUFFIX_CURL_OFF_T LL) - set(CURL_SUFFIX_CURL_OFF_TU LLU) -endif(SIZEOF_LONG_LONG EQUAL 8) - -if(NOT CURL_TYPEOF_CURL_OFF_T) - set(CURL_TYPEOF_CURL_OFF_T ${ssize_t}) - set(CURL_SIZEOF_CURL_OFF_T ${SIZEOF_SSIZE_T}) - # TODO: need adjustment here. - set(CURL_FORMAT_CURL_OFF_T "ld") - set(CURL_FORMAT_CURL_OFF_TU "lu") - set(CURL_FORMAT_OFF_T "%ld") - set(CURL_SUFFIX_CURL_OFF_T L) - set(CURL_SUFFIX_CURL_OFF_TU LU) -endif(NOT CURL_TYPEOF_CURL_OFF_T) - -if(HAVE_SIZEOF_LONG_LONG) - set(HAVE_LONGLONG 1) - set(HAVE_LL 1) -endif(HAVE_SIZEOF_LONG_LONG) - -find_file(RANDOM_FILE urandom /dev) -mark_as_advanced(RANDOM_FILE) - -# Check for some functions that are used -check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME) -check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET) -check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL) -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) -if(CMAKE_USE_OPENSSL) - 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) - check_symbol_exists(CRYPTO_cleanup_all_ex_data "${CURL_INCLUDES}" - HAVE_CRYPTO_CLEANUP_ALL_EX_DATA) - if(HAVE_LIBCRYPTO AND HAVE_LIBSSL) - set(USE_OPENSSL 1) - set(USE_SSLEAY 1) - endif(HAVE_LIBCRYPTO AND HAVE_LIBSSL) -endif(CMAKE_USE_OPENSSL) -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(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(idn_free "${CURL_INCLUDES}" HAVE_IDN_FREE) -check_symbol_exists(idna_strerror "${CURL_INCLUDES}" HAVE_IDNA_STRERROR) -check_symbol_exists(tld_strerror "${CURL_INCLUDES}" HAVE_TLD_STRERROR) -check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE) -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) - -# symbol exists in win32, but function does not. -check_function_exists(inet_pton HAVE_INET_PTON) - -# 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) - -# For other curl specific tests, use this macro. -macro(CURL_INTERNAL_TEST CURL_TEST) - if("${CURL_TEST}" MATCHES "^${CURL_TEST}$") - set(MACRO_CHECK_FUNCTION_DEFINITIONS - "-D${CURL_TEST} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}") - if(CMAKE_REQUIRED_LIBRARIES) - set(CURL_TEST_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") - endif(CMAKE_REQUIRED_LIBRARIES) - - message(STATUS "Performing Curl Test ${CURL_TEST}") - try_compile(${CURL_TEST} - ${CMAKE_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c - CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} - "${CURL_TEST_ADD_LIBRARIES}" - OUTPUT_VARIABLE OUTPUT) - if(${CURL_TEST}) - set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}") - message(STATUS "Performing Curl Test ${CURL_TEST} - Success") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Performing Curl Test ${CURL_TEST} passed with the following output:\n" - "${OUTPUT}\n") - else(${CURL_TEST}) - message(STATUS "Performing Curl Test ${CURL_TEST} - Failed") - set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}") - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Performing Curl Test ${CURL_TEST} failed with the following output:\n" - "${OUTPUT}\n") - endif(${CURL_TEST}) - endif("${CURL_TEST}" MATCHES "^${CURL_TEST}$") -endmacro(CURL_INTERNAL_TEST) - -macro(CURL_INTERNAL_TEST_RUN CURL_TEST) - if("${CURL_TEST}_COMPILE" MATCHES "^${CURL_TEST}_COMPILE$") - set(MACRO_CHECK_FUNCTION_DEFINITIONS - "-D${CURL_TEST} ${CMAKE_REQUIRED_FLAGS}") - if(CMAKE_REQUIRED_LIBRARIES) - set(CURL_TEST_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") - endif(CMAKE_REQUIRED_LIBRARIES) - - message(STATUS "Performing Curl Test ${CURL_TEST}") - try_run(${CURL_TEST} ${CURL_TEST}_COMPILE - ${CMAKE_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c - CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} - "${CURL_TEST_ADD_LIBRARIES}" - OUTPUT_VARIABLE OUTPUT) - if(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST}) - set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}") - message(STATUS "Performing Curl Test ${CURL_TEST} - Success") - else(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST}) - message(STATUS "Performing Curl Test ${CURL_TEST} - Failed") - set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}") - file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log" - "Performing Curl Test ${CURL_TEST} failed with the following output:\n" - "${OUTPUT}") - if(${CURL_TEST}_COMPILE) - file(APPEND - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log" - "There was a problem running this test\n") - endif(${CURL_TEST}_COMPILE) - file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log" - "\n\n") - endif(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST}) - endif("${CURL_TEST}_COMPILE" MATCHES "^${CURL_TEST}_COMPILE$") -endmacro(CURL_INTERNAL_TEST_RUN) - -# 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) -endif(HAVE_FILE_OFFSET_BITS) -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) - -if(_FILE_OFFSET_BITS) - set(_FILE_OFFSET_BITS 64) -endif(_FILE_OFFSET_BITS) -set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64") -set(CMAKE_EXTRA_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/curl/curl.h") -check_type_size("curl_off_t" SIZEOF_CURL_OFF_T) -set(CMAKE_EXTRA_INCLUDE_FILES) -set(CMAKE_REQUIRED_FLAGS) - - -# 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_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_TYPEOF_CURL_SOCKLEN_T int) - set(CURL_SIZEOF_CURL_SOCKLEN_T ${SIZEOF_INT}) -endif() - -include(CMake/OtherTests.cmake) - -add_definitions(-DHAVE_CONFIG_H) - -# For windows, do not allow the compiler to use default target (Vista). -if(WIN32) - add_definitions(-D_WIN32_WINNT=0x0501) -endif(WIN32) - -if(MSVC) - add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) -endif(MSVC) - -# Sets up the dependencies (zlib, OpenSSL, etc.) of a cURL subproject according to options. -# TODO This is far to be complete! -function(SETUP_CURL_DEPENDENCIES TARGET_NAME) - if(CURL_ZLIB AND ZLIB_FOUND) - include_directories(${ZLIB_INCLUDE_DIR}) - endif() - if(CURL_ZLIB AND ZLIB_FOUND) - target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) - #ADD_DEFINITIONS( -DHAVE_ZLIB_H -DHAVE_ZLIB -DHAVE_LIBZ ) - endif() - - if(CMAKE_USE_OPENSSL AND OPENSSL_FOUND) - include_directories(${OPENSSL_INCLUDE_DIR}) - endif() - if(CMAKE_USE_OPENSSL AND CURL_CONFIG_HAS_BEEN_RUN_BEFORE) - target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES}) - #ADD_DEFINITIONS( -DUSE_SSLEAY ) - endif() -endfunction() - -# 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() - -add_subdirectory(lib) - -# 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() diff --git a/third_party/curl/COPYING b/third_party/curl/COPYING deleted file mode 100644 index 1bd3e929b..000000000 --- a/third_party/curl/COPYING +++ /dev/null @@ -1,21 +0,0 @@ -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1996 - 2011, Daniel Stenberg, . - -All rights reserved. - -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", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN -NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall not -be used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization of the copyright holder. diff --git a/third_party/curl/README b/third_party/curl/README deleted file mode 100644 index 2ffacc32c..000000000 --- a/third_party/curl/README +++ /dev/null @@ -1,49 +0,0 @@ - _ _ ____ _ - ___| | | | _ \| | - / __| | | | |_) | | - | (__| |_| | _ <| |___ - \___|\___/|_| \_\_____| - -README - - Curl is a command line tool for transferring data specified with URL - syntax. Find out how to use curl by reading the curl.1 man page or the - MANUAL document. Find out how to install Curl by reading the INSTALL - document. - - libcurl is the library curl is using to do its job. It is readily - available to be used by your software. Read the libcurl.3 man page to - learn how! - - You find answers to the most frequent questions we get in the FAQ document. - - Study the COPYING file for distribution terms and similar. If you distribute - curl binaries or other binaries that involve libcurl, you might enjoy the - LICENSE-MIXING document. - -CONTACT - - If you have problems, questions, ideas or suggestions, please contact us - by posting to a suitable mailing list. See http://curl.haxx.se/mail/ - - All contributors to the project are listed in the THANKS document. - -WEB SITE - - Visit the curl web site for the latest news and downloads: - - http://curl.haxx.se/ - -GIT - - To download the very latest source off the GIT server do this: - - git clone git://github.com/bagder/curl.git - - (you'll get a directory named curl created, filled with the source code) - -NOTICE - - Curl contains pieces of source code that is Copyright (c) 1998, 1999 - Kungliga Tekniska Högskolan. This notice is included here to comply with the - distribution terms. diff --git a/third_party/curl/RELEASE-NOTES b/third_party/curl/RELEASE-NOTES deleted file mode 100644 index 7c3866ee1..000000000 --- a/third_party/curl/RELEASE-NOTES +++ /dev/null @@ -1,32 +0,0 @@ -Curl and libcurl 7.21.6 - - Public curl releases: 122 - Command line options: 144 - curl_easy_setopt() options: 186 - Public functions in libcurl: 58 - Known libcurl bindings: 39 - Contributors: 865 - -This release includes the following changes: - - o Added --tr-encoding and CURLOPT_TRANSFER_ENCODING - -This release includes the following bugfixes: - - o curl-config: fix --version - o curl_easy_setopt.3: CURLOPT_PROXYTYPE clarification - o use HTTPS properly after CONNECT - o SFTP: close file before post quote operations - -This release includes the following known bugs: - - o see docs/KNOWN_BUGS (http://curl.haxx.se/docs/knownbugs.html) - -This release would not have looked like this without help, code, reports and -advice from friends like these: - - Patrick Monnerat, Dan Fandrich, Gisle Vanem, Guenter Knauf, - Rajesh Naganathan, Josue Andrade Gomes, Ryan Schmidt, Fabian Keil, - Julien Chaffraix - - Thanks! (and sorry if I forgot to mention someone) diff --git a/third_party/curl/include/README b/third_party/curl/include/README deleted file mode 100644 index 3e52a1d0a..000000000 --- a/third_party/curl/include/README +++ /dev/null @@ -1,55 +0,0 @@ - _ _ ____ _ - ___| | | | _ \| | - / __| | | | |_) | | - | (__| |_| | _ <| |___ - \___|\___/|_| \_\_____| - -Include files for libcurl, external users. - -They're all placed in the curl subdirectory here for better fit in any kind -of environment. You must include files from here using... - - #include - -... style and point the compiler's include path to the directory holding the -curl subdirectory. It makes it more likely to survive future modifications. - -NOTE FOR LIBCURL HACKERS - -The following notes apply to libcurl version 7.19.0 and later. - -* The distributed curl/curlbuild.h file is only intended to be used on systems - which can not run the also distributed configure script. - -* The distributed curlbuild.h file is generated as a copy of curlbuild.h.dist - when the libcurl source code distribution archive file is originally created. - -* If you check out from git on a non-configure platform, you must run the - appropriate buildconf* script to set up curlbuild.h and other local files - before being able of compiling the library. - -* On systems capable of running the configure script, the configure process - will overwrite the distributed include/curl/curlbuild.h file with one that - is suitable and specific to the library being configured and built, which - is generated from the include/curl/curlbuild.h.in template file. - -* If you intend to distribute an already compiled libcurl library you _MUST_ - also distribute along with it the generated curl/curlbuild.h which has been - used to compile it. Otherwise the library will be of no use for the users of - the library that you have built. It is _your_ responsibility to provide this - file. No one at the cURL project can know how you have built the library. - -* File curl/curlbuild.h includes platform and configuration dependent info, - and must not be modified by anyone. Configure script generates it for you. - -* We cannot assume anything else but very basic compiler features being - present. While libcurl requires an ANSI C compiler to build, some of the - earlier ANSI compilers clearly can't deal with some preprocessor operators. - -* Newlines must remain unix-style for older compilers' sake. - -* Comments must be written in the old-style /* unnested C-fashion */ - -To figure out how to do good and portable checks for features, operating -systems or specific hardwarare, a very good resource is Bjorn Reese's -collection at http://predef.sf.net/ diff --git a/third_party/curl/include/curl/curl.h b/third_party/curl/include/curl/curl.h deleted file mode 100644 index ee9754da8..000000000 --- a/third_party/curl/include/curl/curl.h +++ /dev/null @@ -1,2166 +0,0 @@ -#ifndef __CURL_CURL_H -#define __CURL_CURL_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * If you have libcurl problems, all docs and details are found here: - * http://curl.haxx.se/libcurl/ - * - * curl-library mailing list subscription and unsubscription web interface: - * http://cool.haxx.se/mailman/listinfo/curl-library/ - */ - -#include "curlver.h" /* libcurl version defines */ -#include "curlbuild.h" /* libcurl build definitions */ -#include "curlrules.h" /* libcurl rules enforcement */ - -/* - * Define WIN32 when build target is Win32 API - */ - -#if (defined(_WIN32) || defined(__WIN32__)) && \ - !defined(WIN32) && !defined(__SYMBIAN32__) -#define WIN32 -#endif - -#include -#include - -#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) -/* Needed for __FreeBSD_version symbol definition */ -#include -#endif - -/* The include stuff here below is mainly for time_t! */ -#include -#include - -#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__GNUC__) && \ - !defined(__CYGWIN__) || defined(__MINGW32__) -#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H)) -/* The check above prevents the winsock2 inclusion if winsock.h already was - included, since they can't co-exist without problems */ -#include -#include -#endif -#else - -/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish - libc5-based Linux systems. Only include it on system that are known to - require it! */ -#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ - defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ - defined(ANDROID) || \ - (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) -#include -#endif - -#ifndef _WIN32_WCE -#include -#endif -#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) -#include -#endif -#include -#endif - -#ifdef __BEOS__ -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void CURL; - -/* - * Decorate exportable functions for Win32 and Symbian OS DLL linking. - * This avoids using a .def file for building libcurl.dll. - */ -#if (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) && \ - !defined(CURL_STATICLIB) -#if defined(BUILDING_LIBCURL) -#define CURL_EXTERN __declspec(dllexport) -#else -#define CURL_EXTERN __declspec(dllimport) -#endif -#else - -#ifdef CURL_HIDDEN_SYMBOLS -/* - * This definition is used to make external definitions visible in the - * shared library when symbols are hidden by default. It makes no - * difference when compiling applications whether this is set or not, - * only when compiling the library. - */ -#define CURL_EXTERN CURL_EXTERN_SYMBOL -#else -#define CURL_EXTERN -#endif -#endif - -#ifndef curl_socket_typedef -/* socket typedef */ -#ifdef WIN32 -typedef SOCKET curl_socket_t; -#define CURL_SOCKET_BAD INVALID_SOCKET -#else -typedef int curl_socket_t; -#define CURL_SOCKET_BAD -1 -#endif -#define curl_socket_typedef -#endif /* curl_socket_typedef */ - -struct curl_httppost { - struct curl_httppost *next; /* next entry in the list */ - char *name; /* pointer to allocated name */ - long namelength; /* length of name length */ - char *contents; /* pointer to allocated data contents */ - long contentslength; /* length of contents field */ - char *buffer; /* pointer to allocated buffer contents */ - long bufferlength; /* length of buffer field */ - char *contenttype; /* Content-Type */ - struct curl_slist* contentheader; /* list of extra headers for this form */ - struct curl_httppost *more; /* if one field name has more than one - file, this link should link to following - files */ - long flags; /* as defined below */ -#define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */ -#define HTTPPOST_READFILE (1<<1) /* specified content is a file name */ -#define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer - do not free in formfree */ -#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer - do not free in formfree */ -#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */ -#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */ -#define HTTPPOST_CALLBACK (1<<6) /* upload file contents by using the - regular read callback to get the data - and pass the given pointer as custom - pointer */ - - char *showfilename; /* The file name to show. If not set, the - actual file name will be used (if this - is a file part) */ - void *userp; /* custom pointer used for - HTTPPOST_CALLBACK posts */ -}; - -typedef int (*curl_progress_callback)(void *clientp, - double dltotal, - double dlnow, - double ultotal, - double ulnow); - -#ifndef CURL_MAX_WRITE_SIZE - /* Tests have proven that 20K is a very bad buffer size for uploads on - Windows, while 16K for some odd reason performed a lot better. - We do the ifndef check to allow this value to easier be changed at build - time for those who feel adventurous. The practical minimum is about - 400 bytes since libcurl uses a buffer of this size as a scratch area - (unrelated to network send operations). */ -#define CURL_MAX_WRITE_SIZE 16384 -#endif - -#ifndef CURL_MAX_HTTP_HEADER -/* The only reason to have a max limit for this is to avoid the risk of a bad - server feeding libcurl with a never-ending header that will cause reallocs - infinitely */ -#define CURL_MAX_HTTP_HEADER (100*1024) -#endif - - -/* This is a magic return code for the write callback that, when returned, - will signal libcurl to pause receiving on the current transfer. */ -#define CURL_WRITEFUNC_PAUSE 0x10000001 -typedef size_t (*curl_write_callback)(char *buffer, - size_t size, - size_t nitems, - void *outstream); - - - -/* enumeration of file types */ -typedef enum { - CURLFILETYPE_FILE = 0, - CURLFILETYPE_DIRECTORY, - CURLFILETYPE_SYMLINK, - CURLFILETYPE_DEVICE_BLOCK, - CURLFILETYPE_DEVICE_CHAR, - CURLFILETYPE_NAMEDPIPE, - CURLFILETYPE_SOCKET, - CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ - - CURLFILETYPE_UNKNOWN /* should never occur */ -} curlfiletype; - -#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) -#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) -#define CURLFINFOFLAG_KNOWN_TIME (1<<2) -#define CURLFINFOFLAG_KNOWN_PERM (1<<3) -#define CURLFINFOFLAG_KNOWN_UID (1<<4) -#define CURLFINFOFLAG_KNOWN_GID (1<<5) -#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) -#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) - -/* Content of this structure depends on information which is known and is - achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man - page for callbacks returning this structure -- some fields are mandatory, - some others are optional. The FLAG field has special meaning. */ -struct curl_fileinfo { - char *filename; - curlfiletype filetype; - time_t time; - unsigned int perm; - int uid; - int gid; - curl_off_t size; - long int hardlinks; - - struct { - /* If some of these fields is not NULL, it is a pointer to b_data. */ - char *time; - char *perm; - char *user; - char *group; - char *target; /* pointer to the target filename of a symlink */ - } strings; - - unsigned int flags; - - /* used internally */ - char * b_data; - size_t b_size; - size_t b_used; -}; - -/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ -#define CURL_CHUNK_BGN_FUNC_OK 0 -#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ -#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ - -/* if splitting of data transfer is enabled, this callback is called before - download of an individual chunk started. Note that parameter "remains" works - only for FTP wildcard downloading (for now), otherwise is not used */ -typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, - void *ptr, - int remains); - -/* return codes for CURLOPT_CHUNK_END_FUNCTION */ -#define CURL_CHUNK_END_FUNC_OK 0 -#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ - -/* If splitting of data transfer is enabled this callback is called after - download of an individual chunk finished. - Note! After this callback was set then it have to be called FOR ALL chunks. - Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. - This is the reason why we don't need "transfer_info" parameter in this - callback and we are not interested in "remains" parameter too. */ -typedef long (*curl_chunk_end_callback)(void *ptr); - -/* return codes for FNMATCHFUNCTION */ -#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ -#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */ -#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ - -/* callback type for wildcard downloading pattern matching. If the - string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ -typedef int (*curl_fnmatch_callback)(void *ptr, - const char *pattern, - const char *string); - -/* These are the return codes for the seek callbacks */ -#define CURL_SEEKFUNC_OK 0 -#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ -#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so - libcurl might try other means instead */ -typedef int (*curl_seek_callback)(void *instream, - curl_off_t offset, - int origin); /* 'whence' */ - -/* This is a return code for the read callback that, when returned, will - signal libcurl to immediately abort the current transfer. */ -#define CURL_READFUNC_ABORT 0x10000000 -/* This is a return code for the read callback that, when returned, will - signal libcurl to pause sending data on the current transfer. */ -#define CURL_READFUNC_PAUSE 0x10000001 - -typedef size_t (*curl_read_callback)(char *buffer, - size_t size, - size_t nitems, - void *instream); - -typedef enum { - CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ - CURLSOCKTYPE_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 enum { - CURLIOE_OK, /* I/O operation successful */ - CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ - CURLIOE_FAILRESTART, /* failed to restart the read */ - CURLIOE_LAST /* never use */ -} curlioerr; - -typedef enum { - CURLIOCMD_NOP, /* no operation */ - CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ - CURLIOCMD_LAST /* never use */ -} curliocmd; - -typedef curlioerr (*curl_ioctl_callback)(CURL *handle, - int cmd, - void *clientp); - -/* - * The following typedef's are signatures of malloc, free, realloc, strdup and - * calloc respectively. Function pointers of these types can be passed to the - * curl_global_init_mem() function to set user defined memory management - * callback routines. - */ -typedef void *(*curl_malloc_callback)(size_t size); -typedef void (*curl_free_callback)(void *ptr); -typedef void *(*curl_realloc_callback)(void *ptr, size_t size); -typedef char *(*curl_strdup_callback)(const char *str); -typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); - -/* the kind of data that is passed to information_callback*/ -typedef enum { - CURLINFO_TEXT = 0, - CURLINFO_HEADER_IN, /* 1 */ - CURLINFO_HEADER_OUT, /* 2 */ - CURLINFO_DATA_IN, /* 3 */ - CURLINFO_DATA_OUT, /* 4 */ - CURLINFO_SSL_DATA_IN, /* 5 */ - CURLINFO_SSL_DATA_OUT, /* 6 */ - CURLINFO_END -} curl_infotype; - -typedef int (*curl_debug_callback) - (CURL *handle, /* the handle/transfer this concerns */ - curl_infotype type, /* what kind of data */ - char *data, /* points to the data */ - size_t size, /* size of the data pointed to */ - void *userptr); /* whatever the user please */ - -/* All possible error codes from all sorts of curl functions. Future versions - may return other values, stay prepared. - - Always add new return codes last. Never *EVER* remove any. The return - codes must remain the same! - */ - -typedef enum { - CURLE_OK = 0, - CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ - CURLE_FAILED_INIT, /* 2 */ - CURLE_URL_MALFORMAT, /* 3 */ - CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for - 7.17.0, reused in April 2011 for 7.21.5] */ - CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ - CURLE_COULDNT_RESOLVE_HOST, /* 6 */ - CURLE_COULDNT_CONNECT, /* 7 */ - CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */ - CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server - due to lack of access - when login fails - this is not returned. */ - CURLE_OBSOLETE10, /* 10 - NOT USED */ - CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ - CURLE_OBSOLETE12, /* 12 - NOT USED */ - CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ - CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ - CURLE_FTP_CANT_GET_HOST, /* 15 */ - CURLE_OBSOLETE16, /* 16 - NOT USED */ - CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ - CURLE_PARTIAL_FILE, /* 18 */ - CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ - CURLE_OBSOLETE20, /* 20 - NOT USED */ - CURLE_QUOTE_ERROR, /* 21 - quote command failure */ - CURLE_HTTP_RETURNED_ERROR, /* 22 */ - CURLE_WRITE_ERROR, /* 23 */ - CURLE_OBSOLETE24, /* 24 - NOT USED */ - CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ - CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ - CURLE_OUT_OF_MEMORY, /* 27 */ - /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error - instead of a memory allocation error if CURL_DOES_CONVERSIONS - is defined - */ - CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ - CURLE_OBSOLETE29, /* 29 - NOT USED */ - CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ - CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ - CURLE_OBSOLETE32, /* 32 - NOT USED */ - CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ - CURLE_HTTP_POST_ERROR, /* 34 */ - CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ - CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ - CURLE_FILE_COULDNT_READ_FILE, /* 37 */ - CURLE_LDAP_CANNOT_BIND, /* 38 */ - CURLE_LDAP_SEARCH_FAILED, /* 39 */ - CURLE_OBSOLETE40, /* 40 - NOT USED */ - CURLE_FUNCTION_NOT_FOUND, /* 41 */ - CURLE_ABORTED_BY_CALLBACK, /* 42 */ - CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ - CURLE_OBSOLETE44, /* 44 - NOT USED */ - CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ - CURLE_OBSOLETE46, /* 46 - NOT USED */ - CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */ - CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ - CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */ - CURLE_OBSOLETE50, /* 50 - NOT USED */ - CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint - wasn't verified fine */ - CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ - CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ - CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as - default */ - CURLE_SEND_ERROR, /* 55 - failed sending network data */ - CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ - CURLE_OBSOLETE57, /* 57 - NOT IN USE */ - CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ - CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ - CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */ - CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ - CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ - CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ - CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ - CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind - that failed */ - CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ - CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not - accepted and we failed to login */ - CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ - CURLE_TFTP_PERM, /* 69 - permission problem on server */ - CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ - CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ - CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ - CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ - CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ - CURLE_CONV_FAILED, /* 75 - conversion failed */ - CURLE_CONV_REQD, /* 76 - caller must register conversion - callbacks using curl_easy_setopt options - CURLOPT_CONV_FROM_NETWORK_FUNCTION, - CURLOPT_CONV_TO_NETWORK_FUNCTION, and - CURLOPT_CONV_FROM_UTF8_FUNCTION */ - CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing - or wrong format */ - CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ - CURLE_SSH, /* 79 - error from the SSH layer, somewhat - generic so the error message will be of - interest when this has happened */ - - CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL - connection */ - CURLE_AGAIN, /* 81 - socket is not ready for send/recv, - wait till it's ready and try again (Added - in 7.18.2) */ - CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or - wrong format (Added in 7.19.0) */ - CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in - 7.19.0) */ - CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ - CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ - CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Identifiers */ - CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ - CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ - - CURL_LAST /* never use! */ -} CURLcode; - -#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all - the obsolete stuff removed! */ - -/* compatibility with older names */ -#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING - -/* The following were added in 7.21.5, April 2011 */ -#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION - -/* The following were added in 7.17.1 */ -/* These are scheduled to disappear by 2009 */ -#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION - -/* The following were added in 7.17.0 */ -/* These are scheduled to disappear by 2009 */ -#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ -#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 -#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 -#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 -#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 -#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 -#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 -#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 -#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 -#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 -#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 -#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 -#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN - -#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED -#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE -#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR -#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL -#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS -#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR -#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED - -/* The following were added earlier */ - -#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT - -#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR -#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED -#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED - -#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE -#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME - -/* This was the error code 50 in 7.7.3 and a few earlier versions, this - is no longer used by libcurl but is instead #defined here only to not - make programs break */ -#define CURLE_ALREADY_COMPLETE 99999 - -#endif /*!CURL_NO_OLDIES*/ - -/* This prototype applies to all conversion callbacks */ -typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); - -typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ - void *ssl_ctx, /* actually an - OpenSSL SSL_CTX */ - void *userptr); - -typedef enum { - CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use - CONNECT HTTP/1.1 */ - CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT - HTTP/1.0 */ - CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already - in 7.10 */ - CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ - CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ - CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the - host name rather than the IP address. added - in 7.18.0 */ -} curl_proxytype; /* this enum was added in 7.10 */ - -#define CURLAUTH_NONE 0 /* nothing */ -#define CURLAUTH_BASIC (1<<0) /* Basic (default) */ -#define CURLAUTH_DIGEST (1<<1) /* Digest */ -#define CURLAUTH_GSSNEGOTIATE (1<<2) /* GSS-Negotiate */ -#define CURLAUTH_NTLM (1<<3) /* NTLM */ -#define CURLAUTH_DIGEST_IE (1<<4) /* Digest with IE flavour */ -#define CURLAUTH_ONLY (1<<31) /* used together with a single other - type to force no auth or just that - single type */ -#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) /* all fine types set */ -#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_DEFAULT CURLSSH_AUTH_ANY - -#define CURL_ERROR_SIZE 256 - -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 type { - CURLKHTYPE_UNKNOWN, - CURLKHTYPE_RSA1, - CURLKHTYPE_RSA, - CURLKHTYPE_DSS - } 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; - -#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; - -/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ -#define CURLPROTO_HTTP (1<<0) -#define CURLPROTO_HTTPS (1<<1) -#define CURLPROTO_FTP (1<<2) -#define CURLPROTO_FTPS (1<<3) -#define CURLPROTO_SCP (1<<4) -#define CURLPROTO_SFTP (1<<5) -#define CURLPROTO_TELNET (1<<6) -#define CURLPROTO_LDAP (1<<7) -#define CURLPROTO_LDAPS (1<<8) -#define CURLPROTO_DICT (1<<9) -#define CURLPROTO_FILE (1<<10) -#define CURLPROTO_TFTP (1<<11) -#define CURLPROTO_IMAP (1<<12) -#define CURLPROTO_IMAPS (1<<13) -#define CURLPROTO_POP3 (1<<14) -#define CURLPROTO_POP3S (1<<15) -#define CURLPROTO_SMTP (1<<16) -#define CURLPROTO_SMTPS (1<<17) -#define CURLPROTO_RTSP (1<<18) -#define CURLPROTO_RTMP (1<<19) -#define CURLPROTO_RTMPT (1<<20) -#define CURLPROTO_RTMPE (1<<21) -#define CURLPROTO_RTMPTE (1<<22) -#define CURLPROTO_RTMPS (1<<23) -#define CURLPROTO_RTMPTS (1<<24) -#define CURLPROTO_GOPHER (1<<25) -#define CURLPROTO_ALL (~0) /* enable everything */ - -/* long may be 32 or 64 bits, but we should never depend on anything else - but 32 */ -#define CURLOPTTYPE_LONG 0 -#define CURLOPTTYPE_OBJECTPOINT 10000 -#define CURLOPTTYPE_FUNCTIONPOINT 20000 -#define CURLOPTTYPE_OFF_T 30000 - -/* name is uppercase CURLOPT_, - type is one of the defined CURLOPTTYPE_ - number is unique identifier */ -#ifdef CINIT -#undef CINIT -#endif - -#ifdef CURL_ISOCPP -#define CINIT(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number -#else -/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ -#define LONG CURLOPTTYPE_LONG -#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT -#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT -#define OFF_T CURLOPTTYPE_OFF_T -#define CINIT(name,type,number) CURLOPT_/**/name = type + number -#endif - -/* - * This macro-mania below setups the CURLOPT_[what] enum, to be used with - * curl_easy_setopt(). The first argument in the CINIT() macro is the [what] - * word. - */ - -typedef enum { - /* This is the FILE * or void * the regular output should be written to. */ - CINIT(FILE, OBJECTPOINT, 1), - - /* The full URL to get/put */ - CINIT(URL, OBJECTPOINT, 2), - - /* Port number to connect to, if other than default. */ - CINIT(PORT, LONG, 3), - - /* Name of proxy to use. */ - CINIT(PROXY, OBJECTPOINT, 4), - - /* "name:password" to use when fetching. */ - CINIT(USERPWD, OBJECTPOINT, 5), - - /* "name:password" to use with proxy. */ - CINIT(PROXYUSERPWD, OBJECTPOINT, 6), - - /* Range to get, specified as an ASCII string. */ - CINIT(RANGE, OBJECTPOINT, 7), - - /* not used */ - - /* Specified file stream to upload from (use as input): */ - CINIT(INFILE, OBJECTPOINT, 9), - - /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE - * bytes big. If this is not used, error messages go to stderr instead: */ - CINIT(ERRORBUFFER, OBJECTPOINT, 10), - - /* Function that will be called to store the output (instead of fwrite). The - * parameters will use fwrite() syntax, make sure to follow them. */ - CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11), - - /* Function that will be called to read the input (instead of fread). The - * parameters will use fread() syntax, make sure to follow them. */ - CINIT(READFUNCTION, FUNCTIONPOINT, 12), - - /* Time-out the read operation after this amount of seconds */ - CINIT(TIMEOUT, LONG, 13), - - /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about - * how large the file being sent really is. That allows better error - * checking and better verifies that the upload was successful. -1 means - * unknown size. - * - * For large file support, there is also a _LARGE version of the key - * which takes an off_t type, allowing platforms with larger off_t - * sizes to handle larger files. See below for INFILESIZE_LARGE. - */ - CINIT(INFILESIZE, LONG, 14), - - /* POST static input fields. */ - CINIT(POSTFIELDS, OBJECTPOINT, 15), - - /* Set the referrer page (needed by some CGIs) */ - CINIT(REFERER, OBJECTPOINT, 16), - - /* Set the FTP PORT string (interface name, named or numerical IP address) - Use i.e '-' to use default address. */ - CINIT(FTPPORT, OBJECTPOINT, 17), - - /* Set the User-Agent string (examined by some CGIs) */ - CINIT(USERAGENT, OBJECTPOINT, 18), - - /* If the download receives less than "low speed limit" bytes/second - * during "low speed time" seconds, the operations is aborted. - * You could i.e if you have a pretty high speed connection, abort if - * it is less than 2000 bytes/sec during 20 seconds. - */ - - /* Set the "low speed limit" */ - CINIT(LOW_SPEED_LIMIT, LONG, 19), - - /* Set the "low speed time" */ - CINIT(LOW_SPEED_TIME, LONG, 20), - - /* Set the continuation offset. - * - * Note there is also a _LARGE version of this key which uses - * off_t types, allowing for large file offsets on platforms which - * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. - */ - CINIT(RESUME_FROM, LONG, 21), - - /* Set cookie in request: */ - CINIT(COOKIE, OBJECTPOINT, 22), - - /* This points to a linked list of headers, struct curl_slist kind */ - CINIT(HTTPHEADER, OBJECTPOINT, 23), - - /* This points to a linked list of post entries, struct curl_httppost */ - CINIT(HTTPPOST, OBJECTPOINT, 24), - - /* name of the file keeping your private SSL-certificate */ - CINIT(SSLCERT, OBJECTPOINT, 25), - - /* password for the SSL or SSH private key */ - CINIT(KEYPASSWD, OBJECTPOINT, 26), - - /* send TYPE parameter? */ - CINIT(CRLF, LONG, 27), - - /* send linked-list of QUOTE commands */ - CINIT(QUOTE, OBJECTPOINT, 28), - - /* send FILE * or void * to store headers to, if you use a callback it - is simply passed to the callback unmodified */ - CINIT(WRITEHEADER, OBJECTPOINT, 29), - - /* point to a file to read the initial cookies from, also enables - "cookie awareness" */ - CINIT(COOKIEFILE, OBJECTPOINT, 31), - - /* What version to specifically try to use. - See CURL_SSLVERSION defines below. */ - CINIT(SSLVERSION, LONG, 32), - - /* What kind of HTTP time condition to use, see defines */ - CINIT(TIMECONDITION, LONG, 33), - - /* Time to use with the above condition. Specified in number of seconds - since 1 Jan 1970 */ - CINIT(TIMEVALUE, LONG, 34), - - /* 35 = OBSOLETE */ - - /* Custom request, for customizing the get command like - HTTP: DELETE, TRACE and others - FTP: to use a different list command - */ - CINIT(CUSTOMREQUEST, OBJECTPOINT, 36), - - /* HTTP request, for odd commands like DELETE, TRACE and others */ - CINIT(STDERR, OBJECTPOINT, 37), - - /* 38 is not used */ - - /* send linked-list of post-transfer QUOTE commands */ - CINIT(POSTQUOTE, OBJECTPOINT, 39), - - /* Pass a pointer to string of the output using full variable-replacement - as described elsewhere. */ - CINIT(WRITEINFO, OBJECTPOINT, 40), - - CINIT(VERBOSE, LONG, 41), /* talk a lot */ - CINIT(HEADER, LONG, 42), /* throw the header out too */ - CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */ - CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */ - CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 300 */ - CINIT(UPLOAD, LONG, 46), /* this is an upload */ - CINIT(POST, LONG, 47), /* HTTP POST method */ - CINIT(DIRLISTONLY, LONG, 48), /* return 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 */ - - /* 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 progress callback */ - CINIT(PROGRESSDATA, OBJECTPOINT, 57), - - /* We want the referrer field set automatically when following locations */ - CINIT(AUTOREFERER, LONG, 58), - - /* Port of the proxy, can be set in the proxy string as well with: - "[host]:[port]" */ - CINIT(PROXYPORT, LONG, 59), - - /* size of the POST input data, if strlen() is not good to use */ - CINIT(POSTFIELDSIZE, LONG, 60), - - /* tunnel non-http operations through a HTTP proxy */ - CINIT(HTTPPROXYTUNNEL, LONG, 61), - - /* Set the interface string to use as outgoing network interface */ - CINIT(INTERFACE, OBJECTPOINT, 62), - - /* Set the krb4/5 security level, this also enables krb4/5 awareness. This - * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string - * is set but doesn't match one of these, 'private' will be used. */ - CINIT(KRBLEVEL, OBJECTPOINT, 63), - - /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ - CINIT(SSL_VERIFYPEER, LONG, 64), - - /* The CApath or CAfile used to validate the peer certificate - this option is used only if SSL_VERIFYPEER is true */ - CINIT(CAINFO, OBJECTPOINT, 65), - - /* 66 = OBSOLETE */ - /* 67 = OBSOLETE */ - - /* Maximum number of http redirects to follow */ - CINIT(MAXREDIRS, LONG, 68), - - /* Pass a long set to 1 to get the date of the requested document (if - possible)! Pass a zero to shut it off. */ - CINIT(FILETIME, LONG, 69), - - /* This points to a linked list of telnet options */ - CINIT(TELNETOPTIONS, OBJECTPOINT, 70), - - /* Max amount of cached alive connections */ - CINIT(MAXCONNECTS, LONG, 71), - - /* What policy to use when closing connections when the cache is filled - up */ - CINIT(CLOSEPOLICY, LONG, 72), - - /* 73 = OBSOLETE */ - - /* Set to explicitly use a new connection for the upcoming transfer. - Do not use this unless you're absolutely sure of this, as it makes the - operation slower and is less friendly for the network. */ - CINIT(FRESH_CONNECT, LONG, 74), - - /* Set to explicitly forbid the upcoming transfer's connection to be re-used - when done. Do not use this unless you're absolutely sure of this, as it - makes the operation slower and is less friendly for the network. */ - CINIT(FORBID_REUSE, LONG, 75), - - /* Set to a file name that contains random data for libcurl to use to - seed the random engine when doing SSL connects. */ - CINIT(RANDOM_FILE, OBJECTPOINT, 76), - - /* Set to the Entropy Gathering Daemon socket pathname */ - CINIT(EGDSOCKET, OBJECTPOINT, 77), - - /* Time-out connect operations after this amount of seconds, if connects - are OK within this time, then fine... This only aborts the connect - phase. [Only works on unix-style/SIGALRM operating systems] */ - CINIT(CONNECTTIMEOUT, LONG, 78), - - /* Function that will be called to store headers (instead of fwrite). The - * parameters will use fwrite() syntax, make sure to follow them. */ - CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), - - /* Set this to force the HTTP request to get back to GET. Only really usable - if POST, PUT or a custom request have been used first. - */ - CINIT(HTTPGET, LONG, 80), - - /* Set if we should verify the Common name from the peer certificate in ssl - * handshake, set 1 to check existence, 2 to ensure that it matches the - * provided hostname. */ - CINIT(SSL_VERIFYHOST, LONG, 81), - - /* Specify which file name to write all known cookies in after completed - operation. Set file name to "-" (dash) to make it go to stdout. */ - CINIT(COOKIEJAR, OBJECTPOINT, 82), - - /* Specify which SSL ciphers to use */ - CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83), - - /* Specify which HTTP version to use! This must be set to one of the - CURL_HTTP_VERSION* enums set below. */ - CINIT(HTTP_VERSION, LONG, 84), - - /* Specifically switch on or off the FTP engine's use of the EPSV command. By - default, that one will always be attempted before the more traditional - PASV command. */ - CINIT(FTP_USE_EPSV, LONG, 85), - - /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ - CINIT(SSLCERTTYPE, OBJECTPOINT, 86), - - /* name of the file keeping your private SSL-key */ - CINIT(SSLKEY, OBJECTPOINT, 87), - - /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ - CINIT(SSLKEYTYPE, OBJECTPOINT, 88), - - /* crypto engine for the SSL-sub system */ - CINIT(SSLENGINE, OBJECTPOINT, 89), - - /* set the crypto engine for the SSL-sub system as default - the param has no meaning... - */ - CINIT(SSLENGINE_DEFAULT, LONG, 90), - - /* Non-zero value means to use the global dns cache */ - CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* To become OBSOLETE soon */ - - /* DNS cache timeout */ - CINIT(DNS_CACHE_TIMEOUT, LONG, 92), - - /* send linked-list of pre-transfer QUOTE commands */ - CINIT(PREQUOTE, OBJECTPOINT, 93), - - /* set the debug function */ - CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), - - /* set the data for the debug function */ - CINIT(DEBUGDATA, OBJECTPOINT, 95), - - /* mark this as start of a cookie session */ - CINIT(COOKIESESSION, LONG, 96), - - /* The CApath directory used to validate the peer certificate - this option is used only if SSL_VERIFYPEER is true */ - CINIT(CAPATH, OBJECTPOINT, 97), - - /* Instruct libcurl to use a smaller receive buffer */ - CINIT(BUFFERSIZE, LONG, 98), - - /* Instruct libcurl to not use any signal/alarm handlers, even when using - timeouts. This option is useful for multi-threaded applications. - See libcurl-the-guide for more background information. */ - CINIT(NOSIGNAL, LONG, 99), - - /* Provide a CURLShare for mutexing non-ts data */ - CINIT(SHARE, OBJECTPOINT, 100), - - /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), - CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */ - CINIT(PROXYTYPE, LONG, 101), - - /* Set the Accept-Encoding string. Use this to tell a server you would like - the response to be compressed. Before 7.21.6, this was known as - CURLOPT_ENCODING */ - CINIT(ACCEPT_ENCODING, OBJECTPOINT, 102), - - /* Set pointer to private data */ - CINIT(PRIVATE, OBJECTPOINT, 103), - - /* Set aliases for HTTP 200 in the HTTP Response header */ - CINIT(HTTP200ALIASES, OBJECTPOINT, 104), - - /* Continue to send authentication (user+password) when following locations, - even when hostname changed. This can potentially send off the name - and password to whatever host the server decides. */ - CINIT(UNRESTRICTED_AUTH, LONG, 105), - - /* Specifically switch on or off the FTP engine's use of the EPRT command ( it - also disables the LPRT attempt). By default, those ones will always be - attempted before the good old traditional PORT command. */ - CINIT(FTP_USE_EPRT, LONG, 106), - - /* Set this to a bitmask value to enable the particular authentications - methods you like. Use this in combination with CURLOPT_USERPWD. - Note that setting multiple bits may cause extra network round-trips. */ - CINIT(HTTPAUTH, LONG, 107), - - /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx - in second argument. The function must be matching the - curl_ssl_ctx_callback proto. */ - CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108), - - /* Set the userdata for the ssl context callback function's third - argument */ - CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), - - /* FTP Option that causes missing dirs to be created on the remote server. - In 7.19.4 we introduced the convenience enums for this option using the - CURLFTP_CREATE_DIR prefix. - */ - CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110), - - /* Set this to a bitmask value to enable the particular authentications - methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. - Note that setting multiple bits may cause extra network round-trips. */ - CINIT(PROXYAUTH, LONG, 111), - - /* FTP option that changes the timeout, in seconds, associated with - getting a response. This is different from transfer timeout time and - essentially places a demand on the FTP server to acknowledge commands - in a timely manner. */ - CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112), -#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT - - /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to - tell libcurl to resolve names to those IP versions only. This only has - affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ - CINIT(IPRESOLVE, LONG, 113), - - /* Set this option to limit the size of a file that will be downloaded from - an HTTP or FTP server. - - Note there is also _LARGE version which adds large file support for - platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ - CINIT(MAXFILESIZE, LONG, 114), - - /* See the comment for INFILESIZE above, but in short, specifies - * the size of the file being uploaded. -1 means unknown. - */ - CINIT(INFILESIZE_LARGE, OFF_T, 115), - - /* Sets the continuation offset. There is also a LONG version of this; - * look above for RESUME_FROM. - */ - CINIT(RESUME_FROM_LARGE, OFF_T, 116), - - /* Sets the maximum size of data that will be downloaded from - * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. - */ - CINIT(MAXFILESIZE_LARGE, OFF_T, 117), - - /* Set this option to the file name of your .netrc file you want libcurl - to parse (using the CURLOPT_NETRC option). If not set, libcurl will do - a poor attempt to find the user's home directory and check for a .netrc - file in there. */ - CINIT(NETRC_FILE, OBJECTPOINT, 118), - - /* Enable SSL/TLS for FTP, pick one of: - CURLFTPSSL_TRY - try using SSL, proceed anyway otherwise - CURLFTPSSL_CONTROL - SSL for the control connection or fail - CURLFTPSSL_ALL - SSL for all communication or fail - */ - CINIT(USE_SSL, LONG, 119), - - /* The _LARGE version of the standard POSTFIELDSIZE option */ - CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), - - /* Enable/disable the TCP Nagle algorithm */ - CINIT(TCP_NODELAY, LONG, 121), - - /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ - /* 123 OBSOLETE. Gone in 7.16.0 */ - /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ - /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ - /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ - /* 127 OBSOLETE. Gone in 7.16.0 */ - /* 128 OBSOLETE. Gone in 7.16.0 */ - - /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option - can be used to change libcurl's default action which is to first try - "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK - response has been received. - - Available parameters are: - CURLFTPAUTH_DEFAULT - let libcurl decide - CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS - CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL - */ - CINIT(FTPSSLAUTH, LONG, 129), - - CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130), - CINIT(IOCTLDATA, OBJECTPOINT, 131), - - /* 132 OBSOLETE. Gone in 7.16.0 */ - /* 133 OBSOLETE. Gone in 7.16.0 */ - - /* zero terminated string for pass on to the FTP server when asked for - "account" info */ - CINIT(FTP_ACCOUNT, OBJECTPOINT, 134), - - /* feed cookies into cookie engine */ - CINIT(COOKIELIST, OBJECTPOINT, 135), - - /* ignore Content-Length */ - CINIT(IGNORE_CONTENT_LENGTH, LONG, 136), - - /* Set to non-zero to skip the IP address received in a 227 PASV FTP server - response. Typically used for FTP-SSL purposes but is not restricted to - that. libcurl will then instead use the same IP address it used for the - control connection. */ - CINIT(FTP_SKIP_PASV_IP, LONG, 137), - - /* Select "file method" to use when doing FTP, see the curl_ftpmethod - above. */ - CINIT(FTP_FILEMETHOD, LONG, 138), - - /* Local port number to bind the socket to */ - CINIT(LOCALPORT, LONG, 139), - - /* Number of ports to try, including the first one set with LOCALPORT. - Thus, setting it to 1 will make no additional attempts but the first. - */ - CINIT(LOCALPORTRANGE, LONG, 140), - - /* no transfer, set up connection and let application use the socket by - extracting it with CURLINFO_LASTSOCKET */ - CINIT(CONNECT_ONLY, LONG, 141), - - /* Function that will be called to convert from the - network encoding (instead of using the iconv calls in libcurl) */ - CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142), - - /* Function that will be called to convert to the - network encoding (instead of using the iconv calls in libcurl) */ - CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143), - - /* Function that will be called to convert from UTF8 - (instead of using the iconv calls in libcurl) - Note that this is used only for SSL certificate processing */ - CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144), - - /* if the connection proceeds too quickly then need to slow it down */ - /* limit-rate: maximum number of bytes per second to send or receive */ - CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145), - CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146), - - /* Pointer to command string to send if USER/PASS fails. */ - CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147), - - /* callback function for setting socket options */ - CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148), - CINIT(SOCKOPTDATA, OBJECTPOINT, 149), - - /* set to 0 to disable session ID re-use for this transfer, default is - enabled (== 1) */ - CINIT(SSL_SESSIONID_CACHE, LONG, 150), - - /* allowed SSH authentication methods */ - CINIT(SSH_AUTH_TYPES, LONG, 151), - - /* Used by scp/sftp to do public/private key authentication */ - CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152), - CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153), - - /* Send CCC (Clear Command Channel) after authentication */ - CINIT(FTP_SSL_CCC, LONG, 154), - - /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ - CINIT(TIMEOUT_MS, LONG, 155), - CINIT(CONNECTTIMEOUT_MS, LONG, 156), - - /* set to zero to disable the libcurl's decoding and thus pass the raw body - data to the application even when it is encoded/compressed */ - CINIT(HTTP_TRANSFER_DECODING, LONG, 157), - CINIT(HTTP_CONTENT_DECODING, LONG, 158), - - /* Permission used when creating new files and directories on the remote - server for protocols that support it, SFTP/SCP/FILE */ - CINIT(NEW_FILE_PERMS, LONG, 159), - CINIT(NEW_DIRECTORY_PERMS, LONG, 160), - - /* Set the behaviour of POST when redirecting. Values must be set to one - of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ - CINIT(POSTREDIR, LONG, 161), - - /* used by scp/sftp to verify the host's public key */ - CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162), - - /* Callback function for opening socket (instead of socket(2)). Optionally, - callback is able change the address or refuse to connect returning - CURL_SOCKET_BAD. The callback should have type - curl_opensocket_callback */ - CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163), - CINIT(OPENSOCKETDATA, OBJECTPOINT, 164), - - /* POST volatile input fields. */ - CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165), - - /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ - CINIT(PROXY_TRANSFER_MODE, LONG, 166), - - /* Callback function for seeking in the input stream */ - CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167), - CINIT(SEEKDATA, OBJECTPOINT, 168), - - /* CRL file */ - CINIT(CRLFILE, OBJECTPOINT, 169), - - /* Issuer certificate */ - CINIT(ISSUERCERT, OBJECTPOINT, 170), - - /* (IPv6) Address scope */ - CINIT(ADDRESS_SCOPE, LONG, 171), - - /* Collect certificate chain info and allow it to get retrievable with - CURLINFO_CERTINFO after the transfer is complete. (Unfortunately) only - working with OpenSSL-powered builds. */ - CINIT(CERTINFO, LONG, 172), - - /* "name" and "pwd" to use when fetching. */ - CINIT(USERNAME, OBJECTPOINT, 173), - CINIT(PASSWORD, OBJECTPOINT, 174), - - /* "name" and "pwd" to use with Proxy when fetching. */ - CINIT(PROXYUSERNAME, OBJECTPOINT, 175), - CINIT(PROXYPASSWORD, OBJECTPOINT, 176), - - /* Comma separated list of hostnames defining no-proxy zones. These should - match both hostnames directly, and hostnames within a domain. For - example, local.com will match local.com and www.local.com, but NOT - notlocal.com or www.notlocal.com. For compatibility with other - implementations of this, .local.com will be considered to be the same as - local.com. A single * is the only valid wildcard, and effectively - disables the use of proxy. */ - CINIT(NOPROXY, OBJECTPOINT, 177), - - /* block size for TFTP transfers */ - CINIT(TFTP_BLKSIZE, LONG, 178), - - /* Socks Service */ - CINIT(SOCKS5_GSSAPI_SERVICE, OBJECTPOINT, 179), - - /* Socks Service */ - CINIT(SOCKS5_GSSAPI_NEC, LONG, 180), - - /* set the bitmask for the protocols that are allowed to be used for the - transfer, which thus helps the app which takes URLs from users or other - external inputs and want to restrict what protocol(s) to deal - with. Defaults to CURLPROTO_ALL. */ - CINIT(PROTOCOLS, LONG, 181), - - /* set the bitmask for the protocols that libcurl is allowed to follow to, - as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs - to be set in both bitmasks to be allowed to get redirected to. Defaults - to all protocols except FILE and SCP. */ - CINIT(REDIR_PROTOCOLS, LONG, 182), - - /* set the SSH knownhost file name to use */ - CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183), - - /* set the SSH host key callback, must point to a curl_sshkeycallback - function */ - CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184), - - /* set the SSH host key callback custom pointer */ - CINIT(SSH_KEYDATA, OBJECTPOINT, 185), - - /* set the SMTP mail originator */ - CINIT(MAIL_FROM, OBJECTPOINT, 186), - - /* set the SMTP mail receiver(s) */ - CINIT(MAIL_RCPT, OBJECTPOINT, 187), - - /* FTP: send PRET before PASV */ - CINIT(FTP_USE_PRET, LONG, 188), - - /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ - CINIT(RTSP_REQUEST, LONG, 189), - - /* The RTSP session identifier */ - CINIT(RTSP_SESSION_ID, OBJECTPOINT, 190), - - /* The RTSP stream URI */ - CINIT(RTSP_STREAM_URI, OBJECTPOINT, 191), - - /* The Transport: header to use in RTSP requests */ - CINIT(RTSP_TRANSPORT, OBJECTPOINT, 192), - - /* Manually initialize the client RTSP CSeq for this handle */ - CINIT(RTSP_CLIENT_CSEQ, LONG, 193), - - /* Manually initialize the server RTSP CSeq for this handle */ - CINIT(RTSP_SERVER_CSEQ, LONG, 194), - - /* The stream to pass to INTERLEAVEFUNCTION. */ - CINIT(INTERLEAVEDATA, OBJECTPOINT, 195), - - /* Let the application define a custom write method for RTP data */ - CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196), - - /* Turn on wildcard matching */ - CINIT(WILDCARDMATCH, LONG, 197), - - /* Directory matching callback called before downloading of an - individual file (chunk) started */ - CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198), - - /* Directory matching callback called after the file (chunk) - was downloaded, or skipped */ - CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199), - - /* Change match (fnmatch-like) callback for wildcard matching */ - CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200), - - /* Let the application define custom chunk data pointer */ - CINIT(CHUNK_DATA, OBJECTPOINT, 201), - - /* FNMATCH_FUNCTION user pointer */ - CINIT(FNMATCH_DATA, OBJECTPOINT, 202), - - /* send linked-list of name:port:address sets */ - CINIT(RESOLVE, OBJECTPOINT, 203), - - /* Set a username for authenticated TLS */ - CINIT(TLSAUTH_USERNAME, OBJECTPOINT, 204), - - /* Set a password for authenticated TLS */ - CINIT(TLSAUTH_PASSWORD, OBJECTPOINT, 205), - - /* Set authentication type for authenticated TLS */ - CINIT(TLSAUTH_TYPE, OBJECTPOINT, 206), - - /* Set to 1 to enable the "TE:" header in HTTP requests to ask for - compressed transfer-encoded responses. Set to 0 to disable the use of TE: - in outgoing requests. The current default is 0, but it might change in a - future libcurl release. - - libcurl will ask for the compressed methods it knows of, and if that - isn't any, it will not ask for transfer-encoding at all even if this - option is set to 1. - - */ - CINIT(TRANSFER_ENCODING, LONG, 207), - - 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_WRITEDATA CURLOPT_FILE -#define CURLOPT_READDATA CURLOPT_INFILE -#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER -#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_LAST /* *ILLEGAL* http version */ -}; - -/* - * Public API enums for RTSP requests - */ -enum { - CURL_RTSPREQ_NONE, /* first in list */ - CURL_RTSPREQ_OPTIONS, - CURL_RTSPREQ_DESCRIBE, - CURL_RTSPREQ_ANNOUNCE, - CURL_RTSPREQ_SETUP, - CURL_RTSPREQ_PLAY, - CURL_RTSPREQ_PAUSE, - CURL_RTSPREQ_TEARDOWN, - CURL_RTSPREQ_GET_PARAMETER, - CURL_RTSPREQ_SET_PARAMETER, - CURL_RTSPREQ_RECORD, - CURL_RTSPREQ_RECEIVE, - CURL_RTSPREQ_LAST /* last in list */ -}; - - /* These enums are for use with the CURLOPT_NETRC option. */ -enum CURL_NETRC_OPTION { - CURL_NETRC_IGNORED, /* The .netrc will never be read. - * This is the default. */ - CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred - * to one in the .netrc. */ - CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. - * Unless one is set programmatically, the .netrc - * will be queried. */ - CURL_NETRC_LAST -}; - -enum { - CURL_SSLVERSION_DEFAULT, - CURL_SSLVERSION_TLSv1, - CURL_SSLVERSION_SSLv2, - CURL_SSLVERSION_SSLv3, - - CURL_SSLVERSION_LAST /* never use, keep last */ -}; - -enum CURL_TLSAUTH { - CURL_TLSAUTH_NONE, - CURL_TLSAUTH_SRP, - CURL_TLSAUTH_LAST /* never use, keep last */ -}; - -/* symbols to use with CURLOPT_POSTREDIR. - CURL_REDIR_POST_301 and CURL_REDIR_POST_302 can be bitwise ORed so that - CURL_REDIR_POST_301 | CURL_REDIR_POST_302 == 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_ALL (CURL_REDIR_POST_301|CURL_REDIR_POST_302) - -typedef enum { - CURL_TIMECOND_NONE, - - CURL_TIMECOND_IFMODSINCE, - CURL_TIMECOND_IFUNMODSINCE, - CURL_TIMECOND_LASTMOD, - - CURL_TIMECOND_LAST -} curl_TimeCond; - - -/* curl_strequal() and curl_strnequal() are subject for removal in a future - libcurl, see lib/README.curlx for details */ -CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2); -CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n); - -/* name is uppercase CURLFORM_ */ -#ifdef CFINIT -#undef CFINIT -#endif - -#ifdef CURL_ISOCPP -#define CFINIT(name) CURLFORM_ ## name -#else -/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ -#define CFINIT(name) CURLFORM_/**/name -#endif - -typedef enum { - CFINIT(NOTHING), /********* the first one is unused ************/ - - /* */ - CFINIT(COPYNAME), - CFINIT(PTRNAME), - CFINIT(NAMELENGTH), - CFINIT(COPYCONTENTS), - CFINIT(PTRCONTENTS), - CFINIT(CONTENTSLENGTH), - CFINIT(FILECONTENT), - CFINIT(ARRAY), - CFINIT(OBSOLETE), - CFINIT(FILE), - - CFINIT(BUFFER), - CFINIT(BUFFERPTR), - CFINIT(BUFFERLENGTH), - - CFINIT(CONTENTTYPE), - CFINIT(CONTENTHEADER), - CFINIT(FILENAME), - CFINIT(END), - CFINIT(OBSOLETE2), - - CFINIT(STREAM), - - CURLFORM_LASTENTRY /* the last unused */ -} CURLformoption; - -#undef CFINIT /* done */ - -/* structure to be used as parameter for CURLFORM_ARRAY */ -struct curl_forms { - CURLformoption option; - const char *value; -}; - -/* use this for multipart formpost building */ -/* Returns code for curl_formadd() - * - * Returns: - * CURL_FORMADD_OK on success - * CURL_FORMADD_MEMORY if the FormInfo allocation fails - * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form - * CURL_FORMADD_NULL if a null pointer was given for a char - * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed - * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used - * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) - * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated - * CURL_FORMADD_MEMORY if some allocation for string copying failed. - * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array - * - ***************************************************************************/ -typedef enum { - CURL_FORMADD_OK, /* first, no error */ - - CURL_FORMADD_MEMORY, - CURL_FORMADD_OPTION_TWICE, - CURL_FORMADD_NULL, - CURL_FORMADD_UNKNOWN_OPTION, - CURL_FORMADD_INCOMPLETE, - CURL_FORMADD_ILLEGAL_ARRAY, - CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ - - CURL_FORMADD_LAST /* last */ -} CURLFORMcode; - -/* - * NAME curl_formadd() - * - * DESCRIPTION - * - * Pretty advanced function for building multi-part formposts. Each invoke - * adds one part that together construct a full post. Then use - * CURLOPT_HTTPPOST to send it off to libcurl. - */ -CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, - struct curl_httppost **last_post, - ...); - -/* - * callback function for curl_formget() - * The void *arg pointer will be the one passed as second argument to - * curl_formget(). - * The character buffer passed to it must not be freed. - * Should return the buffer length passed to it as the argument "len" on - * success. - */ -typedef size_t (*curl_formget_callback)(void *arg, const char *buf, size_t len); - -/* - * NAME curl_formget() - * - * DESCRIPTION - * - * Serialize a curl_httppost struct built with curl_formadd(). - * Accepts a void pointer as second argument which will be passed to - * the curl_formget_callback function. - * Returns 0 on success. - */ -CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, - curl_formget_callback append); -/* - * NAME curl_formfree() - * - * DESCRIPTION - * - * Free a multipart formpost previously built with curl_formadd(). - */ -CURL_EXTERN void curl_formfree(struct curl_httppost *form); - -/* - * NAME curl_getenv() - * - * DESCRIPTION - * - * Returns a malloc()'ed string that MUST be curl_free()ed after usage is - * complete. DEPRECATED - see lib/README.curlx - */ -CURL_EXTERN char *curl_getenv(const char *variable); - -/* - * NAME curl_version() - * - * DESCRIPTION - * - * Returns a static ascii string of the libcurl version. - */ -CURL_EXTERN char *curl_version(void); - -/* - * NAME curl_easy_escape() - * - * DESCRIPTION - * - * Escapes URL strings (converts all letters consider illegal in URLs to their - * %XX versions). This function returns a new allocated string or NULL if an - * error occurred. - */ -CURL_EXTERN char *curl_easy_escape(CURL *handle, - const char *string, - int length); - -/* the previous version: */ -CURL_EXTERN char *curl_escape(const char *string, - int length); - - -/* - * NAME curl_easy_unescape() - * - * DESCRIPTION - * - * Unescapes URL encoding in strings (converts all %XX codes to their 8bit - * versions). This function returns a new allocated string or NULL if an error - * occurred. - * Conversion Note: On non-ASCII platforms the ASCII %XX codes are - * converted into the host encoding. - */ -CURL_EXTERN char *curl_easy_unescape(CURL *handle, - const char *string, - int length, - int *outlength); - -/* the previous version */ -CURL_EXTERN char *curl_unescape(const char *string, - int length); - -/* - * NAME curl_free() - * - * DESCRIPTION - * - * Provided for de-allocation in the same translation unit that did the - * allocation. Added in libcurl 7.10 - */ -CURL_EXTERN void curl_free(void *p); - -/* - * NAME curl_global_init() - * - * DESCRIPTION - * - * curl_global_init() should be invoked exactly once for each application that - * uses libcurl and before any call of other libcurl functions. - * - * This function is not thread-safe! - */ -CURL_EXTERN CURLcode curl_global_init(long flags); - -/* - * NAME curl_global_init_mem() - * - * DESCRIPTION - * - * curl_global_init() or curl_global_init_mem() should be invoked exactly once - * for each application that uses libcurl. This function can be used to - * initialize libcurl and set user defined memory management callback - * functions. Users can implement memory management routines to check for - * memory leaks, check for mis-use of the curl library etc. User registered - * callback routines with be invoked by this library instead of the system - * memory management routines like malloc, free etc. - */ -CURL_EXTERN CURLcode curl_global_init_mem(long flags, - curl_malloc_callback m, - curl_free_callback f, - curl_realloc_callback r, - curl_strdup_callback s, - curl_calloc_callback c); - -/* - * NAME curl_global_cleanup() - * - * DESCRIPTION - * - * curl_global_cleanup() should be invoked exactly once for each application - * that uses libcurl - */ -CURL_EXTERN void curl_global_cleanup(void); - -/* linked-list structure for the CURLOPT_QUOTE option (and other) */ -struct curl_slist { - char *data; - struct curl_slist *next; -}; - -/* - * NAME curl_slist_append() - * - * DESCRIPTION - * - * Appends a string to a linked list. If no list exists, it will be created - * first. Returns the new list, after appending. - */ -CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, - const char *); - -/* - * NAME curl_slist_free_all() - * - * DESCRIPTION - * - * free a previously built curl_slist. - */ -CURL_EXTERN void curl_slist_free_all(struct curl_slist *); - -/* - * NAME curl_getdate() - * - * DESCRIPTION - * - * Returns the time, in seconds since 1 Jan 1970 of the time string given in - * the first argument. The time argument in the second parameter is unused - * and should be set to NULL. - */ -CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); - -/* info about the certificate chain, only for OpenSSL builds. Asked - for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ -struct curl_certinfo { - int num_of_certs; /* number of certificates with information */ - struct curl_slist **certinfo; /* for each index in this array, there's a - linked list with textual information in the - format "name: value" */ -}; - -#define CURLINFO_STRING 0x100000 -#define CURLINFO_LONG 0x200000 -#define CURLINFO_DOUBLE 0x300000 -#define CURLINFO_SLIST 0x400000 -#define CURLINFO_MASK 0x0fffff -#define CURLINFO_TYPEMASK 0xf00000 - -typedef enum { - CURLINFO_NONE, /* first, never use this */ - CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, - CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, - CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, - CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, - CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, - CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, - CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, - CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, - CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, - CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, - CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, - CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, - CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, - CURLINFO_FILETIME = CURLINFO_LONG + 14, - CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, - CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, - CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, - CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, - CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, - CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, - CURLINFO_PRIVATE = CURLINFO_STRING + 21, - CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, - CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, - CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, - CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, - CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, - CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, - CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, - CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, - CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, - CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, - CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, - CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, - CURLINFO_CERTINFO = CURLINFO_SLIST + 34, - CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, - CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, - CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, - CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, - CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, - CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, - CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, - CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, - /* Fill in new entries below here! */ - - CURLINFO_LASTONE = 42 -} CURLINFO; - -/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as - CURLINFO_HTTP_CODE */ -#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE - -typedef enum { - CURLCLOSEPOLICY_NONE, /* first, never use this */ - - CURLCLOSEPOLICY_OLDEST, - CURLCLOSEPOLICY_LEAST_RECENTLY_USED, - CURLCLOSEPOLICY_LEAST_TRAFFIC, - CURLCLOSEPOLICY_SLOWEST, - CURLCLOSEPOLICY_CALLBACK, - - CURLCLOSEPOLICY_LAST /* last, never use this */ -} curl_closepolicy; - -#define CURL_GLOBAL_SSL (1<<0) -#define CURL_GLOBAL_WIN32 (1<<1) -#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) -#define CURL_GLOBAL_NOTHING 0 -#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL - - -/***************************************************************************** - * Setup defines, protos etc for the sharing stuff. - */ - -/* Different data locks for a single share */ -typedef enum { - CURL_LOCK_DATA_NONE = 0, - /* CURL_LOCK_DATA_SHARE is used internally to say that - * the locking is just made to change the internal state of the share - * itself. - */ - CURL_LOCK_DATA_SHARE, - CURL_LOCK_DATA_COOKIE, - CURL_LOCK_DATA_DNS, - CURL_LOCK_DATA_SSL_SESSION, - CURL_LOCK_DATA_CONNECT, - CURL_LOCK_DATA_LAST -} curl_lock_data; - -/* Different lock access types */ -typedef enum { - CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ - CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ - CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ - CURL_LOCK_ACCESS_LAST /* never use */ -} curl_lock_access; - -typedef void (*curl_lock_function)(CURL *handle, - curl_lock_data data, - curl_lock_access locktype, - void *userptr); -typedef void (*curl_unlock_function)(CURL *handle, - curl_lock_data data, - void *userptr); - -typedef void CURLSH; - -typedef enum { - CURLSHE_OK, /* all is fine */ - CURLSHE_BAD_OPTION, /* 1 */ - CURLSHE_IN_USE, /* 2 */ - CURLSHE_INVALID, /* 3 */ - CURLSHE_NOMEM, /* out of memory */ - CURLSHE_LAST /* never use */ -} CURLSHcode; - -typedef enum { - CURLSHOPT_NONE, /* don't use */ - CURLSHOPT_SHARE, /* specify a data type to share */ - CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ - CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ - CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ - CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock - callback functions */ - CURLSHOPT_LAST /* never use */ -} CURLSHoption; - -CURL_EXTERN CURLSH *curl_share_init(void); -CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); -CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); - -/**************************************************************************** - * Structures for querying information about the curl library at runtime. - */ - -typedef enum { - CURLVERSION_FIRST, - CURLVERSION_SECOND, - CURLVERSION_THIRD, - CURLVERSION_FOURTH, - CURLVERSION_LAST /* never actually use this */ -} CURLversion; - -/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by - basically all programs ever that want to get version information. It is - meant to be a built-in version number for what kind of struct the caller - expects. If the struct ever changes, we redefine the NOW to another enum - from above. */ -#define CURLVERSION_NOW CURLVERSION_FOURTH - -typedef struct { - CURLversion age; /* age of the returned struct */ - const char *version; /* LIBCURL_VERSION */ - unsigned int version_num; /* LIBCURL_VERSION_NUM */ - const char *host; /* OS/host/cpu/machine when configured */ - int features; /* bitmask, see defines below */ - const char *ssl_version; /* human readable string */ - long ssl_version_num; /* not used anymore, always 0 */ - const char *libz_version; /* human readable string */ - /* protocols is terminated by an entry with a NULL protoname */ - const char * const *protocols; - - /* The fields below this were added in CURLVERSION_SECOND */ - const char *ares; - int ares_num; - - /* This field was added in CURLVERSION_THIRD */ - const char *libidn; - - /* These field were added in CURLVERSION_FOURTH */ - - /* Same as '_libiconv_version' if built with HAVE_ICONV */ - int iconv_ver_num; - - const char *libssh_version; /* human readable string */ - -} curl_version_info_data; - -#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ -#define CURL_VERSION_KERBEROS4 (1<<1) /* kerberos auth is supported */ -#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ -#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ -#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ -#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth support */ -#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 */ -#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */ -#define CURL_VERSION_IDN (1<<10) /* International Domain Names support */ -#define CURL_VERSION_SSPI (1<<11) /* SSPI is supported */ -#define CURL_VERSION_CONV (1<<12) /* character conversions supported */ -#define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */ -#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ - -/* - * NAME curl_version_info() - * - * DESCRIPTION - * - * This function returns a pointer to a static copy of the version info - * struct. See above. - */ -CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); - -/* - * NAME curl_easy_strerror() - * - * DESCRIPTION - * - * The curl_easy_strerror function may be used to turn a CURLcode value - * into the equivalent human readable error string. This is useful - * for printing meaningful error messages. - */ -CURL_EXTERN const char *curl_easy_strerror(CURLcode); - -/* - * NAME curl_share_strerror() - * - * DESCRIPTION - * - * The curl_share_strerror function may be used to turn a CURLSHcode value - * into the equivalent human readable error string. This is useful - * for printing meaningful error messages. - */ -CURL_EXTERN const char *curl_share_strerror(CURLSHcode); - -/* - * NAME curl_easy_pause() - * - * DESCRIPTION - * - * The curl_easy_pause function pauses or unpauses transfers. Select the new - * state by setting the bitmask, use the convenience defines below. - * - */ -CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); - -#define CURLPAUSE_RECV (1<<0) -#define CURLPAUSE_RECV_CONT (0) - -#define CURLPAUSE_SEND (1<<2) -#define CURLPAUSE_SEND_CONT (0) - -#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) -#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) - -#ifdef __cplusplus -} -#endif - -/* unfortunately, the easy.h and multi.h include files need options and info - stuff before they can be included! */ -#include "easy.h" /* nothing in curl is fun without the easy stuff */ -#include "multi.h" - -/* the typechecker doesn't work in C++ (yet) */ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ - ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ - !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) -#include "typecheck-gcc.h" -#else -#if defined(__STDC__) && (__STDC__ >= 1) -/* This preprocessor magic that replaces a call with the exact same call is - only done to make sure application authors pass exactly three arguments - to these functions. */ -#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) -#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) -#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) -#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) -#endif /* __STDC__ >= 1 */ -#endif /* gcc >= 4.3 && !__cplusplus */ - -#endif /* __CURL_CURL_H */ diff --git a/third_party/curl/include/curl/curlbuild.h b/third_party/curl/include/curl/curlbuild.h deleted file mode 100644 index d0b32acbe..000000000 --- a/third_party/curl/include/curl/curlbuild.h +++ /dev/null @@ -1,583 +0,0 @@ -#ifndef __CURL_CURLBUILD_H -#define __CURL_CURLBUILD_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* ================================================================ */ -/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ -/* ================================================================ */ - -/* - * NOTE 1: - * ------- - * - * See file include/curl/curlbuild.h.in, run configure, and forget - * that this file exists it is only used for non-configure systems. - * But you can keep reading if you want ;-) - * - */ - -/* ================================================================ */ -/* NOTES FOR NON-CONFIGURE SYSTEMS */ -/* ================================================================ */ - -/* - * NOTE 1: - * ------- - * - * Nothing in this file is intended to be modified or adjusted by the - * curl library user nor by the curl library builder. - * - * If you think that something actually needs to be changed, adjusted - * or fixed in this file, then, report it on the libcurl development - * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ - * - * Try to keep one section per platform, compiler and architecture, - * otherwise, if an existing section is reused for a different one and - * later on the original is adjusted, probably the piggybacking one can - * be adversely changed. - * - * In order to differentiate between platforms/compilers/architectures - * use only compiler built in predefined preprocessor symbols. - * - * This header file shall only export symbols which are 'curl' or 'CURL' - * prefixed, otherwise public name space would be polluted. - * - * NOTE 2: - * ------- - * - * For any given platform/compiler curl_off_t must be typedef'ed to a - * 64-bit wide signed integral data type. The width of this data type - * must remain constant and independent of any possible large file - * support settings. - * - * As an exception to the above, curl_off_t shall be typedef'ed to a - * 32-bit wide signed integral data type if there is no 64-bit type. - * - * As a general rule, curl_off_t shall not be mapped to off_t. This - * rule shall only be violated if off_t is the only 64-bit data type - * available and the size of off_t is independent of large file support - * settings. Keep your build on the safe side avoiding an off_t gating. - * If you have a 64-bit off_t then take for sure that another 64-bit - * data type exists, dig deeper and you will find it. - * - * NOTE 3: - * ------- - * - * Right now you might be staring at file include/curl/curlbuild.h.dist or - * at file include/curl/curlbuild.h, this is due to the following reason: - * file include/curl/curlbuild.h.dist is renamed to include/curl/curlbuild.h - * when the libcurl source code distribution archive file is created. - * - * File include/curl/curlbuild.h.dist is not included in the distribution - * archive. File include/curl/curlbuild.h is not present in the git tree. - * - * The distributed include/curl/curlbuild.h file is only intended to be used - * on systems which can not run the also distributed configure script. - * - * On systems capable of running the configure script, the configure process - * will overwrite the distributed include/curl/curlbuild.h file with one that - * is suitable and specific to the library being configured and built, which - * is generated from the include/curl/curlbuild.h.in template file. - * - * If you check out from git on a non-configure platform, you must run the - * appropriate buildconf* script to set up curlbuild.h and other local files. - * - */ - -/* ================================================================ */ -/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ -/* ================================================================ */ - -#ifdef CURL_SIZEOF_LONG -# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined -#endif - -#ifdef CURL_TYPEOF_CURL_SOCKLEN_T -# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined -#endif - -#ifdef CURL_SIZEOF_CURL_SOCKLEN_T -# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined -#endif - -#ifdef CURL_TYPEOF_CURL_OFF_T -# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined -#endif - -#ifdef CURL_FORMAT_CURL_OFF_T -# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined -#endif - -#ifdef CURL_FORMAT_CURL_OFF_TU -# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined -#endif - -#ifdef CURL_FORMAT_OFF_T -# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined -#endif - -#ifdef CURL_SIZEOF_CURL_OFF_T -# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined -#endif - -#ifdef CURL_SUFFIX_CURL_OFF_T -# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined -#endif - -#ifdef CURL_SUFFIX_CURL_OFF_TU -# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined -#endif - -/* ================================================================ */ -/* EXTERNAL INTERFACE SETTINGS FOR NON-CONFIGURE SYSTEMS ONLY */ -/* ================================================================ */ - -#if defined(__DJGPP__) || defined(__GO32__) -# if defined(__DJGPP__) && (__DJGPP__ > 1) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# else -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 4 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# endif -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(__SALFORDC__) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 4 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(__BORLANDC__) -# if (__BORLANDC__ < 0x520) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 4 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# else -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T __int64 -# define CURL_FORMAT_CURL_OFF_T "I64d" -# define CURL_FORMAT_CURL_OFF_TU "I64u" -# define CURL_FORMAT_OFF_T "%I64d" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T i64 -# define CURL_SUFFIX_CURL_OFF_TU ui64 -# endif -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(__TURBOC__) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 4 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(__WATCOMC__) -# if defined(__386__) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T __int64 -# define CURL_FORMAT_CURL_OFF_T "I64d" -# define CURL_FORMAT_CURL_OFF_TU "I64u" -# define CURL_FORMAT_OFF_T "%I64d" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T i64 -# define CURL_SUFFIX_CURL_OFF_TU ui64 -# else -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 4 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# endif -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(__POCC__) -# if (__POCC__ < 280) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 4 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# elif defined(_MSC_VER) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T __int64 -# define CURL_FORMAT_CURL_OFF_T "I64d" -# define CURL_FORMAT_CURL_OFF_TU "I64u" -# define CURL_FORMAT_OFF_T "%I64d" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T i64 -# define CURL_SUFFIX_CURL_OFF_TU ui64 -# else -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# endif -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(__LCC__) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 4 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(__SYMBIAN32__) -# if defined(__EABI__) /* Treat all ARM compilers equally */ -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# elif defined(__CW32__) -# pragma longlong on -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# elif defined(__VC32__) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T __int64 -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# endif -# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(__MWERKS__) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(_WIN32_WCE) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T __int64 -# define CURL_FORMAT_CURL_OFF_T "I64d" -# define CURL_FORMAT_CURL_OFF_TU "I64u" -# define CURL_FORMAT_OFF_T "%I64d" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T i64 -# define CURL_SUFFIX_CURL_OFF_TU ui64 -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(__MINGW32__) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "I64d" -# define CURL_FORMAT_CURL_OFF_TU "I64u" -# define CURL_FORMAT_OFF_T "%I64d" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(__VMS) -# if defined(__VAX) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 4 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# else -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# endif -# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -#elif defined(__OS400__) -# if defined(__ILEC400__) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 -# define CURL_PULL_SYS_TYPES_H 1 -# define CURL_PULL_SYS_SOCKET_H 1 -# endif - -#elif defined(__MVS__) -# if defined(__IBMC__) || defined(__IBMCPP__) -# if defined(_ILP32) -# define CURL_SIZEOF_LONG 4 -# elif defined(_LP64) -# define CURL_SIZEOF_LONG 8 -# endif -# if defined(_LONG_LONG) -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# elif defined(_LP64) -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# else -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 4 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# endif -# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 -# define CURL_PULL_SYS_TYPES_H 1 -# define CURL_PULL_SYS_SOCKET_H 1 -# endif - -#elif defined(__370__) -# if defined(__IBMC__) || defined(__IBMCPP__) -# if defined(_ILP32) -# define CURL_SIZEOF_LONG 4 -# elif defined(_LP64) -# define CURL_SIZEOF_LONG 8 -# endif -# if defined(_LONG_LONG) -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# elif defined(_LP64) -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# else -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 4 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# endif -# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 -# define CURL_PULL_SYS_TYPES_H 1 -# define CURL_PULL_SYS_SOCKET_H 1 -# endif - -#elif defined(TPF) -# define CURL_SIZEOF_LONG 8 -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -/* ===================================== */ -/* KEEP MSVC THE PENULTIMATE ENTRY */ -/* ===================================== */ - -#elif defined(_MSC_VER) -# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T __int64 -# define CURL_FORMAT_CURL_OFF_T "I64d" -# define CURL_FORMAT_CURL_OFF_TU "I64u" -# define CURL_FORMAT_OFF_T "%I64d" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T i64 -# define CURL_SUFFIX_CURL_OFF_TU ui64 -# else -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 4 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# endif -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 - -/* ===================================== */ -/* KEEP GENERIC GCC THE LAST ENTRY */ -/* ===================================== */ - -#elif defined(__GNUC__) -# if defined(__i386__) || defined(__ppc__) -# define CURL_SIZEOF_LONG 4 -# define CURL_TYPEOF_CURL_OFF_T long long -# define CURL_FORMAT_CURL_OFF_T "lld" -# define CURL_FORMAT_CURL_OFF_TU "llu" -# define CURL_FORMAT_OFF_T "%lld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T LL -# define CURL_SUFFIX_CURL_OFF_TU ULL -# elif defined(__x86_64__) || defined(__ppc64__) -# define CURL_SIZEOF_LONG 8 -# define CURL_TYPEOF_CURL_OFF_T long -# define CURL_FORMAT_CURL_OFF_T "ld" -# define CURL_FORMAT_CURL_OFF_TU "lu" -# define CURL_FORMAT_OFF_T "%ld" -# define CURL_SIZEOF_CURL_OFF_T 8 -# define CURL_SUFFIX_CURL_OFF_T L -# define CURL_SUFFIX_CURL_OFF_TU UL -# endif -# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t -# define CURL_SIZEOF_CURL_SOCKLEN_T 4 -# define CURL_PULL_SYS_TYPES_H 1 -# define CURL_PULL_SYS_SOCKET_H 1 - -#else -# error "Unknown non-configure build target!" - Error Compilation_aborted_Unknown_non_configure_build_target -#endif - -/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */ -/* sys/types.h is required here to properly make type definitions below. */ -#ifdef CURL_PULL_SYS_TYPES_H -# include -#endif - -/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */ -/* sys/socket.h is required here to properly make type definitions below. */ -#ifdef CURL_PULL_SYS_SOCKET_H -# include -#endif - -/* Data type definition of curl_socklen_t. */ - -#ifdef CURL_TYPEOF_CURL_SOCKLEN_T - typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; -#endif - -/* Data type definition of curl_off_t. */ - -#ifdef CURL_TYPEOF_CURL_OFF_T - typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; -#endif - -#endif /* __CURL_CURLBUILD_H */ diff --git a/third_party/curl/include/curl/curlbuild.h.cmake b/third_party/curl/include/curl/curlbuild.h.cmake deleted file mode 100644 index 3aa772fc4..000000000 --- a/third_party/curl/include/curl/curlbuild.h.cmake +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef __CURL_CURLBUILD_H -#define __CURL_CURLBUILD_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* ================================================================ */ -/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ -/* ================================================================ */ - -/* - * NOTE 1: - * ------- - * - * Nothing in this file is intended to be modified or adjusted by the - * curl library user nor by the curl library builder. - * - * If you think that something actually needs to be changed, adjusted - * or fixed in this file, then, report it on the libcurl development - * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ - * - * This header file shall only export symbols which are 'curl' or 'CURL' - * prefixed, otherwise public name space would be polluted. - * - * NOTE 2: - * ------- - * - * Right now you might be staring at file include/curl/curlbuild.h.in or - * at file include/curl/curlbuild.h, this is due to the following reason: - * - * On systems capable of running the configure script, the configure process - * will overwrite the distributed include/curl/curlbuild.h file with one that - * is suitable and specific to the library being configured and built, which - * is generated from the include/curl/curlbuild.h.in template file. - * - */ - -/* ================================================================ */ -/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ -/* ================================================================ */ - -#ifdef CURL_SIZEOF_LONG -# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined -#endif - -#ifdef CURL_TYPEOF_CURL_SOCKLEN_T -# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined -#endif - -#ifdef CURL_SIZEOF_CURL_SOCKLEN_T -# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined -#endif -#ifdef CURL_TYPEOF_CURL_OFF_T -# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined -#endif - -#ifdef CURL_FORMAT_CURL_OFF_T -# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined -#endif - -#ifdef CURL_FORMAT_CURL_OFF_TU -# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined -#endif - -#ifdef CURL_FORMAT_OFF_T -# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined -#endif - -#ifdef CURL_SIZEOF_CURL_OFF_T -# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined -#endif - -#ifdef CURL_SUFFIX_CURL_OFF_T -# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined -#endif - -#ifdef CURL_SUFFIX_CURL_OFF_TU -# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" - Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined -#endif - -/* ================================================================ */ -/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ -/* ================================================================ */ - -/* Configure process defines this to 1 when it finds out that system */ -/* header file sys/types.h must be included by the external interface. */ -#cmakedefine CURL_PULL_SYS_TYPES_H ${CURL_PULL_SYS_TYPES_H} -#ifdef CURL_PULL_SYS_TYPES_H -# include -#endif - -/* Configure process defines this to 1 when it finds out that system */ -/* header file stdint.h must be included by the external interface. */ -#cmakedefine CURL_PULL_STDINT_H ${CURL_PULL_STDINT_H} -#ifdef CURL_PULL_STDINT_H -# include -#endif - -/* Configure process defines this to 1 when it finds out that system */ -/* header file inttypes.h must be included by the external interface. */ -#cmakedefine CURL_PULL_INTTYPES_H ${CURL_PULL_INTTYPES_H} -#ifdef CURL_PULL_INTTYPES_H -# include -#endif - -/* The size of `long', as computed by sizeof. */ -#cmakedefine CURL_SIZEOF_LONG ${CURL_SIZEOF_LONG} - -/* Integral data type used for curl_socklen_t. */ -#cmakedefine CURL_TYPEOF_CURL_SOCKLEN_T ${CURL_TYPEOF_CURL_SOCKLEN_T} - -/* on windows socklen_t is in here */ -#ifdef _WIN32 -# include -# include -#endif - -#ifdef HAVE_SYS_SOCKET_H -# include -#endif - -/* Data type definition of curl_socklen_t. */ -typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; - -/* The size of `curl_socklen_t', as computed by sizeof. */ -#cmakedefine CURL_SIZEOF_CURL_SOCKLEN_T ${CURL_SIZEOF_CURL_SOCKLEN_T} - -/* Signed integral data type used for curl_off_t. */ -#cmakedefine CURL_TYPEOF_CURL_OFF_T ${CURL_TYPEOF_CURL_OFF_T} - -/* Data type definition of curl_off_t. */ -typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; - -/* curl_off_t formatting string directive without "%" conversion specifier. */ -#cmakedefine CURL_FORMAT_CURL_OFF_T "${CURL_FORMAT_CURL_OFF_T}" - -/* unsigned curl_off_t formatting string without "%" conversion specifier. */ -#cmakedefine CURL_FORMAT_CURL_OFF_TU "${CURL_FORMAT_CURL_OFF_TU}" - -/* curl_off_t formatting string directive with "%" conversion specifier. */ -#cmakedefine CURL_FORMAT_OFF_T "${CURL_FORMAT_OFF_T}" - -/* The size of `curl_off_t', as computed by sizeof. */ -#cmakedefine CURL_SIZEOF_CURL_OFF_T ${CURL_SIZEOF_CURL_OFF_T} - -/* curl_off_t constant suffix. */ -#cmakedefine CURL_SUFFIX_CURL_OFF_T ${CURL_SUFFIX_CURL_OFF_T} - -/* unsigned curl_off_t constant suffix. */ -#cmakedefine CURL_SUFFIX_CURL_OFF_TU ${CURL_SUFFIX_CURL_OFF_TU} - -#endif /* __CURL_CURLBUILD_H */ diff --git a/third_party/curl/include/curl/curlrules.h b/third_party/curl/include/curl/curlrules.h deleted file mode 100644 index cbc12fdd2..000000000 --- a/third_party/curl/include/curl/curlrules.h +++ /dev/null @@ -1,261 +0,0 @@ -#ifndef __CURL_CURLRULES_H -#define __CURL_CURLRULES_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* ================================================================ */ -/* COMPILE TIME SANITY CHECKS */ -/* ================================================================ */ - -/* - * NOTE 1: - * ------- - * - * All checks done in this file are intentionally placed in a public - * header file which is pulled by curl/curl.h when an application is - * being built using an already built libcurl library. Additionally - * this file is also included and used when building the library. - * - * If compilation fails on this file it is certainly sure that the - * problem is elsewhere. It could be a problem in the curlbuild.h - * header file, or simply that you are using different compilation - * settings than those used to build the library. - * - * Nothing in this file is intended to be modified or adjusted by the - * curl library user nor by the curl library builder. - * - * Do not deactivate any check, these are done to make sure that the - * library is properly built and used. - * - * You can find further help on the libcurl development mailing list: - * http://cool.haxx.se/mailman/listinfo/curl-library/ - * - * NOTE 2 - * ------ - * - * Some of the following compile time checks are based on the fact - * that the dimension of a constant array can not be a negative one. - * In this way if the compile time verification fails, the compilation - * will fail issuing an error. The error description wording is compiler - * dependent but it will be quite similar to one of the following: - * - * "negative subscript or subscript is too large" - * "array must have at least one element" - * "-1 is an illegal array size" - * "size of array is negative" - * - * If you are building an application which tries to use an already - * built libcurl library and you are getting this kind of errors on - * this file, it is a clear indication that there is a mismatch between - * how the library was built and how you are trying to use it for your - * application. Your already compiled or binary library provider is the - * only one who can give you the details you need to properly use it. - */ - -/* - * Verify that some macros are actually defined. - */ - -#ifndef CURL_SIZEOF_LONG -# error "CURL_SIZEOF_LONG definition is missing!" - Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing -#endif - -#ifndef CURL_TYPEOF_CURL_SOCKLEN_T -# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!" - Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing -#endif - -#ifndef CURL_SIZEOF_CURL_SOCKLEN_T -# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!" - Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing -#endif - -#ifndef CURL_TYPEOF_CURL_OFF_T -# error "CURL_TYPEOF_CURL_OFF_T definition is missing!" - Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing -#endif - -#ifndef CURL_FORMAT_CURL_OFF_T -# error "CURL_FORMAT_CURL_OFF_T definition is missing!" - Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing -#endif - -#ifndef CURL_FORMAT_CURL_OFF_TU -# error "CURL_FORMAT_CURL_OFF_TU definition is missing!" - Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing -#endif - -#ifndef CURL_FORMAT_OFF_T -# error "CURL_FORMAT_OFF_T definition is missing!" - Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing -#endif - -#ifndef CURL_SIZEOF_CURL_OFF_T -# error "CURL_SIZEOF_CURL_OFF_T definition is missing!" - Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing -#endif - -#ifndef CURL_SUFFIX_CURL_OFF_T -# error "CURL_SUFFIX_CURL_OFF_T definition is missing!" - Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing -#endif - -#ifndef CURL_SUFFIX_CURL_OFF_TU -# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!" - Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing -#endif - -/* - * Macros private to this header file. - */ - -#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1 - -#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1 - -/* - * Verify that the size previously defined and expected for long - * is the same as the one reported by sizeof() at compile time. - */ - -typedef char - __curl_rule_01__ - [CurlchkszEQ(long, CURL_SIZEOF_LONG)]; - -/* - * Verify that the size previously defined and expected for - * curl_off_t is actually the the same as the one reported - * by sizeof() at compile time. - */ - -typedef char - __curl_rule_02__ - [CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)]; - -/* - * Verify at compile time that the size of curl_off_t as reported - * by sizeof() is greater or equal than the one reported for long - * for the current compilation. - */ - -typedef char - __curl_rule_03__ - [CurlchkszGE(curl_off_t, long)]; - -/* - * Verify that the size previously defined and expected for - * curl_socklen_t is actually the the same as the one reported - * by sizeof() at compile time. - */ - -typedef char - __curl_rule_04__ - [CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)]; - -/* - * Verify at compile time that the size of curl_socklen_t as reported - * by sizeof() is greater or equal than the one reported for int for - * the current compilation. - */ - -typedef char - __curl_rule_05__ - [CurlchkszGE(curl_socklen_t, int)]; - -/* ================================================================ */ -/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */ -/* ================================================================ */ - -/* - * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow - * these to be visible and exported by the external libcurl interface API, - * while also making them visible to the library internals, simply including - * setup.h, without actually needing to include curl.h internally. - * If some day this section would grow big enough, all this should be moved - * to its own header file. - */ - -/* - * Figure out if we can use the ## preprocessor operator, which is supported - * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ - * or __cplusplus so we need to carefully check for them too. - */ - -#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ - defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ - defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ - defined(__ILEC400__) - /* This compiler is believed to have an ISO compatible preprocessor */ -#define CURL_ISOCPP -#else - /* This compiler is believed NOT to have an ISO compatible preprocessor */ -#undef CURL_ISOCPP -#endif - -/* - * Macros for minimum-width signed and unsigned curl_off_t integer constants. - */ - -#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) -# define __CURL_OFF_T_C_HLPR2(x) x -# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x) -# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ - __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) -# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ - __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) -#else -# ifdef CURL_ISOCPP -# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix -# else -# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix -# endif -# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix) -# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) -# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) -#endif - -/* - * Get rid of macros private to this header file. - */ - -#undef CurlchkszEQ -#undef CurlchkszGE - -/* - * Get rid of macros not intended to exist beyond this point. - */ - -#undef CURL_PULL_WS2TCPIP_H -#undef CURL_PULL_SYS_TYPES_H -#undef CURL_PULL_SYS_SOCKET_H -#undef CURL_PULL_STDINT_H -#undef CURL_PULL_INTTYPES_H - -#undef CURL_TYPEOF_CURL_SOCKLEN_T -#undef CURL_TYPEOF_CURL_OFF_T - -#ifdef CURL_NO_OLDIES -#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */ -#endif - -#endif /* __CURL_CURLRULES_H */ diff --git a/third_party/curl/include/curl/curlver.h b/third_party/curl/include/curl/curlver.h deleted file mode 100644 index 4db21857d..000000000 --- a/third_party/curl/include/curl/curlver.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef __CURL_CURLVER_H -#define __CURL_CURLVER_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 - 2011 Daniel Stenberg, ." - -/* This is the version number of the libcurl package from which this header - file origins: */ -#define LIBCURL_VERSION "7.21.6" - -/* The numeric version number is also available "in parts" by using these - defines: */ -#define LIBCURL_VERSION_MAJOR 7 -#define LIBCURL_VERSION_MINOR 21 -#define LIBCURL_VERSION_PATCH 6 - -/* This is the numeric version of the libcurl version number, meant for easier - parsing and comparions by programs. The LIBCURL_VERSION_NUM define will - always follow this syntax: - - 0xXXYYZZ - - Where XX, YY and ZZ are the main version, release and patch numbers in - hexadecimal (using 8 bits each). All three numbers are always represented - using two digits. 1.2 would appear as "0x010200" while version 9.11.7 - appears as "0x090b07". - - This 6-digit (24 bits) hexadecimal number does not show pre-release number, - and it is always a greater number in a more recent release. It makes - comparisons with greater than and less than work. -*/ -#define LIBCURL_VERSION_NUM 0x071506 - -/* - * This is the date and time when the full source package was created. The - * timestamp is not stored in git, as the timestamp is properly set in the - * tarballs by the maketgz script. - * - * The format of the date should follow this template: - * - * "Mon Feb 12 11:35:33 UTC 2007" - */ -#define LIBCURL_TIMESTAMP "Fri Apr 22 17:18:50 UTC 2011" - -#endif /* __CURL_CURLVER_H */ diff --git a/third_party/curl/include/curl/easy.h b/third_party/curl/include/curl/easy.h deleted file mode 100644 index c1e3e7609..000000000 --- a/third_party/curl/include/curl/easy.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef __CURL_EASY_H -#define __CURL_EASY_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif - -CURL_EXTERN CURL *curl_easy_init(void); -CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); -CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); -CURL_EXTERN void curl_easy_cleanup(CURL *curl); - -/* - * NAME curl_easy_getinfo() - * - * DESCRIPTION - * - * Request internal information from the curl session with this function. The - * third argument MUST be a pointer to a long, a pointer to a char * or a - * pointer to a double (as the documentation describes elsewhere). The data - * pointed to will be filled in accordingly and can be relied upon only if the - * function returns CURLE_OK. This function is intended to get used *AFTER* a - * performed transfer, all results from this function are undefined until the - * transfer is completed. - */ -CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); - - -/* - * NAME curl_easy_duphandle() - * - * DESCRIPTION - * - * Creates a new curl session handle with the same options set for the handle - * passed in. Duplicating a handle could only be a matter of cloning data and - * options, internal state info and things like persistent connections cannot - * be transferred. It is useful in multithreaded applications when you can run - * curl_easy_duphandle() for each new thread to avoid a series of identical - * curl_easy_setopt() invokes in every thread. - */ -CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl); - -/* - * NAME curl_easy_reset() - * - * DESCRIPTION - * - * Re-initializes a CURL handle to the default values. This puts back the - * handle to the same state as it was in when it was just created. - * - * It does keep: live connections, the Session ID cache, the DNS cache and the - * cookies. - */ -CURL_EXTERN void curl_easy_reset(CURL *curl); - -/* - * NAME curl_easy_recv() - * - * DESCRIPTION - * - * Receives data from the connected socket. Use after successful - * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. - */ -CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, - size_t *n); - -/* - * NAME curl_easy_send() - * - * DESCRIPTION - * - * Sends data over the connected socket. Use after successful - * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. - */ -CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, - size_t buflen, size_t *n); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/third_party/curl/include/curl/mprintf.h b/third_party/curl/include/curl/mprintf.h deleted file mode 100644 index de7dd2f3c..000000000 --- a/third_party/curl/include/curl/mprintf.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef __CURL_MPRINTF_H -#define __CURL_MPRINTF_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 -#include /* needed for FILE */ - -#include "curl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -CURL_EXTERN int curl_mprintf(const char *format, ...); -CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); -CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); -CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, - const char *format, ...); -CURL_EXTERN int curl_mvprintf(const char *format, va_list args); -CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); -CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); -CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, - const char *format, va_list args); -CURL_EXTERN char *curl_maprintf(const char *format, ...); -CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); - -#ifdef _MPRINTF_REPLACE -# undef printf -# undef fprintf -# undef sprintf -# undef vsprintf -# undef snprintf -# undef vprintf -# undef vfprintf -# undef vsnprintf -# undef aprintf -# undef vaprintf -# define printf curl_mprintf -# define fprintf curl_mfprintf -#ifdef CURLDEBUG -/* When built with CURLDEBUG we define away the sprintf() functions since we - don't want internal code to be using them */ -# define sprintf sprintf_was_used -# define vsprintf vsprintf_was_used -#else -# define sprintf curl_msprintf -# define vsprintf curl_mvsprintf -#endif -# define snprintf curl_msnprintf -# define vprintf curl_mvprintf -# define vfprintf curl_mvfprintf -# define vsnprintf curl_mvsnprintf -# define aprintf curl_maprintf -# define vaprintf curl_mvaprintf -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __CURL_MPRINTF_H */ diff --git a/third_party/curl/include/curl/multi.h b/third_party/curl/include/curl/multi.h deleted file mode 100644 index f96566669..000000000 --- a/third_party/curl/include/curl/multi.h +++ /dev/null @@ -1,345 +0,0 @@ -#ifndef __CURL_MULTI_H -#define __CURL_MULTI_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -/* - This is an "external" header file. Don't give away any internals here! - - GOALS - - o Enable a "pull" interface. The application that uses libcurl decides where - and when to ask libcurl to get/send data. - - o Enable multiple simultaneous transfers in the same thread without making it - complicated for the application. - - o Enable the application to select() on its own file descriptors and curl's - file descriptors simultaneous easily. - -*/ - -/* - * This header file should not really need to include "curl.h" since curl.h - * itself includes this file and we expect user applications to do #include - * without the need for especially including multi.h. - * - * For some reason we added this include here at one point, and rather than to - * break existing (wrongly written) libcurl applications, we leave it as-is - * but with this warning attached. - */ -#include "curl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void CURLM; - -typedef enum { - CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or - curl_multi_socket*() soon */ - CURLM_OK, - CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ - CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ - CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ - CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ - CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ - CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ - CURLM_LAST -} CURLMcode; - -/* just to make code nicer when using curl_multi_socket() you can now check - for CURLM_CALL_MULTI_SOCKET too in the same style it works for - curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ -#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM - -typedef enum { - CURLMSG_NONE, /* first, not used */ - CURLMSG_DONE, /* This easy handle has completed. 'result' contains - the CURLcode of the transfer */ - CURLMSG_LAST /* last, not used */ -} CURLMSG; - -struct CURLMsg { - CURLMSG msg; /* what this message means */ - CURL *easy_handle; /* the handle it concerns */ - union { - void *whatever; /* message-specific data */ - CURLcode result; /* return code for transfer */ - } data; -}; -typedef struct CURLMsg CURLMsg; - -/* - * Name: curl_multi_init() - * - * Desc: inititalize multi-style curl usage - * - * Returns: a new CURLM handle to use in all 'curl_multi' functions. - */ -CURL_EXTERN CURLM *curl_multi_init(void); - -/* - * Name: curl_multi_add_handle() - * - * Desc: add a standard curl handle to the multi stack - * - * Returns: CURLMcode type, general multi error code. - */ -CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, - CURL *curl_handle); - - /* - * Name: curl_multi_remove_handle() - * - * Desc: removes a curl handle from the multi stack again - * - * Returns: CURLMcode type, general multi error code. - */ -CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, - CURL *curl_handle); - - /* - * Name: curl_multi_fdset() - * - * Desc: Ask curl for its fd_set sets. The app can use these to select() or - * poll() on. We want curl_multi_perform() called as soon as one of - * them are ready. - * - * Returns: CURLMcode type, general multi error code. - */ -CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, - fd_set *read_fd_set, - fd_set *write_fd_set, - fd_set *exc_fd_set, - int *max_fd); - - /* - * Name: curl_multi_perform() - * - * Desc: When the app thinks there's data available for curl it calls this - * function to read/write whatever there is right now. This returns - * as soon as the reads and writes are done. This function does not - * require that there actually is data available for reading or that - * data can be written, it can be called just in case. It returns - * the number of handles that still transfer data in the second - * argument's integer-pointer. - * - * Returns: CURLMcode type, general multi error code. *NOTE* that this only - * returns errors etc regarding the whole multi stack. There might - * still have occurred problems on invidual transfers even when this - * returns OK. - */ -CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, - int *running_handles); - - /* - * Name: curl_multi_cleanup() - * - * Desc: Cleans up and removes a whole multi stack. It does not free or - * touch any individual easy handles in any way. We need to define - * in what state those handles will be if this function is called - * in the middle of a transfer. - * - * Returns: CURLMcode type, general multi error code. - */ -CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); - -/* - * Name: curl_multi_info_read() - * - * Desc: Ask the multi handle if there's any messages/informationals from - * the individual transfers. Messages include informationals such as - * error code from the transfer or just the fact that a transfer is - * completed. More details on these should be written down as well. - * - * Repeated calls to this function will return a new struct each - * time, until a special "end of msgs" struct is returned as a signal - * that there is no more to get at this point. - * - * The data the returned pointer points to will not survive calling - * curl_multi_cleanup(). - * - * The 'CURLMsg' struct is meant to be very simple and only contain - * very basic informations. If more involved information is wanted, - * we will provide the particular "transfer handle" in that struct - * and that should/could/would be used in subsequent - * curl_easy_getinfo() calls (or similar). The point being that we - * must never expose complex structs to applications, as then we'll - * undoubtably get backwards compatibility problems in the future. - * - * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out - * of structs. It also writes the number of messages left in the - * queue (after this read) in the integer the second argument points - * to. - */ -CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, - int *msgs_in_queue); - -/* - * Name: curl_multi_strerror() - * - * Desc: The curl_multi_strerror function may be used to turn a CURLMcode - * value into the equivalent human readable error string. This is - * useful for printing meaningful error messages. - * - * Returns: A pointer to a zero-terminated error message. - */ -CURL_EXTERN const char *curl_multi_strerror(CURLMcode); - -/* - * Name: curl_multi_socket() and - * curl_multi_socket_all() - * - * Desc: An alternative version of curl_multi_perform() that allows the - * application to pass in one of the file descriptors that have been - * detected to have "action" on them and let libcurl perform. - * See man page for details. - */ -#define CURL_POLL_NONE 0 -#define CURL_POLL_IN 1 -#define CURL_POLL_OUT 2 -#define CURL_POLL_INOUT 3 -#define CURL_POLL_REMOVE 4 - -#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD - -#define CURL_CSELECT_IN 0x01 -#define CURL_CSELECT_OUT 0x02 -#define CURL_CSELECT_ERR 0x04 - -typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ - curl_socket_t s, /* socket */ - int what, /* see above */ - void *userp, /* private callback - pointer */ - void *socketp); /* private socket - pointer */ -/* - * Name: curl_multi_timer_callback - * - * Desc: Called by libcurl whenever the library detects a change in the - * maximum number of milliseconds the app is allowed to wait before - * curl_multi_socket() or curl_multi_perform() must be called - * (to allow libcurl's timed events to take place). - * - * Returns: The callback should return zero. - */ -typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ - long timeout_ms, /* see above */ - void *userp); /* private callback - pointer */ - -CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, - int *running_handles); - -CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, - curl_socket_t s, - int ev_bitmask, - int *running_handles); - -CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, - int *running_handles); - -#ifndef CURL_ALLOW_OLD_MULTI_SOCKET -/* This macro below was added in 7.16.3 to push users who recompile to use - the new curl_multi_socket_action() instead of the old curl_multi_socket() -*/ -#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) -#endif - -/* - * Name: curl_multi_timeout() - * - * Desc: Returns the maximum number of milliseconds the app is allowed to - * wait before curl_multi_socket() or curl_multi_perform() must be - * called (to allow libcurl's timed events to take place). - * - * Returns: CURLM error code. - */ -CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, - long *milliseconds); - -#undef CINIT /* re-using the same name as in curl.h */ - -#ifdef CURL_ISOCPP -#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num -#else -/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ -#define LONG CURLOPTTYPE_LONG -#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT -#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT -#define OFF_T CURLOPTTYPE_OFF_T -#define CINIT(name,type,number) CURLMOPT_/**/name = type + number -#endif - -typedef enum { - /* This is the socket callback function pointer */ - CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1), - - /* This is the argument passed to the socket callback */ - CINIT(SOCKETDATA, OBJECTPOINT, 2), - - /* set to 1 to enable pipelining for this multi handle */ - CINIT(PIPELINING, LONG, 3), - - /* This is the timer callback function pointer */ - CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4), - - /* This is the argument passed to the timer callback */ - CINIT(TIMERDATA, OBJECTPOINT, 5), - - /* maximum number of entries in the connection cache */ - CINIT(MAXCONNECTS, LONG, 6), - - CURLMOPT_LASTENTRY /* the last unused */ -} CURLMoption; - - -/* - * Name: curl_multi_setopt() - * - * Desc: Sets options for the multi handle. - * - * Returns: CURLM error code. - */ -CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, - CURLMoption option, ...); - - -/* - * Name: curl_multi_assign() - * - * Desc: This function sets an association in the multi handle between the - * given socket and a private pointer of the application. This is - * (only) useful for curl_multi_socket uses. - * - * Returns: CURLM error code. - */ -CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, - curl_socket_t sockfd, void *sockp); - -#ifdef __cplusplus -} /* end of extern "C" */ -#endif - -#endif diff --git a/third_party/curl/include/curl/stdcheaders.h b/third_party/curl/include/curl/stdcheaders.h deleted file mode 100644 index ad82ef633..000000000 --- a/third_party/curl/include/curl/stdcheaders.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __STDC_HEADERS_H -#define __STDC_HEADERS_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 - -size_t fread (void *, size_t, size_t, FILE *); -size_t fwrite (const void *, size_t, size_t, FILE *); - -int strcasecmp(const char *, const char *); -int strncasecmp(const char *, const char *, size_t); - -#endif /* __STDC_HEADERS_H */ diff --git a/third_party/curl/include/curl/typecheck-gcc.h b/third_party/curl/include/curl/typecheck-gcc.h deleted file mode 100644 index 46f92d728..000000000 --- a/third_party/curl/include/curl/typecheck-gcc.h +++ /dev/null @@ -1,584 +0,0 @@ -#ifndef __CURL_TYPECHECK_GCC_H -#define __CURL_TYPECHECK_GCC_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* wraps curl_easy_setopt() with typechecking */ - -/* To add a new kind of warning, add an - * if(_curl_is_sometype_option(_curl_opt)) - * if(!_curl_is_sometype(value)) - * _curl_easy_setopt_err_sometype(); - * block and define _curl_is_sometype_option, _curl_is_sometype and - * _curl_easy_setopt_err_sometype below - * - * NOTE: We use two nested 'if' statements here instead of the && operator, in - * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x - * when compiling with -Wlogical-op. - * - * To add an option that uses the same type as an existing option, you'll just - * need to extend the appropriate _curl_*_option macro - */ -#define curl_easy_setopt(handle, option, value) \ -__extension__ ({ \ - __typeof__ (option) _curl_opt = option; \ - if (__builtin_constant_p(_curl_opt)) { \ - if (_curl_is_long_option(_curl_opt)) \ - if (!_curl_is_long(value)) \ - _curl_easy_setopt_err_long(); \ - if (_curl_is_off_t_option(_curl_opt)) \ - if (!_curl_is_off_t(value)) \ - _curl_easy_setopt_err_curl_off_t(); \ - if (_curl_is_string_option(_curl_opt)) \ - if (!_curl_is_string(value)) \ - _curl_easy_setopt_err_string(); \ - if (_curl_is_write_cb_option(_curl_opt)) \ - if (!_curl_is_write_cb(value)) \ - _curl_easy_setopt_err_write_callback(); \ - if ((_curl_opt) == CURLOPT_READFUNCTION) \ - if (!_curl_is_read_cb(value)) \ - _curl_easy_setopt_err_read_cb(); \ - if ((_curl_opt) == CURLOPT_IOCTLFUNCTION) \ - if (!_curl_is_ioctl_cb(value)) \ - _curl_easy_setopt_err_ioctl_cb(); \ - if ((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \ - if (!_curl_is_sockopt_cb(value)) \ - _curl_easy_setopt_err_sockopt_cb(); \ - if ((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \ - if (!_curl_is_opensocket_cb(value)) \ - _curl_easy_setopt_err_opensocket_cb(); \ - if ((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \ - if (!_curl_is_progress_cb(value)) \ - _curl_easy_setopt_err_progress_cb(); \ - if ((_curl_opt) == CURLOPT_DEBUGFUNCTION) \ - if (!_curl_is_debug_cb(value)) \ - _curl_easy_setopt_err_debug_cb(); \ - if ((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \ - if (!_curl_is_ssl_ctx_cb(value)) \ - _curl_easy_setopt_err_ssl_ctx_cb(); \ - if (_curl_is_conv_cb_option(_curl_opt)) \ - if (!_curl_is_conv_cb(value)) \ - _curl_easy_setopt_err_conv_cb(); \ - if ((_curl_opt) == CURLOPT_SEEKFUNCTION) \ - if (!_curl_is_seek_cb(value)) \ - _curl_easy_setopt_err_seek_cb(); \ - if (_curl_is_cb_data_option(_curl_opt)) \ - if (!_curl_is_cb_data(value)) \ - _curl_easy_setopt_err_cb_data(); \ - if ((_curl_opt) == CURLOPT_ERRORBUFFER) \ - if (!_curl_is_error_buffer(value)) \ - _curl_easy_setopt_err_error_buffer(); \ - if ((_curl_opt) == CURLOPT_STDERR) \ - if (!_curl_is_FILE(value)) \ - _curl_easy_setopt_err_FILE(); \ - if (_curl_is_postfields_option(_curl_opt)) \ - if (!_curl_is_postfields(value)) \ - _curl_easy_setopt_err_postfields(); \ - if ((_curl_opt) == CURLOPT_HTTPPOST) \ - if (!_curl_is_arr((value), struct curl_httppost)) \ - _curl_easy_setopt_err_curl_httpost(); \ - if (_curl_is_slist_option(_curl_opt)) \ - if (!_curl_is_arr((value), struct curl_slist)) \ - _curl_easy_setopt_err_curl_slist(); \ - if ((_curl_opt) == CURLOPT_SHARE) \ - if (!_curl_is_ptr((value), CURLSH)) \ - _curl_easy_setopt_err_CURLSH(); \ - } \ - curl_easy_setopt(handle, _curl_opt, value); \ -}) - -/* wraps curl_easy_getinfo() with typechecking */ -/* FIXME: don't allow const pointers */ -#define curl_easy_getinfo(handle, info, arg) \ -__extension__ ({ \ - __typeof__ (info) _curl_info = info; \ - if (__builtin_constant_p(_curl_info)) { \ - if (_curl_is_string_info(_curl_info)) \ - if (!_curl_is_arr((arg), char *)) \ - _curl_easy_getinfo_err_string(); \ - if (_curl_is_long_info(_curl_info)) \ - if (!_curl_is_arr((arg), long)) \ - _curl_easy_getinfo_err_long(); \ - if (_curl_is_double_info(_curl_info)) \ - if (!_curl_is_arr((arg), double)) \ - _curl_easy_getinfo_err_double(); \ - if (_curl_is_slist_info(_curl_info)) \ - if (!_curl_is_arr((arg), struct curl_slist *)) \ - _curl_easy_getinfo_err_curl_slist(); \ - } \ - curl_easy_getinfo(handle, _curl_info, arg); \ -}) - -/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(), - * for now just make sure that the functions are called with three - * arguments - */ -#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) -#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) - - -/* the actual warnings, triggered by calling the _curl_easy_setopt_err* - * functions */ - -/* To define a new warning, use _CURL_WARNING(identifier, "message") */ -#define _CURL_WARNING(id, message) \ - static void __attribute__((warning(message))) __attribute__((unused)) \ - __attribute__((noinline)) id(void) { __asm__(""); } - -_CURL_WARNING(_curl_easy_setopt_err_long, - "curl_easy_setopt expects a long argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_curl_off_t, - "curl_easy_setopt expects a curl_off_t argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_string, - "curl_easy_setopt expects a string (char* or char[]) argument for this option" - ) -_CURL_WARNING(_curl_easy_setopt_err_write_callback, - "curl_easy_setopt expects a curl_write_callback argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_read_cb, - "curl_easy_setopt expects a curl_read_callback argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb, - "curl_easy_setopt expects a curl_ioctl_callback argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb, - "curl_easy_setopt expects a curl_sockopt_callback argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb, - "curl_easy_setopt expects a curl_opensocket_callback argument for this option" - ) -_CURL_WARNING(_curl_easy_setopt_err_progress_cb, - "curl_easy_setopt expects a curl_progress_callback argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_debug_cb, - "curl_easy_setopt expects a curl_debug_callback argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb, - "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_conv_cb, - "curl_easy_setopt expects a curl_conv_callback argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_seek_cb, - "curl_easy_setopt expects a curl_seek_callback argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_cb_data, - "curl_easy_setopt expects a private data pointer as argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_error_buffer, - "curl_easy_setopt expects a char buffer of CURL_ERROR_SIZE as argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_FILE, - "curl_easy_setopt expects a FILE* argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_postfields, - "curl_easy_setopt expects a void* or char* argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_curl_httpost, - "curl_easy_setopt expects a struct curl_httppost* argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_curl_slist, - "curl_easy_setopt expects a struct curl_slist* argument for this option") -_CURL_WARNING(_curl_easy_setopt_err_CURLSH, - "curl_easy_setopt expects a CURLSH* argument for this option") - -_CURL_WARNING(_curl_easy_getinfo_err_string, - "curl_easy_getinfo expects a pointer to char * for this info") -_CURL_WARNING(_curl_easy_getinfo_err_long, - "curl_easy_getinfo expects a pointer to long for this info") -_CURL_WARNING(_curl_easy_getinfo_err_double, - "curl_easy_getinfo expects a pointer to double for this info") -_CURL_WARNING(_curl_easy_getinfo_err_curl_slist, - "curl_easy_getinfo expects a pointer to struct curl_slist * for this info") - -/* groups of curl_easy_setops options that take the same type of argument */ - -/* To add a new option to one of the groups, just add - * (option) == CURLOPT_SOMETHING - * to the or-expression. If the option takes a long or curl_off_t, you don't - * have to do anything - */ - -/* evaluates to true if option takes a long argument */ -#define _curl_is_long_option(option) \ - (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) - -#define _curl_is_off_t_option(option) \ - ((option) > CURLOPTTYPE_OFF_T) - -/* evaluates to true if option takes a char* argument */ -#define _curl_is_string_option(option) \ - ((option) == CURLOPT_URL || \ - (option) == CURLOPT_PROXY || \ - (option) == CURLOPT_INTERFACE || \ - (option) == CURLOPT_NETRC_FILE || \ - (option) == CURLOPT_USERPWD || \ - (option) == CURLOPT_USERNAME || \ - (option) == CURLOPT_PASSWORD || \ - (option) == CURLOPT_PROXYUSERPWD || \ - (option) == CURLOPT_PROXYUSERNAME || \ - (option) == CURLOPT_PROXYPASSWORD || \ - (option) == CURLOPT_NOPROXY || \ - (option) == CURLOPT_ACCEPT_ENCODING || \ - (option) == CURLOPT_REFERER || \ - (option) == CURLOPT_USERAGENT || \ - (option) == CURLOPT_COOKIE || \ - (option) == CURLOPT_COOKIEFILE || \ - (option) == CURLOPT_COOKIEJAR || \ - (option) == CURLOPT_COOKIELIST || \ - (option) == CURLOPT_FTPPORT || \ - (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ - (option) == CURLOPT_FTP_ACCOUNT || \ - (option) == CURLOPT_RANGE || \ - (option) == CURLOPT_CUSTOMREQUEST || \ - (option) == CURLOPT_SSLCERT || \ - (option) == CURLOPT_SSLCERTTYPE || \ - (option) == CURLOPT_SSLKEY || \ - (option) == CURLOPT_SSLKEYTYPE || \ - (option) == CURLOPT_KEYPASSWD || \ - (option) == CURLOPT_SSLENGINE || \ - (option) == CURLOPT_CAINFO || \ - (option) == CURLOPT_CAPATH || \ - (option) == CURLOPT_RANDOM_FILE || \ - (option) == CURLOPT_EGDSOCKET || \ - (option) == CURLOPT_SSL_CIPHER_LIST || \ - (option) == CURLOPT_KRBLEVEL || \ - (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ - (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ - (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ - (option) == CURLOPT_CRLFILE || \ - (option) == CURLOPT_ISSUERCERT || \ - (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ - (option) == CURLOPT_SSH_KNOWNHOSTS || \ - (option) == CURLOPT_MAIL_FROM || \ - (option) == CURLOPT_RTSP_SESSION_ID || \ - (option) == CURLOPT_RTSP_STREAM_URI || \ - (option) == CURLOPT_RTSP_TRANSPORT || \ - 0) - -/* evaluates to true if option takes a curl_write_callback argument */ -#define _curl_is_write_cb_option(option) \ - ((option) == CURLOPT_HEADERFUNCTION || \ - (option) == CURLOPT_WRITEFUNCTION) - -/* evaluates to true if option takes a curl_conv_callback argument */ -#define _curl_is_conv_cb_option(option) \ - ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ - (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ - (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) - -/* evaluates to true if option takes a data argument to pass to a callback */ -#define _curl_is_cb_data_option(option) \ - ((option) == CURLOPT_WRITEDATA || \ - (option) == CURLOPT_READDATA || \ - (option) == CURLOPT_IOCTLDATA || \ - (option) == CURLOPT_SOCKOPTDATA || \ - (option) == CURLOPT_OPENSOCKETDATA || \ - (option) == CURLOPT_PROGRESSDATA || \ - (option) == CURLOPT_WRITEHEADER || \ - (option) == CURLOPT_DEBUGDATA || \ - (option) == CURLOPT_SSL_CTX_DATA || \ - (option) == CURLOPT_SEEKDATA || \ - (option) == CURLOPT_PRIVATE || \ - (option) == CURLOPT_SSH_KEYDATA || \ - (option) == CURLOPT_INTERLEAVEDATA || \ - (option) == CURLOPT_CHUNK_DATA || \ - (option) == CURLOPT_FNMATCH_DATA || \ - 0) - -/* evaluates to true if option takes a POST data argument (void* or char*) */ -#define _curl_is_postfields_option(option) \ - ((option) == CURLOPT_POSTFIELDS || \ - (option) == CURLOPT_COPYPOSTFIELDS || \ - 0) - -/* evaluates to true if option takes a struct curl_slist * argument */ -#define _curl_is_slist_option(option) \ - ((option) == CURLOPT_HTTPHEADER || \ - (option) == CURLOPT_HTTP200ALIASES || \ - (option) == CURLOPT_QUOTE || \ - (option) == CURLOPT_POSTQUOTE || \ - (option) == CURLOPT_PREQUOTE || \ - (option) == CURLOPT_TELNETOPTIONS || \ - (option) == CURLOPT_MAIL_RCPT || \ - 0) - -/* groups of curl_easy_getinfo infos that take the same type of argument */ - -/* evaluates to true if info expects a pointer to char * argument */ -#define _curl_is_string_info(info) \ - (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG) - -/* evaluates to true if info expects a pointer to long argument */ -#define _curl_is_long_info(info) \ - (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) - -/* evaluates to true if info expects a pointer to double argument */ -#define _curl_is_double_info(info) \ - (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) - -/* true if info expects a pointer to struct curl_slist * argument */ -#define _curl_is_slist_info(info) \ - (CURLINFO_SLIST < (info)) - - -/* typecheck helpers -- check whether given expression has requested type*/ - -/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros, - * otherwise define a new macro. Search for __builtin_types_compatible_p - * in the GCC manual. - * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is - * the actual expression passed to the curl_easy_setopt macro. This - * means that you can only apply the sizeof and __typeof__ operators, no - * == or whatsoever. - */ - -/* XXX: should evaluate to true iff expr is a pointer */ -#define _curl_is_any_ptr(expr) \ - (sizeof(expr) == sizeof(void*)) - -/* evaluates to true if expr is NULL */ -/* XXX: must not evaluate expr, so this check is not accurate */ -#define _curl_is_NULL(expr) \ - (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) - -/* evaluates to true if expr is type*, const type* or NULL */ -#define _curl_is_ptr(expr, type) \ - (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), type *) || \ - __builtin_types_compatible_p(__typeof__(expr), const type *)) - -/* evaluates to true if expr is one of type[], type*, NULL or const type* */ -#define _curl_is_arr(expr, type) \ - (_curl_is_ptr((expr), type) || \ - __builtin_types_compatible_p(__typeof__(expr), type [])) - -/* evaluates to true if expr is a string */ -#define _curl_is_string(expr) \ - (_curl_is_arr((expr), char) || \ - _curl_is_arr((expr), signed char) || \ - _curl_is_arr((expr), unsigned char)) - -/* evaluates to true if expr is a long (no matter the signedness) - * XXX: for now, int is also accepted (and therefore short and char, which - * are promoted to int when passed to a variadic function) */ -#define _curl_is_long(expr) \ - (__builtin_types_compatible_p(__typeof__(expr), long) || \ - __builtin_types_compatible_p(__typeof__(expr), signed long) || \ - __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ - __builtin_types_compatible_p(__typeof__(expr), int) || \ - __builtin_types_compatible_p(__typeof__(expr), signed int) || \ - __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ - __builtin_types_compatible_p(__typeof__(expr), short) || \ - __builtin_types_compatible_p(__typeof__(expr), signed short) || \ - __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ - __builtin_types_compatible_p(__typeof__(expr), char) || \ - __builtin_types_compatible_p(__typeof__(expr), signed char) || \ - __builtin_types_compatible_p(__typeof__(expr), unsigned char)) - -/* evaluates to true if expr is of type curl_off_t */ -#define _curl_is_off_t(expr) \ - (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) - -/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ -/* XXX: also check size of an char[] array? */ -#define _curl_is_error_buffer(expr) \ - (__builtin_types_compatible_p(__typeof__(expr), char *) || \ - __builtin_types_compatible_p(__typeof__(expr), char[])) - -/* evaluates to true if expr is of type (const) void* or (const) FILE* */ -#if 0 -#define _curl_is_cb_data(expr) \ - (_curl_is_ptr((expr), void) || \ - _curl_is_ptr((expr), FILE)) -#else /* be less strict */ -#define _curl_is_cb_data(expr) \ - _curl_is_any_ptr(expr) -#endif - -/* evaluates to true if expr is of type FILE* */ -#define _curl_is_FILE(expr) \ - (__builtin_types_compatible_p(__typeof__(expr), FILE *)) - -/* evaluates to true if expr can be passed as POST data (void* or char*) */ -#define _curl_is_postfields(expr) \ - (_curl_is_ptr((expr), void) || \ - _curl_is_arr((expr), char)) - -/* FIXME: the whole callback checking is messy... - * The idea is to tolerate char vs. void and const vs. not const - * pointers in arguments at least - */ -/* helper: __builtin_types_compatible_p distinguishes between functions and - * function pointers, hide it */ -#define _curl_callback_compatible(func, type) \ - (__builtin_types_compatible_p(__typeof__(func), type) || \ - __builtin_types_compatible_p(__typeof__(func), type*)) - -/* evaluates to true if expr is of type curl_read_callback or "similar" */ -#define _curl_is_read_cb(expr) \ - (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \ - _curl_callback_compatible((expr), _curl_read_callback1) || \ - _curl_callback_compatible((expr), _curl_read_callback2) || \ - _curl_callback_compatible((expr), _curl_read_callback3) || \ - _curl_callback_compatible((expr), _curl_read_callback4) || \ - _curl_callback_compatible((expr), _curl_read_callback5) || \ - _curl_callback_compatible((expr), _curl_read_callback6)) -typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*); -typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*); -typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*); -typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*); -typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*); -typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*); - -/* evaluates to true if expr is of type curl_write_callback or "similar" */ -#define _curl_is_write_cb(expr) \ - (_curl_is_read_cb(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \ - _curl_callback_compatible((expr), _curl_write_callback1) || \ - _curl_callback_compatible((expr), _curl_write_callback2) || \ - _curl_callback_compatible((expr), _curl_write_callback3) || \ - _curl_callback_compatible((expr), _curl_write_callback4) || \ - _curl_callback_compatible((expr), _curl_write_callback5) || \ - _curl_callback_compatible((expr), _curl_write_callback6)) -typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*); -typedef size_t (_curl_write_callback2)(const char *, size_t, size_t, - const void*); -typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*); -typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*); -typedef size_t (_curl_write_callback5)(const void *, size_t, size_t, - const void*); -typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*); - -/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ -#define _curl_is_ioctl_cb(expr) \ - (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \ - _curl_callback_compatible((expr), _curl_ioctl_callback1) || \ - _curl_callback_compatible((expr), _curl_ioctl_callback2) || \ - _curl_callback_compatible((expr), _curl_ioctl_callback3) || \ - _curl_callback_compatible((expr), _curl_ioctl_callback4)) -typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*); -typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*); -typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*); -typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*); - -/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ -#define _curl_is_sockopt_cb(expr) \ - (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \ - _curl_callback_compatible((expr), _curl_sockopt_callback1) || \ - _curl_callback_compatible((expr), _curl_sockopt_callback2)) -typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); -typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t, - curlsocktype); - -/* evaluates to true if expr is of type curl_opensocket_callback or "similar" */ -#define _curl_is_opensocket_cb(expr) \ - (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\ - _curl_callback_compatible((expr), _curl_opensocket_callback1) || \ - _curl_callback_compatible((expr), _curl_opensocket_callback2) || \ - _curl_callback_compatible((expr), _curl_opensocket_callback3) || \ - _curl_callback_compatible((expr), _curl_opensocket_callback4)) -typedef curl_socket_t (_curl_opensocket_callback1) - (void *, curlsocktype, struct curl_sockaddr *); -typedef curl_socket_t (_curl_opensocket_callback2) - (void *, curlsocktype, const struct curl_sockaddr *); -typedef curl_socket_t (_curl_opensocket_callback3) - (const void *, curlsocktype, struct curl_sockaddr *); -typedef curl_socket_t (_curl_opensocket_callback4) - (const void *, curlsocktype, const struct curl_sockaddr *); - -/* evaluates to true if expr is of type curl_progress_callback or "similar" */ -#define _curl_is_progress_cb(expr) \ - (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \ - _curl_callback_compatible((expr), _curl_progress_callback1) || \ - _curl_callback_compatible((expr), _curl_progress_callback2)) -typedef int (_curl_progress_callback1)(void *, - double, double, double, double); -typedef int (_curl_progress_callback2)(const void *, - double, double, double, double); - -/* evaluates to true if expr is of type curl_debug_callback or "similar" */ -#define _curl_is_debug_cb(expr) \ - (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \ - _curl_callback_compatible((expr), _curl_debug_callback1) || \ - _curl_callback_compatible((expr), _curl_debug_callback2) || \ - _curl_callback_compatible((expr), _curl_debug_callback3) || \ - _curl_callback_compatible((expr), _curl_debug_callback4)) -typedef int (_curl_debug_callback1) (CURL *, - curl_infotype, char *, size_t, void *); -typedef int (_curl_debug_callback2) (CURL *, - curl_infotype, char *, size_t, const void *); -typedef int (_curl_debug_callback3) (CURL *, - curl_infotype, const char *, size_t, void *); -typedef int (_curl_debug_callback4) (CURL *, - curl_infotype, const char *, size_t, const void *); - -/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ -/* this is getting even messier... */ -#define _curl_is_ssl_ctx_cb(expr) \ - (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \ - _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \ - _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \ - _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \ - _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \ - _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \ - _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \ - _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \ - _curl_callback_compatible((expr), _curl_ssl_ctx_callback8)) -typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *); -typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *); -typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *); -typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *); -#ifdef HEADER_SSL_H -/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX - * this will of course break if we're included before OpenSSL headers... - */ -typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); -typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); -typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); -typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, const void *); -#else -typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; -typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; -typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7; -typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; -#endif - -/* evaluates to true if expr is of type curl_conv_callback or "similar" */ -#define _curl_is_conv_cb(expr) \ - (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \ - _curl_callback_compatible((expr), _curl_conv_callback1) || \ - _curl_callback_compatible((expr), _curl_conv_callback2) || \ - _curl_callback_compatible((expr), _curl_conv_callback3) || \ - _curl_callback_compatible((expr), _curl_conv_callback4)) -typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); -typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length); -typedef CURLcode (*_curl_conv_callback3)(void *, size_t length); -typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); - -/* evaluates to true if expr is of type curl_seek_callback or "similar" */ -#define _curl_is_seek_cb(expr) \ - (_curl_is_NULL(expr) || \ - __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \ - _curl_callback_compatible((expr), _curl_seek_callback1) || \ - _curl_callback_compatible((expr), _curl_seek_callback2)) -typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); -typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int); - - -#endif /* __CURL_TYPECHECK_GCC_H */ diff --git a/third_party/curl/include/curl/types.h b/third_party/curl/include/curl/types.h deleted file mode 100644 index d37d6ae9e..000000000 --- a/third_party/curl/include/curl/types.h +++ /dev/null @@ -1 +0,0 @@ -/* not used */ diff --git a/third_party/curl/lib/CMakeLists.txt b/third_party/curl/lib/CMakeLists.txt deleted file mode 100644 index aec1a3c5b..000000000 --- a/third_party/curl/lib/CMakeLists.txt +++ /dev/null @@ -1,124 +0,0 @@ -set(LIB_NAME libcurl) - -configure_file(${CURL_SOURCE_DIR}/include/curl/curlbuild.h.cmake - ${CURL_BINARY_DIR}/include/curl/curlbuild.h) -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 - ${CURL_BINARY_DIR}/include/curl/curlbuild.h - ) - -if(MSVC) - list(APPEND CSOURCES libcurl.rc) -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) - -if(HAVE_FEATURES_H) - set_source_files_properties( - cookie.c - easy.c - formdata.c - getenv.c - nonblock.c - hash.c - http.c - if2ip.c - mprintf.c - multi.c - sendf.c - telnet.c - transfer.c - url.c - COMPILE_FLAGS -D_BSD_SOURCE) -endif(HAVE_FEATURES_H) - - -# 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(CURL_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() - -add_library( - ${LIB_NAME} - ${CURL_USER_DEFINED_DYNAMIC_OR_STATIC} - ${HHEADERS} ${CSOURCES} - ) - -target_link_libraries(${LIB_NAME} ${CURL_LIBS}) - -if(WIN32) - add_definitions( -D_USRDLL ) -endif() - -set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL) - -setup_curl_dependencies(${LIB_NAME}) - -# 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(MSVC) - if(NOT BUILD_RELEASE_DEBUG_DIRS) - # Ugly workaround to remove the "/debug" or "/release" in each output - set_target_properties(${LIB_NAME} PROPERTIES PREFIX "../") - set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "../") - endif() -endif() - -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") - endif() -endif() diff --git a/third_party/curl/lib/Makefile.inc b/third_party/curl/lib/Makefile.inc deleted file mode 100644 index b6b8e773b..000000000 --- a/third_party/curl/lib/Makefile.inc +++ /dev/null @@ -1,40 +0,0 @@ -# ./lib/Makefile.inc -# Using the backslash as line continuation character might be problematic -# with some make flavours, as Watcom's wmake showed us already. If we -# ever want to change this in a portable manner then we should consider -# this idea (posted to the libcurl list by Adam Kellas): -# CSRC1 = file1.c file2.c file3.c -# CSRC2 = file4.c file5.c file6.c -# CSOURCES = $(CSRC1) $(CSRC2) - -CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ - cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \ - ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c \ - netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \ - curl_fnmatch.c fileinfo.c ftplistparser.c wildcard.c krb5.c \ - memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c \ - content_encoding.c share.c http_digest.c md4.c md5.c curl_rand.c \ - http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c \ - hostares.c hostasyn.c hostip4.c hostip6.c hostsyn.c hostthre.c \ - inet_ntop.c parsedate.c select.c gtls.c sslgen.c tftp.c splay.c \ - strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c \ - socks_gssapi.c socks_sspi.c curl_sspi.c slist.c nonblock.c \ - curl_memrchr.c imap.c pop3.c smtp.c pingpong.c rtsp.c curl_threads.c \ - warnless.c hmac.c polarssl.c curl_rtmp.c openldap.c curl_gethostname.c\ - gopher.c axtls.c idn_win32.c http_negotiate_sspi.c cyassl.c http_proxy.c \ - non-ascii.c - -HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \ - progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \ - if2ip.h speedcheck.h urldata.h curl_ldap.h ssluse.h escape.h telnet.h \ - getinfo.h strequal.h krb4.h memdebug.h http_chunks.h curl_rand.h \ - curl_fnmatch.h wildcard.h fileinfo.h ftplistparser.h strtok.h \ - connect.h llist.h hash.h content_encoding.h share.h curl_md4.h \ - curl_md5.h http_digest.h http_negotiate.h http_ntlm.h inet_pton.h \ - strtoofft.h strerror.h inet_ntop.h curlx.h curl_memory.h setup.h \ - transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h gtls.h \ - tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h nssg.h \ - curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.h slist.h nonblock.h \ - curl_memrchr.h imap.h pop3.h smtp.h pingpong.h rtsp.h curl_threads.h \ - warnless.h curl_hmac.h polarssl.h curl_rtmp.h curl_gethostname.h \ - gopher.h axtls.h cyassl.h http_proxy.h non-ascii.h diff --git a/third_party/curl/lib/README.ares b/third_party/curl/lib/README.ares deleted file mode 100644 index 8c77937eb..000000000 --- a/third_party/curl/lib/README.ares +++ /dev/null @@ -1,69 +0,0 @@ - _ _ ____ _ - ___| | | | _ \| | - / __| | | | |_) | | - | (__| |_| | _ <| |___ - \___|\___/|_| \_\_____| - - How To Build libcurl to Use c-ares For Asynch Name Resolves - =========================================================== - -c-ares: - http://c-ares.haxx.se/ - -NOTE - The latest libcurl version requires c-ares 1.6.0 or later. - - Once upon the time libcurl built fine with the "original" ares. That is no - longer true. You need to use c-ares. - -Build c-ares -============ - -1. unpack the c-ares archive -2. cd c-ares-dir -3. ./configure -4. make -5. make install - -Build libcurl to use c-ares in the curl source tree -=================================================== - -1. name or symlink the c-ares source directory 'ares' in the curl source - directory -2. ./configure --enable-ares - - Optionally, you can point out the c-ares install tree root with the the - --enable-ares option. - -3. make - -Build libcurl to use an installed c-ares -======================================== - -1. ./configure --enable-ares=/path/to/ares/install -2. make - -c-ares on win32 -=============== -(description brought by Dominick Meglio) - -First I compiled c-ares. I changed the default C runtime library to be the -single-threaded rather than the multi-threaded (this seems to be required to -prevent linking errors later on). Then I simply build the areslib project (the -other projects adig/ahost seem to fail under MSVC). - -Next was libcurl. I opened lib/config-win32.h and I added a: - #define USE_ARES 1 - -Next thing I did was I added the path for the ares includes to the include -path, and the libares.lib to the libraries. - -Lastly, I also changed libcurl to be single-threaded rather than -multi-threaded, again this was to prevent some duplicate symbol errors. I'm -not sure why I needed to change everything to single-threaded, but when I -didn't I got redefinition errors for several CRT functions (malloc, stricmp, -etc.) - -I would have modified the MSVC++ project files, but I only have VC.NET and it -uses a different format than VC6.0 so I didn't want to go and change -everything and remove VC6.0 support from libcurl. diff --git a/third_party/curl/lib/README.curl_off_t b/third_party/curl/lib/README.curl_off_t deleted file mode 100644 index 923b2774c..000000000 --- a/third_party/curl/lib/README.curl_off_t +++ /dev/null @@ -1,68 +0,0 @@ - - curl_off_t explained - ==================== - -curl_off_t is a data type provided by the external libcurl include headers. It -is the type meant to be used for the curl_easy_setopt() options that end with -LARGE. The type is 64bit large on most modern platforms. - -Transition from < 7.19.0 to >= 7.19.0 -------------------------------------- - -Applications that used libcurl before 7.19.0 that are rebuilt with a libcurl -that is 7.19.0 or later may or may not have to worry about anything of -this. We have made a significant effort to make the transition really seamless -and transparent. - -You have have to take notice if you are in one of the following situations: - -o Your app is using or will after the transition use a libcurl that is built - with LFS (large file support) disabled even though your system otherwise - supports it. - -o Your app is using or will after the transition use a libcurl that doesn't - support LFS at all, but your system and compiler support 64bit data types. - -In both these cases, the curl_off_t type will now (after the transition) be -64bit where it previously was 32bit. This will cause a binary incompatibility -that you MAY need to deal with. - -Benefits --------- - -This new way has several benefits: - -o Platforms without LFS support can still use libcurl to do >32 bit file - transfers and range operations etc as long as they have >32 bit data-types - supported. - -o Applications will no longer easily build with the curl_off_t size - mismatched, which has been a very frequent (and annoying) problem with - libcurl <= 7.18.2 - -Historically ------------- - -Previously, before 7.19.0, the curl_off_t type would be rather strongly -connected to the size of the system off_t type, where currently curl_off_t is -independent of that. - -The strong connection to off_t made it troublesome for application authors -since when they did mistakes, they could get curl_off_t type of different -sizes in the app vs libcurl, and that caused strange effects that were hard to -track and detect by users of libcurl. - -SONAME ------- - -We opted to not bump the soname for the library unconditionally, simply -because soname bumping is causing a lot of grief and moaning all over the -community so we try to keep that at minimum. Also, our selected design path -should be 100% backwards compatible for the vast majority of all libcurl -users. - -Enforce SONAME bump -------------------- - -If configure doesn't detect your case where a bump is necessary, re-run it -with the --enable-soname-bump command line option! diff --git a/third_party/curl/lib/README.curlx b/third_party/curl/lib/README.curlx deleted file mode 100644 index 5375b0d1d..000000000 --- a/third_party/curl/lib/README.curlx +++ /dev/null @@ -1,61 +0,0 @@ - _ _ ____ _ - ___| | | | _ \| | - / __| | | | |_) | | - | (__| |_| | _ <| |___ - \___|\___/|_| \_\_____| - - Source Code Functions Apps Might Use - ==================================== - -The libcurl source code offers a few functions by source only. They are not -part of the official libcurl API, but the source files might be useful for -others so apps can optionally compile/build with these sources to gain -additional functions. - -We provide them through a single header file for easy access for apps: -"curlx.h" - - curlx_strtoofft() - - A macro that converts a string containing a number to a curl_off_t number. - This might use the curlx_strtoll() function which is provided as source - code in strtoofft.c. Note that the function is only provided if no - strtoll() (or equivalent) function exist on your platform. If curl_off_t - is only a 32 bit number on your platform, this macro uses strtol(). - - curlx_tvnow() - - returns a struct timeval for the current time. - - curlx_tvdiff() - - returns the difference between two timeval structs, in number of - milliseconds. - - curlx_tvdiff_secs() - - returns the same as curlx_tvdiff but with full usec resolution (as a - double) - -FUTURE -====== - - Several functions will be removed from the public curl_ name space in a - future libcurl release. They will then only become available as curlx_ - functions instead. To make the transition easier, we already today provide - these functions with the curlx_ prefix to allow sources to get built properly - with the new function names. The functions this concerns are: - - curlx_getenv - curlx_strequal - curlx_strnequal - curlx_mvsnprintf - curlx_msnprintf - curlx_maprintf - curlx_mvaprintf - curlx_msprintf - curlx_mprintf - curlx_mfprintf - curlx_mvsprintf - curlx_mvprintf - curlx_mvfprintf diff --git a/third_party/curl/lib/README.encoding b/third_party/curl/lib/README.encoding deleted file mode 100644 index 1012bb9ec..000000000 --- a/third_party/curl/lib/README.encoding +++ /dev/null @@ -1,60 +0,0 @@ - - Content Encoding Support for libcurl - -* About content encodings: - -HTTP/1.1 [RFC 2616] specifies that a client may request that a server encode -its response. This is usually used to compress a response using one of a set -of commonly available compression techniques. These schemes are `deflate' (the -zlib algorithm), `gzip' and `compress' [sec 3.5, RFC 2616]. A client requests -that the sever perform an encoding by including an Accept-Encoding header in -the request document. The value of the header should be one of the recognized -tokens `deflate', ... (there's a way to register new schemes/tokens, see sec -3.5 of the spec). A server MAY honor the client's encoding request. When a -response is encoded, the server includes a Content-Encoding header in the -response. The value of the Content-Encoding header indicates which scheme was -used to encode the data. - -A client may tell a server that it can understand several different encoding -schemes. In this case the server may choose any one of those and use it to -encode the response (indicating which one using the Content-Encoding header). -It's also possible for a client to attach priorities to different schemes so -that the server knows which it prefers. See sec 14.3 of RFC 2616 for more -information on the Accept-Encoding header. - -* Current support for content encoding: - -Support for the 'deflate' and 'gzip' content encoding are supported by -libcurl. Both regular and chunked transfers should work fine. The library -zlib is required for this feature. 'deflate' support was added by James -Gallagher, and support for the 'gzip' encoding was added by Dan Fandrich. - -* The libcurl interface: - -To cause libcurl to request a content encoding use: - - curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ) - -where is the intended value of the Accept-Encoding header. - -Currently, libcurl only understands how to process responses that use the -"deflate" or "gzip" Content-Encoding, so the only values for -CURLOPT_ACCEPT_ENCODING that will work (besides "identity," which does -nothing) are "deflate" and "gzip" If a response is encoded using the -"compress" or methods, libcurl will return an error indicating that the -response could not be decoded. If is NULL no Accept-Encoding header -is generated. If is a zero-length string, then an Accept-Encoding -header containing all supported encodings will be generated. - -The CURLOPT_ACCEPT_ENCODING must be set to any non-NULL value for content to -be automatically decoded. If it is not set and the server still sends encoded -content (despite not having been asked), the data is returned in its raw form -and the Content-Encoding type is not checked. - -* The curl interface: - -Use the --compressed option with curl to cause it to ask servers to compress -responses using any format supported by curl. - -James Gallagher -Dan Fandrich diff --git a/third_party/curl/lib/README.hostip b/third_party/curl/lib/README.hostip deleted file mode 100644 index 9723b93fd..000000000 --- a/third_party/curl/lib/README.hostip +++ /dev/null @@ -1,35 +0,0 @@ - hostip.c explained - ================== - - The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c - source file are these: - - CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use - that. The host may not be able to resolve IPv6, but we don't really have to - take that into account. Hosts that aren't IPv6-enabled have CURLRES_IPV4 - defined. - - CURLRES_ARES - is defined if libcurl is built to use c-ares for asynchronous - name resolves. It cannot have ENABLE_IPV6 defined at the same time, as c-ares - has no ipv6 support. This can be Windows or *nix. - - CURLRES_THREADED - is defined if libcurl is built to run under (native) - Windows, and then the name resolve will be done in a new thread, and the - supported asynch API will be the same as for ares-builds. - - If any of the two previous are defined, CURLRES_ASYNCH is defined too. If - libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is - defined. - - The host*.c sources files are split up like this: - - hostip.c - method-independent resolver functions and utility functions - hostasyn.c - functions for asynchronous name resolves - hostsyn.c - functions for synchronous name resolves - hostares.c - functions for ares-using name resolves - hostthre.c - functions for threaded name resolves - hostip4.c - ipv4-specific functions - hostip6.c - ipv6-specific functions - - The hostip.h is the single united header file for all this. It defines the - CURLRES_* defines based on the config*.h and setup.h defines. diff --git a/third_party/curl/lib/README.httpauth b/third_party/curl/lib/README.httpauth deleted file mode 100644 index 960504510..000000000 --- a/third_party/curl/lib/README.httpauth +++ /dev/null @@ -1,74 +0,0 @@ - -1. PUT/POST without a known auth to use (possibly no auth required): - - (When explicitly set to use a multi-pass auth when doing a POST/PUT, - libcurl should immediately go the Content-Length: 0 bytes route to avoid - the first send all data phase, step 2. If told to use a single-pass auth, - goto step 3.) - - Issue the proper PUT/POST request immediately, with the correct - Content-Length and Expect: headers. - - If a 100 response is received or the wait for one times out, start sending - the request-body. - - If a 401 (or 407 when talking through a proxy) is received, then: - - If we have "more than just a little" data left to send, close the - connection. Exactly what "more than just a little" means will have to be - determined. Possibly the current transfer speed should be taken into - account as well. - - NOTE: if the size of the POST data is less than MAX_INITIAL_POST_SIZE (when - CURLOPT_POSTFIELDS is used), libcurl will send everything in one single - write() (all request-headers and request-body) and thus it will - unconditionally send the full post data here. - -2. PUT/POST with multi-pass auth but not yet completely negotiated: - - Send a PUT/POST request, we know that it will be rejected and thus we claim - Content-Length zero to avoid having to send the request-body. (This seems - to be what IE does.) - -3. PUT/POST as the last step in the auth negotiation, that is when we have - what we believe is a completed negotiation: - - Send a full and proper PUT/POST request (again) with the proper - Content-Length and a following request-body. - - NOTE: this may very well be the second (or even third) time the whole or at - least parts of the request body is sent to the server. Since the data may - be provided to libcurl with a callback, we need a way to tell the app that - the upload is to be restarted so that the callback will provide data from - the start again. This requires an API method/mechanism that libcurl - doesn't have today. See below. - -Data Rewind - - It will be troublesome for some apps to deal with a rewind like this in all - circumstances. I'm thinking for example when using 'curl' to upload data - from stdin. If libcurl ends up having to rewind the reading for a request - to succeed, of course a lack of this callback or if it returns failure, will - cause the request to fail completely. - - The new callback is set with CURLOPT_IOCTLFUNCTION (in an attempt to add a - more generic function that might be used for other IO-related controls in - the future): - - curlioerr curl_ioctl(CURL *handle, curliocmd cmd, void *clientp); - - And in the case where the read is to be rewinded, it would be called with a - cmd named CURLIOCMD_RESTARTREAD. The callback would then return CURLIOE_OK, - if things are fine, or CURLIOE_FAILRESTART if not. - -Backwards Compatibility - - The approach used until now, that issues a HEAD on the given URL to trigger - the auth negotiation could still be supported and encouraged, but it would - be up to the app to first fetch a URL with GET/HEAD to negotiate on, since - then a following PUT/POST wouldn't need to negotiate authentication and - thus avoid double-sending data. - - Optionally, we keep the current approach if some option is set - (CURLOPT_HEADBEFOREAUTH or similar), since it seems to work fairly well for - POST on most servers. diff --git a/third_party/curl/lib/README.memoryleak b/third_party/curl/lib/README.memoryleak deleted file mode 100644 index 166177794..000000000 --- a/third_party/curl/lib/README.memoryleak +++ /dev/null @@ -1,55 +0,0 @@ - _ _ ____ _ - ___| | | | _ \| | - / __| | | | |_) | | - | (__| |_| | _ <| |___ - \___|\___/|_| \_\_____| - - How To Track Down Suspected Memory Leaks in libcurl - =================================================== - -Single-threaded - - Please note that this memory leak system is not adjusted to work in more - than one thread. If you want/need to use it in a multi-threaded app. Please - adjust accordingly. - - -Build - - Rebuild libcurl with -DCURLDEBUG (usually, rerunning configure with - --enable-debug fixes this). 'make clean' first, then 'make' so that all - files actually are rebuilt properly. It will also make sense to build - libcurl with the debug option (usually -g to the compiler) so that debugging - it will be easier if you actually do find a leak in the library. - - This will create a library that has memory debugging enabled. - -Modify Your Application - - Add a line in your application code: - - curl_memdebug("dump"); - - This will make the malloc debug system output a full trace of all resource - using functions to the given file name. Make sure you rebuild your program - and that you link with the same libcurl you built for this purpose as - described above. - -Run Your Application - - Run your program as usual. Watch the specified memory trace file grow. - - Make your program exit and use the proper libcurl cleanup functions etc. So - that all non-leaks are returned/freed properly. - -Analyze the Flow - - Use the tests/memanalyze.pl perl script to analyze the dump file: - - tests/memanalyze.pl dump - - This now outputs a report on what resources that were allocated but never - freed etc. This report is very fine for posting to the list! - - If this doesn't produce any output, no leak was detected in libcurl. Then - the leak is mostly likely to be in your code. diff --git a/third_party/curl/lib/README.multi_socket b/third_party/curl/lib/README.multi_socket deleted file mode 100644 index d91e1d9f2..000000000 --- a/third_party/curl/lib/README.multi_socket +++ /dev/null @@ -1,53 +0,0 @@ -Implementation of the curl_multi_socket API - - The main ideas of the new API are simply: - - 1 - The application can use whatever event system it likes as it gets info - from libcurl about what file descriptors libcurl waits for what action - on. (The previous API returns fd_sets which is very select()-centric). - - 2 - When the application discovers action on a single socket, it calls - libcurl and informs that there was action on this particular socket and - libcurl can then act on that socket/transfer only and not care about - any other transfers. (The previous API always had to scan through all - the existing transfers.) - - The idea is that curl_multi_socket_action() calls a given callback with - information about what socket to wait for what action on, and the callback - only gets called if the status of that socket has changed. - - We also added a timer callback that makes libcurl call the application when - the timeout value changes, and you set that with curl_multi_setopt() and the - CURLMOPT_TIMERFUNCTION option. To get this to work, Internally, there's an - added a struct to each easy handle in which we store an "expire time" (if - any). The structs are then "splay sorted" so that we can add and remove - times from the linked list and yet somewhat swiftly figure out both how long - time there is until the next nearest timer expires and which timer (handle) - we should take care of now. Of course, the upside of all this is that we get - a curl_multi_timeout() that should also work with old-style applications - that use curl_multi_perform(). - - We created an internal "socket to easy handles" hash table that given - a socket (file descriptor) return the easy handle that waits for action on - that socket. This hash is made using the already existing hash code - (previously only used for the DNS cache). - - To make libcurl able to report plain sockets in the socket callback, we had - to re-organize the internals of the curl_multi_fdset() etc so that the - conversion from sockets to fd_sets for that function is only done in the - last step before the data is returned. I also had to extend c-ares to get a - function that can return plain sockets, as that library too returned only - fd_sets and that is no longer good enough. The changes done to c-ares are - available in c-ares 1.3.1 and later. - - We have done a test runs with up to 9000 connections (with a single active - one). The curl_multi_socket_action() invoke then takes less than 10 - microseconds in average (using the read-only-1-byte-at-a-time hack). We are - now below the 60 microseconds "per socket action" goal (the extra 50 is the - time libevent needs). - -Documentation - - http://curl.haxx.se/libcurl/c/curl_multi_socket_action.html - http://curl.haxx.se/libcurl/c/curl_multi_timeout.html - http://curl.haxx.se/libcurl/c/curl_multi_setopt.html diff --git a/third_party/curl/lib/README.pingpong b/third_party/curl/lib/README.pingpong deleted file mode 100644 index 69ba9aadb..000000000 --- a/third_party/curl/lib/README.pingpong +++ /dev/null @@ -1,30 +0,0 @@ -Date: December 5, 2009 - -Pingpong -======== - - Pingpong is just my (Daniel's) jestful collective name on the protocols that - share a very similar kind of back-and-forth procedure with command and - responses to and from the server. FTP was previously the only protocol in - that family that libcurl supported, but when POP3, IMAP and SMTP joined the - team I moved some of the internals into a separate pingpong module to be - easier to get used by all these protocols to reduce code duplication and ease - code re-use between these protocols. - -FTP - - In 7.20.0 we converted code to use the new pingpong code from previously - having been all "native" FTP code. - -POP3 - - There's no support in the documented URL format to specify the exact mail to - get, but we support that as the path specified in the URL. - -IMAP - -SMTP - - There's no official URL syntax defined for SMTP, but we use only the generic - one and we provide two additional libcurl options to specify receivers and - sender of the actual mail. diff --git a/third_party/curl/lib/README.pipelining b/third_party/curl/lib/README.pipelining deleted file mode 100644 index c7b462248..000000000 --- a/third_party/curl/lib/README.pipelining +++ /dev/null @@ -1,51 +0,0 @@ -HTTP Pipelining with libcurl -============================ - -Background - -Since pipelining implies that one or more requests are sent to a server before -the previous response(s) have been received, we only support it for multi -interface use. - -Considerations - -When using the multi interface, you create one easy handle for each transfer. -Bascially any number of handles can be created, added and used with the multi -interface - simultaneously. It is an interface designed to allow many -simultaneous transfers while still using a single thread. Pipelining does not -change any of these details. - -API - -We've added a new option to curl_multi_setopt() called CURLMOPT_PIPELINING -that enables "attempted pipelining" and then all easy handles used on that -handle will attempt to use an existing pipeline. - -Details - -- A pipeline is only created if a previous connection exists to the same IP - address that the new request is being made to use. - -- Pipelines are only supported for HTTP(S) as no other currently supported - protocol has features resemembling this, but we still name this feature - plain 'pipelining' to possibly one day support it for other protocols as - well. - -- HTTP Pipelining is for GET and HEAD requests only. - -- When a pipeline is in use, we must take precautions so that when used easy - handles (i.e those who still wait for a response) are removed from the multi - handle, we must deal with the outstanding response nicely. - -- Explicitly asking for pipelining handle X and handle Y won't be supported. - It isn't easy for an app to do this association. The lib should probably - still resolve the second one properly to make sure that they actually _can_ - be considered for pipelining. Also, asking for explicit pipelining on handle - X may be tricky when handle X get a closed connection. - -- We need options to control max pipeline length, and probably how to behave - if we reach that limit. As was discussed on the list, it can probably be - made very complicated, so perhaps we can think of a way to pass all - variables involved to a callback and let the application decide how to act - in specific situations. Either way, these fancy options are only interesting - to work on when everything is working and we have working apps to test with. diff --git a/third_party/curl/lib/amigaos.c b/third_party/curl/lib/amigaos.c deleted file mode 100644 index 2055126fe..000000000 --- a/third_party/curl/lib/amigaos.c +++ /dev/null @@ -1,80 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifdef __AMIGA__ /* Any AmigaOS flavour */ - -#include "amigaos.h" -#include - -struct Library *SocketBase = NULL; -extern int errno, h_errno; - -#ifdef __libnix__ -#include -void __request(const char *msg); -#else -# define __request( msg ) Printf( msg "\n\a") -#endif - -void amiga_cleanup() -{ - if(SocketBase) { - CloseLibrary(SocketBase); - SocketBase = NULL; - } -} - -BOOL amiga_init() -{ - if(!SocketBase) - SocketBase = OpenLibrary("bsdsocket.library", 4); - - if(!SocketBase) { - __request("No TCP/IP Stack running!"); - return FALSE; - } - - if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno, - SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "cURL", - TAG_DONE)) { - __request("SocketBaseTags ERROR"); - return FALSE; - } - -#ifndef __libnix__ - atexit(amiga_cleanup); -#endif - - return TRUE; -} - -#ifdef __libnix__ -ADD2EXIT(amiga_cleanup,-50); -#endif - -#else /* __AMIGA__ */ - -#ifdef __POCC__ -# pragma warn(disable:2024) /* Disable warning #2024: Empty input file */ -#endif - -#endif /* __AMIGA__ */ diff --git a/third_party/curl/lib/amigaos.h b/third_party/curl/lib/amigaos.h deleted file mode 100644 index 2746885b0..000000000 --- a/third_party/curl/lib/amigaos.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef LIBCURL_AMIGAOS_H -#define LIBCURL_AMIGAOS_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifdef __AMIGA__ /* Any AmigaOS flavour */ - -#ifndef __ixemul__ - -#include -#include - -#include -#include - -#include - -#include "config-amigaos.h" - -#ifndef select -# define select(args...) WaitSelect( args, NULL) -#endif -#ifndef ioctl -# define ioctl(a,b,c,d) IoctlSocket( (LONG)a, (ULONG)b, (char*)c) -#endif -#define _AMIGASF 1 - -extern void amiga_cleanup(); -extern BOOL amiga_init(); - -#else /* __ixemul__ */ - -#warning compiling with ixemul... - -#endif /* __ixemul__ */ -#endif /* __AMIGA__ */ -#endif /* LIBCURL_AMIGAOS_H */ diff --git a/third_party/curl/lib/arpa_telnet.h b/third_party/curl/lib/arpa_telnet.h deleted file mode 100644 index 6626928b5..000000000 --- a/third_party/curl/lib/arpa_telnet.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef HEADER_CURL_ARPA_TELNET_H -#define HEADER_CURL_ARPA_TELNET_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#ifndef CURL_DISABLE_TELNET -/* - * Telnet option defines. Add more here if in need. - */ -#define CURL_TELOPT_BINARY 0 /* binary 8bit data */ -#define CURL_TELOPT_SGA 3 /* Suppress Go Ahead */ -#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */ -#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */ -#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */ - -#define CURL_TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */ -#define CURL_NEW_ENV_VAR 0 -#define CURL_NEW_ENV_VALUE 1 - -/* - * The telnet options represented as strings - */ -static const char * const telnetoptions[]= -{ - "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", - "NAME", "STATUS", "TIMING MARK", "RCTE", - "NAOL", "NAOP", "NAOCRD", "NAOHTS", - "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", - "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", - "DE TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION", - "TERM TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", - "TTYLOC", "3270 REGIME", "X3 PAD", "NAWS", - "TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC", - "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON" -}; - -#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON - -#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM) -#define CURL_TELOPT(x) telnetoptions[x] - -#define CURL_NTELOPTS 40 - -/* - * First some defines - */ -#define CURL_xEOF 236 /* End Of File */ -#define CURL_SE 240 /* Sub negotiation End */ -#define CURL_NOP 241 /* No OPeration */ -#define CURL_DM 242 /* Data Mark */ -#define CURL_GA 249 /* Go Ahead, reverse the line */ -#define CURL_SB 250 /* SuBnegotiation */ -#define CURL_WILL 251 /* Our side WILL use this option */ -#define CURL_WONT 252 /* Our side WON'T use this option */ -#define CURL_DO 253 /* DO use this option! */ -#define CURL_DONT 254 /* DON'T use this option! */ -#define CURL_IAC 255 /* Interpret As Command */ - -/* - * Then those numbers represented as strings: - */ -static const char * const telnetcmds[]= -{ - "EOF", "SUSP", "ABORT", "EOR", "SE", - "NOP", "DMARK", "BRK", "IP", "AO", - "AYT", "EC", "EL", "GA", "SB", - "WILL", "WONT", "DO", "DONT", "IAC" -}; - -#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */ -#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */ - -#define CURL_TELQUAL_IS 0 -#define CURL_TELQUAL_SEND 1 -#define CURL_TELQUAL_INFO 2 -#define CURL_TELQUAL_NAME 3 - -#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \ - ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) ) -#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM] - -#endif /* CURL_DISABLE_TELNET */ - -#endif /* HEADER_CURL_ARPA_TELNET_H */ diff --git a/third_party/curl/lib/axtls.c b/third_party/curl/lib/axtls.c deleted file mode 100644 index b6d93e909..000000000 --- a/third_party/curl/lib/axtls.c +++ /dev/null @@ -1,500 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, DirecTV - * contact: Eric Hu - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Source file for all axTLS-specific code for the TLS/SSL layer. No code - * but sslgen.c should ever call or use these functions. - */ - -#include "setup.h" -#ifdef USE_AXTLS -#include -#include "axtls.h" - -#include -#include -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#include "sendf.h" -#include "inet_pton.h" -#include "sslgen.h" -#include "parsedate.h" -#include "connect.h" /* for the connect timeout */ -#include "select.h" -#define _MPRINTF_REPLACE /* use our functions only */ -#include -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* SSL_read is opied from axTLS compat layer */ -static int SSL_read(SSL *ssl, void *buf, int num) -{ - uint8_t *read_buf; - int ret; - - while((ret = ssl_read(ssl, &read_buf)) == SSL_OK); - - if(ret > SSL_OK){ - memcpy(buf, read_buf, ret > num ? num : ret); - } - - return ret; -} - -/* Global axTLS init, called from Curl_ssl_init() */ -int Curl_axtls_init(void) -{ -/* axTLS has no global init. Everything is done through SSL and SSL_CTX - * structs stored in connectdata structure. Perhaps can move to axtls.h. - */ - return 1; -} - -int Curl_axtls_cleanup(void) -{ - /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */ - return 1; -} - -static CURLcode map_error_to_curl(int axtls_err) -{ - switch (axtls_err) - { - case SSL_ERROR_NOT_SUPPORTED: - case SSL_ERROR_INVALID_VERSION: - case -70: /* protocol version alert from server */ - return CURLE_UNSUPPORTED_PROTOCOL; - break; - case SSL_ERROR_NO_CIPHER: - return CURLE_SSL_CIPHER; - break; - case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */ - case SSL_ERROR_NO_CERT_DEFINED: - case -42: /* bad certificate alert from server */ - case -43: /* unsupported cert alert from server */ - case -44: /* cert revoked alert from server */ - case -45: /* cert expired alert from server */ - case -46: /* cert unknown alert from server */ - return CURLE_SSL_CERTPROBLEM; - break; - case SSL_X509_ERROR(X509_NOT_OK): - case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT): - case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE): - case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID): - case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED): - case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED): - case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN): - case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST): - case SSL_X509_ERROR(X509_INVALID_PRIV_KEY): - return CURLE_PEER_FAILED_VERIFICATION; - break; - case -48: /* unknown ca alert from server */ - return CURLE_SSL_CACERT; - break; - case -49: /* access denied alert from server */ - return CURLE_REMOTE_ACCESS_DENIED; - break; - case SSL_ERROR_CONN_LOST: - case SSL_ERROR_SOCK_SETUP_FAILURE: - case SSL_ERROR_INVALID_HANDSHAKE: - case SSL_ERROR_INVALID_PROT_MSG: - case SSL_ERROR_INVALID_HMAC: - case SSL_ERROR_INVALID_SESSION: - case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */ - case SSL_ERROR_FINISHED_INVALID: - case SSL_ERROR_NO_CLIENT_RENOG: - default: - return CURLE_SSL_CONNECT_ERROR; - break; - } -} - -static Curl_recv axtls_recv; -static Curl_send axtls_send; - -/* - * This function is called after the TCP connect has completed. Setup the TLS - * layer and do all necessary magic. - */ -CURLcode -Curl_axtls_connect(struct connectdata *conn, - int sockindex) - -{ - struct SessionHandle *data = conn->data; - SSL_CTX *ssl_ctx; - SSL *ssl; - int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0}; - int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0}; - int i, ssl_fcn_return; - const uint8_t *ssl_sessionid; - size_t ssl_idsize; - const char *x509; - - /* Assuming users will not compile in custom key/cert to axTLS */ - uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER; - - if(conn->ssl[sockindex].state == ssl_connection_complete) - /* to make us tolerant against being called more than once for the - same connection */ - return CURLE_OK; - - /* axTLS only supports TLSv1 */ - /* check to see if we've been told to use an explicit SSL/TLS version */ - switch(data->set.ssl.version) { - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - break; - default: - failf(data, "axTLS only supports TLSv1"); - return CURLE_SSL_CONNECT_ERROR; - } - -#ifdef AXTLSDEBUG - client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS; -#endif /* AXTLSDEBUG */ - - /* Allocate an SSL_CTX struct */ - ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS); - if(ssl_ctx == NULL) { - failf(data, "unable to create client SSL context"); - return CURLE_SSL_CONNECT_ERROR; - } - - /* Load the trusted CA cert bundle file */ - if(data->set.ssl.CAfile) { - if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL) - != SSL_OK){ - infof(data, "error reading ca cert file %s \n", - data->set.ssl.CAfile); - if(data->set.ssl.verifypeer){ - Curl_axtls_close(conn, sockindex); - return CURLE_SSL_CACERT_BADFILE; - } - } - else - infof(data, "found certificates in %s\n", data->set.ssl.CAfile); - } - - /* gtls.c tasks we're skipping for now: - * 1) certificate revocation list checking - * 2) dns name assignment to host - * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore - * 4) set certificate priority. axTLS ignores type and sends certs in - * order added. can probably ignore this. - */ - - /* Load client certificate */ - if(data->set.str[STRING_CERT]){ - i=0; - /* Instead of trying to analyze cert type here, let axTLS try them all. */ - while(cert_types[i] != 0){ - ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], - data->set.str[STRING_CERT], NULL); - if(ssl_fcn_return == SSL_OK){ - infof(data, "successfully read cert file %s \n", - data->set.str[STRING_CERT]); - break; - } - i++; - } - /* Tried all cert types, none worked. */ - if(cert_types[i] == 0){ - failf(data, "%s is not x509 or pkcs12 format", - data->set.str[STRING_CERT]); - Curl_axtls_close(conn, sockindex); - return CURLE_SSL_CERTPROBLEM; - } - } - - /* Load client key. - If a pkcs12 file successfully loaded a cert, then there's nothing to do - because the key has already been loaded. */ - if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12){ - i=0; - /* Instead of trying to analyze key type here, let axTLS try them all. */ - while(key_types[i] != 0){ - ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], - data->set.str[STRING_KEY], NULL); - if(ssl_fcn_return == SSL_OK){ - infof(data, "successfully read key file %s \n", - data->set.str[STRING_KEY]); - break; - } - i++; - } - /* Tried all key types, none worked. */ - if(key_types[i] == 0){ - failf(data, "Failure: %s is not a supported key file", - data->set.str[STRING_KEY]); - Curl_axtls_close(conn, sockindex); - return CURLE_SSL_CONNECT_ERROR; - } - } - - /* gtls.c does more here that is being left out for now - * 1) set session credentials. can probably ignore since axtls puts this - * info in the ssl_ctx struct - * 2) setting up callbacks. these seem gnutls specific - */ - - /* In axTLS, handshaking happens inside ssl_client_new. */ - if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) { - /* we got a session id, use it! */ - infof (data, "SSL re-using session ID\n"); - ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], - ssl_sessionid, (uint8_t)ssl_idsize); - } - else - ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0); - - /* Check to make sure handshake was ok. */ - ssl_fcn_return = ssl_handshake_status(ssl); - if(ssl_fcn_return != SSL_OK){ - Curl_axtls_close(conn, sockindex); - ssl_display_error(ssl_fcn_return); /* goes to stdout. */ - return map_error_to_curl(ssl_fcn_return); - } - infof (data, "handshake completed successfully\n"); - - /* Here, gtls.c gets the peer certificates and fails out depending on - * settings in "data." axTLS api doesn't have get cert chain fcn, so omit? - */ - - /* Verify server's certificate */ - if(data->set.ssl.verifypeer){ - if(ssl_verify_cert(ssl) != SSL_OK){ - Curl_axtls_close(conn, sockindex); - failf(data, "server cert verify failed"); - return CURLE_SSL_CONNECT_ERROR; - } - } - else - infof(data, "\t server certificate verification SKIPPED\n"); - - /* Here, gtls.c does issuer verification. axTLS has no straightforward - * equivalent, so omitting for now.*/ - - /* See if common name was set in server certificate */ - x509 = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); - if(x509 == NULL) - infof(data, "error fetching CN from cert\n"); - - /* Here, gtls.c does the following - * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but - * it seems useful. Omitting for now. - * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert - * 3) displays a bunch of cert information. axTLS doesn't support most of - * this, but a couple fields are available. - */ - - /* General housekeeping */ - conn->ssl[sockindex].state = ssl_connection_complete; - conn->ssl[sockindex].ssl = ssl; - conn->ssl[sockindex].ssl_ctx = ssl_ctx; - conn->recv[sockindex] = axtls_recv; - conn->send[sockindex] = axtls_send; - - /* Put our freshly minted SSL session in cache */ - ssl_idsize = ssl_get_session_id_size(ssl); - ssl_sessionid = ssl_get_session_id(ssl); - if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize) - != CURLE_OK) - infof (data, "failed to add session to cache\n"); - - return CURLE_OK; -} - - -/* return number of sent (non-SSL) bytes */ -static ssize_t axtls_send(struct connectdata *conn, - int sockindex, - const void *mem, - size_t len, - CURLcode *err) -{ - /* ssl_write() returns 'int' while write() and send() returns 'size_t' */ - int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len); - - infof(conn->data, " axtls_send\n"); - - if(rc < 0 ) { - *err = map_error_to_curl(rc); - rc = -1; /* generic error code for send failure */ - } - - *err = CURLE_OK; - return rc; -} - -void Curl_axtls_close_all(struct SessionHandle *data) -{ - (void)data; - infof(data, " Curl_axtls_close_all\n"); -} - -void Curl_axtls_close(struct connectdata *conn, int sockindex) -{ - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - infof(conn->data, " Curl_axtls_close\n"); - if(connssl->ssl) { - /* line from ssluse.c: (void)SSL_shutdown(connssl->ssl); - axTLS compat layer does nothing for SSL_shutdown */ - - /* The following line is from ssluse.c. There seems to be no axTLS - equivalent. ssl_free and ssl_ctx_free close things. - SSL_set_connect_state(connssl->handle); */ - - ssl_free (connssl->ssl); - connssl->ssl = NULL; - } - if(connssl->ssl_ctx) { - ssl_ctx_free (connssl->ssl_ctx); - connssl->ssl_ctx = NULL; - } -} - -/* - * This function is called to shut down the SSL layer but keep the - * socket open (CCC - Clear Command Channel) - */ -int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) -{ - /* Outline taken from ssluse.c since functions are in axTLS compat layer. - axTLS's error set is much smaller, so a lot of error-handling was removed. - */ - int retval = 0; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - struct SessionHandle *data = conn->data; - char buf[120]; /* We will use this for the OpenSSL error buffer, so it has - to be at least 120 bytes long. */ - ssize_t nread; - - infof(conn->data, " Curl_axtls_shutdown\n"); - - /* This has only been tested on the proftpd server, and the mod_tls code - sends a close notify alert without waiting for a close notify alert in - response. Thus we wait for a close notify alert from the server, but - we do not send one. Let's hope other servers do the same... */ - - /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too - if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) - (void)SSL_shutdown(connssl->ssl); - */ - - if(connssl->ssl) { - int what = Curl_socket_ready(conn->sock[sockindex], - CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); - if(what > 0) { - /* Something to read, let's do it and hope that it is the close - notify alert from the server */ - nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf, - sizeof(buf)); - - if (nread < SSL_OK){ - failf(data, "close notify alert not received during shutdown"); - retval = -1; - } - } - else if(0 == what) { - /* timeout */ - failf(data, "SSL shutdown timeout"); - } - else { - /* anything that gets here is fatally bad */ - failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); - retval = -1; - } - - ssl_free (connssl->ssl); - connssl->ssl = NULL; - } - return retval; -} - -static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ - int num, /* socketindex */ - char *buf, /* store read data here */ - size_t buffersize, /* max amount to read */ - CURLcode *err) -{ - struct ssl_connect_data *connssl = &conn->ssl[num]; - ssize_t ret = 0; - - infof(conn->data, " axtls_recv\n"); - - if(connssl){ - ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize); - - /* axTLS isn't terribly generous about error reporting */ - /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS - team approves proposed fix. */ - if(ret == -3 ){ - Curl_axtls_close(conn, num); - } - else if(ret < 0) { - failf(conn->data, "axTLS recv error (%d)", (int)ret); - *err = map_error_to_curl(ret); - return -1; - } - } - - *err = CURLE_OK; - return ret; -} - -/* - * Return codes: - * 1 means the connection is still in place - * 0 means the connection has been closed - * -1 means the connection status is unknown - */ -int Curl_axtls_check_cxn(struct connectdata *conn) -{ - /* ssluse.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1); - axTLS compat layer always returns the last argument, so connection is - always alive? */ - - infof(conn->data, " Curl_axtls_check_cxn\n"); - return 1; /* connection still in place */ -} - -void Curl_axtls_session_free(void *ptr) -{ - (void)ptr; - /* free the ID */ - /* both ssluse.c and gtls.c do something here, but axTLS's OpenSSL - compatibility layer does nothing, so we do nothing too. */ -} - -size_t Curl_axtls_version(char *buffer, size_t size) -{ - return snprintf(buffer, size, "axTLS/%s", ssl_version()); -} - -#endif /* USE_AXTLS */ diff --git a/third_party/curl/lib/axtls.h b/third_party/curl/lib/axtls.h deleted file mode 100644 index 967f90930..000000000 --- a/third_party/curl/lib/axtls.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef __AXTLS_H -#define __AXTLS_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, DirecTV - * contact: Eric Hu - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifdef USE_AXTLS -#include "curl/curl.h" -#include "urldata.h" - -int Curl_axtls_init(void); -int Curl_axtls_cleanup(void); -CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex); - -/* tell axTLS to close down all open information regarding connections (and - thus session ID caching etc) */ -void Curl_axtls_close_all(struct SessionHandle *data); - - /* close a SSL connection */ -void Curl_axtls_close(struct connectdata *conn, int sockindex); - -void Curl_axtls_session_free(void *ptr); -size_t Curl_axtls_version(char *buffer, size_t size); -int Curl_axtls_shutdown(struct connectdata *conn, int sockindex); -int Curl_axtls_check_cxn(struct connectdata *conn); - -/* API setup for axTLS */ -#define curlssl_init Curl_axtls_init -#define curlssl_cleanup Curl_axtls_cleanup -#define curlssl_connect Curl_axtls_connect -#define curlssl_session_free(x) Curl_axtls_session_free(x) -#define curlssl_close_all Curl_axtls_close_all -#define curlssl_close Curl_axtls_close -#define curlssl_shutdown(x,y) Curl_axtls_shutdown(x,y) -#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN) -#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN) -#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL) -#define curlssl_version Curl_axtls_version -#define curlssl_check_cxn(x) Curl_axtls_check_cxn(x) -#define curlssl_data_pending(x,y) (x=x, y=y, 0) - -#endif /* USE_AXTLS */ -#endif diff --git a/third_party/curl/lib/base64.c b/third_party/curl/lib/base64.c deleted file mode 100644 index 0c492dc45..000000000 --- a/third_party/curl/lib/base64.c +++ /dev/null @@ -1,222 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* Base64 encoding/decoding */ - -#include "setup.h" - -#include -#include - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "urldata.h" /* for the SessionHandle definition */ -#include "warnless.h" -#include "curl_base64.h" -#include "curl_memory.h" -#include "non-ascii.h" - -/* include memdebug.h last */ -#include "memdebug.h" - -/* ---- Base64 Encoding/Decoding Table --- */ -static const char table64[]= - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -static void decodeQuantum(unsigned char *dest, const char *src) -{ - const char *s, *p; - unsigned long i, v, x = 0; - - for(i = 0, s = src; i < 4; i++, s++) { - v = 0; - p = table64; - while(*p && (*p != *s)) { - v++; - p++; - } - if(*p == *s) - x = (x << 6) + v; - else if(*s == '=') - x = (x << 6); - } - - dest[2] = curlx_ultouc(x); - x >>= 8; - dest[1] = curlx_ultouc(x); - x >>= 8; - dest[0] = curlx_ultouc(x); -} - -/* - * Curl_base64_decode() - * - * Given a base64 string at src, decode it and return an allocated memory in - * the *outptr. Returns the length of the decoded data. - */ -size_t Curl_base64_decode(const char *src, unsigned char **outptr) -{ - size_t length = 0; - size_t equalsTerm = 0; - size_t i; - size_t numQuantums; - unsigned char lastQuantum[3]; - size_t rawlen = 0; - unsigned char *newstr; - - *outptr = NULL; - - while((src[length] != '=') && src[length]) - length++; - /* A maximum of two = padding characters is allowed */ - if(src[length] == '=') { - equalsTerm++; - if(src[length+equalsTerm] == '=') - equalsTerm++; - } - numQuantums = (length + equalsTerm) / 4; - - /* Don't allocate a buffer if the decoded length is 0 */ - if(numQuantums == 0) - return 0; - - rawlen = (numQuantums * 3) - equalsTerm; - - /* The buffer must be large enough to make room for the last quantum - (which may be partially thrown out) and the zero terminator. */ - newstr = malloc(rawlen+4); - if(!newstr) - return 0; - - *outptr = newstr; - - /* Decode all but the last quantum (which may not decode to a - multiple of 3 bytes) */ - for(i = 0; i < numQuantums - 1; i++) { - decodeQuantum(newstr, src); - newstr += 3; src += 4; - } - - /* This final decode may actually read slightly past the end of the buffer - if the input string is missing pad bytes. This will almost always be - harmless. */ - decodeQuantum(lastQuantum, src); - for(i = 0; i < 3 - equalsTerm; i++) - newstr[i] = lastQuantum[i]; - - newstr[i] = '\0'; /* zero terminate */ - return rawlen; -} - -/* - * Curl_base64_encode() - * - * Returns the length of the newly created base64 string. The third argument - * is a pointer to an allocated area holding the base64 data. If something - * went wrong, 0 is returned. - * - */ -size_t Curl_base64_encode(struct SessionHandle *data, - const char *inputbuff, size_t insize, - char **outptr) -{ - unsigned char ibuf[3]; - unsigned char obuf[4]; - int i; - int inputparts; - char *output; - char *base64data; - char *convbuf = NULL; - - const char *indata = inputbuff; - - *outptr = NULL; /* set to NULL in case of failure before we reach the end */ - - if(0 == insize) - insize = strlen(indata); - - base64data = output = malloc(insize*4/3+4); - if(NULL == output) - return 0; - - /* - * The base64 data needs to be created using the network encoding - * not the host encoding. And we can't change the actual input - * so we copy it to a buffer, translate it, and use that instead. - */ - if(Curl_convert_clone(data, indata, insize, &convbuf)) - return 0; - - if(convbuf) - indata = (char *)convbuf; - - while(insize > 0) { - for (i = inputparts = 0; i < 3; i++) { - if(insize > 0) { - inputparts++; - ibuf[i] = (unsigned char) *indata; - indata++; - insize--; - } - else - ibuf[i] = 0; - } - - obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2); - obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \ - ((ibuf[1] & 0xF0) >> 4)); - obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \ - ((ibuf[2] & 0xC0) >> 6)); - obuf[3] = (unsigned char) (ibuf[2] & 0x3F); - - switch(inputparts) { - case 1: /* only one byte read */ - snprintf(output, 5, "%c%c==", - table64[obuf[0]], - table64[obuf[1]]); - break; - case 2: /* two bytes read */ - snprintf(output, 5, "%c%c%c=", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]]); - break; - default: - snprintf(output, 5, "%c%c%c%c", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]], - table64[obuf[3]] ); - break; - } - output += 4; - } - *output=0; - *outptr = base64data; /* make it return the actual data memory */ - - if(convbuf) - free(convbuf); - - return strlen(base64data); /* return the length of the new data */ -} -/* ---- End of Base64 Encoding ---- */ diff --git a/third_party/curl/lib/connect.c b/third_party/curl/lib/connect.c deleted file mode 100644 index 69d84c359..000000000 --- a/third_party/curl/lib/connect.c +++ /dev/null @@ -1,1159 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include /* may need it */ -#endif -#ifdef HAVE_SYS_UN_H -#include /* for sockaddr_un */ -#endif -#ifdef HAVE_NETINET_TCP_H -#include /* for TCP_NODELAY */ -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif - -#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) -#include -#endif -#ifdef NETWARE -#undef in_addr_t -#define in_addr_t unsigned long -#endif -#ifdef __VMS -#include -#include -#endif - -#include -#include -#include - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "urldata.h" -#include "sendf.h" -#include "if2ip.h" -#include "strerror.h" -#include "connect.h" -#include "curl_memory.h" -#include "select.h" -#include "url.h" /* for Curl_safefree() */ -#include "multiif.h" -#include "sockaddr.h" /* required for Curl_sockaddr_storage */ -#include "inet_ntop.h" -#include "inet_pton.h" -#include "sslgen.h" /* for Curl_ssl_check_cxn() */ -#include "progress.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -#ifdef __SYMBIAN32__ -/* This isn't actually supported under Symbian OS */ -#undef SO_NOSIGPIPE -#endif - -struct Curl_sockaddr_ex { - int family; - int socktype; - int protocol; - unsigned int addrlen; - union { - struct sockaddr addr; - struct Curl_sockaddr_storage buff; - } _sa_ex_u; -}; -#define sa_addr _sa_ex_u.addr - -static bool verifyconnect(curl_socket_t sockfd, int *error); - -static CURLcode -singleipconnect(struct connectdata *conn, - const Curl_addrinfo *ai, /* start connecting to this */ - long timeout_ms, - curl_socket_t *sock, - bool *connected); - -/* - * Curl_timeleft() returns the amount of milliseconds left allowed for the - * transfer/connection. If the value is negative, the timeout time has already - * elapsed. - * - * The start time is stored in progress.t_startsingle - as set with - * Curl_pgrsTime(..., TIMER_STARTSINGLE); - * - * If 'nowp' is non-NULL, it points to the current time. - * 'duringconnect' is FALSE if not during a connect, as then of course the - * connect timeout is not taken into account! - */ -long Curl_timeleft(struct SessionHandle *data, - struct timeval *nowp, - bool duringconnect) -{ - int timeout_set = 0; - long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; - struct timeval now; - - /* if a timeout is set, use the most restrictive one */ - - if(data->set.timeout > 0) - timeout_set |= 1; - if(duringconnect && (data->set.connecttimeout > 0)) - timeout_set |= 2; - - switch (timeout_set) { - case 1: - timeout_ms = data->set.timeout; - break; - case 2: - timeout_ms = data->set.connecttimeout; - break; - case 3: - if(data->set.timeout < data->set.connecttimeout) - timeout_ms = data->set.timeout; - else - timeout_ms = data->set.connecttimeout; - break; - default: - /* use the default */ - if(!duringconnect) - /* if we're not during connect, there's no default timeout so if we're - at zero we better just return zero and not make it a negative number - by the math below */ - return 0; - break; - } - - if(!nowp) { - now = Curl_tvnow(); - nowp = &now; - } - - /* subtract elapsed time */ - timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle); - if(!timeout_ms) - /* avoid returning 0 as that means no timeout! */ - return -1; - - return timeout_ms; -} - -/* - * waitconnect() waits for a TCP connect on the given socket for the specified - * number if milliseconds. It returns: - */ - -#define WAITCONN_CONNECTED 0 -#define WAITCONN_SELECT_ERROR -1 -#define WAITCONN_TIMEOUT 1 -#define WAITCONN_FDSET_ERROR 2 -#define WAITCONN_ABORTED 3 - -static -int waitconnect(struct connectdata *conn, - curl_socket_t sockfd, /* socket */ - long timeout_msec) -{ - int rc; -#ifdef mpeix - /* Call this function once now, and ignore the results. We do this to - "clear" the error state on the socket so that we can later read it - reliably. This is reported necessary on the MPE/iX operating system. */ - (void)verifyconnect(sockfd, NULL); -#endif - - for(;;) { - - /* now select() until we get connect or timeout */ - rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)(timeout_msec>1000? - 1000:timeout_msec)); - if(Curl_pgrsUpdate(conn)) - return WAITCONN_ABORTED; - - if(-1 == rc) - /* error, no connect here, try next */ - return WAITCONN_SELECT_ERROR; - - else if(0 == rc) { - /* timeout */ - timeout_msec -= 1000; - if(timeout_msec <= 0) - return WAITCONN_TIMEOUT; - - continue; - } - - if(rc & CURL_CSELECT_ERR) - /* error condition caught */ - return WAITCONN_FDSET_ERROR; - - break; - } - return WAITCONN_CONNECTED; -} - -static CURLcode bindlocal(struct connectdata *conn, - curl_socket_t sockfd, int af) -{ - struct SessionHandle *data = conn->data; - - struct Curl_sockaddr_storage sa; - struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */ - curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */ - struct sockaddr_in *si4 = (struct sockaddr_in *)&sa; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa; -#endif - - struct Curl_dns_entry *h=NULL; - unsigned short port = data->set.localport; /* use this port number, 0 for - "random" */ - /* how many port numbers to try to bind to, increasing one at a time */ - int portnum = data->set.localportrange; - const char *dev = data->set.str[STRING_DEVICE]; - int error; - char myhost[256] = ""; - int done = 0; /* -1 for error, 1 for address found */ - - /************************************************************* - * Select device to bind socket to - *************************************************************/ - if ( !dev && !port ) - /* no local kind of binding was requested */ - return CURLE_OK; - - memset(&sa, 0, sizeof(struct Curl_sockaddr_storage)); - - if(dev && (strlen(dev)<255) ) { - - /* interface */ - if(Curl_if2ip(af, dev, myhost, sizeof(myhost))) { - /* - * We now have the numerical IP address in the 'myhost' buffer - */ - infof(data, "Local Interface %s is ip %s using address family %i\n", - dev, myhost, af); - done = 1; - -#ifdef SO_BINDTODEVICE - /* I am not sure any other OSs than Linux that provide this feature, and - * at the least I cannot test. --Ben - * - * This feature allows one to tightly bind the local socket to a - * particular interface. This will force even requests to other local - * interfaces to go out the external interface. - * - * - * Only bind to the interface when specified as interface, not just as a - * hostname or ip address. - */ - if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, - dev, (curl_socklen_t)strlen(dev)+1) != 0) { - error = SOCKERRNO; - infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;" - " will do regular bind\n", - dev, error, Curl_strerror(conn, error)); - /* This is typically "errno 1, error: Operation not permitted" if - you're not running as root or another suitable privileged user */ - } -#endif - } - else { - /* - * This was not an interface, resolve the name as a host name - * or IP number - * - * Temporarily force name resolution to use only the address type - * of the connection. The resolve functions should really be changed - * to take a type parameter instead. - */ - long ipver = conn->ip_version; - int rc; - - if (af == AF_INET) - conn->ip_version = CURL_IPRESOLVE_V4; -#ifdef ENABLE_IPV6 - else if (af == AF_INET6) - conn->ip_version = CURL_IPRESOLVE_V6; -#endif - - rc = Curl_resolv(conn, dev, 0, &h); - if(rc == CURLRESOLV_PENDING) - (void)Curl_wait_for_resolv(conn, &h); - conn->ip_version = ipver; - - if(h) { - /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ - Curl_printable_address(h->addr, myhost, sizeof(myhost)); - infof(data, "Name '%s' family %i resolved to '%s' family %i\n", - dev, af, myhost, h->addr->ai_family); - Curl_resolv_unlock(data, h); - done = 1; - } - else { - /* - * provided dev was no interface (or interfaces are not supported - * e.g. solaris) no ip address and no domain we fail here - */ - done = -1; - } - } - - if(done > 0) { -#ifdef ENABLE_IPV6 - /* ipv6 address */ - if((af == AF_INET6) && - (Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0)) { - si6->sin6_family = AF_INET6; - si6->sin6_port = htons(port); - sizeof_sa = sizeof(struct sockaddr_in6); - } - else -#endif - /* ipv4 address */ - if((af == AF_INET) && - (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) { - si4->sin_family = AF_INET; - si4->sin_port = htons(port); - sizeof_sa = sizeof(struct sockaddr_in); - } - } - - if(done < 1) { - failf(data, "Couldn't bind to '%s'", dev); - return CURLE_INTERFACE_FAILED; - } - } - else { - /* no device was given, prepare sa to match af's needs */ -#ifdef ENABLE_IPV6 - if ( af == AF_INET6 ) { - si6->sin6_family = AF_INET6; - si6->sin6_port = htons(port); - sizeof_sa = sizeof(struct sockaddr_in6); - } - else -#endif - if ( af == AF_INET ) { - si4->sin_family = AF_INET; - si4->sin_port = htons(port); - sizeof_sa = sizeof(struct sockaddr_in); - } - } - - for(;;) { - if( bind(sockfd, sock, sizeof_sa) >= 0) { - /* we succeeded to bind */ - struct Curl_sockaddr_storage add; - curl_socklen_t size = sizeof(add); - memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); - if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { - data->state.os_errno = error = SOCKERRNO; - failf(data, "getsockname() failed with errno %d: %s", - error, Curl_strerror(conn, error)); - return CURLE_INTERFACE_FAILED; - } - infof(data, "Local port: %hu\n", port); - conn->bits.bound = TRUE; - return CURLE_OK; - } - - if(--portnum > 0) { - infof(data, "Bind to local port %hu failed, trying next\n", port); - port++; /* try next port */ - /* We re-use/clobber the port variable here below */ - if(sock->sa_family == AF_INET) - si4->sin_port = ntohs(port); -#ifdef ENABLE_IPV6 - else - si6->sin6_port = ntohs(port); -#endif - } - else - break; - } - - data->state.os_errno = error = SOCKERRNO; - failf(data, "bind failed with errno %d: %s", - error, Curl_strerror(conn, error)); - - return CURLE_INTERFACE_FAILED; -} - -/* - * verifyconnect() returns TRUE if the connect really has happened. - */ -static bool verifyconnect(curl_socket_t sockfd, int *error) -{ - bool rc = TRUE; -#ifdef SO_ERROR - int err = 0; - curl_socklen_t errSize = sizeof(err); - -#ifdef WIN32 - /* - * In October 2003 we effectively nullified this function on Windows due to - * problems with it using all CPU in multi-threaded cases. - * - * In May 2004, we bring it back to offer more info back on connect failures. - * Gisle Vanem could reproduce the former problems with this function, but - * could avoid them by adding this SleepEx() call below: - * - * "I don't have Rational Quantify, but the hint from his post was - * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe - * just Sleep(0) would be enough?) would release whatever - * mutex/critical-section the ntdll call is waiting on. - * - * Someone got to verify this on Win-NT 4.0, 2000." - */ - -#ifdef _WIN32_WCE - Sleep(0); -#else - SleepEx(0, FALSE); -#endif - -#endif - - if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) - err = SOCKERRNO; -#ifdef _WIN32_WCE - /* Old WinCE versions don't support SO_ERROR */ - if(WSAENOPROTOOPT == err) { - SET_SOCKERRNO(0); - err = 0; - } -#endif -#ifdef __minix - /* Minix 3.1.x doesn't support getsockopt on UDP sockets */ - if(EBADIOCTL == err) { - SET_SOCKERRNO(0); - err = 0; - } -#endif - if((0 == err) || (EISCONN == err)) - /* we are connected, awesome! */ - rc = TRUE; - else - /* This wasn't a successful connect */ - rc = FALSE; - if(error) - *error = err; -#else - (void)sockfd; - if(error) - *error = SOCKERRNO; -#endif - return rc; -} - -/* Used within the multi interface. Try next IP address, return TRUE if no - more address exists or error */ -static CURLcode trynextip(struct connectdata *conn, - int sockindex, - bool *connected) -{ - curl_socket_t sockfd; - Curl_addrinfo *ai; - - /* First clean up after the failed socket. - Don't close it yet to ensure that the next IP's socket gets a different - file descriptor, which can prevent bugs when the curl_multi_socket_action - interface is used with certain select() replacements such as kqueue. */ - curl_socket_t fd_to_close = conn->sock[sockindex]; - conn->sock[sockindex] = CURL_SOCKET_BAD; - *connected = FALSE; - - if(sockindex != FIRSTSOCKET) { - sclose(fd_to_close); - return CURLE_COULDNT_CONNECT; /* no next */ - } - - /* try the next address */ - ai = conn->ip_addr->ai_next; - - while(ai) { - CURLcode res = singleipconnect(conn, ai, 0L, &sockfd, connected); - if(res) - return res; - if(sockfd != CURL_SOCKET_BAD) { - /* store the new socket descriptor */ - conn->sock[sockindex] = sockfd; - conn->ip_addr = ai; - sclose(fd_to_close); - return CURLE_OK; - } - ai = ai->ai_next; - } - sclose(fd_to_close); - return CURLE_COULDNT_CONNECT; -} - -/* Copies connection info into the session handle to make it available - when the session handle is no longer associated with a connection. */ -void Curl_persistconninfo(struct connectdata *conn) -{ - memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN); - memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN); - conn->data->info.conn_primary_port = conn->primary_port; - conn->data->info.conn_local_port = conn->local_port; -} - -/* retrieves ip address and port from a sockaddr structure */ -static bool getaddressinfo(struct sockaddr* sa, char* addr, - long* port) -{ - unsigned short us_port; - struct sockaddr_in* si = NULL; -#ifdef ENABLE_IPV6 - struct sockaddr_in6* si6 = NULL; -#endif -#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) - struct sockaddr_un* su = NULL; -#endif - - switch (sa->sa_family) { - case AF_INET: - si = (struct sockaddr_in*) sa; - if(Curl_inet_ntop(sa->sa_family, &si->sin_addr, - addr, MAX_IPADR_LEN)) { - us_port = ntohs(si->sin_port); - *port = us_port; - return TRUE; - } - break; -#ifdef ENABLE_IPV6 - case AF_INET6: - si6 = (struct sockaddr_in6*)sa; - if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr, - addr, MAX_IPADR_LEN)) { - us_port = ntohs(si6->sin6_port); - *port = us_port; - return TRUE; - } - break; -#endif -#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) - case AF_UNIX: - su = (struct sockaddr_un*)sa; - snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path); - *port = 0; - return TRUE; -#endif - default: - break; - } - - addr[0] = '\0'; - *port = 0; - - return FALSE; -} - -/* retrieves the start/end point information of a socket of an established - connection */ -void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) -{ - int error; - curl_socklen_t len; - struct Curl_sockaddr_storage ssrem; - struct Curl_sockaddr_storage ssloc; - struct SessionHandle *data = conn->data; - - if(!conn->bits.reuse) { - - len = sizeof(struct Curl_sockaddr_storage); - if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { - error = SOCKERRNO; - failf(data, "getpeername() failed with errno %d: %s", - error, Curl_strerror(conn, error)); - return; - } - - len = sizeof(struct Curl_sockaddr_storage); - if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) { - error = SOCKERRNO; - failf(data, "getsockname() failed with errno %d: %s", - error, Curl_strerror(conn, error)); - return; - } - - if(!getaddressinfo((struct sockaddr*)&ssrem, - conn->primary_ip, &conn->primary_port)) { - error = ERRNO; - failf(data, "ssrem inet_ntop() failed with errno %d: %s", - error, Curl_strerror(conn, error)); - return; - } - - if(!getaddressinfo((struct sockaddr*)&ssloc, - conn->local_ip, &conn->local_port)) { - error = ERRNO; - failf(data, "ssloc inet_ntop() failed with errno %d: %s", - error, Curl_strerror(conn, error)); - return; - } - - } - - /* persist connection info in session handle */ - Curl_persistconninfo(conn); -} - -/* - * Curl_is_connected() is used from the multi interface to check if the - * firstsocket has connected. - */ - -CURLcode Curl_is_connected(struct connectdata *conn, - int sockindex, - bool *connected) -{ - int rc; - struct SessionHandle *data = conn->data; - CURLcode code = CURLE_OK; - curl_socket_t sockfd = conn->sock[sockindex]; - long allow = DEFAULT_CONNECT_TIMEOUT; - int error = 0; - struct timeval now; - - DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); - - *connected = FALSE; /* a very negative world view is best */ - - if(conn->bits.tcpconnect) { - /* we are connected already! */ - *connected = TRUE; - return CURLE_OK; - } - - now = Curl_tvnow(); - - /* figure out how long time we have left to connect */ - allow = Curl_timeleft(data, &now, TRUE); - - if(allow < 0) { - /* time-out, bail out, go home */ - failf(data, "Connection time-out"); - return CURLE_OPERATION_TIMEDOUT; - } - - /* check for connect without timeout as we want to return immediately */ - rc = waitconnect(conn, sockfd, 0); - if(WAITCONN_TIMEOUT == rc) { - if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) { - infof(data, "After %ldms connect time, move on!\n", - conn->timeoutms_per_addr); - goto next; - } - - /* not an error, but also no connection yet */ - return code; - } - - if(WAITCONN_CONNECTED == rc) { - if(verifyconnect(sockfd, &error)) { - /* we are connected, awesome! */ - conn->bits.tcpconnect = TRUE; - *connected = TRUE; - Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ - Curl_verboseconnect(conn); - Curl_updateconninfo(conn, sockfd); - - return CURLE_OK; - } - /* nope, not connected for real */ - } - else { - /* nope, not connected */ - if(WAITCONN_FDSET_ERROR == rc) { - (void)verifyconnect(sockfd, &error); - infof(data, "%s\n",Curl_strerror(conn, error)); - } - else - infof(data, "Connection failed\n"); - } - - /* - * The connection failed here, we should attempt to connect to the "next - * address" for the given host. But first remember the latest error. - */ - if(error) { - data->state.os_errno = error; - SET_SOCKERRNO(error); - } - next: - - code = trynextip(conn, sockindex, connected); - - if(code) { - error = SOCKERRNO; - data->state.os_errno = error; - failf(data, "Failed connect to %s:%ld; %s", - conn->host.name, conn->port, Curl_strerror(conn, error)); - } - - return code; -} - -static void tcpnodelay(struct connectdata *conn, - curl_socket_t sockfd) -{ -#ifdef TCP_NODELAY - struct SessionHandle *data= conn->data; - curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay; - int proto = IPPROTO_TCP; - -#if 0 - /* The use of getprotobyname() is disabled since it isn't thread-safe on - numerous systems. On these getprotobyname_r() should be used instead, but - that exists in at least one 4 arg version and one 5 arg version, and - since the proto number rarely changes anyway we now just use the hard - coded number. The "proper" fix would need a configure check for the - correct function much in the same style the gethostbyname_r versions are - detected. */ - struct protoent *pe = getprotobyname("tcp"); - if(pe) - proto = pe->p_proto; -#endif - - if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff, - sizeof(onoff)) < 0) - infof(data, "Could not set TCP_NODELAY: %s\n", - Curl_strerror(conn, SOCKERRNO)); - else - infof(data,"TCP_NODELAY set\n"); -#else - (void)conn; - (void)sockfd; -#endif -} - -#ifdef SO_NOSIGPIPE -/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when - sending data to a dead peer (instead of relying on the 4th argument to send - being MSG_NOSIGNAL). Possibly also existing and in use on other BSD - systems? */ -static void nosigpipe(struct connectdata *conn, - curl_socket_t sockfd) -{ - struct SessionHandle *data= conn->data; - int onoff = 1; - if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, - sizeof(onoff)) < 0) - infof(data, "Could not set SO_NOSIGPIPE: %s\n", - Curl_strerror(conn, SOCKERRNO)); -} -#else -#define nosigpipe(x,y) -#endif - -#ifdef WIN32 -/* When you run a program that uses the Windows Sockets API, you may - experience slow performance when you copy data to a TCP server. - - http://support.microsoft.com/kb/823764 - - Work-around: Make the Socket Send Buffer Size Larger Than the Program Send - Buffer Size - -*/ -void Curl_sndbufset(curl_socket_t sockfd) -{ - int val = CURL_MAX_WRITE_SIZE + 32; - int curval = 0; - int curlen = sizeof(curval); - - if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0) - if (curval > val) - return; - - setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); -} -#endif - - -/* - * singleipconnect() - * - * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to - * CURL_SOCKET_BAD. Other errors will however return proper errors. - * - * singleipconnect() connects to the given IP only, and it may return without - * having connected if used from the multi interface. - */ -static CURLcode -singleipconnect(struct connectdata *conn, - const Curl_addrinfo *ai, - long timeout_ms, - curl_socket_t *sockp, - bool *connected) -{ - struct Curl_sockaddr_ex addr; - int rc; - int error; - bool isconnected = FALSE; - struct SessionHandle *data = conn->data; - curl_socket_t sockfd; - CURLcode res = CURLE_OK; -#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) - struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr; -#endif - - *sockp = CURL_SOCKET_BAD; - - /* - * The Curl_sockaddr_ex structure is basically libcurl's external API - * curl_sockaddr structure with enough space available to directly hold - * any protocol-specific address structures. The variable declared here - * will be used to pass / receive data to/from the fopensocket callback - * if this has been set, before that, it is initialized from parameters. - */ - - addr.family = ai->ai_family; - addr.socktype = conn->socktype; - addr.protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol; - addr.addrlen = ai->ai_addrlen; - - if(addr.addrlen > sizeof(struct Curl_sockaddr_storage)) - addr.addrlen = sizeof(struct Curl_sockaddr_storage); - memcpy(&addr.sa_addr, ai->ai_addr, addr.addrlen); - - *connected = FALSE; /* default is not connected */ - - if(data->set.fopensocket) - /* - * If the opensocket callback is set, all the destination address - * information is passed to the callback. Depending on this information the - * callback may opt to abort the connection, this is indicated returning - * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When - * the callback returns a valid socket the destination address information - * might have been changed and this 'new' address will actually be used - * here to connect. - */ - sockfd = data->set.fopensocket(data->set.opensocket_client, - CURLSOCKTYPE_IPCXN, - (struct curl_sockaddr *)&addr); - else - /* opensocket callback not set, so simply create the socket now */ - sockfd = socket(addr.family, addr.socktype, addr.protocol); - - if(sockfd == CURL_SOCKET_BAD) - /* no socket, no connection */ - return CURLE_OK; - -#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) - if (conn->scope && (addr.family == AF_INET6)) - sa6->sin6_scope_id = conn->scope; -#endif - - /* store remote address and port used in this connection attempt */ - if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, - conn->primary_ip, &conn->primary_port)) { - /* malformed address or bug in inet_ntop, try next address */ - error = ERRNO; - failf(data, "sa_addr inet_ntop() failed with errno %d: %s", - error, Curl_strerror(conn, error)); - sclose(sockfd); - return CURLE_OK; - } - memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); - infof(data, " Trying %s... ", conn->ip_addr_str); - - Curl_persistconninfo(conn); - -#ifdef ENABLE_IPV6 - if(addr.family == AF_INET6) - conn->bits.ipv6 = TRUE; -#endif - - if(data->set.tcp_nodelay) - tcpnodelay(conn, sockfd); - - nosigpipe(conn, sockfd); - - Curl_sndbufset(sockfd); - - if(data->set.fsockopt) { - /* activate callback for setting socket options */ - error = data->set.fsockopt(data->set.sockopt_client, - sockfd, - CURLSOCKTYPE_IPCXN); - - if(error == CURL_SOCKOPT_ALREADY_CONNECTED) - isconnected = TRUE; - else if(error) { - sclose(sockfd); /* close the socket and bail out */ - return CURLE_ABORTED_BY_CALLBACK; - } - } - - /* possibly bind the local end to an IP, interface or port */ - res = bindlocal(conn, sockfd, addr.family); - if(res) { - sclose(sockfd); /* close socket and bail out */ - return res; - } - - /* set socket non-blocking */ - curlx_nonblock(sockfd, TRUE); - - /* Connect TCP sockets, bind UDP */ - if(!isconnected && (conn->socktype == SOCK_STREAM)) { - rc = connect(sockfd, &addr.sa_addr, addr.addrlen); - conn->connecttime = Curl_tvnow(); - if(conn->num_addr > 1) - Curl_expire(data, conn->timeoutms_per_addr); - } - else - rc = 0; - - if(-1 == rc) { - error = SOCKERRNO; - - switch (error) { - case EINPROGRESS: - case EWOULDBLOCK: -#if defined(EAGAIN) -#if (EAGAIN) != (EWOULDBLOCK) - /* On some platforms EAGAIN and EWOULDBLOCK are the - * same value, and on others they are different, hence - * the odd #if - */ - case EAGAIN: -#endif -#endif - rc = waitconnect(conn, sockfd, timeout_ms); - if(WAITCONN_ABORTED == rc) { - sclose(sockfd); - return CURLE_ABORTED_BY_CALLBACK; - } - break; - default: - /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect to %s: %s", - conn->ip_addr_str, Curl_strerror(conn,error)); - data->state.os_errno = error; - break; - } - } - - /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from - connect(). We can be sure of this since connect() cannot return 1. */ - if((WAITCONN_TIMEOUT == rc) && - (data->state.used_interface == Curl_if_multi)) { - /* Timeout when running the multi interface */ - *sockp = sockfd; - return CURLE_OK; - } - - if(!isconnected) - isconnected = verifyconnect(sockfd, &error); - - if(!rc && isconnected) { - /* we are connected, awesome! */ - *connected = TRUE; /* this is a true connect */ - infof(data, "connected\n"); - Curl_updateconninfo(conn, sockfd); - *sockp = sockfd; - return CURLE_OK; - } - else if(WAITCONN_TIMEOUT == rc) - infof(data, "Timeout\n"); - else { - data->state.os_errno = error; - infof(data, "%s\n", Curl_strerror(conn, error)); - } - - /* connect failed or timed out */ - sclose(sockfd); - - return CURLE_OK; -} - -/* - * TCP connect to the given host with timeout, proxy or remote doesn't matter. - * There might be more than one IP address to try out. Fill in the passed - * pointer with the connected socket. - */ - -CURLcode Curl_connecthost(struct connectdata *conn, /* context */ - const struct Curl_dns_entry *remotehost, - curl_socket_t *sockconn, /* the connected socket */ - Curl_addrinfo **addr, /* the one we used */ - bool *connected) /* really connected? */ -{ - struct SessionHandle *data = conn->data; - curl_socket_t sockfd = CURL_SOCKET_BAD; - int aliasindex; - Curl_addrinfo *ai; - Curl_addrinfo *curr_addr; - - struct timeval after; - struct timeval before = Curl_tvnow(); - - /************************************************************* - * Figure out what maximum time we have left - *************************************************************/ - long timeout_ms; - - DEBUGASSERT(sockconn); - *connected = FALSE; /* default to not connected */ - - /* get the timeout left */ - timeout_ms = Curl_timeleft(data, &before, TRUE); - - if(timeout_ms < 0) { - /* a precaution, no need to continue if time already is up */ - failf(data, "Connection time-out"); - return CURLE_OPERATION_TIMEDOUT; - } - - /* Max time for each address */ - conn->num_addr = Curl_num_addresses(remotehost->addr); - conn->timeoutms_per_addr = timeout_ms / conn->num_addr; - - ai = remotehost->addr; - - /* Below is the loop that attempts to connect to all IP-addresses we - * know for the given host. One by one until one IP succeeds. - */ - - /* - * Connecting with a Curl_addrinfo chain - */ - for (curr_addr = ai, aliasindex=0; curr_addr; - curr_addr = curr_addr->ai_next, aliasindex++) { - - /* start connecting to the IP curr_addr points to */ - CURLcode res = - singleipconnect(conn, curr_addr, - /* don't hang when doing multi */ - (data->state.used_interface == Curl_if_multi)?0: - conn->timeoutms_per_addr, &sockfd, connected); - - if(res) - return res; - - if(sockfd != CURL_SOCKET_BAD) - break; - - /* get a new timeout for next attempt */ - after = Curl_tvnow(); - timeout_ms -= Curl_tvdiff(after, before); - if(timeout_ms < 0) { - failf(data, "connect() timed out!"); - return CURLE_OPERATION_TIMEDOUT; - } - before = after; - } /* end of connect-to-each-address loop */ - - *sockconn = sockfd; /* the socket descriptor we've connected */ - - if(sockfd == CURL_SOCKET_BAD) { - /* no good connect was made */ - failf(data, "couldn't connect to host"); - return CURLE_COULDNT_CONNECT; - } - - /* leave the socket in non-blocking mode */ - - /* store the address we use */ - if(addr) - *addr = curr_addr; - - data->info.numconnects++; /* to track the number of connections made */ - - return CURLE_OK; -} - -/* - * Used to extract socket and connectdata struct for the most recent - * transfer on the given SessionHandle. - * - * The returned socket will be CURL_SOCKET_BAD in case of failure! - */ -curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, - struct connectdata **connp) -{ - curl_socket_t sockfd; - - DEBUGASSERT(data); - - if((data->state.lastconnect != -1) && - (data->state.connc->connects[data->state.lastconnect] != NULL)) { - struct connectdata *c = - data->state.connc->connects[data->state.lastconnect]; - if(connp) - /* only store this if the caller cares for it */ - *connp = c; - sockfd = c->sock[FIRSTSOCKET]; - /* we have a socket connected, let's determine if the server shut down */ - /* determine if ssl */ - if(c->ssl[FIRSTSOCKET].use) { - /* use the SSL context */ - if(!Curl_ssl_check_cxn(c)) - return CURL_SOCKET_BAD; /* FIN received */ - } -/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ -#ifdef MSG_PEEK - else { - /* use the socket */ - char buf; - if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, - (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { - return CURL_SOCKET_BAD; /* FIN received */ - } - } -#endif - } - else - return CURL_SOCKET_BAD; - - return sockfd; -} diff --git a/third_party/curl/lib/connect.h b/third_party/curl/lib/connect.h deleted file mode 100644 index 0720085c2..000000000 --- a/third_party/curl/lib/connect.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef __CONNECT_H -#define __CONNECT_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */ - -CURLcode Curl_is_connected(struct connectdata *conn, - int sockindex, - bool *connected); - -CURLcode Curl_connecthost(struct connectdata *conn, - const struct Curl_dns_entry *host, /* connect to - this */ - curl_socket_t *sockconn, /* not set if error */ - Curl_addrinfo **addr, /* the one we used */ - bool *connected); /* truly connected? */ - -/* generic function that returns how much time there's left to run, according - to the timeouts set */ -long Curl_timeleft(struct SessionHandle *data, - struct timeval *nowp, - bool duringconnect); - -#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ - -/* - * Used to extract socket and connectdata struct for the most recent - * transfer on the given SessionHandle. - * - * The returned socket will be CURL_SOCKET_BAD in case of failure! - */ -curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, - struct connectdata **connp); - -#ifdef WIN32 -/* When you run a program that uses the Windows Sockets API, you may - experience slow performance when you copy data to a TCP server. - - http://support.microsoft.com/kb/823764 - - Work-around: Make the Socket Send Buffer Size Larger Than the Program Send - Buffer Size - -*/ -void Curl_sndbufset(curl_socket_t sockfd); -#else -#define Curl_sndbufset(y) -#endif - -void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd); - -void Curl_persistconninfo(struct connectdata *conn); - -#endif diff --git a/third_party/curl/lib/content_encoding.c b/third_party/curl/lib/content_encoding.c deleted file mode 100644 index 6fb7c8d3a..000000000 --- a/third_party/curl/lib/content_encoding.c +++ /dev/null @@ -1,426 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_LIBZ - -#include -#include - -#include "urldata.h" -#include -#include "sendf.h" -#include "content_encoding.h" -#include "curl_memory.h" - -#include "memdebug.h" - -/* Comment this out if zlib is always going to be at least ver. 1.2.0.4 - (doing so will reduce code size slightly). */ -#define OLD_ZLIB_SUPPORT 1 - -#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */ - -#define GZIP_MAGIC_0 0x1f -#define GZIP_MAGIC_1 0x8b - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xE0 /* bits 5..7: reserved */ - -static CURLcode -process_zlib_error(struct connectdata *conn, z_stream *z) -{ - struct SessionHandle *data = conn->data; - if(z->msg) - failf (data, "Error while processing content unencoding: %s", - z->msg); - else - failf (data, "Error while processing content unencoding: " - "Unknown failure within decompression software."); - - return CURLE_BAD_CONTENT_ENCODING; -} - -static CURLcode -exit_zlib(z_stream *z, zlibInitState *zlib_init, CURLcode result) -{ - inflateEnd(z); - *zlib_init = ZLIB_UNINIT; - return result; -} - -static CURLcode -inflate_stream(struct connectdata *conn, - struct SingleRequest *k) -{ - int allow_restart = 1; - z_stream *z = &k->z; /* zlib state structure */ - uInt nread = z->avail_in; - Bytef *orig_in = z->next_in; - int status; /* zlib status */ - CURLcode result = CURLE_OK; /* Curl_client_write status */ - char *decomp; /* Put the decompressed data here. */ - - /* Dynamically allocate a buffer for decompression because it's uncommonly - large to hold on the stack */ - decomp = malloc(DSIZ); - if(decomp == NULL) { - return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); - } - - /* because the buffer size is fixed, iteratively decompress and transfer to - the client via client_write. */ - for (;;) { - /* (re)set buffer for decompressed output for every iteration */ - z->next_out = (Bytef *)decomp; - z->avail_out = DSIZ; - - status = inflate(z, Z_SYNC_FLUSH); - if(status == Z_OK || status == Z_STREAM_END) { - allow_restart = 0; - if((DSIZ - z->avail_out) && (!k->ignorebody)) { - result = Curl_client_write(conn, CLIENTWRITE_BODY, decomp, - DSIZ - z->avail_out); - /* if !CURLE_OK, clean up, return */ - if(result) { - free(decomp); - return exit_zlib(z, &k->zlib_init, result); - } - } - - /* Done? clean up, return */ - if(status == Z_STREAM_END) { - free(decomp); - if(inflateEnd(z) == Z_OK) - return exit_zlib(z, &k->zlib_init, result); - else - return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); - } - - /* Done with these bytes, exit */ - - /* status is always Z_OK at this point! */ - if(z->avail_in == 0) { - free(decomp); - return result; - } - } - else if(allow_restart && status == Z_DATA_ERROR) { - /* some servers seem to not generate zlib headers, so this is an attempt - to fix and continue anyway */ - - (void) inflateEnd(z); /* don't care about the return code */ - if(inflateInit2(z, -MAX_WBITS) != Z_OK) { - free(decomp); - return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); - } - z->next_in = orig_in; - z->avail_in = nread; - allow_restart = 0; - continue; - } - else { /* Error; exit loop, handle below */ - free(decomp); - return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); - } - } - /* Will never get here */ -} - -CURLcode -Curl_unencode_deflate_write(struct connectdata *conn, - struct SingleRequest *k, - ssize_t nread) -{ - z_stream *z = &k->z; /* zlib state structure */ - - /* Initialize zlib? */ - if(k->zlib_init == ZLIB_UNINIT) { - z->zalloc = (alloc_func)Z_NULL; - z->zfree = (free_func)Z_NULL; - z->opaque = 0; - z->next_in = NULL; - z->avail_in = 0; - if(inflateInit(z) != Z_OK) - return process_zlib_error(conn, z); - k->zlib_init = ZLIB_INIT; - } - - /* Set the compressed input when this function is called */ - z->next_in = (Bytef *)k->str; - z->avail_in = (uInt)nread; - - /* Now uncompress the data */ - return inflate_stream(conn, k); -} - -#ifdef OLD_ZLIB_SUPPORT -/* Skip over the gzip header */ -static enum { - GZIP_OK, - GZIP_BAD, - GZIP_UNDERFLOW -} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen) -{ - int method, flags; - const ssize_t totallen = len; - - /* The shortest header is 10 bytes */ - if(len < 10) - return GZIP_UNDERFLOW; - - if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1)) - return GZIP_BAD; - - method = data[2]; - flags = data[3]; - - if(method != Z_DEFLATED || (flags & RESERVED) != 0) { - /* Can't handle this compression method or unknown flag */ - return GZIP_BAD; - } - - /* Skip over time, xflags, OS code and all previous bytes */ - len -= 10; - data += 10; - - if(flags & EXTRA_FIELD) { - ssize_t extra_len; - - if(len < 2) - return GZIP_UNDERFLOW; - - extra_len = (data[1] << 8) | data[0]; - - if(len < (extra_len+2)) - return GZIP_UNDERFLOW; - - len -= (extra_len + 2); - data += (extra_len + 2); - } - - if(flags & ORIG_NAME) { - /* Skip over NUL-terminated file name */ - while(len && *data) { - --len; - ++data; - } - if(!len || *data) - return GZIP_UNDERFLOW; - - /* Skip over the NUL */ - --len; - ++data; - } - - if(flags & COMMENT) { - /* Skip over NUL-terminated comment */ - while(len && *data) { - --len; - ++data; - } - if(!len || *data) - return GZIP_UNDERFLOW; - - /* Skip over the NUL */ - --len; - } - - if(flags & HEAD_CRC) { - if(len < 2) - return GZIP_UNDERFLOW; - - len -= 2; - } - - *headerlen = totallen - len; - return GZIP_OK; -} -#endif - -CURLcode -Curl_unencode_gzip_write(struct connectdata *conn, - struct SingleRequest *k, - ssize_t nread) -{ - z_stream *z = &k->z; /* zlib state structure */ - - /* Initialize zlib? */ - if(k->zlib_init == ZLIB_UNINIT) { - z->zalloc = (alloc_func)Z_NULL; - z->zfree = (free_func)Z_NULL; - z->opaque = 0; - z->next_in = NULL; - z->avail_in = 0; - - if(strcmp(zlibVersion(), "1.2.0.4") >= 0) { - /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */ - if(inflateInit2(z, MAX_WBITS+32) != Z_OK) { - return process_zlib_error(conn, z); - } - k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */ - } - else { - /* we must parse the gzip header ourselves */ - if(inflateInit2(z, -MAX_WBITS) != Z_OK) { - return process_zlib_error(conn, z); - } - k->zlib_init = ZLIB_INIT; /* Initial call state */ - } - } - - if(k->zlib_init == ZLIB_INIT_GZIP) { - /* Let zlib handle the gzip decompression entirely */ - z->next_in = (Bytef *)k->str; - z->avail_in = (uInt)nread; - /* Now uncompress the data */ - return inflate_stream(conn, k); - } - -#ifndef OLD_ZLIB_SUPPORT - /* Support for old zlib versions is compiled away and we are running with - an old version, so return an error. */ - return exit_zlib(z, &k->zlib_init, CURLE_FUNCTION_NOT_FOUND); - -#else - /* This next mess is to get around the potential case where there isn't - * enough data passed in to skip over the gzip header. If that happens, we - * malloc a block and copy what we have then wait for the next call. If - * there still isn't enough (this is definitely a worst-case scenario), we - * make the block bigger, copy the next part in and keep waiting. - * - * This is only required with zlib versions < 1.2.0.4 as newer versions - * can handle the gzip header themselves. - */ - - switch (k->zlib_init) { - /* Skip over gzip header? */ - case ZLIB_INIT: - { - /* Initial call state */ - ssize_t hlen; - - switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) { - case GZIP_OK: - z->next_in = (Bytef *)k->str + hlen; - z->avail_in = (uInt)(nread - hlen); - k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ - break; - - case GZIP_UNDERFLOW: - /* We need more data so we can find the end of the gzip header. It's - * possible that the memory block we malloc here will never be freed if - * the transfer abruptly aborts after this point. Since it's unlikely - * that circumstances will be right for this code path to be followed in - * the first place, and it's even more unlikely for a transfer to fail - * immediately afterwards, it should seldom be a problem. - */ - z->avail_in = (uInt)nread; - z->next_in = malloc(z->avail_in); - if(z->next_in == NULL) { - return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); - } - memcpy(z->next_in, k->str, z->avail_in); - k->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */ - /* We don't have any data to inflate yet */ - return CURLE_OK; - - case GZIP_BAD: - default: - return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); - } - - } - break; - - case ZLIB_GZIP_HEADER: - { - /* Need more gzip header data state */ - ssize_t hlen; - unsigned char *oldblock = z->next_in; - - z->avail_in += (uInt)nread; - z->next_in = realloc(z->next_in, z->avail_in); - if(z->next_in == NULL) { - free(oldblock); - return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); - } - /* Append the new block of data to the previous one */ - memcpy(z->next_in + z->avail_in - nread, k->str, nread); - - switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) { - case GZIP_OK: - /* This is the zlib stream data */ - free(z->next_in); - /* Don't point into the malloced block since we just freed it */ - z->next_in = (Bytef *)k->str + hlen + nread - z->avail_in; - z->avail_in = (uInt)(z->avail_in - hlen); - k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ - break; - - case GZIP_UNDERFLOW: - /* We still don't have any data to inflate! */ - return CURLE_OK; - - case GZIP_BAD: - default: - free(z->next_in); - return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z)); - } - - } - break; - - case ZLIB_GZIP_INFLATING: - default: - /* Inflating stream state */ - z->next_in = (Bytef *)k->str; - z->avail_in = (uInt)nread; - break; - } - - if(z->avail_in == 0) { - /* We don't have any data to inflate; wait until next time */ - return CURLE_OK; - } - - /* We've parsed the header, now uncompress the data */ - return inflate_stream(conn, k); -#endif -} - -void Curl_unencode_cleanup(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - struct SingleRequest *k = &data->req; - z_stream *z = &k->z; - if(k->zlib_init != ZLIB_UNINIT) - (void) exit_zlib(z, &k->zlib_init, CURLE_OK); -} - -#endif /* HAVE_LIBZ */ diff --git a/third_party/curl/lib/content_encoding.h b/third_party/curl/lib/content_encoding.h deleted file mode 100644 index 3aff9d3c0..000000000 --- a/third_party/curl/lib/content_encoding.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __CURL_CONTENT_ENCODING_H -#define __CURL_CONTENT_ENCODING_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "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) -#endif - -CURLcode Curl_unencode_deflate_write(struct connectdata *conn, - struct SingleRequest *req, - ssize_t nread); - -CURLcode -Curl_unencode_gzip_write(struct connectdata *conn, - struct SingleRequest *k, - ssize_t nread); - - -#endif diff --git a/third_party/curl/lib/cookie.c b/third_party/curl/lib/cookie.c deleted file mode 100644 index e81b9e36e..000000000 --- a/third_party/curl/lib/cookie.c +++ /dev/null @@ -1,1168 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/*** - - -RECEIVING COOKIE INFORMATION -============================ - -struct CookieInfo *cookie_init(char *file); - - Inits a cookie struct to store data in a local file. This is always - called before any cookies are set. - -int cookies_set(struct CookieInfo *cookie, char *cookie_line); - - The 'cookie_line' parameter is a full "Set-cookie:" line as - received from a server. - - The function need to replace previously stored lines that this new - line superceeds. - - It may remove lines that are expired. - - It should return an indication of success/error. - - -SENDING COOKIE INFORMATION -========================== - -struct Cookies *cookie_getlist(struct CookieInfo *cookie, - char *host, char *path, bool secure); - - For a given host and path, return a linked list of cookies that - the client should send to the server if used now. The secure - boolean informs the cookie if a secure connection is achieved or - not. - - It shall only return cookies that haven't expired. - - -Example set of cookies: - - Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure - Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; - domain=.fidelity.com; path=/ftgw; secure - Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; - domain=.fidelity.com; path=/; secure - Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; - domain=.fidelity.com; path=/; secure - Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; - domain=.fidelity.com; path=/; secure - Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; - domain=.fidelity.com; path=/; secure - Set-cookie: - Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday, - 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure -****/ - - -#include "setup.h" - -#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) - -#include -#include - -#define _MPRINTF_REPLACE /* without this on windows OS we get undefined reference to snprintf */ -#include - -#include "urldata.h" -#include "cookie.h" -#include "strequal.h" -#include "strtok.h" -#include "sendf.h" -#include "curl_memory.h" -#include "share.h" -#include "strtoofft.h" -#include "rawstr.h" -#include "curl_memrchr.h" - -/* The last #include file should be: */ -#include "memdebug.h" - - -static void freecookie(struct Cookie *co) -{ - if(co->expirestr) - free(co->expirestr); - if(co->domain) - free(co->domain); - if(co->path) - free(co->path); - if(co->name) - free(co->name); - if(co->value) - free(co->value); - if(co->maxage) - free(co->maxage); - if(co->version) - free(co->version); - - free(co); -} - -static bool tailmatch(const char *little, const char *bigone) -{ - size_t littlelen = strlen(little); - size_t biglen = strlen(bigone); - - if(littlelen > biglen) - return FALSE; - - return (bool)Curl_raw_equal(little, bigone+biglen-littlelen); -} - -/* - * Load cookies from all given cookie files (CURLOPT_COOKIEFILE). - */ -void Curl_cookie_loadfiles(struct SessionHandle *data) -{ - struct curl_slist *list = data->change.cookielist; - if(list) { - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - while(list) { - data->cookies = Curl_cookie_init(data, - list->data, - data->cookies, - data->set.cookiesession); - list = list->next; - } - Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); - curl_slist_free_all(data->change.cookielist); /* clean up list */ - data->change.cookielist = NULL; /* don't do this again! */ - } -} - -/* - * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL - * that will be freed before the allocated string is stored there. - * - * It is meant to easily replace strdup() - */ -static void strstore(char **str, const char *newstr) -{ - if(*str) - free(*str); - *str = strdup(newstr); -} - - -/**************************************************************************** - * - * Curl_cookie_add() - * - * Add a single cookie line to the cookie keeping object. - * - ***************************************************************************/ - -struct Cookie * -Curl_cookie_add(struct SessionHandle *data, - /* The 'data' pointer here may be NULL at times, and thus - must only be used very carefully for things that can deal - with data being NULL. Such as infof() and similar */ - - struct CookieInfo *c, - bool httpheader, /* TRUE if HTTP header-style line */ - char *lineptr, /* first character of the line */ - const char *domain, /* default domain */ - const char *path) /* full path used when this cookie is set, - used to get default path for the cookie - unless set */ -{ - struct Cookie *clist; - char name[MAX_NAME]; - struct Cookie *co; - struct Cookie *lastc=NULL; - time_t now = time(NULL); - bool replace_old = FALSE; - bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */ - -#ifdef CURL_DISABLE_VERBOSE_STRINGS - (void)data; -#endif - - /* First, alloc and init a new struct for it */ - co = calloc(1, sizeof(struct Cookie)); - if(!co) - return NULL; /* bail out if we're this low on memory */ - - if(httpheader) { - /* This line was read off a HTTP-header */ - const char *ptr; - const char *sep; - const char *semiptr; - char *what; - - what = malloc(MAX_COOKIE_LINE); - if(!what) { - free(co); - return NULL; - } - - semiptr=strchr(lineptr, ';'); /* first, find a semicolon */ - - while(*lineptr && ISBLANK(*lineptr)) - lineptr++; - - ptr = lineptr; - do { - /* we have a = pair or a 'secure' word here */ - sep = strchr(ptr, '='); - if(sep && (!semiptr || (semiptr>sep)) ) { - /* - * There is a = sign and if there was a semicolon too, which make sure - * that the semicolon comes _after_ the equal sign. - */ - - name[0]=what[0]=0; /* init the buffers */ - if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;=]=%" - MAX_COOKIE_LINE_TXT "[^;\r\n]", - name, what)) { - /* this is a = pair. We use strstore() below to properly - deal with received cookie headers that have the same string - property set more than once, and then we use the last one. */ - - const char *whatptr; - - /* Strip off trailing whitespace from the 'what' */ - size_t len=strlen(what); - while(len && ISBLANK(what[len-1])) { - what[len-1]=0; - len--; - } - - /* Skip leading whitespace from the 'what' */ - whatptr=what; - while(*whatptr && ISBLANK(*whatptr)) { - whatptr++; - } - - if(Curl_raw_equal("path", name)) { - strstore(&co->path, whatptr); - if(!co->path) { - badcookie = TRUE; /* out of memory bad */ - break; - } - } - else if(Curl_raw_equal("domain", name)) { - /* note that this name may or may not have a preceding dot, but - we don't care about that, we treat the names the same anyway */ - - const char *domptr=whatptr; - const char *nextptr; - int dotcount=1; - - /* Count the dots, we need to make sure that there are enough - of them. */ - - if('.' == whatptr[0]) - /* don't count the initial dot, assume it */ - domptr++; - - do { - nextptr = strchr(domptr, '.'); - if(nextptr) { - if(domptr != nextptr) - dotcount++; - domptr = nextptr+1; - } - } while(nextptr); - - /* The original Netscape cookie spec defined that this domain name - MUST have three dots (or two if one of the seven holy TLDs), - but it seems that these kinds of cookies are in use "out there" - so we cannot be that strict. I've therefore lowered the check - to not allow less than two dots. */ - - if(dotcount < 2) { - /* Received and skipped a cookie with a domain using too few - dots. */ - badcookie=TRUE; /* mark this as a bad cookie */ - infof(data, "skipped cookie with illegal dotcount domain: %s\n", - whatptr); - } - else { - /* Now, we make sure that our host is within the given domain, - or the given domain is not valid and thus cannot be set. */ - - if('.' == whatptr[0]) - whatptr++; /* ignore preceding dot */ - - if(!domain || tailmatch(whatptr, domain)) { - const char *tailptr=whatptr; - if(tailptr[0] == '.') - tailptr++; - strstore(&co->domain, tailptr); /* don't prefix w/dots - internally */ - if(!co->domain) { - badcookie = TRUE; - break; - } - co->tailmatch=TRUE; /* we always do that if the domain name was - given */ - } - else { - /* we did not get a tailmatch and then the attempted set domain - is not a domain to which the current host belongs. Mark as - bad. */ - badcookie=TRUE; - infof(data, "skipped cookie with bad tailmatch domain: %s\n", - whatptr); - } - } - } - else if(Curl_raw_equal("version", name)) { - strstore(&co->version, whatptr); - if(!co->version) { - badcookie = TRUE; - break; - } - } - else if(Curl_raw_equal("max-age", name)) { - /* Defined in RFC2109: - - Optional. The Max-Age attribute defines the lifetime of the - cookie, in seconds. The delta-seconds value is a decimal non- - negative integer. After delta-seconds seconds elapse, the - client should discard the cookie. A value of zero means the - cookie should be discarded immediately. - - */ - strstore(&co->maxage, whatptr); - if(!co->maxage) { - badcookie = TRUE; - break; - } - co->expires = - strtol((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0],NULL,10) - + (long)now; - } - else if(Curl_raw_equal("expires", name)) { - strstore(&co->expirestr, whatptr); - if(!co->expirestr) { - badcookie = TRUE; - break; - } - /* Note that if the date couldn't get parsed for whatever reason, - the cookie will be treated as a session cookie */ - co->expires = curl_getdate(what, &now); - - /* Session cookies have expires set to 0 so if we get that back - from the date parser let's add a second to make it a - non-session cookie */ - if (co->expires == 0) - co->expires = 1; - else if( co->expires < 0 ) - co->expires = 0; - } - else if(!co->name) { - co->name = strdup(name); - co->value = strdup(whatptr); - if(!co->name || !co->value) { - badcookie = TRUE; - break; - } - } - /* - else this is the second (or more) name we don't know - about! */ - } - else { - /* this is an "illegal" = pair */ - } - } - else { - if(sscanf(ptr, "%" MAX_COOKIE_LINE_TXT "[^;\r\n]", - what)) { - if(Curl_raw_equal("secure", what)) { - co->secure = TRUE; - } - else if (Curl_raw_equal("httponly", what)) { - co->httponly = TRUE; - } - /* else, - unsupported keyword without assign! */ - - } - } - if(!semiptr || !*semiptr) { - /* we already know there are no more cookies */ - semiptr = NULL; - continue; - } - - ptr=semiptr+1; - while(*ptr && ISBLANK(*ptr)) - ptr++; - semiptr=strchr(ptr, ';'); /* now, find the next semicolon */ - - if(!semiptr && *ptr) - /* There are no more semicolons, but there's a final name=value pair - coming up */ - semiptr=strchr(ptr, '\0'); - } while(semiptr); - - if(!badcookie && !co->domain) { - if(domain) { - /* no domain was given in the header line, set the default */ - co->domain=strdup(domain); - if(!co->domain) - badcookie = TRUE; - } - } - - if(!badcookie && !co->path && path) { - /* No path was given in the header line, set the default. - Note that the passed-in path to this function MAY have a '?' and - following part that MUST not be stored as part of the path. */ - char *queryp = strchr(path, '?'); - - /* queryp is where the interesting part of the path ends, so now we - want to the find the last */ - char *endslash; - if(!queryp) - endslash = strrchr(path, '/'); - else - endslash = memrchr(path, '/', (size_t)(queryp - path)); - if(endslash) { - size_t pathlen = (size_t)(endslash-path+1); /* include ending slash */ - co->path=malloc(pathlen+1); /* one extra for the zero byte */ - if(co->path) { - memcpy(co->path, path, pathlen); - co->path[pathlen]=0; /* zero terminate */ - } - else - badcookie = TRUE; - } - } - - free(what); - - if(badcookie || !co->name) { - /* we didn't get a cookie name or a bad one, - this is an illegal line, bail out */ - freecookie(co); - return NULL; - } - - } - else { - /* This line is NOT a HTTP header style line, we do offer support for - reading the odd netscape cookies-file format here */ - char *ptr; - char *firstptr; - char *tok_buf=NULL; - int fields; - - /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies - marked with httpOnly after the domain name are not accessible - from javascripts, but since curl does not operate at javascript - level, we include them anyway. In Firefox's cookie files, these - lines are preceded with #HttpOnly_ and then everything is - as usual, so we skip 10 characters of the line.. - */ - if (strncmp(lineptr, "#HttpOnly_", 10) == 0) { - lineptr += 10; - co->httponly = TRUE; - } - - if(lineptr[0]=='#') { - /* don't even try the comments */ - free(co); - return NULL; - } - /* strip off the possible end-of-line characters */ - ptr=strchr(lineptr, '\r'); - if(ptr) - *ptr=0; /* clear it */ - ptr=strchr(lineptr, '\n'); - if(ptr) - *ptr=0; /* clear it */ - - firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */ - - /* Here's a quick check to eliminate normal HTTP-headers from this */ - if(!firstptr || strchr(firstptr, ':')) { - free(co); - return NULL; - } - - /* Now loop through the fields and init the struct we already have - allocated */ - for(ptr=firstptr, fields=0; ptr && !badcookie; - ptr=strtok_r(NULL, "\t", &tok_buf), fields++) { - switch(fields) { - case 0: - if(ptr[0]=='.') /* skip preceding dots */ - ptr++; - co->domain = strdup(ptr); - if(!co->domain) - badcookie = TRUE; - break; - case 1: - /* This field got its explanation on the 23rd of May 2001 by - Andrés García: - - flag: A TRUE/FALSE value indicating if all machines within a given - domain can access the variable. This value is set automatically by - the browser, depending on the value you set for the domain. - - As far as I can see, it is set to true when the cookie says - .domain.com and to false when the domain is complete www.domain.com - */ - co->tailmatch=(bool)Curl_raw_equal(ptr, "TRUE"); /* store information */ - break; - case 2: - /* It turns out, that sometimes the file format allows the path - field to remain not filled in, we try to detect this and work - around it! Andrés García made us aware of this... */ - if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) { - /* only if the path doesn't look like a boolean option! */ - co->path = strdup(ptr); - if(!co->path) - badcookie = TRUE; - break; - } - /* this doesn't look like a path, make one up! */ - co->path = strdup("/"); - if(!co->path) - badcookie = TRUE; - fields++; /* add a field and fall down to secure */ - /* FALLTHROUGH */ - case 3: - co->secure = (bool)Curl_raw_equal(ptr, "TRUE"); - break; - case 4: - co->expires = curlx_strtoofft(ptr, NULL, 10); - break; - case 5: - co->name = strdup(ptr); - if(!co->name) - badcookie = TRUE; - break; - case 6: - co->value = strdup(ptr); - if(!co->value) - badcookie = TRUE; - break; - } - } - if(6 == fields) { - /* we got a cookie with blank contents, fix it */ - co->value = strdup(""); - if(!co->value) - badcookie = TRUE; - else - fields++; - } - - if(!badcookie && (7 != fields)) - /* we did not find the sufficient number of fields */ - badcookie = TRUE; - - if(badcookie) { - freecookie(co); - return NULL; - } - - } - - if(!c->running && /* read from a file */ - c->newsession && /* clean session cookies */ - !co->expires) { /* this is a session cookie since it doesn't expire! */ - freecookie(co); - return NULL; - } - - co->livecookie = c->running; - - /* now, we have parsed the incoming line, we must now check if this - superceeds an already existing cookie, which it may if the previous have - the same domain and path as this */ - - clist = c->cookies; - replace_old = FALSE; - while(clist) { - if(Curl_raw_equal(clist->name, co->name)) { - /* the names are identical */ - - if(clist->domain && co->domain) { - if(Curl_raw_equal(clist->domain, co->domain)) - /* The domains are identical */ - replace_old=TRUE; - } - else if(!clist->domain && !co->domain) - replace_old = TRUE; - - if(replace_old) { - /* the domains were identical */ - - if(clist->path && co->path) { - if(Curl_raw_equal(clist->path, co->path)) { - replace_old = TRUE; - } - else - replace_old = FALSE; - } - else if(!clist->path && !co->path) - replace_old = TRUE; - else - replace_old = FALSE; - - } - - if(replace_old && !co->livecookie && clist->livecookie) { - /* Both cookies matched fine, except that the already present - cookie is "live", which means it was set from a header, while - the new one isn't "live" and thus only read from a file. We let - live cookies stay alive */ - - /* Free the newcomer and get out of here! */ - freecookie(co); - return NULL; - } - - if(replace_old) { - co->next = clist->next; /* get the next-pointer first */ - - /* then free all the old pointers */ - free(clist->name); - if(clist->value) - free(clist->value); - if(clist->domain) - free(clist->domain); - if(clist->path) - free(clist->path); - if(clist->expirestr) - free(clist->expirestr); - - if(clist->version) - free(clist->version); - if(clist->maxage) - free(clist->maxage); - - *clist = *co; /* then store all the new data */ - - free(co); /* free the newly alloced memory */ - co = clist; /* point to the previous struct instead */ - - /* We have replaced a cookie, now skip the rest of the list but - make sure the 'lastc' pointer is properly set */ - do { - lastc = clist; - clist = clist->next; - } while(clist); - break; - } - } - lastc = clist; - clist = clist->next; - } - - if(c->running) - /* Only show this when NOT reading the cookies from a file */ - infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, " - "expire %" FORMAT_OFF_T "\n", - replace_old?"Replaced":"Added", co->name, co->value, - co->domain, co->path, co->expires); - - if(!replace_old) { - /* then make the last item point on this new one */ - if(lastc) - lastc->next = co; - else - c->cookies = co; - } - - c->numcookies++; /* one more cookie in the jar */ - return co; -} - -/***************************************************************************** - * - * Curl_cookie_init() - * - * Inits a cookie struct to read data from a local file. This is always - * called before any cookies are set. File may be NULL. - * - * If 'newsession' is TRUE, discard all "session cookies" on read from file. - * - ****************************************************************************/ -struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, - const char *file, - struct CookieInfo *inc, - bool newsession) -{ - struct CookieInfo *c; - FILE *fp; - bool fromfile=TRUE; - - if(NULL == inc) { - /* we didn't get a struct, create one */ - c = calloc(1, sizeof(struct CookieInfo)); - if(!c) - return NULL; /* failed to get memory */ - c->filename = strdup(file?file:"none"); /* copy the name just in case */ - } - else { - /* we got an already existing one, use that */ - c = inc; - } - c->running = FALSE; /* this is not running, this is init */ - - if(file && strequal(file, "-")) { - fp = stdin; - fromfile=FALSE; - } - else if(file && !*file) { - /* points to a "" string */ - fp = NULL; - } - else - fp = file?fopen(file, "r"):NULL; - - c->newsession = newsession; /* new session? */ - - if(fp) { - char *lineptr; - bool headerline; - - char *line = malloc(MAX_COOKIE_LINE); - if(line) { - while(fgets(line, MAX_COOKIE_LINE, fp)) { - if(checkprefix("Set-Cookie:", line)) { - /* This is a cookie line, get it! */ - lineptr=&line[11]; - headerline=TRUE; - } - else { - lineptr=line; - headerline=FALSE; - } - while(*lineptr && ISBLANK(*lineptr)) - lineptr++; - - Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL); - } - free(line); /* free the line buffer */ - } - if(fromfile) - fclose(fp); - } - - c->running = TRUE; /* now, we're running */ - - return c; -} - -/* sort this so that the longest path gets before the shorter path */ -static int cookie_sort(const void *p1, const void *p2) -{ - struct Cookie *c1 = *(struct Cookie **)p1; - struct Cookie *c2 = *(struct Cookie **)p2; - - size_t l1 = c1->path?strlen(c1->path):0; - size_t l2 = c2->path?strlen(c2->path):0; - - return (l2 > l1) ? 1 : (l2 < l1) ? -1 : 0 ; -} - -/***************************************************************************** - * - * Curl_cookie_getlist() - * - * For a given host and path, return a linked list of cookies that the - * client should send to the server if used now. The secure boolean informs - * the cookie if a secure connection is achieved or not. - * - * It shall only return cookies that haven't expired. - * - ****************************************************************************/ - -struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, - const char *host, const char *path, - bool secure) -{ - struct Cookie *newco; - struct Cookie *co; - time_t now = time(NULL); - struct Cookie *mainco=NULL; - size_t matches = 0; - - if(!c || !c->cookies) - return NULL; /* no cookie struct or no cookies in the struct */ - - co = c->cookies; - - while(co) { - /* only process this cookie if it is not expired or had no expire - date AND that if the cookie requires we're secure we must only - continue if we are! */ - if( (!co->expires || (co->expires > now)) && - (co->secure?secure:TRUE) ) { - - /* now check if the domain is correct */ - if(!co->domain || - (co->tailmatch && tailmatch(co->domain, host)) || - (!co->tailmatch && Curl_raw_equal(host, co->domain)) ) { - /* the right part of the host matches the domain stuff in the - cookie data */ - - /* now check the left part of the path with the cookies path - requirement */ - if(!co->path || - /* not using checkprefix() because matching should be - case-sensitive */ - !strncmp(co->path, path, strlen(co->path)) ) { - - /* and now, we know this is a match and we should create an - entry for the return-linked-list */ - - newco = malloc(sizeof(struct Cookie)); - if(newco) { - /* first, copy the whole source cookie: */ - memcpy(newco, co, sizeof(struct Cookie)); - - /* then modify our next */ - newco->next = mainco; - - /* point the main to us */ - mainco = newco; - - matches++; - } - else { - fail: - /* failure, clear up the allocated chain and return NULL */ - while(mainco) { - co = mainco->next; - free(mainco); - mainco = co; - } - - return NULL; - } - } - } - } - co = co->next; - } - - if(matches) { - /* Now we need to make sure that if there is a name appearing more than - once, the longest specified path version comes first. To make this - the swiftest way, we just sort them all based on path length. */ - struct Cookie **array; - size_t i; - - /* alloc an array and store all cookie pointers */ - array = (struct Cookie **)malloc(sizeof(struct Cookie *) * matches); - if(!array) - goto fail; - - co = mainco; - - for(i=0; co; co = co->next) - array[i++] = co; - - /* now sort the cookie pointers in path lenth order */ - qsort(array, matches, sizeof(struct Cookie *), cookie_sort); - - /* remake the linked list order according to the new order */ - - mainco = array[0]; /* start here */ - for(i=0; inext = array[i+1]; - array[matches-1]->next = NULL; /* terminate the list */ - - free(array); /* remove the temporary data again */ - } - - return mainco; /* return the new list */ -} - -/***************************************************************************** - * - * Curl_cookie_clearall() - * - * Clear all existing cookies and reset the counter. - * - ****************************************************************************/ -void Curl_cookie_clearall(struct CookieInfo *cookies) -{ - if(cookies) { - Curl_cookie_freelist(cookies->cookies, TRUE); - cookies->cookies = NULL; - cookies->numcookies = 0; - } -} - -/***************************************************************************** - * - * Curl_cookie_freelist() - * - * Free a list of cookies previously returned by Curl_cookie_getlist(); - * - * The 'cookiestoo' argument tells this function whether to just free the - * list or actually also free all cookies within the list as well. - * - ****************************************************************************/ - -void Curl_cookie_freelist(struct Cookie *co, bool cookiestoo) -{ - struct Cookie *next; - if(co) { - while(co) { - next = co->next; - if(cookiestoo) - freecookie(co); - else - free(co); /* we only free the struct since the "members" are all just - pointed out in the main cookie list! */ - co = next; - } - } -} - - -/***************************************************************************** - * - * Curl_cookie_clearsess() - * - * Free all session cookies in the cookies list. - * - ****************************************************************************/ -void Curl_cookie_clearsess(struct CookieInfo *cookies) -{ - struct Cookie *first, *curr, *next, *prev = NULL; - - if(!cookies || !cookies->cookies) - return; - - first = curr = prev = cookies->cookies; - - for(; curr; curr = next) { - next = curr->next; - if(!curr->expires) { - if(first == curr) - first = next; - - if(prev == curr) - prev = next; - else - prev->next = next; - - freecookie(curr); - cookies->numcookies--; - } - else - prev = curr; - } - - cookies->cookies = first; -} - - -/***************************************************************************** - * - * Curl_cookie_cleanup() - * - * Free a "cookie object" previous created with cookie_init(). - * - ****************************************************************************/ -void Curl_cookie_cleanup(struct CookieInfo *c) -{ - struct Cookie *co; - struct Cookie *next; - if(c) { - if(c->filename) - free(c->filename); - co = c->cookies; - - while(co) { - next = co->next; - freecookie(co); - co = next; - } - free(c); /* free the base struct as well */ - } -} - -/* get_netscape_format() - * - * Formats a string for Netscape output file, w/o a newline at the end. - * - * Function returns a char * to a formatted line. Has to be free()d -*/ -static char *get_netscape_format(const struct Cookie *co) -{ - return aprintf( - "%s" /* httponly preamble */ - "%s%s\t" /* domain */ - "%s\t" /* tailmatch */ - "%s\t" /* path */ - "%s\t" /* secure */ - "%" FORMAT_OFF_T "\t" /* expires */ - "%s\t" /* name */ - "%s", /* value */ - co->httponly?"#HttpOnly_":"", - /* Make sure all domains are prefixed with a dot if they allow - tailmatching. This is Mozilla-style. */ - (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"", - co->domain?co->domain:"unknown", - co->tailmatch?"TRUE":"FALSE", - co->path?co->path:"/", - co->secure?"TRUE":"FALSE", - co->expires, - co->name, - co->value?co->value:""); -} - -/* - * Curl_cookie_output() - * - * Writes all internally known cookies to the specified file. Specify - * "-" as file name to write to stdout. - * - * The function returns non-zero on write failure. - */ -int Curl_cookie_output(struct CookieInfo *c, const char *dumphere) -{ - struct Cookie *co; - FILE *out; - bool use_stdout=FALSE; - - if((NULL == c) || (0 == c->numcookies)) - /* If there are no known cookies, we don't write or even create any - destination file */ - return 0; - - if(strequal("-", dumphere)) { - /* use stdout */ - out = stdout; - use_stdout=TRUE; - } - else { - out = fopen(dumphere, "w"); - if(!out) - return 1; /* failure */ - } - - if(c) { - char *format_ptr; - - fputs("# Netscape HTTP Cookie File\n" - "# http://curl.haxx.se/rfc/cookie_spec.html\n" - "# This file was generated by libcurl! Edit at your own risk.\n\n", - out); - co = c->cookies; - - while(co) { - format_ptr = get_netscape_format(co); - if(format_ptr == NULL) { - fprintf(out, "#\n# Fatal libcurl error\n"); - if(!use_stdout) - fclose(out); - return 1; - } - fprintf(out, "%s\n", format_ptr); - free(format_ptr); - co=co->next; - } - } - - if(!use_stdout) - fclose(out); - - return 0; -} - -struct curl_slist *Curl_cookie_list(struct SessionHandle *data) -{ - struct curl_slist *list = NULL; - struct curl_slist *beg; - struct Cookie *c; - char *line; - - if((data->cookies == NULL) || - (data->cookies->numcookies == 0)) - return NULL; - - c = data->cookies->cookies; - - beg = list; - while(c) { - /* fill the list with _all_ the cookies we know */ - line = get_netscape_format(c); - if(line == NULL) { - curl_slist_free_all(beg); - return NULL; - } - list = curl_slist_append(list, line); - free(line); - if(list == NULL) { - curl_slist_free_all(beg); - return NULL; - } - else if(beg == NULL) { - beg = list; - } - c = c->next; - } - - return list; -} - -void Curl_flush_cookies(struct SessionHandle *data, int cleanup) -{ - if(data->set.str[STRING_COOKIEJAR]) { - if(data->change.cookielist) { - /* If there is a list of cookie files to read, do it first so that - we have all the told files read before we write the new jar. - Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */ - Curl_cookie_loadfiles(data); - } - - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - - /* if we have a destination file for all the cookies to get dumped to */ - if(Curl_cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR])) - infof(data, "WARNING: failed to save cookies in %s\n", - data->set.str[STRING_COOKIEJAR]); - } - else { - if(cleanup && data->change.cookielist) - /* since nothing is written, we can just free the list of cookie file - names */ - curl_slist_free_all(data->change.cookielist); /* clean up list */ - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - } - - if(cleanup && (!data->share || (data->cookies != data->share->cookies))) { - Curl_cookie_cleanup(data->cookies); - } - Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); -} - -#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */ diff --git a/third_party/curl/lib/cookie.h b/third_party/curl/lib/cookie.h deleted file mode 100644 index 6b159b238..000000000 --- a/third_party/curl/lib/cookie.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef __COOKIE_H -#define __COOKIE_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 -#if defined(WIN32) -#include -#else -#ifdef HAVE_SYS_TIME_H -#include -#endif -#endif - -#include - -struct Cookie { - struct Cookie *next; /* next in the chain */ - char *name; /* = value */ - char *value; /* name = */ - char *path; /* path = */ - char *domain; /* domain = */ - curl_off_t expires; /* expires = */ - char *expirestr; /* the plain text version */ - bool tailmatch; /* weather we do tail-matchning of the domain name */ - - /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ - char *version; /* Version = */ - char *maxage; /* Max-Age = */ - - bool secure; /* whether the 'secure' keyword was used */ - bool livecookie; /* updated from a server, not a stored file */ - bool httponly; /* true if the httponly directive is present */ -}; - -struct CookieInfo { - /* linked list of cookies we know of */ - struct Cookie *cookies; - - char *filename; /* file we read from/write to */ - bool running; /* state info, for cookie adding information */ - long numcookies; /* number of cookies in the "jar" */ - bool newsession; /* new session, discard session cookies on load */ -}; - -/* This is the maximum line length we accept for a cookie line. RFC 2109 - section 6.3 says: - - "at least 4096 bytes per cookie (as measured by the size of the characters - that comprise the cookie non-terminal in the syntax description of the - Set-Cookie header)" - -*/ -#define MAX_COOKIE_LINE 5000 -#define MAX_COOKIE_LINE_TXT "4999" - -/* This is the maximum length of a cookie name we deal with: */ -#define MAX_NAME 1024 -#define MAX_NAME_TXT "1023" - -struct SessionHandle; -/* - * Add a cookie to the internal list of cookies. The domain and path arguments - * are only used if the header boolean is TRUE. - */ - -struct Cookie *Curl_cookie_add(struct SessionHandle *data, - struct CookieInfo *, bool header, char *lineptr, - const char *domain, const char *path); - -struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, - const char *, bool); -void Curl_cookie_freelist(struct Cookie *cookies, bool cookiestoo); -void Curl_cookie_clearall(struct CookieInfo *cookies); -void Curl_cookie_clearsess(struct CookieInfo *cookies); -int Curl_cookie_output(struct CookieInfo *, const char *); - -#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES) -#define Curl_cookie_list(x) NULL -#define Curl_cookie_loadfiles(x) do { } while (0) -#define Curl_cookie_init(x,y,z,w) NULL -#define Curl_cookie_cleanup(x) -#define Curl_flush_cookies(x,y) -#else -void Curl_flush_cookies(struct SessionHandle *data, int cleanup); -void Curl_cookie_cleanup(struct CookieInfo *); -struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, - const char *, struct CookieInfo *, bool); -struct curl_slist *Curl_cookie_list(struct SessionHandle *data); -void Curl_cookie_loadfiles(struct SessionHandle *data); -#endif - -#endif diff --git a/third_party/curl/lib/curl_addrinfo.c b/third_party/curl/lib/curl_addrinfo.c deleted file mode 100644 index 43843301c..000000000 --- a/third_party/curl/lib/curl_addrinfo.c +++ /dev/null @@ -1,529 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include - -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_NETDB_H -# include -#endif -#ifdef HAVE_ARPA_INET_H -# include -#endif - -#ifdef __VMS -# include -# include -# include -#endif - -#if defined(NETWARE) && defined(__NOVELL_LIBC__) -# undef in_addr_t -# define in_addr_t unsigned long -#endif - -#include "curl_addrinfo.h" -#include "inet_pton.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - - -/* - * Curl_freeaddrinfo() - * - * This is used to free a linked list of Curl_addrinfo structs along - * with all its associated allocated storage. This function should be - * called once for each successful call to Curl_getaddrinfo_ex() or to - * any function call which actually allocates a Curl_addrinfo struct. - */ - -#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \ - defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__) - /* workaround icc 9.1 optimizer issue */ -# define vqualifier volatile -#else -# define vqualifier -#endif - -void -Curl_freeaddrinfo(Curl_addrinfo *cahead) -{ - Curl_addrinfo *vqualifier canext; - Curl_addrinfo *ca; - - for(ca = cahead; ca != NULL; ca = canext) { - - if(ca->ai_addr) - free(ca->ai_addr); - - if(ca->ai_canonname) - free(ca->ai_canonname); - - canext = ca->ai_next; - - free(ca); - } -} - - -#ifdef HAVE_GETADDRINFO -/* - * Curl_getaddrinfo_ex() - * - * This is a wrapper function around system's getaddrinfo(), with - * the only difference that instead of returning a linked list of - * addrinfo structs this one returns a linked list of Curl_addrinfo - * ones. The memory allocated by this function *MUST* be free'd with - * Curl_freeaddrinfo(). For each successful call to this function - * there must be an associated call later to Curl_freeaddrinfo(). - * - * There should be no single call to system's getaddrinfo() in the - * whole library, any such call should be 'routed' through this one. - */ - -int -Curl_getaddrinfo_ex(const char *nodename, - const char *servname, - const struct addrinfo *hints, - Curl_addrinfo **result) -{ - const struct addrinfo *ai; - struct addrinfo *aihead; - Curl_addrinfo *cafirst = NULL; - Curl_addrinfo *calast = NULL; - Curl_addrinfo *ca; - size_t ss_size; - int error; - - *result = NULL; /* assume failure */ - - error = getaddrinfo(nodename, servname, hints, &aihead); - if(error) - return error; - - /* traverse the addrinfo list */ - - for(ai = aihead; ai != NULL; ai = ai->ai_next) { - - /* ignore elements with unsupported address family, */ - /* settle family-specific sockaddr structure size. */ - if(ai->ai_family == AF_INET) - ss_size = sizeof(struct sockaddr_in); -#ifdef ENABLE_IPV6 - else if(ai->ai_family == AF_INET6) - ss_size = sizeof(struct sockaddr_in6); -#endif - else - continue; - - /* ignore elements without required address info */ - if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0)) - continue; - - /* ignore elements with bogus address size */ - if((size_t)ai->ai_addrlen < ss_size) - continue; - - if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) { - error = EAI_MEMORY; - break; - } - - /* copy each structure member individually, member ordering, */ - /* size, or padding might be different for each platform. */ - - ca->ai_flags = ai->ai_flags; - ca->ai_family = ai->ai_family; - ca->ai_socktype = ai->ai_socktype; - ca->ai_protocol = ai->ai_protocol; - ca->ai_addrlen = (curl_socklen_t)ss_size; - ca->ai_addr = NULL; - ca->ai_canonname = NULL; - ca->ai_next = NULL; - - if((ca->ai_addr = malloc(ss_size)) == NULL) { - error = EAI_MEMORY; - free(ca); - break; - } - memcpy(ca->ai_addr, ai->ai_addr, ss_size); - - if(ai->ai_canonname != NULL) { - if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) { - error = EAI_MEMORY; - free(ca->ai_addr); - free(ca); - break; - } - } - - /* if the return list is empty, this becomes the first element */ - if(!cafirst) - cafirst = ca; - - /* add this element last in the return list */ - if(calast) - calast->ai_next = ca; - calast = ca; - - } - - /* destroy the addrinfo list */ - if(aihead) - freeaddrinfo(aihead); - - /* if we failed, also destroy the Curl_addrinfo list */ - if(error) { - Curl_freeaddrinfo(cafirst); - cafirst = NULL; - } - else if(!cafirst) { -#ifdef EAI_NONAME - /* rfc3493 conformant */ - error = EAI_NONAME; -#else - /* rfc3493 obsoleted */ - error = EAI_NODATA; -#endif -#ifdef USE_WINSOCK - SET_SOCKERRNO(error); -#endif - } - - *result = cafirst; - - /* This is not a CURLcode */ - return error; -} -#endif /* HAVE_GETADDRINFO */ - - -/* - * Curl_he2ai() - * - * This function returns a pointer to the first element of a newly allocated - * Curl_addrinfo struct linked list filled with the data of a given hostent. - * Curl_addrinfo is meant to work like the addrinfo struct does for a IPv6 - * stack, but usable also for IPv4, all hosts and environments. - * - * The memory allocated by this function *MUST* be free'd later on calling - * Curl_freeaddrinfo(). For each successful call to this function there - * must be an associated call later to Curl_freeaddrinfo(). - * - * Curl_addrinfo defined in "lib/curl_addrinfo.h" - * - * struct Curl_addrinfo { - * int ai_flags; - * int ai_family; - * int ai_socktype; - * int ai_protocol; - * curl_socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo * - * char *ai_canonname; - * struct sockaddr *ai_addr; - * struct Curl_addrinfo *ai_next; - * }; - * typedef struct Curl_addrinfo Curl_addrinfo; - * - * hostent defined in - * - * struct hostent { - * char *h_name; - * char **h_aliases; - * int h_addrtype; - * int h_length; - * char **h_addr_list; - * }; - * - * for backward compatibility: - * - * #define h_addr h_addr_list[0] - */ - -Curl_addrinfo * -Curl_he2ai(const struct hostent *he, int port) -{ - Curl_addrinfo *ai; - Curl_addrinfo *prevai = NULL; - Curl_addrinfo *firstai = NULL; - struct sockaddr_in *addr; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 *addr6; -#endif - CURLcode result = CURLE_OK; - int i; - char *curr; - - if(!he) - /* no input == no output! */ - return NULL; - - DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL)); - - for(i=0; (curr = he->h_addr_list[i]) != NULL; i++) { - - size_t ss_size; -#ifdef ENABLE_IPV6 - if (he->h_addrtype == AF_INET6) - ss_size = sizeof (struct sockaddr_in6); - else -#endif - ss_size = sizeof (struct sockaddr_in); - - if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) { - result = CURLE_OUT_OF_MEMORY; - break; - } - if((ai->ai_canonname = strdup(he->h_name)) == NULL) { - result = CURLE_OUT_OF_MEMORY; - free(ai); - break; - } - if((ai->ai_addr = calloc(1, ss_size)) == NULL) { - result = CURLE_OUT_OF_MEMORY; - free(ai->ai_canonname); - free(ai); - break; - } - - if(!firstai) - /* store the pointer we want to return from this function */ - firstai = ai; - - if(prevai) - /* make the previous entry point to this */ - prevai->ai_next = ai; - - ai->ai_family = he->h_addrtype; - - /* we return all names as STREAM, so when using this address for TFTP - the type must be ignored and conn->socktype be used instead! */ - ai->ai_socktype = SOCK_STREAM; - - ai->ai_addrlen = (curl_socklen_t)ss_size; - - /* leave the rest of the struct filled with zero */ - - switch (ai->ai_family) { - case AF_INET: - addr = (void *)ai->ai_addr; /* storage area for this info */ - - memcpy(&addr->sin_addr, curr, sizeof(struct in_addr)); - addr->sin_family = (unsigned short)(he->h_addrtype); - addr->sin_port = htons((unsigned short)port); - break; - -#ifdef ENABLE_IPV6 - case AF_INET6: - addr6 = (void *)ai->ai_addr; /* storage area for this info */ - - memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr)); - addr6->sin6_family = (unsigned short)(he->h_addrtype); - addr6->sin6_port = htons((unsigned short)port); - break; -#endif - } - - prevai = ai; - } - - if(result != CURLE_OK) { - Curl_freeaddrinfo(firstai); - firstai = NULL; - } - - return firstai; -} - - -struct namebuff { - struct hostent hostentry; - union { - struct in_addr ina4; -#ifdef ENABLE_IPV6 - struct in6_addr ina6; -#endif - } addrentry; - char *h_addr_list[2]; -}; - - -/* - * Curl_ip2addr() - * - * This function takes an internet address, in binary form, as input parameter - * along with its address family and the string version of the address, and it - * returns a Curl_addrinfo chain filled in correctly with information for the - * given address/host - */ - -Curl_addrinfo * -Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port) -{ - Curl_addrinfo *ai; - -#if defined(__VMS) && \ - defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64) -#pragma pointer_size save -#pragma pointer_size short -#pragma message disable PTRMISMATCH -#endif - - struct hostent *h; - struct namebuff *buf; - char *addrentry; - char *hoststr; - size_t addrsize; - - DEBUGASSERT(inaddr && hostname); - - buf = malloc(sizeof(struct namebuff)); - if(!buf) - return NULL; - - hoststr = strdup(hostname); - if(!hoststr) { - free(buf); - return NULL; - } - - switch(af) { - case AF_INET: - addrsize = sizeof(struct in_addr); - addrentry = (void *)&buf->addrentry.ina4; - memcpy(addrentry, inaddr, sizeof(struct in_addr)); - break; -#ifdef ENABLE_IPV6 - case AF_INET6: - addrsize = sizeof(struct in6_addr); - addrentry = (void *)&buf->addrentry.ina6; - memcpy(addrentry, inaddr, sizeof(struct in6_addr)); - break; -#endif - default: - free(hoststr); - free(buf); - return NULL; - } - - h = &buf->hostentry; - h->h_name = hoststr; - h->h_aliases = NULL; - h->h_addrtype = (short)af; - h->h_length = (short)addrsize; - h->h_addr_list = &buf->h_addr_list[0]; - h->h_addr_list[0] = addrentry; - h->h_addr_list[1] = NULL; /* terminate list of entries */ - -#if defined(__VMS) && \ - defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64) -#pragma pointer_size restore -#pragma message enable PTRMISMATCH -#endif - - ai = Curl_he2ai(h, port); - - free(hoststr); - free(buf); - - return ai; -} - -/* - * Given an IPv4 or IPv6 dotted string address, this converts it to a proper - * allocated Curl_addrinfo struct and returns it. - */ -Curl_addrinfo *Curl_str2addr(char *address, int port) -{ - struct in_addr in; - if(Curl_inet_pton(AF_INET, address, &in) > 0) - /* This is a dotted IP address 123.123.123.123-style */ - return Curl_ip2addr(AF_INET, &in, address, port); -#ifdef ENABLE_IPV6 - else { - struct in6_addr in6; - if(Curl_inet_pton(AF_INET6, address, &in6) > 0) - /* This is a dotted IPv6 address ::1-style */ - return Curl_ip2addr(AF_INET6, &in6, address, port); - } -#endif - return NULL; /* bad input format */ -} - -#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) -/* - * curl_dofreeaddrinfo() - * - * This is strictly for memory tracing and are using the same style as the - * family otherwise present in memdebug.c. I put these ones here since they - * require a bunch of structs I didn't want to include in memdebug.c - */ - -void -curl_dofreeaddrinfo(struct addrinfo *freethis, - int line, const char *source) -{ - (freeaddrinfo)(freethis); - curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n", - source, line, (void *)freethis); -} -#endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */ - - -#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) -/* - * curl_dogetaddrinfo() - * - * This is strictly for memory tracing and are using the same style as the - * family otherwise present in memdebug.c. I put these ones here since they - * require a bunch of structs I didn't want to include in memdebug.c - */ - -int -curl_dogetaddrinfo(const char *hostname, - const char *service, - const struct addrinfo *hints, - struct addrinfo **result, - int line, const char *source) -{ - int res=(getaddrinfo)(hostname, service, hints, result); - if(0 == res) - /* success */ - curl_memlog("ADDR %s:%d getaddrinfo() = %p\n", - source, line, (void *)*result); - else - curl_memlog("ADDR %s:%d getaddrinfo() failed\n", - source, line); - return res; -} -#endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */ diff --git a/third_party/curl/lib/curl_addrinfo.h b/third_party/curl/lib/curl_addrinfo.h deleted file mode 100644 index 11c339474..000000000 --- a/third_party/curl/lib/curl_addrinfo.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef HEADER_CURL_ADDRINFO_H -#define HEADER_CURL_ADDRINFO_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_NETDB_H -# include -#endif -#ifdef HAVE_ARPA_INET_H -# include -#endif - -#ifdef __VMS -# include -# include -# include -#endif - - -/* - * Curl_addrinfo is our internal struct definition that we use to allow - * consistent internal handling of this data. We use this even when the - * system provides an addrinfo structure definition. And we use this for - * all sorts of IPv4 and IPV6 builds. - */ - -struct Curl_addrinfo { - int ai_flags; - int ai_family; - int ai_socktype; - int ai_protocol; - curl_socklen_t ai_addrlen; /* Follow rfc3493 struct addrinfo */ - char *ai_canonname; - struct sockaddr *ai_addr; - struct Curl_addrinfo *ai_next; -}; -typedef struct Curl_addrinfo Curl_addrinfo; - -void -Curl_freeaddrinfo(Curl_addrinfo *cahead); - -#ifdef HAVE_GETADDRINFO -int -Curl_getaddrinfo_ex(const char *nodename, - const char *servname, - const struct addrinfo *hints, - Curl_addrinfo **result); -#endif - -Curl_addrinfo * -Curl_he2ai(const struct hostent *he, int port); - -Curl_addrinfo * -Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); - -Curl_addrinfo *Curl_str2addr(char *dotted, int port); - -#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) -void -curl_dofreeaddrinfo(struct addrinfo *freethis, - int line, const char *source); -#endif - -#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) -int -curl_dogetaddrinfo(const char *hostname, - const char *service, - const struct addrinfo *hints, - struct addrinfo **result, - int line, const char *source); -#endif - -#endif /* HEADER_CURL_ADDRINFO_H */ diff --git a/third_party/curl/lib/curl_base64.h b/third_party/curl/lib/curl_base64.h deleted file mode 100644 index 2498a0a22..000000000 --- a/third_party/curl/lib/curl_base64.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef HEADER_CURL_BASE64_H -#define HEADER_CURL_BASE64_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -size_t Curl_base64_encode(struct SessionHandle *data, - const char *inputbuff, size_t insize, - char **outptr); - -size_t Curl_base64_decode(const char *src, unsigned char **outptr); - -#endif /* HEADER_CURL_BASE64_H */ diff --git a/third_party/curl/lib/curl_config.h.cmake b/third_party/curl/lib/curl_config.h.cmake deleted file mode 100644 index deebe71dc..000000000 --- a/third_party/curl/lib/curl_config.h.cmake +++ /dev/null @@ -1,953 +0,0 @@ -/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ - -/* Define to 1 if you have the $func function. */ -#cmakedefine AS_TR_CPP ${AS_TR_CPP} - -/* when building libcurl itself */ -#cmakedefine BUILDING_LIBCURL ${BUILDING_LIBCURL} - -/* Location of default ca bundle */ -#cmakedefine CURL_CA_BUNDLE ${CURL_CA_BUNDLE} - -/* Location of default ca path */ -#cmakedefine CURL_CA_PATH ${CURL_CA_PATH} - -/* to disable cookies support */ -#cmakedefine CURL_DISABLE_COOKIES ${CURL_DISABLE_COOKIES} - -/* to disable cryptographic authentication */ -#cmakedefine CURL_DISABLE_CRYPTO_AUTH ${CURL_DISABLE_CRYPTO_AUTH} - -/* to disable DICT */ -#cmakedefine CURL_DISABLE_DICT ${CURL_DISABLE_DICT} - -/* to disable FILE */ -#cmakedefine CURL_DISABLE_FILE ${CURL_DISABLE_FILE} - -/* to disable FTP */ -#cmakedefine CURL_DISABLE_FTP ${CURL_DISABLE_FTP} - -/* to disable HTTP */ -#cmakedefine CURL_DISABLE_HTTP ${CURL_DISABLE_HTTP} - -/* to disable LDAP */ -#cmakedefine CURL_DISABLE_LDAP ${CURL_DISABLE_LDAP} - -/* to disable LDAPS */ -#cmakedefine CURL_DISABLE_LDAPS ${CURL_DISABLE_LDAPS} - -/* to disable proxies */ -#cmakedefine CURL_DISABLE_PROXY ${CURL_DISABLE_PROXY} - -/* to disable TELNET */ -#cmakedefine CURL_DISABLE_TELNET ${CURL_DISABLE_TELNET} - -/* to disable TFTP */ -#cmakedefine CURL_DISABLE_TFTP ${CURL_DISABLE_TFTP} - -/* to disable verbose strings */ -#cmakedefine CURL_DISABLE_VERBOSE_STRINGS ${CURL_DISABLE_VERBOSE_STRINGS} - -/* 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 - -/* to enable hidden symbols */ -#cmakedefine CURL_HIDDEN_SYMBOLS ${CURL_HIDDEN_SYMBOLS} - -/* Use Windows LDAP implementation */ -#cmakedefine CURL_LDAP_WIN ${CURL_LDAP_WIN} - -/* when not building a shared library */ -#cmakedefine CURL_STATICLIB ${CURL_STATICLIB} - -/* Set to explicitly specify we don't want to use thread-safe functions */ -#cmakedefine DISABLED_THREADSAFE ${DISABLED_THREADSAFE} - -/* your Entropy Gathering Daemon socket pathname */ -#cmakedefine EGD_SOCKET ${EGD_SOCKET} - -/* Define if you want to enable IPv6 support */ -#cmakedefine ENABLE_IPV6 ${ENABLE_IPV6} - -/* 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 ${HAVE_ALARM} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_ALLOCA_H ${HAVE_ALLOCA_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_ARPA_INET_H ${HAVE_ARPA_INET_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_ARPA_TFTP_H ${HAVE_ARPA_TFTP_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_ASSERT_H ${HAVE_ASSERT_H} - -/* Define to 1 if you have the `basename' function. */ -#cmakedefine HAVE_BASENAME ${HAVE_BASENAME} - -/* Define to 1 if bool is an available type. */ -#cmakedefine HAVE_BOOL_T ${HAVE_BOOL_T} - -/* Define to 1 if you have the clock_gettime function and monotonic timer. */ -#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC ${HAVE_CLOCK_GETTIME_MONOTONIC} - -/* Define to 1 if you have the `closesocket' function. */ -#cmakedefine HAVE_CLOSESOCKET ${HAVE_CLOSESOCKET} - -/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ -#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA ${HAVE_CRYPTO_CLEANUP_ALL_EX_DATA} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_CRYPTO_H ${HAVE_CRYPTO_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_DES_H ${HAVE_DES_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_DLFCN_H ${HAVE_DLFCN_H} - -/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ -#cmakedefine HAVE_ENGINE_LOAD_BUILTIN_ENGINES ${HAVE_ENGINE_LOAD_BUILTIN_ENGINES} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_ERR_H ${HAVE_ERR_H} - -/* Define to 1 if you have the fcntl function. */ -#cmakedefine HAVE_FCNTL ${HAVE_FCNTL} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H} - -/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ -#cmakedefine HAVE_FCNTL_O_NONBLOCK ${HAVE_FCNTL_O_NONBLOCK} - -/* Define to 1 if you have the fdopen function. */ -#cmakedefine HAVE_FDOPEN ${HAVE_FDOPEN} - -/* Define to 1 if you have the `fork' function. */ -#cmakedefine HAVE_FORK ${HAVE_FORK} - -/* Define to 1 if you have the freeaddrinfo function. */ -#cmakedefine HAVE_FREEADDRINFO ${HAVE_FREEADDRINFO} - -/* Define to 1 if you have the freeifaddrs function. */ -#cmakedefine HAVE_FREEIFADDRS ${HAVE_FREEIFADDRS} - -/* Define to 1 if you have the ftruncate function. */ -#cmakedefine HAVE_FTRUNCATE ${HAVE_FTRUNCATE} - -/* Define to 1 if you have a working getaddrinfo function. */ -#cmakedefine HAVE_GETADDRINFO ${HAVE_GETADDRINFO} - -/* Define to 1 if you have the `geteuid' function. */ -#cmakedefine HAVE_GETEUID ${HAVE_GETEUID} - -/* Define to 1 if you have the gethostbyaddr function. */ -#cmakedefine HAVE_GETHOSTBYADDR ${HAVE_GETHOSTBYADDR} - -/* Define to 1 if you have the gethostbyaddr_r function. */ -#cmakedefine HAVE_GETHOSTBYADDR_R ${HAVE_GETHOSTBYADDR_R} - -/* gethostbyaddr_r() takes 5 args */ -#cmakedefine HAVE_GETHOSTBYADDR_R_5 ${HAVE_GETHOSTBYADDR_R_5} - -/* gethostbyaddr_r() takes 7 args */ -#cmakedefine HAVE_GETHOSTBYADDR_R_7 ${HAVE_GETHOSTBYADDR_R_7} - -/* gethostbyaddr_r() takes 8 args */ -#cmakedefine HAVE_GETHOSTBYADDR_R_8 ${HAVE_GETHOSTBYADDR_R_8} - -/* Define to 1 if you have the gethostbyname function. */ -#cmakedefine HAVE_GETHOSTBYNAME ${HAVE_GETHOSTBYNAME} - -/* Define to 1 if you have the gethostbyname_r function. */ -#cmakedefine HAVE_GETHOSTBYNAME_R ${HAVE_GETHOSTBYNAME_R} - -/* gethostbyname_r() takes 3 args */ -#cmakedefine HAVE_GETHOSTBYNAME_R_3 ${HAVE_GETHOSTBYNAME_R_3} - -/* gethostbyname_r() takes 5 args */ -#cmakedefine HAVE_GETHOSTBYNAME_R_5 ${HAVE_GETHOSTBYNAME_R_5} - -/* gethostbyname_r() takes 6 args */ -#cmakedefine HAVE_GETHOSTBYNAME_R_6 ${HAVE_GETHOSTBYNAME_R_6} - -/* Define to 1 if you have the gethostname function. */ -#cmakedefine HAVE_GETHOSTNAME ${HAVE_GETHOSTNAME} - -/* Define to 1 if you have a working getifaddrs function. */ -#cmakedefine HAVE_GETIFADDRS ${HAVE_GETIFADDRS} - -/* Define to 1 if you have the getnameinfo function. */ -#cmakedefine HAVE_GETNAMEINFO ${HAVE_GETNAMEINFO} - -/* Define to 1 if you have the `getpass_r' function. */ -#cmakedefine HAVE_GETPASS_R ${HAVE_GETPASS_R} - -/* Define to 1 if you have the `getppid' function. */ -#cmakedefine HAVE_GETPPID ${HAVE_GETPPID} - -/* Define to 1 if you have the `getprotobyname' function. */ -#cmakedefine HAVE_GETPROTOBYNAME ${HAVE_GETPROTOBYNAME} - -/* Define to 1 if you have the `getpwuid' function. */ -#cmakedefine HAVE_GETPWUID ${HAVE_GETPWUID} - -/* Define to 1 if you have the `getrlimit' function. */ -#cmakedefine HAVE_GETRLIMIT ${HAVE_GETRLIMIT} - -/* Define to 1 if you have the getservbyport_r function. */ -#cmakedefine HAVE_GETSERVBYPORT_R ${HAVE_GETSERVBYPORT_R} - -/* Define to 1 if you have the `gettimeofday' function. */ -#cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY} - -/* Define to 1 if you have a working glibc-style strerror_r function. */ -#cmakedefine HAVE_GLIBC_STRERROR_R ${HAVE_GLIBC_STRERROR_R} - -/* Define to 1 if you have a working gmtime_r function. */ -#cmakedefine HAVE_GMTIME_R ${HAVE_GMTIME_R} - -/* if you have the gssapi libraries */ -#cmakedefine HAVE_GSSAPI ${HAVE_GSSAPI} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_GSSAPI_GSSAPI_GENERIC_H ${HAVE_GSSAPI_GSSAPI_GENERIC_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_GSSAPI_GSSAPI_H ${HAVE_GSSAPI_GSSAPI_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_GSSAPI_GSSAPI_KRB5_H ${HAVE_GSSAPI_GSSAPI_KRB5_H} - -/* if you have the GNU gssapi libraries */ -#cmakedefine HAVE_GSSGNU ${HAVE_GSSGNU} - -/* if you have the Heimdal gssapi libraries */ -#cmakedefine HAVE_GSSHEIMDAL ${HAVE_GSSHEIMDAL} - -/* if you have the MIT gssapi libraries */ -#cmakedefine HAVE_GSSMIT ${HAVE_GSSMIT} - -/* Define to 1 if you have the `idna_strerror' function. */ -#cmakedefine HAVE_IDNA_STRERROR ${HAVE_IDNA_STRERROR} - -/* Define to 1 if you have the `idn_free' function. */ -#cmakedefine HAVE_IDN_FREE ${HAVE_IDN_FREE} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_IDN_FREE_H ${HAVE_IDN_FREE_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_IFADDRS_H ${HAVE_IFADDRS_H} - -/* Define to 1 if you have the `inet_addr' function. */ -#cmakedefine HAVE_INET_ADDR ${HAVE_INET_ADDR} - -/* Define to 1 if you have the inet_ntoa_r function. */ -#cmakedefine HAVE_INET_NTOA_R ${HAVE_INET_NTOA_R} - -/* inet_ntoa_r() takes 2 args */ -#cmakedefine HAVE_INET_NTOA_R_2 ${HAVE_INET_NTOA_R_2} - -/* inet_ntoa_r() takes 3 args */ -#cmakedefine HAVE_INET_NTOA_R_3 ${HAVE_INET_NTOA_R_3} - -/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ -#cmakedefine HAVE_INET_NTOP ${HAVE_INET_NTOP} - -/* Define to 1 if you have a IPv6 capable working inet_pton function. */ -#cmakedefine HAVE_INET_PTON ${HAVE_INET_PTON} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H} - -/* Define to 1 if you have the ioctl function. */ -#cmakedefine HAVE_IOCTL ${HAVE_IOCTL} - -/* Define to 1 if you have the ioctlsocket function. */ -#cmakedefine HAVE_IOCTLSOCKET ${HAVE_IOCTLSOCKET} - -/* Define to 1 if you have the IoctlSocket camel case function. */ -#cmakedefine HAVE_IOCTLSOCKET_CAMEL ${HAVE_IOCTLSOCKET_CAMEL} - -/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. - */ -#cmakedefine HAVE_IOCTLSOCKET_CAMEL_FIONBIO ${HAVE_IOCTLSOCKET_CAMEL_FIONBIO} - -/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ -#cmakedefine HAVE_IOCTLSOCKET_FIONBIO ${HAVE_IOCTLSOCKET_FIONBIO} - -/* Define to 1 if you have a working ioctl FIONBIO function. */ -#cmakedefine HAVE_IOCTL_FIONBIO ${HAVE_IOCTL_FIONBIO} - -/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ -#cmakedefine HAVE_IOCTL_SIOCGIFADDR ${HAVE_IOCTL_SIOCGIFADDR} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_IO_H ${HAVE_IO_H} - -/* if you have the Kerberos4 libraries (including -ldes) */ -#cmakedefine HAVE_KRB4 ${HAVE_KRB4} - -/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ -#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM ${HAVE_KRB_GET_OUR_IP_FOR_REALM} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_KRB_H ${HAVE_KRB_H} - -/* Define to 1 if you have the lber.h header file. */ -#cmakedefine HAVE_LBER_H ${HAVE_LBER_H} - -/* Define to 1 if you have the ldapssl.h header file. */ -#cmakedefine HAVE_LDAPSSL_H ${HAVE_LDAPSSL_H} - -/* Define to 1 if you have the ldap.h header file. */ -#cmakedefine HAVE_LDAP_H ${HAVE_LDAP_H} - -/* Use LDAPS implementation */ -#cmakedefine HAVE_LDAP_SSL ${HAVE_LDAP_SSL} - -/* Define to 1 if you have the ldap_ssl.h header file. */ -#cmakedefine HAVE_LDAP_SSL_H ${HAVE_LDAP_SSL_H} - -/* Define to 1 if you have the `ldap_url_parse' function. */ -#cmakedefine HAVE_LDAP_URL_PARSE ${HAVE_LDAP_URL_PARSE} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_LIBGEN_H ${HAVE_LIBGEN_H} - -/* Define to 1 if you have the `idn' library (-lidn). */ -#cmakedefine HAVE_LIBIDN ${HAVE_LIBIDN} - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -#cmakedefine HAVE_LIBRESOLV ${HAVE_LIBRESOLV} - -/* Define to 1 if you have the `resolve' library (-lresolve). */ -#cmakedefine HAVE_LIBRESOLVE ${HAVE_LIBRESOLVE} - -/* Define to 1 if you have the `socket' library (-lsocket). */ -#cmakedefine HAVE_LIBSOCKET ${HAVE_LIBSOCKET} - -/* Define to 1 if you have the `ssh2' library (-lssh2). */ -#cmakedefine HAVE_LIBSSH2 ${HAVE_LIBSSH2} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_LIBSSH2_H ${HAVE_LIBSSH2_H} - -/* Define to 1 if you have the `ssl' library (-lssl). */ -#cmakedefine HAVE_LIBSSL ${HAVE_LIBSSL} - -/* if zlib is available */ -#cmakedefine HAVE_LIBZ ${HAVE_LIBZ} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H} - -/* if your compiler supports LL */ -#cmakedefine HAVE_LL ${HAVE_LL} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_LOCALE_H ${HAVE_LOCALE_H} - -/* Define to 1 if you have a working localtime_r function. */ -#cmakedefine HAVE_LOCALTIME_R ${HAVE_LOCALTIME_R} - -/* Define to 1 if the compiler supports the 'long long' data type. */ -#cmakedefine HAVE_LONGLONG ${HAVE_LONGLONG} - -/* Define to 1 if you have the malloc.h header file. */ -#cmakedefine HAVE_MALLOC_H ${HAVE_MALLOC_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_MEMORY_H ${HAVE_MEMORY_H} - -/* Define to 1 if you have the MSG_NOSIGNAL flag. */ -#cmakedefine HAVE_MSG_NOSIGNAL ${HAVE_MSG_NOSIGNAL} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_NETDB_H ${HAVE_NETDB_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_NETINET_IN_H ${HAVE_NETINET_IN_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_NETINET_TCP_H ${HAVE_NETINET_TCP_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_NET_IF_H ${HAVE_NET_IF_H} - -/* Define to 1 if NI_WITHSCOPEID exists and works. */ -#cmakedefine HAVE_NI_WITHSCOPEID ${HAVE_NI_WITHSCOPEID} - -/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE - */ -#cmakedefine HAVE_OLD_GSSMIT ${HAVE_OLD_GSSMIT} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_OPENSSL_CRYPTO_H ${HAVE_OPENSSL_CRYPTO_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_OPENSSL_ENGINE_H ${HAVE_OPENSSL_ENGINE_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_OPENSSL_ERR_H ${HAVE_OPENSSL_ERR_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_OPENSSL_PEM_H ${HAVE_OPENSSL_PEM_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_OPENSSL_PKCS12_H ${HAVE_OPENSSL_PKCS12_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_OPENSSL_RSA_H ${HAVE_OPENSSL_RSA_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_OPENSSL_SSL_H ${HAVE_OPENSSL_SSL_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_OPENSSL_X509_H ${HAVE_OPENSSL_X509_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_PEM_H ${HAVE_PEM_H} - -/* Define to 1 if you have the `perror' function. */ -#cmakedefine HAVE_PERROR ${HAVE_PERROR} - -/* Define to 1 if you have the `pipe' function. */ -#cmakedefine HAVE_PIPE ${HAVE_PIPE} - -/* if you have the function PK11_CreateGenericObject */ -#cmakedefine HAVE_PK11_CREATEGENERICOBJECT ${HAVE_PK11_CREATEGENERICOBJECT} - -/* Define to 1 if you have a working poll function. */ -#cmakedefine HAVE_POLL ${HAVE_POLL} - -/* If you have a fine poll */ -#cmakedefine HAVE_POLL_FINE ${HAVE_POLL_FINE} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_POLL_H ${HAVE_POLL_H} - -/* Define to 1 if you have a working POSIX-style strerror_r function. */ -#cmakedefine HAVE_POSIX_STRERROR_R ${HAVE_POSIX_STRERROR_R} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_PWD_H ${HAVE_PWD_H} - -/* Define to 1 if you have the `RAND_egd' function. */ -#cmakedefine HAVE_RAND_EGD ${HAVE_RAND_EGD} - -/* Define to 1 if you have the `RAND_screen' function. */ -#cmakedefine HAVE_RAND_SCREEN ${HAVE_RAND_SCREEN} - -/* Define to 1 if you have the `RAND_status' function. */ -#cmakedefine HAVE_RAND_STATUS ${HAVE_RAND_STATUS} - -/* Define to 1 if you have the recv function. */ -#cmakedefine HAVE_RECV ${HAVE_RECV} - -/* Define to 1 if you have the recvfrom function. */ -#cmakedefine HAVE_RECVFROM ${HAVE_RECVFROM} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_RSA_H ${HAVE_RSA_H} - -/* Define to 1 if you have the select function. */ -#cmakedefine HAVE_SELECT ${HAVE_SELECT} - -/* Define to 1 if you have the send function. */ -#cmakedefine HAVE_SEND ${HAVE_SEND} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SETJMP_H ${HAVE_SETJMP_H} - -/* Define to 1 if you have the `setlocale' function. */ -#cmakedefine HAVE_SETLOCALE ${HAVE_SETLOCALE} - -/* Define to 1 if you have the `setmode' function. */ -#cmakedefine HAVE_SETMODE ${HAVE_SETMODE} - -/* Define to 1 if you have the `setrlimit' function. */ -#cmakedefine HAVE_SETRLIMIT ${HAVE_SETRLIMIT} - -/* Define to 1 if you have the setsockopt function. */ -#cmakedefine HAVE_SETSOCKOPT ${HAVE_SETSOCKOPT} - -/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ -#cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK ${HAVE_SETSOCKOPT_SO_NONBLOCK} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SGTTY_H ${HAVE_SGTTY_H} - -/* Define to 1 if you have the sigaction function. */ -#cmakedefine HAVE_SIGACTION ${HAVE_SIGACTION} - -/* Define to 1 if you have the siginterrupt function. */ -#cmakedefine HAVE_SIGINTERRUPT ${HAVE_SIGINTERRUPT} - -/* Define to 1 if you have the signal function. */ -#cmakedefine HAVE_SIGNAL ${HAVE_SIGNAL} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SIGNAL_H ${HAVE_SIGNAL_H} - -/* Define to 1 if you have the sigsetjmp function or macro. */ -#cmakedefine HAVE_SIGSETJMP ${HAVE_SIGSETJMP} - -/* Define to 1 if sig_atomic_t is an available typedef. */ -#cmakedefine HAVE_SIG_ATOMIC_T ${HAVE_SIG_ATOMIC_T} - -/* Define to 1 if sig_atomic_t is already defined as volatile. */ -#cmakedefine HAVE_SIG_ATOMIC_T_VOLATILE ${HAVE_SIG_ATOMIC_T_VOLATILE} - -/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ -#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID ${HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID} - -/* Define to 1 if you have the `socket' function. */ -#cmakedefine HAVE_SOCKET ${HAVE_SOCKET} - -/* Define this if you have the SPNEGO library fbopenssl */ -#cmakedefine HAVE_SPNEGO ${HAVE_SPNEGO} - -/* Define to 1 if you have the `SSL_get_shutdown' function. */ -#cmakedefine HAVE_SSL_GET_SHUTDOWN ${HAVE_SSL_GET_SHUTDOWN} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SSL_H ${HAVE_SSL_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STDBOOL_H ${HAVE_STDBOOL_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STDIO_H ${HAVE_STDIO_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H} - -/* Define to 1 if you have the strcasecmp function. */ -#cmakedefine HAVE_STRCASECMP ${HAVE_STRCASECMP} - -/* Define to 1 if you have the strcasestr function. */ -#cmakedefine HAVE_STRCASESTR ${HAVE_STRCASESTR} - -/* Define to 1 if you have the strcmpi function. */ -#cmakedefine HAVE_STRCMPI ${HAVE_STRCMPI} - -/* Define to 1 if you have the strdup function. */ -#cmakedefine HAVE_STRDUP ${HAVE_STRDUP} - -/* Define to 1 if you have the strerror_r function. */ -#cmakedefine HAVE_STRERROR_R ${HAVE_STRERROR_R} - -/* Define to 1 if you have the stricmp function. */ -#cmakedefine HAVE_STRICMP ${HAVE_STRICMP} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STRINGS_H ${HAVE_STRINGS_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STRING_H ${HAVE_STRING_H} - -/* Define to 1 if you have the strlcat function. */ -#cmakedefine HAVE_STRLCAT ${HAVE_STRLCAT} - -/* Define to 1 if you have the `strlcpy' function. */ -#cmakedefine HAVE_STRLCPY ${HAVE_STRLCPY} - -/* Define to 1 if you have the strncasecmp function. */ -#cmakedefine HAVE_STRNCASECMP ${HAVE_STRNCASECMP} - -/* Define to 1 if you have the strncmpi function. */ -#cmakedefine HAVE_STRNCMPI ${HAVE_STRNCMPI} - -/* Define to 1 if you have the strnicmp function. */ -#cmakedefine HAVE_STRNICMP ${HAVE_STRNICMP} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STROPTS_H ${HAVE_STROPTS_H} - -/* Define to 1 if you have the strstr function. */ -#cmakedefine HAVE_STRSTR ${HAVE_STRSTR} - -/* Define to 1 if you have the strtok_r function. */ -#cmakedefine HAVE_STRTOK_R ${HAVE_STRTOK_R} - -/* Define to 1 if you have the strtoll function. */ -#cmakedefine HAVE_STRTOLL ${HAVE_STRTOLL} - -/* if struct sockaddr_storage is defined */ -#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE ${HAVE_STRUCT_SOCKADDR_STORAGE} - -/* Define to 1 if you have the timeval struct. */ -#cmakedefine HAVE_STRUCT_TIMEVAL ${HAVE_STRUCT_TIMEVAL} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_FILIO_H ${HAVE_SYS_FILIO_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_IOCTL_H ${HAVE_SYS_IOCTL_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_PARAM_H ${HAVE_SYS_PARAM_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_POLL_H ${HAVE_SYS_POLL_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_RESOURCE_H ${HAVE_SYS_RESOURCE_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_SELECT_H ${HAVE_SYS_SELECT_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_SOCKIO_H ${HAVE_SYS_SOCKIO_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_STAT_H ${HAVE_SYS_STAT_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_TIME_H ${HAVE_SYS_TIME_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_UIO_H ${HAVE_SYS_UIO_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_UN_H ${HAVE_SYS_UN_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_UTIME_H ${HAVE_SYS_UTIME_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_TERMIO_H ${HAVE_TERMIO_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_TIME_H ${HAVE_TIME_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_TLD_H ${HAVE_TLD_H} - -/* Define to 1 if you have the `tld_strerror' function. */ -#cmakedefine HAVE_TLD_STRERROR ${HAVE_TLD_STRERROR} - -/* Define to 1 if you have the `uname' function. */ -#cmakedefine HAVE_UNAME ${HAVE_UNAME} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H} - -/* Define to 1 if you have the `utime' function. */ -#cmakedefine HAVE_UTIME ${HAVE_UTIME} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_UTIME_H ${HAVE_UTIME_H} - -/* Define to 1 if compiler supports C99 variadic macro style. */ -#cmakedefine HAVE_VARIADIC_MACROS_C99 ${HAVE_VARIADIC_MACROS_C99} - -/* Define to 1 if compiler supports old gcc variadic macro style. */ -#cmakedefine HAVE_VARIADIC_MACROS_GCC ${HAVE_VARIADIC_MACROS_GCC} - -/* Define to 1 if you have the winber.h header file. */ -#cmakedefine HAVE_WINBER_H ${HAVE_WINBER_H} - -/* Define to 1 if you have the windows.h header file. */ -#cmakedefine HAVE_WINDOWS_H ${HAVE_WINDOWS_H} - -/* Define to 1 if you have the winldap.h header file. */ -#cmakedefine HAVE_WINLDAP_H ${HAVE_WINLDAP_H} - -/* Define to 1 if you have the winsock2.h header file. */ -#cmakedefine HAVE_WINSOCK2_H ${HAVE_WINSOCK2_H} - -/* Define to 1 if you have the winsock.h header file. */ -#cmakedefine HAVE_WINSOCK_H ${HAVE_WINSOCK_H} - -/* Define this symbol if your OS supports changing the contents of argv */ -#cmakedefine HAVE_WRITABLE_ARGV ${HAVE_WRITABLE_ARGV} - -/* Define to 1 if you have the writev function. */ -#cmakedefine HAVE_WRITEV ${HAVE_WRITEV} - -/* Define to 1 if you have the ws2tcpip.h header file. */ -#cmakedefine HAVE_WS2TCPIP_H ${HAVE_WS2TCPIP_H} - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_X509_H ${HAVE_X509_H} - -/* Define if you have the header file. */ -#cmakedefine HAVE_PROCESS_H ${HAVE_PROCESS_H} - -/* if you have the zlib.h header file */ -#cmakedefine HAVE_ZLIB_H ${HAVE_ZLIB_H} - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#cmakedefine LT_OBJDIR ${LT_OBJDIR} - -/* Define to 1 if you are building a native Windows target. */ -#cmakedefine NATIVE_WINDOWS ${NATIVE_WINDOWS} - -/* If you lack a fine basename() prototype */ -#cmakedefine NEED_BASENAME_PROTO ${NEED_BASENAME_PROTO} - -/* Define to 1 if you need the lber.h header file even with ldap.h */ -#cmakedefine NEED_LBER_H ${NEED_LBER_H} - -/* Define to 1 if you need the malloc.h header file even with stdlib.h */ -#cmakedefine NEED_MALLOC_H ${NEED_MALLOC_H} - -/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ -#cmakedefine NEED_REENTRANT ${NEED_REENTRANT} - -/* 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 ${RECVFROM_TYPE_ARG2_IS_VOID} - -/* 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 ${RECVFROM_TYPE_ARG5_IS_VOID} - -/* 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 ${RECVFROM_TYPE_ARG6_IS_VOID} - -/* 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. */ -#cmakedefine SIZEOF_INT ${SIZEOF_INT} - -/* The size of `short', as computed by sizeof. */ -#cmakedefine SIZEOF_SHORT ${SIZEOF_SHORT} - -/* The size of `long', as computed by sizeof. */ -#cmakedefine SIZEOF_LONG ${SIZEOF_LONG} - -/* The size of `off_t', as computed by sizeof. */ -#cmakedefine SIZEOF_OFF_T ${SIZEOF_OFF_T} - -/* The size of `size_t', as computed by sizeof. */ -#cmakedefine SIZEOF_SIZE_T ${SIZEOF_SIZE_T} - -/* The size of `time_t', as computed by sizeof. */ -#cmakedefine SIZEOF_TIME_T ${SIZEOF_TIME_T} - -/* The size of `void*', as computed by sizeof. */ -#cmakedefine SIZEOF_VOIDP ${SIZEOF_VOIDP} - -/* Define to 1 if you have the ANSI C header files. */ -#cmakedefine STDC_HEADERS ${STDC_HEADERS} - -/* 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 and . */ -#cmakedefine TIME_WITH_SYS_TIME ${TIME_WITH_SYS_TIME} - -/* Define if you want to enable c-ares support */ -#cmakedefine USE_ARES ${USE_ARES} - -/* Define to disable non-blocking sockets. */ -#cmakedefine USE_BLOCKING_SOCKETS ${USE_BLOCKING_SOCKETS} - -/* if GnuTLS is enabled */ -#cmakedefine USE_GNUTLS ${USE_GNUTLS} - -/* if PolarSSL is enabled */ -#cmakedefine USE_POLARSSL ${USE_POLARSSL} - -/* if libSSH2 is in use */ -#cmakedefine USE_LIBSSH2 ${USE_LIBSSH2} - -/* If you want to build curl with the built-in manual */ -#cmakedefine USE_MANUAL ${USE_MANUAL} - -/* if NSS is enabled */ -#cmakedefine USE_NSS ${USE_NSS} - -/* if OpenSSL is in use */ -#cmakedefine USE_OPENSSL ${USE_OPENSSL} - -/* if SSL is enabled */ -#cmakedefine USE_SSLEAY ${USE_SSLEAY} - -/* Define to 1 if you are building a Windows target without large file - support. */ -#cmakedefine USE_WIN32_LARGE_FILES ${USE_WIN32_LARGE_FILES} - -/* to enable SSPI support */ -#cmakedefine USE_WINDOWS_SSPI ${USE_WINDOWS_SSPI} - -/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ -#cmakedefine USE_YASSLEMUL ${USE_YASSLEMUL} - -/* Version number of package */ -#cmakedefine VERSION ${VERSION} - -/* Define to avoid automatic inclusion of winsock.h */ -#cmakedefine WIN32_LEAN_AND_MEAN ${WIN32_LEAN_AND_MEAN} - -/* Define to 1 if OS is AIX. */ -#ifndef _ALL_SOURCE -# undef _ALL_SOURCE -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -#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 does not define. */ -#cmakedefine size_t ${size_t} - -/* the signed version of size_t */ -#cmakedefine ssize_t ${ssize_t} diff --git a/third_party/curl/lib/curl_fnmatch.c b/third_party/curl/lib/curl_fnmatch.c deleted file mode 100644 index ad4ec1871..000000000 --- a/third_party/curl/lib/curl_fnmatch.c +++ /dev/null @@ -1,424 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include "curl_fnmatch.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -#define CURLFNM_CHARSET_LEN (sizeof(char) * 256) -#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15) - -#define CURLFNM_NEGATE CURLFNM_CHARSET_LEN - -#define CURLFNM_ALNUM (CURLFNM_CHARSET_LEN + 1) -#define CURLFNM_DIGIT (CURLFNM_CHARSET_LEN + 2) -#define CURLFNM_XDIGIT (CURLFNM_CHARSET_LEN + 3) -#define CURLFNM_ALPHA (CURLFNM_CHARSET_LEN + 4) -#define CURLFNM_PRINT (CURLFNM_CHARSET_LEN + 5) -#define CURLFNM_BLANK (CURLFNM_CHARSET_LEN + 6) -#define CURLFNM_LOWER (CURLFNM_CHARSET_LEN + 7) -#define CURLFNM_GRAPH (CURLFNM_CHARSET_LEN + 8) -#define CURLFNM_SPACE (CURLFNM_CHARSET_LEN + 9) -#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10) - -typedef enum { - CURLFNM_LOOP_DEFAULT = 0, - CURLFNM_LOOP_BACKSLASH -} loop_state; - -typedef enum { - CURLFNM_SCHS_DEFAULT = 0, - CURLFNM_SCHS_MAYRANGE, - CURLFNM_SCHS_MAYRANGE2, - CURLFNM_SCHS_RIGHTBR, - CURLFNM_SCHS_RIGHTBRLEFTBR -} setcharset_state; - -typedef enum { - CURLFNM_PKW_INIT = 0, - CURLFNM_PKW_DDOT -} parsekey_state; - -#define SETCHARSET_OK 1 -#define SETCHARSET_FAIL 0 - -static int parsekeyword(unsigned char **pattern, unsigned char *charset) -{ - parsekey_state state = CURLFNM_PKW_INIT; -#define KEYLEN 10 - char keyword[KEYLEN] = { 0 }; - int found = FALSE; - int i; - unsigned char *p = *pattern; - for(i = 0; !found; i++) { - char c = *p++; - if(i >= KEYLEN) - return SETCHARSET_FAIL; - switch(state) { - case CURLFNM_PKW_INIT: - if(ISALPHA(c) && ISLOWER(c)) - keyword[i] = c; - else if(c == ':') - state = CURLFNM_PKW_DDOT; - else - return 0; - break; - case CURLFNM_PKW_DDOT: - if(c == ']') - found = TRUE; - else - return SETCHARSET_FAIL; - } - } -#undef KEYLEN - - *pattern = p; /* move caller's pattern pointer */ - if(strcmp(keyword, "digit") == 0) - charset[CURLFNM_DIGIT] = 1; - else if(strcmp(keyword, "alnum") == 0) - charset[CURLFNM_ALNUM] = 1; - else if(strcmp(keyword, "alpha") == 0) - charset[CURLFNM_ALPHA] = 1; - else if(strcmp(keyword, "xdigit") == 0) - charset[CURLFNM_XDIGIT] = 1; - else if(strcmp(keyword, "print") == 0) - charset[CURLFNM_PRINT] = 1; - else if(strcmp(keyword, "graph") == 0) - charset[CURLFNM_GRAPH] = 1; - else if(strcmp(keyword, "space") == 0) - charset[CURLFNM_SPACE] = 1; - else if(strcmp(keyword, "blank") == 0) - charset[CURLFNM_BLANK] = 1; - else if(strcmp(keyword, "upper") == 0) - charset[CURLFNM_UPPER] = 1; - else if(strcmp(keyword, "lower") == 0) - charset[CURLFNM_LOWER] = 1; - else - return SETCHARSET_FAIL; - return SETCHARSET_OK; -} - -/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */ -static int setcharset(unsigned char **p, unsigned char *charset) -{ - setcharset_state state = CURLFNM_SCHS_DEFAULT; - unsigned char rangestart = 0; - unsigned char lastchar = 0; - bool something_found = FALSE; - unsigned char c; - for(;;) { - c = **p; - switch(state) { - case CURLFNM_SCHS_DEFAULT: - if(ISALNUM(c)) { /* ASCII value */ - rangestart = c; - charset[c] = 1; - (*p)++; - state = CURLFNM_SCHS_MAYRANGE; - something_found = TRUE; - } - else if(c == ']') { - if(something_found) - return SETCHARSET_OK; - else - something_found = TRUE; - state = CURLFNM_SCHS_RIGHTBR; - charset[c] = 1; - (*p)++; - } - else if(c == '[') { - char c2 = *((*p)+1); - if(c2 == ':') { /* there has to be a keyword */ - (*p) += 2; - if(parsekeyword(p, charset)) { - state = CURLFNM_SCHS_DEFAULT; - } - else - return SETCHARSET_FAIL; - } - else { - charset[c] = 1; - (*p)++; - } - something_found = TRUE; - } - else if(c == '?' || c == '*') { - something_found = TRUE; - charset[c] = 1; - (*p)++; - } - else if(c == '^' || c == '!') { - if(!something_found) { - if(charset[CURLFNM_NEGATE]) { - charset[c] = 1; - something_found = TRUE; - } - else - charset[CURLFNM_NEGATE] = 1; /* negate charset */ - } - else - charset[c] = 1; - (*p)++; - } - else if(c == '\\') { - c = *(++(*p)); - if(ISPRINT((c))) { - something_found = TRUE; - state = CURLFNM_SCHS_MAYRANGE; - charset[c] = 1; - rangestart = c; - (*p)++; - } - else - return SETCHARSET_FAIL; - } - else if(c == '\0') { - return SETCHARSET_FAIL; - } - else { - charset[c] = 1; - (*p)++; - something_found = TRUE; - } - break; - case CURLFNM_SCHS_MAYRANGE: - if(c == '-') { - charset[c] = 1; - (*p)++; - lastchar = '-'; - state = CURLFNM_SCHS_MAYRANGE2; - } - else if(c == '[') { - state = CURLFNM_SCHS_DEFAULT; - } - else if(ISALNUM(c)) { - charset[c] = 1; - (*p)++; - } - else if(c == '\\') { - c = *(++(*p)); - if(ISPRINT(c)) { - charset[c] = 1; - (*p)++; - } - else - return SETCHARSET_FAIL; - } - else if(c == ']') { - return SETCHARSET_OK; - } - else - return SETCHARSET_FAIL; - break; - case CURLFNM_SCHS_MAYRANGE2: - if(c == '\\') { - c = *(++(*p)); - if(!ISPRINT(c)) - return SETCHARSET_FAIL; - } - if(c == ']') { - return SETCHARSET_OK; - } - else if(c == '\\') { - c = *(++(*p)); - if(ISPRINT(c)) { - charset[c] = 1; - state = CURLFNM_SCHS_DEFAULT; - (*p)++; - } - else - return SETCHARSET_FAIL; - } - if(c >= rangestart) { - if((ISLOWER(c) && ISLOWER(rangestart)) || - (ISDIGIT(c) && ISDIGIT(rangestart)) || - (ISUPPER(c) && ISUPPER(rangestart))) { - charset[lastchar] = 0; - rangestart++; - while(rangestart++ <= c) - charset[rangestart-1] = 1; - (*p)++; - state = CURLFNM_SCHS_DEFAULT; - } - else - return SETCHARSET_FAIL; - } - break; - case CURLFNM_SCHS_RIGHTBR: - if(c == '[') { - state = CURLFNM_SCHS_RIGHTBRLEFTBR; - charset[c] = 1; - (*p)++; - } - else if(c == ']') { - return SETCHARSET_OK; - } - else if(c == '\0') { - return SETCHARSET_FAIL; - } - else if(ISPRINT(c)) { - charset[c] = 1; - (*p)++; - state = CURLFNM_SCHS_DEFAULT; - } - else - /* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a - * nonsense warning 'statement not reached' at end of the fnc when - * compiling on Solaris */ - goto fail; - break; - case CURLFNM_SCHS_RIGHTBRLEFTBR: - if(c == ']') { - return SETCHARSET_OK; - } - else { - state = CURLFNM_SCHS_DEFAULT; - charset[c] = 1; - (*p)++; - } - break; - } - } -fail: - return SETCHARSET_FAIL; -} - -static int loop(const unsigned char *pattern, const unsigned char *string) -{ - loop_state state = CURLFNM_LOOP_DEFAULT; - unsigned char *p = (unsigned char *)pattern; - unsigned char *s = (unsigned char *)string; - unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 }; - int rc = 0; - - for (;;) { - switch(state) { - case CURLFNM_LOOP_DEFAULT: - if(*p == '*') { - while(*(p+1) == '*') /* eliminate multiple stars */ - p++; - if(*s == '\0' && *(p+1) == '\0') - return CURL_FNMATCH_MATCH; - rc = loop(p + 1, s); /* *.txt matches .txt <=> .txt matches .txt */ - if(rc == CURL_FNMATCH_MATCH) - return CURL_FNMATCH_MATCH; - if(*s) /* let the star eat up one character */ - s++; - else - return CURL_FNMATCH_NOMATCH; - } - else if(*p == '?') { - if(ISPRINT(*s)) { - s++; - p++; - } - else if(*s == '\0') - return CURL_FNMATCH_NOMATCH; - else - return CURL_FNMATCH_FAIL; /* cannot deal with other character */ - } - else if(*p == '\0') { - if(*s == '\0') - return CURL_FNMATCH_MATCH; - else - return CURL_FNMATCH_NOMATCH; - } - else if(*p == '\\') { - state = CURLFNM_LOOP_BACKSLASH; - p++; - } - else if(*p == '[') { - unsigned char *pp = p+1; /* cannot handle with pointer to register */ - if(setcharset(&pp, charset)) { - int found = FALSE; - if(charset[(unsigned int)*s]) - found = TRUE; - else if(charset[CURLFNM_ALNUM]) - found = ISALNUM(*s); - else if(charset[CURLFNM_ALPHA]) - found = ISALPHA(*s); - else if(charset[CURLFNM_DIGIT]) - found = ISDIGIT(*s); - else if(charset[CURLFNM_XDIGIT]) - found = ISXDIGIT(*s); - else if(charset[CURLFNM_PRINT]) - found = ISPRINT(*s); - else if(charset[CURLFNM_SPACE]) - found = ISSPACE(*s); - else if(charset[CURLFNM_UPPER]) - found = ISUPPER(*s); - else if(charset[CURLFNM_LOWER]) - found = ISLOWER(*s); - else if(charset[CURLFNM_BLANK]) - found = ISBLANK(*s); - else if(charset[CURLFNM_GRAPH]) - found = ISGRAPH(*s); - - if(charset[CURLFNM_NEGATE]) - found = !found; - - if(found) { - p = pp+1; - s++; - memset(charset, 0, CURLFNM_CHSET_SIZE); - } - else - return CURL_FNMATCH_NOMATCH; - } - else - return CURL_FNMATCH_FAIL; - } - else { - if(*p++ != *s++) - return CURL_FNMATCH_NOMATCH; - } - break; - case CURLFNM_LOOP_BACKSLASH: - if(ISPRINT(*p)) { - if(*p++ == *s++) - state = CURLFNM_LOOP_DEFAULT; - else - return CURL_FNMATCH_NOMATCH; - } - else - return CURL_FNMATCH_FAIL; - break; - } - } -} - -int Curl_fnmatch(void *ptr, const char *pattern, const char *string) -{ - (void)ptr; /* the argument is specified by the curl_fnmatch_callback - prototype, but not used by Curl_fnmatch() */ - if(!pattern || !string) { - return CURL_FNMATCH_FAIL; - } - return loop((unsigned char *)pattern, (unsigned char *)string); -} diff --git a/third_party/curl/lib/curl_fnmatch.h b/third_party/curl/lib/curl_fnmatch.h deleted file mode 100644 index 6335d0312..000000000 --- a/third_party/curl/lib/curl_fnmatch.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef HEADER_CURL_FNMATCH_H -#define HEADER_CURL_FNMATCH_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#define CURL_FNMATCH_MATCH 0 -#define CURL_FNMATCH_NOMATCH 1 -#define CURL_FNMATCH_FAIL 2 - -/* default pattern matching function - * ================================= - * Implemented with recursive backtracking, if you want to use Curl_fnmatch, - * please note that there is not implemented UTF/UNICODE support. - * - * Implemented features: - * '?' notation, does not match UTF characters - * '*' can also work with UTF string - * [a-zA-Z0-9] enumeration support - * - * keywords: alnum, digit, xdigit, alpha, print, blank, lower, graph, space - * and upper (use as "[[:alnum:]]") - */ -int Curl_fnmatch(void *ptr, const char *pattern, const char *string); - -#endif /* HEADER_CURL_FNMATCH_H */ diff --git a/third_party/curl/lib/curl_gethostname.c b/third_party/curl/lib/curl_gethostname.c deleted file mode 100644 index 7f0bfed54..000000000 --- a/third_party/curl/lib/curl_gethostname.c +++ /dev/null @@ -1,81 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_UNISTD_H -# include -#endif - -#include "curl_gethostname.h" - -/* - * Curl_gethostname() is a wrapper around gethostname() which allows - * overriding the host name that the function would normally return. - * This capability is used by the test suite to verify exact matching - * of NTLM authentication, which exercises libcurl's MD4 and DES code. - * - * For libcurl debug enabled builds host name overriding takes place - * when environment variable CURL_GETHOSTNAME is set, using the value - * held by the variable to override returned host name. - * - * For libcurl shared library release builds the test suite preloads - * another shared library named libhostname using the LD_PRELOAD - * mechanism which intercepts, and might override, the gethostname() - * function call. In this case a given platform must support the - * LD_PRELOAD mechanism and additionally have environment variable - * CURL_GETHOSTNAME set in order to override the returned host name. - * - * For libcurl static library release builds no overriding takes place. - */ - -int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) { - -#ifndef HAVE_GETHOSTNAME - - /* Allow compilation and return failure when unavailable */ - (void) name; - (void) namelen; - return -1; - -#else - -#ifdef DEBUGBUILD - - /* Override host name when environment variable CURL_GETHOSTNAME is set */ - const char *force_hostname = getenv("CURL_GETHOSTNAME"); - if(force_hostname) { - strncpy(name, force_hostname, namelen); - name[namelen-1] = '\0'; - return 0; - } - -#endif /* DEBUGBUILD */ - - /* The call to system's gethostname() might get intercepted by the - libhostname library when libcurl is built as a non-debug shared - library when running the test suite. */ - return gethostname(name, namelen); - -#endif - -} diff --git a/third_party/curl/lib/curl_gethostname.h b/third_party/curl/lib/curl_gethostname.h deleted file mode 100644 index b8ecf88d6..000000000 --- a/third_party/curl/lib/curl_gethostname.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef HEADER_CURL_GETHOSTNAME_H -#define HEADER_CURL_GETHOSTNAME_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen); - -#endif /* HEADER_CURL_GETHOSTNAME_H */ diff --git a/third_party/curl/lib/curl_hmac.h b/third_party/curl/lib/curl_hmac.h deleted file mode 100644 index 9b65c8c2a..000000000 --- a/third_party/curl/lib/curl_hmac.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef HEADER_CURL_HMAC_H -#define HEADER_CURL_HMAC_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifndef CURL_DISABLE_CRYPTO_AUTH - -typedef void (* HMAC_hinit_func)(void * context); -typedef void (* HMAC_hupdate_func)(void * context, - const unsigned char * data, - unsigned int len); -typedef void (* HMAC_hfinal_func)(unsigned char * result, void * context); - - -/* Per-hash function HMAC parameters. */ - -typedef struct { - HMAC_hinit_func hmac_hinit; /* Initialize context procedure. */ - HMAC_hupdate_func hmac_hupdate; /* Update context with data. */ - HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */ - unsigned int hmac_ctxtsize; /* Context structure size. */ - unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */ - unsigned int hmac_resultlen; /* Result length (bytes). */ -} HMAC_params; - - -/* HMAC computation context. */ - -typedef struct { - const HMAC_params * hmac_hash; /* Hash function definition. */ - void * hmac_hashctxt1; /* Hash function context 1. */ - void * hmac_hashctxt2; /* Hash function context 2. */ -} HMAC_context; - - -/* Prototypes. */ - -HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams, - const unsigned char * key, - unsigned int keylen); -int Curl_HMAC_update(HMAC_context * context, - const unsigned char * data, - unsigned int len); -int Curl_HMAC_final(HMAC_context * context, unsigned char * result); - -#endif - -#endif /* HEADER_CURL_HMAC_H */ diff --git a/third_party/curl/lib/curl_ldap.h b/third_party/curl/lib/curl_ldap.h deleted file mode 100644 index 4cd13cfd2..000000000 --- a/third_party/curl/lib/curl_ldap.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __CURL_LDAP_H -#define __CURL_LDAP_H - -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#ifndef CURL_DISABLE_LDAP -extern const struct Curl_handler Curl_handler_ldap; - -#if !defined(CURL_DISABLE_LDAPS) && \ - ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ - (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) -extern const struct Curl_handler Curl_handler_ldaps; -#endif - -#endif -#endif /* __CURL_LDAP_H */ diff --git a/third_party/curl/lib/curl_md4.h b/third_party/curl/lib/curl_md4.h deleted file mode 100644 index 6b6c16e13..000000000 --- a/third_party/curl/lib/curl_md4.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef HEADER_CURL_MD4_H -#define HEADER_CURL_MD4_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -/* NSS crypto library does not provide the MD4 hash algorithm, so that we have - * a local implementation of it */ -#ifdef USE_NSS -void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len); -#endif /* USE_NSS */ - -#endif /* HEADER_CURL_MD4_H */ diff --git a/third_party/curl/lib/curl_md5.h b/third_party/curl/lib/curl_md5.h deleted file mode 100644 index ddc61e3e5..000000000 --- a/third_party/curl/lib/curl_md5.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef HEADER_CURL_MD5_H -#define HEADER_CURL_MD5_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifndef CURL_DISABLE_CRYPTO_AUTH -#include "curl_hmac.h" - -extern const HMAC_params Curl_HMAC_MD5[1]; - -void Curl_md5it(unsigned char *output, - const unsigned char *input); -#endif - -#endif /* HEADER_CURL_MD5_H */ diff --git a/third_party/curl/lib/curl_memory.h b/third_party/curl/lib/curl_memory.h deleted file mode 100644 index e11945823..000000000 --- a/third_party/curl/lib/curl_memory.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef HEADER_CURL_MEMORY_H -#define HEADER_CURL_MEMORY_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 /* for the typedefs */ - -extern curl_malloc_callback Curl_cmalloc; -extern curl_free_callback Curl_cfree; -extern curl_realloc_callback Curl_crealloc; -extern curl_strdup_callback Curl_cstrdup; -extern curl_calloc_callback Curl_ccalloc; - -#ifndef CURLDEBUG -/* Only do this define-mania if we're not using the memdebug system, as that - has preference on this magic. */ -#undef strdup -#define strdup(ptr) Curl_cstrdup(ptr) -#undef malloc -#define malloc(size) Curl_cmalloc(size) -#undef calloc -#define calloc(nbelem,size) Curl_ccalloc(nbelem, size) -#undef realloc -#define realloc(ptr,size) Curl_crealloc(ptr, size) -#undef free -#define free(ptr) Curl_cfree(ptr) - -#endif - -#endif /* HEADER_CURL_MEMORY_H */ diff --git a/third_party/curl/lib/curl_memrchr.c b/third_party/curl/lib/curl_memrchr.c deleted file mode 100644 index a1e2bf0e5..000000000 --- a/third_party/curl/lib/curl_memrchr.c +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include "curl_memrchr.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -#ifndef HAVE_MEMRCHR - -/* - * Curl_memrchr() - * - * Our memrchr() function clone for systems which lack this function. The - * memrchr() function is like the memchr() function, except that it searches - * backwards from the end of the n bytes pointed to by s instead of forward - * from the beginning. - */ - -void * -Curl_memrchr(const void *s, int c, size_t n) -{ - const unsigned char *p = s; - const unsigned char *q = s; - - p += n - 1; - - while (p >= q) { - if (*p == (unsigned char)c) - return (void *)p; - p--; - } - - return NULL; -} - -#endif /* HAVE_MEMRCHR */ diff --git a/third_party/curl/lib/curl_memrchr.h b/third_party/curl/lib/curl_memrchr.h deleted file mode 100644 index 37061b608..000000000 --- a/third_party/curl/lib/curl_memrchr.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef HEADER_CURL_MEMRCHR_H -#define HEADER_CURL_MEMRCHR_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_MEMRCHR - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#else /* HAVE_MEMRCHR */ - -void *Curl_memrchr(const void *s, int c, size_t n); - -#define memrchr(x,y,z) Curl_memrchr((x),(y),(z)) - -#endif /* HAVE_MEMRCHR */ - -#endif /* HEADER_CURL_MEMRCHR_H */ diff --git a/third_party/curl/lib/curl_rand.c b/third_party/curl/lib/curl_rand.c deleted file mode 100644 index b374889aa..000000000 --- a/third_party/curl/lib/curl_rand.c +++ /dev/null @@ -1,60 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include - -#include "curl_rand.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* Private pseudo-random number seed. Unsigned integer >= 32bit. Threads - mutual exclusion is not implemented to acess it since we do not require - high quality random numbers (only used in form boudary generation). */ - -static unsigned int randseed; - -/* Pseudo-random number support. */ - -unsigned int Curl_rand(void) -{ - unsigned int r; - /* Return an unsigned 32-bit pseudo-random number. */ - r = randseed = randseed * 1103515245 + 12345; - return (r << 16) | ((r >> 16) & 0xFFFF); -} - -void Curl_srand(void) -{ - /* Randomize pseudo-random number sequence. */ - - randseed = (unsigned int) time(NULL); - Curl_rand(); - Curl_rand(); - Curl_rand(); -} diff --git a/third_party/curl/lib/curl_rand.h b/third_party/curl/lib/curl_rand.h deleted file mode 100644 index 26cfb7f03..000000000 --- a/third_party/curl/lib/curl_rand.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef HEADER_CURL_RAND_H -#define HEADER_CURL_RAND_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -void Curl_srand(void); - -unsigned int Curl_rand(void); - -#endif /* HEADER_CURL_RAND_H */ diff --git a/third_party/curl/lib/curl_rtmp.c b/third_party/curl/lib/curl_rtmp.c deleted file mode 100644 index bae8a76c0..000000000 --- a/third_party/curl/lib/curl_rtmp.c +++ /dev/null @@ -1,292 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, Howard Chu, - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef USE_LIBRTMP - -#include "urldata.h" -#include "nonblock.h" /* for curlx_nonblock */ -#include "progress.h" /* for Curl_pgrsSetUploadSize */ -#include "transfer.h" -#include -#include - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -#ifdef _WIN32 -#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e) -#define SET_RCVTIMEO(tv,s) int tv = s*1000 -#else -#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0} -#endif - -#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */ - -static CURLcode rtmp_setup(struct connectdata *conn); -static CURLcode rtmp_do(struct connectdata *conn, bool *done); -static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature); -static CURLcode rtmp_connect(struct connectdata *conn, bool *done); -static CURLcode rtmp_disconnect(struct connectdata *conn, bool dead_connection); - -static Curl_recv rtmp_recv; -static Curl_send rtmp_send; - -/* - * RTMP protocol handler.h, based on http://rtmpdump.mplayerhq.hu - */ - -const struct Curl_handler Curl_handler_rtmp = { - "RTMP", /* scheme */ - rtmp_setup, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - rtmp_disconnect, /* disconnect */ - PORT_RTMP, /* defport */ - CURLPROTO_RTMP, /* protocol */ - PROTOPT_NONE /* flags*/ -}; - -const struct Curl_handler Curl_handler_rtmpt = { - "RTMPT", /* scheme */ - rtmp_setup, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - rtmp_disconnect, /* disconnect */ - PORT_RTMPT, /* defport */ - CURLPROTO_RTMPT, /* protocol */ - PROTOPT_NONE /* flags*/ -}; - -const struct Curl_handler Curl_handler_rtmpe = { - "RTMPE", /* scheme */ - rtmp_setup, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - rtmp_disconnect, /* disconnect */ - PORT_RTMP, /* defport */ - CURLPROTO_RTMPE, /* protocol */ - PROTOPT_NONE /* flags*/ -}; - -const struct Curl_handler Curl_handler_rtmpte = { - "RTMPTE", /* scheme */ - rtmp_setup, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - rtmp_disconnect, /* disconnect */ - PORT_RTMPT, /* defport */ - CURLPROTO_RTMPTE, /* protocol */ - PROTOPT_NONE /* flags*/ -}; - -const struct Curl_handler Curl_handler_rtmps = { - "RTMPS", /* scheme */ - rtmp_setup, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - rtmp_disconnect, /* disconnect */ - PORT_RTMPS, /* defport */ - CURLPROTO_RTMPS, /* protocol */ - PROTOPT_NONE /* flags*/ -}; -const struct Curl_handler Curl_handler_rtmpts = { - "RTMPTS", /* scheme */ - rtmp_setup, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - rtmp_disconnect, /* disconnect */ - PORT_RTMPS, /* defport */ - CURLPROTO_RTMPTS, /* protocol */ - PROTOPT_NONE /* flags*/ -}; - -static CURLcode rtmp_setup(struct connectdata *conn) -{ - RTMP *r = RTMP_Alloc(); - - if (!r) - return CURLE_OUT_OF_MEMORY; - - RTMP_Init(r); - RTMP_SetBufferMS(r, DEF_BUFTIME); - if (!RTMP_SetupURL(r, conn->data->change.url)) { - RTMP_Free(r); - return CURLE_URL_MALFORMAT; - } - conn->proto.generic = r; - return CURLE_OK; -} - -static CURLcode rtmp_connect(struct connectdata *conn, bool *done) -{ - RTMP *r = conn->proto.generic; - SET_RCVTIMEO(tv,10); - - r->m_sb.sb_socket = conn->sock[FIRSTSOCKET]; - - /* We have to know if it's a write before we send the - * connect request packet - */ - if (conn->data->set.upload) - r->Link.protocol |= RTMP_FEATURE_WRITE; - - /* For plain streams, use the buffer toggle trick to keep data flowing */ - if (!(r->Link.lFlags & RTMP_LF_LIVE) && !(r->Link.protocol & RTMP_FEATURE_HTTP)) - r->Link.lFlags |= RTMP_LF_BUFX; - - curlx_nonblock(r->m_sb.sb_socket, FALSE); - setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); - - if (!RTMP_Connect1(r, NULL)) - return CURLE_FAILED_INIT; - - /* Clients must send a periodic BytesReceived report to the server */ - r->m_bSendCounter = true; - - *done = TRUE; - conn->recv[FIRSTSOCKET] = rtmp_recv; - conn->send[FIRSTSOCKET] = rtmp_send; - return CURLE_OK; -} - -static CURLcode rtmp_do(struct connectdata *conn, bool *done) -{ - RTMP *r = conn->proto.generic; - - if (!RTMP_ConnectStream(r, 0)) - return CURLE_FAILED_INIT; - - if (conn->data->set.upload) { - Curl_pgrsSetUploadSize(conn->data, conn->data->set.infilesize); - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); - } else - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); - *done = TRUE; - return CURLE_OK; -} - -static CURLcode rtmp_done(struct connectdata *conn, CURLcode status, - bool premature) -{ - (void)conn; /* unused */ - (void)status; /* unused */ - (void)premature; /* unused */ - - return CURLE_OK; -} - -static CURLcode rtmp_disconnect(struct connectdata *conn, - bool dead_connection) -{ - RTMP *r = conn->proto.generic; - (void)dead_connection; - if (r) { - conn->proto.generic = NULL; - RTMP_Close(r); - RTMP_Free(r); - } - return CURLE_OK; -} - -static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf, - size_t len, CURLcode *err) -{ - RTMP *r = conn->proto.generic; - ssize_t nread; - - (void)sockindex; /* unused */ - - nread = RTMP_Read(r, buf, len); - if (nread < 0) { - if (r->m_read.status == RTMP_READ_COMPLETE || - r->m_read.status == RTMP_READ_EOF) { - conn->data->req.size = conn->data->req.bytecount; - nread = 0; - } else - *err = CURLE_RECV_ERROR; - } - return nread; -} - -static ssize_t rtmp_send(struct connectdata *conn, int sockindex, - const void *buf, size_t len, CURLcode *err) -{ - RTMP *r = conn->proto.generic; - ssize_t num; - - (void)sockindex; /* unused */ - - num = RTMP_Write(r, (char *)buf, len); - if (num < 0) { - *err = CURLE_SEND_ERROR; - } - return num; -} -#endif /* USE_LIBRTMP */ diff --git a/third_party/curl/lib/curl_rtmp.h b/third_party/curl/lib/curl_rtmp.h deleted file mode 100644 index 4a9e9e60c..000000000 --- a/third_party/curl/lib/curl_rtmp.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef HEADER_CURL_RTMP_H -#define HEADER_CURL_RTMP_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, Howard Chu, - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#ifdef USE_LIBRTMP -extern const struct Curl_handler Curl_handler_rtmp; -extern const struct Curl_handler Curl_handler_rtmpt; -extern const struct Curl_handler Curl_handler_rtmpe; -extern const struct Curl_handler Curl_handler_rtmpte; -extern const struct Curl_handler Curl_handler_rtmps; -extern const struct Curl_handler Curl_handler_rtmpts; -#endif - -#endif /* HEADER_CURL_RTMP_H */ diff --git a/third_party/curl/lib/curl_sspi.c b/third_party/curl/lib/curl_sspi.c deleted file mode 100644 index b985dbceb..000000000 --- a/third_party/curl/lib/curl_sspi.c +++ /dev/null @@ -1,121 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef USE_WINDOWS_SSPI - -#include - -#include "curl_sspi.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - - -/* We use our own typedef here since some headers might lack these */ -typedef PSecurityFunctionTableA (APIENTRY *INITSECURITYINTERFACE_FN_A)(VOID); - -/* Handle of security.dll or secur32.dll, depending on Windows version */ -HMODULE s_hSecDll = NULL; - -/* Pointer to SSPI dispatch table */ -PSecurityFunctionTableA s_pSecFn = NULL; - - -/* - * Curl_sspi_global_init() - * - * This is used to load the Security Service Provider Interface (SSPI) - * dynamic link library portably across all Windows versions, without - * the need to directly link libcurl, nor the application using it, at - * build time. - * - * Once this function has been executed, Windows SSPI functions can be - * called through the Security Service Provider Interface dispatch table. - */ - -CURLcode -Curl_sspi_global_init(void) -{ - OSVERSIONINFO osver; - INITSECURITYINTERFACE_FN_A pInitSecurityInterface; - - /* If security interface is not yet initialized try to do this */ - if(s_hSecDll == NULL) { - - /* Find out Windows version */ - memset(&osver, 0, sizeof(osver)); - osver.dwOSVersionInfoSize = sizeof(osver); - if(! GetVersionEx(&osver)) - return CURLE_FAILED_INIT; - - /* Security Service Provider Interface (SSPI) functions are located in - * security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP - * have both these DLLs (security.dll forwards calls to secur32.dll) */ - - /* Load SSPI dll into the address space of the calling process */ - if(osver.dwPlatformId == VER_PLATFORM_WIN32_NT - && osver.dwMajorVersion == 4) - s_hSecDll = LoadLibrary("security.dll"); - else - s_hSecDll = LoadLibrary("secur32.dll"); - if(! s_hSecDll) - return CURLE_FAILED_INIT; - - /* Get address of the InitSecurityInterfaceA function from the SSPI dll */ - pInitSecurityInterface = (INITSECURITYINTERFACE_FN_A) - GetProcAddress(s_hSecDll, "InitSecurityInterfaceA"); - if(! pInitSecurityInterface) - return CURLE_FAILED_INIT; - - /* Get pointer to Security Service Provider Interface dispatch table */ - s_pSecFn = pInitSecurityInterface(); - if(! s_pSecFn) - return CURLE_FAILED_INIT; - - } - return CURLE_OK; -} - - -/* - * Curl_sspi_global_cleanup() - * - * This deinitializes the Security Service Provider Interface from libcurl. - */ - -void -Curl_sspi_global_cleanup(void) -{ - if(s_hSecDll) { - FreeLibrary(s_hSecDll); - s_hSecDll = NULL; - s_pSecFn = NULL; - } -} - -#endif /* USE_WINDOWS_SSPI */ diff --git a/third_party/curl/lib/curl_sspi.h b/third_party/curl/lib/curl_sspi.h deleted file mode 100644 index c0e4f368f..000000000 --- a/third_party/curl/lib/curl_sspi.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef HEADER_CURL_SSPI_H -#define HEADER_CURL_SSPI_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef USE_WINDOWS_SSPI - -#include - -/* - * When including the following three headers, it is mandatory to define either - * SECURITY_WIN32 or SECURITY_KERNEL, indicating who is compiling the code. - */ - -#undef SECURITY_WIN32 -#undef SECURITY_KERNEL -#define SECURITY_WIN32 1 -#include -#include -#include - -/* Provide some definitions missing in MinGW's headers */ - -#ifndef SEC_I_CONTEXT_EXPIRED -# define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L) -#endif -#ifndef SEC_E_BUFFER_TOO_SMALL -# define SEC_E_BUFFER_TOO_SMALL ((HRESULT)0x80090321L) -#endif -#ifndef SEC_E_CONTEXT_EXPIRED -# define SEC_E_CONTEXT_EXPIRED ((HRESULT)0x80090317L) -#endif -#ifndef SEC_E_CRYPTO_SYSTEM_INVALID -# define SEC_E_CRYPTO_SYSTEM_INVALID ((HRESULT)0x80090337L) -#endif -#ifndef SEC_E_MESSAGE_ALTERED -# define SEC_E_MESSAGE_ALTERED ((HRESULT)0x8009030FL) -#endif -#ifndef SEC_E_OUT_OF_SEQUENCE -# define SEC_E_OUT_OF_SEQUENCE ((HRESULT)0x80090310L) -#endif - -CURLcode Curl_sspi_global_init(void); -void Curl_sspi_global_cleanup(void); - -/* Forward-declaration of global variables defined in curl_sspi.c */ - -extern HMODULE s_hSecDll; -extern PSecurityFunctionTableA s_pSecFn; - -#endif /* USE_WINDOWS_SSPI */ -#endif /* HEADER_CURL_SSPI_H */ diff --git a/third_party/curl/lib/curl_threads.c b/third_party/curl/lib/curl_threads.c deleted file mode 100644 index fd10bd487..000000000 --- a/third_party/curl/lib/curl_threads.c +++ /dev/null @@ -1,127 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#if defined(USE_THREADS_POSIX) -# ifdef HAVE_PTHREAD_H -# include -# endif -#elif defined(USE_THREADS_WIN32) -# ifdef HAVE_PROCESS_H -# include -# endif -#endif - -#include "curl_threads.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -#if defined(USE_THREADS_POSIX) - -struct curl_actual_call { - unsigned int (*func)(void *); - void *arg; -}; - -static void *curl_thread_create_thunk(void *arg) -{ - struct curl_actual_call * ac = arg; - unsigned int (*func)(void *) = ac->func; - void *real_arg = ac->arg; - - free(ac); - - (*func)(real_arg); - - return 0; -} - -curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg) -{ - curl_thread_t t; - struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call)); - if(!ac) - return curl_thread_t_null; - - ac->func = func; - ac->arg = arg; - - if(pthread_create(&t, NULL, curl_thread_create_thunk, ac) != 0) { - free(ac); - return curl_thread_t_null; - } - - return t; -} - -void Curl_thread_destroy(curl_thread_t hnd) -{ - if(hnd != curl_thread_t_null) - pthread_detach(hnd); -} - -int Curl_thread_join(curl_thread_t *hnd) -{ - int ret = (pthread_join(*hnd, NULL) == 0); - - *hnd = curl_thread_t_null; - - return ret; -} - -#elif defined(USE_THREADS_WIN32) - -curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*), void *arg) -{ -#ifdef _WIN32_WCE - return CreateThread(NULL, 0, func, arg, 0, NULL); -#else - curl_thread_t t; - t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL); - if((t == 0) || (t == (curl_thread_t)-1L)) - return curl_thread_t_null; - return t; -#endif -} - -void Curl_thread_destroy(curl_thread_t hnd) -{ - CloseHandle(hnd); -} - -int Curl_thread_join(curl_thread_t *hnd) -{ - int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0); - - Curl_thread_destroy(*hnd); - - *hnd = curl_thread_t_null; - - return ret; -} - -#endif /* USE_THREADS_* */ diff --git a/third_party/curl/lib/curl_threads.h b/third_party/curl/lib/curl_threads.h deleted file mode 100644 index ba81054a2..000000000 --- a/third_party/curl/lib/curl_threads.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef HEADER_CURL_THREADS_H -#define HEADER_CURL_THREADS_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#if defined(USE_THREADS_POSIX) -# define CURL_STDCALL -# define curl_mutex_t pthread_mutex_t -# define curl_thread_t pthread_t -# define curl_thread_t_null (pthread_t)0 -# define Curl_mutex_init(m) pthread_mutex_init(m, NULL) -# define Curl_mutex_acquire(m) pthread_mutex_lock(m) -# define Curl_mutex_release(m) pthread_mutex_unlock(m) -# define Curl_mutex_destroy(m) pthread_mutex_destroy(m) -#elif defined(USE_THREADS_WIN32) -# define CURL_STDCALL __stdcall -# define curl_mutex_t CRITICAL_SECTION -# define curl_thread_t HANDLE -# define curl_thread_t_null (HANDLE)0 -# define Curl_mutex_init(m) InitializeCriticalSection(m) -# define Curl_mutex_acquire(m) EnterCriticalSection(m) -# define Curl_mutex_release(m) LeaveCriticalSection(m) -# define Curl_mutex_destroy(m) DeleteCriticalSection(m) -#endif - -#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) - -curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*), - void *arg); - -void Curl_thread_destroy(curl_thread_t hnd); - -int Curl_thread_join(curl_thread_t *hnd); - -#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ - -#endif /* HEADER_CURL_THREADS_H */ diff --git a/third_party/curl/lib/curlx.h b/third_party/curl/lib/curlx.h deleted file mode 100644 index a1df66902..000000000 --- a/third_party/curl/lib/curlx.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef __CURLX_H -#define __CURLX_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Defines protos and includes all header files that provide the curlx_* - * functions. The curlx_* functions are not part of the libcurl API, but are - * stand-alone functions whose sources can be built and linked by apps if need - * be. - */ - -#include -/* this is still a public header file that provides the curl_mprintf() - functions while they still are offered publicly. They will be made library- - private one day */ - -#include "strequal.h" -/* "strequal.h" provides the strequal protos */ - -#include "strtoofft.h" -/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a - curl_off_t number from a given string. -*/ - -#include "timeval.h" -/* - "timeval.h" sets up a 'struct timeval' even for platforms that otherwise - don't have one and has protos for these functions: - - curlx_tvnow() - curlx_tvdiff() - curlx_tvdiff_secs() -*/ - -#include "nonblock.h" -/* "nonblock.h" provides curlx_nonblock() */ - -#include "warnless.h" -/* "warnless.h" provides functions: - - curlx_ultous() - curlx_ultouc() - curlx_uztosi() -*/ - -/* Now setup curlx_ * names for the functions that are to become curlx_ and - be removed from a future libcurl official API: - curlx_getenv - curlx_mprintf (and its variations) - curlx_strequal - curlx_strnequal - -*/ - -#define curlx_getenv curl_getenv -#define curlx_strequal curl_strequal -#define curlx_strnequal curl_strnequal -#define curlx_raw_equal Curl_raw_equal -#define curlx_mvsnprintf curl_mvsnprintf -#define curlx_msnprintf curl_msnprintf -#define curlx_maprintf curl_maprintf -#define curlx_mvaprintf curl_mvaprintf -#define curlx_msprintf curl_msprintf -#define curlx_mprintf curl_mprintf -#define curlx_mfprintf curl_mfprintf -#define curlx_mvsprintf curl_mvsprintf -#define curlx_mvprintf curl_mvprintf -#define curlx_mvfprintf curl_mvfprintf - -#ifdef ENABLE_CURLX_PRINTF -/* If this define is set, we define all "standard" printf() functions to use - the curlx_* version instead. It makes the source code transparent and - easier to understand/patch. Undefine them first in case _MPRINTF_REPLACE - is set. */ -# undef printf -# undef fprintf -# undef sprintf -# undef snprintf -# undef vprintf -# undef vfprintf -# undef vsprintf -# undef vsnprintf -# undef aprintf -# undef vaprintf - -# define printf curlx_mprintf -# define fprintf curlx_mfprintf -# define sprintf curlx_msprintf -# define snprintf curlx_msnprintf -# define vprintf curlx_mvprintf -# define vfprintf curlx_mvfprintf -# define vsprintf curlx_mvsprintf -# define vsnprintf curlx_mvsnprintf -# define aprintf curlx_maprintf -# define vaprintf curlx_mvaprintf -#endif /* ENABLE_CURLX_PRINTF */ - -#endif /* __CURLX_H */ diff --git a/third_party/curl/lib/cyassl.c b/third_party/curl/lib/cyassl.c deleted file mode 100644 index 3e15b1879..000000000 --- a/third_party/curl/lib/cyassl.c +++ /dev/null @@ -1,571 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Source file for all CyaSSL-specific code for the TLS/SSL layer. No code - * but sslgen.c should ever call or use these functions. - * - */ - -#include "setup.h" -#ifdef USE_CYASSL - -#include -#include -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - - -#include "urldata.h" -#include "sendf.h" -#include "inet_pton.h" -#include "cyassl.h" -#include "sslgen.h" -#include "parsedate.h" -#include "connect.h" /* for the connect timeout */ -#include "select.h" -#include "rawstr.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - - -static Curl_recv cyassl_recv; -static Curl_send cyassl_send; - - -static int do_file_type(const char *type) -{ - if(!type || !type[0]) - return SSL_FILETYPE_PEM; - if(Curl_raw_equal(type, "PEM")) - return SSL_FILETYPE_PEM; - if(Curl_raw_equal(type, "DER")) - return SSL_FILETYPE_ASN1; - return -1; -} - -/* - * This function loads all the client/CA certificates and CRLs. Setup the TLS - * layer and do all necessary magic. - */ -static CURLcode -cyassl_connect_step1(struct connectdata *conn, - int sockindex) -{ - struct SessionHandle *data = conn->data; - struct ssl_connect_data* conssl = &conn->ssl[sockindex]; - SSL_METHOD* req_method = NULL; - void* ssl_sessionid = NULL; - curl_socket_t sockfd = conn->sock[sockindex]; - - if(conssl->state == ssl_connection_complete) - return CURLE_OK; - - /* CyaSSL doesn't support SSLv2 */ - if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { - failf(data, "CyaSSL does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - - /* check to see if we've been told to use an explicit SSL/TLS version */ - switch(data->set.ssl.version) { - case CURL_SSLVERSION_DEFAULT: - /* we try to figure out version */ - req_method = SSLv23_client_method(); - break; - case CURL_SSLVERSION_TLSv1: - req_method = TLSv1_client_method(); - break; - case CURL_SSLVERSION_SSLv3: - req_method = SSLv3_client_method(); - break; - default: - req_method = TLSv1_client_method(); - } - - if(!req_method) { - failf(data, "SSL: couldn't create a method!"); - return CURLE_OUT_OF_MEMORY; - } - - if(conssl->ctx) - SSL_CTX_free(conssl->ctx); - conssl->ctx = SSL_CTX_new(req_method); - - if(!conssl->ctx) { - failf(data, "SSL: couldn't create a context!"); - return CURLE_OUT_OF_MEMORY; - } - - /* load trusted cacert */ - if(data->set.str[STRING_SSL_CAFILE]) { - if (!SSL_CTX_load_verify_locations(conssl->ctx, - data->set.str[STRING_SSL_CAFILE], - data->set.str[STRING_SSL_CAPATH])) { - if (data->set.ssl.verifypeer) { - /* Fail if we insiste on successfully verifying the server. */ - failf(data,"error setting certificate verify locations:\n" - " CAfile: %s\n CApath: %s\n", - data->set.str[STRING_SSL_CAFILE]? - data->set.str[STRING_SSL_CAFILE]: "none", - data->set.str[STRING_SSL_CAPATH]? - data->set.str[STRING_SSL_CAPATH] : "none"); - return CURLE_SSL_CACERT_BADFILE; - } - else { - /* Just continue with a warning if no strict certificate - verification is required. */ - infof(data, "error setting certificate verify locations," - " continuing anyway:\n"); - } - } - else { - /* Everything is fine. */ - infof(data, "successfully set certificate verify locations:\n"); - } - infof(data, - " CAfile: %s\n" - " CApath: %s\n", - data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]: - "none", - data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]: - "none"); - } - - /* Load the client certificate, and private key */ - if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) { - int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]); - - if (SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT], - file_type) != 1) { - failf(data, "unable to use client certificate (no key or wrong pass" - " phrase?)"); - return CURLE_SSL_CONNECT_ERROR; - } - - file_type = do_file_type(data->set.str[STRING_KEY_TYPE]); - if (SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY], - file_type) != 1) { - failf(data, "unable to set private key"); - return CURLE_SSL_CONNECT_ERROR; - } - } - - /* SSL always tries to verify the peer, this only says whether it should - * fail to connect if the verification fails, or if it should continue - * anyway. In the latter case the result of the verification is checked with - * SSL_get_verify_result() below. */ - SSL_CTX_set_verify(conssl->ctx, - data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE, - NULL); - - /* Let's make an SSL structure */ - if (conssl->handle) - SSL_free(conssl->handle); - conssl->handle = SSL_new(conssl->ctx); - if (!conssl->handle) { - failf(data, "SSL: couldn't create a context (handle)!"); - return CURLE_OUT_OF_MEMORY; - } - - /* Check if there's a cached ID we can/should use here! */ - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) { - /* we got a session id, use it! */ - if(!SSL_set_session(conssl->handle, ssl_sessionid)) { - failf(data, "SSL: SSL_set_session failed: %s", - ERR_error_string(SSL_get_error(conssl->handle, 0),NULL)); - return CURLE_SSL_CONNECT_ERROR; - } - /* Informational message */ - infof (data, "SSL re-using session ID\n"); - } - - /* pass the raw socket into the SSL layer */ - if (!SSL_set_fd(conssl->handle, (int)sockfd)) { - failf(data, "SSL: SSL_set_fd failed"); - return CURLE_SSL_CONNECT_ERROR; - } - - conssl->connecting_state = ssl_connect_2; - return CURLE_OK; -} - - -static CURLcode -cyassl_connect_step2(struct connectdata *conn, - int sockindex) -{ - int ret = -1; - struct SessionHandle *data = conn->data; - struct ssl_connect_data* conssl = &conn->ssl[sockindex]; - - infof(data, "CyaSSL: Connecting to %s:%d\n", - conn->host.name, conn->remote_port); - - conn->recv[sockindex] = cyassl_recv; - conn->send[sockindex] = cyassl_send; - - ret = SSL_connect(conssl->handle); - if (ret != 1) { - char error_buffer[80]; - int detail = SSL_get_error(conssl->handle, ret); - - if (SSL_ERROR_WANT_READ == detail) { - conssl->connecting_state = ssl_connect_2_reading; - return CURLE_OK; - } - - if (SSL_ERROR_WANT_WRITE == detail) { - conssl->connecting_state = ssl_connect_2_writing; - return CURLE_OK; - } - - failf(data, "SSL_connect failed with error %d: %s", detail, - ERR_error_string(detail, error_buffer)); - return CURLE_SSL_CONNECT_ERROR; - } - - conssl->connecting_state = ssl_connect_3; - infof(data, "SSL connected"); - - return CURLE_OK; -} - - -static CURLcode -cyassl_connect_step3(struct connectdata *conn, - int sockindex) -{ - CURLcode retcode = CURLE_OK; - void *old_ssl_sessionid=NULL; - struct SessionHandle *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - int incache; - SSL_SESSION *our_ssl_sessionid; - - DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - - our_ssl_sessionid = SSL_get_session(connssl->handle); - - incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); - if (incache) { - if (old_ssl_sessionid != our_ssl_sessionid) { - infof(data, "old SSL session ID is stale, removing\n"); - Curl_ssl_delsessionid(conn, old_ssl_sessionid); - incache = FALSE; - } - } - if (!incache) { - retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, - 0 /* unknown size */); - if(retcode) { - failf(data, "failed to store ssl session"); - return retcode; - } - } - - connssl->connecting_state = ssl_connect_done; - - return retcode; -} - - -static ssize_t cyassl_send(struct connectdata *conn, - int sockindex, - const void *mem, - size_t len, - CURLcode *curlcode) -{ - char error_buffer[80]; - int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; - int rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen); - - if (rc < 0) { - int err = SSL_get_error(conn->ssl[sockindex].handle, rc); - - switch(err) { - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - /* there's data pending, re-invoke SSL_write() */ - *curlcode = CURLE_AGAIN; - return -1; - default: - failf(conn->data, "SSL write: %s, errno %d", - ERR_error_string(err, error_buffer), - SOCKERRNO); - *curlcode = CURLE_SEND_ERROR; - return -1; - } - } - return rc; -} - -void Curl_cyassl_close_all(struct SessionHandle *data) -{ - (void)data; -} - -void Curl_cyassl_close(struct connectdata *conn, int sockindex) -{ - struct ssl_connect_data *conssl = &conn->ssl[sockindex]; - - if(conssl->handle) { - (void)SSL_shutdown(conssl->handle); - SSL_free (conssl->handle); - conssl->handle = NULL; - } - if(conssl->ctx) { - SSL_CTX_free (conssl->ctx); - conssl->ctx = NULL; - } -} - -static ssize_t cyassl_recv(struct connectdata *conn, - int num, - char *buf, - size_t buffersize, - CURLcode *curlcode) -{ - char error_buffer[80]; - int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; - int nread = SSL_read(conn->ssl[num].handle, buf, buffsize); - - if (nread < 0) { - int err = SSL_get_error(conn->ssl[num].handle, nread); - - switch(err) { - case SSL_ERROR_ZERO_RETURN: /* no more data */ - break; - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - /* there's data pending, re-invoke SSL_read() */ - *curlcode = CURLE_AGAIN; - return -1; - default: - failf(conn->data, "SSL read: %s, errno %d", - ERR_error_string(err, error_buffer), - SOCKERRNO); - *curlcode = CURLE_RECV_ERROR; - return -1; - } - } - return nread; -} - - -void Curl_cyassl_session_free(void *ptr) -{ - (void)ptr; - /* CyaSSL reuses sessions on own, no free */ -} - - -size_t Curl_cyassl_version(char *buffer, size_t size) -{ -#ifdef CYASSL_VERSION - return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION); -#else - return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8"); -#endif -} - - -int Curl_cyassl_init(void) -{ - InitCyaSSL(); - - return 1; -} - - -bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex) -{ - if (conn->ssl[connindex].handle) /* SSL is in use */ - return (bool)(0 != SSL_pending(conn->ssl[connindex].handle)); - else - return FALSE; -} - - -/* - * This function is called to shut down the SSL layer but keep the - * socket open (CCC - Clear Command Channel) - */ -int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex) -{ - int retval = 0; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - if(connssl->handle) { - SSL_free (connssl->handle); - connssl->handle = NULL; - } - return retval; -} - - -static CURLcode -cyassl_connect_common(struct connectdata *conn, - int sockindex, - bool nonblocking, - bool *done) -{ - CURLcode retcode; - struct SessionHandle *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - curl_socket_t sockfd = conn->sock[sockindex]; - long timeout_ms; - int what; - - /* check if the connection has already been established */ - if(ssl_connection_complete == connssl->state) { - *done = TRUE; - return CURLE_OK; - } - - if(ssl_connect_1==connssl->connecting_state) { - /* Find out how much more time we're allowed */ - timeout_ms = Curl_timeleft(data, NULL, TRUE); - - if(timeout_ms < 0) { - /* no need to continue if time already is up */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - retcode = cyassl_connect_step1(conn, sockindex); - if(retcode) - return retcode; - } - - while(ssl_connect_2 == connssl->connecting_state || - ssl_connect_2_reading == connssl->connecting_state || - ssl_connect_2_writing == connssl->connecting_state) { - - /* check allowed time left */ - timeout_ms = Curl_timeleft(data, NULL, TRUE); - - if(timeout_ms < 0) { - /* no need to continue if time already is up */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - /* if ssl is expecting something, check if it's available. */ - if(connssl->connecting_state == ssl_connect_2_reading - || connssl->connecting_state == ssl_connect_2_writing) { - - curl_socket_t writefd = ssl_connect_2_writing== - connssl->connecting_state?sockfd:CURL_SOCKET_BAD; - curl_socket_t readfd = ssl_connect_2_reading== - connssl->connecting_state?sockfd:CURL_SOCKET_BAD; - - what = Curl_socket_ready(readfd, writefd, - nonblocking?0:(int)timeout_ms); - if(what < 0) { - /* fatal error */ - failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); - return CURLE_SSL_CONNECT_ERROR; - } - else if(0 == what) { - if(nonblocking) { - *done = FALSE; - return CURLE_OK; - } - else { - /* timeout */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - } - /* socket is readable or writable */ - } - - /* Run transaction, and return to the caller if it failed or if - * this connection is part of a multi handle and this loop would - * execute again. This permits the owner of a multi handle to - * abort a connection attempt before step2 has completed while - * ensuring that a client using select() or epoll() will always - * have a valid fdset to wait on. - */ - retcode = cyassl_connect_step2(conn, sockindex); - if(retcode || (nonblocking && - (ssl_connect_2 == connssl->connecting_state || - ssl_connect_2_reading == connssl->connecting_state || - ssl_connect_2_writing == connssl->connecting_state))) - return retcode; - - } /* repeat step2 until all transactions are done. */ - - if(ssl_connect_3==connssl->connecting_state) { - retcode = cyassl_connect_step3(conn, sockindex); - if(retcode) - return retcode; - } - - if(ssl_connect_done==connssl->connecting_state) { - connssl->state = ssl_connection_complete; - conn->recv[sockindex] = cyassl_recv; - conn->send[sockindex] = cyassl_send; - *done = TRUE; - } - else - *done = FALSE; - - /* Reset our connect state machine */ - connssl->connecting_state = ssl_connect_1; - - return CURLE_OK; -} - - -CURLcode -Curl_cyassl_connect_nonblocking(struct connectdata *conn, - int sockindex, - bool *done) -{ - return cyassl_connect_common(conn, sockindex, TRUE, done); -} - - -CURLcode -Curl_cyassl_connect(struct connectdata *conn, - int sockindex) -{ - CURLcode retcode; - bool done = FALSE; - - retcode = cyassl_connect_common(conn, sockindex, FALSE, &done); - if(retcode) - return retcode; - - DEBUGASSERT(done); - - return CURLE_OK; -} - -#endif diff --git a/third_party/curl/lib/cyassl.h b/third_party/curl/lib/cyassl.h deleted file mode 100644 index a21592a28..000000000 --- a/third_party/curl/lib/cyassl.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef HEADER_CURL_CYASSL_H -#define HEADER_CURL_CYASSL_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifdef USE_CYASSL - -CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex); -bool Curl_cyassl_data_pending(const struct connectdata* conn,int connindex); -int Curl_cyassl_shutdown(struct connectdata* conn, int sockindex); - -/* tell CyaSSL to close down all open information regarding connections (and - thus session ID caching etc) */ -void Curl_cyassl_close_all(struct SessionHandle *data); - - /* close a SSL connection */ -void Curl_cyassl_close(struct connectdata *conn, int sockindex); - -void Curl_cyassl_session_free(void *ptr); -size_t Curl_cyassl_version(char *buffer, size_t size); -int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex); -int Curl_cyassl_init(void); -CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn, - int sockindex, - bool *done); - -/* API setup for CyaSSL */ -#define curlssl_init Curl_cyassl_init -#define curlssl_cleanup() -#define curlssl_connect Curl_cyassl_connect -#define curlssl_connect_nonblocking Curl_cyassl_connect_nonblocking -#define curlssl_session_free(x) Curl_cyassl_session_free(x) -#define curlssl_close_all Curl_cyassl_close_all -#define curlssl_close Curl_cyassl_close -#define curlssl_shutdown(x,y) Curl_cyassl_shutdown(x,y) -#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN) -#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN) -#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL) -#define curlssl_version Curl_cyassl_version -#define curlssl_check_cxn(x) (x=x, -1) -#define curlssl_data_pending(x,y) Curl_cyassl_data_pending(x,y) - -#endif /* USE_CYASSL */ -#endif /* HEADER_CURL_CYASSL_H */ diff --git a/third_party/curl/lib/dict.c b/third_party/curl/lib/dict.c deleted file mode 100644 index e079fd188..000000000 --- a/third_party/curl/lib/dict.c +++ /dev/null @@ -1,301 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef CURL_DISABLE_DICT - -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#include -#else -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SELECT_H -#include -#endif - - -#endif - -#include "urldata.h" -#include -#include "transfer.h" -#include "sendf.h" - -#include "progress.h" -#include "strequal.h" -#include "dict.h" -#include "rawstr.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - - -/* - * Forward declarations. - */ - -static CURLcode dict_do(struct connectdata *conn, bool *done); - -/* - * DICT protocol handler. - */ - -const struct Curl_handler Curl_handler_dict = { - "DICT", /* scheme */ - ZERO_NULL, /* setup_connection */ - dict_do, /* do_it */ - ZERO_NULL, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_DICT, /* defport */ - CURLPROTO_DICT, /* protocol */ - PROTOPT_NONE /* flags */ -}; - -static char *unescape_word(struct SessionHandle *data, const char *inputbuff) -{ - char *newp; - char *dictp; - char *ptr; - int len; - char byte; - int olen=0; - - newp = curl_easy_unescape(data, inputbuff, 0, &len); - if(!newp) - return NULL; - - dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */ - if(dictp) { - /* According to RFC2229 section 2.2, these letters need to be escaped with - \[letter] */ - for(ptr = newp; - (byte = *ptr) != 0; - ptr++) { - if((byte <= 32) || (byte == 127) || - (byte == '\'') || (byte == '\"') || (byte == '\\')) { - dictp[olen++] = '\\'; - } - dictp[olen++] = byte; - } - dictp[olen]=0; - - free(newp); - } - return dictp; -} - -static CURLcode dict_do(struct connectdata *conn, bool *done) -{ - char *word; - char *eword; - char *ppath; - char *database = NULL; - char *strategy = NULL; - char *nthdef = NULL; /* This is not part of the protocol, but required - by RFC 2229 */ - CURLcode result=CURLE_OK; - struct SessionHandle *data=conn->data; - curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; - - char *path = data->state.path; - curl_off_t *bytecount = &data->req.bytecount; - - *done = TRUE; /* unconditionally */ - - if(conn->bits.user_passwd) { - /* AUTH is missing */ - } - - if(Curl_raw_nequal(path, DICT_MATCH, sizeof(DICT_MATCH)-1) || - Curl_raw_nequal(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) || - Curl_raw_nequal(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) { - - word = strchr(path, ':'); - if(word) { - word++; - database = strchr(word, ':'); - if(database) { - *database++ = (char)0; - strategy = strchr(database, ':'); - if(strategy) { - *strategy++ = (char)0; - nthdef = strchr(strategy, ':'); - if(nthdef) { - *nthdef = (char)0; - } - } - } - } - - if((word == NULL) || (*word == (char)0)) { - infof(data, "lookup word is missing"); - word=(char *)"default"; - } - if((database == NULL) || (*database == (char)0)) { - database = (char *)"!"; - } - if((strategy == NULL) || (*strategy == (char)0)) { - strategy = (char *)"."; - } - - eword = unescape_word(data, word); - if(!eword) - return CURLE_OUT_OF_MEMORY; - - result = Curl_sendf(sockfd, conn, - "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" - "MATCH " - "%s " /* database */ - "%s " /* strategy */ - "%s\r\n" /* word */ - "QUIT\r\n", - - database, - strategy, - eword - ); - - free(eword); - - if(result) { - failf(data, "Failed sending DICT request"); - return result; - } - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, - -1, NULL); /* no upload */ - } - else if(Curl_raw_nequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) || - Curl_raw_nequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) || - Curl_raw_nequal(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) { - - word = strchr(path, ':'); - if(word) { - word++; - database = strchr(word, ':'); - if(database) { - *database++ = (char)0; - nthdef = strchr(database, ':'); - if(nthdef) { - *nthdef = (char)0; - } - } - } - - if((word == NULL) || (*word == (char)0)) { - infof(data, "lookup word is missing"); - word=(char *)"default"; - } - if((database == NULL) || (*database == (char)0)) { - database = (char *)"!"; - } - - eword = unescape_word(data, word); - if(!eword) - return CURLE_OUT_OF_MEMORY; - - result = Curl_sendf(sockfd, conn, - "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" - "DEFINE " - "%s " /* database */ - "%s\r\n" /* word */ - "QUIT\r\n", - database, - eword); - - free(eword); - - if(result) { - failf(data, "Failed sending DICT request"); - return result; - } - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, - -1, NULL); /* no upload */ - } - else { - - ppath = strchr(path, '/'); - if(ppath) { - int i; - - ppath++; - for (i = 0; ppath[i]; i++) { - if(ppath[i] == ':') - ppath[i] = ' '; - } - result = Curl_sendf(sockfd, conn, - "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n" - "%s\r\n" - "QUIT\r\n", ppath); - if(result) { - failf(data, "Failed sending DICT request"); - return result; - } - - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL); - } - } - - return CURLE_OK; -} -#endif /*CURL_DISABLE_DICT*/ diff --git a/third_party/curl/lib/dict.h b/third_party/curl/lib/dict.h deleted file mode 100644 index 44fd9d49d..000000000 --- a/third_party/curl/lib/dict.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef HEADER_CURL_DICT_H -#define HEADER_CURL_DICT_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifndef CURL_DISABLE_DICT -extern const struct Curl_handler Curl_handler_dict; -#endif - -#endif /* HEADER_CURL_DICT_H */ diff --git a/third_party/curl/lib/easy.c b/third_party/curl/lib/easy.c deleted file mode 100644 index 05d8ded9d..000000000 --- a/third_party/curl/lib/easy.c +++ /dev/null @@ -1,930 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include -#include - -#include "strequal.h" - -#ifdef WIN32 -#include -#include -#else -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#endif /* WIN32 ... */ - -#include "urldata.h" -#include -#include "transfer.h" -#include "sslgen.h" -#include "url.h" -#include "getinfo.h" -#include "hostip.h" -#include "share.h" -#include "strdup.h" -#include "curl_memory.h" -#include "progress.h" -#include "easyif.h" -#include "select.h" -#include "sendf.h" /* for failf function prototype */ -#include "http_ntlm.h" -#include "connect.h" /* for Curl_getconnectinfo */ -#include "slist.h" -#include "curl_rand.h" -#include "non-ascii.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -/* win32_cleanup() is for win32 socket cleanup functionality, the opposite - of win32_init() */ -static void win32_cleanup(void) -{ -#ifdef USE_WINSOCK - WSACleanup(); -#endif -#ifdef USE_WINDOWS_SSPI - Curl_sspi_global_cleanup(); -#endif -} - -/* win32_init() performs win32 socket initialization to properly setup the - stack to allow networking */ -static CURLcode win32_init(void) -{ -#ifdef USE_WINSOCK - WORD wVersionRequested; - WSADATA wsaData; - int res; - -#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2) - Error IPV6_requires_winsock2 -#endif - - wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); - - res = WSAStartup(wVersionRequested, &wsaData); - - if(res != 0) - /* Tell the user that we couldn't find a useable */ - /* winsock.dll. */ - return CURLE_FAILED_INIT; - - /* Confirm that the Windows Sockets DLL supports what we need.*/ - /* Note that if the DLL supports versions greater */ - /* than wVersionRequested, it will still return */ - /* wVersionRequested in wVersion. wHighVersion contains the */ - /* highest supported version. */ - - if( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) || - HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) { - /* Tell the user that we couldn't find a useable */ - - /* winsock.dll. */ - WSACleanup(); - return CURLE_FAILED_INIT; - } - /* The Windows Sockets DLL is acceptable. Proceed. */ -#endif - -#ifdef USE_WINDOWS_SSPI - { - CURLcode err = Curl_sspi_global_init(); - if (err != CURLE_OK) - return err; - } -#endif - - return CURLE_OK; -} - -#ifdef USE_LIBIDN -/* - * Initialise use of IDNA library. - * It falls back to ASCII if $CHARSET isn't defined. This doesn't work for - * idna_to_ascii_lz(). - */ -static void idna_init (void) -{ -#ifdef WIN32 - char buf[60]; - UINT cp = GetACP(); - - if(!getenv("CHARSET") && cp > 0) { - snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp); - putenv(buf); - } -#else - /* to do? */ -#endif -} -#endif /* USE_LIBIDN */ - -/* true globals -- for curl_global_init() and curl_global_cleanup() */ -static unsigned int initialized; -static long init_flags; - -/* - * strdup (and other memory functions) is redefined in complicated - * ways, but at this point it must be defined as the system-supplied strdup - * so the callback pointer is initialized correctly. - */ -#if defined(_WIN32_WCE) -#define system_strdup _strdup -#elif !defined(HAVE_STRDUP) -#define system_strdup curlx_strdup -#else -#define system_strdup strdup -#endif - -#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) -# pragma warning(disable:4232) /* MSVC extension, dllimport identity */ -#endif - -#ifndef __SYMBIAN32__ -/* - * If a memory-using function (like curl_getenv) is used before - * curl_global_init() is called, we need to have these pointers set already. - */ -curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc; -curl_free_callback Curl_cfree = (curl_free_callback)free; -curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; -curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; -curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; -#else -/* - * Symbian OS doesn't support initialization to code in writeable static data. - * Initialization will occur in the curl_global_init() call. - */ -curl_malloc_callback Curl_cmalloc; -curl_free_callback Curl_cfree; -curl_realloc_callback Curl_crealloc; -curl_strdup_callback Curl_cstrdup; -curl_calloc_callback Curl_ccalloc; -#endif - -#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) -# pragma warning(default:4232) /* MSVC extension, dllimport identity */ -#endif - -/** - * curl_global_init() globally initializes cURL given a bitwise set of the - * different features of what to initialize. - */ -CURLcode curl_global_init(long flags) -{ - if(initialized++) - return CURLE_OK; - - /* Setup the default memory functions here (again) */ - Curl_cmalloc = (curl_malloc_callback)malloc; - Curl_cfree = (curl_free_callback)free; - Curl_crealloc = (curl_realloc_callback)realloc; - Curl_cstrdup = (curl_strdup_callback)system_strdup; - Curl_ccalloc = (curl_calloc_callback)calloc; - - if(flags & CURL_GLOBAL_SSL) - if(!Curl_ssl_init()) { - DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n")); - return CURLE_FAILED_INIT; - } - - if(flags & CURL_GLOBAL_WIN32) - if(win32_init() != CURLE_OK) { - DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); - return CURLE_FAILED_INIT; - } - -#ifdef __AMIGA__ - if(!amiga_init()) { - DEBUGF(fprintf(stderr, "Error: amiga_init failed\n")); - return CURLE_FAILED_INIT; - } -#endif - -#ifdef NETWARE - if(netware_init()) { - DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n")); - } -#endif - -#ifdef USE_LIBIDN - idna_init(); -#endif - -#ifdef CARES_HAVE_ARES_LIBRARY_INIT - if(ares_library_init(ARES_LIB_INIT_ALL)) { - DEBUGF(fprintf(stderr, "Error: ares_library_init failed\n")); - return CURLE_FAILED_INIT; - } -#endif - -#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT) - if(libssh2_init(0)) { - DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n")); - return CURLE_FAILED_INIT; - } -#endif - - init_flags = flags; - - /* Preset pseudo-random number sequence. */ - - Curl_srand(); - - return CURLE_OK; -} - -/* - * curl_global_init_mem() globally initializes cURL and also registers the - * user provided callback routines. - */ -CURLcode curl_global_init_mem(long flags, curl_malloc_callback m, - curl_free_callback f, curl_realloc_callback r, - curl_strdup_callback s, curl_calloc_callback c) -{ - CURLcode code = CURLE_OK; - - /* Invalid input, return immediately */ - if(!m || !f || !r || !s || !c) - return CURLE_FAILED_INIT; - - /* Already initialized, don't do it again */ - if( initialized ) - return CURLE_OK; - - /* Call the actual init function first */ - code = curl_global_init(flags); - if(code == CURLE_OK) { - Curl_cmalloc = m; - Curl_cfree = f; - Curl_cstrdup = s; - Curl_crealloc = r; - Curl_ccalloc = c; - } - - return code; -} - -/** - * curl_global_cleanup() globally cleanups cURL, uses the value of - * "init_flags" to determine what needs to be cleaned up and what doesn't. - */ -void curl_global_cleanup(void) -{ - if(!initialized) - return; - - if(--initialized) - return; - - Curl_global_host_cache_dtor(); - - if(init_flags & CURL_GLOBAL_SSL) - Curl_ssl_cleanup(); - -#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP - ares_library_cleanup(); -#endif - - if(init_flags & CURL_GLOBAL_WIN32) - win32_cleanup(); - -#ifdef __AMIGA__ - amiga_cleanup(); -#endif - -#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT) - (void)libssh2_exit(); -#endif - - init_flags = 0; -} - -/* - * curl_easy_init() is the external interface to alloc, setup and init an - * easy handle that is returned. If anything goes wrong, NULL is returned. - */ -CURL *curl_easy_init(void) -{ - CURLcode res; - struct SessionHandle *data; - - /* Make sure we inited the global SSL stuff */ - if(!initialized) { - res = curl_global_init(CURL_GLOBAL_DEFAULT); - if(res) { - /* something in the global init failed, return nothing */ - DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n")); - return NULL; - } - } - - /* We use curl_open() with undefined URL so far */ - res = Curl_open(&data); - if(res != CURLE_OK) { - DEBUGF(fprintf(stderr, "Error: Curl_open failed\n")); - return NULL; - } - - return data; -} - -/* - * curl_easy_setopt() is the external interface for setting options on an - * easy handle. - */ - -#undef curl_easy_setopt -CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...) -{ - va_list arg; - struct SessionHandle *data = curl; - CURLcode ret; - - if(!curl) - return CURLE_BAD_FUNCTION_ARGUMENT; - - va_start(arg, tag); - - ret = Curl_setopt(data, tag, arg); - - va_end(arg); - return ret; -} - -#ifdef CURL_MULTIEASY -/*************************************************************************** - * This function is still only for testing purposes. It makes a great way - * to run the full test suite on the multi interface instead of the easy one. - *************************************************************************** - * - * The *new* curl_easy_perform() is the external interface that performs a - * transfer previously setup. - * - * Wrapper-function that: creates a multi handle, adds the easy handle to it, - * runs curl_multi_perform() until the transfer is done, then detaches the - * easy handle, destroys the multi handle and returns the easy handle's return - * code. This will make everything internally use and assume multi interface. - */ -CURLcode curl_easy_perform(CURL *easy) -{ - CURLM *multi; - CURLMcode mcode; - CURLcode code = CURLE_OK; - int still_running; - struct timeval timeout; - int rc; - CURLMsg *msg; - fd_set fdread; - fd_set fdwrite; - fd_set fdexcep; - int maxfd; - - if(!easy) - return CURLE_BAD_FUNCTION_ARGUMENT; - - multi = curl_multi_init(); - if(!multi) - return CURLE_OUT_OF_MEMORY; - - mcode = curl_multi_add_handle(multi, easy); - if(mcode) { - curl_multi_cleanup(multi); - if(mcode == CURLM_OUT_OF_MEMORY) - return CURLE_OUT_OF_MEMORY; - else - return CURLE_FAILED_INIT; - } - - /* we start some action by calling perform right away */ - - do { - while(CURLM_CALL_MULTI_PERFORM == - curl_multi_perform(multi, &still_running)); - - if(!still_running) - break; - - FD_ZERO(&fdread); - FD_ZERO(&fdwrite); - FD_ZERO(&fdexcep); - - /* timeout once per second */ - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - /* Old deprecated style: get file descriptors from the transfers */ - curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); - rc = Curl_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); - - /* The way is to extract the sockets and wait for them without using - select. This whole alternative version should probably rather use the - curl_multi_socket() approach. */ - - if(rc == -1) - /* select error */ - break; - - /* timeout or data to send/receive => loop! */ - } while(still_running); - - msg = curl_multi_info_read(multi, &rc); - if(msg) - code = msg->data.result; - - mcode = curl_multi_remove_handle(multi, easy); - /* what to do if it fails? */ - - mcode = curl_multi_cleanup(multi); - /* what to do if it fails? */ - - return code; -} -#else -/* - * curl_easy_perform() is the external interface that performs a transfer - * previously setup. - */ -CURLcode curl_easy_perform(CURL *curl) -{ - struct SessionHandle *data = (struct SessionHandle *)curl; - - if(!data) - return CURLE_BAD_FUNCTION_ARGUMENT; - - if( ! (data->share && data->share->hostcache) ) { - /* this handle is not using a shared dns cache */ - - if(data->set.global_dns_cache && - (data->dns.hostcachetype != HCACHE_GLOBAL)) { - /* global dns cache was requested but still isn't */ - struct curl_hash *ptr; - - if(data->dns.hostcachetype == HCACHE_PRIVATE) { - /* if the current cache is private, kill it first */ - Curl_hash_destroy(data->dns.hostcache); - data->dns.hostcachetype = HCACHE_NONE; - data->dns.hostcache = NULL; - } - - ptr = Curl_global_host_cache_init(); - if(ptr) { - /* only do this if the global cache init works */ - data->dns.hostcache = ptr; - data->dns.hostcachetype = HCACHE_GLOBAL; - } - } - - if(!data->dns.hostcache) { - data->dns.hostcachetype = HCACHE_PRIVATE; - data->dns.hostcache = Curl_mk_dnscache(); - - if(!data->dns.hostcache) - /* While we possibly could survive and do good without a host cache, - the fact that creating it failed indicates that things are truly - screwed up and we should bail out! */ - return CURLE_OUT_OF_MEMORY; - } - - } - - if(!data->state.connc) { - /* oops, no connection cache, make one up */ - data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1L); - if(!data->state.connc) - return CURLE_OUT_OF_MEMORY; - } - - return Curl_perform(data); -} -#endif - -/* - * curl_easy_cleanup() is the external interface to cleaning/freeing the given - * easy handle. - */ -void curl_easy_cleanup(CURL *curl) -{ - struct SessionHandle *data = (struct SessionHandle *)curl; - - if(!data) - return; - - Curl_close(data); -} - -/* - * Store a pointed to the multi handle within the easy handle's data struct. - */ -void Curl_easy_addmulti(struct SessionHandle *data, - void *multi) -{ - data->multi = multi; - if(multi == NULL) - /* the association is cleared, mark the easy handle as not used by an - interface */ - data->state.used_interface = Curl_if_none; -} - -void Curl_easy_initHandleData(struct SessionHandle *data) -{ - memset(&data->req, 0, sizeof(struct SingleRequest)); - - data->req.maxdownload = -1; -} - -/* - * curl_easy_getinfo() is an external interface that allows an app to retrieve - * information from a performed transfer and similar. - */ -#undef curl_easy_getinfo -CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...) -{ - va_list arg; - void *paramp; - struct SessionHandle *data = (struct SessionHandle *)curl; - - va_start(arg, info); - paramp = va_arg(arg, void *); - - return Curl_getinfo(data, info, paramp); -} - -/* - * curl_easy_duphandle() is an external interface to allow duplication of a - * given input easy handle. The returned handle will be a new working handle - * with all options set exactly as the input source handle. - */ -CURL *curl_easy_duphandle(CURL *incurl) -{ - struct SessionHandle *data=(struct SessionHandle *)incurl; - - struct SessionHandle *outcurl = calloc(1, sizeof(struct SessionHandle)); - if(NULL == outcurl) - goto fail; - - /* - * We setup a few buffers we need. We should probably make them - * get setup on-demand in the code, as that would probably decrease - * the likeliness of us forgetting to init a buffer here in the future. - */ - outcurl->state.headerbuff = malloc(HEADERSIZE); - if(!outcurl->state.headerbuff) - goto fail; - outcurl->state.headersize = HEADERSIZE; - - /* copy all userdefined values */ - if(Curl_dupset(outcurl, data) != CURLE_OK) - goto fail; - - /* the connection cache is setup on demand */ - outcurl->state.connc = NULL; - - outcurl->state.lastconnect = -1; - - outcurl->progress.flags = data->progress.flags; - outcurl->progress.callback = data->progress.callback; - - if(data->cookies) { - /* If cookies are enabled in the parent handle, we enable them - in the clone as well! */ - outcurl->cookies = Curl_cookie_init(data, - data->cookies->filename, - outcurl->cookies, - data->set.cookiesession); - if(!outcurl->cookies) - goto fail; - } - - /* duplicate all values in 'change' */ - if(data->change.cookielist) { - outcurl->change.cookielist = - Curl_slist_duplicate(data->change.cookielist); - if(!outcurl->change.cookielist) - goto fail; - } - - if(data->change.url) { - outcurl->change.url = strdup(data->change.url); - if(!outcurl->change.url) - goto fail; - outcurl->change.url_alloc = TRUE; - } - - if(data->change.referer) { - outcurl->change.referer = strdup(data->change.referer); - if(!outcurl->change.referer) - goto fail; - outcurl->change.referer_alloc = TRUE; - } - -#ifdef USE_ARES - /* If we use ares, we clone the ares channel for the new handle */ - if(ARES_SUCCESS != ares_dup(&outcurl->state.areschannel, - data->state.areschannel)) - goto fail; -#endif - - Curl_convert_setup(outcurl); - - Curl_easy_initHandleData(outcurl); - - outcurl->magic = CURLEASY_MAGIC_NUMBER; - - /* we reach this point and thus we are OK */ - - return outcurl; - - fail: - - if(outcurl) { - if(outcurl->state.connc && - (outcurl->state.connc->type == CONNCACHE_PRIVATE)) - Curl_rm_connc(outcurl->state.connc); - if(outcurl->state.headerbuff) - free(outcurl->state.headerbuff); - if(outcurl->change.cookielist) - curl_slist_free_all(outcurl->change.cookielist); - if(outcurl->change.url) - free(outcurl->change.url); - if(outcurl->change.referer) - free(outcurl->change.referer); - Curl_freeset(outcurl); - free(outcurl); - } - - return NULL; -} - -/* - * curl_easy_reset() is an external interface that allows an app to re- - * initialize a session handle to the default values. - */ -void curl_easy_reset(CURL *curl) -{ - struct SessionHandle *data = (struct SessionHandle *)curl; - - Curl_safefree(data->state.pathbuffer); - data->state.pathbuffer=NULL; - - Curl_safefree(data->state.proto.generic); - data->state.proto.generic=NULL; - - /* zero out UserDefined data: */ - Curl_freeset(data); - memset(&data->set, 0, sizeof(struct UserDefined)); - (void)Curl_init_userdefined(&data->set); - - /* zero out Progress data: */ - memset(&data->progress, 0, sizeof(struct Progress)); - - /* init Handle data */ - Curl_easy_initHandleData(data); - - data->progress.flags |= PGRS_HIDE; - data->state.current_speed = -1; /* init to negative == impossible */ -} - -/* - * curl_easy_pause() allows an application to pause or unpause a specific - * transfer and direction. This function sets the full new state for the - * current connection this easy handle operates on. - * - * NOTE: if you have the receiving paused and you call this function to remove - * the pausing, you may get your write callback called at this point. - * - * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h - */ -CURLcode curl_easy_pause(CURL *curl, int action) -{ - struct SessionHandle *data = (struct SessionHandle *)curl; - struct SingleRequest *k = &data->req; - CURLcode result = CURLE_OK; - - /* first switch off both pause bits */ - int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE); - - /* set the new desired pause bits */ - newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) | - ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0); - - /* put it back in the keepon */ - k->keepon = newstate; - - if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) { - /* we have a buffer for sending that we now seem to be able to deliver since - the receive pausing is lifted! */ - - /* get the pointer, type and length in local copies since the function may - return PAUSE again and then we'll get a new copy allocted and stored in - the tempwrite variables */ - char *tempwrite = data->state.tempwrite; - char *freewrite = tempwrite; /* store this pointer to free it later */ - size_t tempsize = data->state.tempwritesize; - int temptype = data->state.tempwritetype; - size_t chunklen; - - /* clear tempwrite here just to make sure it gets cleared if there's no - further use of it, and make sure we don't clear it after the function - invoke as it may have been set to a new value by then */ - data->state.tempwrite = NULL; - - /* since the write callback API is define to never exceed - CURL_MAX_WRITE_SIZE bytes in a single call, and since we may in fact - have more data than that in our buffer here, we must loop sending the - data in multiple calls until there's no data left or we get another - pause returned. - - A tricky part is that the function we call will "buffer" the data - itself when it pauses on a particular buffer, so we may need to do some - extra trickery if we get a pause return here. - */ - do { - chunklen = (tempsize > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:tempsize; - - result = Curl_client_write(data->state.current_conn, - temptype, tempwrite, chunklen); - if(result) - /* failures abort the loop at once */ - break; - - if(data->state.tempwrite && (tempsize - chunklen)) { - /* Ouch, the reading is again paused and the block we send is now - "cached". If this is the final chunk we can leave it like this, but - if we have more chunks that are cached after this, we need to free - the newly cached one and put back a version that is truly the entire - contents that is saved for later - */ - char *newptr; - - /* note that tempsize is still the size as before the callback was - used, and thus the whole piece of data to keep */ - newptr = realloc(data->state.tempwrite, tempsize); - - if(!newptr) { - free(data->state.tempwrite); /* free old area */ - data->state.tempwrite = NULL; - result = CURLE_OUT_OF_MEMORY; - /* tempwrite will be freed further down */ - break; - } - data->state.tempwrite = newptr; /* store new pointer */ - memcpy(newptr, tempwrite, tempsize); - data->state.tempwritesize = tempsize; /* store new size */ - /* tempwrite will be freed further down */ - break; /* go back to pausing until further notice */ - } - else { - tempsize -= chunklen; /* left after the call above */ - tempwrite += chunklen; /* advance the pointer */ - } - - } while((result == CURLE_OK) && tempsize); - - free(freewrite); /* this is unconditionally no longer used */ - } - - return result; -} - - -static CURLcode easy_connection(struct SessionHandle *data, - curl_socket_t *sfd, - struct connectdata **connp) -{ - if(data == NULL) - return CURLE_BAD_FUNCTION_ARGUMENT; - - /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ - if(!data->set.connect_only) { - failf(data, "CONNECT_ONLY is required!"); - return CURLE_UNSUPPORTED_PROTOCOL; - } - - *sfd = Curl_getconnectinfo(data, connp); - - if(*sfd == CURL_SOCKET_BAD) { - failf(data, "Failed to get recent socket"); - return CURLE_UNSUPPORTED_PROTOCOL; - } - - return CURLE_OK; -} - -/* - * Receives data from the connected socket. Use after successful - * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. - * Returns CURLE_OK on success, error code on error. - */ -CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n) -{ - curl_socket_t sfd; - CURLcode ret; - ssize_t n1; - struct connectdata *c; - struct SessionHandle *data = (struct SessionHandle *)curl; - - ret = easy_connection(data, &sfd, &c); - if(ret) - return ret; - - *n = 0; - ret = Curl_read(c, sfd, buffer, buflen, &n1); - - if(ret != CURLE_OK) - return ret; - - *n = (size_t)n1; - - return CURLE_OK; -} - -/* - * Sends data over the connected socket. Use after successful - * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. - */ -CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen, - size_t *n) -{ - curl_socket_t sfd; - CURLcode ret; - ssize_t n1; - struct connectdata *c = NULL; - struct SessionHandle *data = (struct SessionHandle *)curl; - - ret = easy_connection(data, &sfd, &c); - if(ret) - return ret; - - *n = 0; - ret = Curl_write(c, sfd, buffer, buflen, &n1); - - if(n1 == -1) - return CURLE_SEND_ERROR; - - /* detect EAGAIN */ - if((CURLE_OK == ret) && (0 == n1)) - return CURLE_AGAIN; - - *n = (size_t)n1; - - return ret; -} diff --git a/third_party/curl/lib/easyif.h b/third_party/curl/lib/easyif.h deleted file mode 100644 index d05b7d610..000000000 --- a/third_party/curl/lib/easyif.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __EASYIF_H -#define __EASYIF_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Prototypes for library-wide functions provided by easy.c - */ -void Curl_easy_addmulti(struct SessionHandle *data, void *multi); - -void Curl_easy_initHandleData(struct SessionHandle *data); - -#endif /* __EASYIF_H */ diff --git a/third_party/curl/lib/escape.c b/third_party/curl/lib/escape.c deleted file mode 100644 index 4e8dd6e4c..000000000 --- a/third_party/curl/lib/escape.c +++ /dev/null @@ -1,196 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* Escape and unescape URL encoding in strings. The functions return a new - * allocated string or NULL if an error occurred. */ - -#include "setup.h" -#include -#include - -#include -#include -#include -#include "curl_memory.h" -#include "urldata.h" -#include "warnless.h" -#include "non-ascii.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -/* Portable character check (remember EBCDIC). Do not use isalnum() because - its behavior is altered by the current locale. - See http://tools.ietf.org/html/rfc3986#section-2.3 -*/ -static bool Curl_isunreserved(unsigned char in) -{ - switch (in) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'L': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': - case '-': case '.': case '_': case '~': - return TRUE; - default: - break; - } - return FALSE; -} - -/* for ABI-compatibility with previous versions */ -char *curl_escape(const char *string, int inlength) -{ - return curl_easy_escape(NULL, string, inlength); -} - -/* for ABI-compatibility with previous versions */ -char *curl_unescape(const char *string, int length) -{ - return curl_easy_unescape(NULL, string, length, NULL); -} - -char *curl_easy_escape(CURL *handle, const char *string, int inlength) -{ - size_t alloc = (inlength?(size_t)inlength:strlen(string))+1; - char *ns; - char *testing_ptr = NULL; - unsigned char in; /* we need to treat the characters unsigned */ - size_t newlen = alloc; - int strindex=0; - size_t length; - - ns = malloc(alloc); - if(!ns) - return NULL; - - length = alloc-1; - while(length--) { - in = *string; - - if (Curl_isunreserved(in)) { - /* just copy this */ - ns[strindex++]=in; - } - else { - /* encode it */ - newlen += 2; /* the size grows with two, since this'll become a %XX */ - if(newlen > alloc) { - alloc *= 2; - testing_ptr = realloc(ns, alloc); - if(!testing_ptr) { - free( ns ); - return NULL; - } - else { - ns = testing_ptr; - } - } - - if(Curl_convert_to_network(handle, &in, 1)) { - /* Curl_convert_to_network calls failf if unsuccessful */ - free(ns); - return NULL; - } - - snprintf(&ns[strindex], 4, "%%%02X", in); - - strindex+=3; - } - string++; - } - ns[strindex]=0; /* terminate it */ - return ns; -} - -/* - * Unescapes the given URL escaped string of given length. Returns a - * pointer to a malloced string with length given in *olen. - * If length == 0, the length is assumed to be strlen(string). - * If olen == NULL, no output length is stored. - */ -char *curl_easy_unescape(CURL *handle, const char *string, int length, - int *olen) -{ - int alloc = (length?length:(int)strlen(string))+1; - char *ns = malloc(alloc); - unsigned char in; - int strindex=0; - unsigned long hex; - - if(!ns) - return NULL; - - while(--alloc > 0) { - in = *string; - if(('%' == in) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { - /* this is two hexadecimal digits following a '%' */ - char hexstr[3]; - char *ptr; - hexstr[0] = string[1]; - hexstr[1] = string[2]; - hexstr[2] = 0; - - hex = strtoul(hexstr, &ptr, 16); - - in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */ - - if(Curl_convert_from_network(handle, &in, 1)) { - /* Curl_convert_from_network calls failf if unsuccessful */ - free(ns); - return NULL; - } - - string+=2; - alloc-=2; - } - - ns[strindex++] = in; - string++; - } - ns[strindex]=0; /* terminate it */ - - if(olen) - /* store output size */ - *olen = strindex; - return ns; -} - -/* For operating systems/environments that use different malloc/free - systems for the app and for this library, we provide a free that uses - the library's memory system */ -void curl_free(void *p) -{ - if(p) - free(p); -} diff --git a/third_party/curl/lib/escape.h b/third_party/curl/lib/escape.h deleted file mode 100644 index 04b06a973..000000000 --- a/third_party/curl/lib/escape.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __ESCAPE_H -#define __ESCAPE_H - -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -/* Escape and unescape URL encoding in strings. The functions return a new - * allocated string or NULL if an error occurred. */ - - -#endif diff --git a/third_party/curl/lib/file.c b/third_party/curl/lib/file.c deleted file mode 100644 index ad671233c..000000000 --- a/third_party/curl/lib/file.c +++ /dev/null @@ -1,591 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef CURL_DISABLE_FILE -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#include -#include -#else -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#endif - -#endif /* WIN32 */ - -#include "strtoofft.h" -#include "urldata.h" -#include -#include "progress.h" -#include "sendf.h" -#include "escape.h" -#include "file.h" -#include "speedcheck.h" -#include "getinfo.h" -#include "transfer.h" -#include "url.h" -#include "curl_memory.h" -#include "parsedate.h" /* for the week day and month names */ - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) || defined(__SYMBIAN32__) -#define DOS_FILESYSTEM 1 -#endif - -#ifdef OPEN_NEEDS_ARG3 -# define open_readonly(p,f) open((p),(f),(0)) -#else -# define open_readonly(p,f) open((p),(f)) -#endif - -/* - * Forward declarations. - */ - -static CURLcode file_do(struct connectdata *, bool *done); -static CURLcode file_done(struct connectdata *conn, - CURLcode status, bool premature); -static CURLcode file_connect(struct connectdata *conn, bool *done); - -/* - * FILE scheme handler. - */ - -const struct Curl_handler Curl_handler_file = { - "FILE", /* scheme */ - ZERO_NULL, /* setup_connection */ - file_do, /* do_it */ - file_done, /* done */ - ZERO_NULL, /* do_more */ - file_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - 0, /* defport */ - CURLPROTO_FILE, /* protocol */ - PROTOPT_BANPROXY /* flags */ -}; - - - /* - Check if this is a range download, and if so, set the internal variables - properly. This code is copied from the FTP implementation and might as - well be factored out. - */ -static CURLcode file_range(struct connectdata *conn) -{ - curl_off_t from, to; - curl_off_t totalsize=-1; - char *ptr; - char *ptr2; - struct SessionHandle *data = conn->data; - - if(data->state.use_range && data->state.range) { - from=curlx_strtoofft(data->state.range, &ptr, 0); - while(*ptr && (ISSPACE(*ptr) || (*ptr=='-'))) - ptr++; - to=curlx_strtoofft(ptr, &ptr2, 0); - if(ptr == ptr2) { - /* we didn't get any digit */ - to=-1; - } - if((-1 == to) && (from>=0)) { - /* X - */ - data->state.resume_from = from; - DEBUGF(infof(data, "RANGE %" FORMAT_OFF_T " to end of file\n", - from)); - } - else if(from < 0) { - /* -Y */ - data->req.maxdownload = -from; - data->state.resume_from = from; - DEBUGF(infof(data, "RANGE the last %" FORMAT_OFF_T " bytes\n", - -from)); - } - else { - /* X-Y */ - totalsize = to-from; - data->req.maxdownload = totalsize+1; /* include last byte */ - data->state.resume_from = from; - DEBUGF(infof(data, "RANGE from %" FORMAT_OFF_T - " getting %" FORMAT_OFF_T " bytes\n", - from, data->req.maxdownload)); - } - DEBUGF(infof(data, "range-download from %" FORMAT_OFF_T - " to %" FORMAT_OFF_T ", totally %" FORMAT_OFF_T " bytes\n", - from, to, data->req.maxdownload)); - } - else - data->req.maxdownload = -1; - return CURLE_OK; -} - -/* - * file_connect() gets called from Curl_protocol_connect() to allow us to - * do protocol-specific actions at connect-time. We emulate a - * connect-then-transfer protocol and "connect" to the file here - */ -static CURLcode file_connect(struct connectdata *conn, bool *done) -{ - struct SessionHandle *data = conn->data; - char *real_path = curl_easy_unescape(data, data->state.path, 0, NULL); - struct FILEPROTO *file; - int fd; -#ifdef DOS_FILESYSTEM - int i; - char *actual_path; -#endif - - if(!real_path) - return CURLE_OUT_OF_MEMORY; - - /* If there already is a protocol-specific struct allocated for this - sessionhandle, deal with it */ - Curl_reset_reqproto(conn); - - if(!data->state.proto.file) { - file = calloc(1, sizeof(struct FILEPROTO)); - if(!file) { - free(real_path); - return CURLE_OUT_OF_MEMORY; - } - data->state.proto.file = file; - } - else { - /* file is not a protocol that can deal with "persistancy" */ - file = data->state.proto.file; - Curl_safefree(file->freepath); - if(file->fd != -1) - close(file->fd); - file->path = NULL; - file->freepath = NULL; - file->fd = -1; - } - -#ifdef DOS_FILESYSTEM - /* If the first character is a slash, and there's - something that looks like a drive at the beginning of - the path, skip the slash. If we remove the initial - slash in all cases, paths without drive letters end up - relative to the current directory which isn't how - browsers work. - - Some browsers accept | instead of : as the drive letter - separator, so we do too. - - On other platforms, we need the slash to indicate an - absolute pathname. On Windows, absolute paths start - with a drive letter. - */ - actual_path = real_path; - if((actual_path[0] == '/') && - actual_path[1] && - (actual_path[2] == ':' || actual_path[2] == '|')) - { - actual_path[2] = ':'; - actual_path++; - } - - /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */ - for (i=0; actual_path[i] != '\0'; ++i) - if(actual_path[i] == '/') - actual_path[i] = '\\'; - - fd = open_readonly(actual_path, O_RDONLY|O_BINARY); /* no CR/LF translation */ - file->path = actual_path; -#else - fd = open_readonly(real_path, O_RDONLY); - file->path = real_path; -#endif - file->freepath = real_path; /* free this when done */ - - file->fd = fd; - if(!data->set.upload && (fd == -1)) { - failf(data, "Couldn't open file %s", data->state.path); - file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE); - return CURLE_FILE_COULDNT_READ_FILE; - } - *done = TRUE; - - return CURLE_OK; -} - -static CURLcode file_done(struct connectdata *conn, - CURLcode status, bool premature) -{ - struct FILEPROTO *file = conn->data->state.proto.file; - (void)status; /* not used */ - (void)premature; /* not used */ - Curl_safefree(file->freepath); - - if(file->fd != -1) - close(file->fd); - - return CURLE_OK; -} - -#ifdef DOS_FILESYSTEM -#define DIRSEP '\\' -#else -#define DIRSEP '/' -#endif - -static CURLcode file_upload(struct connectdata *conn) -{ - struct FILEPROTO *file = conn->data->state.proto.file; - const char *dir = strchr(file->path, DIRSEP); - FILE *fp; - CURLcode res=CURLE_OK; - struct SessionHandle *data = conn->data; - char *buf = data->state.buffer; - size_t nread; - size_t nwrite; - curl_off_t bytecount = 0; - struct timeval now = Curl_tvnow(); - struct_stat file_stat; - const char* buf2; - - /* - * Since FILE: doesn't do the full init, we need to provide some extra - * assignments here. - */ - conn->fread_func = data->set.fread_func; - conn->fread_in = data->set.in; - conn->data->req.upload_fromhere = buf; - - if(!dir) - return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ - - if(!dir[1]) - return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ - - if(data->state.resume_from) - fp = fopen( file->path, "ab" ); - else { - int fd; - -#ifdef DOS_FILESYSTEM - fd = open(file->path, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, - conn->data->set.new_file_perms); -#else - fd = open(file->path, O_WRONLY|O_CREAT|O_TRUNC, - conn->data->set.new_file_perms); -#endif - if(fd < 0) { - failf(data, "Can't open %s for writing", file->path); - return CURLE_WRITE_ERROR; - } - close(fd); - fp = fopen(file->path, "wb"); - } - - if(!fp) { - failf(data, "Can't open %s for writing", file->path); - return CURLE_WRITE_ERROR; - } - - if(-1 != data->set.infilesize) - /* known size of data to "upload" */ - Curl_pgrsSetUploadSize(data, data->set.infilesize); - - /* treat the negative resume offset value as the case of "-" */ - if(data->state.resume_from < 0) { - if(fstat(fileno(fp), &file_stat)) { - fclose(fp); - failf(data, "Can't get the size of %s", file->path); - return CURLE_WRITE_ERROR; - } - else - data->state.resume_from = (curl_off_t)file_stat.st_size; - } - - while(res == CURLE_OK) { - int readcount; - res = Curl_fillreadbuffer(conn, BUFSIZE, &readcount); - if(res) - break; - - if(readcount <= 0) /* fix questionable compare error. curlvms */ - break; - - nread = (size_t)readcount; - - /*skip bytes before resume point*/ - if(data->state.resume_from) { - if( (curl_off_t)nread <= data->state.resume_from ) { - data->state.resume_from -= nread; - nread = 0; - buf2 = buf; - } - else { - buf2 = buf + data->state.resume_from; - nread -= (size_t)data->state.resume_from; - data->state.resume_from = 0; - } - } - else - buf2 = buf; - - /* write the data to the target */ - nwrite = fwrite(buf2, 1, nread, fp); - if(nwrite != nread) { - res = CURLE_SEND_ERROR; - break; - } - - bytecount += nread; - - Curl_pgrsSetUploadCounter(data, bytecount); - - if(Curl_pgrsUpdate(conn)) - res = CURLE_ABORTED_BY_CALLBACK; - else - res = Curl_speedcheck(data, now); - } - if(!res && Curl_pgrsUpdate(conn)) - res = CURLE_ABORTED_BY_CALLBACK; - - fclose(fp); - - return res; -} - -/* - * file_do() is the protocol-specific function for the do-phase, separated - * from the connect-phase above. Other protocols merely setup the transfer in - * the do-phase, to have it done in the main transfer loop but since some - * platforms we support don't allow select()ing etc on file handles (as - * opposed to sockets) we instead perform the whole do-operation in this - * function. - */ -static CURLcode file_do(struct connectdata *conn, bool *done) -{ - /* This implementation ignores the host name in conformance with - RFC 1738. Only local files (reachable via the standard file system) - are supported. This means that files on remotely mounted directories - (via NFS, Samba, NT sharing) can be accessed through a file:// URL - */ - CURLcode res = CURLE_OK; - struct_stat statbuf; /* struct_stat instead of struct stat just to allow the - Windows version to have a different struct without - having to redefine the simple word 'stat' */ - curl_off_t expected_size=0; - bool fstated=FALSE; - ssize_t nread; - size_t bytestoread; - struct SessionHandle *data = conn->data; - char *buf = data->state.buffer; - curl_off_t bytecount = 0; - int fd; - struct timeval now = Curl_tvnow(); - - *done = TRUE; /* unconditionally */ - - Curl_initinfo(data); - Curl_pgrsStartNow(data); - - if(data->set.upload) - return file_upload(conn); - - /* get the fd from the connection phase */ - fd = conn->data->state.proto.file->fd; - - /* VMS: This only works reliable for STREAMLF files */ - if( -1 != fstat(fd, &statbuf)) { - /* we could stat it, then read out the size */ - expected_size = statbuf.st_size; - /* and store the modification time */ - data->info.filetime = (long)statbuf.st_mtime; - fstated = TRUE; - } - - if(fstated && !data->state.range && data->set.timecondition) { - if(!Curl_meets_timecondition(data, (time_t)data->info.filetime)) { - *done = TRUE; - return CURLE_OK; - } - } - - /* If we have selected NOBODY and HEADER, it means that we only want file - information. Which for FILE can't be much more than the file size and - date. */ - if(data->set.opt_no_body && data->set.include_header && fstated) { - CURLcode result; - snprintf(buf, sizeof(data->state.buffer), - "Content-Length: %" FORMAT_OFF_T "\r\n", expected_size); - result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); - if(result) - return result; - - result = Curl_client_write(conn, CLIENTWRITE_BOTH, - (char *)"Accept-ranges: bytes\r\n", 0); - if(result) - return result; - - if(fstated) { - time_t filetime = (time_t)statbuf.st_mtime; - struct tm buffer; - const struct tm *tm = &buffer; - result = Curl_gmtime(filetime, &buffer); - if(result) - return result; - - /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ - snprintf(buf, BUFSIZE-1, - "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", - Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], - tm->tm_mday, - Curl_month[tm->tm_mon], - tm->tm_year + 1900, - tm->tm_hour, - tm->tm_min, - tm->tm_sec); - result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); - } - /* if we fstat()ed the file, set the file size to make it available post- - transfer */ - if(fstated) - Curl_pgrsSetDownloadSize(data, expected_size); - return result; - } - - /* Check whether file range has been specified */ - file_range(conn); - - /* Adjust the start offset in case we want to get the N last bytes - * of the stream iff the filesize could be determined */ - if(data->state.resume_from < 0) { - if(!fstated) { - failf(data, "Can't get the size of file."); - return CURLE_READ_ERROR; - } - else - data->state.resume_from += (curl_off_t)statbuf.st_size; - } - - if(data->state.resume_from <= expected_size) - expected_size -= data->state.resume_from; - else { - failf(data, "failed to resume file:// transfer"); - return CURLE_BAD_DOWNLOAD_RESUME; - } - - /* A high water mark has been specified so we obey... */ - if (data->req.maxdownload > 0) - expected_size = data->req.maxdownload; - - if(fstated && (expected_size == 0)) - return CURLE_OK; - - /* The following is a shortcut implementation of file reading - this is both more efficient than the former call to download() and - it avoids problems with select() and recv() on file descriptors - in Winsock */ - if(fstated) - Curl_pgrsSetDownloadSize(data, expected_size); - - if(data->state.resume_from) { - if(data->state.resume_from != - lseek(fd, data->state.resume_from, SEEK_SET)) - return CURLE_BAD_DOWNLOAD_RESUME; - } - - Curl_pgrsTime(data, TIMER_STARTTRANSFER); - - while(res == CURLE_OK) { - /* Don't fill a whole buffer if we want less than all data */ - bytestoread = (expected_size < BUFSIZE-1)?(size_t)expected_size:BUFSIZE-1; - nread = read(fd, buf, bytestoread); - - if( nread > 0) - buf[nread] = 0; - - if (nread <= 0 || expected_size == 0) - break; - - bytecount += nread; - expected_size -= nread; - - res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread); - if(res) - return res; - - Curl_pgrsSetDownloadCounter(data, bytecount); - - if(Curl_pgrsUpdate(conn)) - res = CURLE_ABORTED_BY_CALLBACK; - else - res = Curl_speedcheck(data, now); - } - if(Curl_pgrsUpdate(conn)) - res = CURLE_ABORTED_BY_CALLBACK; - - return res; -} - -#endif diff --git a/third_party/curl/lib/file.h b/third_party/curl/lib/file.h deleted file mode 100644 index 5e3bd7564..000000000 --- a/third_party/curl/lib/file.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __FILE_H -#define __FILE_H - -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - - -/**************************************************************************** - * FILE unique setup - ***************************************************************************/ -struct FILEPROTO { - char *path; /* the path we operate on */ - char *freepath; /* pointer to the allocated block we must free, this might - differ from the 'path' pointer */ - int fd; /* open file descriptor to read from! */ -}; - -#ifndef CURL_DISABLE_FILE -extern const struct Curl_handler Curl_handler_file; -#endif -#endif diff --git a/third_party/curl/lib/fileinfo.c b/third_party/curl/lib/fileinfo.c deleted file mode 100644 index f5dbfce4b..000000000 --- a/third_party/curl/lib/fileinfo.c +++ /dev/null @@ -1,75 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include "strdup.h" -#include "fileinfo.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -struct curl_fileinfo *Curl_fileinfo_alloc(void) -{ - struct curl_fileinfo *tmp = malloc(sizeof(struct curl_fileinfo)); - if(!tmp) - return NULL; - memset(tmp, 0, sizeof(struct curl_fileinfo)); - return tmp; -} - -void Curl_fileinfo_dtor(void *user, void *element) -{ - struct curl_fileinfo *finfo = element; - (void) user; - if(!finfo) - return; - - if(finfo->b_data){ - free(finfo->b_data); - } - - free(finfo); -} - -struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src) -{ - struct curl_fileinfo *ptr = malloc(sizeof(struct curl_fileinfo)); - if(!ptr) - return NULL; - *ptr = *src; - - ptr->b_data = malloc(src->b_size); - if(!ptr->b_data) { - free(ptr); - return NULL; - } - else { - memcpy(ptr->b_data, src->b_data, src->b_size); - return ptr; - } -} diff --git a/third_party/curl/lib/fileinfo.h b/third_party/curl/lib/fileinfo.h deleted file mode 100644 index b0e5e59e1..000000000 --- a/third_party/curl/lib/fileinfo.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef HEADER_CURL_FILEINFO_H -#define HEADER_CURL_FILEINFO_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 - -struct curl_fileinfo *Curl_fileinfo_alloc(void); - -void Curl_fileinfo_dtor(void *, void *); - -struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src); - -#endif /* HEADER_CURL_FILEINFO_H */ diff --git a/third_party/curl/lib/formdata.c b/third_party/curl/lib/formdata.c deleted file mode 100644 index f221ae966..000000000 --- a/third_party/curl/lib/formdata.c +++ /dev/null @@ -1,1701 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - Debug the form generator stand-alone by compiling this source file with: - - gcc -DHAVE_CONFIG_H -I../ -g -D_FORM_DEBUG -DCURLDEBUG -o formdata \ - -I../include formdata.c strequal.c memdebug.c mprintf.c strerror.c - - (depending on circumstances you may need further externals added) - - run the 'formdata' executable the output should end with: - All Tests seem to have worked ... - and the following parts should be there: - -Content-Disposition: form-data; name="simple_COPYCONTENTS" -value for simple COPYCONTENTS - -Content-Disposition: form-data; name="COPYCONTENTS_+_CONTENTTYPE" -Content-Type: image/gif -value for COPYCONTENTS + CONTENTTYPE - -Content-Disposition: form-data; name="PRNAME_+_NAMELENGTH_+_COPYNAME_+_CONTENTSLENGTH" -vlue for PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH -(or you might see P^@RNAME and v^@lue at the start) - -Content-Disposition: form-data; name="simple_PTRCONTENTS" -value for simple PTRCONTENTS - -Content-Disposition: form-data; name="PTRCONTENTS_+_CONTENTSLENGTH" -vlue for PTRCONTENTS + CONTENTSLENGTH -(or you might see v^@lue at the start) - -Content-Disposition: form-data; name="PTRCONTENTS_+_CONTENTSLENGTH_+_CONTENTTYPE" -Content-Type: application/octet-stream -vlue for PTRCONTENTS + CONTENTSLENGTH + CONTENTTYPE -(or you might see v^@lue at the start) - -Content-Disposition: form-data; name="FILE1_+_CONTENTTYPE"; filename="formdata.h" -Content-Type: text/html -... - -Content-Disposition: form-data; name="FILE1_+_FILE2" -Content-Type: multipart/mixed, boundary=curlz1s0dkticx49MV1KGcYP5cvfSsz -... -Content-Disposition: attachment; filename="formdata.h" -Content-Type: application/octet-stream -... -Content-Disposition: attachment; filename="Makefile.b32" -Content-Type: application/octet-stream -... - -Content-Disposition: form-data; name="FILE1_+_FILE2_+_FILE3" -Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1 -... -Content-Disposition: attachment; filename="formdata.h" -Content-Type: application/octet-stream -... -Content-Disposition: attachment; filename="Makefile.b32" -Content-Type: application/octet-stream -... -Content-Disposition: attachment; filename="formdata.h" -Content-Type: application/octet-stream -... - - -Content-Disposition: form-data; name="ARRAY: FILE1_+_FILE2_+_FILE3" -Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1 -... -Content-Disposition: attachment; filename="formdata.h" -Content-Type: application/octet-stream -... -Content-Disposition: attachment; filename="Makefile.b32" -Content-Type: application/octet-stream -... -Content-Disposition: attachment; filename="formdata.h" -Content-Type: application/octet-stream -... - -Content-Disposition: form-data; name="FILECONTENT" -... - - */ - -#include "setup.h" -#include - -/* Length of the random boundary string. */ -#define BOUNDARY_LENGTH 40 - -#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) - -#include -#include -#include -#include -#include -#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) -#include -#endif -#include "urldata.h" /* for struct SessionHandle */ -#include "formdata.h" -#include "curl_rand.h" -#include "strequal.h" -#include "curl_memory.h" -#include "sendf.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -#endif /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */ - -#ifndef CURL_DISABLE_HTTP - -#ifndef HAVE_BASENAME -static char *Curl_basename(char *path); -#define basename(x) Curl_basename((x)) -#endif - -static size_t readfromfile(struct Form *form, char *buffer, size_t size); - -/* What kind of Content-Type to use on un-specified files with unrecognized - extensions. */ -#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream" - -#define FORM_FILE_SEPARATOR ',' -#define FORM_TYPE_SEPARATOR ';' - -/*************************************************************************** - * - * AddHttpPost() - * - * Adds a HttpPost structure to the list, if parent_post is given becomes - * a subpost of parent_post instead of a direct list element. - * - * Returns newly allocated HttpPost on success and NULL if malloc failed. - * - ***************************************************************************/ -static struct curl_httppost * -AddHttpPost(char *name, size_t namelength, - char *value, size_t contentslength, - char *buffer, size_t bufferlength, - char *contenttype, - long flags, - struct curl_slist* contentHeader, - char *showfilename, char *userp, - struct curl_httppost *parent_post, - struct curl_httppost **httppost, - struct curl_httppost **last_post) -{ - struct curl_httppost *post; - post = calloc(1, sizeof(struct curl_httppost)); - if(post) { - post->name = name; - post->namelength = (long)(name?(namelength?namelength:strlen(name)):0); - post->contents = value; - post->contentslength = (long)contentslength; - post->buffer = buffer; - post->bufferlength = (long)bufferlength; - post->contenttype = contenttype; - post->contentheader = contentHeader; - post->showfilename = showfilename; - post->userp = userp, - post->flags = flags; - } - else - return NULL; - - if(parent_post) { - /* now, point our 'more' to the original 'more' */ - post->more = parent_post->more; - - /* then move the original 'more' to point to ourselves */ - parent_post->more = post; - } - else { - /* make the previous point to this */ - if(*last_post) - (*last_post)->next = post; - else - (*httppost) = post; - - (*last_post) = post; - } - return post; -} - -/*************************************************************************** - * - * AddFormInfo() - * - * Adds a FormInfo structure to the list presented by parent_form_info. - * - * Returns newly allocated FormInfo on success and NULL if malloc failed/ - * parent_form_info is NULL. - * - ***************************************************************************/ -static FormInfo * AddFormInfo(char *value, - char *contenttype, - FormInfo *parent_form_info) -{ - FormInfo *form_info; - form_info = calloc(1, sizeof(struct FormInfo)); - if(form_info) { - if(value) - form_info->value = value; - if(contenttype) - form_info->contenttype = contenttype; - form_info->flags = HTTPPOST_FILENAME; - } - else - return NULL; - - if(parent_form_info) { - /* now, point our 'more' to the original 'more' */ - form_info->more = parent_form_info->more; - - /* then move the original 'more' to point to ourselves */ - parent_form_info->more = form_info; - } - else - return NULL; - - return form_info; -} - -/*************************************************************************** - * - * ContentTypeForFilename() - * - * Provides content type for filename if one of the known types (else - * (either the prevtype or the default is returned). - * - * Returns some valid contenttype for filename. - * - ***************************************************************************/ -static const char * ContentTypeForFilename (const char *filename, - const char *prevtype) -{ - const char *contenttype = NULL; - unsigned int i; - /* - * No type was specified, we scan through a few well-known - * extensions and pick the first we match! - */ - struct ContentType { - char extension[6]; - const char *type; - }; - static const struct ContentType ctts[]={ - {".gif", "image/gif"}, - {".jpg", "image/jpeg"}, - {".jpeg", "image/jpeg"}, - {".txt", "text/plain"}, - {".html", "text/html"}, - {".xml", "application/xml"} - }; - - if(prevtype) - /* default to the previously set/used! */ - contenttype = prevtype; - else - contenttype = HTTPPOST_CONTENTTYPE_DEFAULT; - - if(filename) { /* in case a NULL was passed in */ - for(i=0; i= strlen(ctts[i].extension)) { - if(strequal(filename + - strlen(filename) - strlen(ctts[i].extension), - ctts[i].extension)) { - contenttype = ctts[i].type; - break; - } - } - } - } - /* we have a contenttype by now */ - return contenttype; -} - -/*************************************************************************** - * - * memdup() - * - * Copies the 'source' data to a newly allocated buffer buffer (that is - * returned). Uses buffer_length if not null, else uses strlen to determine - * the length of the buffer to be copied - * - * Returns the new pointer or NULL on failure. - * - ***************************************************************************/ -static char *memdup(const char *src, size_t buffer_length) -{ - size_t length; - bool add = FALSE; - char *buffer; - - if(buffer_length) - length = buffer_length; - else if(src) { - length = strlen(src); - add = TRUE; - } - else - /* no length and a NULL src pointer! */ - return strdup(""); - - buffer = malloc(length+add); - if(!buffer) - return NULL; /* fail */ - - memcpy(buffer, src, length); - - /* if length unknown do null termination */ - if(add) - buffer[length] = '\0'; - - return buffer; -} - -/*************************************************************************** - * - * FormAdd() - * - * Stores a formpost parameter and builds the appropriate linked list. - * - * Has two principal functionalities: using files and byte arrays as - * post parts. Byte arrays are either copied or just the pointer is stored - * (as the user requests) while for files only the filename and not the - * content is stored. - * - * While you may have only one byte array for each name, multiple filenames - * are allowed (and because of this feature CURLFORM_END is needed after - * using CURLFORM_FILE). - * - * Examples: - * - * Simple name/value pair with copied contents: - * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", - * CURLFORM_COPYCONTENTS, "value", CURLFORM_END); - * - * name/value pair where only the content pointer is remembered: - * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", - * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END); - * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used) - * - * storing a filename (CONTENTTYPE is optional!): - * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", - * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text", - * CURLFORM_END); - * - * storing multiple filenames: - * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", - * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END); - * - * Returns: - * CURL_FORMADD_OK on success - * CURL_FORMADD_MEMORY if the FormInfo allocation fails - * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form - * CURL_FORMADD_NULL if a null pointer was given for a char - * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed - * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used - * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or an error) - * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated - * CURL_FORMADD_MEMORY if some allocation for string copying failed. - * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array - * - ***************************************************************************/ - -static -CURLFORMcode FormAdd(struct curl_httppost **httppost, - struct curl_httppost **last_post, - va_list params) -{ - FormInfo *first_form, *current_form, *form = NULL; - CURLFORMcode return_value = CURL_FORMADD_OK; - const char *prevtype = NULL; - struct curl_httppost *post = NULL; - CURLformoption option; - struct curl_forms *forms = NULL; - char *array_value=NULL; /* value read from an array */ - - /* This is a state variable, that if TRUE means that we're parsing an - array that we got passed to us. If FALSE we're parsing the input - va_list arguments. */ - bool array_state = FALSE; - - /* - * We need to allocate the first struct to fill in. - */ - first_form = calloc(1, sizeof(struct FormInfo)); - if(!first_form) - return CURL_FORMADD_MEMORY; - - current_form = first_form; - - /* - * Loop through all the options set. Break if we have an error to report. - */ - while(return_value == CURL_FORMADD_OK) { - - /* first see if we have more parts of the array param */ - if( array_state && forms ) { - /* get the upcoming option from the given array */ - option = forms->option; - array_value = (char *)forms->value; - - forms++; /* advance this to next entry */ - if(CURLFORM_END == option) { - /* end of array state */ - array_state = FALSE; - continue; - } - } - else { - /* This is not array-state, get next option */ - option = va_arg(params, CURLformoption); - if(CURLFORM_END == option) - break; - } - - switch (option) { - case CURLFORM_ARRAY: - if(array_state) - /* we don't support an array from within an array */ - return_value = CURL_FORMADD_ILLEGAL_ARRAY; - else { - forms = va_arg(params, struct curl_forms *); - if(forms) - array_state = TRUE; - else - return_value = CURL_FORMADD_NULL; - } - break; - - /* - * Set the Name property. - */ - case CURLFORM_PTRNAME: -#ifdef CURL_DOES_CONVERSIONS - /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy - * the data in all cases so that we'll have safe memory for the eventual - * conversion. - */ -#else - current_form->flags |= HTTPPOST_PTRNAME; /* fall through */ -#endif - case CURLFORM_COPYNAME: - if(current_form->name) - return_value = CURL_FORMADD_OPTION_TWICE; - else { - char *name = array_state? - array_value:va_arg(params, char *); - if(name) - current_form->name = name; /* store for the moment */ - else - return_value = CURL_FORMADD_NULL; - } - break; - case CURLFORM_NAMELENGTH: - if(current_form->namelength) - return_value = CURL_FORMADD_OPTION_TWICE; - else - current_form->namelength = - array_state?(size_t)array_value:(size_t)va_arg(params, long); - break; - - /* - * Set the contents property. - */ - case CURLFORM_PTRCONTENTS: - current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */ - case CURLFORM_COPYCONTENTS: - if(current_form->value) - return_value = CURL_FORMADD_OPTION_TWICE; - else { - char *value = - array_state?array_value:va_arg(params, char *); - if(value) - current_form->value = value; /* store for the moment */ - else - return_value = CURL_FORMADD_NULL; - } - break; - case CURLFORM_CONTENTSLENGTH: - if(current_form->contentslength) - return_value = CURL_FORMADD_OPTION_TWICE; - else - current_form->contentslength = - array_state?(size_t)array_value:(size_t)va_arg(params, long); - break; - - /* Get contents from a given file name */ - case CURLFORM_FILECONTENT: - if(current_form->flags != 0) - return_value = CURL_FORMADD_OPTION_TWICE; - else { - const char *filename = array_state? - array_value:va_arg(params, char *); - if(filename) { - current_form->value = strdup(filename); - if(!current_form->value) - return_value = CURL_FORMADD_MEMORY; - else { - current_form->flags |= HTTPPOST_READFILE; - current_form->value_alloc = TRUE; - } - } - else - return_value = CURL_FORMADD_NULL; - } - break; - - /* We upload a file */ - case CURLFORM_FILE: - { - const char *filename = array_state?array_value: - va_arg(params, char *); - - if(current_form->value) { - if(current_form->flags & HTTPPOST_FILENAME) { - if(filename) { - if((current_form = AddFormInfo(strdup(filename), - NULL, current_form)) == NULL) - return_value = CURL_FORMADD_MEMORY; - } - else - return_value = CURL_FORMADD_NULL; - } - else - return_value = CURL_FORMADD_OPTION_TWICE; - } - else { - if(filename) { - current_form->value = strdup(filename); - if(!current_form->value) - return_value = CURL_FORMADD_MEMORY; - else { - current_form->flags |= HTTPPOST_FILENAME; - current_form->value_alloc = TRUE; - } - } - else - return_value = CURL_FORMADD_NULL; - } - break; - } - - case CURLFORM_BUFFER: - { - const char *filename = array_state?array_value: - va_arg(params, char *); - - if(current_form->value) { - if(current_form->flags & HTTPPOST_BUFFER) { - if(filename) { - if((current_form = AddFormInfo(strdup(filename), - NULL, current_form)) == NULL) - return_value = CURL_FORMADD_MEMORY; - } - else - return_value = CURL_FORMADD_NULL; - } - else - return_value = CURL_FORMADD_OPTION_TWICE; - } - else { - if(filename) { - current_form->value = strdup(filename); - if(!current_form->value) - return_value = CURL_FORMADD_MEMORY; - } - else - return_value = CURL_FORMADD_NULL; - current_form->flags |= HTTPPOST_BUFFER; - } - break; - } - - case CURLFORM_BUFFERPTR: - current_form->flags |= HTTPPOST_PTRBUFFER; - if(current_form->buffer) - return_value = CURL_FORMADD_OPTION_TWICE; - else { - char *buffer = - array_state?array_value:va_arg(params, char *); - if(buffer) - current_form->buffer = buffer; /* store for the moment */ - else - return_value = CURL_FORMADD_NULL; - } - break; - - case CURLFORM_BUFFERLENGTH: - if(current_form->bufferlength) - return_value = CURL_FORMADD_OPTION_TWICE; - else - current_form->bufferlength = - array_state?(size_t)array_value:(size_t)va_arg(params, long); - break; - - case CURLFORM_STREAM: - current_form->flags |= HTTPPOST_CALLBACK; - if(current_form->userp) - return_value = CURL_FORMADD_OPTION_TWICE; - else { - char *userp = - array_state?array_value:va_arg(params, char *); - if(userp) { - current_form->userp = userp; - current_form->value = userp; /* this isn't strictly true but we - derive a value from this later on - and we need this non-NULL to be - accepted as a fine form part */ - } - else - return_value = CURL_FORMADD_NULL; - } - break; - - case CURLFORM_CONTENTTYPE: - { - const char *contenttype = - array_state?array_value:va_arg(params, char *); - if(current_form->contenttype) { - if(current_form->flags & HTTPPOST_FILENAME) { - if(contenttype) { - if((current_form = AddFormInfo(NULL, - strdup(contenttype), - current_form)) == NULL) - return_value = CURL_FORMADD_MEMORY; - } - else - return_value = CURL_FORMADD_NULL; - } - else - return_value = CURL_FORMADD_OPTION_TWICE; - } - else { - if(contenttype) { - current_form->contenttype = strdup(contenttype); - if(!current_form->contenttype) - return_value = CURL_FORMADD_MEMORY; - else - current_form->contenttype_alloc = TRUE; - } - else - return_value = CURL_FORMADD_NULL; - } - break; - } - case CURLFORM_CONTENTHEADER: - { - /* this "cast increases required alignment of target type" but - we consider it OK anyway */ - struct curl_slist* list = array_state? - (struct curl_slist*)array_value: - va_arg(params, struct curl_slist*); - - if( current_form->contentheader ) - return_value = CURL_FORMADD_OPTION_TWICE; - else - current_form->contentheader = list; - - break; - } - case CURLFORM_FILENAME: - { - const char *filename = array_state?array_value: - va_arg(params, char *); - if( current_form->showfilename ) - return_value = CURL_FORMADD_OPTION_TWICE; - else { - current_form->showfilename = strdup(filename); - if(!current_form->showfilename) - return_value = CURL_FORMADD_MEMORY; - else - current_form->showfilename_alloc = TRUE; - } - break; - } - default: - return_value = CURL_FORMADD_UNKNOWN_OPTION; - } - } - - if(CURL_FORMADD_OK == return_value) { - /* go through the list, check for completeness and if everything is - * alright add the HttpPost item otherwise set return_value accordingly */ - - post = NULL; - for(form = first_form; - form != NULL; - form = form->more) { - if( ((!form->name || !form->value) && !post) || - ( (form->contentslength) && - (form->flags & HTTPPOST_FILENAME) ) || - ( (form->flags & HTTPPOST_FILENAME) && - (form->flags & HTTPPOST_PTRCONTENTS) ) || - - ( (!form->buffer) && - (form->flags & HTTPPOST_BUFFER) && - (form->flags & HTTPPOST_PTRBUFFER) ) || - - ( (form->flags & HTTPPOST_READFILE) && - (form->flags & HTTPPOST_PTRCONTENTS) ) - ) { - return_value = CURL_FORMADD_INCOMPLETE; - break; - } - else { - if( ((form->flags & HTTPPOST_FILENAME) || - (form->flags & HTTPPOST_BUFFER)) && - !form->contenttype ) { - /* our contenttype is missing */ - form->contenttype - = strdup(ContentTypeForFilename(form->value, prevtype)); - if(!form->contenttype) { - return_value = CURL_FORMADD_MEMORY; - break; - } - form->contenttype_alloc = TRUE; - } - if( !(form->flags & HTTPPOST_PTRNAME) && - (form == first_form) ) { - /* Note that there's small risk that form->name is NULL here if the - app passed in a bad combo, so we better check for that first. */ - if(form->name) - /* copy name (without strdup; possibly contains null characters) */ - form->name = memdup(form->name, form->namelength); - if(!form->name) { - return_value = CURL_FORMADD_MEMORY; - break; - } - form->name_alloc = TRUE; - } - if( !(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE | - HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | - HTTPPOST_CALLBACK)) ) { - /* copy value (without strdup; possibly contains null characters) */ - form->value = memdup(form->value, form->contentslength); - if(!form->value) { - return_value = CURL_FORMADD_MEMORY; - break; - } - form->value_alloc = TRUE; - } - post = AddHttpPost(form->name, form->namelength, - form->value, form->contentslength, - form->buffer, form->bufferlength, - form->contenttype, form->flags, - form->contentheader, form->showfilename, - form->userp, - post, httppost, - last_post); - - if(!post) { - return_value = CURL_FORMADD_MEMORY; - break; - } - - if(form->contenttype) - prevtype = form->contenttype; - } - } - } - - if(return_value) { - /* we return on error, free possibly allocated fields */ - if(!form) - form = current_form; - if(form) { - if(form->name_alloc) - free(form->name); - if(form->value_alloc) - free(form->value); - if(form->contenttype_alloc) - free(form->contenttype); - if(form->showfilename_alloc) - free(form->showfilename); - } - } - - /* always delete the allocated memory before returning */ - form = first_form; - while(form != NULL) { - FormInfo *delete_form; - - delete_form = form; - form = form->more; - free (delete_form); - } - - return return_value; -} - -/* - * curl_formadd() is a public API to add a section to the multipart formpost. - */ - -CURLFORMcode curl_formadd(struct curl_httppost **httppost, - struct curl_httppost **last_post, - ...) -{ - va_list arg; - CURLFORMcode result; - va_start(arg, last_post); - result = FormAdd(httppost, last_post, arg); - va_end(arg); - return result; -} - -/* - * AddFormData() adds a chunk of data to the FormData linked list. - * - * size is incremented by the chunk length, unless it is NULL - */ -static CURLcode AddFormData(struct FormData **formp, - enum formtype type, - const void *line, - size_t length, - curl_off_t *size) -{ - struct FormData *newform = malloc(sizeof(struct FormData)); - if(!newform) - return CURLE_OUT_OF_MEMORY; - newform->next = NULL; - - if(type <= FORM_CONTENT) { - /* we make it easier for plain strings: */ - if(!length) - length = strlen((char *)line); - - newform->line = malloc(length+1); - if(!newform->line) { - free(newform); - return CURLE_OUT_OF_MEMORY; - } - memcpy(newform->line, line, length); - newform->length = length; - newform->line[length]=0; /* zero terminate for easier debugging */ - } - else - /* For callbacks and files we don't have any actual data so we just keep a - pointer to whatever this points to */ - newform->line = (char *)line; - - newform->type = type; - - if(*formp) { - (*formp)->next = newform; - *formp = newform; - } - else - *formp = newform; - - if(size) { - if(type != FORM_FILE) - /* for static content as well as callback data we add the size given - as input argument */ - *size += length; - else { - /* Since this is a file to be uploaded here, add the size of the actual - file */ - if(!strequal("-", newform->line)) { - struct_stat file; - if(!stat(newform->line, &file)) { - *size += file.st_size; - } - } - } - } - return CURLE_OK; -} - -/* - * AddFormDataf() adds printf()-style formatted data to the formdata chain. - */ - -static CURLcode AddFormDataf(struct FormData **formp, - curl_off_t *size, - const char *fmt, ...) -{ - char s[4096]; - va_list ap; - va_start(ap, fmt); - vsnprintf(s, sizeof(s), fmt, ap); - va_end(ap); - - return AddFormData(formp, FORM_DATA, s, 0, size); -} - -/* - * Curl_formclean() is used from http.c, this cleans a built FormData linked - * list - */ -void Curl_formclean(struct FormData **form_ptr) -{ - struct FormData *next, *form; - - form = *form_ptr; - if(!form) - return; - - do { - next=form->next; /* the following form line */ - if(form->type <= FORM_CONTENT) - free(form->line); /* free the line */ - free(form); /* free the struct */ - - } while((form = next) != NULL); /* continue */ - - *form_ptr = NULL; -} - -/* - * curl_formget() - * Serialize a curl_httppost struct. - * Returns 0 on success. - */ -int curl_formget(struct curl_httppost *form, void *arg, - curl_formget_callback append) -{ - CURLcode rc; - curl_off_t size; - struct FormData *data, *ptr; - - rc = Curl_getformdata(NULL, &data, form, NULL, &size); - if(rc != CURLE_OK) - return (int)rc; - - for (ptr = data; ptr; ptr = ptr->next) { - if(ptr->type == FORM_FILE) { - char buffer[8192]; - size_t nread; - struct Form temp; - - Curl_FormInit(&temp, ptr); - - do { - nread = readfromfile(&temp, buffer, sizeof(buffer)); - if((nread == (size_t) -1) || (nread != append(arg, buffer, nread))) { - if(temp.fp) { - fclose(temp.fp); - } - Curl_formclean(&data); - return -1; - } - } while(nread == sizeof(buffer)); - } - else { - if(ptr->length != append(arg, ptr->line, ptr->length)) { - Curl_formclean(&data); - return -1; - } - } - } - Curl_formclean(&data); - return 0; -} - -/* - * curl_formfree() is an external function to free up a whole form post - * chain - */ -void curl_formfree(struct curl_httppost *form) -{ - struct curl_httppost *next; - - if(!form) - /* no form to free, just get out of this */ - return; - - do { - next=form->next; /* the following form line */ - - /* recurse to sub-contents */ - if(form->more) - curl_formfree(form->more); - - if( !(form->flags & HTTPPOST_PTRNAME) && form->name) - free(form->name); /* free the name */ - if( !(form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_CALLBACK)) && - form->contents) - free(form->contents); /* free the contents */ - if(form->contenttype) - free(form->contenttype); /* free the content type */ - if(form->showfilename) - free(form->showfilename); /* free the faked file name */ - free(form); /* free the struct */ - - } while((form = next) != NULL); /* continue */ -} - -#ifndef HAVE_BASENAME -/* - (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 - Edition) - - The basename() function shall take the pathname pointed to by path and - return a pointer to the final component of the pathname, deleting any - trailing '/' characters. - - If the string pointed to by path consists entirely of the '/' character, - basename() shall return a pointer to the string "/". If the string pointed - to by path is exactly "//", it is implementation-defined whether '/' or "//" - is returned. - - If path is a null pointer or points to an empty string, basename() shall - return a pointer to the string ".". - - The basename() function may modify the string pointed to by path, and may - return a pointer to static storage that may then be overwritten by a - subsequent call to basename(). - - The basename() function need not be reentrant. A function that is not - required to be reentrant is not required to be thread-safe. - -*/ -static char *Curl_basename(char *path) -{ - /* Ignore all the details above for now and make a quick and simple - implementaion here */ - char *s1; - char *s2; - - s1=strrchr(path, '/'); - s2=strrchr(path, '\\'); - - if(s1 && s2) { - path = (s1 > s2? s1 : s2)+1; - } - else if(s1) - path = s1 + 1; - else if(s2) - path = s2 + 1; - - return path; -} -#endif - -static char *strippath(const char *fullfile) -{ - char *filename; - char *base; - filename = strdup(fullfile); /* duplicate since basename() may ruin the - buffer it works on */ - if(!filename) - return NULL; - base = strdup(basename(filename)); - - free(filename); /* free temporary buffer */ - - return base; /* returns an allocated string or NULL ! */ -} - -/* - * Curl_getformdata() converts a linked list of "meta data" into a complete - * (possibly huge) multipart formdata. The input list is in 'post', while the - * output resulting linked lists gets stored in '*finalform'. *sizep will get - * the total size of the whole POST. - * A multipart/form_data content-type is built, unless a custom content-type - * is passed in 'custom_content_type'. - * - * This function will not do a failf() for the potential memory failures but - * should for all other errors it spots. Just note that this function MAY get - * a NULL pointer in the 'data' argument. - */ - -CURLcode Curl_getformdata(struct SessionHandle *data, - struct FormData **finalform, - struct curl_httppost *post, - const char *custom_content_type, - curl_off_t *sizep) -{ - struct FormData *form = NULL; - struct FormData *firstform; - struct curl_httppost *file; - CURLcode result = CURLE_OK; - - curl_off_t size=0; /* support potentially ENORMOUS formposts */ - char *boundary; - char *fileboundary=NULL; - struct curl_slist* curList; - - *finalform=NULL; /* default form is empty */ - - if(!post) - return result; /* no input => no output! */ - - boundary = Curl_FormBoundary(); - if(!boundary) - return CURLE_OUT_OF_MEMORY; - - /* Make the first line of the output */ - result = AddFormDataf(&form, NULL, - "%s; boundary=%s\r\n", - custom_content_type?custom_content_type: - "Content-Type: multipart/form-data", - boundary); - - if(result) { - free(boundary); - return result; - } - /* we DO NOT include that line in the total size of the POST, since it'll be - part of the header! */ - - firstform = form; - - do { - - if(size) { - result = AddFormDataf(&form, &size, "\r\n"); - if(result) - break; - } - - /* boundary */ - result = AddFormDataf(&form, &size, "--%s\r\n", boundary); - if(result) - break; - - /* Maybe later this should be disabled when a custom_content_type is - passed, since Content-Disposition is not meaningful for all multipart - types. - */ - result = AddFormDataf(&form, &size, - "Content-Disposition: form-data; name=\""); - if(result) - break; - - result = AddFormData(&form, FORM_DATA, post->name, post->namelength, - &size); - if(result) - break; - - result = AddFormDataf(&form, &size, "\""); - if(result) - break; - - if(post->more) { - /* If used, this is a link to more file names, we must then do - the magic to include several files with the same field name */ - - fileboundary = Curl_FormBoundary(); - - result = AddFormDataf(&form, &size, - "\r\nContent-Type: multipart/mixed," - " boundary=%s\r\n", - fileboundary); - if(result) - break; - } - - file = post; - - do { - - /* If 'showfilename' is set, that is a faked name passed on to us - to use to in the formpost. If that is not set, the actually used - local file name should be added. */ - - if(post->more) { - /* if multiple-file */ - char *filebasename= NULL; - if(!file->showfilename) { - filebasename = strippath(file->contents); - if(!filebasename) { - Curl_formclean(&firstform); - free(boundary); - return CURLE_OUT_OF_MEMORY; - } - } - - result = AddFormDataf(&form, &size, - "\r\n--%s\r\nContent-Disposition: " - "attachment; filename=\"%s\"", - fileboundary, - (file->showfilename?file->showfilename: - filebasename)); - if(filebasename) - free(filebasename); - if(result) - break; - } - else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER| - HTTPPOST_CALLBACK)) { - /* it should be noted that for the HTTPPOST_FILENAME and - HTTPPOST_CALLBACK cases the ->showfilename struct member is always - assigned at this point */ - char *filebasename= - (!post->showfilename)?strippath(post->contents):NULL; - - result = AddFormDataf(&form, &size, - "; filename=\"%s\"", - (post->showfilename?post->showfilename: - filebasename)); - if(filebasename) - free(filebasename); - - if(result) - break; - } - - if(file->contenttype) { - /* we have a specified type */ - result = AddFormDataf(&form, &size, - "\r\nContent-Type: %s", - file->contenttype); - if(result) - break; - } - - curList = file->contentheader; - while( curList ) { - /* Process the additional headers specified for this form */ - result = AddFormDataf( &form, &size, "\r\n%s", curList->data ); - if(result) - break; - curList = curList->next; - } - if(result) { - Curl_formclean(&firstform); - free(boundary); - return result; - } - - result = AddFormDataf(&form, &size, "\r\n\r\n"); - if(result) - break; - - if((post->flags & HTTPPOST_FILENAME) || - (post->flags & HTTPPOST_READFILE)) { - /* we should include the contents from the specified file */ - FILE *fileread; - - fileread = strequal("-", file->contents)? - stdin:fopen(file->contents, "rb"); /* binary read for win32 */ - - /* - * VMS: This only allows for stream files on VMS. Stream files are - * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC, - * every record needs to have a \n appended & 1 added to SIZE - */ - - if(fileread) { - if(fileread != stdin) { - /* close the file again */ - fclose(fileread); - /* add the file name only - for later reading from this */ - result = AddFormData(&form, FORM_FILE, file->contents, 0, &size); - } - else { - /* When uploading from stdin, we can't know the size of the file, - * thus must read the full file as before. We *could* use chunked - * transfer-encoding, but that only works for HTTP 1.1 and we - * can't be sure we work with such a server. - */ - size_t nread; - char buffer[512]; - while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) { - result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size); - if(result) - break; - } - } - } - else { - if(data) - failf(data, "couldn't open file \"%s\"\n", file->contents); - *finalform = NULL; - result = CURLE_READ_ERROR; - } - } - else if(post->flags & HTTPPOST_BUFFER) - /* include contents of buffer */ - result = AddFormData(&form, FORM_CONTENT, post->buffer, - post->bufferlength, &size); - else if(post->flags & HTTPPOST_CALLBACK) - /* the contents should be read with the callback and the size - is set with the contentslength */ - result = AddFormData(&form, FORM_CALLBACK, post->userp, - post->contentslength, &size); - else - /* include the contents we got */ - result = AddFormData(&form, FORM_CONTENT, post->contents, - post->contentslength, &size); - - file = file->more; - } while(file && !result); /* for each specified file for this field */ - - if(result) { - Curl_formclean(&firstform); - free(boundary); - return result; - } - - if(post->more) { - /* this was a multiple-file inclusion, make a termination file - boundary: */ - result = AddFormDataf(&form, &size, - "\r\n--%s--", - fileboundary); - free(fileboundary); - if(result) - break; - } - - } while((post = post->next) != NULL); /* for each field */ - if(result) { - Curl_formclean(&firstform); - free(boundary); - return result; - } - - /* end-boundary for everything */ - result = AddFormDataf(&form, &size, - "\r\n--%s--\r\n", - boundary); - if(result) { - Curl_formclean(&firstform); - free(boundary); - return result; - } - - *sizep = size; - - free(boundary); - - *finalform=firstform; - - return result; -} - -/* - * Curl_FormInit() inits the struct 'form' points to with the 'formdata' - * and resets the 'sent' counter. - */ -int Curl_FormInit(struct Form *form, struct FormData *formdata ) -{ - if(!formdata) - return 1; /* error */ - - form->data = formdata; - form->sent = 0; - form->fp = NULL; - form->fread_func = ZERO_NULL; - - return 0; -} - -static size_t readfromfile(struct Form *form, char *buffer, - size_t size) -{ - size_t nread; - bool callback = (bool)(form->data->type == FORM_CALLBACK); - - if(callback) - nread = form->fread_func(buffer, 1, size, form->data->line); - else { - if(!form->fp) { - /* this file hasn't yet been opened */ - form->fp = fopen(form->data->line, "rb"); /* b is for binary */ - if(!form->fp) - return (size_t)-1; /* failure */ - } - nread = fread(buffer, 1, size, form->fp); - } - if(!nread || nread > size) { - /* this is the last chunk from the file, move on */ - if(!callback) { - fclose(form->fp); - form->fp = NULL; - } - form->data = form->data->next; - } - - return nread; -} - -/* - * Curl_FormReader() is the fread() emulation function that will be used to - * deliver the formdata to the transfer loop and then sent away to the peer. - */ -size_t Curl_FormReader(char *buffer, - size_t size, - size_t nitems, - FILE *mydata) -{ - struct Form *form; - size_t wantedsize; - size_t gotsize = 0; - - form=(struct Form *)mydata; - - wantedsize = size * nitems; - - if(!form->data) - return 0; /* nothing, error, empty */ - - if((form->data->type == FORM_FILE) || - (form->data->type == FORM_CALLBACK)) { - gotsize = readfromfile(form, buffer, wantedsize); - - if(gotsize) - /* If positive or -1, return. If zero, continue! */ - return gotsize; - } - do { - - if( (form->data->length - form->sent ) > wantedsize - gotsize) { - - memcpy(buffer + gotsize , form->data->line + form->sent, - wantedsize - gotsize); - - form->sent += wantedsize-gotsize; - - return wantedsize; - } - - memcpy(buffer+gotsize, - form->data->line + form->sent, - (form->data->length - form->sent) ); - gotsize += form->data->length - form->sent; - - form->sent = 0; - - form->data = form->data->next; /* advance */ - - } while(form->data && (form->data->type < FORM_CALLBACK)); - /* If we got an empty line and we have more data, we proceed to the next - line immediately to avoid returning zero before we've reached the end. */ - - return gotsize; -} - -/* - * Curl_formpostheader() returns the first line of the formpost, the - * request-header part (which is not part of the request-body like the rest of - * the post). - */ -char *Curl_formpostheader(void *formp, size_t *len) -{ - char *header; - struct Form *form=(struct Form *)formp; - - if(!form->data) - return 0; /* nothing, ERROR! */ - - header = form->data->line; - *len = form->data->length; - - form->data = form->data->next; /* advance */ - - return header; -} - - -#ifdef _FORM_DEBUG -int FormAddTest(const char * errormsg, - struct curl_httppost **httppost, - struct curl_httppost **last_post, - ...) -{ - int result; - va_list arg; - va_start(arg, last_post); - if((result = FormAdd(httppost, last_post, arg))) - fprintf (stderr, "ERROR doing FormAdd ret: %d action: %s\n", result, - errormsg); - va_end(arg); - return result; -} - - -int main(int argc, argv_item_t argv[]) -{ - char name1[] = "simple_COPYCONTENTS"; - char name2[] = "COPYCONTENTS_+_CONTENTTYPE"; - char name3[] = "PTRNAME_+_NAMELENGTH_+_COPYNAME_+_CONTENTSLENGTH"; - char name4[] = "simple_PTRCONTENTS"; - char name5[] = "PTRCONTENTS_+_CONTENTSLENGTH"; - char name6[] = "PTRCONTENTS_+_CONTENTSLENGTH_+_CONTENTTYPE"; - char name7[] = "FILE1_+_CONTENTTYPE"; - char name8[] = "FILE1_+_FILE2"; - char name9[] = "FILE1_+_FILE2_+_FILE3"; - char name10[] = "ARRAY: FILE1_+_FILE2_+_FILE3"; - char name11[] = "FILECONTENT"; - char value1[] = "value for simple COPYCONTENTS"; - char value2[] = "value for COPYCONTENTS + CONTENTTYPE"; - char value3[] = "value for PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH"; - char value4[] = "value for simple PTRCONTENTS"; - char value5[] = "value for PTRCONTENTS + CONTENTSLENGTH"; - char value6[] = "value for PTRCONTENTS + CONTENTSLENGTH + CONTENTTYPE"; - char value7[] = "formdata.h"; - char value8[] = "Makefile.b32"; - char type2[] = "image/gif"; - char type6[] = "text/plain"; - char type7[] = "text/html"; - int name3length = strlen(name3); - int value3length = strlen(value3); - int value5length = strlen(value5); - int value6length = strlen(value6); - int errors = 0; - CURLcode rc; - curl_off_t size; - size_t nread; - char buffer[4096]; - struct curl_httppost *httppost=NULL; - struct curl_httppost *last_post=NULL; - struct curl_forms forms[4]; - - struct FormData *form; - struct Form formread; - - (void) argc; - (void) argv; - - Curl_srand(); /* Because we do not call curl_global_init() here. */ - - if(FormAddTest("simple COPYCONTENTS test", &httppost, &last_post, - CURLFORM_COPYNAME, name1, CURLFORM_COPYCONTENTS, value1, - CURLFORM_END)) - ++errors; - if(FormAddTest("COPYCONTENTS + CONTENTTYPE test", &httppost, &last_post, - CURLFORM_COPYNAME, name2, CURLFORM_COPYCONTENTS, value2, - CURLFORM_CONTENTTYPE, type2, CURLFORM_END)) - ++errors; - /* make null character at start to check that contentslength works - correctly */ - name3[1] = '\0'; - value3[1] = '\0'; - if(FormAddTest("PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH test", - &httppost, &last_post, - CURLFORM_PTRNAME, name3, CURLFORM_COPYCONTENTS, value3, - CURLFORM_CONTENTSLENGTH, value3length, - CURLFORM_NAMELENGTH, name3length, CURLFORM_END)) - ++errors; - if(FormAddTest("simple PTRCONTENTS test", &httppost, &last_post, - CURLFORM_COPYNAME, name4, CURLFORM_PTRCONTENTS, value4, - CURLFORM_END)) - ++errors; - /* make null character at start to check that contentslength works - correctly */ - value5[1] = '\0'; - if(FormAddTest("PTRCONTENTS + CONTENTSLENGTH test", &httppost, &last_post, - CURLFORM_COPYNAME, name5, CURLFORM_PTRCONTENTS, value5, - CURLFORM_CONTENTSLENGTH, value5length, CURLFORM_END)) - ++errors; - /* make null character at start to check that contentslength works - correctly */ - value6[1] = '\0'; - if(FormAddTest("PTRCONTENTS + CONTENTSLENGTH + CONTENTTYPE test", - &httppost, &last_post, - CURLFORM_COPYNAME, name6, CURLFORM_PTRCONTENTS, value6, - CURLFORM_CONTENTSLENGTH, value6length, - CURLFORM_CONTENTTYPE, type6, CURLFORM_END)) - ++errors; - if(FormAddTest("FILE + CONTENTTYPE test", &httppost, &last_post, - CURLFORM_COPYNAME, name7, CURLFORM_FILE, value7, - CURLFORM_CONTENTTYPE, type7, CURLFORM_END)) - ++errors; - if(FormAddTest("FILE1 + FILE2 test", &httppost, &last_post, - CURLFORM_COPYNAME, name8, CURLFORM_FILE, value7, - CURLFORM_FILE, value8, CURLFORM_END)) - ++errors; - if(FormAddTest("FILE1 + FILE2 + FILE3 test", &httppost, &last_post, - CURLFORM_COPYNAME, name9, CURLFORM_FILE, value7, - CURLFORM_FILE, value8, CURLFORM_FILE, value7, CURLFORM_END)) - ++errors; - forms[0].option = CURLFORM_FILE; - forms[0].value = value7; - forms[1].option = CURLFORM_FILE; - forms[1].value = value8; - forms[2].option = CURLFORM_FILE; - forms[2].value = value7; - forms[3].option = CURLFORM_END; - if(FormAddTest("FILE1 + FILE2 + FILE3 ARRAY test", &httppost, &last_post, - CURLFORM_COPYNAME, name10, CURLFORM_ARRAY, forms, - CURLFORM_END)) - ++errors; - if(FormAddTest("FILECONTENT test", &httppost, &last_post, - CURLFORM_COPYNAME, name11, CURLFORM_FILECONTENT, value7, - CURLFORM_END)) - ++errors; - - rc = Curl_getformdata(NULL, &form, httppost, NULL, &size); - if(rc != CURLE_OK) { - if(rc != CURLE_READ_ERROR) { - const char *errortext = curl_easy_strerror(rc); - fprintf(stdout, "\n==> Curl_getformdata error: %s\n", errortext); - } - return 0; - } - - Curl_FormInit(&formread, form); - - for(;;) { - nread = Curl_FormReader(buffer, 1, sizeof(buffer), - (FILE *)&formread); - - if(nread < 1) - break; - fwrite(buffer, nread, 1, stdout); - } - - fprintf(stdout, "size: "); - fprintf(stdout, "%" FORMAT_OFF_T, size); - fprintf(stdout, "\n"); - if(errors) - fprintf(stdout, "\n==> %d Test(s) failed!\n", errors); - else - fprintf(stdout, "\nAll Tests seem to have worked (please check output)\n"); - - return 0; -} - -#endif /* _FORM_DEBUG */ - -#else /* CURL_DISABLE_HTTP */ -CURLFORMcode curl_formadd(struct curl_httppost **httppost, - struct curl_httppost **last_post, - ...) -{ - (void)httppost; - (void)last_post; - return CURL_FORMADD_DISABLED; -} - -int curl_formget(struct curl_httppost *form, void *arg, - curl_formget_callback append) -{ - (void) form; - (void) arg; - (void) append; - return CURL_FORMADD_DISABLED; -} - -void curl_formfree(struct curl_httppost *form) -{ - (void)form; - /* does nothing HTTP is disabled */ -} - -#endif /* CURL_DISABLE_HTTP */ - -#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) - -/* - * Curl_FormBoundary() creates a suitable boundary string and returns an - * allocated one. This is also used by SSL-code so it must be present even - * if HTTP is disabled! - */ -char *Curl_FormBoundary(void) -{ - char *retstring; - size_t i; - - static const char table16[]="0123456789abcdef"; - - retstring = malloc(BOUNDARY_LENGTH+1); - - if(!retstring) - return NULL; /* failed */ - - strcpy(retstring, "----------------------------"); - - for(i=strlen(retstring); i, et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -enum formtype { - FORM_DATA, /* form metadata (convert to network encoding if necessary) */ - FORM_CONTENT, /* form content (never convert) */ - FORM_CALLBACK, /* 'line' points to the custom pointer we pass to the callback - */ - FORM_FILE /* 'line' points to a file name we should read from - to create the form data (never convert) */ -}; - -/* plain and simple linked list with lines to send */ -struct FormData { - struct FormData *next; - enum formtype type; - char *line; - size_t length; -}; - -struct Form { - struct FormData *data; /* current form line to send */ - size_t sent; /* number of bytes of the current line that has - already been sent in a previous invoke */ - FILE *fp; /* file to read from */ - curl_read_callback fread_func; /* fread callback pointer */ -}; - -/* used by FormAdd for temporary storage */ -typedef struct FormInfo { - char *name; - bool name_alloc; - size_t namelength; - char *value; - bool value_alloc; - size_t contentslength; - char *contenttype; - bool contenttype_alloc; - long flags; - char *buffer; /* pointer to existing buffer used for file upload */ - size_t bufferlength; - char *showfilename; /* The file name to show. If not set, the actual - file name will be used */ - bool showfilename_alloc; - char *userp; /* pointer for the read callback */ - struct curl_slist* contentheader; - struct FormInfo *more; -} FormInfo; - -int Curl_FormInit(struct Form *form, struct FormData *formdata ); - -CURLcode Curl_getformdata(struct SessionHandle *data, - struct FormData **, - struct curl_httppost *post, - const char *custom_contenttype, - curl_off_t *size); - -/* fread() emulation */ -size_t Curl_FormReader(char *buffer, - size_t size, - size_t nitems, - FILE *mydata); - -/* - * Curl_formpostheader() returns the first line of the formpost, the - * request-header part (which is not part of the request-body like the rest of - * the post). - */ -char *Curl_formpostheader(void *formp, size_t *len); - -char *Curl_FormBoundary(void); - -void Curl_formclean(struct FormData **); - -CURLcode Curl_formconvert(struct SessionHandle *, struct FormData *); - -#endif /* HEADER_CURL_FORMDATA_H */ diff --git a/third_party/curl/lib/ftp.c b/third_party/curl/lib/ftp.c deleted file mode 100644 index 9be8ed997..000000000 --- a/third_party/curl/lib/ftp.c +++ /dev/null @@ -1,4230 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef CURL_DISABLE_FTP -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_UTSNAME_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef __VMS -#include -#include -#endif - -#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) -#undef in_addr_t -#define in_addr_t unsigned long -#endif - -#include -#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" - -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) -#include "krb4.h" -#endif - -#include "strtoofft.h" -#include "strequal.h" -#include "sslgen.h" -#include "connect.h" -#include "strerror.h" -#include "inet_ntop.h" -#include "inet_pton.h" -#include "select.h" -#include "parsedate.h" /* for the week day and month names */ -#include "sockaddr.h" /* required for Curl_sockaddr_storage */ -#include "multiif.h" -#include "url.h" -#include "rawstr.h" -#include "speedcheck.h" -#include "warnless.h" -#include "http_proxy.h" -#include "non-ascii.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -#ifndef NI_MAXHOST -#define NI_MAXHOST 1025 -#endif -#ifndef INET_ADDRSTRLEN -#define INET_ADDRSTRLEN 16 -#endif - -#ifdef CURL_DISABLE_VERBOSE_STRINGS -#define ftp_pasv_verbose(a,b,c,d) do { } while(0) -#endif - -/* Local API functions */ -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_post_rest(struct connectdata *conn); -static CURLcode ftp_state_post_cwd(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_nextconnect(struct connectdata *conn); -static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done); -static int ftp_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_post_retr_size(struct connectdata *conn, - curl_off_t filesize); - -/* easy-to-use macro: */ -#define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z)) != CURLE_OK) \ - return result -#define PPSENDF(x,y,z) if((result = Curl_pp_sendf(x,y,z)) != CURLE_OK) \ - return result - - -/* - * FTP protocol handler. - */ - -const struct Curl_handler Curl_handler_ftp = { - "FTP", /* scheme */ - ftp_setup_connection, /* setup_connection */ - ftp_do, /* do_it */ - ftp_done, /* done */ - ftp_nextconnect, /* do_more */ - ftp_connect, /* connect_it */ - ftp_multi_statemach, /* connecting */ - ftp_doing, /* doing */ - ftp_getsock, /* proto_getsock */ - ftp_getsock, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ftp_disconnect, /* disconnect */ - PORT_FTP, /* defport */ - CURLPROTO_FTP, /* protocol */ - PROTOPT_DUAL | PROTOPT_CLOSEACTION /* 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_nextconnect, /* do_more */ - ftp_connect, /* connect_it */ - ftp_multi_statemach, /* connecting */ - ftp_doing, /* doing */ - ftp_getsock, /* proto_getsock */ - ftp_getsock, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ftp_disconnect, /* disconnect */ - PORT_FTPS, /* defport */ - CURLPROTO_FTP | CURLPROTO_FTPS, /* protocol */ - PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION /* flags */ -}; -#endif - -#ifndef CURL_DISABLE_HTTP -/* - * HTTP-proxyed FTP protocol handler. - */ - -static const struct Curl_handler Curl_handler_ftp_proxy = { - "FTP", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_FTP, /* defport */ - CURLPROTO_HTTP, /* protocol */ - PROTOPT_NONE /* flags */ -}; - - -#ifdef USE_SSL -/* - * HTTP-proxyed FTPS protocol handler. - */ - -static const struct Curl_handler Curl_handler_ftps_proxy = { - "FTPS", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_FTPS, /* defport */ - CURLPROTO_HTTP, /* protocol */ - PROTOPT_NONE /* flags */ -}; -#endif -#endif - - -/* - * NOTE: back in the old days, we added code in the FTP code that made NOBODY - * requests on files respond with headers passed to the client/stdout that - * looked like HTTP ones. - * - * This approach is not very elegant, it causes confusion and is error-prone. - * It is subject for removal at the next (or at least a future) soname bump. - * Until then you can test the effects of the removal by undefining the - * following define named CURL_FTP_HTTPSTYLE_HEAD. - */ -#define CURL_FTP_HTTPSTYLE_HEAD 1 - -static void freedirs(struct ftp_conn *ftpc) -{ - int i; - if(ftpc->dirs) { - for (i=0; i < ftpc->dirdepth; i++){ - if(ftpc->dirs[i]) { - free(ftpc->dirs[i]); - ftpc->dirs[i]=NULL; - } - } - free(ftpc->dirs); - ftpc->dirs = NULL; - ftpc->dirdepth = 0; - } - if(ftpc->file) { - free(ftpc->file); - ftpc->file = NULL; - } -} - -/* Returns non-zero if the given string contains CR (\r) or LF (\n), - which are not allowed within RFC 959 . - 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 (bool)((NULL != strchr(string, '\r')) || - (NULL != strchr(string, '\n'))); -} - -/*********************************************************************** - * - * AllowServerConnect() - * - * When we've issue the PORT command, we have told the server to connect - * to us. This function will sit and wait here until the server has - * connected. - * - */ -static CURLcode AllowServerConnect(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - curl_socket_t sock = conn->sock[SECONDARYSOCKET]; - long timeout_ms; - long interval_ms; - 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); - - for(;;) { - timeout_ms = Curl_timeleft(data, NULL, TRUE); - - if(timeout_ms < 0) { - /* if a timeout was already reached, bail out */ - failf(data, "Timeout while waiting for server connect"); - return CURLE_OPERATION_TIMEDOUT; - } - - interval_ms = 1000; /* use 1 second timeout intervals */ - if(timeout_ms < interval_ms) - interval_ms = timeout_ms; - - switch (Curl_socket_ready(sock, CURL_SOCKET_BAD, (int)interval_ms)) { - case -1: /* error */ - /* let's die here */ - failf(data, "Error while waiting for server connect"); - return CURLE_FTP_PORT_FAILED; - case 0: /* timeout */ - break; /* loop */ - default: - /* we have received data here */ - if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) { - size = sizeof(add); - - s=accept(sock, (struct sockaddr *) &add, &size); - } - sclose(sock); /* close the first socket */ - - if(CURL_SOCKET_BAD == s) { - failf(data, "Error accept()ing server connect"); - return CURLE_FTP_PORT_FAILED; - } - infof(data, "Connection accepted from server\n"); - - conn->sock[SECONDARYSOCKET] = s; - curlx_nonblock(s, TRUE); /* enable non-blocking */ - return CURLE_OK; - } /* switch() */ - } - /* never reaches this point */ -} - -/* 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 int ftp_endofresp(struct pingpong *pp, - int *code) -{ - char *line = pp->linestart_resp; - size_t len = pp->nread_resp; - - if((len > 3) && LASTLINE(line)) { - *code = curlx_sltosi(strtol(line, NULL, 10)); - return 1; - } - return 0; -} - -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; -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - struct SessionHandle *data = conn->data; - char * const buf = data->state.buffer; -#endif - CURLcode result = CURLE_OK; - int code; - - result = Curl_pp_readresp(sockfd, pp, &code, size); - -#if defined(HAVE_KRB4) || 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 */ - conn->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. */ - return CURLE_OPERATION_TIMEDOUT; - - return result; -} - -/* --- parse FTP server responses --- */ - -/* - * Curl_GetFTPResponse() is a BLOCKING function to read the full response - * from a server after a command. - * - */ - -CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ - struct connectdata *conn, - int *ftpcode) /* return the ftp-code */ -{ - /* - * We cannot read just one byte per read() and then go back to select() as - * the OpenSSL read() doesn't grok that properly. - * - * Alas, read as much as possible, split up into lines, use the ending - * line in a response or continue reading. */ - - curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; - long timeout; /* timeout in milliseconds */ - long interval_ms; - struct SessionHandle *data = conn->data; - CURLcode result = CURLE_OK; - struct ftp_conn *ftpc = &conn->proto.ftpc; - struct pingpong *pp = &ftpc->pp; - size_t nread; - int cache_skip=0; - int value_to_be_ignored=0; - - if(ftpcode) - *ftpcode = 0; /* 0 for errors */ - else - /* make the pointer point to something for the rest of this function */ - ftpcode = &value_to_be_ignored; - - *nreadp=0; - - while(!*ftpcode && !result) { - /* check and reset timeout value every lap */ - timeout = Curl_pp_state_timeout(pp); - - if(timeout <=0 ) { - failf(data, "FTP response timeout"); - return CURLE_OPERATION_TIMEDOUT; /* already too little time */ - } - - interval_ms = 1000; /* use 1 second timeout intervals */ - if(timeout < interval_ms) - interval_ms = timeout; - - /* - * Since this function is blocking, we need to wait here for input on the - * connection and only then we call the response reading function. We do - * timeout at least every second to make the timeout check run. - * - * A caution here is that the ftp_readresp() function has a cache that may - * contain pieces of a response from the previous invoke and we need to - * make sure we don't just wait for input while there is unhandled data in - * that cache. But also, if the cache is there, we call ftp_readresp() and - * the cache wasn't good enough to continue we must not just busy-loop - * around this function. - * - */ - - if(pp->cache && (cache_skip < 2)) { - /* - * There's a cache left since before. We then skipping the wait for - * socket action, unless this is the same cache like the previous round - * as then the cache was deemed not enough to act on and we then need to - * wait for more data anyway. - */ - } - else { - switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, (int)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; -} - -/* This is the ONLY way to change FTP state! */ -static void state(struct connectdata *conn, - ftpstate newstate) -{ -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - /* for debug purposes */ - static const char * const 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 - struct ftp_conn *ftpc = &conn->proto.ftpc; -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - if(ftpc->state != newstate) - infof(conn->data, "FTP %p state change from %s to %s\n", - ftpc, names[ftpc->state], names[newstate]); -#endif - ftpc->state = newstate; -} - -static CURLcode ftp_state_user(struct connectdata *conn) -{ - CURLcode result; - struct FTP *ftp = conn->data->state.proto.ftp; - /* 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, "PWD", NULL); - 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); -} - -/* 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_post_cwd(conn); - else { - ftpc->count2 = 0; /* count2 counts failed CWDs */ - - /* count3 is set to allow a MKD to fail once. In the case when first CWD - fails and then MKD fails (due to another session raced it to create the - dir) this then allows for a second try to CWD to it */ - ftpc->count3 = (conn->data->set.ftp_create_missing_dirs==2)?1:0; - - if(conn->bits.reuse && ftpc->entrypath) { - /* This is a re-used connection. Since we change directory to where the - transfer is taking place, we must first get back to the original dir - where we ended up after login: */ - ftpc->count1 = 0; /* we count this as the first path, then we add one - for all upcoming ones in the ftp->dirs[] array */ - PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath); - state(conn, FTP_CWD); - } - else { - if(ftpc->dirdepth) { - ftpc->count1 = 1; - /* issue the first CWD, the rest is sent when the CWD responses are - received... */ - PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->count1 -1]); - state(conn, FTP_CWD); - } - else { - /* No CWD necessary */ - result = ftp_state_post_cwd(conn); - } - } - } - return result; -} - -typedef enum { - EPRT, - PORT, - DONE -} ftpport; - -static CURLcode ftp_state_use_port(struct connectdata *conn, - ftpport fcmd) /* start with this */ - -{ - CURLcode result = CURLE_OK; - struct ftp_conn *ftpc = &conn->proto.ftpc; - struct SessionHandle *data=conn->data; - curl_socket_t portsock= CURL_SOCKET_BAD; - char myhost[256] = ""; - - struct Curl_sockaddr_storage ss; - Curl_addrinfo *res, *ai; - curl_socklen_t sslen; - char hbuf[NI_MAXHOST]; - struct sockaddr *sa=(struct sockaddr *)&ss; - struct sockaddr_in * const sa4 = (void *)sa; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 * const sa6 = (void *)sa; -#endif - char tmp[1024]; - static const char mode[][5] = { "EPRT", "PORT" }; - int rc; - int error; - char *host=NULL; - char *string_ftpport = data->set.str[STRING_FTPPORT]; - struct Curl_dns_entry *h=NULL; - unsigned short port_min = 0; - unsigned short port_max = 0; - unsigned short port; - - char *addr = NULL; - - /* Step 1, figure out what is requested, - * accepted format : - * (ipv4|ipv6|domain|interface)?(:port(-range)?)? - */ - - if(data->set.str[STRING_FTPPORT] && - (strlen(data->set.str[STRING_FTPPORT]) > 1)) { - -#ifdef ENABLE_IPV6 - size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ? - INET6_ADDRSTRLEN : strlen(string_ftpport); -#else - size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ? - INET_ADDRSTRLEN : strlen(string_ftpport); -#endif - char *ip_start = string_ftpport; - char *ip_end = NULL; - char *port_start = NULL; - char *port_sep = NULL; - - addr = calloc(addrlen+1, 1); - if (!addr) - return CURLE_OUT_OF_MEMORY; - -#ifdef ENABLE_IPV6 - if(*string_ftpport == '[') { - /* [ipv6]:port(-range) */ - ip_start = string_ftpport + 1; - if((ip_end = strchr(string_ftpport, ']')) != NULL ) - strncpy(addr, ip_start, ip_end - ip_start); - } - else -#endif - if( *string_ftpport == ':') { - /* :port */ - ip_end = string_ftpport; - } - else if( (ip_end = strchr(string_ftpport, ':')) != NULL) { - /* either ipv6 or (ipv4|domain|interface):port(-range) */ -#ifdef ENABLE_IPV6 - if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { - /* ipv6 */ - port_min = port_max = 0; - strcpy(addr, string_ftpport); - ip_end = NULL; /* this got no port ! */ - } else -#endif - { - /* (ipv4|domain|interface):port(-range) */ - strncpy(addr, string_ftpport, ip_end - ip_start ); - } - } - else - /* ipv4|interface */ - strcpy(addr, string_ftpport); - - /* parse the port */ - if( ip_end != NULL ) { - if((port_start = strchr(ip_end, ':')) != NULL) { - port_min = curlx_ultous(strtoul(port_start+1, NULL, 10)); - if((port_sep = strchr(port_start, '-')) != NULL) { - port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10)); - } - else - port_max = port_min; - } - } - - /* correct errors like: - * :1234-1230 - * :-4711 , in this case port_min is (unsigned)-1, - * therefore port_min > port_max for all cases - * but port_max = (unsigned)-1 - */ - if(port_min > port_max ) - port_min = port_max = 0; - - - if(*addr != '\0') { - /* attempt to get the address of the given interface name */ - if(!Curl_if2ip(conn->ip_addr->ai_family, addr, - hbuf, sizeof(hbuf))) - /* not an interface, use the given string as host name instead */ - host = addr; - else - 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) ); - if (addr) - 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 */ - } - - /* resolv ip/host to ip */ - rc = Curl_resolv(conn, host, 0, &h); - if(rc == CURLRESOLV_PENDING) - (void)Curl_wait_for_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 (addr) - free(addr); - - if (res == NULL) { - failf(data, "Curl_resolv failed, we can not recover!"); - return CURLE_FTP_PORT_FAILED; - } - - /* step 2, create a socket for the requested address */ - - portsock = CURL_SOCKET_BAD; - error = 0; - for (ai = res; ai; ai = ai->ai_next) { - /* - * Workaround for AIX5 getaddrinfo() problem (it doesn't set ai_socktype): - */ - if(ai->ai_socktype == 0) - ai->ai_socktype = conn->socktype; - - portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if(portsock == CURL_SOCKET_BAD) { - 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(error == EADDRNOTAVAIL) { - - /* The requested bind address is not local. Use the address used for - * the control connection instead and restart the port loop - */ - failf(data, "bind(port=%hu) failed: %s", port, - Curl_strerror(conn, error) ); - - sslen = sizeof(ss); - if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { - failf(data, "getsockname() failed: %s", - Curl_strerror(conn, SOCKERRNO) ); - sclose(portsock); - return CURLE_FTP_PORT_FAILED; - } - port = port_min; - continue; - } - else if(error != EADDRINUSE && error != EACCES) { - failf(data, "bind(port=%hu) failed: %s", port, - Curl_strerror(conn, error) ); - sclose(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!"); - sclose(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) ); - sclose(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)); - sclose(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) - return result; - break; - } - else if(PORT == fcmd) { - char *source = myhost; - char *dest = tmp; - - /* translate x.x.x.x to x,x,x,x */ - while(source && *source) { - if(*source == '.') - *dest=','; - else - *dest = *source; - dest++; - source++; - } - *dest = 0; - snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff)); - - result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp); - if(result) - return result; - break; - } - } - - /* store which command was sent */ - ftpc->count1 = fcmd; - - /* we set the secondary socket variable to this for now, it is only so that - the cleanup function will close it in case we fail before the true - secondary stuff is made */ - if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) - sclose(conn->sock[SECONDARYSOCKET]); - conn->sock[SECONDARYSOCKET] = portsock; - - /* this tcpconnect assignment below is a hackish work-around to make the - multi interface with active FTP work - as it will not wait for a - (passive) connect in Curl_is_connected(). - - The *proper* fix is to make sure that the active connection from the - server is done in a non-blocking way. Currently, it is still BLOCKING. - */ - conn->bits.tcpconnect = 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; -} - -/* 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_post_rest(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->state.proto.ftp; - struct SessionHandle *data = conn->data; - - if(ftp->transfer != FTPTRANSFER_BODY) { - /* doesn't transfer any data */ - - /* still possibly do PRE QUOTE jobs */ - state(conn, FTP_RETR_PREQUOTE); - result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); - } - else if(data->set.ftp_use_port) { - /* We have chosen to use the PORT (or similar) command */ - result = ftp_state_use_port(conn, EPRT); - } - else { - /* We have chosen (this is default) to use the PASV (or similar) command */ - if(data->set.ftp_use_pret) { - /* The user has requested that we send a PRET command - to prepare the server for the upcoming PASV */ - if(!conn->proto.ftpc.file) { - PPSENDF(&conn->proto.ftpc.pp, "PRET %s", - data->set.str[STRING_CUSTOMREQUEST]? - data->set.str[STRING_CUSTOMREQUEST]: - (data->set.ftp_list_only?"NLST":"LIST")); - } - else if(data->set.upload) { - PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file); - } - else { - PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file); - } - state(conn, FTP_PRET); - } - else { - result = ftp_state_use_pasv(conn); - } - } - return result; -} - -static CURLcode ftp_state_post_size(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->state.proto.ftp; - 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_post_rest(conn); - - return result; -} - -static CURLcode ftp_state_post_type(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->state.proto.ftp; - 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_post_size(conn); - - return result; -} - -static CURLcode ftp_state_post_listtype(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - - /* If this output is to be machine-parsed, the NLST command might be better - to use, since the LIST command output is not specified or standard in any - way. It has turned out that the NLST list output is not the same on all - servers either... */ - - /* - if FTPFILE_NOCWD was specified, we are currently in - the user's home directory, so we should add the path - as argument for the LIST / NLST / or custom command. - Whether the server will support this, is uncertain. - - The other ftp_filemethods will CWD into dir/dir/ first and - then just do LIST (in that case: nothing to do here) - */ - char *cmd,*lstArg,*slashPos; - - lstArg = NULL; - if((data->set.ftp_filemethod == FTPFILE_NOCWD) && - data->state.path && - data->state.path[0] && - strchr(data->state.path,'/')) { - - lstArg = strdup(data->state.path); - if(!lstArg) - return CURLE_OUT_OF_MEMORY; - - /* Check if path does not end with /, as then we cut off the file part */ - if(lstArg[strlen(lstArg) - 1] != '/') { - - /* chop off the file part if format is dir/dir/file */ - slashPos = strrchr(lstArg,'/'); - if(slashPos) - *(slashPos+1) = '\0'; - } - } - - cmd = aprintf( "%s%s%s", - data->set.str[STRING_CUSTOMREQUEST]? - data->set.str[STRING_CUSTOMREQUEST]: - (data->set.ftp_list_only?"NLST":"LIST"), - lstArg? " ": "", - lstArg? lstArg: "" ); - - if(!cmd) { - if(lstArg) - free(lstArg); - return CURLE_OUT_OF_MEMORY; - } - - PPSENDF(&conn->proto.ftpc.pp, "%s",cmd); - - if(lstArg) - free(lstArg); - - free(cmd); - - state(conn, FTP_LIST); - - return result; -} - -static CURLcode ftp_state_post_retrtype(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_post_stortype(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_post_mdtm(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->state.proto.ftp; - struct SessionHandle *data = conn->data; - struct ftp_conn *ftpc = &conn->proto.ftpc; - - /* If we have selected NOBODY and HEADER, it means that we only want file - information. Which in FTP can't be much more than the file size and - date. */ - if(data->set.opt_no_body && ftpc->file && - ftp_need_type(conn, data->set.prefer_ascii)) { - /* The SIZE command is _not_ RFC 959 specified, and therefor many servers - may not support it! It is however the only way we have to get a file's - size! */ - - ftp->transfer = FTPTRANSFER_INFO; - /* this means no actual transfer will be made */ - - /* Some servers return different sizes for different modes, and thus we - must set the proper type before we check the size */ - result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE); - if(result) - return result; - } - else - result = ftp_state_post_type(conn); - - return result; -} - -/* This is called after the CWD commands have been done in the beginning of - the DO phase */ -static CURLcode ftp_state_post_cwd(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - struct ftp_conn *ftpc = &conn->proto.ftpc; - - /* Requested time of file or time-depended transfer? */ - if((data->set.get_filetime || data->set.timecondition) && ftpc->file) { - - /* we have requested to get the modified-time of the file, this is a white - spot as the MDTM is not mentioned in RFC959 */ - PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file); - - state(conn, FTP_MDTM); - } - else - result = ftp_state_post_mdtm(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->state.proto.ftp; - struct SessionHandle *data = conn->data; - struct ftp_conn *ftpc = &conn->proto.ftpc; - int seekerr = CURL_SEEKFUNC_OK; - - if((data->state.resume_from && !sizechecked) || - ((data->state.resume_from > 0) && sizechecked)) { - /* we're about to continue the uploading of a file */ - /* 1. get already existing file's size. We use the SIZE command for this - which may not exist in the server! The SIZE command is not in - RFC959. */ - - /* 2. This used to set REST. But since we can do append, we - don't another ftp command. We just skip the source file - offset and then we APPEND the rest on the file instead */ - - /* 3. pass file-size number of bytes in the source file */ - /* 4. lower the infilesize counter */ - /* => transfer as usual */ - - if(data->state.resume_from < 0 ) { - /* Got no given size to start from, figure it out */ - PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); - state(conn, FTP_STOR_SIZE); - return result; - } - - /* enable append */ - data->set.ftp_append = TRUE; - - /* Let's read off the proper amount of bytes from the input. */ - if(conn->seek_func) { - seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, - SEEK_SET); - } - - if(seekerr != CURL_SEEKFUNC_OK) { - if(seekerr != CURL_SEEKFUNC_CANTSEEK) { - failf(data, "Could not seek stream"); - return CURLE_FTP_COULDNT_USE_REST; - } - /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ - else { - curl_off_t passed=0; - do { - size_t readthisamountnow = - (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? - BUFSIZE : curlx_sotouz(data->state.resume_from - passed); - - size_t actuallyread = - conn->fread_func(data->state.buffer, 1, readthisamountnow, - conn->fread_in); - - passed += actuallyread; - if((actuallyread == 0) || (actuallyread > readthisamountnow)) { - /* this checks for greater-than only to make sure that the - CURL_READFUNC_ABORT return code still aborts */ - failf(data, "Failed to read data"); - return CURLE_FTP_COULDNT_USE_REST; - } - } while(passed < data->state.resume_from); - } - } - /* now, decrease the size of the read */ - if(data->set.infilesize>0) { - data->set.infilesize -= data->state.resume_from; - - if(data->set.infilesize <= 0) { - infof(data, "File already completely uploaded\n"); - - /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - - /* Set ->transfer so that we won't get any error in - * ftp_done() because we didn't transfer anything! */ - ftp->transfer = FTPTRANSFER_NONE; - - state(conn, FTP_STOP); - return CURLE_OK; - } - } - /* we've passed, proceed as normal */ - } /* resume_from */ - - PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s", - ftpc->file); - - state(conn, FTP_STOR); - - return result; -} - -static CURLcode ftp_state_quote(struct connectdata *conn, - bool init, - ftpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - struct FTP *ftp = data->state.proto.ftp; - struct ftp_conn *ftpc = &conn->proto.ftpc; - bool quote=FALSE; - struct curl_slist *item; - - switch(instate) { - case FTP_QUOTE: - default: - item = data->set.quote; - break; - case FTP_RETR_PREQUOTE: - case FTP_STOR_PREQUOTE: - item = data->set.prequote; - break; - case FTP_POSTQUOTE: - item = data->set.postquote; - break; - } - - /* - * This state uses: - * 'count1' to iterate over the commands to send - * 'count2' to store wether to allow commands to fail - */ - - if(init) - ftpc->count1 = 0; - else - ftpc->count1++; - - if(item) { - int i = 0; - - /* Skip count1 items in the linked list */ - while((i< ftpc->count1) && item) { - item = item->next; - i++; - } - if(item) { - char *cmd = item->data; - if(cmd[0] == '*') { - cmd++; - ftpc->count2 = 1; /* the sent command is allowed to fail */ - } - else - ftpc->count2 = 0; /* failure means cancel operation */ - - PPSENDF(&ftpc->pp, "%s", cmd); - state(conn, instate); - quote = TRUE; - } - } - - if(!quote) { - /* No more quote to send, continue to ... */ - switch(instate) { - case FTP_QUOTE: - default: - result = ftp_state_cwd(conn); - break; - case FTP_RETR_PREQUOTE: - if(ftp->transfer != FTPTRANSFER_BODY) - state(conn, FTP_STOP); - else { - if(ftpc->known_filesize != -1) { - Curl_pgrsSetDownloadSize(data, ftpc->known_filesize); - result = ftp_state_post_retr_size(conn, ftpc->known_filesize); - } - else { - PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); - state(conn, FTP_RETR_SIZE); - } - } - break; - case FTP_STOR_PREQUOTE: - result = ftp_state_ul_setup(conn, FALSE); - break; - case FTP_POSTQUOTE: - break; - } - } - - return result; -} - -static CURLcode ftp_state_pasv_resp(struct connectdata *conn, - int ftpcode) -{ - struct ftp_conn *ftpc = &conn->proto.ftpc; - CURLcode result; - struct SessionHandle *data=conn->data; - Curl_addrinfo *conninfo; - struct Curl_dns_entry *addr=NULL; - int rc; - unsigned short connectport; /* the local port connect() should use! */ - unsigned short newport=0; /* remote port */ - bool connected; - - /* newhost must be able to hold a full IP-style address in ASCII, which - in the IPv6 case means 5*8-1 = 39 letters */ -#define NEWHOST_BUFSIZE 48 - char newhost[NEWHOST_BUFSIZE]; - char *str=&data->state.buffer[4]; /* start on the first letter */ - - if((ftpc->count1 == 0) && - (ftpcode == 229)) { - /* positive EPSV response */ - char *ptr = strchr(str, '('); - if(ptr) { - unsigned int num; - char separator[4]; - ptr++; - if(5 == sscanf(ptr, "%c%c%c%u%c", - &separator[0], - &separator[1], - &separator[2], - &num, - &separator[3])) { - const char sep1 = separator[0]; - int i; - - /* The four separators should be identical, or else this is an oddly - formatted reply and we bail out immediately. */ - for(i=1; i<4; i++) { - if(separator[i] != sep1) { - ptr=NULL; /* set to NULL to signal error */ - break; - } - } - if(ptr) { - newport = (unsigned short)(num & 0xffff); - - if(conn->bits.tunnel_proxy || - data->set.proxytype == CURLPROXY_SOCKS5 || - data->set.proxytype == CURLPROXY_SOCKS5_HOSTNAME || - data->set.proxytype == CURLPROXY_SOCKS4 || - data->set.proxytype == CURLPROXY_SOCKS4A) - /* proxy tunnel -> use other host info because ip_addr_str is the - proxy address not the ftp host */ - snprintf(newhost, sizeof(newhost), "%s", conn->host.name); - else - /* use the same IP we are already connected to */ - snprintf(newhost, NEWHOST_BUFSIZE, "%s", conn->ip_addr_str); - } - } - else - ptr=NULL; - } - if(!ptr) { - failf(data, "Weirdly formatted EPSV reply"); - return CURLE_FTP_WEIRD_PASV_REPLY; - } - } - else if((ftpc->count1 == 1) && - (ftpcode == 227)) { - /* positive PASV response */ - int ip[4]; - int port[2]; - - /* - * Scan for a sequence of six comma-separated numbers and use them as - * IP+port indicators. - * - * Found reply-strings include: - * "227 Entering Passive Mode (127,0,0,1,4,51)" - * "227 Data transfer will passively listen to 127,0,0,1,4,51" - * "227 Entering passive mode. 127,0,0,1,4,51" - */ - while(*str) { - if(6 == sscanf(str, "%d,%d,%d,%d,%d,%d", - &ip[0], &ip[1], &ip[2], &ip[3], - &port[0], &port[1])) - break; - str++; - } - - if(!*str) { - failf(data, "Couldn't interpret the 227-response"); - return CURLE_FTP_WEIRD_227_FORMAT; - } - - /* we got OK from server */ - if(data->set.ftp_skip_ip) { - /* told to ignore the remotely given IP but instead use the one we used - for the control connection */ - infof(data, "Skips %d.%d.%d.%d for data connection, uses %s instead\n", - ip[0], ip[1], ip[2], ip[3], - conn->ip_addr_str); - if(conn->bits.tunnel_proxy || - data->set.proxytype == CURLPROXY_SOCKS5 || - data->set.proxytype == CURLPROXY_SOCKS5_HOSTNAME || - data->set.proxytype == CURLPROXY_SOCKS4 || - data->set.proxytype == CURLPROXY_SOCKS4A) - /* proxy tunnel -> use other host info because ip_addr_str is the - proxy address not the ftp host */ - snprintf(newhost, sizeof(newhost), "%s", conn->host.name); - else - snprintf(newhost, sizeof(newhost), "%s", conn->ip_addr_str); - } - else - snprintf(newhost, sizeof(newhost), - "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); - newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); - } - else if(ftpc->count1 == 0) { - /* EPSV failed, move on to PASV */ - - /* disable it for next transfer */ - conn->bits.ftp_use_epsv = FALSE; - infof(data, "disabling EPSV usage\n"); - - PPSENDF(&ftpc->pp, "PASV", NULL); - ftpc->count1++; - /* remain in the FTP_PASV state */ - return result; - } - else { - failf(data, "Bad PASV/EPSV response: %03d", ftpcode); - return CURLE_FTP_WEIRD_PASV_REPLY; - } - - if(data->set.str[STRING_PROXY] && *data->set.str[STRING_PROXY]) { - /* - * This is a tunnel through a http proxy and we need to connect to the - * proxy again here. - * - * We don't want to rely on a former host lookup that might've expired - * now, instead we remake the lookup here and now! - */ - rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr); - if(rc == CURLRESOLV_PENDING) - /* BLOCKING, ignores the return code but 'addr' will be NULL in - case of failure */ - (void)Curl_wait_for_resolv(conn, &addr); - - connectport = - (unsigned short)conn->port; /* we connect to the proxy's port */ - - if(!addr) { - failf(data, "Can't resolve proxy host %s:%hu", - conn->proxy.name, connectport); - return CURLE_FTP_CANT_GET_HOST; - } - } - else { - /* normal, direct, ftp connection */ - rc = Curl_resolv(conn, newhost, newport, &addr); - if(rc == CURLRESOLV_PENDING) - /* BLOCKING */ - (void)Curl_wait_for_resolv(conn, &addr); - - connectport = newport; /* we connect to the remote port */ - - if(!addr) { - failf(data, "Can't resolve new host %s:%hu", newhost, connectport); - return CURLE_FTP_CANT_GET_HOST; - } - } - - result = Curl_connecthost(conn, - addr, - &conn->sock[SECONDARYSOCKET], - &conninfo, - &connected); - - Curl_resolv_unlock(data, addr); /* we're done using this address */ - - if(result && ftpc->count1 == 0 && ftpcode == 229) { - infof(data, "got positive EPSV response, but can't connect. " - "Disabling EPSV\n"); - /* disable it for next transfer */ - conn->bits.ftp_use_epsv = FALSE; - data->state.errorbuf = FALSE; /* allow error message to get rewritten */ - PPSENDF(&ftpc->pp, "PASV", NULL); - ftpc->count1++; - /* remain in the FTP_PASV state */ - return result; - } - - if(result) - return result; - - conn->bits.tcpconnect = connected; /* simply TRUE or FALSE */ - - /* - * 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 and we should not be "hanging" here waiting. - */ - - if(data->set.verbose) - /* this just dumps information about this second connection */ - ftp_pasv_verbose(conn, conninfo, newhost, connectport); - - switch(data->set.proxytype) { - /* FIX: this MUST wait for a proper connect first if 'connected' is - * FALSE */ - case CURLPROXY_SOCKS5: - case CURLPROXY_SOCKS5_HOSTNAME: - result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, newport, - SECONDARYSOCKET, conn); - break; - case CURLPROXY_SOCKS4: - result = Curl_SOCKS4(conn->proxyuser, newhost, newport, - SECONDARYSOCKET, conn, FALSE); - break; - case CURLPROXY_SOCKS4A: - result = Curl_SOCKS4(conn->proxyuser, newhost, newport, - SECONDARYSOCKET, conn, TRUE); - break; - case CURLPROXY_HTTP: - case CURLPROXY_HTTP_1_0: - /* do nothing here. handled later. */ - break; - default: - failf(data, "unknown proxytype option given"); - result = CURLE_COULDNT_CONNECT; - break; - } - - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - /* FIX: this MUST wait for a proper connect first if 'connected' is - * FALSE */ - - /* BLOCKING */ - /* We want "seamless" FTP operations through HTTP proxy tunnel */ - - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member - * conn->proto.http; we want FTP through HTTP and we have to change the - * member temporarily for connecting to the HTTP proxy. After - * Curl_proxyCONNECT we have to set back the member to the original struct - * FTP pointer - */ - struct HTTP http_proxy; - struct FTP *ftp_save = data->state.proto.ftp; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->state.proto.http = &http_proxy; - - result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport); - - data->state.proto.ftp = ftp_save; - - if(CURLE_OK != result) - return result; - } - - - state(conn, FTP_STOP); /* this phase is completed */ - - return result; -} - -static CURLcode ftp_state_port_resp(struct connectdata *conn, - int ftpcode) -{ - struct SessionHandle *data = conn->data; - struct ftp_conn *ftpc = &conn->proto.ftpc; - ftpport fcmd = (ftpport)ftpc->count1; - CURLcode result = CURLE_OK; - - if(ftpcode != 200) { - /* the command failed */ - - if(EPRT == fcmd) { - infof(data, "disabling EPRT usage\n"); - conn->bits.ftp_use_eprt = FALSE; - } - fcmd++; - - if(fcmd == DONE) { - failf(data, "Failed to do PORT"); - result = CURLE_FTP_PORT_FAILED; - } - else - /* try next */ - result = ftp_state_use_port(conn, fcmd); - } - else { - infof(data, "Connect data stream actively\n"); - state(conn, FTP_STOP); /* end of DO phase */ - } - - return result; -} - -static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, - int ftpcode) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data=conn->data; - struct FTP *ftp = data->state.proto.ftp; - struct ftp_conn *ftpc = &conn->proto.ftpc; - - switch(ftpcode) { - case 213: - { - /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the - last .sss part is optional and means fractions of a second */ - int year, month, day, hour, minute, second; - char *buf = data->state.buffer; - if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d", - &year, &month, &day, &hour, &minute, &second)) { - /* we have a time, reformat it */ - time_t secs=time(NULL); - /* using the good old yacc/bison yuck */ - snprintf(buf, sizeof(conn->data->state.buffer), - "%04d%02d%02d %02d:%02d:%02d GMT", - year, month, day, hour, minute, second); - /* now, convert this into a time() value: */ - data->info.filetime = (long)curl_getdate(buf, &secs); - } - -#ifdef CURL_FTP_HTTPSTYLE_HEAD - /* If we asked for a time of the file and we actually got one as well, - we "emulate" a HTTP-style header in our output. */ - - if(data->set.opt_no_body && - ftpc->file && - data->set.get_filetime && - (data->info.filetime>=0) ) { - time_t filetime = (time_t)data->info.filetime; - struct tm buffer; - const struct tm *tm = &buffer; - - result = Curl_gmtime(filetime, &buffer); - if(result) - return result; - - /* format: "Tue, 15 Nov 1994 12:45:26" */ - snprintf(buf, BUFSIZE-1, - "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", - Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], - tm->tm_mday, - Curl_month[tm->tm_mon], - tm->tm_year + 1900, - tm->tm_hour, - tm->tm_min, - tm->tm_sec); - result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); - if(result) - return result; - } /* end of a ridiculous amount of conditionals */ -#endif - } - break; - default: - infof(data, "unsupported MDTM reply format\n"); - break; - case 550: /* "No such file or directory" */ - failf(data, "Given file does not exist"); - result = CURLE_FTP_COULDNT_RETR_FILE; - break; - } - - if(data->set.timecondition) { - if((data->info.filetime > 0) && (data->set.timevalue > 0)) { - switch(data->set.timecondition) { - case CURL_TIMECOND_IFMODSINCE: - default: - if(data->info.filetime <= data->set.timevalue) { - infof(data, "The requested document is not new enough\n"); - ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ - data->info.timecond = TRUE; - state(conn, FTP_STOP); - return CURLE_OK; - } - break; - case CURL_TIMECOND_IFUNMODSINCE: - if(data->info.filetime > data->set.timevalue) { - infof(data, "The requested document is not old enough\n"); - ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ - data->info.timecond = TRUE; - state(conn, FTP_STOP); - return CURLE_OK; - } - break; - } /* switch */ - } - else { - infof(data, "Skipping time comparison\n"); - } - } - - if(!result) - result = ftp_state_post_mdtm(conn); - - return result; -} - -static CURLcode ftp_state_type_resp(struct connectdata *conn, - int ftpcode, - ftpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data=conn->data; - - if(ftpcode/100 != 2) { - /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a - successful 'TYPE I'. While that is not as RFC959 says, it is still a - positive response code and we allow that. */ - failf(data, "Couldn't set desired mode"); - return CURLE_FTP_COULDNT_SET_TYPE; - } - if(ftpcode != 200) - infof(data, "Got a %03d response code instead of the assumed 200\n", - ftpcode); - - if(instate == FTP_TYPE) - result = ftp_state_post_type(conn); - else if(instate == FTP_LIST_TYPE) - result = ftp_state_post_listtype(conn); - else if(instate == FTP_RETR_TYPE) - result = ftp_state_post_retrtype(conn); - else if(instate == FTP_STOR_TYPE) - result = ftp_state_post_stortype(conn); - - return result; -} - -static CURLcode ftp_state_post_retr_size(struct connectdata *conn, - curl_off_t filesize) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data=conn->data; - struct FTP *ftp = data->state.proto.ftp; - 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 (%" FORMAT_OFF_T - ") was beyond file size (%" FORMAT_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 (%" FORMAT_OFF_T - ") was beyond file size (%" FORMAT_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 %" FORMAT_OFF_T - "\n", data->state.resume_from); - - PPSENDF(&ftpc->pp, "REST %" FORMAT_OFF_T, data->state.resume_from); - - state(conn, FTP_RETR_REST); - - } - else { - /* no resume */ - PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); - state(conn, FTP_RETR); - } - - return result; -} - -static CURLcode ftp_state_size_resp(struct connectdata *conn, - int ftpcode, - ftpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data=conn->data; - curl_off_t filesize; - char *buf = data->state.buffer; - - /* get the size from the ascii string: */ - filesize = (ftpcode == 213)?curlx_strtoofft(buf+4, NULL, 0):-1; - - if(instate == FTP_SIZE) { -#ifdef CURL_FTP_HTTPSTYLE_HEAD - if(-1 != filesize) { - snprintf(buf, sizeof(data->state.buffer), - "Content-Length: %" FORMAT_OFF_T "\r\n", filesize); - result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); - if(result) - return result; - } -#endif - Curl_pgrsSetDownloadSize(data, filesize); - result = ftp_state_post_size(conn); - } - else if(instate == FTP_RETR_SIZE) { - Curl_pgrsSetDownloadSize(data, filesize); - result = ftp_state_post_retr_size(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_post_rest(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) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - struct FTP *ftp = data->state.proto.ftp; - - if(ftpcode>=400) { - failf(data, "Failed FTP upload: %0d", ftpcode); - /* oops, we never close the sockets! */ - return CURLE_UPLOAD_FAILED; - } - - if(data->set.ftp_use_port) { - /* BLOCKING */ - /* PORT means we are now awaiting the server to connect to us. */ - result = AllowServerConnect(conn); - if( result ) - return result; - } - - if(conn->ssl[SECONDARYSOCKET].use) { - /* since we only have a plaintext TCP connection here, we must now - do the TLS stuff */ - infof(data, "Doing the SSL/TLS handshake on the data stream\n"); - /* BLOCKING */ - result = Curl_ssl_connect(conn, SECONDARYSOCKET); - if(result) - return result; - } - - *(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->set.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); - state(conn, FTP_STOP); - - conn->proto.ftpc.pp.pending_resp = TRUE; /* expect a server response */ - - return result; -} - -/* for LIST and RETR responses */ -static CURLcode ftp_state_get_resp(struct connectdata *conn, - int ftpcode, - ftpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - struct FTP *ftp = data->state.proto.ftp; - char *buf = data->state.buffer; - - if((ftpcode == 150) || (ftpcode == 125)) { - - /* - A; - 150 Opening BINARY mode data connection for /etc/passwd (2241 - bytes). (ok, the file is being transferred) - - B: - 150 Opening ASCII mode data connection for /bin/ls - - C: - 150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes). - - D: - 150 Opening ASCII mode data connection for /linux/fisk/kpanelrc (0.0.0.0,0) (545 bytes). - - E: - 125 Data connection already open; Transfer starting. */ - - curl_off_t size=-1; /* default unknown size */ - - - /* - * It appears that there are FTP-servers that return size 0 for files when - * SIZE is used on the file while being in BINARY mode. To work around - * that (stupid) behavior, we attempt to parse the RETR response even if - * the SIZE returned size zero. - * - * Debugging help from Salvatore Sorrentino on February 26, 2003. - */ - - if((instate != FTP_LIST) && - !data->set.prefer_ascii && - (ftp->downloadsize < 1)) { - /* - * It seems directory listings either don't show the size or very - * often uses size 0 anyway. ASCII transfers may very well turn out - * that the transferred amount of data is not the same as this line - * tells, why using this number in those cases only confuses us. - * - * Example D above makes this parsing a little tricky */ - char *bytes; - bytes=strstr(buf, " bytes"); - if(bytes--) { - long in=(long)(bytes-buf); - /* this is a hint there is size information in there! ;-) */ - while(--in) { - /* scan for the left parenthesis and break there */ - if('(' == *bytes) - break; - /* skip only digits */ - if(!ISDIGIT(*bytes)) { - bytes=NULL; - break; - } - /* one more estep backwards */ - bytes--; - } - /* if we have nothing but digits: */ - if(bytes++) { - /* get the number! */ - size = curlx_strtoofft(bytes, NULL, 0); - } - } - } - else if(ftp->downloadsize > -1) - size = ftp->downloadsize; - - if(data->set.ftp_use_port) { - /* BLOCKING */ - result = AllowServerConnect(conn); - if( result ) - return result; - } - - if(conn->ssl[SECONDARYSOCKET].use) { - /* since we only have a plaintext TCP connection here, we must now - do the TLS stuff */ - infof(data, "Doing the SSL/TLS handshake on the data stream\n"); - result = Curl_ssl_connect(conn, SECONDARYSOCKET); - if(result) - return result; - } - - if(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 = %" FORMAT_OFF_T "\n", data->req.maxdownload); - - if(instate != FTP_LIST) - infof(data, "Getting file with size: %" FORMAT_OFF_T "\n", size); - - /* FTP download: */ - Curl_setup_transfer(conn, SECONDARYSOCKET, size, FALSE, - ftp->bytecountp, -1, NULL); /* no upload here */ - - conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */ - state(conn, FTP_STOP); - } - 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; - -#ifdef HAVE_KRB4 - if(conn->data->set.krb) { - /* We may need to issue a KAUTH here to have access to the files - * do it if user supplied a password - */ - if(conn->passwd && *conn->passwd) { - /* BLOCKING */ - result = Curl_krb_kauth(conn); - if(result) - return result; - } - } -#endif - if(conn->ssl[FIRSTSOCKET].use) { - /* PBSZ = PROTECTION BUFFER SIZE. - - The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says: - - Specifically, the PROT command MUST be preceded by a PBSZ - command and a PBSZ command MUST be preceded by a successful - security data exchange (the TLS negotiation in this case) - - ... (and on page 8): - - Thus the PBSZ command must still be issued, but must have a - parameter of '0' to indicate that no buffering is taking place - and the data connection should not be encapsulated. - */ - PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0); - state(conn, FTP_PBSZ); - } - else { - result = ftp_state_pwd(conn); - } - return result; -} - -/* for USER and PASS responses */ -static CURLcode ftp_state_user_resp(struct connectdata *conn, - int ftpcode, - ftpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - struct FTP *ftp = data->state.proto.ftp; - struct ftp_conn *ftpc = &conn->proto.ftpc; - (void)instate; /* no use for this yet */ - - /* some need password anyway, and others just return 2xx ignored */ - if((ftpcode == 331) && (ftpc->state == FTP_USER)) { - /* 331 Password required for ... - (the server requires to send the user's password too) */ - PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:""); - state(conn, FTP_PASS); - } - else if(ftpcode/100 == 2) { - /* 230 User ... logged in. - (the user logged in with or without password) */ - result = ftp_state_loggedin(conn); - } - else if(ftpcode == 332) { - if(data->set.str[STRING_FTP_ACCOUNT]) { - PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]); - state(conn, FTP_ACCT); - } - else { - failf(data, "ACCT requested but none available"); - result = CURLE_LOGIN_DENIED; - } - } - else { - /* All other response codes, like: - - 530 User ... access denied - (the server denies to log the specified user) */ - - if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] && - !conn->data->state.ftp_trying_alternative) { - /* Ok, USER failed. Let's try the supplied command. */ - PPSENDF(&conn->proto.ftpc.pp, "%s", - conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); - conn->data->state.ftp_trying_alternative = TRUE; - state(conn, FTP_USER); - result = CURLE_OK; - } - else { - failf(data, "Access denied: %03d", ftpcode); - result = CURLE_LOGIN_DENIED; - } - } - return result; -} - -/* for ACCT response */ -static CURLcode ftp_state_acct_resp(struct connectdata *conn, - int ftpcode) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - if(ftpcode != 230) { - failf(data, "ACCT rejected by server: %03d", ftpcode); - result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */ - } - else - result = ftp_state_loggedin(conn); - - return result; -} - - -static CURLcode ftp_statemach_act(struct connectdata *conn) -{ - CURLcode result; - curl_socket_t sock = conn->sock[FIRSTSOCKET]; - struct SessionHandle *data=conn->data; - int ftpcode; - struct ftp_conn *ftpc = &conn->proto.ftpc; - struct pingpong *pp = &ftpc->pp; - static const char ftpauth[][4] = { "SSL", "TLS" }; - size_t nread = 0; - - if(pp->sendleft) - return Curl_pp_flushsend(pp); - - /* we read a piece of response */ - 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 != 220) { - failf(data, "Got a %03d ftp-server response when 220 was expected", - ftpcode); - return CURLE_FTP_WEIRD_SERVER_REPLY; - } - - /* We have received a 220 response fine, now we proceed. */ -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - if(data->set.krb) { - /* If not anonymous login, try a secure login. Note that this - procedure is still BLOCKING. */ - - Curl_sec_request_prot(conn, "private"); - /* We set private first as default, in case the line below fails to - set a valid level */ - Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]); - - if(Curl_sec_login(conn) != CURLE_OK) - infof(data, "Logging in with password in cleartext!\n"); - else - infof(data, "Authentication successful\n"); - } -#endif - - if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) { - /* We don't have a SSL/TLS connection yet, but FTPS is - requested. Try a FTPS connection now */ - - ftpc->count3=0; - switch(data->set.ftpsslauth) { - case CURLFTPAUTH_DEFAULT: - case CURLFTPAUTH_SSL: - ftpc->count2 = 1; /* add one to get next */ - ftpc->count1 = 0; - break; - case CURLFTPAUTH_TLS: - ftpc->count2 = -1; /* subtract one to get next */ - ftpc->count1 = 1; - break; - default: - failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d", - (int)data->set.ftpsslauth); - return CURLE_UNKNOWN_OPTION; /* we don't know what to do */ - } - PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); - state(conn, FTP_AUTH); - } - else { - result = ftp_state_user(conn); - if(result) - return result; - } - - break; - - case FTP_AUTH: - /* we have gotten the response to a previous AUTH command */ - - /* RFC2228 (page 5) says: - * - * If the server is willing to accept the named security mechanism, - * and does not require any security data, it must respond with - * reply code 234/334. - */ - - if((ftpcode == 234) || (ftpcode == 334)) { - /* Curl_ssl_connect is BLOCKING */ - result = Curl_ssl_connect(conn, FIRSTSOCKET); - if(CURLE_OK == result) { - conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */ - result = ftp_state_user(conn); - } - } - else if(ftpc->count3 < 1) { - ftpc->count3++; - ftpc->count1 += ftpc->count2; /* get next attempt */ - result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); - /* remain in this same state */ - } - else { - if(data->set.ftp_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.ftp_ssl == CURLUSESSL_CONTROL ? 'C' : 'P'); - state(conn, FTP_PROT); - - break; - - case FTP_PROT: - if(ftpcode/100 == 2) - /* We have enabled SSL for the data connection! */ - conn->ssl[SECONDARYSOCKET].use = - (bool)(data->set.ftp_ssl != CURLUSESSL_CONTROL); - /* FTP servers typically responds with 500 if they decide to reject - our 'P' request */ - else if(data->set.ftp_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, "CCC", NULL); - state(conn, FTP_CCC); - } - else { - result = ftp_state_pwd(conn); - if(result) - return result; - } - break; - - case FTP_CCC: - if(ftpcode < 500) { - /* First shut down the SSL layer (note: this call will block) */ - result = Curl_ssl_shutdown(conn, FIRSTSOCKET); - - if(result) { - failf(conn->data, "Failed to clear the command channel (CCC)"); - return result; - } - } - - /* Then continue as normal */ - result = ftp_state_pwd(conn); - if(result) - return result; - break; - - case FTP_PWD: - if(ftpcode == 257) { - char *ptr=&data->state.buffer[4]; /* start on the first letter */ - char *dir; - char *store; - - dir = malloc(nread + 1); - if(!dir) - return CURLE_OUT_OF_MEMORY; - - /* Reply format is like - 257"" and the RFC959 - says - - The directory name can contain any character; embedded - double-quotes should be escaped by double-quotes (the - "quote-doubling" convention). - */ - if('\"' == *ptr) { - /* it started good */ - ptr++; - for (store = dir; *ptr;) { - if('\"' == *ptr) { - if('\"' == ptr[1]) { - /* "quote-doubling" */ - *store = ptr[1]; - ptr++; - } - else { - /* end of path */ - *store = '\0'; /* zero terminate */ - break; /* get out of this loop */ - } - } - else - *store = *ptr; - store++; - ptr++; - } - if(ftpc->entrypath) - free(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; - - /* If the path name does not look like an absolute path (i.e.: it - does not start with a '/'), we probably need some server-dependent - adjustments. For example, this is the case when connecting to - an OS400 FTP server: this server supports two name syntaxes, - the default one being incompatible with standard pathes. In - addition, this server switches automatically to the regular path - syntax when one is encountered in a command: this results in - having an entrypath in the wrong syntax when later used in CWD. - The method used here is to check the server OS: we do it only - if the path name looks strange to minimize overhead on other - systems. */ - - if(!ftpc->server_os && ftpc->entrypath[0] != '/') { - PPSENDF(&ftpc->pp, "SYST", NULL); - state(conn, FTP_SYST); - break; - } - } - 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 - */ - while (*ptr == ' ') - ptr++; - for (store = os; *ptr && *ptr != ' ';) - *store++ = *ptr++; - *store = '\0'; /* zero terminate */ - ftpc->server_os = os; - - /* Check for special servers here. */ - - if(strequal(ftpc->server_os, "OS/400")) { - /* Force OS400 name format 1. */ - PPSENDF(&ftpc->pp, "SITE NAMEFMT 1", NULL); - state(conn, FTP_NAMEFMT); - break; - } - else { - /* Nothing special for the target server. */ - } - } - else { - /* Cannot identify server OS. Continue anyway and cross fingers. */ - } - - state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ - DEBUGF(infof(data, "protocol connect phase DONE\n")); - break; - - case FTP_NAMEFMT: - if(ftpcode == 250) { - /* Name format change successful: reload initial path. */ - ftp_state_pwd(conn); - break; - } - - state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ - DEBUGF(infof(data, "protocol connect phase DONE\n")); - break; - - case FTP_QUOTE: - case FTP_POSTQUOTE: - case FTP_RETR_PREQUOTE: - case FTP_STOR_PREQUOTE: - if((ftpcode >= 400) && !ftpc->count2) { - /* failure response code, and not allowed to fail */ - failf(conn->data, "QUOT command failed with %03d", ftpcode); - return CURLE_QUOTE_ERROR; - } - result = ftp_state_quote(conn, FALSE, ftpc->state); - if(result) - return result; - - break; - - case FTP_CWD: - if(ftpcode/100 != 2) { - /* failure to CWD there */ - if(conn->data->set.ftp_create_missing_dirs && - ftpc->count1 && !ftpc->count2) { - /* try making it */ - ftpc->count2++; /* counter to prevent CWD-MKD loops */ - PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->count1 - 1]); - state(conn, FTP_MKD); - } - else { - /* return failure */ - failf(data, "Server denied you to change to the given directory"); - ftpc->cwdfail = TRUE; /* don't remember this path as we failed - to enter it */ - return CURLE_REMOTE_ACCESS_DENIED; - } - } - else { - /* success */ - ftpc->count2=0; - if(++ftpc->count1 <= ftpc->dirdepth) { - /* send next CWD */ - PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]); - } - else { - result = ftp_state_post_cwd(conn); - if(result) - return result; - } - } - break; - - case FTP_MKD: - if((ftpcode/100 != 2) && !ftpc->count3--) { - /* failure to MKD the dir */ - failf(data, "Failed to MKD dir: %03d", ftpcode); - return CURLE_REMOTE_ACCESS_DENIED; - } - state(conn, FTP_CWD); - /* send CWD */ - PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]); - break; - - case FTP_MDTM: - result = ftp_state_mdtm_resp(conn, ftpcode); - break; - - case FTP_TYPE: - case FTP_LIST_TYPE: - case FTP_RETR_TYPE: - case FTP_STOR_TYPE: - result = ftp_state_type_resp(conn, ftpcode, ftpc->state); - break; - - case FTP_SIZE: - case FTP_RETR_SIZE: - case FTP_STOR_SIZE: - result = ftp_state_size_resp(conn, ftpcode, ftpc->state); - break; - - case FTP_REST: - case FTP_RETR_REST: - result = ftp_state_rest_resp(conn, ftpcode, ftpc->state); - break; - - case FTP_PRET: - if(ftpcode != 200) { - /* there only is this one standard OK return code. */ - failf(data, "PRET command not accepted: %03d", ftpcode); - return CURLE_FTP_PRET_FAILED; - } - result = ftp_state_use_pasv(conn); - break; - - case FTP_PASV: - result = ftp_state_pasv_resp(conn, ftpcode); - break; - - case FTP_PORT: - result = ftp_state_port_resp(conn, ftpcode); - break; - - case FTP_LIST: - case FTP_RETR: - result = ftp_state_get_resp(conn, ftpcode, ftpc->state); - break; - - case FTP_STOR: - result = ftp_state_stor_resp(conn, ftpcode); - 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_multi_statemach(&ftpc->pp); - - /* Check for the state outside of the Curl_socket_ready() return code checks - since at times we are in fact already in this state when this function - gets called. */ - *done = (bool)(ftpc->state == FTP_STOP); - - return result; -} - -static CURLcode ftp_easy_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_easy_statemach(pp); - if(result) - break; - } - - return result; -} - -/* - * Allocate and initialize the struct FTP for the current SessionHandle. If - * need be. - */ - -#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \ - defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__) - /* workaround icc 9.1 optimizer issue */ -#pragma optimize("", off) -#endif - -static CURLcode ftp_init(struct connectdata *conn) -{ - struct FTP *ftp; - - if(NULL == conn->data->state.proto.ftp) { - conn->data->state.proto.ftp = malloc(sizeof(struct FTP)); - if(NULL == conn->data->state.proto.ftp) - return CURLE_OUT_OF_MEMORY; - } - - ftp = conn->data->state.proto.ftp; - - /* 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(TRUE == isBadFtpString(ftp->user)) - return CURLE_URL_MALFORMAT; - if(TRUE == isBadFtpString(ftp->passwd)) - return CURLE_URL_MALFORMAT; - - conn->proto.ftpc.known_filesize = -1; /* unknown size for now */ - - return CURLE_OK; -} - -#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \ - defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__) - /* workaround icc 9.1 optimizer issue */ -#pragma optimize("", on) -#endif - -/* - * 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 is not. When called as - * a part of the easy interface, it will always be TRUE. - */ -static CURLcode ftp_connect(struct connectdata *conn, - bool *done) /* see description above */ -{ - CURLcode result; - struct ftp_conn *ftpc = &conn->proto.ftpc; - struct SessionHandle *data=conn->data; - struct pingpong *pp = &ftpc->pp; - - *done = FALSE; /* default to not done yet */ - - /* If there already is a protocol-specific struct allocated for this - sessionhandle, deal with it */ - Curl_reset_reqproto(conn); - - result = ftp_init(conn); - if(CURLE_OK != result) - return result; - - /* We always support persistent connections on ftp */ - conn->bits.close = FALSE; - - 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->bits.tunnel_proxy && conn->bits.httpproxy) { - /* for FTP over HTTP proxy */ - struct HTTP http_proxy; - struct FTP *ftp_save; - - /* BLOCKING */ - /* We want "seamless" FTP operations through HTTP proxy tunnel */ - - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member - * conn->proto.http; we want FTP through HTTP and we have to change the - * member temporarily for connecting to the HTTP proxy. After - * Curl_proxyCONNECT we have to set back the member to the original struct - * FTP pointer - */ - ftp_save = data->state.proto.ftp; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->state.proto.http = &http_proxy; - - result = Curl_proxyCONNECT(conn, FIRSTSOCKET, - conn->host.name, conn->remote_port); - - data->state.proto.ftp = ftp_save; - - if(CURLE_OK != result) - return result; - } - - if(conn->handler->protocol & CURLPROTO_FTPS) { - /* BLOCKING */ - /* FTPS is simply ftp with SSL for the control channel */ - /* now, perform the SSL initialization for this socket */ - 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); - - if(data->state.used_interface == Curl_if_multi) - result = ftp_multi_statemach(conn, done); - else { - result = ftp_easy_statemach(conn); - if(!result) - *done = TRUE; - } - - return result; -} - -/*********************************************************************** - * - * ftp_done() - * - * The DONE function. This does what needs to be done after a single DO has - * performed. - * - * Input argument is already checked for validity. - */ -static CURLcode ftp_done(struct connectdata *conn, CURLcode status, - bool premature) -{ - struct SessionHandle *data = conn->data; - struct FTP *ftp = data->state.proto.ftp; - struct ftp_conn *ftpc = &conn->proto.ftpc; - struct pingpong *pp = &ftpc->pp; - ssize_t nread; - int ftpcode; - CURLcode result=CURLE_OK; - bool was_ctl_valid = ftpc->ctl_valid; - char *path; - const char *path_to_use = data->state.path; - - if(!ftp) - /* When the easy handle is removed from the multi while libcurl is still - * trying to resolve the host name, it seems that the ftp struct is not - * yet initialized, but the removal action calls Curl_done() which calls - * this function. So we simply return success if no ftp pointer is set. - */ - return CURLE_OK; - - switch(status) { - case CURLE_BAD_DOWNLOAD_RESUME: - case CURLE_FTP_WEIRD_PASV_REPLY: - case CURLE_FTP_PORT_FAILED: - case CURLE_FTP_COULDNT_SET_TYPE: - case CURLE_FTP_COULDNT_RETR_FILE: - case CURLE_UPLOAD_FAILED: - case CURLE_REMOTE_ACCESS_DENIED: - case CURLE_FILESIZE_EXCEEDED: - case CURLE_REMOTE_FILE_NOT_FOUND: - case CURLE_WRITE_ERROR: - /* the connection stays alive fine even though this happened */ - /* fall-through */ - case CURLE_OK: /* doesn't affect the control connection's status */ - if(!premature) { - ftpc->ctl_valid = was_ctl_valid; - break; - } - /* until we cope better with prematurely ended requests, let them - * fallback as if in complete failure */ - default: /* by default, an error means the control connection is - wedged and should not be used anymore */ - ftpc->ctl_valid = FALSE; - ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the - current path, as this connection is going */ - conn->bits.close = TRUE; /* marked for closure */ - result = status; /* use the already set error code */ - break; - } - - /* now store a copy of the directory we are in */ - if(ftpc->prevpath) - free(ftpc->prevpath); - - if(data->set.wildcardmatch) { - if(data->set.chunk_end && ftpc->file) { - data->set.chunk_end(data->wildcard.customptr); - } - ftpc->known_filesize = -1; - } - - /* get the "raw" path */ - path = curl_easy_unescape(data, path_to_use, 0, NULL); - if(!path) { - /* out of memory, but we can limp along anyway (and should try to - * since we're in the out of memory cleanup path) */ - ftpc->prevpath = NULL; /* no path */ - } - else { - size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */ - size_t dlen = strlen(path)-flen; - if(!ftpc->cwdfail) { - if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) { - ftpc->prevpath = path; - if(flen) - /* if 'path' is not the whole string */ - ftpc->prevpath[dlen]=0; /* terminate */ - } - else { - /* we never changed dir */ - ftpc->prevpath=strdup(""); - free(path); - } - if(ftpc->prevpath) - infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath); - } - else { - ftpc->prevpath = NULL; /* no path */ - free(path); - } - } - /* free the dir tree and file parts */ - freedirs(ftpc); - - /* shut down the socket to inform the server we're done */ - -#ifdef _WIN32_WCE - shutdown(conn->sock[SECONDARYSOCKET],2); /* SD_BOTH */ -#endif - - if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) { - if(!result && ftpc->dont_check && data->req.maxdownload > 0) - /* partial download completed */ - result = Curl_pp_sendf(pp, "ABOR"); - - if(conn->ssl[SECONDARYSOCKET].use) { - /* The secondary socket is using SSL so we must close down that part - first before we close the socket for real */ - Curl_ssl_close(conn, SECONDARYSOCKET); - - /* Note that we keep "use" set to TRUE since that (next) connection is - still requested to use SSL */ - } - if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) { - sclose(conn->sock[SECONDARYSOCKET]); - conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; - } - } - - if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid && - pp->pending_resp && !premature) { - /* - * Let's see what the server says about the transfer we just performed, - * but lower the timeout as sometimes this connection has died while the - * data has been transferred. This happens when doing through NATs etc that - * abandon old silent connections. - */ - long old_time = pp->response_time; - - pp->response_time = 60*1000; /* give it only a minute for now */ - pp->response = Curl_tvnow(); /* timeout relative now */ - - result = Curl_GetFTPResponse(&nread, conn, &ftpcode); - - pp->response_time = old_time; /* set this back to previous value */ - - if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) { - failf(data, "control connection looks dead"); - ftpc->ctl_valid = FALSE; /* mark control connection as bad */ - conn->bits.close = TRUE; /* mark for closure */ - } - - 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"); - conn->bits.close = TRUE; /* mark for closure */ - 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->set.infilesize) && - (data->set.infilesize != *ftp->bytecountp) && - !data->set.crlf && - (ftp->transfer == FTPTRANSFER_BODY)) { - failf(data, "Uploaded unaligned file size (%" FORMAT_OFF_T - " out of %" FORMAT_OFF_T " bytes)", - *ftp->bytecountp, data->set.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: %" FORMAT_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; - } - - FTPSENDF(conn, "%s", cmd); - - pp->response = Curl_tvnow(); /* timeout relative now */ - - result = Curl_GetFTPResponse(&nread, conn, &ftpcode); - if(result) - return result; - - if(!acceptfail && (ftpcode >= 400)) { - failf(conn->data, "QUOT string not accepted: %s", cmd); - return CURLE_QUOTE_ERROR; - } - } - - item = item->next; - } - - return CURLE_OK; -} - -/*********************************************************************** - * - * ftp_need_type() - * - * Returns TRUE if we in the current situation should send TYPE - */ -static int ftp_need_type(struct connectdata *conn, - bool ascii_wanted) -{ - return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I'); -} - -/*********************************************************************** - * - * ftp_nb_type() - * - * Set TYPE. We only deal with ASCII or BINARY so this function - * sets one of them. - * If the transfer type is not sent, simulate on OK response in newstate - */ -static CURLcode ftp_nb_type(struct connectdata *conn, - bool ascii, ftpstate newstate) -{ - struct ftp_conn *ftpc = &conn->proto.ftpc; - CURLcode result; - char want = (char)(ascii?'A':'I'); - - if(ftpc->transfertype == want) { - state(conn, newstate); - return ftp_state_type_resp(conn, 200, newstate); - } - - PPSENDF(&ftpc->pp, "TYPE %c", want); - state(conn, newstate); - - /* keep track of our current transfer type */ - ftpc->transfertype = want; - return CURLE_OK; -} - -/*************************************************************************** - * - * ftp_pasv_verbose() - * - * This function only outputs some informationals about this second connection - * when we've issued a PASV command before and thus we have connected to a - * possibly new IP address. - * - */ -#ifndef CURL_DISABLE_VERBOSE_STRINGS -static void -ftp_pasv_verbose(struct connectdata *conn, - Curl_addrinfo *ai, - char *newhost, /* ascii version */ - int port) -{ - char buf[256]; - Curl_printable_address(ai, buf, sizeof(buf)); - infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port); -} -#endif - -/* - Check if this is a range download, and if so, set the internal variables - properly. - */ - -static CURLcode ftp_range(struct connectdata *conn) -{ - curl_off_t from, to; - char *ptr; - char *ptr2; - struct SessionHandle *data = conn->data; - struct ftp_conn *ftpc = &conn->proto.ftpc; - - if(data->state.use_range && data->state.range) { - from=curlx_strtoofft(data->state.range, &ptr, 0); - while(*ptr && (ISSPACE(*ptr) || (*ptr=='-'))) - ptr++; - to=curlx_strtoofft(ptr, &ptr2, 0); - if(ptr == ptr2) { - /* we didn't get any digit */ - to=-1; - } - if((-1 == to) && (from>=0)) { - /* X - */ - data->state.resume_from = from; - DEBUGF(infof(conn->data, "FTP RANGE %" FORMAT_OFF_T " to end of file\n", - from)); - } - else if(from < 0) { - /* -Y */ - data->req.maxdownload = -from; - data->state.resume_from = from; - DEBUGF(infof(conn->data, "FTP RANGE the last %" FORMAT_OFF_T " bytes\n", - -from)); - } - else { - /* X-Y */ - data->req.maxdownload = (to-from)+1; /* include last byte */ - data->state.resume_from = from; - DEBUGF(infof(conn->data, "FTP RANGE from %" FORMAT_OFF_T - " getting %" FORMAT_OFF_T " bytes\n", - from, data->req.maxdownload)); - } - DEBUGF(infof(conn->data, "range-download from %" FORMAT_OFF_T - " to %" FORMAT_OFF_T ", totally %" FORMAT_OFF_T " bytes\n", - from, to, data->req.maxdownload)); - ftpc->dont_check = TRUE; /* dont check for successful transfer */ - } - else - data->req.maxdownload = -1; - return CURLE_OK; -} - - -/* - * ftp_nextconnect() - * - * This function shall be called when the second FTP (data) connection is - * connected. - */ - -static CURLcode ftp_nextconnect(struct connectdata *conn) -{ - struct SessionHandle *data=conn->data; - struct ftp_conn *ftpc = &conn->proto.ftpc; - CURLcode result = CURLE_OK; - - /* the ftp struct is inited in ftp_connect() */ - struct FTP *ftp = data->state.proto.ftp; - - DEBUGF(infof(data, "DO-MORE phase starts\n")); - - 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(data->set.upload) { - result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE); - if(result) - return result; - } - 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_easy_statemach(conn); - } - - if((result == CURLE_OK) && (ftp->transfer != FTPTRANSFER_BODY)) - /* no data to transfer. FIX: it feels like a kludge to have this here - too! */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - - /* end of transfer */ - 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->state.proto.ftp; - 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 */ - if(conn->data->state.used_interface == Curl_if_multi) - result = ftp_multi_statemach(conn, dophase_done); - else { - result = ftp_easy_statemach(conn); - *dophase_done = TRUE; /* with the easy interface we are done here */ - } - *connected = conn->bits.tcpconnect; - - if(*dophase_done) - DEBUGF(infof(conn->data, "DO phase is complete\n")); - - return result; -} - -static void wc_data_dtor(void *ptr) -{ - struct ftp_wc_tmpdata *tmp = ptr; - if(tmp) - Curl_ftp_parselist_data_free(&tmp->parser); - Curl_safefree(tmp); -} - -static CURLcode init_wc_data(struct connectdata *conn) -{ - char *last_slash; - char *path = conn->data->state.path; - struct WildcardData *wildcard = &(conn->data->wildcard); - CURLcode ret = CURLE_OK; - struct ftp_wc_tmpdata *ftp_tmp; - - last_slash = strrchr(conn->data->state.path, '/'); - if(last_slash) { - last_slash++; - if(last_slash[0] == '\0') { - wildcard->state = CURLWC_CLEAN; - ret = ftp_parse_url_path(conn); - return ret; - } - else { - wildcard->pattern = strdup(last_slash); - if (!wildcard->pattern) - return CURLE_OUT_OF_MEMORY; - last_slash[0] = '\0'; /* cut file from path */ - } - } - else { /* there is only 'wildcard pattern' or nothing */ - if(path[0]) { - wildcard->pattern = strdup(path); - if (!wildcard->pattern) - return CURLE_OUT_OF_MEMORY; - path[0] = '\0'; - } - else { /* only list */ - wildcard->state = CURLWC_CLEAN; - ret = ftp_parse_url_path(conn); - return ret; - } - } - - /* program continues only if URL is not ending with slash, allocate needed - resources for wildcard transfer */ - - /* allocate ftp protocol specific temporary wildcard data */ - ftp_tmp = malloc(sizeof(struct ftp_wc_tmpdata)); - if(!ftp_tmp) { - return CURLE_OUT_OF_MEMORY; - } - - /* INITIALIZE parselist structure */ - ftp_tmp->parser = Curl_ftp_parselist_data_alloc(); - if(!ftp_tmp->parser) { - 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 */ - ret = ftp_parse_url_path(conn); - if(ret) { - return ret; - } - - /* backup old write_function */ - ftp_tmp->backup.write_function = conn->data->set.fwrite_func; - /* parsing write function (callback included directly from ftplistparser.c) */ - 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; - - wildcard->path = strdup(conn->data->state.path); - if(!wildcard->path) { - return CURLE_OUT_OF_MEMORY; - } - - infof(conn->data, "Wildcard - Parsing started\n"); - return CURLE_OK; -} - -/* This is called recursively */ -static CURLcode wc_statemach(struct connectdata *conn) -{ - struct WildcardData * const wildcard = &(conn->data->wildcard); - CURLcode ret = CURLE_OK; - - switch (wildcard->state) { - case CURLWC_INIT: - ret = init_wc_data(conn); - if(wildcard->state == CURLWC_CLEAN) - /* only listing! */ - break; - else - wildcard->state = ret ? CURLWC_ERROR : CURLWC_MATCHING; - break; - - case CURLWC_MATCHING: { - /* In this state is LIST response successfully parsed, so lets restore - previous WRITEFUNCTION callback and WRITEDATA pointer */ - struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp; - conn->data->set.fwrite_func = ftp_tmp->backup.write_function; - conn->data->set.out = ftp_tmp->backup.file_descriptor; - wildcard->state = CURLWC_DOWNLOADING; - - if(Curl_ftp_parselist_geterror(ftp_tmp->parser)) { - /* error found in LIST parsing */ - wildcard->state = CURLWC_CLEAN; - return wc_statemach(conn); - } - else if(wildcard->filelist->size == 0) { - /* no corresponding file */ - wildcard->state = CURLWC_CLEAN; - return CURLE_REMOTE_FILE_NOT_FOUND; - } - return wc_statemach(conn); - } - - case CURLWC_DOWNLOADING: { - /* filelist has at least one file, lets get first one */ - struct ftp_conn *ftpc = &conn->proto.ftpc; - struct curl_fileinfo *finfo = wildcard->filelist->head->ptr; - char *tmp_path = malloc(strlen(conn->data->state.path) + - strlen(finfo->filename) + 1); - if(!tmp_path) { - return CURLE_OUT_OF_MEMORY; - } - - tmp_path[0] = 0; - /* make full path to matched file */ - strcat(tmp_path, wildcard->path); - strcat(tmp_path, finfo->filename); - /* switch default "state.pathbuffer" and tmp_path, good to see - ftp_parse_url_path function to understand this trick */ - if(conn->data->state.pathbuffer) - free(conn->data->state.pathbuffer); - conn->data->state.pathbuffer = tmp_path; - conn->data->state.path = tmp_path; - - infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); - if(conn->data->set.chunk_bgn) { - long userresponse = conn->data->set.chunk_bgn( - finfo, wildcard->customptr, (int)wildcard->filelist->size); - switch(userresponse) { - case CURL_CHUNK_BGN_FUNC_SKIP: - infof(conn->data, "Wildcard - \"%s\" skipped by user\n", - finfo->filename); - wildcard->state = CURLWC_SKIP; - return wc_statemach(conn); - case CURL_CHUNK_BGN_FUNC_FAIL: - return CURLE_CHUNK_FAILED; - } - } - - if(finfo->filetype != CURLFILETYPE_FILE) { - wildcard->state = CURLWC_SKIP; - return wc_statemach(conn); - } - - if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) - ftpc->known_filesize = finfo->size; - - ret = ftp_parse_url_path(conn); - if(ret) { - return ret; - } - - /* we don't need the Curl_fileinfo of first file anymore */ - Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL); - - if(wildcard->filelist->size == 0) { /* remains only one file to down. */ - wildcard->state = CURLWC_CLEAN; - /* after that will be ftp_do called once again and no transfer - will be done because of CURLWC_CLEAN state */ - return CURLE_OK; - } - } break; - - case CURLWC_SKIP: { - if(conn->data->set.chunk_end) - conn->data->set.chunk_end(conn->data->wildcard.customptr); - Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL); - wildcard->state = (wildcard->filelist->size == 0) ? - CURLWC_CLEAN : CURLWC_DOWNLOADING; - return wc_statemach(conn); - } - - case CURLWC_CLEAN: { - struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp; - ret = CURLE_OK; - if(ftp_tmp) { - ret = Curl_ftp_parselist_geterror(ftp_tmp->parser); - } - wildcard->state = ret ? CURLWC_ERROR : CURLWC_DONE; - } break; - - case CURLWC_DONE: - case CURLWC_ERROR: - break; - } - - return ret; -} - -/*********************************************************************** - * - * ftp_do() - * - * This function is registered as 'curl_do' function. It decodes the path - * parts etc as a wrapper to the actual DO function (ftp_perform). - * - * The input argument is already checked for validity. - */ -static CURLcode ftp_do(struct connectdata *conn, bool *done) -{ - CURLcode retcode = CURLE_OK; - - *done = FALSE; /* default to false */ - - /* - Since connections can be re-used between SessionHandles, this might be a - connection already existing but on a fresh SessionHandle struct so we must - make sure we have a good 'struct FTP' to play with. For new connections, - the struct FTP is allocated and setup in the ftp_connect() function. - */ - Curl_reset_reqproto(conn); - retcode = ftp_init(conn); - if(retcode) - return retcode; - - if(conn->data->set.wildcardmatch) { - retcode = wc_statemach(conn); - if(conn->data->wildcard.state == CURLWC_SKIP || - conn->data->wildcard.state == CURLWC_DONE) { - /* do not call ftp_regular_transfer */ - return CURLE_OK; - } - if(retcode) /* error, loop or skipping the file */ - return retcode; - } - else { /* no wildcard FSM needed */ - retcode = ftp_parse_url_path(conn); - if(retcode) - return retcode; - } - - retcode = ftp_regular_transfer(conn, done); - - return retcode; -} - - -CURLcode Curl_ftpsendf(struct connectdata *conn, - const char *fmt, ...) -{ - ssize_t bytes_written; -#define SBUF_SIZE 1024 - char s[SBUF_SIZE]; - size_t write_len; - char *sptr=s; - CURLcode res = CURLE_OK; -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - enum protection_level data_sec = conn->data_prot; -#endif - - va_list ap; - va_start(ap, fmt); - vsnprintf(s, SBUF_SIZE-3, fmt, ap); - va_end(ap); - - strcat(s, "\r\n"); /* append a trailing CRLF */ - - bytes_written=0; - write_len = strlen(s); - - res = Curl_convert_to_network(conn->data, s, write_len); - /* Curl_convert_to_network calls failf if unsuccessful */ - if(res) - return(res); - - for(;;) { -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - conn->data_prot = PROT_CMD; -#endif - res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, - &bytes_written); -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); - conn->data_prot = data_sec; -#endif - - if(CURLE_OK != res) - break; - - if(conn->data->set.verbose) - Curl_debug(conn->data, CURLINFO_HEADER_OUT, - sptr, (size_t)bytes_written, conn); - - if(bytes_written != (ssize_t)write_len) { - write_len -= bytes_written; - sptr += bytes_written; - } - else - break; - } - - return res; -} - -/*********************************************************************** - * - * ftp_quit() - * - * This should be called before calling sclose() on an ftp control connection - * (not data connections). We should then wait for the response from the - * server before returning. The calling code should then try to close the - * connection. - * - */ -static CURLcode ftp_quit(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - - if(conn->proto.ftpc.ctl_valid) { - PPSENDF(&conn->proto.ftpc.pp, "QUIT", NULL); - state(conn, FTP_QUIT); - - result = ftp_easy_statemach(conn); - } - - return result; -} - -/*********************************************************************** - * - * ftp_disconnect() - * - * Disconnect from an FTP server. Cleanup protocol-specific per-connection - * resources. BLOCKING. - */ -static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) -{ - struct ftp_conn *ftpc= &conn->proto.ftpc; - struct pingpong *pp = &ftpc->pp; - - /* We cannot send quit unconditionally. If this connection is stale or - bad in any way, sending quit and waiting around here will make the - disconnect wait in vain and cause more problems than we need to. - - ftp_quit() will check the state of ftp->ctl_valid. If it's ok it - will try to send the QUIT command, otherwise it will just return. - */ - if(dead_connection) - ftpc->ctl_valid = FALSE; - - /* The FTP session may or may not have been allocated/setup at this point! */ - (void)ftp_quit(conn); /* ignore errors on the QUIT */ - - if(ftpc->entrypath) { - struct SessionHandle *data = conn->data; - if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) { - data->state.most_recent_ftp_entrypath = NULL; - } - free(ftpc->entrypath); - ftpc->entrypath = NULL; - } - - freedirs(ftpc); - if(ftpc->prevpath) { - free(ftpc->prevpath); - ftpc->prevpath = NULL; - } - if(ftpc->server_os) { - free(ftpc->server_os); - ftpc->server_os = NULL; - } - - Curl_pp_disconnect(pp); - -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - Curl_sec_end(conn); -#endif - - return CURLE_OK; -} - -/*********************************************************************** - * - * ftp_parse_url_path() - * - * Parse the URL path into separate path components. - * - */ -static -CURLcode ftp_parse_url_path(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - /* the ftp struct is already inited in ftp_connect() */ - struct FTP *ftp = data->state.proto.ftp; - struct ftp_conn *ftpc = &conn->proto.ftpc; - const char *slash_pos; /* position of the first '/' char in curpos */ - const char *path_to_use = data->state.path; - const char *cur_pos; - const char *filename = NULL; - - cur_pos = path_to_use; /* current position in path. point at the begin - of next path component */ - - ftpc->ctl_valid = FALSE; - ftpc->cwdfail = FALSE; - - switch(data->set.ftp_filemethod) { - case FTPFILE_NOCWD: - /* fastest, but less standard-compliant */ - - /* - The best time to check whether the path is a file or directory is right - here. so: - - the first condition in the if() right here, is there just in case - someone decides to set path to NULL one day - */ - if(data->state.path && - data->state.path[0] && - (data->state.path[strlen(data->state.path) - 1] != '/') ) - filename = data->state.path; /* this is a full file path */ - /* - ftpc->file is not used anywhere other than for operations on a file. - In other words, never for directory operations. - So we can safely leave filename as NULL here and use it as a - argument in dir/file decisions. - */ - break; - - case FTPFILE_SINGLECWD: - /* get the last slash */ - if(!path_to_use[0]) { - /* no dir, no file */ - ftpc->dirdepth = 0; - break; - } - slash_pos=strrchr(cur_pos, '/'); - if(slash_pos || !*cur_pos) { - ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0])); - if(!ftpc->dirs) - return CURLE_OUT_OF_MEMORY; - - ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/", - slash_pos?(int)(slash_pos-cur_pos):1, - NULL); - if(!ftpc->dirs[0]) { - freedirs(ftpc); - return CURLE_OUT_OF_MEMORY; - } - ftpc->dirdepth = 1; /* we consider it to be a single dir */ - filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */ - } - else - filename = cur_pos; /* this is a file name only */ - break; - - default: /* allow pretty much anything */ - case FTPFILE_MULTICWD: - ftpc->dirdepth = 0; - ftpc->diralloc = 5; /* default dir depth to allocate */ - ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0])); - if(!ftpc->dirs) - return CURLE_OUT_OF_MEMORY; - - /* we have a special case for listing the root dir only */ - if(strequal(path_to_use, "/")) { - cur_pos++; /* make it point to the zero byte */ - ftpc->dirs[0] = strdup("/"); - ftpc->dirdepth++; - } - else { - /* parse the URL path into separate path components */ - while((slash_pos = strchr(cur_pos, '/')) != NULL) { - /* 1 or 0 pointer offset to indicate absolute directory */ - ssize_t absolute_dir = ((cur_pos - data->state.path > 0) && - (ftpc->dirdepth == 0))?1:0; - - /* seek out the next path component */ - if(slash_pos-cur_pos) { - /* we skip empty path components, like "x//y" since the FTP command - CWD requires a parameter and a non-existent parameter a) doesn't - work on many servers and b) has no effect on the others. */ - int len = (int)(slash_pos - cur_pos + absolute_dir); - ftpc->dirs[ftpc->dirdepth] = - curl_easy_unescape(conn->data, cur_pos - absolute_dir, len, NULL); - if(!ftpc->dirs[ftpc->dirdepth]) { /* run out of memory ... */ - failf(data, "no memory"); - freedirs(ftpc); - return CURLE_OUT_OF_MEMORY; - } - if(isBadFtpString(ftpc->dirs[ftpc->dirdepth])) { - free(ftpc->dirs[ftpc->dirdepth]); - freedirs(ftpc); - return CURLE_URL_MALFORMAT; - } - } - else { - cur_pos = slash_pos + 1; /* jump to the rest of the string */ - 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 = (char **)bigger; - } - } - } - filename = cur_pos; /* the rest is the file name */ - break; - } /* switch */ - - if(filename && *filename) { - ftpc->file = curl_easy_unescape(conn->data, filename, 0, NULL); - if(NULL == ftpc->file) { - freedirs(ftpc); - failf(data, "no memory"); - return CURLE_OUT_OF_MEMORY; - } - if(isBadFtpString(ftpc->file)) { - freedirs(ftpc); - return CURLE_URL_MALFORMAT; - } - } - else - ftpc->file=NULL; /* instead of point to a zero byte, we make it a NULL - pointer */ - - if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) { - /* We need a file name when uploading. Return error! */ - failf(data, "Uploading to a URL without a file name!"); - return CURLE_URL_MALFORMAT; - } - - ftpc->cwddone = FALSE; /* default to not done */ - - if(ftpc->prevpath) { - /* prevpath is "raw" so we convert the input path before we compare the - strings */ - int dlen; - char *path = curl_easy_unescape(conn->data, data->state.path, 0, &dlen); - if(!path) { - freedirs(ftpc); - return CURLE_OUT_OF_MEMORY; - } - - dlen -= ftpc->file?(int)strlen(ftpc->file):0; - if((dlen == (int)strlen(ftpc->prevpath)) && - strnequal(path, ftpc->prevpath, dlen)) { - infof(data, "Request has same path as previous transfer\n"); - ftpc->cwddone = TRUE; - } - free(path); - } - - return CURLE_OK; -} - -/* call this when the DO phase has completed */ -static CURLcode ftp_dophase_done(struct connectdata *conn, - bool connected) -{ - CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->state.proto.ftp; - struct ftp_conn *ftpc = &conn->proto.ftpc; - - if(connected) - result = ftp_nextconnect(conn); - - if(result && (conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD)) { - /* Failure detected, close the second socket if it was created already */ - sclose(conn->sock[SECONDARYSOCKET]); - conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; - return result; - } - - if(ftp->transfer != FTPTRANSFER_BODY) - /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - else if(!connected) - /* since we didn't connect now, we want do_more to get called */ - conn->bits.do_more = TRUE; - - ftpc->ctl_valid = TRUE; /* seems good */ - - return result; -} - -/* called from multi.c while DOing */ -static CURLcode ftp_doing(struct connectdata *conn, - bool *dophase_done) -{ - CURLcode result; - result = ftp_multi_statemach(conn, dophase_done); - - if(*dophase_done) { - result = ftp_dophase_done(conn, FALSE /* not connected */); - - DEBUGF(infof(conn->data, "DO phase is complete\n")); - } - return result; -} - -/*********************************************************************** - * - * ftp_regular_transfer() - * - * The input argument is already checked for validity. - * - * Performs all commands done before a regular transfer between a local and a - * remote host. - * - * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the - * ftp_done() function without finding any major problem. - */ -static -CURLcode ftp_regular_transfer(struct connectdata *conn, - bool *dophase_done) -{ - CURLcode result=CURLE_OK; - bool connected=FALSE; - struct SessionHandle *data = conn->data; - struct ftp_conn *ftpc = &conn->proto.ftpc; - data->req.size = -1; /* make sure this is unknown at this point */ - - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - Curl_pgrsSetUploadSize(data, 0); - Curl_pgrsSetDownloadSize(data, 0); - - ftpc->ctl_valid = TRUE; /* starts good */ - - result = ftp_perform(conn, - &connected, /* have we connected after PASV/PORT */ - dophase_done); /* all commands in the DO-phase done? */ - - if(CURLE_OK == result) { - - if(!*dophase_done) - /* the DO phase has not completed yet */ - return CURLE_OK; - - result = ftp_dophase_done(conn, connected); - if(result) - return result; - } - else - freedirs(ftpc); - - return result; -} - -static CURLcode ftp_setup_connection(struct connectdata * conn) -{ - struct SessionHandle *data = conn->data; - char * type; - char command; - - if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { - /* Unless we have asked to tunnel ftp operations through the proxy, we - switch and use HTTP operations only */ -#ifndef CURL_DISABLE_HTTP - if(conn->handler == &Curl_handler_ftp) - conn->handler = &Curl_handler_ftp_proxy; - else { -#ifdef USE_SSL - conn->handler = &Curl_handler_ftps_proxy; -#else - failf(data, "FTPS not supported!"); - return CURLE_UNSUPPORTED_PROTOCOL; -#endif - } - /* - * We explicitly mark this connection as persistent here as we're doing - * FTP over HTTP and thus we accidentally avoid setting this value - * otherwise. - */ - conn->bits.close = FALSE; -#else - failf(data, "FTP over http proxy requires HTTP support built-in!"); - return CURLE_UNSUPPORTED_PROTOCOL; -#endif - } - - 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=" 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; - } - } - - return CURLE_OK; -} - -#endif /* CURL_DISABLE_FTP */ diff --git a/third_party/curl/lib/ftp.h b/third_party/curl/lib/ftp.h deleted file mode 100644 index d8ef34823..000000000 --- a/third_party/curl/lib/ftp.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef HEADER_CURL_FTP_H -#define HEADER_CURL_FTP_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#include "pingpong.h" - -#ifndef CURL_DISABLE_FTP -extern const struct Curl_handler Curl_handler_ftp; - -#ifdef USE_SSL -extern const struct Curl_handler Curl_handler_ftps; -#endif - -CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...); -CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn, - int *ftpcode); -#endif /* CURL_DISABLE_FTP */ - -/**************************************************************************** - * FTP unique setup - ***************************************************************************/ -typedef enum { - FTP_STOP, /* do nothing state, stops the state machine */ - FTP_WAIT220, /* waiting for the initial 220 response immediately after - a connect */ - FTP_AUTH, - FTP_USER, - FTP_PASS, - FTP_ACCT, - FTP_PBSZ, - FTP_PROT, - FTP_CCC, - FTP_PWD, - FTP_SYST, - FTP_NAMEFMT, - FTP_QUOTE, /* waiting for a response to a command sent in a quote list */ - FTP_RETR_PREQUOTE, - FTP_STOR_PREQUOTE, - FTP_POSTQUOTE, - FTP_CWD, /* change dir */ - FTP_MKD, /* if the dir didn't exist */ - FTP_MDTM, /* to figure out the datestamp */ - FTP_TYPE, /* to set type when doing a head-like request */ - FTP_LIST_TYPE, /* set type when about to do a dir list */ - FTP_RETR_TYPE, /* set type when about to RETR a file */ - FTP_STOR_TYPE, /* set type when about to STOR a file */ - FTP_SIZE, /* get the remote file's size for head-like request */ - FTP_RETR_SIZE, /* get the remote file's size for RETR */ - FTP_STOR_SIZE, /* get the size for (resumed) STOR */ - FTP_REST, /* when used to check if the server supports it in head-like */ - FTP_RETR_REST, /* when asking for "resume" in for RETR */ - FTP_PORT, /* generic state for PORT, LPRT and EPRT, check count1 */ - FTP_PRET, /* generic state for PRET RETR, PRET STOR and PRET LIST/NLST */ - FTP_PASV, /* generic state for PASV and EPSV, check count1 */ - FTP_LIST, /* generic state for LIST, NLST or a custom list command */ - FTP_RETR, - FTP_STOR, /* generic state for STOR and APPE */ - FTP_QUIT, - FTP_LAST /* never used */ -} ftpstate; - -struct ftp_parselist_data; /* defined later in ftplistparser.c */ - -struct ftp_wc_tmpdata { - struct ftp_parselist_data *parser; - - struct { - curl_write_callback write_function; - FILE *file_descriptor; - } backup; -}; - -typedef enum { - FTPFILE_MULTICWD = 1, /* as defined by RFC1738 */ - FTPFILE_NOCWD = 2, /* use SIZE / RETR / STOR on the full path */ - FTPFILE_SINGLECWD = 3 /* make one CWD, then SIZE / RETR / STOR on the file */ -} curl_ftpfile; - -typedef enum { - FTPTRANSFER_BODY, /* yes do transfer a body */ - FTPTRANSFER_INFO, /* do still go through to get info/headers */ - FTPTRANSFER_NONE, /* don't get anything and don't get info */ - FTPTRANSFER_LAST /* end of list marker, never used */ -} curl_ftptransfer; - -/* This FTP struct is used in the SessionHandle. All FTP data that is - connection-oriented must be in FTP_conn to properly deal with the fact that - perhaps the SessionHandle is changed between the times the connection is - used. */ -struct FTP { - curl_off_t *bytecountp; - char *user; /* user name string */ - char *passwd; /* password string */ - - /* transfer a file/body or not, done as a typedefed enum just to make - debuggers display the full symbol and not just the numerical value */ - curl_ftptransfer transfer; - curl_off_t downloadsize; -}; - - -/* ftp_conn is used for struct connection-oriented data in the connectdata - struct */ -struct ftp_conn { - struct pingpong pp; - char *entrypath; /* the PWD reply when we logged on */ - char **dirs; /* realloc()ed array for path components */ - int dirdepth; /* number of entries used in the 'dirs' array */ - int diralloc; /* number of entries allocated for the 'dirs' array */ - char *file; /* decoded file */ - bool dont_check; /* Set to TRUE to prevent the final (post-transfer) - file size and 226/250 status check. It should still - read the line, just ignore the result. */ - bool ctl_valid; /* Tells Curl_ftp_quit() whether or not to do anything. If - the connection has timed out or been closed, this - should be FALSE when it gets to Curl_ftp_quit() */ - bool cwddone; /* if it has been determined that the proper CWD combo - already has been done */ - bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent - caching the current directory */ - char *prevpath; /* conn->path from the previous transfer */ - char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a - and others (A/I or zero) */ - int count1; /* general purpose counter for the state machine */ - int count2; /* general purpose counter for the state machine */ - int count3; /* general purpose counter for the state machine */ - ftpstate state; /* always use ftp.c:state() to change state! */ - char * server_os; /* The target server operating system. */ - curl_off_t known_filesize; /* file size is different from -1, if wildcard - LIST parsing was done and wc_statemach set it */ -}; - -#endif /* HEADER_CURL_FTP_H */ diff --git a/third_party/curl/lib/ftplistparser.c b/third_party/curl/lib/ftplistparser.c deleted file mode 100644 index 6f7475337..000000000 --- a/third_party/curl/lib/ftplistparser.c +++ /dev/null @@ -1,1046 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/** - * Now implemented: - * - * 1) UNIX version 1 - * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog - * 2) UNIX version 2 - * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog - * 3) UNIX version 3 - * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog - * 4) UNIX symlink - * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000 - * 5) DOS style - * 01-29-97 11:32PM prog - */ - -#include "setup.h" - -#include - -#include "ftplistparser.h" -#include "curl_fnmatch.h" - -#include "urldata.h" -#include "ftp.h" -#include "fileinfo.h" -#include "llist.h" -#include "strtoofft.h" -#include "rawstr.h" -#include "ftp.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* allocs buffer which will contain one line of LIST command response */ -#define FTP_BUFFER_ALLOCSIZE 160 - -typedef enum { - PL_UNIX_TOTALSIZE = 0, - PL_UNIX_FILETYPE, - PL_UNIX_PERMISSION, - PL_UNIX_HLINKS, - PL_UNIX_USER, - PL_UNIX_GROUP, - PL_UNIX_SIZE, - PL_UNIX_TIME, - PL_UNIX_FILENAME, - PL_UNIX_SYMLINK -} pl_unix_mainstate; - -typedef union { - enum { - PL_UNIX_TOTALSIZE_INIT = 0, - PL_UNIX_TOTALSIZE_READING - } total_dirsize; - - enum { - PL_UNIX_HLINKS_PRESPACE = 0, - PL_UNIX_HLINKS_NUMBER - } hlinks; - - enum { - PL_UNIX_USER_PRESPACE = 0, - PL_UNIX_USER_PARSING - } user; - - enum { - PL_UNIX_GROUP_PRESPACE = 0, - PL_UNIX_GROUP_NAME - } group; - - enum { - PL_UNIX_SIZE_PRESPACE = 0, - PL_UNIX_SIZE_NUMBER - } size; - - enum { - PL_UNIX_TIME_PREPART1 = 0, - PL_UNIX_TIME_PART1, - PL_UNIX_TIME_PREPART2, - PL_UNIX_TIME_PART2, - PL_UNIX_TIME_PREPART3, - PL_UNIX_TIME_PART3 - } time; - - enum { - PL_UNIX_FILENAME_PRESPACE = 0, - PL_UNIX_FILENAME_NAME, - PL_UNIX_FILENAME_WINDOWSEOL - } filename; - - enum { - PL_UNIX_SYMLINK_PRESPACE = 0, - PL_UNIX_SYMLINK_NAME, - PL_UNIX_SYMLINK_PRETARGET1, - PL_UNIX_SYMLINK_PRETARGET2, - PL_UNIX_SYMLINK_PRETARGET3, - PL_UNIX_SYMLINK_PRETARGET4, - PL_UNIX_SYMLINK_TARGET, - PL_UNIX_SYMLINK_WINDOWSEOL - } symlink; -} pl_unix_substate; - -typedef enum { - PL_WINNT_DATE = 0, - PL_WINNT_TIME, - PL_WINNT_DIRORSIZE, - PL_WINNT_FILENAME -} pl_winNT_mainstate; - -typedef union { - enum { - PL_WINNT_TIME_PRESPACE = 0, - PL_WINNT_TIME_TIME - } time; - enum { - PL_WINNT_DIRORSIZE_PRESPACE = 0, - PL_WINNT_DIRORSIZE_CONTENT - } dirorsize; - enum { - PL_WINNT_FILENAME_PRESPACE = 0, - PL_WINNT_FILENAME_CONTENT, - PL_WINNT_FILENAME_WINEOL - } filename; -} pl_winNT_substate; - -/* This struct is used in wildcard downloading - for parsing LIST response */ -struct ftp_parselist_data { - enum { - OS_TYPE_UNKNOWN = 0, - OS_TYPE_UNIX, - OS_TYPE_WIN_NT - } os_type; - - union { - struct { - pl_unix_mainstate main; - pl_unix_substate sub; - } UNIX; - - struct { - pl_winNT_mainstate main; - pl_winNT_substate sub; - } NT; - } state; - - CURLcode error; - struct curl_fileinfo *file_data; - unsigned int item_length; - size_t item_offset; - struct { - size_t filename; - size_t user; - size_t group; - size_t time; - size_t perm; - size_t symlink_target; - } offsets; -}; - -struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void) -{ - return calloc(1, sizeof(struct ftp_parselist_data)); -} - - -void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data) -{ - if(*pl_data) - free(*pl_data); - *pl_data = NULL; -} - - -CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data) -{ - return pl_data->error; -} - - -#define FTP_LP_MALFORMATED_PERM 0x01000000 - -static int ftp_pl_get_permission(const char *str) -{ - int permissions = 0; - /* USER */ - if(str[0] == 'r') - permissions |= 1 << 8; - else if(str[0] != '-') - permissions |= FTP_LP_MALFORMATED_PERM; - if(str[1] == 'w') - permissions |= 1 << 7; - else if(str[1] != '-') - permissions |= FTP_LP_MALFORMATED_PERM; - - if(str[2] == 'x') - permissions |= 1 << 6; - else if(str[2] == 's') { - permissions |= 1 << 6; - permissions |= 1 << 11; - } - else if(str[2] == 'S') - permissions |= 1 << 11; - else if(str[2] != '-') - permissions |= FTP_LP_MALFORMATED_PERM; - /* GROUP */ - if(str[3] == 'r') - permissions |= 1 << 5; - else if(str[3] != '-') - permissions |= FTP_LP_MALFORMATED_PERM; - if(str[4] == 'w') - permissions |= 1 << 4; - else if(str[4] != '-') - permissions |= FTP_LP_MALFORMATED_PERM; - if(str[5] == 'x') - permissions |= 1 << 3; - else if(str[5] == 's') { - permissions |= 1 << 3; - permissions |= 1 << 10; - } - else if(str[5] == 'S') - permissions |= 1 << 10; - else if(str[5] != '-') - permissions |= FTP_LP_MALFORMATED_PERM; - /* others */ - if(str[6] == 'r') - permissions |= 1 << 2; - else if(str[6] != '-') - permissions |= FTP_LP_MALFORMATED_PERM; - if(str[7] == 'w') - permissions |= 1 << 1; - else if(str[7] != '-') - permissions |= FTP_LP_MALFORMATED_PERM; - if(str[8] == 'x') - permissions |= 1; - else if(str[8] == 't') { - permissions |= 1; - permissions |= 1 << 9; - } - else if(str[8] == 'T') - permissions |= 1 << 9; - else if(str[8] != '-') - permissions |= FTP_LP_MALFORMATED_PERM; - - return permissions; -} - -static void PL_ERROR(struct connectdata *conn, CURLcode err) -{ - struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp; - struct ftp_parselist_data *parser = tmpdata->parser; - if(parser->file_data) - Curl_fileinfo_dtor(NULL, parser->file_data); - parser->file_data = NULL; - parser->error = err; -} - -static bool ftp_pl_gettime(struct ftp_parselist_data *parser, char *string) -{ - (void)parser; - (void)string; - /* TODO - * There could be possible parse timestamp from server. Leaving unimplemented - * for now. - * If you want implement this, please add CURLFINFOFLAG_KNOWN_TIME flag to - * parser->file_data->flags - * - * Ftp servers are giving usually these formats: - * Apr 11 1998 (unknown time.. set it to 00:00:00?) - * Apr 11 12:21 (unknown year -> set it to NOW() time?) - * 08-05-09 02:49PM (ms-dos format) - * 20100421092538 -> for MLST/MLSD response - */ - - return FALSE; -} - -static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, - struct curl_fileinfo *finfo) -{ - curl_fnmatch_callback compare; - struct WildcardData *wc = &conn->data->wildcard; - struct ftp_wc_tmpdata *tmpdata = wc->tmp; - struct curl_llist *llist = wc->filelist; - struct ftp_parselist_data *parser = tmpdata->parser; - bool add = TRUE; - - /* move finfo pointers to b_data */ - char *str = finfo->b_data; - finfo->filename = str + parser->offsets.filename; - finfo->strings.group = parser->offsets.group ? - str + parser->offsets.group : NULL; - finfo->strings.perm = parser->offsets.perm ? - str + parser->offsets.perm : NULL; - finfo->strings.target = parser->offsets.symlink_target ? - str + parser->offsets.symlink_target : NULL; - finfo->strings.time = str + parser->offsets.time; - finfo->strings.user = parser->offsets.user ? - str + parser->offsets.user : NULL; - - /* get correct fnmatch callback */ - compare = conn->data->set.fnmatch; - if(!compare) - compare = Curl_fnmatch; - - /* filter pattern-corresponding filenames */ - if(compare(conn->data->set.fnmatch_data, wc->pattern, finfo->filename) == 0) { - /* discard symlink which is containing multiple " -> " */ - if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target && - (strstr(finfo->strings.target, " -> "))) { - add = FALSE; - } - } - else { - add = FALSE; - } - - if(add) { - if(!Curl_llist_insert_next(llist, llist->tail, finfo)) { - Curl_fileinfo_dtor(NULL, finfo); - tmpdata->parser->file_data = NULL; - return CURLE_OUT_OF_MEMORY; - } - } - else { - Curl_fileinfo_dtor(NULL, finfo); - } - - tmpdata->parser->file_data = NULL; - return CURLE_OK; -} - -size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, - void *connptr) -{ - size_t bufflen = size*nmemb; - struct connectdata *conn = (struct connectdata *)connptr; - struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp; - struct ftp_parselist_data *parser = tmpdata->parser; - struct curl_fileinfo *finfo; - unsigned long i = 0; - CURLcode rc; - - if(parser->error) { /* error in previous call */ - /* scenario: - * 1. call => OK.. - * 2. call => OUT_OF_MEMORY (or other error) - * 3. (last) call => is skipped RIGHT HERE and the error is hadled later - * in wc_statemach() - */ - return bufflen; - } - - if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) { - /* considering info about FILE response format */ - parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ? - OS_TYPE_WIN_NT : OS_TYPE_UNIX; - } - - while(i < bufflen) { /* FSM */ - - char c = buffer[i]; - if(!parser->file_data) { /* tmp file data is not allocated yet */ - parser->file_data = Curl_fileinfo_alloc(); - if(!parser->file_data) { - parser->error = CURLE_OUT_OF_MEMORY; - return bufflen; - } - parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE); - if(!parser->file_data->b_data) { - PL_ERROR(conn, CURLE_OUT_OF_MEMORY); - return bufflen; - } - parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE; - parser->item_offset = 0; - parser->item_length = 0; - } - - finfo = parser->file_data; - finfo->b_data[finfo->b_used++] = c; - - if(finfo->b_used >= finfo->b_size - 1) { - /* if it is important, extend buffer space for file data */ - char *tmp = realloc(finfo->b_data, - finfo->b_size + FTP_BUFFER_ALLOCSIZE); - if(tmp) { - finfo->b_size += FTP_BUFFER_ALLOCSIZE; - finfo->b_data = tmp; - } - else { - Curl_fileinfo_dtor(NULL, parser->file_data); - parser->file_data = NULL; - parser->error = CURLE_OUT_OF_MEMORY; - PL_ERROR(conn, CURLE_OUT_OF_MEMORY); - return bufflen; - } - } - - switch (parser->os_type) { - case OS_TYPE_UNIX: - switch (parser->state.UNIX.main) { - case PL_UNIX_TOTALSIZE: - switch(parser->state.UNIX.sub.total_dirsize) { - case PL_UNIX_TOTALSIZE_INIT: - if(c == 't') { - parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING; - parser->item_length++; - } - else { - parser->state.UNIX.main = PL_UNIX_FILETYPE; - /* start FSM again not considering size of directory */ - finfo->b_used = 0; - i--; - } - break; - case PL_UNIX_TOTALSIZE_READING: - parser->item_length++; - if(c == '\r') { - parser->item_length--; - finfo->b_used--; - } - else if(c == '\n') { - finfo->b_data[parser->item_length - 1] = 0; - if(strncmp("total ", finfo->b_data, 6) == 0) { - char *endptr = finfo->b_data+6; - /* here we can deal with directory size */ - while(ISSPACE(*endptr)) - endptr++; - if(*endptr != 0) { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - else { - parser->state.UNIX.main = PL_UNIX_FILETYPE; - finfo->b_used = 0; - } - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - } - break; - } - break; - case PL_UNIX_FILETYPE: - switch (c) { - case '-': - finfo->filetype = CURLFILETYPE_FILE; - break; - case 'd': - finfo->filetype = CURLFILETYPE_DIRECTORY; - break; - case 'l': - finfo->filetype = CURLFILETYPE_SYMLINK; - break; - case 'p': - finfo->filetype = CURLFILETYPE_NAMEDPIPE; - break; - case 's': - finfo->filetype = CURLFILETYPE_SOCKET; - break; - case 'c': - finfo->filetype = CURLFILETYPE_DEVICE_CHAR; - break; - case 'b': - finfo->filetype = CURLFILETYPE_DEVICE_BLOCK; - break; - case 'D': - finfo->filetype = CURLFILETYPE_DOOR; - break; - default: - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - parser->state.UNIX.main = PL_UNIX_PERMISSION; - parser->item_length = 0; - parser->item_offset = 1; - break; - case PL_UNIX_PERMISSION: - parser->item_length++; - if(parser->item_length <= 9) { - if(!strchr("rwx-tTsS", c)) { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - } - else if(parser->item_length == 10) { - unsigned int perm; - if(c != ' ') { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - finfo->b_data[10] = 0; /* terminate permissions */ - perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset); - if(perm & FTP_LP_MALFORMATED_PERM) { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM; - parser->file_data->perm = perm; - parser->offsets.perm = parser->item_offset; - - parser->item_length = 0; - parser->state.UNIX.main = PL_UNIX_HLINKS; - parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE; - } - break; - case PL_UNIX_HLINKS: - switch(parser->state.UNIX.sub.hlinks) { - case PL_UNIX_HLINKS_PRESPACE: - if(c != ' ') { - if(c >= '0' && c <= '9') { - parser->item_offset = finfo->b_used - 1; - parser->item_length = 1; - parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER; - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - } - break; - case PL_UNIX_HLINKS_NUMBER: - parser->item_length ++; - if(c == ' ') { - char *p; - long int hlinks; - finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; - hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10); - if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) { - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT; - parser->file_data->hardlinks = hlinks; - } - parser->item_length = 0; - parser->item_offset = 0; - parser->state.UNIX.main = PL_UNIX_USER; - parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE; - } - else if(c < '0' || c > '9') { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - } - break; - case PL_UNIX_USER: - switch(parser->state.UNIX.sub.user) { - case PL_UNIX_USER_PRESPACE: - if(c != ' ') { - parser->item_offset = finfo->b_used - 1; - parser->item_length = 1; - parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING; - } - break; - case PL_UNIX_USER_PARSING: - parser->item_length++; - if(c == ' ') { - finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; - parser->offsets.user = parser->item_offset; - parser->state.UNIX.main = PL_UNIX_GROUP; - parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE; - parser->item_offset = 0; - parser->item_length = 0; - } - break; - } - break; - case PL_UNIX_GROUP: - switch(parser->state.UNIX.sub.group) { - case PL_UNIX_GROUP_PRESPACE: - if(c != ' ') { - parser->item_offset = finfo->b_used - 1; - parser->item_length = 1; - parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME; - } - break; - case PL_UNIX_GROUP_NAME: - parser->item_length++; - if(c == ' ') { - finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; - parser->offsets.group = parser->item_offset; - parser->state.UNIX.main = PL_UNIX_SIZE; - parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE; - parser->item_offset = 0; - parser->item_length = 0; - } - break; - } - break; - case PL_UNIX_SIZE: - switch(parser->state.UNIX.sub.size) { - case PL_UNIX_SIZE_PRESPACE: - if(c != ' ') { - if(c >= '0' && c <= '9') { - parser->item_offset = finfo->b_used - 1; - parser->item_length = 1; - parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER; - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - } - break; - case PL_UNIX_SIZE_NUMBER: - parser->item_length++; - if(c == ' ') { - char *p; - curl_off_t fsize; - finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; - fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10); - if(p[0] == '\0' && fsize != CURL_OFF_T_MAX && - fsize != CURL_OFF_T_MIN) { - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE; - parser->file_data->size = fsize; - } - parser->item_length = 0; - parser->item_offset = 0; - parser->state.UNIX.main = PL_UNIX_TIME; - parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1; - } - else if (!ISDIGIT(c)) { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - } - break; - case PL_UNIX_TIME: - switch(parser->state.UNIX.sub.time) { - case PL_UNIX_TIME_PREPART1: - if(c != ' ') { - if(ISALNUM(c)) { - parser->item_offset = finfo->b_used -1; - parser->item_length = 1; - parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1; - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - } - break; - case PL_UNIX_TIME_PART1: - parser->item_length++; - if(c == ' ') { - parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2; - } - else if(!ISALNUM(c) && c != '.') { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - case PL_UNIX_TIME_PREPART2: - parser->item_length++; - if(c != ' ') { - if(ISALNUM(c)) { - parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2; - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - } - break; - case PL_UNIX_TIME_PART2: - parser->item_length++; - if(c == ' ') { - parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3; - } - else if(!ISALNUM(c) && c != '.') { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - case PL_UNIX_TIME_PREPART3: - parser->item_length++; - if(c != ' ') { - if(ISALNUM(c)) { - parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3; - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - } - break; - case PL_UNIX_TIME_PART3: - parser->item_length++; - if(c == ' ') { - finfo->b_data[parser->item_offset + parser->item_length -1] = 0; - parser->offsets.time = parser->item_offset; - if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) { - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME; - } - if(finfo->filetype == CURLFILETYPE_SYMLINK) { - parser->state.UNIX.main = PL_UNIX_SYMLINK; - parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE; - } - else { - parser->state.UNIX.main = PL_UNIX_FILENAME; - parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE; - } - } - else if(!ISALNUM(c) && c != '.' && c != ':') { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - } - break; - case PL_UNIX_FILENAME: - switch(parser->state.UNIX.sub.filename) { - case PL_UNIX_FILENAME_PRESPACE: - if(c != ' ') { - parser->item_offset = finfo->b_used - 1; - parser->item_length = 1; - parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME; - } - break; - case PL_UNIX_FILENAME_NAME: - parser->item_length++; - if(c == '\r') { - parser->item_length--; - parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL; - } - else if(c == '\n') { - finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; - parser->offsets.filename = parser->item_offset; - parser->state.UNIX.main = PL_UNIX_FILETYPE; - rc = ftp_pl_insert_finfo(conn, finfo); - if(rc) { - PL_ERROR(conn, rc); - return bufflen; - } - } - break; - case PL_UNIX_FILENAME_WINDOWSEOL: - if(c == '\n') { - finfo->b_data[parser->item_offset + parser->item_length] = 0; - parser->offsets.filename = parser->item_offset; - parser->state.UNIX.main = PL_UNIX_FILETYPE; - rc = ftp_pl_insert_finfo(conn, finfo); - if(rc) { - PL_ERROR(conn, rc); - return bufflen; - } - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - } - break; - case PL_UNIX_SYMLINK: - switch(parser->state.UNIX.sub.symlink) { - case PL_UNIX_SYMLINK_PRESPACE: - if(c != ' ') { - parser->item_offset = finfo->b_used - 1; - parser->item_length = 1; - parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; - } - break; - case PL_UNIX_SYMLINK_NAME: - parser->item_length++; - if(c == ' ') { - parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1; - } - else if(c == '\r' || c == '\n') { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - case PL_UNIX_SYMLINK_PRETARGET1: - parser->item_length++; - if(c == '-') { - parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2; - } - else if(c == '\r' || c == '\n') { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - else { - parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; - } - break; - case PL_UNIX_SYMLINK_PRETARGET2: - parser->item_length++; - if(c == '>') { - parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3; - } - else if(c == '\r' || c == '\n') { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - else { - parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; - } - break; - case PL_UNIX_SYMLINK_PRETARGET3: - parser->item_length++; - if(c == ' ') { - parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4; - /* now place where is symlink following */ - finfo->b_data[parser->item_offset + parser->item_length - 4] = 0; - parser->offsets.filename = parser->item_offset; - parser->item_length = 0; - parser->item_offset = 0; - } - else if(c == '\r' || c == '\n') { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - else { - parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; - } - break; - case PL_UNIX_SYMLINK_PRETARGET4: - if(c != '\r' && c != '\n') { - parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET; - parser->item_offset = finfo->b_used - 1; - parser->item_length = 1; - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - case PL_UNIX_SYMLINK_TARGET: - parser->item_length ++; - if(c == '\r') { - parser->item_length --; - parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL; - } - else if(c == '\n') { - finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; - parser->offsets.symlink_target = parser->item_offset; - rc = ftp_pl_insert_finfo(conn, finfo); - if(rc) { - PL_ERROR(conn, rc); - return bufflen; - } - parser->state.UNIX.main = PL_UNIX_FILETYPE; - } - break; - case PL_UNIX_SYMLINK_WINDOWSEOL: - if(c == '\n') { - finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; - parser->offsets.symlink_target = parser->item_offset; - rc = ftp_pl_insert_finfo(conn, finfo); - if(rc) { - PL_ERROR(conn, rc); - return bufflen; - } - parser->state.UNIX.main = PL_UNIX_FILETYPE; - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - } - break; - } - break; - case OS_TYPE_WIN_NT: - switch(parser->state.NT.main) { - case PL_WINNT_DATE: - parser->item_length++; - if(parser->item_length < 9) { - if(!strchr("0123456789-", c)) { /* only simple control */ - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - } - else if(parser->item_length == 9) { - if(c == ' ') { - parser->state.NT.main = PL_WINNT_TIME; - parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE; - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - case PL_WINNT_TIME: - parser->item_length++; - switch(parser->state.NT.sub.time) { - case PL_WINNT_TIME_PRESPACE: - if(!ISSPACE(c)) { - parser->state.NT.sub.time = PL_WINNT_TIME_TIME; - } - break; - case PL_WINNT_TIME_TIME: - if(c == ' ') { - parser->offsets.time = parser->item_offset; - finfo->b_data[parser->item_offset + parser->item_length -1] = 0; - parser->state.NT.main = PL_WINNT_DIRORSIZE; - parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE; - parser->item_length = 0; - } - else if(!strchr("APM0123456789:", c)) { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - } - break; - case PL_WINNT_DIRORSIZE: - switch(parser->state.NT.sub.dirorsize) { - case PL_WINNT_DIRORSIZE_PRESPACE: - if(c == ' ') { - - } - else { - parser->item_offset = finfo->b_used - 1; - parser->item_length = 1; - parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT; - } - break; - case PL_WINNT_DIRORSIZE_CONTENT: - parser->item_length ++; - if(c == ' ') { - finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; - if(strcmp("", finfo->b_data + parser->item_offset) == 0) { - finfo->filetype = CURLFILETYPE_DIRECTORY; - finfo->size = 0; - } - else { - char *endptr; - finfo->size = curlx_strtoofft(finfo->b_data + parser->item_offset, - &endptr, 10); - if(!*endptr) { - if(finfo->size == CURL_OFF_T_MAX || - finfo->size == CURL_OFF_T_MIN) { - if(errno == ERANGE) { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - } - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - /* correct file type */ - parser->file_data->filetype = CURLFILETYPE_FILE; - } - - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE; - parser->item_length = 0; - parser->state.NT.main = PL_WINNT_FILENAME; - parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; - } - break; - } - break; - case PL_WINNT_FILENAME: - switch (parser->state.NT.sub.filename) { - case PL_WINNT_FILENAME_PRESPACE: - if(c != ' ') { - parser->item_offset = finfo->b_used -1; - parser->item_length = 1; - parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT; - } - break; - case PL_WINNT_FILENAME_CONTENT: - parser->item_length++; - if(c == '\r') { - parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL; - finfo->b_data[finfo->b_used - 1] = 0; - } - else if(c == '\n') { - parser->offsets.filename = parser->item_offset; - finfo->b_data[finfo->b_used - 1] = 0; - parser->offsets.filename = parser->item_offset; - rc = ftp_pl_insert_finfo(conn, finfo); - if(rc) { - PL_ERROR(conn, rc); - return bufflen; - } - parser->state.NT.main = PL_WINNT_DATE; - parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; - } - break; - case PL_WINNT_FILENAME_WINEOL: - if(c == '\n') { - parser->offsets.filename = parser->item_offset; - rc = ftp_pl_insert_finfo(conn, finfo); - if(rc) { - PL_ERROR(conn, rc); - return bufflen; - } - parser->state.NT.main = PL_WINNT_DATE; - parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; - } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } - break; - } - break; - } - break; - default: - return bufflen+1; - } - - i++; - } - - return bufflen; -} diff --git a/third_party/curl/lib/ftplistparser.h b/third_party/curl/lib/ftplistparser.h deleted file mode 100644 index 67a06c296..000000000 --- a/third_party/curl/lib/ftplistparser.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef HEADER_CURL_FTPLISTPARSER_H -#define HEADER_CURL_FTPLISTPARSER_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 - -/* WRITEFUNCTION callback for parsing LIST responses */ -size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, - void *connptr); - -struct ftp_parselist_data; /* defined inside ftplibparser.c */ - -CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data); - -struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void); - -void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data); - -#endif /* HEADER_CURL_FTPLISTPARSER_H */ diff --git a/third_party/curl/lib/getenv.c b/third_party/curl/lib/getenv.c deleted file mode 100644 index 3e4f8fd77..000000000 --- a/third_party/curl/lib/getenv.c +++ /dev/null @@ -1,65 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include -#include - -#ifdef __VMS -#include -#endif - -#include -#include "curl_memory.h" - -#include "memdebug.h" - -static -char *GetEnv(const char *variable) -{ -#ifdef _WIN32_WCE - return NULL; -#else -#ifdef WIN32 - char env[MAX_PATH]; /* MAX_PATH is from windef.h */ - char *temp = getenv(variable); - env[0] = '\0'; - if(temp != NULL) - ExpandEnvironmentStringsA(temp, env, sizeof(env)); - return (env[0] != '\0')?strdup(env):NULL; -#else - char *env = getenv(variable); -#ifdef __VMS - if(env && strcmp("HOME",variable) == 0) - env = decc_translate_vms(env); -#endif - return (env && env[0])?strdup(env):NULL; -#endif -#endif -} - -char *curl_getenv(const char *v) -{ - return GetEnv(v); -} diff --git a/third_party/curl/lib/getinfo.c b/third_party/curl/lib/getinfo.c deleted file mode 100644 index bb289741a..000000000 --- a/third_party/curl/lib/getinfo.c +++ /dev/null @@ -1,283 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include - -#include "urldata.h" -#include "getinfo.h" - -#include -#include -#include -#include -#include "curl_memory.h" -#include "sslgen.h" -#include "connect.h" /* Curl_getconnectinfo() */ -#include "progress.h" - -/* Make this the last #include */ -#include "memdebug.h" - -/* - * This is supposed to be called in the beginning of a perform() session - * and should reset all session-info variables - */ -CURLcode Curl_initinfo(struct SessionHandle *data) -{ - struct Progress *pro = &data->progress; - struct PureInfo *info =&data->info; - - pro->t_nslookup = 0; - pro->t_connect = 0; - pro->t_pretransfer = 0; - pro->t_starttransfer = 0; - pro->timespent = 0; - pro->t_redirect = 0; - - info->httpcode = 0; - info->httpversion=0; - info->filetime=-1; /* -1 is an illegal time and thus means unknown */ - - if(info->contenttype) - free(info->contenttype); - info->contenttype = NULL; - - info->header_size = 0; - info->request_size = 0; - info->numconnects = 0; - - info->conn_primary_ip[0] = '\0'; - info->conn_local_ip[0] = '\0'; - info->conn_primary_port = 0; - info->conn_local_port = 0; - - return CURLE_OK; -} - -CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...) -{ - va_list arg; - long *param_longp=NULL; - double *param_doublep=NULL; - char **param_charp=NULL; - struct curl_slist **param_slistp=NULL; - int type; - curl_socket_t sockfd; - - union { - struct curl_certinfo * to_certinfo; - struct curl_slist * to_slist; - } ptr; - - if(!data) - return CURLE_BAD_FUNCTION_ARGUMENT; - - va_start(arg, info); - - type = CURLINFO_TYPEMASK & (int)info; - switch(type) { - case CURLINFO_STRING: - param_charp = va_arg(arg, char **); - if(NULL == param_charp) - return CURLE_BAD_FUNCTION_ARGUMENT; - break; - case CURLINFO_LONG: - param_longp = va_arg(arg, long *); - if(NULL == param_longp) - return CURLE_BAD_FUNCTION_ARGUMENT; - break; - case CURLINFO_DOUBLE: - param_doublep = va_arg(arg, double *); - if(NULL == param_doublep) - return CURLE_BAD_FUNCTION_ARGUMENT; - break; - case CURLINFO_SLIST: - param_slistp = va_arg(arg, struct curl_slist **); - if(NULL == param_slistp) - return CURLE_BAD_FUNCTION_ARGUMENT; - break; - default: - return CURLE_BAD_FUNCTION_ARGUMENT; - } - - switch(info) { - case CURLINFO_EFFECTIVE_URL: - *param_charp = data->change.url?data->change.url:(char *)""; - break; - case CURLINFO_RESPONSE_CODE: - *param_longp = data->info.httpcode; - break; - case CURLINFO_HTTP_CONNECTCODE: - *param_longp = data->info.httpproxycode; - break; - case CURLINFO_FILETIME: - *param_longp = data->info.filetime; - break; - case CURLINFO_HEADER_SIZE: - *param_longp = data->info.header_size; - break; - case CURLINFO_REQUEST_SIZE: - *param_longp = data->info.request_size; - break; - case CURLINFO_TOTAL_TIME: - *param_doublep = data->progress.timespent; - break; - case CURLINFO_NAMELOOKUP_TIME: - *param_doublep = data->progress.t_nslookup; - break; - case CURLINFO_CONNECT_TIME: - *param_doublep = data->progress.t_connect; - break; - case CURLINFO_APPCONNECT_TIME: - *param_doublep = data->progress.t_appconnect; - break; - case CURLINFO_PRETRANSFER_TIME: - *param_doublep = data->progress.t_pretransfer; - break; - case CURLINFO_STARTTRANSFER_TIME: - *param_doublep = data->progress.t_starttransfer; - break; - case CURLINFO_SIZE_UPLOAD: - *param_doublep = (double)data->progress.uploaded; - break; - case CURLINFO_SIZE_DOWNLOAD: - *param_doublep = (double)data->progress.downloaded; - break; - case CURLINFO_SPEED_DOWNLOAD: - *param_doublep = (double)data->progress.dlspeed; - break; - case CURLINFO_SPEED_UPLOAD: - *param_doublep = (double)data->progress.ulspeed; - break; - case CURLINFO_SSL_VERIFYRESULT: - *param_longp = data->set.ssl.certverifyresult; - break; - case CURLINFO_CONTENT_LENGTH_DOWNLOAD: - *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)? - (double)data->progress.size_dl:-1; - break; - case CURLINFO_CONTENT_LENGTH_UPLOAD: - *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)? - (double)data->progress.size_ul:-1; - break; - case CURLINFO_REDIRECT_TIME: - *param_doublep = data->progress.t_redirect; - break; - case CURLINFO_REDIRECT_COUNT: - *param_longp = data->set.followlocation; - break; - case CURLINFO_CONTENT_TYPE: - *param_charp = data->info.contenttype; - break; - case CURLINFO_PRIVATE: - *param_charp = (char *) data->set.private_data; - break; - case CURLINFO_HTTPAUTH_AVAIL: - *param_longp = data->info.httpauthavail; - break; - case CURLINFO_PROXYAUTH_AVAIL: - *param_longp = data->info.proxyauthavail; - break; - case CURLINFO_OS_ERRNO: - *param_longp = data->state.os_errno; - break; - case CURLINFO_NUM_CONNECTS: - *param_longp = data->info.numconnects; - break; - case CURLINFO_SSL_ENGINES: - *param_slistp = Curl_ssl_engines_list(data); - break; - case CURLINFO_COOKIELIST: - *param_slistp = Curl_cookie_list(data); - break; - case CURLINFO_FTP_ENTRY_PATH: - /* Return the entrypath string from the most recent connection. - This pointer was copied from the connectdata structure by FTP. - The actual string may be free()ed by subsequent libcurl calls so - it must be copied to a safer area before the next libcurl call. - Callers must never free it themselves. */ - *param_charp = data->state.most_recent_ftp_entrypath; - break; - case CURLINFO_LASTSOCKET: - sockfd = Curl_getconnectinfo(data, NULL); - - /* note: this is not a good conversion for systems with 64 bit sockets and - 32 bit longs */ - if(sockfd != CURL_SOCKET_BAD) - *param_longp = (long)sockfd; - else - /* this interface is documented to return -1 in case of badness, which - may not be the same as the CURL_SOCKET_BAD value */ - *param_longp = -1; - break; - case CURLINFO_REDIRECT_URL: - /* Return the URL this request would have been redirected to if that - option had been enabled! */ - *param_charp = data->info.wouldredirect; - break; - case CURLINFO_PRIMARY_IP: - /* Return the ip address of the most recent (primary) connection */ - *param_charp = data->info.conn_primary_ip; - break; - case CURLINFO_PRIMARY_PORT: - /* Return the (remote) port of the most recent (primary) connection */ - *param_longp = data->info.conn_primary_port; - break; - case CURLINFO_LOCAL_IP: - /* Return the source/local ip address of the most recent (primary) - connection */ - *param_charp = data->info.conn_local_ip; - break; - case CURLINFO_LOCAL_PORT: - /* Return the local port of the most recent (primary) connection */ - *param_longp = data->info.conn_local_port; - break; - case CURLINFO_CERTINFO: - /* Return the a pointer to the certinfo struct. Not really an slist - pointer but we can pretend it is here */ - ptr.to_certinfo = &data->info.certs; - *param_slistp = ptr.to_slist; - break; - case CURLINFO_CONDITION_UNMET: - /* return if the condition prevented the document to get transferred */ - *param_longp = data->info.timecond; - break; - case CURLINFO_RTSP_SESSION_ID: - *param_charp = data->set.str[STRING_RTSP_SESSION_ID]; - break; - case CURLINFO_RTSP_CLIENT_CSEQ: - *param_longp = data->state.rtsp_next_client_CSeq; - break; - case CURLINFO_RTSP_SERVER_CSEQ: - *param_longp = data->state.rtsp_next_server_CSeq; - break; - case CURLINFO_RTSP_CSEQ_RECV: - *param_longp = data->state.rtsp_CSeq_recv; - break; - - default: - return CURLE_BAD_FUNCTION_ARGUMENT; - } - return CURLE_OK; -} diff --git a/third_party/curl/lib/getinfo.h b/third_party/curl/lib/getinfo.h deleted file mode 100644 index 3879ff73a..000000000 --- a/third_party/curl/lib/getinfo.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef HEADER_CURL_GETINFO_H -#define HEADER_CURL_GETINFO_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...); -CURLcode Curl_initinfo(struct SessionHandle *data); - -#endif /* HEADER_CURL_GETINFO_H */ diff --git a/third_party/curl/lib/gopher.c b/third_party/curl/lib/gopher.c deleted file mode 100644 index 6718bafb1..000000000 --- a/third_party/curl/lib/gopher.c +++ /dev/null @@ -1,210 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef CURL_DISABLE_GOPHER - -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#include -#else -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SELECT_H -#include -#endif - - -#endif - -#include "urldata.h" -#include -#include "transfer.h" -#include "sendf.h" - -#include "progress.h" -#include "strequal.h" -#include "gopher.h" -#include "rawstr.h" -#include "select.h" -#include "url.h" -#include "warnless.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - - -/* - * Forward declarations. - */ - -static CURLcode gopher_do(struct connectdata *conn, bool *done); - -/* - * Gopher protocol handler. - * This is also a nice simple template to build off for simple - * connect-command-download protocols. - */ - -const struct Curl_handler Curl_handler_gopher = { - "GOPHER", /* scheme */ - ZERO_NULL, /* setup_connection */ - gopher_do, /* do_it */ - ZERO_NULL, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_GOPHER, /* defport */ - CURLPROTO_GOPHER, /* protocol */ - PROTOPT_NONE /* flags */ -}; - -static CURLcode gopher_do(struct connectdata *conn, bool *done) -{ - CURLcode result=CURLE_OK; - struct SessionHandle *data=conn->data; - curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; - - curl_off_t *bytecount = &data->req.bytecount; - char *path = data->state.path; - char *sel; - char *sel_org = NULL; - ssize_t amount, k; - - *done = TRUE; /* unconditionally */ - - /* Create selector. Degenerate cases: / and /1 => convert to "" */ - if (strlen(path) <= 2) - sel = (char *)""; - else { - char *newp; - size_t j, i; - int len; - - /* Otherwise, drop / and the first character (i.e., item type) ... */ - newp = path; - newp+=2; - - /* ... then turn ? into TAB for search servers, Veronica, etc. ... */ - j = strlen(newp); - for(i=0; i, et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifndef CURL_DISABLE_GOPHER -extern const struct Curl_handler Curl_handler_gopher; -#endif - -#endif /* HEADER_CURL_GOPHER_H */ diff --git a/third_party/curl/lib/gtls.c b/third_party/curl/lib/gtls.c deleted file mode 100644 index 71ceb34d9..000000000 --- a/third_party/curl/lib/gtls.c +++ /dev/null @@ -1,1026 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code - * but sslgen.c should ever call or use these functions. - * - * Note: don't use the GnuTLS' *_t variable type names in this source code, - * since they were not present in 1.0.X. - */ - -#include "setup.h" -#ifdef USE_GNUTLS -#include -#include -#include - -#include -#include -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#include "urldata.h" -#include "sendf.h" -#include "inet_pton.h" -#include "gtls.h" -#include "sslgen.h" -#include "parsedate.h" -#include "connect.h" /* for the connect timeout */ -#include "select.h" -#include "rawstr.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* - Some hackish cast macros based on: - http://library.gnome.org/devel/glib/unstable/glib-Type-Conversion-Macros.html -*/ -#ifndef GNUTLS_POINTER_TO_INT_CAST -#define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p)) -#endif -#ifndef GNUTLS_INT_TO_POINTER_CAST -#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i)) -#endif - -/* Enable GnuTLS debugging by defining GTLSDEBUG */ -/*#define GTLSDEBUG */ - -#ifdef GTLSDEBUG -static void tls_log_func(int level, const char *str) -{ - fprintf(stderr, "|<%d>| %s", level, str); -} -#endif -static bool gtls_inited = FALSE; - -/* - * Custom push and pull callback functions used by GNU TLS to read and write - * to the socket. These functions are simple wrappers to send() and recv() - * (although here using the sread/swrite macros as defined by setup_once.h). - * We use custom functions rather than the GNU TLS defaults because it allows - * us to get specific about the fourth "flags" argument, and to use arbitrary - * private data with gnutls_transport_set_ptr if we wish. - * - * When these custom push and pull callbacks fail, GNU TLS checks its own - * session-specific error variable, and when not set also its own global - * errno variable, in order to take appropriate action. GNU TLS does not - * require that the transport is actually a socket. This implies that for - * Windows builds these callbacks should ideally set the session-specific - * error variable using function gnutls_transport_set_errno or as a last - * resort global errno variable using gnutls_transport_set_global_errno, - * with a transport agnostic error value. This implies that some winsock - * error translation must take place in these callbacks. - */ - -#ifdef USE_WINSOCK -# define gtls_EINTR 4 -# define gtls_EIO 5 -# define gtls_EAGAIN 11 -static int gtls_mapped_sockerrno(void) -{ - switch(SOCKERRNO) { - case WSAEWOULDBLOCK: - return gtls_EAGAIN; - case WSAEINTR: - return gtls_EINTR; - default: - break; - } - return gtls_EIO; -} -#endif - -static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len) -{ - ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len); -#ifdef USE_WINSOCK - if(ret < 0) - gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); -#endif - return ret; -} - -static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len) -{ - ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len); -#ifdef USE_WINSOCK - if(ret < 0) - gnutls_transport_set_global_errno(gtls_mapped_sockerrno()); -#endif - return ret; -} - -/* Curl_gtls_init() - * - * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that - * are not thread-safe and thus this function itself is not thread-safe and - * must only be called from within curl_global_init() to keep the thread - * situation under control! - */ -int Curl_gtls_init(void) -{ - int ret = 1; - if(!gtls_inited) { - ret = gnutls_global_init()?0:1; -#ifdef GTLSDEBUG - gnutls_global_set_log_function(tls_log_func); - gnutls_global_set_log_level(2); -#endif - gtls_inited = TRUE; - } - return ret; -} - -int Curl_gtls_cleanup(void) -{ - if(gtls_inited) { - gnutls_global_deinit(); - gtls_inited = FALSE; - } - return 1; -} - -static void showtime(struct SessionHandle *data, - const char *text, - time_t stamp) -{ - struct tm buffer; - const struct tm *tm = &buffer; - CURLcode result = Curl_gmtime(stamp, &buffer); - if(result) - return; - - snprintf(data->state.buffer, - BUFSIZE, - "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n", - text, - Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], - tm->tm_mday, - Curl_month[tm->tm_mon], - tm->tm_year + 1900, - tm->tm_hour, - tm->tm_min, - tm->tm_sec); - infof(data, "%s", data->state.buffer); -} - -static gnutls_datum load_file (const char *file) -{ - FILE *f; - gnutls_datum loaded_file = { NULL, 0 }; - long filelen; - void *ptr; - - if (!(f = fopen(file, "r"))) - return loaded_file; - if (fseek(f, 0, SEEK_END) != 0 - || (filelen = ftell(f)) < 0 - || fseek(f, 0, SEEK_SET) != 0 - || !(ptr = malloc((size_t)filelen))) - goto out; - if (fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) { - free(ptr); - goto out; - } - - loaded_file.data = ptr; - loaded_file.size = (unsigned int)filelen; -out: - fclose(f); - return loaded_file; -} - -static void unload_file(gnutls_datum data) { - free(data.data); -} - - -/* this function does a SSL/TLS (re-)handshake */ -static CURLcode handshake(struct connectdata *conn, - int sockindex, - bool duringconnect, - bool nonblocking) -{ - struct SessionHandle *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - gnutls_session session = conn->ssl[sockindex].session; - curl_socket_t sockfd = conn->sock[sockindex]; - long timeout_ms; - int rc; - int what; - - for(;;) { - /* check allowed time left */ - timeout_ms = Curl_timeleft(data, NULL, duringconnect); - - if(timeout_ms < 0) { - /* no need to continue if time already is up */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - /* if ssl is expecting something, check if it's available. */ - if(connssl->connecting_state == ssl_connect_2_reading - || connssl->connecting_state == ssl_connect_2_writing) { - - curl_socket_t writefd = ssl_connect_2_writing== - connssl->connecting_state?sockfd:CURL_SOCKET_BAD; - curl_socket_t readfd = ssl_connect_2_reading== - connssl->connecting_state?sockfd:CURL_SOCKET_BAD; - - what = Curl_socket_ready(readfd, writefd, - nonblocking?0:(int)timeout_ms?1000:timeout_ms); - if(what < 0) { - /* fatal error */ - failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); - return CURLE_SSL_CONNECT_ERROR; - } - else if(0 == what) { - if(nonblocking) - return CURLE_OK; - else if(timeout_ms) { - /* timeout */ - failf(data, "SSL connection timeout at %ld", timeout_ms); - return CURLE_OPERATION_TIMEDOUT; - } - } - /* socket is readable or writable */ - } - - rc = gnutls_handshake(session); - - if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) { - connssl->connecting_state = - gnutls_record_get_direction(session)? - ssl_connect_2_writing:ssl_connect_2_reading; - if(nonblocking) - return CURLE_OK; - } - else if (rc < 0) { - failf(data, "gnutls_handshake() failed: %s", gnutls_strerror(rc)); - return CURLE_SSL_CONNECT_ERROR; - } - else { - /* Reset our connect state machine */ - connssl->connecting_state = ssl_connect_1; - return CURLE_OK; - } - } -} - -static gnutls_x509_crt_fmt do_file_type(const char *type) -{ - if(!type || !type[0]) - return GNUTLS_X509_FMT_PEM; - if(Curl_raw_equal(type, "PEM")) - return GNUTLS_X509_FMT_PEM; - if(Curl_raw_equal(type, "DER")) - return GNUTLS_X509_FMT_DER; - return -1; -} - -static CURLcode -gtls_connect_step1(struct connectdata *conn, - int sockindex) -{ - static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; - struct SessionHandle *data = conn->data; - gnutls_session session; - int rc; - void *ssl_sessionid; - size_t ssl_idsize; - bool sni = TRUE; /* default is SNI enabled */ -#ifdef ENABLE_IPV6 - struct in6_addr addr; -#else - struct in_addr addr; -#endif - - if(conn->ssl[sockindex].state == ssl_connection_complete) - /* to make us tolerant against being called more than once for the - same connection */ - return CURLE_OK; - - if(!gtls_inited) - Curl_gtls_init(); - - /* GnuTLS only supports SSLv3 and TLSv1 */ - if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { - failf(data, "GnuTLS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) - sni = FALSE; /* SSLv3 has no SNI */ - - /* allocate a cred struct */ - rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred); - if(rc != GNUTLS_E_SUCCESS) { - failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); - return CURLE_SSL_CONNECT_ERROR; - } - -#ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { - infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); - - rc = gnutls_srp_allocate_client_credentials( - &conn->ssl[sockindex].srp_client_cred); - if(rc != GNUTLS_E_SUCCESS) { - failf(data, "gnutls_srp_allocate_client_cred() failed: %s", - gnutls_strerror(rc)); - return CURLE_OUT_OF_MEMORY; - } - - rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].srp_client_cred, - data->set.ssl.username, - data->set.ssl.password); - if(rc != GNUTLS_E_SUCCESS) { - failf(data, "gnutls_srp_set_client_cred() failed: %s", - gnutls_strerror(rc)); - return CURLE_BAD_FUNCTION_ARGUMENT; - } - } -#endif - - if(data->set.ssl.CAfile) { - /* set the trusted CA cert bundle file */ - gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred, - GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); - - rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred, - data->set.ssl.CAfile, - GNUTLS_X509_FMT_PEM); - if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)\n", - data->set.ssl.CAfile, gnutls_strerror(rc)); - if(data->set.ssl.verifypeer) - return CURLE_SSL_CACERT_BADFILE; - } - else - infof(data, "found %d certificates in %s\n", - rc, data->set.ssl.CAfile); - } - - if(data->set.ssl.CRLfile) { - /* set the CRL list file */ - rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred, - data->set.ssl.CRLfile, - GNUTLS_X509_FMT_PEM); - if(rc < 0) { - failf(data, "error reading crl file %s (%s)\n", - data->set.ssl.CRLfile, gnutls_strerror(rc)); - return CURLE_SSL_CRL_BADFILE; - } - else - infof(data, "found %d CRL in %s\n", - rc, data->set.ssl.CRLfile); - } - - /* Initialize TLS session as a client */ - rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT); - if(rc != GNUTLS_E_SUCCESS) { - failf(data, "gnutls_init() failed: %d", rc); - return CURLE_SSL_CONNECT_ERROR; - } - - /* convenient assign */ - session = conn->ssl[sockindex].session; - - if ((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && -#ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && -#endif - sni && - (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name, - strlen(conn->host.name)) < 0)) - infof(data, "WARNING: failed to configure server name indication (SNI) " - "TLS extension\n"); - - /* Use default priorities */ - rc = gnutls_set_default_priority(session); - if(rc != GNUTLS_E_SUCCESS) - return CURLE_SSL_CONNECT_ERROR; - - if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) { - static const int protocol_priority[] = { GNUTLS_SSL3, 0 }; - gnutls_protocol_set_priority(session, protocol_priority); - if(rc != GNUTLS_E_SUCCESS) - return CURLE_SSL_CONNECT_ERROR; - } - - /* Sets the priority on the certificate types supported by gnutls. Priority - is higher for types specified before others. After specifying the types - you want, you must append a 0. */ - rc = gnutls_certificate_type_set_priority(session, cert_type_priority); - if(rc != GNUTLS_E_SUCCESS) - return CURLE_SSL_CONNECT_ERROR; - - if(data->set.str[STRING_CERT]) { - if( gnutls_certificate_set_x509_key_file( - conn->ssl[sockindex].cred, - data->set.str[STRING_CERT], - data->set.str[STRING_KEY] ? - data->set.str[STRING_KEY] : data->set.str[STRING_CERT], - do_file_type(data->set.str[STRING_CERT_TYPE]) ) != GNUTLS_E_SUCCESS) { - failf(data, "error reading X.509 key or certificate file"); - return CURLE_SSL_CONNECT_ERROR; - } - } - -#ifdef USE_TLS_SRP - /* put the credentials to the current session */ - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { - rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, - conn->ssl[sockindex].srp_client_cred); - if (rc != GNUTLS_E_SUCCESS) { - failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc)); - } - } else -#endif - rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, - conn->ssl[sockindex].cred); - - /* set the connection handle (file descriptor for the socket) */ - gnutls_transport_set_ptr(session, - GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex])); - - /* register callback functions to send and receive data. */ - gnutls_transport_set_push_function(session, Curl_gtls_push); - gnutls_transport_set_pull_function(session, Curl_gtls_pull); - - /* lowat must be set to zero when using custom push and pull functions. */ - gnutls_transport_set_lowat(session, 0); - - /* This might be a reconnect, so we check for a session ID in the cache - to speed up things */ - - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) { - /* we got a session id, use it! */ - gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); - - /* Informational message */ - infof (data, "SSL re-using session ID\n"); - } - - return CURLE_OK; -} - -static Curl_recv gtls_recv; -static Curl_send gtls_send; - -static CURLcode -gtls_connect_step3(struct connectdata *conn, - int sockindex) -{ - unsigned int cert_list_size; - const gnutls_datum *chainp; - unsigned int verify_status; - gnutls_x509_crt x509_cert,x509_issuer; - gnutls_datum issuerp; - char certbuf[256]; /* big enough? */ - size_t size; - unsigned int algo; - unsigned int bits; - time_t certclock; - const char *ptr; - struct SessionHandle *data = conn->data; - gnutls_session session = conn->ssl[sockindex].session; - int rc; - int incache; - void *ssl_sessionid; - CURLcode result = CURLE_OK; - - /* This function will return the peer's raw certificate (chain) as sent by - the peer. These certificates are in raw format (DER encoded for - X.509). In case of a X.509 then a certificate list may be present. The - first certificate in the list is the peer's certificate, following the - issuer's certificate, then the issuer's issuer etc. */ - - chainp = gnutls_certificate_get_peers(session, &cert_list_size); - if(!chainp) { - if(data->set.ssl.verifypeer || - data->set.ssl.verifyhost || - data->set.ssl.issuercert) { -#ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP - && data->set.ssl.username != NULL - && !data->set.ssl.verifypeer - && gnutls_cipher_get(session)) { - /* no peer cert, but auth is ok if we have SRP user and cipher and no - peer verify */ - } - else { -#endif - failf(data, "failed to get server cert"); - return CURLE_PEER_FAILED_VERIFICATION; -#ifdef USE_TLS_SRP - } -#endif - } - infof(data, "\t common name: WARNING couldn't obtain\n"); - } - - if(data->set.ssl.verifypeer) { - /* This function will try to verify the peer's certificate and return its - status (trusted, invalid etc.). The value of status should be one or - more of the gnutls_certificate_status_t enumerated elements bitwise - or'd. To avoid denial of service attacks some default upper limits - regarding the certificate key size and chain size are set. To override - them use gnutls_certificate_set_verify_limits(). */ - - rc = gnutls_certificate_verify_peers2(session, &verify_status); - if(rc < 0) { - failf(data, "server cert verify failed: %d", rc); - return CURLE_SSL_CONNECT_ERROR; - } - - /* verify_status is a bitmask of gnutls_certificate_status bits */ - if(verify_status & GNUTLS_CERT_INVALID) { - if(data->set.ssl.verifypeer) { - failf(data, "server certificate verification failed. CAfile: %s " - "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none", - data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none"); - return CURLE_SSL_CACERT; - } - else - infof(data, "\t server certificate verification FAILED\n"); - } - else - infof(data, "\t server certificate verification OK\n"); - } - else { - infof(data, "\t server certificate verification SKIPPED\n"); - goto after_server_cert_verification; - } - - /* initialize an X.509 certificate structure. */ - gnutls_x509_crt_init(&x509_cert); - - /* convert the given DER or PEM encoded Certificate to the native - gnutls_x509_crt_t format */ - gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER); - - if (data->set.ssl.issuercert) { - gnutls_x509_crt_init(&x509_issuer); - issuerp = load_file(data->set.ssl.issuercert); - gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM); - rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer); - unload_file(issuerp); - if (rc <= 0) { - failf(data, "server certificate issuer check failed (IssuerCert: %s)", - data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); - return CURLE_SSL_ISSUER_ERROR; - } - infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n", - data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); - } - - size=sizeof(certbuf); - rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME, - 0, /* the first and only one */ - FALSE, - certbuf, - &size); - if(rc) { - infof(data, "error fetching CN from cert:%s\n", - gnutls_strerror(rc)); - } - - /* This function will check if the given certificate's subject matches the - given hostname. This is a basic implementation of the matching described - in RFC2818 (HTTPS), which takes into account wildcards, and the subject - alternative name PKIX extension. Returns non zero on success, and zero on - failure. */ - rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name); - - if(!rc) { - if(data->set.ssl.verifyhost > 1) { - failf(data, "SSL: certificate subject name (%s) does not match " - "target host name '%s'", certbuf, conn->host.dispname); - gnutls_x509_crt_deinit(x509_cert); - return CURLE_PEER_FAILED_VERIFICATION; - } - else - infof(data, "\t common name: %s (does not match '%s')\n", - certbuf, conn->host.dispname); - } - else - infof(data, "\t common name: %s (matched)\n", certbuf); - - /* Check for time-based validity */ - certclock = gnutls_x509_crt_get_expiration_time(x509_cert); - - if(certclock == (time_t)-1) { - failf(data, "server cert expiration date verify failed"); - return CURLE_SSL_CONNECT_ERROR; - } - - if(certclock < time(NULL)) { - if(data->set.ssl.verifypeer) { - failf(data, "server certificate expiration date has passed."); - return CURLE_PEER_FAILED_VERIFICATION; - } - else - infof(data, "\t server certificate expiration date FAILED\n"); - } - else - infof(data, "\t server certificate expiration date OK\n"); - - certclock = gnutls_x509_crt_get_activation_time(x509_cert); - - if(certclock == (time_t)-1) { - failf(data, "server cert activation date verify failed"); - return CURLE_SSL_CONNECT_ERROR; - } - - if(certclock > time(NULL)) { - if(data->set.ssl.verifypeer) { - failf(data, "server certificate not activated yet."); - return CURLE_PEER_FAILED_VERIFICATION; - } - else - infof(data, "\t server certificate activation date FAILED\n"); - } - else - infof(data, "\t server certificate activation date OK\n"); - - /* Show: - - - ciphers used - - subject - - start date - - expire date - - common name - - issuer - - */ - - /* public key algorithm's parameters */ - algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits); - infof(data, "\t certificate public key: %s\n", - gnutls_pk_algorithm_get_name(algo)); - - /* version of the X.509 certificate. */ - infof(data, "\t certificate version: #%d\n", - gnutls_x509_crt_get_version(x509_cert)); - - - size = sizeof(certbuf); - gnutls_x509_crt_get_dn(x509_cert, certbuf, &size); - infof(data, "\t subject: %s\n", certbuf); - - certclock = gnutls_x509_crt_get_activation_time(x509_cert); - showtime(data, "start date", certclock); - - certclock = gnutls_x509_crt_get_expiration_time(x509_cert); - showtime(data, "expire date", certclock); - - size = sizeof(certbuf); - gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); - infof(data, "\t issuer: %s\n", certbuf); - - gnutls_x509_crt_deinit(x509_cert); - -after_server_cert_verification: - - /* compression algorithm (if any) */ - ptr = gnutls_compression_get_name(gnutls_compression_get(session)); - /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ - infof(data, "\t compression: %s\n", ptr); - - /* the name of the cipher used. ie 3DES. */ - ptr = gnutls_cipher_get_name(gnutls_cipher_get(session)); - infof(data, "\t cipher: %s\n", ptr); - - /* the MAC algorithms name. ie SHA1 */ - ptr = gnutls_mac_get_name(gnutls_mac_get(session)); - infof(data, "\t MAC: %s\n", ptr); - - conn->ssl[sockindex].state = ssl_connection_complete; - conn->recv[sockindex] = gtls_recv; - conn->send[sockindex] = gtls_send; - - { - /* we always unconditionally get the session id here, as even if we - already got it from the cache and asked to use it in the connection, it - might've been rejected and then a new one is in use now and we need to - detect that. */ - void *connect_sessionid; - size_t connect_idsize; - - /* get the session ID data size */ - gnutls_session_get_data(session, NULL, &connect_idsize); - connect_sessionid = malloc(connect_idsize); /* get a buffer for it */ - - if(connect_sessionid) { - /* extract session ID to the allocated buffer */ - gnutls_session_get_data(session, connect_sessionid, &connect_idsize); - - incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)); - if (incache) { - /* there was one before in the cache, so instead of risking that the - previous one was rejected, we just kill that and store the new */ - Curl_ssl_delsessionid(conn, ssl_sessionid); - } - - /* store this session id */ - result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize); - if(result) { - free(connect_sessionid); - result = CURLE_OUT_OF_MEMORY; - } - } - else - result = CURLE_OUT_OF_MEMORY; - } - - return result; -} - - -/* - * This function is called after the TCP connect has completed. Setup the TLS - * layer and do all necessary magic. - */ -/* We use connssl->connecting_state to keep track of the connection status; - there are three states: 'ssl_connect_1' (not started yet or complete), - 'ssl_connect_2_reading' (waiting for data from server), and - 'ssl_connect_2_writing' (waiting to be able to write). - */ -static CURLcode -gtls_connect_common(struct connectdata *conn, - int sockindex, - bool nonblocking, - bool *done) -{ - int rc; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - /* Initiate the connection, if not already done */ - if(ssl_connect_1==connssl->connecting_state) { - rc = gtls_connect_step1 (conn, sockindex); - if(rc) - return rc; - } - - rc = handshake(conn, sockindex, TRUE, nonblocking); - if(rc) - /* handshake() sets its own error message with failf() */ - return rc; - - /* Finish connecting once the handshake is done */ - if(ssl_connect_1==connssl->connecting_state) { - rc = gtls_connect_step3(conn, sockindex); - if(rc) - return rc; - } - - *done = ssl_connect_1==connssl->connecting_state; - - return CURLE_OK; -} - -CURLcode -Curl_gtls_connect_nonblocking(struct connectdata *conn, - int sockindex, - bool *done) -{ - return gtls_connect_common(conn, sockindex, TRUE, done); -} - -CURLcode -Curl_gtls_connect(struct connectdata *conn, - int sockindex) - -{ - CURLcode retcode; - bool done = FALSE; - - retcode = gtls_connect_common(conn, sockindex, FALSE, &done); - if(retcode) - return retcode; - - DEBUGASSERT(done); - - return CURLE_OK; -} - -static ssize_t gtls_send(struct connectdata *conn, - int sockindex, - const void *mem, - size_t len, - CURLcode *curlcode) -{ - ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len); - - if(rc < 0 ) { - *curlcode = (rc == GNUTLS_E_AGAIN) - ? CURLE_AGAIN - : CURLE_SEND_ERROR; - - rc = -1; - } - - return rc; -} - -void Curl_gtls_close_all(struct SessionHandle *data) -{ - /* FIX: make the OpenSSL code more generic and use parts of it here */ - (void)data; -} - -static void close_one(struct connectdata *conn, - int idx) -{ - if(conn->ssl[idx].session) { - gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR); - gnutls_deinit(conn->ssl[idx].session); - conn->ssl[idx].session = NULL; - } - if(conn->ssl[idx].cred) { - gnutls_certificate_free_credentials(conn->ssl[idx].cred); - conn->ssl[idx].cred = NULL; - } -#ifdef USE_TLS_SRP - if (conn->ssl[idx].srp_client_cred) { - gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred); - conn->ssl[idx].srp_client_cred = NULL; - } -#endif -} - -void Curl_gtls_close(struct connectdata *conn, int sockindex) -{ - close_one(conn, sockindex); -} - -/* - * This function is called to shut down the SSL layer but keep the - * socket open (CCC - Clear Command Channel) - */ -int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) -{ - ssize_t result; - int retval = 0; - struct SessionHandle *data = conn->data; - int done = 0; - char buf[120]; - - /* This has only been tested on the proftpd server, and the mod_tls code - sends a close notify alert without waiting for a close notify alert in - response. Thus we wait for a close notify alert from the server, but - we do not send one. Let's hope other servers do the same... */ - - if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) - gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR); - - if(conn->ssl[sockindex].session) { - while(!done) { - int what = Curl_socket_ready(conn->sock[sockindex], - CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); - if(what > 0) { - /* Something to read, let's do it and hope that it is the close - notify alert from the server */ - result = gnutls_record_recv(conn->ssl[sockindex].session, - buf, sizeof(buf)); - switch(result) { - case 0: - /* This is the expected response. There was no data but only - the close notify alert */ - done = 1; - break; - case GNUTLS_E_AGAIN: - case GNUTLS_E_INTERRUPTED: - infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n"); - break; - default: - retval = -1; - done = 1; - break; - } - } - else if(0 == what) { - /* timeout */ - failf(data, "SSL shutdown timeout"); - done = 1; - break; - } - else { - /* anything that gets here is fatally bad */ - failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); - retval = -1; - done = 1; - } - } - gnutls_deinit(conn->ssl[sockindex].session); - } - gnutls_certificate_free_credentials(conn->ssl[sockindex].cred); - -#ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP - && data->set.ssl.username != NULL) - gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred); -#endif - - conn->ssl[sockindex].cred = NULL; - conn->ssl[sockindex].session = NULL; - - return retval; -} - -static ssize_t gtls_recv(struct connectdata *conn, /* connection data */ - int num, /* socketindex */ - char *buf, /* store read data here */ - size_t buffersize, /* max amount to read */ - CURLcode *curlcode) -{ - ssize_t ret; - - ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize); - if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) { - *curlcode = CURLE_AGAIN; - return -1; - } - - if(ret == GNUTLS_E_REHANDSHAKE) { - /* BLOCKING call, this is bad but a work-around for now. Fixing this "the - proper way" takes a whole lot of work. */ - CURLcode rc = handshake(conn, num, FALSE, FALSE); - if(rc) - /* handshake() writes error message on its own */ - *curlcode = rc; - else - *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */ - return -1; - } - - if(ret < 0) { - failf(conn->data, "GnuTLS recv error (%d): %s", - (int)ret, gnutls_strerror((int)ret)); - *curlcode = CURLE_RECV_ERROR; - return -1; - } - - return ret; -} - -void Curl_gtls_session_free(void *ptr) -{ - free(ptr); -} - -size_t Curl_gtls_version(char *buffer, size_t size) -{ - return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL)); -} - -int Curl_gtls_seed(struct SessionHandle *data) -{ - /* we have the "SSL is seeded" boolean static to prevent multiple - time-consuming seedings in vain */ - static bool ssl_seeded = FALSE; - - /* Quickly add a bit of entropy */ - gcry_fast_random_poll(); - - if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || - data->set.str[STRING_SSL_EGDSOCKET]) { - - /* TODO: to a good job seeding the RNG - This may involve the gcry_control function and these options: - GCRYCTL_SET_RANDOM_SEED_FILE - GCRYCTL_SET_RNDEGD_SOCKET - */ - ssl_seeded = TRUE; - } - return 0; -} - -#endif /* USE_GNUTLS */ diff --git a/third_party/curl/lib/gtls.h b/third_party/curl/lib/gtls.h deleted file mode 100644 index 6275b49a3..000000000 --- a/third_party/curl/lib/gtls.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef __GTLS_H -#define __GTLS_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifdef USE_GNUTLS - -int Curl_gtls_init(void); -int Curl_gtls_cleanup(void); -CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex); -CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn, - int sockindex, - bool *done); - -/* tell GnuTLS to close down all open information regarding connections (and - thus session ID caching etc) */ -void Curl_gtls_close_all(struct SessionHandle *data); - - /* close a SSL connection */ -void Curl_gtls_close(struct connectdata *conn, int sockindex); - -void Curl_gtls_session_free(void *ptr); -size_t Curl_gtls_version(char *buffer, size_t size); -int Curl_gtls_shutdown(struct connectdata *conn, int sockindex); -int Curl_gtls_seed(struct SessionHandle *data); - -/* API setup for GnuTLS */ -#define curlssl_init Curl_gtls_init -#define curlssl_cleanup Curl_gtls_cleanup -#define curlssl_connect Curl_gtls_connect -#define curlssl_connect_nonblocking Curl_gtls_connect_nonblocking -#define curlssl_session_free(x) Curl_gtls_session_free(x) -#define curlssl_close_all Curl_gtls_close_all -#define curlssl_close Curl_gtls_close -#define curlssl_shutdown(x,y) Curl_gtls_shutdown(x,y) -#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN) -#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN) -#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL) -#define curlssl_version Curl_gtls_version -#define curlssl_check_cxn(x) (x=x, -1) -#define curlssl_data_pending(x,y) (x=x, y=y, 0) - -#endif /* USE_GNUTLS */ -#endif diff --git a/third_party/curl/lib/hash.c b/third_party/curl/lib/hash.c deleted file mode 100644 index cdcd26017..000000000 --- a/third_party/curl/lib/hash.c +++ /dev/null @@ -1,339 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include - -#include "hash.h" -#include "llist.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -static void -hash_element_dtor(void *user, void *element) -{ - struct curl_hash *h = (struct curl_hash *) user; - struct curl_hash_element *e = (struct curl_hash_element *) element; - - if(e->key) - free(e->key); - - if(e->ptr) - h->dtor(e->ptr); - - free(e); -} - -/* return 1 on error, 0 is fine */ -int -Curl_hash_init(struct curl_hash *h, - int slots, - hash_function hfunc, - comp_function comparator, - curl_hash_dtor dtor) -{ - int i; - - if(!slots || !hfunc || !comparator ||!dtor) { - return 1; /* failure */ - } - - h->hash_func = hfunc; - h->comp_func = comparator; - h->dtor = dtor; - h->size = 0; - h->slots = slots; - - h->table = malloc(slots * sizeof(struct curl_llist *)); - if(h->table) { - for (i = 0; i < slots; ++i) { - h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor); - if(!h->table[i]) { - while(i--) - Curl_llist_destroy(h->table[i], NULL); - free(h->table); - return 1; /* failure */ - } - } - return 0; /* fine */ - } - else - return 1; /* failure */ -} - -struct curl_hash * -Curl_hash_alloc(int slots, - hash_function hfunc, - comp_function comparator, - curl_hash_dtor dtor) -{ - struct curl_hash *h; - - if(!slots || !hfunc || !comparator ||!dtor) { - return NULL; /* failure */ - } - - h = malloc(sizeof(struct curl_hash)); - if(h) { - if(Curl_hash_init(h, slots, hfunc, comparator, dtor)) { - /* failure */ - free(h); - h = NULL; - } - } - - return h; -} - - - -static struct curl_hash_element * -mk_hash_element(const void *key, size_t key_len, const void *p) -{ - struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element)); - - if(he) { - void *dupkey = malloc(key_len); - if(dupkey) { - /* copy the key */ - memcpy(dupkey, key, key_len); - - he->key = dupkey; - he->key_len = key_len; - he->ptr = (void *) p; - } - else { - /* failed to duplicate the key, free memory and fail */ - free(he); - he = NULL; - } - } - return he; -} - -#define FETCH_LIST(x,y,z) x->table[x->hash_func(y, z, x->slots)] - -/* Insert the data in the hash. If there already was a match in the hash, - that data is replaced. */ -void * -Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p) -{ - struct curl_hash_element *he; - struct curl_llist_element *le; - struct curl_llist *l = FETCH_LIST (h, key, key_len); - - for (le = l->head; le; le = le->next) { - he = (struct curl_hash_element *) le->ptr; - if(h->comp_func(he->key, he->key_len, key, key_len)) { - Curl_llist_remove(l, le, (void *)h); - --h->size; - break; - } - } - - he = mk_hash_element(key, key_len, p); - if(he) { - if(Curl_llist_insert_next(l, l->tail, he)) { - ++h->size; - return p; /* return the new entry */ - } - /* - * Couldn't insert it, destroy the 'he' element and the key again. We - * don't call hash_element_dtor() since that would also call the - * "destructor" for the actual data 'p'. When we fail, we shall not touch - * that data. - */ - free(he->key); - free(he); - } - - return NULL; /* failure */ -} - -/* remove the identified hash entry, returns non-zero on failure */ -int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len) -{ - struct curl_llist_element *le; - struct curl_hash_element *he; - struct curl_llist *l = FETCH_LIST(h, key, key_len); - - for (le = l->head; le; le = le->next) { - he = le->ptr; - if(h->comp_func(he->key, he->key_len, key, key_len)) { - Curl_llist_remove(l, le, (void *) h); - return 0; - } - } - return 1; -} - -void * -Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len) -{ - struct curl_llist_element *le; - struct curl_hash_element *he; - struct curl_llist *l = FETCH_LIST(h, key, key_len); - - for (le = l->head; le; le = le->next) { - he = le->ptr; - if(h->comp_func(he->key, he->key_len, key, key_len)) { - return he->ptr; - } - } - - return NULL; -} - -#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST) -void -Curl_hash_apply(curl_hash *h, void *user, - void (*cb)(void *user, void *ptr)) -{ - struct curl_llist_element *le; - int i; - - for (i = 0; i < h->slots; ++i) { - for (le = (h->table[i])->head; - le; - le = le->next) { - curl_hash_element *el = le->ptr; - cb(user, el->ptr); - } - } -} -#endif - -void -Curl_hash_clean(struct curl_hash *h) -{ - int i; - - for (i = 0; i < h->slots; ++i) { - Curl_llist_destroy(h->table[i], (void *) h); - h->table[i] = NULL; - } - - free(h->table); -} - -void -Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, - int (*comp)(void *, void *)) -{ - struct curl_llist_element *le; - struct curl_llist_element *lnext; - struct curl_llist *list; - int i; - - for (i = 0; i < h->slots; ++i) { - list = h->table[i]; - le = list->head; /* get first list entry */ - while(le) { - struct curl_hash_element *he = le->ptr; - lnext = le->next; - /* ask the callback function if we shall remove this entry or not */ - if(comp(user, he->ptr)) { - Curl_llist_remove(list, le, (void *) h); - --h->size; /* one less entry in the hash now */ - } - le = lnext; - } - } -} - -void -Curl_hash_destroy(struct curl_hash *h) -{ - if(!h) - return; - - Curl_hash_clean(h); - - free(h); -} - -size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num) -{ - const char* key_str = (const char *) key; - const char *end = key_str + key_length; - unsigned long h = 5381; - - while(key_str < end) { - h += h << 5; - h ^= (unsigned long) *key_str++; - } - - return (h % slots_num); -} - -size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2, size_t key2_len) -{ - char *key1 = (char *)k1; - char *key2 = (char *)k2; - - if(key1_len == key2_len && - *key1 == *key2 && - memcmp(key1, key2, key1_len) == 0) { - return 1; - } - - return 0; -} - -#if 0 /* useful function for debugging hashes and their contents */ -void Curl_hash_print(struct curl_hash *h, - void (*func)(void *)) -{ - int i; - struct curl_llist_element *le; - struct curl_llist *list; - struct curl_hash_element *he; - if(!h) - return; - - fprintf(stderr, "=Hash dump=\n"); - - for (i = 0; i < h->slots; i++) { - list = h->table[i]; - le = list->head; /* get first list entry */ - if(le) { - fprintf(stderr, "index %d:", i); - while(le) { - he = le->ptr; - if(func) - func(he->ptr); - else - fprintf(stderr, " [%p]", he->ptr); - le = le->next; - } - fprintf(stderr, "\n"); - } - } -} -#endif diff --git a/third_party/curl/lib/hash.h b/third_party/curl/lib/hash.h deleted file mode 100644 index 993aaedd2..000000000 --- a/third_party/curl/lib/hash.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef __HASH_H -#define __HASH_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include - -#include "llist.h" - -/* Hash function prototype */ -typedef size_t (*hash_function) (void* key, - size_t key_length, - size_t slots_num); - -/* - Comparator function prototype. Compares two keys. -*/ -typedef size_t (*comp_function) (void* key1, - size_t key1_len, - void*key2, - size_t key2_len); - -typedef void (*curl_hash_dtor)(void *); - -struct curl_hash { - struct curl_llist **table; - - /* Hash function to be used for this hash table */ - hash_function hash_func; - - /* Comparator function to compare keys */ - comp_function comp_func; - curl_hash_dtor dtor; - int slots; - size_t size; -}; - -struct curl_hash_element { - void *ptr; - char *key; - size_t key_len; -}; - - -int Curl_hash_init(struct curl_hash *h, - int slots, - hash_function hfunc, - comp_function comparator, - curl_hash_dtor dtor); - -struct curl_hash *Curl_hash_alloc(int slots, - hash_function hfunc, - comp_function comparator, - curl_hash_dtor dtor); - -void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p); -int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len); -void *Curl_hash_pick(struct curl_hash *, void * key, size_t key_len); -void Curl_hash_apply(struct curl_hash *h, void *user, - void (*cb)(void *user, void *ptr)); -int Curl_hash_count(struct curl_hash *h); -void Curl_hash_clean(struct curl_hash *h); -void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, - int (*comp)(void *, void *)); -void Curl_hash_destroy(struct curl_hash *h); - -size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num); -size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2, - size_t key2_len); - -#endif diff --git a/third_party/curl/lib/hmac.c b/third_party/curl/lib/hmac.c deleted file mode 100644 index 8cb5f2eaa..000000000 --- a/third_party/curl/lib/hmac.c +++ /dev/null @@ -1,131 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * RFC2104 Keyed-Hashing for Message Authentication - * - ***************************************************************************/ - -#include "setup.h" - -#ifndef CURL_DISABLE_CRYPTO_AUTH - -#include "curl_hmac.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* - * Generic HMAC algorithm. - * - * This module computes HMAC digests based on any hash function. Parameters - * and computing procedures are set-up dynamically at HMAC computation - * context initialisation. - */ - -static const unsigned char hmac_ipad = 0x36; -static const unsigned char hmac_opad = 0x5C; - - - -HMAC_context * -Curl_HMAC_init(const HMAC_params * hashparams, - const unsigned char * key, - unsigned int keylen) -{ - size_t i; - HMAC_context * ctxt; - unsigned char * hkey; - unsigned char b; - - /* Create HMAC context. */ - i = sizeof *ctxt + 2 * hashparams->hmac_ctxtsize + hashparams->hmac_resultlen; - ctxt = malloc(i); - - if(!ctxt) - return ctxt; - - ctxt->hmac_hash = hashparams; - ctxt->hmac_hashctxt1 = (void *) (ctxt + 1); - ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 + - hashparams->hmac_ctxtsize); - - /* If the key is too long, replace it by its hash digest. */ - if(keylen > hashparams->hmac_maxkeylen) { - (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); - (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen); - hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize; - (*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1); - key = hkey; - keylen = hashparams->hmac_resultlen; - } - - /* Prime the two hash contexts with the modified key. */ - (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); - (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2); - - for (i = 0; i < keylen; i++) { - b = (unsigned char)(*key ^ hmac_ipad); - (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1); - b = (unsigned char)(*key++ ^ hmac_opad); - (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1); - } - - for (; i < hashparams->hmac_maxkeylen; i++) { - (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1); - (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1); - } - - /* Done, return pointer to HMAC context. */ - return ctxt; -} - -int Curl_HMAC_update(HMAC_context * ctxt, - const unsigned char * data, - unsigned int len) -{ - /* Update first hash calculation. */ - (*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len); - return 0; -} - - -int Curl_HMAC_final(HMAC_context * ctxt, unsigned char * result) -{ - const HMAC_params * hashparams = ctxt->hmac_hash; - - /* Do not get result if called with a null parameter: only release storage. */ - - if(!result) - result = (unsigned char *) ctxt->hmac_hashctxt2 + - ctxt->hmac_hash->hmac_ctxtsize; - - (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1); - (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, - result, hashparams->hmac_resultlen); - (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2); - free((char *) ctxt); - return 0; -} - -#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/third_party/curl/lib/hostares.c b/third_party/curl/lib/hostares.c deleted file mode 100644 index a165cb91f..000000000 --- a/third_party/curl/lib/hostares.c +++ /dev/null @@ -1,439 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include - -#ifdef HAVE_LIMITS_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include /* required for free() prototypes */ -#endif -#ifdef HAVE_UNISTD_H -#include /* for the close() proto */ -#endif -#ifdef __VMS -#include -#include -#include -#endif - -#ifdef HAVE_PROCESS_H -#include -#endif - -#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) -#undef in_addr_t -#define in_addr_t unsigned long -#endif - -#include "urldata.h" -#include "sendf.h" -#include "hostip.h" -#include "hash.h" -#include "share.h" -#include "strerror.h" -#include "url.h" -#include "multiif.h" -#include "inet_pton.h" -#include "connect.h" -#include "select.h" -#include "progress.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/*********************************************************************** - * Only for ares-enabled builds - **********************************************************************/ - -#ifdef CURLRES_ARES - -/* - * Curl_resolv_fdset() is called when someone from the outside world (using - * curl_multi_fdset()) wants to get our fd_set setup and we're talking with - * ares. The caller must make sure that this function is only called when we - * have a working ares channel. - * - * Returns: CURLE_OK always! - */ - -int Curl_resolv_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) - -{ - struct timeval maxtime; - struct timeval timebuf; - struct timeval *timeout; - int max = ares_getsock(conn->data->state.areschannel, - (ares_socket_t *)socks, numsocks); - - - maxtime.tv_sec = CURL_TIMEOUT_RESOLVE; - maxtime.tv_usec = 0; - - timeout = ares_timeout(conn->data->state.areschannel, &maxtime, &timebuf); - - Curl_expire(conn->data, - (timeout->tv_sec * 1000) + (timeout->tv_usec/1000)); - - return max; -} - -/* - * waitperform() - * - * 1) Ask ares what sockets it currently plays with, then - * 2) wait for the timeout period to check for action on ares' sockets. - * 3) tell ares to act on all the sockets marked as "with action" - * - * return number of sockets it worked on - */ - -static int waitperform(struct connectdata *conn, int timeout_ms) -{ - struct SessionHandle *data = conn->data; - int nfds; - int bitmask; - ares_socket_t socks[ARES_GETSOCK_MAXNUM]; - struct pollfd pfd[ARES_GETSOCK_MAXNUM]; - int i; - int num = 0; - - bitmask = ares_getsock(data->state.areschannel, socks, ARES_GETSOCK_MAXNUM); - - for(i=0; i < ARES_GETSOCK_MAXNUM; i++) { - pfd[i].events = 0; - pfd[i].revents = 0; - if(ARES_GETSOCK_READABLE(bitmask, i)) { - pfd[i].fd = socks[i]; - pfd[i].events |= POLLRDNORM|POLLIN; - } - if(ARES_GETSOCK_WRITABLE(bitmask, i)) { - pfd[i].fd = socks[i]; - pfd[i].events |= POLLWRNORM|POLLOUT; - } - if(pfd[i].events != 0) - num++; - else - break; - } - - if(num) - nfds = Curl_poll(pfd, num, timeout_ms); - else - nfds = 0; - - if(!nfds) - /* Call ares_process() unconditonally here, even if we simply timed out - above, as otherwise the ares name resolve won't timeout! */ - ares_process_fd(data->state.areschannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD); - else { - /* move through the descriptors and ask for processing on them */ - for(i=0; i < num; i++) - ares_process_fd(data->state.areschannel, - pfd[i].revents & (POLLRDNORM|POLLIN)? - pfd[i].fd:ARES_SOCKET_BAD, - pfd[i].revents & (POLLWRNORM|POLLOUT)? - pfd[i].fd:ARES_SOCKET_BAD); - } - return nfds; -} - -/* - * Curl_is_resolved() is called repeatedly to check if a previous name resolve - * request has completed. It should also make sure to time-out if the - * operation seems to take too long. - * - * Returns normal CURLcode errors. - */ -CURLcode Curl_is_resolved(struct connectdata *conn, - struct Curl_dns_entry **dns) -{ - struct SessionHandle *data = conn->data; - - *dns = NULL; - - waitperform(conn, 0); - - if(conn->async.done) { - /* we're done, kill the ares handle */ - if(!conn->async.dns) { - failf(data, "Could not resolve host: %s (%s)", conn->host.dispname, - ares_strerror(conn->async.status)); - return CURLE_COULDNT_RESOLVE_HOST; - } - *dns = conn->async.dns; - } - - return CURLE_OK; -} - -/* - * Curl_wait_for_resolv() waits for a resolve to finish. This function should - * be avoided since using this risk getting the multi interface to "hang". - * - * If 'entry' is non-NULL, make it point to the resolved dns entry - * - * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and - * CURLE_OPERATION_TIMEDOUT if a time-out occurred. - */ -CURLcode Curl_wait_for_resolv(struct connectdata *conn, - struct Curl_dns_entry **entry) -{ - CURLcode rc=CURLE_OK; - struct SessionHandle *data = conn->data; - long timeout; - struct timeval now = Curl_tvnow(); - - timeout = Curl_timeleft(data, &now, TRUE); - if(!timeout) - timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */ - - /* Wait for the name resolve query to complete. */ - for(;;) { - struct timeval *tvp, tv, store; - long timediff; - int itimeout; - int timeout_ms; - - itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout; - - store.tv_sec = itimeout/1000; - store.tv_usec = (itimeout%1000)*1000; - - tvp = ares_timeout(data->state.areschannel, &store, &tv); - - /* use the timeout period ares returned to us above if less than one - second is left, otherwise just use 1000ms to make sure the progress - callback gets called frequent enough */ - if(!tvp->tv_sec) - timeout_ms = (int)(tvp->tv_usec/1000); - else - timeout_ms = 1000; - - waitperform(conn, timeout_ms); - - if(conn->async.done) - break; - - if(Curl_pgrsUpdate(conn)) { - rc = CURLE_ABORTED_BY_CALLBACK; - timeout = -1; /* trigger the cancel below */ - } - else { - struct timeval now2 = Curl_tvnow(); - timediff = Curl_tvdiff(now2, now); /* spent time */ - timeout -= timediff?timediff:1; /* always deduct at least 1 */ - now = now2; /* for next loop */ - } - if(timeout < 0) { - /* our timeout, so we cancel the ares operation */ - ares_cancel(data->state.areschannel); - break; - } - } - - /* Operation complete, if the lookup was successful we now have the entry - in the cache. */ - - if(entry) - *entry = conn->async.dns; - - if(!conn->async.dns) { - /* a name was not resolved */ - if((timeout < 0) || (conn->async.status == ARES_ETIMEOUT)) { - if (conn->bits.httpproxy) { - failf(data, "Resolving proxy timed out: %s", conn->proxy.dispname); - rc = CURLE_COULDNT_RESOLVE_PROXY; - } - else { - failf(data, "Resolving host timed out: %s", conn->host.dispname); - rc = CURLE_COULDNT_RESOLVE_HOST; - } - } - else if(conn->async.done) { - if (conn->bits.httpproxy) { - failf(data, "Could not resolve proxy: %s (%s)", conn->proxy.dispname, - ares_strerror(conn->async.status)); - rc = CURLE_COULDNT_RESOLVE_PROXY; - } - else { - failf(data, "Could not resolve host: %s (%s)", conn->host.dispname, - ares_strerror(conn->async.status)); - rc = CURLE_COULDNT_RESOLVE_HOST; - } - } - else - rc = CURLE_OPERATION_TIMEDOUT; - - /* close the connection, since we can't return failure here without - cleaning up this connection properly */ - conn->bits.close = TRUE; - } - - return rc; -} - -/* - * ares_query_completed_cb() is the callback that ares will call when - * the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(), - * when using ares, is completed either successfully or with failure. - */ -static void ares_query_completed_cb(void *arg, /* (struct connectdata *) */ - int status, -#ifdef HAVE_CARES_CALLBACK_TIMEOUTS - int timeouts, -#endif - struct hostent *hostent) -{ - struct connectdata *conn = (struct connectdata *)arg; - struct Curl_addrinfo * ai = NULL; - -#ifdef HAVE_CARES_CALLBACK_TIMEOUTS - (void)timeouts; /* ignored */ -#endif - - switch(status) { - case CURL_ASYNC_SUCCESS: - ai = Curl_he2ai(hostent, conn->async.port); - break; - case ARES_EDESTRUCTION: - /* this ares handle is getting destroyed, the 'arg' pointer may not be - valid! */ - return; - default: - /* do nothing */ - break; - } - - (void)Curl_addrinfo_callback(arg, status, ai); -} - -/* - * Curl_getaddrinfo() - when using ares - * - * Returns name information about the given hostname and port number. If - * successful, the 'hostent' is returned and the forth argument will point to - * memory we need to free after use. That memory *MUST* be freed with - * Curl_freeaddrinfo(), nothing else. - */ -Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, - const char *hostname, - int port, - int *waitp) -{ - char *bufp; - struct SessionHandle *data = conn->data; - struct in_addr in; - int family = PF_INET; -#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ - struct in6_addr in6; -#endif /* CURLRES_IPV6 */ - - *waitp = 0; /* default to synchronous response */ - - /* First check if this is an IPv4 address string */ - if(Curl_inet_pton(AF_INET, hostname, &in) > 0) { - /* This is a dotted IP address 123.123.123.123-style */ - return Curl_ip2addr(AF_INET, &in, hostname, port); - } - -#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ - /* Otherwise, check if this is an IPv6 address string */ - if (Curl_inet_pton (AF_INET6, hostname, &in6) > 0) { - /* This must be an IPv6 address literal. */ - return Curl_ip2addr(AF_INET6, &in6, hostname, port); - } - - switch(conn->ip_version) { - default: -#if ARES_VERSION >= 0x010601 - family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older - c-ares versions this just falls through and defaults - to PF_INET */ - break; -#endif - case CURL_IPRESOLVE_V4: - family = PF_INET; - break; - case CURL_IPRESOLVE_V6: - family = PF_INET6; - break; - } -#endif /* CURLRES_IPV6 */ - - bufp = strdup(hostname); - - if(bufp) { - Curl_safefree(conn->async.hostname); - conn->async.hostname = bufp; - conn->async.port = port; - conn->async.done = FALSE; /* not done */ - conn->async.status = 0; /* clear */ - conn->async.dns = NULL; /* clear */ - conn->async.temp_ai = NULL; /* clear */ - -#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ - if(family == PF_UNSPEC) { - conn->async.num_pending = 2; - - /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname(data->state.areschannel, hostname, PF_INET, - ares_query_completed_cb, conn); - ares_gethostbyname(data->state.areschannel, hostname, PF_INET6, - ares_query_completed_cb, conn); - } - else -#endif /* CURLRES_IPV6 */ - { - conn->async.num_pending = 1; - - /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname(data->state.areschannel, hostname, family, - ares_query_completed_cb, conn); - } - - *waitp = 1; /* expect asynchronous response */ - } - return NULL; /* no struct yet */ -} -#endif /* CURLRES_ARES */ diff --git a/third_party/curl/lib/hostasyn.c b/third_party/curl/lib/hostasyn.c deleted file mode 100644 index 555da822c..000000000 --- a/third_party/curl/lib/hostasyn.c +++ /dev/null @@ -1,205 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include /* required for free() prototypes */ -#endif -#ifdef HAVE_UNISTD_H -#include /* for the close() proto */ -#endif -#ifdef __VMS -#include -#include -#include -#endif - -#ifdef HAVE_PROCESS_H -#include -#endif - -#include "urldata.h" -#include "sendf.h" -#include "hostip.h" -#include "hash.h" -#include "share.h" -#include "strerror.h" -#include "url.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/*********************************************************************** - * Only for builds using asynchronous name resolves - **********************************************************************/ -#ifdef CURLRES_ASYNCH - -/* - * Cancel all possibly still on-going resolves for this connection. - */ -void Curl_async_cancel(struct connectdata *conn) -{ - /* If we have a "half" response already received, we first clear that off - so that nothing is tempted to use it */ - if(conn->async.temp_ai) { - Curl_freeaddrinfo(conn->async.temp_ai); - conn->async.temp_ai = NULL; - } -} - - -/* - * Curl_addrinfo_callback() gets called by ares, gethostbyname_thread() - * or getaddrinfo_thread() when we got the name resolved (or not!). - * - * If the status argument is CURL_ASYNC_SUCCESS, this function takes - * ownership of the Curl_addrinfo passed, storing the resolved data - * in the DNS cache. - * - * The storage operation locks and unlocks the DNS cache. - */ -CURLcode Curl_addrinfo_callback(struct connectdata *conn, - int status, - struct Curl_addrinfo *ai) -{ - struct Curl_dns_entry *dns = NULL; - CURLcode rc = CURLE_OK; - - conn->async.status = status; - - if(CURL_ASYNC_SUCCESS == status) { - if(ai) { - struct SessionHandle *data = conn->data; - -#if defined(ENABLE_IPV6) && defined(CURLRES_ARES) /* CURLRES_IPV6 */ - Curl_addrinfo *ai_tail = ai; - - while (ai_tail->ai_next) - ai_tail = ai_tail->ai_next; - - /* Add the new results to the list of old results. */ - ai_tail->ai_next = conn->async.temp_ai; - conn->async.temp_ai = ai; - - if(--conn->async.num_pending > 0) - /* We are not done yet. Just return. */ - return CURLE_OK; - - /* make sure the temp pointer is cleared and isn't pointing to something - we take care of below */ - conn->async.temp_ai = NULL; -#endif - if(data->share) - Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - - dns = Curl_cache_addr(data, ai, - conn->async.hostname, - conn->async.port); - if(!dns) { - /* failed to store, cleanup and return error */ - Curl_freeaddrinfo(ai); - rc = CURLE_OUT_OF_MEMORY; - } - - if(data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); - } - else { -#if defined(ENABLE_IPV6) && defined(CURLRES_ARES) /* CURLRES_IPV6 */ - if(--conn->async.num_pending > 0) { - /* We are not done yet. Clean up and return. - This function will be called again. */ - if(conn->async.temp_ai) { - Curl_freeaddrinfo(conn->async.temp_ai); - conn->async.temp_ai = NULL; - } - return CURLE_OUT_OF_MEMORY; - } -#endif - rc = CURLE_OUT_OF_MEMORY; - } - } -#if defined(ENABLE_IPV6) && defined(CURLRES_ARES) /* CURLRES_IPV6 */ - else - { - if(--conn->async.num_pending > 0) - /* We are not done yet. Just return. */ - return CURLE_OK; - - if(conn->async.temp_ai) { - /* We are done, and while this latest request - failed, some previous results exist. */ - struct SessionHandle *data = conn->data; - - if(data->share) - Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - - dns = Curl_cache_addr(data, conn->async.temp_ai, - conn->async.hostname, - conn->async.port); - if(!dns) { - /* failed to store, cleanup and return error */ - Curl_freeaddrinfo(conn->async.temp_ai); - rc = CURLE_OUT_OF_MEMORY; - } - if(data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); - - /* make sure the temp pointer is cleared and isn't pointing to - something we've taken care of already */ - conn->async.temp_ai = NULL; - } - } -#endif - - conn->async.dns = dns; - - /* Set async.done TRUE last in this function since it may be used multi- - threaded and once this is TRUE the other thread may read fields from the - async struct */ - conn->async.done = TRUE; - - /* ipv4: The input hostent struct will be freed by ares when we return from - this function */ - return rc; -} - -#endif /* CURLRES_ASYNCH */ diff --git a/third_party/curl/lib/hostip.c b/third_party/curl/lib/hostip.c deleted file mode 100644 index 36273c562..000000000 --- a/third_party/curl/lib/hostip.c +++ /dev/null @@ -1,722 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include /* required for free() prototypes */ -#endif -#ifdef HAVE_UNISTD_H -#include /* for the close() proto */ -#endif -#ifdef __VMS -#include -#include -#include -#endif - -#ifdef HAVE_SETJMP_H -#include -#endif -#ifdef HAVE_SIGNAL_H -#include -#endif - -#ifdef HAVE_PROCESS_H -#include -#endif - -#include "urldata.h" -#include "sendf.h" -#include "hostip.h" -#include "hash.h" -#include "share.h" -#include "strerror.h" -#include "url.h" -#include "inet_ntop.h" -#include "warnless.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -#if defined(CURLRES_SYNCH) && \ - defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP) -/* alarm-based timeouts can only be used with all the dependencies satisfied */ -#define USE_ALARM_TIMEOUT -#endif - -/* - * hostip.c explained - * ================== - * - * The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c - * source file are these: - * - * CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use - * that. The host may not be able to resolve IPv6, but we don't really have to - * take that into account. Hosts that aren't IPv6-enabled have CURLRES_IPV4 - * defined. - * - * CURLRES_ARES - is defined if libcurl is built to use c-ares for - * asynchronous name resolves. This can be Windows or *nix. - * - * CURLRES_THREADED - is defined if libcurl is built to run under (native) - * Windows, and then the name resolve will be done in a new thread, and the - * supported API will be the same as for ares-builds. - * - * If any of the two previous are defined, CURLRES_ASYNCH is defined too. If - * libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is - * defined. - * - * The host*.c sources files are split up like this: - * - * hostip.c - method-independent resolver functions and utility functions - * hostasyn.c - functions for asynchronous name resolves - * hostsyn.c - functions for synchronous name resolves - * hostares.c - functions for ares-using name resolves - * hostthre.c - functions for threaded name resolves - * hostip4.c - ipv4-specific functions - * hostip6.c - ipv6-specific functions - * - * The hostip.h is the united header file for all this. It defines the - * CURLRES_* defines based on the config*.h and setup.h defines. - */ - -/* These two symbols are for the global DNS cache */ -static struct curl_hash hostname_cache; -static int host_cache_initialized; - -static void freednsentry(void *freethis); - -/* - * Curl_global_host_cache_init() initializes and sets up a global DNS cache. - * Global DNS cache is general badness. Do not use. This will be removed in - * a future version. Use the share interface instead! - * - * Returns a struct curl_hash pointer on success, NULL on failure. - */ -struct curl_hash *Curl_global_host_cache_init(void) -{ - int rc = 0; - if(!host_cache_initialized) { - rc = Curl_hash_init(&hostname_cache, 7, Curl_hash_str, - Curl_str_key_compare, freednsentry); - if(!rc) - host_cache_initialized = 1; - } - return rc?NULL:&hostname_cache; -} - -/* - * Destroy and cleanup the global DNS cache - */ -void Curl_global_host_cache_dtor(void) -{ - if(host_cache_initialized) { - Curl_hash_clean(&hostname_cache); - host_cache_initialized = 0; - } -} - -/* - * Return # of adresses in a Curl_addrinfo struct - */ -int Curl_num_addresses(const Curl_addrinfo *addr) -{ - int i = 0; - while(addr) { - addr = addr->ai_next; - i++; - } - return i; -} - -/* - * Curl_printable_address() returns a printable version of the 1st address - * given in the 'ai' argument. The result will be stored in the buf that is - * bufsize bytes big. - * - * If the conversion fails, it returns NULL. - */ -const char * -Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize) -{ - const struct sockaddr_in *sa4; - const struct in_addr *ipaddr4; -#ifdef ENABLE_IPV6 - const struct sockaddr_in6 *sa6; - const struct in6_addr *ipaddr6; -#endif - - switch (ai->ai_family) { - case AF_INET: - sa4 = (const void *)ai->ai_addr; - ipaddr4 = &sa4->sin_addr; - return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, - bufsize); -#ifdef ENABLE_IPV6 - case AF_INET6: - sa6 = (const void *)ai->ai_addr; - ipaddr6 = &sa6->sin6_addr; - return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, - bufsize); -#endif - default: - break; - } - return NULL; -} - -/* - * Return a hostcache id string for the providing host + port, to be used by - * the DNS caching. - */ -static char * -create_hostcache_id(const char *server, int port) -{ - /* create and return the new allocated entry */ - return aprintf("%s:%d", server, port); -} - -struct hostcache_prune_data { - long cache_timeout; - time_t now; -}; - -/* - * This function is set as a callback to be called for every entry in the DNS - * cache when we want to prune old unused entries. - * - * Returning non-zero means remove the entry, return 0 to keep it in the - * cache. - */ -static int -hostcache_timestamp_remove(void *datap, void *hc) -{ - struct hostcache_prune_data *data = - (struct hostcache_prune_data *) datap; - struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc; - - return (data->now - c->timestamp >= data->cache_timeout); -} - -/* - * Prune the DNS cache. This assumes that a lock has already been taken. - */ -static void -hostcache_prune(struct curl_hash *hostcache, long cache_timeout, time_t now) -{ - struct hostcache_prune_data user; - - user.cache_timeout = cache_timeout; - user.now = now; - - Curl_hash_clean_with_criterium(hostcache, - (void *) &user, - hostcache_timestamp_remove); -} - -/* - * Library-wide function for pruning the DNS cache. This function takes and - * returns the appropriate locks. - */ -void Curl_hostcache_prune(struct SessionHandle *data) -{ - time_t now; - - if((data->set.dns_cache_timeout == -1) || !data->dns.hostcache) - /* cache forever means never prune, and NULL hostcache means - we can't do it */ - return; - - if(data->share) - Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - - time(&now); - - /* Remove outdated and unused entries from the hostcache */ - hostcache_prune(data->dns.hostcache, - data->set.dns_cache_timeout, - now); - - if(data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); -} - -/* - * Check if the entry should be pruned. Assumes a locked cache. - */ -static int -remove_entry_if_stale(struct SessionHandle *data, struct Curl_dns_entry *dns) -{ - struct hostcache_prune_data user; - - if( !dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache) - /* cache forever means never prune, and NULL hostcache means - we can't do it */ - return 0; - - time(&user.now); - user.cache_timeout = data->set.dns_cache_timeout; - - if( !hostcache_timestamp_remove(&user,dns) ) - return 0; - - Curl_hash_clean_with_criterium(data->dns.hostcache, - (void *) &user, - hostcache_timestamp_remove); - - return 1; -} - - -#ifdef HAVE_SIGSETJMP -/* Beware this is a global and unique instance. This is used to store the - return address that we can jump back to from inside a signal handler. This - is not thread-safe stuff. */ -sigjmp_buf curl_jmpenv; -#endif - - -/* - * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. - * - * When calling Curl_resolv() has resulted in a response with a returned - * address, we call this function to store the information in the dns - * cache etc - * - * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. - */ -struct Curl_dns_entry * -Curl_cache_addr(struct SessionHandle *data, - Curl_addrinfo *addr, - const char *hostname, - int port) -{ - char *entry_id; - size_t entry_len; - struct Curl_dns_entry *dns; - struct Curl_dns_entry *dns2; - - /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) - return NULL; - entry_len = strlen(entry_id); - - /* Create a new cache entry */ - dns = calloc(1, sizeof(struct Curl_dns_entry)); - if(!dns) { - free(entry_id); - return NULL; - } - - dns->inuse = 0; /* init to not used */ - dns->addr = addr; /* this is the address(es) */ - time(&dns->timestamp); - if(dns->timestamp == 0) - dns->timestamp = 1; /* zero indicates that entry isn't in hash table */ - - /* Store the resolved data in our DNS cache. */ - dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len+1, - (void *)dns); - if(!dns2) { - free(dns); - free(entry_id); - return NULL; - } - - dns = dns2; - dns->inuse++; /* mark entry as in-use */ - - /* free the allocated entry_id */ - free(entry_id); - - return dns; -} - -/* - * Curl_resolv() is the main name resolve function within libcurl. It resolves - * a name and returns a pointer to the entry in the 'entry' argument (if one - * is provided). This function might return immediately if we're using asynch - * resolves. See the return codes. - * - * The cache entry we return will get its 'inuse' counter increased when this - * function is used. You MUST call Curl_resolv_unlock() later (when you're - * done using this struct) to decrease the counter again. - * - * In debug mode, we specifically test for an interface name "LocalHost" - * and resolve "localhost" instead as a means to permit test cases - * to connect to a local test server with any host name. - * - * Return codes: - * - * CURLRESOLV_ERROR (-1) = error, no pointer - * CURLRESOLV_RESOLVED (0) = OK, pointer provided - * CURLRESOLV_PENDING (1) = waiting for response, no pointer - */ - -int Curl_resolv(struct connectdata *conn, - const char *hostname, - int port, - struct Curl_dns_entry **entry) -{ - char *entry_id = NULL; - struct Curl_dns_entry *dns = NULL; - size_t entry_len; - struct SessionHandle *data = conn->data; - CURLcode result; - int rc = CURLRESOLV_ERROR; /* default to failure */ - - *entry = NULL; - - /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) - return rc; - - entry_len = strlen(entry_id); - - if(data->share) - Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - - /* See if its already in our dns cache */ - dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1); - - /* free the allocated entry_id again */ - free(entry_id); - - /* See whether the returned entry is stale. Done before we release lock */ - if( remove_entry_if_stale(data, dns) ) - dns = NULL; /* the memory deallocation is being handled by the hash */ - - if(dns) { - dns->inuse++; /* we use it! */ - rc = CURLRESOLV_RESOLVED; - } - - if(data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); - - if(!dns) { - /* The entry was not in the cache. Resolve it to IP address */ - - Curl_addrinfo *addr; - int respwait; - - /* Check what IP specifics the app has requested and if we can provide it. - * If not, bail out. */ - if(!Curl_ipvalid(conn)) - return CURLRESOLV_ERROR; - - /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a - non-zero value indicating that we need to wait for the response to the - resolve call */ - addr = Curl_getaddrinfo(conn, -#ifdef DEBUGBUILD - (data->set.str[STRING_DEVICE] - && !strcmp(data->set.str[STRING_DEVICE], - "LocalHost"))?"localhost": -#endif - hostname, port, &respwait); - - if(!addr) { - if(respwait) { - /* the response to our resolve call will come asynchronously at - a later time, good or bad */ - /* First, check that we haven't received the info by now */ - result = Curl_is_resolved(conn, &dns); - if(result) /* error detected */ - return CURLRESOLV_ERROR; - if(dns) - rc = CURLRESOLV_RESOLVED; /* pointer provided */ - else - rc = CURLRESOLV_PENDING; /* no info yet */ - } - } - else { - if(data->share) - Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - - /* we got a response, store it in the cache */ - dns = Curl_cache_addr(data, addr, hostname, port); - - if(data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); - - if(!dns) - /* returned failure, bail out nicely */ - Curl_freeaddrinfo(addr); - else - rc = CURLRESOLV_RESOLVED; - } - } - - *entry = dns; - - return rc; -} - -#ifdef USE_ALARM_TIMEOUT -/* - * This signal handler jumps back into the main libcurl code and continues - * execution. This effectively causes the remainder of the application to run - * within a signal handler which is nonportable and could lead to problems. - */ -static -RETSIGTYPE alarmfunc(int sig) -{ - /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */ - (void)sig; - siglongjmp(curl_jmpenv, 1); - return; -} -#endif /* USE_ALARM_TIMEOUT */ - -/* - * Curl_resolv_timeout() is the same as Curl_resolv() but specifies a - * timeout. This function might return immediately if we're using asynch - * resolves. See the return codes. - * - * The cache entry we return will get its 'inuse' counter increased when this - * function is used. You MUST call Curl_resolv_unlock() later (when you're - * done using this struct) to decrease the counter again. - * - * If built with a synchronous resolver and use of signals is not - * disabled by the application, then a nonzero timeout will cause a - * timeout after the specified number of milliseconds. Otherwise, timeout - * is ignored. - * - * Return codes: - * - * CURLRESOLV_TIMEDOUT(-2) = warning, time too short or previous alarm expired - * CURLRESOLV_ERROR (-1) = error, no pointer - * CURLRESOLV_RESOLVED (0) = OK, pointer provided - * CURLRESOLV_PENDING (1) = waiting for response, no pointer - */ - -int Curl_resolv_timeout(struct connectdata *conn, - const char *hostname, - int port, - struct Curl_dns_entry **entry, - long timeoutms) -{ -#ifdef USE_ALARM_TIMEOUT -#ifdef HAVE_SIGACTION - struct sigaction keep_sigact; /* store the old struct here */ - volatile bool keep_copysig = FALSE; /* wether old sigact has been saved */ - struct sigaction sigact; -#else -#ifdef HAVE_SIGNAL - void (*keep_sigact)(int); /* store the old handler here */ -#endif /* HAVE_SIGNAL */ -#endif /* HAVE_SIGACTION */ - volatile long timeout; - volatile unsigned int prev_alarm = 0; - struct SessionHandle *data = conn->data; -#endif /* USE_ALARM_TIMEOUT */ - int rc; - - *entry = NULL; - -#ifdef USE_ALARM_TIMEOUT - if (data->set.no_signal) - /* Ignore the timeout when signals are disabled */ - timeout = 0; - else - timeout = timeoutms; - - if(!timeout) - /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */ - return Curl_resolv(conn, hostname, port, entry); - - if(timeout < 1000) - /* The alarm() function only provides integer second resolution, so if - we want to wait less than one second we must bail out already now. */ - return CURLRESOLV_TIMEDOUT; - - /************************************************************* - * Set signal handler to catch SIGALRM - * Store the old value to be able to set it back later! - *************************************************************/ -#ifdef HAVE_SIGACTION - sigaction(SIGALRM, NULL, &sigact); - keep_sigact = sigact; - keep_copysig = TRUE; /* yes, we have a copy */ - sigact.sa_handler = alarmfunc; -#ifdef SA_RESTART - /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */ - sigact.sa_flags &= ~SA_RESTART; -#endif - /* now set the new struct */ - sigaction(SIGALRM, &sigact, NULL); -#else /* HAVE_SIGACTION */ - /* no sigaction(), revert to the much lamer signal() */ -#ifdef HAVE_SIGNAL - keep_sigact = signal(SIGALRM, alarmfunc); -#endif -#endif /* HAVE_SIGACTION */ - - /* alarm() makes a signal get sent when the timeout fires off, and that - will abort system calls */ - prev_alarm = alarm(curlx_sltoui(timeout/1000L)); - - /* This allows us to time-out from the name resolver, as the timeout - will generate a signal and we will siglongjmp() from that here. - This technique has problems (see alarmfunc). - This should be the last thing we do before calling Curl_resolv(), - as otherwise we'd have to worry about variables that get modified - before we invoke Curl_resolv() (and thus use "volatile"). */ - if(sigsetjmp(curl_jmpenv, 1)) { - /* this is coming from a siglongjmp() after an alarm signal */ - failf(data, "name lookup timed out"); - rc = CURLRESOLV_ERROR; - goto clean_up; - } - -#else -#ifndef CURLRES_ASYNCH - if(timeoutms) - infof(conn->data, "timeout on name lookup is not supported\n"); -#else - (void)timeoutms; /* timeoutms not used with an async resolver */ -#endif -#endif /* USE_ALARM_TIMEOUT */ - - /* Perform the actual name resolution. This might be interrupted by an - * alarm if it takes too long. - */ - rc = Curl_resolv(conn, hostname, port, entry); - -#ifdef USE_ALARM_TIMEOUT -clean_up: - - if(!prev_alarm) - /* deactivate a possibly active alarm before uninstalling the handler */ - alarm(0); - -#ifdef HAVE_SIGACTION - if(keep_copysig) { - /* we got a struct as it looked before, now put that one back nice - and clean */ - sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */ - } -#else -#ifdef HAVE_SIGNAL - /* restore the previous SIGALRM handler */ - signal(SIGALRM, keep_sigact); -#endif -#endif /* HAVE_SIGACTION */ - - /* switch back the alarm() to either zero or to what it was before minus - the time we spent until now! */ - if(prev_alarm) { - /* there was an alarm() set before us, now put it back */ - unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created); - - /* the alarm period is counted in even number of seconds */ - unsigned long alarm_set = prev_alarm - elapsed_ms/1000; - - if(!alarm_set || - ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) { - /* if the alarm time-left reached zero or turned "negative" (counted - with unsigned values), we should fire off a SIGALRM here, but we - won't, and zero would be to switch it off so we never set it to - less than 1! */ - alarm(1); - rc = CURLRESOLV_TIMEDOUT; - failf(data, "Previous alarm fired off!"); - } - else - alarm((unsigned int)alarm_set); - } -#endif /* USE_ALARM_TIMEOUT */ - - return rc; -} - -/* - * Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been - * made, the struct may be destroyed due to pruning. It is important that only - * one unlock is made for each Curl_resolv() call. - */ -void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns) -{ - DEBUGASSERT(dns && (dns->inuse>0)); - - if(data->share) - Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - - dns->inuse--; - /* only free if nobody is using AND it is not in hostcache (timestamp == - 0) */ - if (dns->inuse == 0 && dns->timestamp == 0) { - Curl_freeaddrinfo(dns->addr); - free(dns); - } - - if(data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); -} - -/* - * File-internal: free a cache dns entry. - */ -static void freednsentry(void *freethis) -{ - struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis; - - /* mark the entry as not in hostcache */ - p->timestamp = 0; - if (p->inuse == 0) { - Curl_freeaddrinfo(p->addr); - free(p); - } -} - -/* - * Curl_mk_dnscache() creates a new DNS cache and returns the handle for it. - */ -struct curl_hash *Curl_mk_dnscache(void) -{ - return Curl_hash_alloc(7, Curl_hash_str, Curl_str_key_compare, freednsentry); -} diff --git a/third_party/curl/lib/hostip.h b/third_party/curl/lib/hostip.h deleted file mode 100644 index a7c334568..000000000 --- a/third_party/curl/lib/hostip.h +++ /dev/null @@ -1,234 +0,0 @@ -#ifndef HEADER_CURL_HOSTIP_H -#define HEADER_CURL_HOSTIP_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" -#include "hash.h" -#include "curl_addrinfo.h" - -#ifdef HAVE_SETJMP_H -#include -#endif - -#ifdef NETWARE -#undef in_addr_t -#define in_addr_t unsigned long -#endif - -/* - * Comfortable CURLRES_* definitions are included from setup.h - */ - -#ifdef USE_ARES -#include -#endif - -/* Allocate enough memory to hold the full name information structs and - * everything. OSF1 is known to require at least 8872 bytes. The buffer - * required for storing all possible aliases and IP numbers is according to - * Stevens' Unix Network Programming 2nd edition, p. 304: 8192 bytes! - */ -#define CURL_HOSTENT_SIZE 9000 - -#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this - many seconds for a name resolve */ - -#ifdef CURLRES_ARES -#define CURL_ASYNC_SUCCESS ARES_SUCCESS -#if ARES_VERSION >= 0x010500 -/* c-ares 1.5.0 or later, the callback proto is modified */ -#define HAVE_CARES_CALLBACK_TIMEOUTS 1 -#endif -#else -#define CURL_ASYNC_SUCCESS CURLE_OK -#define ares_cancel(x) do {} while(0) -#define ares_destroy(x) do {} while(0) -#endif - -struct addrinfo; -struct hostent; -struct SessionHandle; -struct connectdata; - -#ifdef CURLRES_ASYNCH -void Curl_async_cancel(struct connectdata *conn); -#else -#define Curl_async_cancel(x) do {} while(0) -#endif - -/* - * Curl_global_host_cache_init() initializes and sets up a global DNS cache. - * Global DNS cache is general badness. Do not use. This will be removed in - * a future version. Use the share interface instead! - * - * Returns a struct curl_hash pointer on success, NULL on failure. - */ -struct curl_hash *Curl_global_host_cache_init(void); -void Curl_global_host_cache_dtor(void); - -struct Curl_dns_entry { - Curl_addrinfo *addr; - /* timestamp == 0 -- entry not in hostcache - timestamp != 0 -- entry is in hostcache */ - time_t timestamp; - long inuse; /* use-counter, make very sure you decrease this - when you're done using the address you received */ -}; - -/* - * Curl_resolv() returns an entry with the info for the specified host - * and port. - * - * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after - * use, or we'll leak memory! - */ -/* return codes */ -#define CURLRESOLV_TIMEDOUT -2 -#define CURLRESOLV_ERROR -1 -#define CURLRESOLV_RESOLVED 0 -#define CURLRESOLV_PENDING 1 -int Curl_resolv(struct connectdata *conn, const char *hostname, - int port, struct Curl_dns_entry **dnsentry); -int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, - int port, struct Curl_dns_entry **dnsentry, - long timeoutms); - -#ifdef CURLRES_IPV6 -/* - * Curl_ipv6works() returns TRUE if ipv6 seems to work. - */ -bool Curl_ipv6works(void); -#else -#define Curl_ipv6works() FALSE -#endif - -/* - * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've - * been set and returns TRUE if they are OK. - */ -bool Curl_ipvalid(struct connectdata *conn); - -/* - * Curl_getaddrinfo() is the generic low-level name resolve API within this - * source file. There are several versions of this function - for different - * name resolve layers (selected at build-time). They all take this same set - * of arguments - */ -Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, - const char *hostname, - int port, - int *waitp); - -CURLcode Curl_is_resolved(struct connectdata *conn, - struct Curl_dns_entry **dns); -CURLcode Curl_wait_for_resolv(struct connectdata *conn, - struct Curl_dns_entry **dnsentry); - -/* Curl_resolv_getsock() is a generic function that exists in multiple - versions depending on what name resolve technology we've built to use. The - function is called from the multi_getsock() function. 'sock' is a pointer - to an array to hold the file descriptors, with 'numsock' being the size of - that array (in number of entries). This function is supposed to return - bitmask indicating what file descriptors (referring to array indexes in the - 'sock' array) to wait for, read/write. */ -int Curl_resolv_getsock(struct connectdata *conn, curl_socket_t *sock, - int numsocks); - -/* unlock a previously resolved dns entry */ -void Curl_resolv_unlock(struct SessionHandle *data, - struct Curl_dns_entry *dns); - -/* for debugging purposes only: */ -void Curl_scan_cache_used(void *user, void *ptr); - -/* make a new dns cache and return the handle */ -struct curl_hash *Curl_mk_dnscache(void); - -/* prune old entries from the DNS cache */ -void Curl_hostcache_prune(struct SessionHandle *data); - -/* Return # of adresses in a Curl_addrinfo struct */ -int Curl_num_addresses (const Curl_addrinfo *addr); - -#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) -int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, - GETNAMEINFO_TYPE_ARG2 salen, - char *host, GETNAMEINFO_TYPE_ARG46 hostlen, - char *serv, GETNAMEINFO_TYPE_ARG46 servlen, - GETNAMEINFO_TYPE_ARG7 flags, - int line, const char *source); -#endif - -/* IPv4 threadsafe resolve function used for synch and asynch builds */ -Curl_addrinfo *Curl_ipv4_resolve_r(const char * hostname, int port); - -/* - * Curl_addrinfo_callback() is used when we build with any asynch specialty. - * Handles end of async request processing. Inserts ai into hostcache when - * status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async - * request completed wether successful or failed. - */ -CURLcode Curl_addrinfo_callback(struct connectdata *conn, - int status, - Curl_addrinfo *ai); - -/* - * Curl_printable_address() returns a printable version of the 1st address - * given in the 'ip' argument. The result will be stored in the buf that is - * bufsize bytes big. - */ -const char *Curl_printable_address(const Curl_addrinfo *ip, - char *buf, size_t bufsize); - -/* - * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. - * - * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. - */ -struct Curl_dns_entry * -Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr, - const char *hostname, int port); - -/* - * Curl_destroy_thread_data() cleans up async resolver data. - * Complementary of ares_destroy. - */ -struct Curl_async; /* forward-declaration */ -void Curl_destroy_thread_data(struct Curl_async *async); - -#ifndef INADDR_NONE -#define CURL_INADDR_NONE (in_addr_t) ~0 -#else -#define CURL_INADDR_NONE INADDR_NONE -#endif - -#ifdef HAVE_SIGSETJMP -/* Forward-declaration of variable defined in hostip.c. Beware this - * is a global and unique instance. This is used to store the return - * address that we can jump back to from inside a signal handler. - * This is not thread-safe stuff. - */ -extern sigjmp_buf curl_jmpenv; -#endif - -#endif /* HEADER_CURL_HOSTIP_H */ diff --git a/third_party/curl/lib/hostip4.c b/third_party/curl/lib/hostip4.c deleted file mode 100644 index 6dc525765..000000000 --- a/third_party/curl/lib/hostip4.c +++ /dev/null @@ -1,319 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include /* required for free() prototypes */ -#endif -#ifdef HAVE_UNISTD_H -#include /* for the close() proto */ -#endif -#ifdef __VMS -#include -#include -#include -#endif - -#ifdef HAVE_PROCESS_H -#include -#endif - -#include "urldata.h" -#include "sendf.h" -#include "hostip.h" -#include "hash.h" -#include "share.h" -#include "strerror.h" -#include "url.h" -#include "inet_pton.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/*********************************************************************** - * Only for plain-ipv4 builds - **********************************************************************/ -#ifdef CURLRES_IPV4 /* plain ipv4 code coming up */ -/* - * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've - * been set and returns TRUE if they are OK. - */ -bool Curl_ipvalid(struct connectdata *conn) -{ - if(conn->ip_version == CURL_IPRESOLVE_V6) - /* an ipv6 address was requested and we can't get/use one */ - return FALSE; - - return TRUE; /* OK, proceed */ -} - -#ifdef CURLRES_SYNCH -/* - * Curl_getaddrinfo() - the ipv4 synchronous version. - * - * The original code to this function was from the Dancer source code, written - * by Bjorn Reese, it has since been patched and modified considerably. - * - * gethostbyname_r() is the thread-safe version of the gethostbyname() - * function. When we build for plain IPv4, we attempt to use this - * function. There are _three_ different gethostbyname_r() versions, and we - * detect which one this platform supports in the configure script and set up - * the HAVE_GETHOSTBYNAME_R_3, HAVE_GETHOSTBYNAME_R_5 or - * HAVE_GETHOSTBYNAME_R_6 defines accordingly. Note that HAVE_GETADDRBYNAME - * has the corresponding rules. This is primarily on *nix. Note that some unix - * flavours have thread-safe versions of the plain gethostbyname() etc. - * - */ -Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, - const char *hostname, - int port, - int *waitp) -{ - Curl_addrinfo *ai = NULL; - -#ifdef CURL_DISABLE_VERBOSE_STRINGS - (void)conn; -#endif - - *waitp = 0; /* synchronous response only */ - - ai = Curl_ipv4_resolve_r(hostname, port); - if(!ai) - infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n", hostname); - - return ai; -} -#endif /* CURLRES_SYNCH */ -#endif /* CURLRES_IPV4 */ - -/* - * Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function. - * - * This is used for both synchronous and asynchronous resolver builds, - * implying that only threadsafe code and function calls may be used. - * - */ -Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, - int port) -{ -#if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3) - int res; -#endif - Curl_addrinfo *ai = NULL; - struct hostent *h = NULL; - struct in_addr in; - struct hostent *buf = NULL; - - if(Curl_inet_pton(AF_INET, hostname, &in) > 0) - /* This is a dotted IP address 123.123.123.123-style */ - return Curl_ip2addr(AF_INET, &in, hostname, port); - -#if defined(HAVE_GETADDRINFO_THREADSAFE) - else { - struct addrinfo hints; - char sbuf[NI_MAXSERV]; - char *sbufptr = NULL; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_INET; - hints.ai_socktype = SOCK_STREAM; - if(port) { - snprintf(sbuf, sizeof(sbuf), "%d", port); - sbufptr = sbuf; - } - - (void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai); - -#elif defined(HAVE_GETHOSTBYNAME_R) - /* - * gethostbyname_r() is the preferred resolve function for many platforms. - * Since there are three different versions of it, the following code is - * somewhat #ifdef-ridden. - */ - else { - int h_errnop; - - buf = calloc(1, CURL_HOSTENT_SIZE); - if(!buf) - return NULL; /* major failure */ - /* - * The clearing of the buffer is a workaround for a gethostbyname_r bug in - * qnx nto and it is also _required_ for some of these functions on some - * platforms. - */ - -#if defined(HAVE_GETHOSTBYNAME_R_5) - /* Solaris, IRIX and more */ - h = gethostbyname_r(hostname, - (struct hostent *)buf, - (char *)buf + sizeof(struct hostent), - CURL_HOSTENT_SIZE - sizeof(struct hostent), - &h_errnop); - - /* If the buffer is too small, it returns NULL and sets errno to - * ERANGE. The errno is thread safe if this is compiled with - * -D_REENTRANT as then the 'errno' variable is a macro defined to get - * used properly for threads. - */ - - if(h) { - ; - } - else -#elif defined(HAVE_GETHOSTBYNAME_R_6) - /* Linux */ - - (void)gethostbyname_r(hostname, - (struct hostent *)buf, - (char *)buf + sizeof(struct hostent), - CURL_HOSTENT_SIZE - sizeof(struct hostent), - &h, /* DIFFERENCE */ - &h_errnop); - /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a - * sudden this function returns EAGAIN if the given buffer size is too - * small. Previous versions are known to return ERANGE for the same - * problem. - * - * This wouldn't be such a big problem if older versions wouldn't - * sometimes return EAGAIN on a common failure case. Alas, we can't - * assume that EAGAIN *or* ERANGE means ERANGE for any given version of - * glibc. - * - * For now, we do that and thus we may call the function repeatedly and - * fail for older glibc versions that return EAGAIN, until we run out of - * buffer size (step_size grows beyond CURL_HOSTENT_SIZE). - * - * If anyone has a better fix, please tell us! - * - * ------------------------------------------------------------------- - * - * On October 23rd 2003, Dan C dug up more details on the mysteries of - * gethostbyname_r() in glibc: - * - * In glibc 2.2.5 the interface is different (this has also been - * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't - * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32 - * (shipped/upgraded by Redhat 7.2) don't show this behavior! - * - * In this "buggy" version, the return code is -1 on error and 'errno' - * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a - * thread-safe variable. - */ - - if(!h) /* failure */ -#elif defined(HAVE_GETHOSTBYNAME_R_3) - /* AIX, Digital Unix/Tru64, HPUX 10, more? */ - - /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of - * the plain fact that it does not return unique full buffers on each - * call, but instead several of the pointers in the hostent structs will - * point to the same actual data! This have the unfortunate down-side that - * our caching system breaks down horribly. Luckily for us though, AIX 4.3 - * and more recent versions have a "completely thread-safe"[*] libc where - * all the data is stored in thread-specific memory areas making calls to - * the plain old gethostbyname() work fine even for multi-threaded - * programs. - * - * This AIX 4.3 or later detection is all made in the configure script. - * - * Troels Walsted Hansen helped us work this out on March 3rd, 2003. - * - * [*] = much later we've found out that it isn't at all "completely - * thread-safe", but at least the gethostbyname() function is. - */ - - if(CURL_HOSTENT_SIZE >= - (sizeof(struct hostent)+sizeof(struct hostent_data))) { - - /* August 22nd, 2000: Albert Chin-A-Young brought an updated version - * that should work! September 20: Richard Prescott worked on the buffer - * size dilemma. - */ - - res = gethostbyname_r(hostname, - (struct hostent *)buf, - (struct hostent_data *)((char *)buf + - sizeof(struct hostent))); - h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */ - } - else - res = -1; /* failure, too smallish buffer size */ - - if(!res) { /* success */ - - h = buf; /* result expected in h */ - - /* This is the worst kind of the different gethostbyname_r() interfaces. - * Since we don't know how big buffer this particular lookup required, - * we can't realloc down the huge alloc without doing closer analysis of - * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every - * name lookup. Fixing this would require an extra malloc() and then - * calling Curl_addrinfo_copy() that subsequent realloc()s down the new - * memory area to the actually used amount. - */ - } - else -#endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */ - { - h = NULL; /* set return code to NULL */ - free(buf); - } -#else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ - /* - * Here is code for platforms that don't have a thread safe - * getaddrinfo() nor gethostbyname_r() function or for which - * gethostbyname() is the preferred one. - */ - else { - h = gethostbyname((void*)hostname); -#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ - } - - if(h) { - ai = Curl_he2ai(h, port); - - if(buf) /* used a *_r() function */ - free(buf); - } - - return ai; -} diff --git a/third_party/curl/lib/hostip6.c b/third_party/curl/lib/hostip6.c deleted file mode 100644 index 61cc0d9a1..000000000 --- a/third_party/curl/lib/hostip6.c +++ /dev/null @@ -1,235 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include /* required for free() prototypes */ -#endif -#ifdef HAVE_UNISTD_H -#include /* for the close() proto */ -#endif -#ifdef __VMS -#include -#include -#include -#endif - -#ifdef HAVE_PROCESS_H -#include -#endif - -#include "urldata.h" -#include "sendf.h" -#include "hostip.h" -#include "hash.h" -#include "share.h" -#include "strerror.h" -#include "url.h" -#include "inet_pton.h" -#include "connect.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/*********************************************************************** - * Only for ipv6-enabled builds - **********************************************************************/ -#ifdef CURLRES_IPV6 - - -#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) -/* These are strictly for memory tracing and are using the same style as the - * family otherwise present in memdebug.c. I put these ones here since they - * require a bunch of structs I didn't want to include in memdebug.c - */ - -/* - * For CURLRES_ARS, this should be written using ares_gethostbyaddr() - * (ignoring the fact c-ares doesn't return 'serv'). - */ - -int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, - GETNAMEINFO_TYPE_ARG2 salen, - char *host, GETNAMEINFO_TYPE_ARG46 hostlen, - char *serv, GETNAMEINFO_TYPE_ARG46 servlen, - GETNAMEINFO_TYPE_ARG7 flags, - int line, const char *source) -{ - int res = (getnameinfo)(sa, salen, - host, hostlen, - serv, servlen, - flags); - if(0 == res) - /* success */ - curl_memlog("GETNAME %s:%d getnameinfo()\n", - source, line); - else - curl_memlog("GETNAME %s:%d getnameinfo() failed = %d\n", - source, line, res); - return res; -} -#endif /* defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) */ - -/* - * Curl_ipv6works() returns TRUE if ipv6 seems to work. - */ -bool Curl_ipv6works(void) -{ - /* the nature of most system is that IPv6 status doesn't come and go - during a program's lifetime so we only probe the first time and then we - have the info kept for fast re-use */ - static int ipv6_works = -1; - if(-1 == ipv6_works) { - /* probe to see if we have a working IPv6 stack */ - curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0); - if(s == CURL_SOCKET_BAD) - /* an ipv6 address was requested but we can't get/use one */ - ipv6_works = 0; - else { - ipv6_works = 1; - sclose(s); - } - } - return (ipv6_works>0)?TRUE:FALSE; -} - -/* - * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've - * been set and returns TRUE if they are OK. - */ -bool Curl_ipvalid(struct connectdata *conn) -{ - if(conn->ip_version == CURL_IPRESOLVE_V6) - return Curl_ipv6works(); - return TRUE; -} - -#if defined(CURLRES_SYNCH) - -#ifdef DEBUG_ADDRINFO -static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai) -{ - printf("dump_addrinfo:\n"); - for ( ; ai; ai = ai->ai_next) { - char buf[INET6_ADDRSTRLEN]; - - printf(" fam %2d, CNAME %s, ", - ai->ai_family, ai->ai_canonname ? ai->ai_canonname : ""); - if(Curl_printable_address(ai, buf, sizeof(buf))) - printf("%s\n", buf); - else - printf("failed; %s\n", Curl_strerror(conn, SOCKERRNO)); - } -} -#else -#define dump_addrinfo(x,y) -#endif - -/* - * Curl_getaddrinfo() when built ipv6-enabled (non-threading and - * non-ares version). - * - * Returns name information about the given hostname and port number. If - * successful, the 'addrinfo' is returned and the forth argument will point to - * memory we need to free after use. That memory *MUST* be freed with - * Curl_freeaddrinfo(), nothing else. - */ -Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, - const char *hostname, - int port, - int *waitp) -{ - struct addrinfo hints; - Curl_addrinfo *res; - int error; - char sbuf[NI_MAXSERV]; - char *sbufptr = NULL; - char addrbuf[128]; - int pf; - struct SessionHandle *data = conn->data; - - *waitp = 0; /* synchronous response only */ - - /* - * Check if a limited name resolve has been requested. - */ - switch(conn->ip_version) { - case CURL_IPRESOLVE_V4: - pf = PF_INET; - break; - case CURL_IPRESOLVE_V6: - pf = PF_INET6; - break; - default: - pf = PF_UNSPEC; - break; - } - - if((pf != PF_INET) && !Curl_ipv6works()) - /* the stack seems to be a non-ipv6 one */ - pf = PF_INET; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = pf; - hints.ai_socktype = conn->socktype; - - if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) || - (1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) { - /* the given address is numerical only, prevent a reverse lookup */ - hints.ai_flags = AI_NUMERICHOST; - } - - if(port) { - snprintf(sbuf, sizeof(sbuf), "%d", port); - sbufptr=sbuf; - } - error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res); - if(error) { - infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port); - return NULL; - } - - dump_addrinfo(conn, res); - - return res; -} -#endif /* CURLRES_SYNCH */ -#endif /* CURLRES_IPV6 */ diff --git a/third_party/curl/lib/hostsyn.c b/third_party/curl/lib/hostsyn.c deleted file mode 100644 index b68e4702e..000000000 --- a/third_party/curl/lib/hostsyn.c +++ /dev/null @@ -1,123 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include /* required for free() prototypes */ -#endif -#ifdef HAVE_UNISTD_H -#include /* for the close() proto */ -#endif -#ifdef __VMS -#include -#include -#include -#endif - -#ifdef HAVE_PROCESS_H -#include -#endif - -#include "urldata.h" -#include "sendf.h" -#include "hostip.h" -#include "hash.h" -#include "share.h" -#include "strerror.h" -#include "url.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/*********************************************************************** - * Only for builds using synchronous name resolves - **********************************************************************/ -#ifdef CURLRES_SYNCH - -/* - * Curl_wait_for_resolv() for synch-builds. Curl_resolv() can never return - * wait==TRUE, so this function will never be called. If it still gets called, - * we return failure at once. - * - * We provide this function only to allow multi.c to remain unaware if we are - * doing asynch resolves or not. - */ -CURLcode Curl_wait_for_resolv(struct connectdata *conn, - struct Curl_dns_entry **entry) -{ - (void)conn; - *entry=NULL; - return CURLE_COULDNT_RESOLVE_HOST; -} - -/* - * This function will never be called when synch-built. If it still gets - * called, we return failure at once. - * - * We provide this function only to allow multi.c to remain unaware if we are - * doing asynch resolves or not. - */ -CURLcode Curl_is_resolved(struct connectdata *conn, - struct Curl_dns_entry **dns) -{ - (void)conn; - *dns = NULL; - - return CURLE_COULDNT_RESOLVE_HOST; -} - -/* - * We just return OK, this function is never actually used for synch builds. - * It is present here to keep #ifdefs out from multi.c - */ - -int Curl_resolv_getsock(struct connectdata *conn, - curl_socket_t *sock, - int numsocks) -{ - (void)conn; - (void)sock; - (void)numsocks; - - return 0; /* no bits since we don't use any socks */ -} - -#endif /* truly sync */ diff --git a/third_party/curl/lib/hostthre.c b/third_party/curl/lib/hostthre.c deleted file mode 100644 index dc8e4af74..000000000 --- a/third_party/curl/lib/hostthre.c +++ /dev/null @@ -1,566 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include /* required for free() prototypes */ -#endif -#ifdef HAVE_UNISTD_H -#include /* for the close() proto */ -#endif -#ifdef __VMS -#include -#include -#include -#endif - -#if defined(USE_THREADS_POSIX) -# ifdef HAVE_PTHREAD_H -# include -# endif -#elif defined(USE_THREADS_WIN32) -# ifdef HAVE_PROCESS_H -# include -# endif -#endif - -#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) -#undef in_addr_t -#define in_addr_t unsigned long -#endif - -#include "urldata.h" -#include "sendf.h" -#include "hostip.h" -#include "hash.h" -#include "share.h" -#include "strerror.h" -#include "url.h" -#include "multiif.h" -#include "inet_pton.h" -#include "inet_ntop.h" -#include "curl_threads.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/*********************************************************************** - * Only for threaded name resolves builds - **********************************************************************/ -#ifdef CURLRES_THREADED - -/* This function is used to init a threaded resolve */ -static bool init_resolve_thread(struct connectdata *conn, - const char *hostname, int port, - const struct addrinfo *hints); - - -/* Data for synchronization between resolver thread and its parent */ -struct thread_sync_data { - curl_mutex_t * mtx; - int done; - - char * hostname; /* hostname to resolve, Curl_async.hostname - duplicate */ - int port; - int sock_error; - Curl_addrinfo *res; -#ifdef HAVE_GETADDRINFO - struct addrinfo hints; -#endif -}; - -struct thread_data { - curl_thread_t thread_hnd; - curl_socket_t dummy_sock; - unsigned int poll_interval; - int interval_end; - struct thread_sync_data tsd; -}; - -static struct thread_sync_data * conn_thread_sync_data(struct connectdata *conn) -{ - return &(((struct thread_data *)conn->async.os_specific)->tsd); -} - -#define CONN_THREAD_SYNC_DATA(conn) &(((conn)->async.os_specific)->tsd); - -/* Destroy resolver thread synchronization data */ -static -void destroy_thread_sync_data(struct thread_sync_data * tsd) -{ - if (tsd->mtx) { - Curl_mutex_destroy(tsd->mtx); - free(tsd->mtx); - } - - if(tsd->hostname) - free(tsd->hostname); - - if (tsd->res) - Curl_freeaddrinfo(tsd->res); - - memset(tsd,0,sizeof(*tsd)); -} - -/* Initialize resolver thread synchronization data */ -static -int init_thread_sync_data(struct thread_sync_data * tsd, - const char * hostname, - int port, - const struct addrinfo *hints) -{ - memset(tsd, 0, sizeof(*tsd)); - - tsd->port = port; -#ifdef CURLRES_IPV6 - DEBUGASSERT(hints); - tsd->hints = *hints; -#else - (void) hints; -#endif - - tsd->mtx = malloc(sizeof(curl_mutex_t)); - if (tsd->mtx == NULL) goto err_exit; - - Curl_mutex_init(tsd->mtx); - - tsd->sock_error = CURL_ASYNC_SUCCESS; - - /* Copying hostname string because original can be destroyed by parent - * thread during gethostbyname execution. - */ - tsd->hostname = strdup(hostname); - if (!tsd->hostname) goto err_exit; - - return 1; - - err_exit: - /* Memory allocation failed */ - destroy_thread_sync_data(tsd); - return 0; -} - -static int getaddrinfo_complete(struct connectdata *conn) -{ - struct thread_sync_data *tsd = conn_thread_sync_data(conn); - int rc; - - rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res); - /* The tsd->res structure has been copied to async.dns and perhaps the DNS cache. - Set our copy to NULL so destroy_thread_sync_data doesn't free it. - */ - tsd->res = NULL; - - return rc; -} - - -#ifdef HAVE_GETADDRINFO - -/* - * getaddrinfo_thread() resolves a name and then exits. - * - * For builds without ARES, but with ENABLE_IPV6, create a resolver thread - * and wait on it. - */ -static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg) -{ - struct thread_sync_data *tsd = (struct thread_sync_data*)arg; - char service [NI_MAXSERV]; - int rc; - - snprintf(service, sizeof(service), "%d", tsd->port); - - rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res); - - if (rc != 0) { - tsd->sock_error = SOCKERRNO; - if (tsd->sock_error == 0) - tsd->sock_error = ENOMEM; - } - - Curl_mutex_acquire(tsd->mtx); - tsd->done = 1; - Curl_mutex_release(tsd->mtx); - - return 0; -} - -#else /* HAVE_GETADDRINFO */ - -/* - * gethostbyname_thread() resolves a name and then exits. - */ -static unsigned int CURL_STDCALL gethostbyname_thread (void *arg) -{ - struct thread_sync_data *tsd = (struct thread_sync_data *)arg; - - tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port); - - if (!tsd->res) { - tsd->sock_error = SOCKERRNO; - if (tsd->sock_error == 0) - tsd->sock_error = ENOMEM; - } - - Curl_mutex_acquire(tsd->mtx); - tsd->done = 1; - Curl_mutex_release(tsd->mtx); - - return 0; -} - -#endif /* HAVE_GETADDRINFO */ - -/* - * Curl_destroy_thread_data() cleans up async resolver data and thread handle. - * Complementary of ares_destroy. - */ -void Curl_destroy_thread_data (struct Curl_async *async) -{ - if(async->hostname) - free(async->hostname); - - if(async->os_specific) { - struct thread_data *td = (struct thread_data*) async->os_specific; - - if (td->dummy_sock != CURL_SOCKET_BAD) - sclose(td->dummy_sock); - - if (td->thread_hnd != curl_thread_t_null) - Curl_thread_join(&td->thread_hnd); - - destroy_thread_sync_data(&td->tsd); - - free(async->os_specific); - } - async->hostname = NULL; - async->os_specific = NULL; -} - -/* - * init_resolve_thread() starts a new thread that performs the actual - * resolve. This function returns before the resolve is done. - * - * Returns FALSE in case of failure, otherwise TRUE. - */ -static bool init_resolve_thread (struct connectdata *conn, - const char *hostname, int port, - const struct addrinfo *hints) -{ - struct thread_data *td = calloc(1, sizeof(struct thread_data)); - int err = ENOMEM; - - conn->async.os_specific = (void*) td; - if(!td) - goto err_exit; - - conn->async.port = port; - conn->async.done = FALSE; - conn->async.status = 0; - conn->async.dns = NULL; - td->dummy_sock = CURL_SOCKET_BAD; - td->thread_hnd = curl_thread_t_null; - - if (!init_thread_sync_data(&td->tsd, hostname, port, hints)) - goto err_exit; - - Curl_safefree(conn->async.hostname); - conn->async.hostname = strdup(hostname); - if(!conn->async.hostname) - goto err_exit; - -#ifdef WIN32 - /* This socket is only to keep Curl_resolv_fdset() and select() happy; - * should never become signalled for read since it's unbound but - * Windows needs at least 1 socket in select(). - */ - td->dummy_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (td->dummy_sock == CURL_SOCKET_BAD) - goto err_exit; -#endif - -#ifdef HAVE_GETADDRINFO - td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd); -#else - td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd); -#endif - - if(!td->thread_hnd) { -#ifndef _WIN32_WCE - err = errno; -#endif - goto err_exit; - } - - return TRUE; - - err_exit: - Curl_destroy_thread_data(&conn->async); - - SET_ERRNO(err); - - return FALSE; -} - - -/* - * Curl_wait_for_resolv() waits for a resolve to finish. This function should - * be avoided since using this risk getting the multi interface to "hang". - * - * If 'entry' is non-NULL, make it point to the resolved dns entry - * - * This is the version for resolves-in-a-thread. - */ -CURLcode Curl_wait_for_resolv(struct connectdata *conn, - struct Curl_dns_entry **entry) -{ - struct thread_data *td = (struct thread_data*) conn->async.os_specific; - struct SessionHandle *data = conn->data; - CURLcode rc = CURLE_OK; - - DEBUGASSERT(conn && td); - - /* wait for the thread to resolve the name */ - if (Curl_thread_join(&td->thread_hnd)) { - rc = getaddrinfo_complete(conn); - } else { - DEBUGASSERT(0); - } - - conn->async.done = TRUE; - - if(entry) - *entry = conn->async.dns; - - if(!conn->async.dns) { - /* a name was not resolved */ - if (conn->bits.httpproxy) { - failf(data, "Could not resolve proxy: %s; %s", - conn->async.hostname, Curl_strerror(conn, conn->async.status)); - rc = CURLE_COULDNT_RESOLVE_PROXY; - } else { - failf(data, "Could not resolve host: %s; %s", - conn->async.hostname, Curl_strerror(conn, conn->async.status)); - rc = CURLE_COULDNT_RESOLVE_HOST; - } - } - - Curl_destroy_thread_data(&conn->async); - - if(!conn->async.dns) - conn->bits.close = TRUE; - - return (rc); -} - -/* - * Curl_is_resolved() is called repeatedly to check if a previous name resolve - * request has completed. It should also make sure to time-out if the - * operation seems to take too long. - */ -CURLcode Curl_is_resolved(struct connectdata *conn, - struct Curl_dns_entry **entry) -{ - struct SessionHandle *data = conn->data; - struct thread_data *td = (struct thread_data*) conn->async.os_specific; - int done = 0; - - *entry = NULL; - - if (!td) { - DEBUGASSERT(td); - return CURLE_COULDNT_RESOLVE_HOST; - } - - Curl_mutex_acquire(td->tsd.mtx); - done = td->tsd.done; - Curl_mutex_release(td->tsd.mtx); - - if (done) { - getaddrinfo_complete(conn); - Curl_destroy_thread_data(&conn->async); - - if(!conn->async.dns) { - failf(data, "Could not resolve host: %s; %s", - conn->host.name, Curl_strerror(conn, conn->async.status)); - return CURLE_COULDNT_RESOLVE_HOST; - } - *entry = conn->async.dns; - } else { - /* poll for name lookup done with exponential backoff up to 250ms */ - int elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle); - if (elapsed < 0) - elapsed = 0; - - if (td->poll_interval == 0) - /* Start at 1ms poll interval */ - td->poll_interval = 1; - else if (elapsed >= td->interval_end) - /* Back-off exponentially if last interval expired */ - td->poll_interval *= 2; - - if (td->poll_interval > 250) - td->poll_interval = 250; - - td->interval_end = elapsed + td->poll_interval; - Curl_expire(conn->data, td->poll_interval); - } - - return CURLE_OK; -} - -int Curl_resolv_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - const struct thread_data *td = - (const struct thread_data *) conn->async.os_specific; - - if(td && td->dummy_sock != CURL_SOCKET_BAD) { - if(numsocks) { - /* return one socket waiting for readable, even though this is just - a dummy */ - socks[0] = td->dummy_sock; - return GETSOCK_READSOCK(0); - } - } - return 0; -} - -#ifndef HAVE_GETADDRINFO -/* - * Curl_getaddrinfo() - for platforms without getaddrinfo - */ -Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, - const char *hostname, - int port, - int *waitp) -{ - struct in_addr in; - - *waitp = 0; /* default to synchronous response */ - - if(Curl_inet_pton(AF_INET, hostname, &in) > 0) - /* This is a dotted IP address 123.123.123.123-style */ - return Curl_ip2addr(AF_INET, &in, hostname, port); - - /* fire up a new resolver thread! */ - if(init_resolve_thread(conn, hostname, port, NULL)) { - *waitp = 1; /* expect asynchronous response */ - return NULL; - } - - /* fall-back to blocking version */ - return Curl_ipv4_resolve_r(hostname, port); -} - -#else /* !HAVE_GETADDRINFO */ - -/* - * Curl_getaddrinfo() - for getaddrinfo - */ -Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, - const char *hostname, - int port, - int *waitp) -{ - struct addrinfo hints; - Curl_addrinfo *res; - int error; - char sbuf[NI_MAXSERV]; - int pf = PF_INET; - struct SessionHandle *data = conn->data; - - *waitp = 0; /* default to synchronous response */ - -#ifndef CURLRES_IPV4 - /* - * Check if a limited name resolve has been requested. - */ - switch(conn->ip_version) { - case CURL_IPRESOLVE_V4: - pf = PF_INET; - break; - case CURL_IPRESOLVE_V6: - pf = PF_INET6; - break; - default: - pf = PF_UNSPEC; - break; - } - - if((pf != PF_INET) && !Curl_ipv6works()) - /* the stack seems to be a non-ipv6 one */ - pf = PF_INET; - -#endif /* !CURLRES_IPV4 */ - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = pf; - hints.ai_socktype = conn->socktype; - - snprintf(sbuf, sizeof(sbuf), "%d", port); - - /* fire up a new resolver thread! */ - if(init_resolve_thread(conn, hostname, port, &hints)) { - *waitp = 1; /* expect asynchronous response */ - return NULL; - } - - /* fall-back to blocking version */ - infof(data, "init_resolve_thread() failed for %s; %s\n", - hostname, Curl_strerror(conn, ERRNO)); - - error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res); - if(error) { - infof(data, "getaddrinfo() failed for %s:%d; %s\n", - hostname, port, Curl_strerror(conn, SOCKERRNO)); - return NULL; - } - return res; -} - -#endif /* !HAVE_GETADDRINFO */ - -#endif /* CURLRES_THREADED */ diff --git a/third_party/curl/lib/http.c b/third_party/curl/lib/http.c deleted file mode 100644 index 1e463ee69..000000000 --- a/third_party/curl/lib/http.c +++ /dev/null @@ -1,3365 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef CURL_DISABLE_HTTP -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#include -#else -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#ifdef HAVE_TIME_H -#ifdef TIME_WITH_SYS_TIME -#include -#endif -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#endif - -#include "urldata.h" -#include -#include "transfer.h" -#include "sendf.h" -#include "formdata.h" -#include "progress.h" -#include "curl_base64.h" -#include "cookie.h" -#include "strequal.h" -#include "sslgen.h" -#include "http_digest.h" -#include "http_ntlm.h" -#include "http_negotiate.h" -#include "url.h" -#include "share.h" -#include "hostip.h" -#include "http.h" -#include "curl_memory.h" -#include "select.h" -#include "parsedate.h" /* for the week day and month names */ -#include "strtoofft.h" -#include "multiif.h" -#include "rawstr.h" -#include "content_encoding.h" -#include "rtsp.h" -#include "http_proxy.h" -#include "warnless.h" -#include "non-ascii.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -/* - * Forward declarations. - */ - -static int http_getsock_do(struct connectdata *conn, - curl_socket_t *socks, - int numsocks); -#ifdef USE_SSL -static CURLcode https_connecting(struct connectdata *conn, bool *done); -static int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks); -#else -#define https_connecting(x,y) CURLE_COULDNT_CONNECT -#endif - -/* - * HTTP handler interface. - */ -const struct Curl_handler Curl_handler_http = { - "HTTP", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - Curl_http_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - http_getsock_do, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_HTTP, /* defport */ - CURLPROTO_HTTP, /* protocol */ - PROTOPT_NONE /* flags */ -}; - -#ifdef USE_SSL -/* - * HTTPS handler interface. - */ -const struct Curl_handler Curl_handler_https = { - "HTTPS", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - Curl_http_connect, /* connect_it */ - https_connecting, /* connecting */ - ZERO_NULL, /* doing */ - https_getsock, /* proto_getsock */ - http_getsock_do, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_HTTPS, /* defport */ - CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */ - PROTOPT_SSL /* flags */ -}; -#endif - - -/* - * checkheaders() checks the linked list of custom HTTP headers for a - * particular header (prefix). - * - * Returns a pointer to the first matching header or NULL if none matched. - */ -char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader) -{ - struct curl_slist *head; - size_t thislen = strlen(thisheader); - - for(head = data->set.headers; head; head=head->next) { - if(Curl_raw_nequal(head->data, thisheader, thislen)) - return head->data; - } - return NULL; -} - -/* - * Strip off leading and trailing whitespace from the value in the - * given HTTP header line and return a strdupped copy. Returns NULL in - * case of allocation failure. Returns an empty string if the header value - * consists entirely of whitespace. - */ -char *Curl_copy_header_value(const char *h) -{ - const char *start; - const char *end; - char *value; - size_t len; - - DEBUGASSERT(h); - - /* Find the end of the header name */ - while (*h && (*h != ':')) - ++h; - - if (*h) - /* Skip over colon */ - ++h; - - /* Find the first non-space letter */ - start = h; - while(*start && ISSPACE(*start)) - start++; - - /* data is in the host encoding so - use '\r' and '\n' instead of 0x0d and 0x0a */ - end = strchr(start, '\r'); - if(!end) - end = strchr(start, '\n'); - if(!end) - end = strchr(start, '\0'); - if(!end) - return NULL; - - /* skip all trailing space letters */ - while((end > start) && ISSPACE(*end)) - end--; - - /* get length of the type */ - len = end-start+1; - - value = malloc(len + 1); - if(!value) - return NULL; - - memcpy(value, start, len); - value[len] = 0; /* zero terminate */ - - return value; -} - -/* - * http_output_basic() sets up an Authorization: header (or the proxy version) - * for HTTP Basic authentication. - * - * Returns CURLcode. - */ -static CURLcode http_output_basic(struct connectdata *conn, bool proxy) -{ - char *authorization; - struct SessionHandle *data=conn->data; - char **userp; - const char *user; - const char *pwd; - - if(proxy) { - userp = &conn->allocptr.proxyuserpwd; - user = conn->proxyuser; - pwd = conn->proxypasswd; - } - else { - userp = &conn->allocptr.userpwd; - user = conn->user; - pwd = conn->passwd; - } - - snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd); - if(Curl_base64_encode(data, data->state.buffer, - strlen(data->state.buffer), - &authorization) > 0) { - if(*userp) - free(*userp); - *userp = aprintf( "%sAuthorization: Basic %s\r\n", - proxy?"Proxy-":"", - authorization); - free(authorization); - if(!*userp) - return CURLE_OUT_OF_MEMORY; - } - else - return CURLE_OUT_OF_MEMORY; - return CURLE_OK; -} - -/* pickoneauth() selects the most favourable authentication method from the - * ones available and the ones we want. - * - * return TRUE if one was picked - */ -static bool pickoneauth(struct auth *pick) -{ - bool picked; - /* only deal with authentication we want */ - long avail = pick->avail & pick->want; - picked = TRUE; - - /* The order of these checks is highly relevant, as this will be the order - of preference in case of the existence of multiple accepted types. */ - if(avail & CURLAUTH_GSSNEGOTIATE) - pick->picked = CURLAUTH_GSSNEGOTIATE; - else if(avail & CURLAUTH_DIGEST) - pick->picked = CURLAUTH_DIGEST; - else if(avail & CURLAUTH_NTLM) - pick->picked = CURLAUTH_NTLM; - else if(avail & CURLAUTH_BASIC) - pick->picked = CURLAUTH_BASIC; - else { - pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */ - picked = FALSE; - } - pick->avail = CURLAUTH_NONE; /* clear it here */ - - return picked; -} - -/* - * Curl_http_perhapsrewind() - * - * If we are doing POST or PUT { - * If we have more data to send { - * If we are doing NTLM { - * Keep sending since we must not disconnect - * } - * else { - * If there is more than just a little data left to send, close - * the current connection by force. - * } - * } - * If we have sent any data { - * If we don't have track of all the data { - * call app to tell it to rewind - * } - * else { - * rewind internally so that the operation can restart fine - * } - * } - * } - */ -CURLcode Curl_http_perhapsrewind(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - struct HTTP *http = data->state.proto.http; - curl_off_t bytessent; - curl_off_t expectsend = -1; /* default is unknown */ - - if(!http || !(conn->handler->protocol & CURLPROTO_HTTP)) - /* If this is still NULL, we have not reach very far and we can - safely skip this rewinding stuff, or this is attempted to get used - when HTTP isn't activated */ - return CURLE_OK; - - switch(data->set.httpreq) { - case HTTPREQ_GET: - case HTTPREQ_HEAD: - return CURLE_OK; - default: - break; - } - - bytessent = http->writebytecount; - - if(conn->bits.authneg) - /* This is a state where we are known to be negotiating and we don't send - any data then. */ - expectsend = 0; - else { - /* figure out how much data we are expected to send */ - switch(data->set.httpreq) { - case HTTPREQ_POST: - if(data->set.postfieldsize != -1) - expectsend = data->set.postfieldsize; - else if(data->set.postfields) - expectsend = (curl_off_t)strlen(data->set.postfields); - break; - case HTTPREQ_PUT: - if(data->set.infilesize != -1) - expectsend = data->set.infilesize; - break; - case HTTPREQ_POST_FORM: - expectsend = http->postsize; - break; - default: - break; - } - } - - conn->bits.rewindaftersend = FALSE; /* default */ - - if((expectsend == -1) || (expectsend > bytessent)) { - /* There is still data left to send */ - if((data->state.authproxy.picked == CURLAUTH_NTLM) || - (data->state.authhost.picked == CURLAUTH_NTLM)) { - if(((expectsend - bytessent) < 2000) || - (conn->ntlm.state != NTLMSTATE_NONE)) { - /* The NTLM-negotiation has started *OR* there is just a little (<2K) - data left to send, keep on sending. */ - - /* rewind data when completely done sending! */ - if(!conn->bits.authneg) - conn->bits.rewindaftersend = TRUE; - - return CURLE_OK; - } - if(conn->bits.close) - /* this is already marked to get closed */ - return CURLE_OK; - - infof(data, "NTLM send, close instead of sending %" FORMAT_OFF_T - " bytes\n", (curl_off_t)(expectsend - bytessent)); - } - - /* This is not NTLM or NTLM with many bytes left to send: close - */ - conn->bits.close = TRUE; - data->req.size = 0; /* don't download any more than 0 bytes */ - - /* There still is data left to send, but this connection is marked for - closure so we can safely do the rewind right now */ - } - - if(bytessent) - /* we rewind now at once since if we already sent something */ - return Curl_readrewind(conn); - - return CURLE_OK; -} - -/* - * Curl_http_auth_act() gets called when all HTTP headers have been received - * and it checks what authentication methods that are available and decides - * which one (if any) to use. It will set 'newurl' if an auth method was - * picked. - */ - -CURLcode Curl_http_auth_act(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - bool pickhost = FALSE; - bool pickproxy = FALSE; - CURLcode code = CURLE_OK; - - if(100 <= data->req.httpcode && 199 >= data->req.httpcode) - /* this is a transient response code, ignore */ - return CURLE_OK; - - if(data->state.authproblem) - return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK; - - if(conn->bits.user_passwd && - ((data->req.httpcode == 401) || - (conn->bits.authneg && data->req.httpcode < 300))) { - pickhost = pickoneauth(&data->state.authhost); - if(!pickhost) - data->state.authproblem = TRUE; - } - if(conn->bits.proxy_user_passwd && - ((data->req.httpcode == 407) || - (conn->bits.authneg && data->req.httpcode < 300))) { - pickproxy = pickoneauth(&data->state.authproxy); - if(!pickproxy) - data->state.authproblem = TRUE; - } - - if(pickhost || pickproxy) { - /* In case this is GSS auth, the newurl field is already allocated so - we must make sure to free it before allocating a new one. As figured - out in bug #2284386 */ - Curl_safefree(data->req.newurl); - data->req.newurl = strdup(data->change.url); /* clone URL */ - if(!data->req.newurl) - return CURLE_OUT_OF_MEMORY; - - if((data->set.httpreq != HTTPREQ_GET) && - (data->set.httpreq != HTTPREQ_HEAD) && - !conn->bits.rewindaftersend) { - code = Curl_http_perhapsrewind(conn); - if(code) - return code; - } - } - - else if((data->req.httpcode < 300) && - (!data->state.authhost.done) && - conn->bits.authneg) { - /* no (known) authentication available, - authentication is not "done" yet and - no authentication seems to be required and - we didn't try HEAD or GET */ - if((data->set.httpreq != HTTPREQ_GET) && - (data->set.httpreq != HTTPREQ_HEAD)) { - data->req.newurl = strdup(data->change.url); /* clone URL */ - if(!data->req.newurl) - return CURLE_OUT_OF_MEMORY; - data->state.authhost.done = TRUE; - } - } - if(Curl_http_should_fail(conn)) { - failf (data, "The requested URL returned error: %d", - data->req.httpcode); - code = CURLE_HTTP_RETURNED_ERROR; - } - - return code; -} - - -/* - * Output the correct authentication header depending on the auth type - * and whether or not it is to a proxy. - */ -static CURLcode -output_auth_headers(struct connectdata *conn, - struct auth *authstatus, - const char *request, - const char *path, - bool proxy) -{ - struct SessionHandle *data = conn->data; - const char *auth=NULL; - CURLcode result = CURLE_OK; -#ifdef USE_HTTP_NEGOTIATE - struct negotiatedata *negdata = proxy? - &data->state.proxyneg:&data->state.negotiate; -#endif - -#ifdef CURL_DISABLE_CRYPTO_AUTH - (void)request; - (void)path; -#endif - -#ifdef USE_HTTP_NEGOTIATE - negdata->state = GSS_AUTHNONE; - if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) && - negdata->context && !GSS_ERROR(negdata->status)) { - auth="GSS-Negotiate"; - result = Curl_output_negotiate(conn, proxy); - if(result) - return result; - authstatus->done = TRUE; - negdata->state = GSS_AUTHSENT; - } - else -#endif -#ifdef USE_NTLM - if(authstatus->picked == CURLAUTH_NTLM) { - auth="NTLM"; - result = Curl_output_ntlm(conn, proxy); - if(result) - return result; - } - else -#endif -#ifndef CURL_DISABLE_CRYPTO_AUTH - if(authstatus->picked == CURLAUTH_DIGEST) { - auth="Digest"; - result = Curl_output_digest(conn, - proxy, - (const unsigned char *)request, - (const unsigned char *)path); - if(result) - return result; - } - else -#endif - if(authstatus->picked == CURLAUTH_BASIC) { - /* Basic */ - if((proxy && conn->bits.proxy_user_passwd && - !Curl_checkheaders(data, "Proxy-authorization:")) || - (!proxy && conn->bits.user_passwd && - !Curl_checkheaders(data, "Authorization:"))) { - auth="Basic"; - result = http_output_basic(conn, proxy); - if(result) - return result; - } - /* NOTE: this function should set 'done' TRUE, as the other auth - functions work that way */ - authstatus->done = TRUE; - } - - if(auth) { - infof(data, "%s auth using %s with user '%s'\n", - proxy?"Proxy":"Server", auth, - proxy?(conn->proxyuser?conn->proxyuser:""): - (conn->user?conn->user:"")); - authstatus->multi = (bool)(!authstatus->done); - } - else - authstatus->multi = FALSE; - - return CURLE_OK; -} - -/** - * Curl_http_output_auth() setups the authentication headers for the - * host/proxy and the correct authentication - * method. conn->data->state.authdone is set to TRUE when authentication is - * done. - * - * @param conn all information about the current connection - * @param request pointer to the request keyword - * @param path pointer to the requested path - * @param proxytunnel boolean if this is the request setting up a "proxy - * tunnel" - * - * @returns CURLcode - */ -CURLcode -Curl_http_output_auth(struct connectdata *conn, - const char *request, - const char *path, - bool proxytunnel) /* TRUE if this is the request setting - up the proxy tunnel */ -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - struct auth *authhost; - struct auth *authproxy; - - DEBUGASSERT(data); - - authhost = &data->state.authhost; - authproxy = &data->state.authproxy; - - if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) || - conn->bits.user_passwd) - /* continue please */ ; - else { - authhost->done = TRUE; - authproxy->done = TRUE; - return CURLE_OK; /* no authentication with no user or password */ - } - - if(authhost->want && !authhost->picked) - /* The app has selected one or more methods, but none has been picked - so far by a server round-trip. Then we set the picked one to the - want one, and if this is one single bit it'll be used instantly. */ - authhost->picked = authhost->want; - - if(authproxy->want && !authproxy->picked) - /* The app has selected one or more methods, but none has been picked so - far by a proxy round-trip. Then we set the picked one to the want one, - and if this is one single bit it'll be used instantly. */ - authproxy->picked = authproxy->want; - -#ifndef CURL_DISABLE_PROXY - /* Send proxy authentication header if needed */ - if(conn->bits.httpproxy && - (conn->bits.tunnel_proxy == proxytunnel)) { - result = output_auth_headers(conn, authproxy, request, path, TRUE); - if(result) - return result; - } - else -#else - (void)proxytunnel; -#endif /* CURL_DISABLE_PROXY */ - /* we have no proxy so let's pretend we're done authenticating - with it */ - authproxy->done = TRUE; - - /* To prevent the user+password to get sent to other than the original - host due to a location-follow, we do some weirdo checks here */ - if(!data->state.this_is_a_follow || - conn->bits.netrc || - !data->state.first_host || - data->set.http_disable_hostname_check_before_authentication || - Curl_raw_equal(data->state.first_host, conn->host.name)) { - result = output_auth_headers(conn, authhost, request, path, FALSE); - } - else - authhost->done = TRUE; - - return result; -} - - -/* - * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate: - * headers. They are dealt with both in the transfer.c main loop and in the - * proxy CONNECT loop. - */ - -CURLcode Curl_http_input_auth(struct connectdata *conn, - int httpcode, - const char *header) /* the first non-space */ -{ - /* - * This resource requires authentication - */ - struct SessionHandle *data = conn->data; - - long *availp; - const char *start; - struct auth *authp; - - if(httpcode == 407) { - start = header+strlen("Proxy-authenticate:"); - availp = &data->info.proxyauthavail; - authp = &data->state.authproxy; - } - else { - start = header+strlen("WWW-Authenticate:"); - availp = &data->info.httpauthavail; - authp = &data->state.authhost; - } - - /* pass all white spaces */ - while(*start && ISSPACE(*start)) - start++; - - /* - * Here we check if we want the specific single authentication (using ==) and - * if we do, we initiate usage of it. - * - * If the provided authentication is wanted as one out of several accepted - * types (using &), we OR this authentication type to the authavail - * variable. - * - * Note: - * - * ->picked is first set to the 'want' value (one or more bits) before the - * request is sent, and then it is again set _after_ all response 401/407 - * headers have been received but then only to a single preferred method - * (bit). - * - */ - -#ifdef USE_HTTP_NEGOTIATE - if(checkprefix("GSS-Negotiate", start) || - checkprefix("Negotiate", start)) { - int neg; - *availp |= CURLAUTH_GSSNEGOTIATE; - authp->avail |= CURLAUTH_GSSNEGOTIATE; - - if(data->state.negotiate.state == GSS_AUTHSENT) { - /* if we sent GSS authentication in the outgoing request and we get this - back, we're in trouble */ - infof(data, "Authentication problem. Ignoring this.\n"); - data->state.authproblem = TRUE; - } - else { - neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); - if(neg == 0) { - DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->change.url); - if(!data->req.newurl) - return CURLE_OUT_OF_MEMORY; - data->state.authproblem = FALSE; - /* we received GSS auth info and we dealt with it fine */ - data->state.negotiate.state = GSS_AUTHRECV; - } - else { - data->state.authproblem = TRUE; - } - } - } - else -#endif -#ifdef USE_NTLM - /* NTLM support requires the SSL crypto libs */ - if(checkprefix("NTLM", start)) { - *availp |= CURLAUTH_NTLM; - authp->avail |= CURLAUTH_NTLM; - if(authp->picked == CURLAUTH_NTLM) { - /* NTLM authentication is picked and activated */ - CURLntlm ntlm = - Curl_input_ntlm(conn, (bool)(httpcode == 407), start); - - if(CURLNTLM_BAD != ntlm) - data->state.authproblem = FALSE; - else { - infof(data, "Authentication problem. Ignoring this.\n"); - data->state.authproblem = TRUE; - } - } - } - else -#endif -#ifndef CURL_DISABLE_CRYPTO_AUTH - if(checkprefix("Digest", start)) { - if((authp->avail & CURLAUTH_DIGEST) != 0) { - infof(data, "Ignoring duplicate digest auth header.\n"); - } - else { - CURLdigest dig; - *availp |= CURLAUTH_DIGEST; - authp->avail |= CURLAUTH_DIGEST; - - /* We call this function on input Digest headers even if Digest - * authentication isn't activated yet, as we need to store the - * incoming data from this header in case we are gonna use Digest. */ - dig = Curl_input_digest(conn, (bool)(httpcode == 407), start); - - if(CURLDIGEST_FINE != dig) { - infof(data, "Authentication problem. Ignoring this.\n"); - data->state.authproblem = TRUE; - } - } - } - else -#endif - if(checkprefix("Basic", start)) { - *availp |= CURLAUTH_BASIC; - authp->avail |= CURLAUTH_BASIC; - if(authp->picked == CURLAUTH_BASIC) { - /* We asked for Basic authentication but got a 40X back - anyway, which basically means our name+password isn't - valid. */ - authp->avail = CURLAUTH_NONE; - infof(data, "Authentication problem. Ignoring this.\n"); - data->state.authproblem = TRUE; - } - } - - return CURLE_OK; -} - -/** - * Curl_http_should_fail() determines whether an HTTP response has gotten us - * into an error state or not. - * - * @param conn all information about the current connection - * - * @retval 0 communications should continue - * - * @retval 1 communications should not continue - */ -int Curl_http_should_fail(struct connectdata *conn) -{ - struct SessionHandle *data; - int httpcode; - - DEBUGASSERT(conn); - data = conn->data; - DEBUGASSERT(data); - - httpcode = data->req.httpcode; - - /* - ** If we haven't been asked to fail on error, - ** don't fail. - */ - if(!data->set.http_fail_on_error) - return 0; - - /* - ** Any code < 400 is never terminal. - */ - if(httpcode < 400) - return 0; - - if(data->state.resume_from && - (data->set.httpreq==HTTPREQ_GET) && - (httpcode == 416)) { - /* "Requested Range Not Satisfiable", just proceed and - pretend this is no error */ - return 0; - } - - /* - ** Any code >= 400 that's not 401 or 407 is always - ** a terminal error - */ - if((httpcode != 401) && - (httpcode != 407)) - return 1; - - /* - ** All we have left to deal with is 401 and 407 - */ - DEBUGASSERT((httpcode == 401) || (httpcode == 407)); - - /* - ** Examine the current authentication state to see if this - ** is an error. The idea is for this function to get - ** called after processing all the headers in a response - ** message. So, if we've been to asked to authenticate a - ** particular stage, and we've done it, we're OK. But, if - ** we're already completely authenticated, it's not OK to - ** get another 401 or 407. - ** - ** It is possible for authentication to go stale such that - ** the client needs to reauthenticate. Once that info is - ** available, use it here. - */ -#if 0 /* set to 1 when debugging this functionality */ - infof(data,"%s: authstage = %d\n",__FUNCTION__,data->state.authstage); - infof(data,"%s: authwant = 0x%08x\n",__FUNCTION__,data->state.authwant); - infof(data,"%s: authavail = 0x%08x\n",__FUNCTION__,data->state.authavail); - infof(data,"%s: httpcode = %d\n",__FUNCTION__,k->httpcode); - infof(data,"%s: authdone = %d\n",__FUNCTION__,data->state.authdone); - infof(data,"%s: newurl = %s\n",__FUNCTION__,data->req.newurl ? - data->req.newurl : "(null)"); - infof(data,"%s: authproblem = %d\n",__FUNCTION__,data->state.authproblem); -#endif - - /* - ** Either we're not authenticating, or we're supposed to - ** be authenticating something else. This is an error. - */ - if((httpcode == 401) && !conn->bits.user_passwd) - return TRUE; - if((httpcode == 407) && !conn->bits.proxy_user_passwd) - return TRUE; - - return data->state.authproblem; -} - -/* - * readmoredata() is a "fread() emulation" to provide POST and/or request - * data. It is used when a huge POST is to be made and the entire chunk wasn't - * sent in the first send(). This function will then be called from the - * transfer.c loop when more data is to be sent to the peer. - * - * Returns the amount of bytes it filled the buffer with. - */ -static size_t readmoredata(char *buffer, - size_t size, - size_t nitems, - void *userp) -{ - struct connectdata *conn = (struct connectdata *)userp; - struct HTTP *http = conn->data->state.proto.http; - size_t fullsize = size * nitems; - - if(0 == http->postsize) - /* nothing to return */ - return 0; - - /* make sure that a HTTP request is never sent away chunked! */ - conn->data->req.forbidchunk = (bool)(http->sending == HTTPSEND_REQUEST); - - if(http->postsize <= (curl_off_t)fullsize) { - memcpy(buffer, http->postdata, (size_t)http->postsize); - fullsize = (size_t)http->postsize; - - if(http->backup.postsize) { - /* move backup data into focus and continue on that */ - http->postdata = http->backup.postdata; - http->postsize = http->backup.postsize; - conn->fread_func = http->backup.fread_func; - conn->fread_in = http->backup.fread_in; - - http->sending++; /* move one step up */ - - http->backup.postsize=0; - } - else - http->postsize = 0; - - return fullsize; - } - - memcpy(buffer, http->postdata, fullsize); - http->postdata += fullsize; - http->postsize -= fullsize; - - return fullsize; -} - -/* ------------------------------------------------------------------------- */ -/* add_buffer functions */ - -/* - * Curl_add_buffer_init() sets up and returns a fine buffer struct - */ -Curl_send_buffer *Curl_add_buffer_init(void) -{ - return calloc(1, sizeof(Curl_send_buffer)); -} - -/* - * Curl_add_buffer_send() sends a header buffer and frees all associated - * memory. Body data may be appended to the header data if desired. - * - * Returns CURLcode - */ -CURLcode Curl_add_buffer_send(Curl_send_buffer *in, - struct connectdata *conn, - - /* add the number of sent bytes to this - counter */ - long *bytes_written, - - /* how much of the buffer contains body data */ - size_t included_body_bytes, - int socketindex) - -{ - ssize_t amount; - CURLcode res; - char *ptr; - size_t size; - struct HTTP *http = conn->data->state.proto.http; - size_t sendsize; - curl_socket_t sockfd; - size_t headersize; - - DEBUGASSERT(socketindex <= SECONDARYSOCKET); - - sockfd = conn->sock[socketindex]; - - /* The looping below is required since we use non-blocking sockets, but due - to the circumstances we will just loop and try again and again etc */ - - ptr = in->buffer; - size = in->size_used; - - headersize = size - included_body_bytes; /* the initial part that isn't body - is header */ - - DEBUGASSERT(size > included_body_bytes); - - res = Curl_convert_to_network(conn->data, ptr, headersize); - /* Curl_convert_to_network calls failf if unsuccessful */ - if(res) { - /* conversion failed, free memory and return to the caller */ - if(in->buffer) - free(in->buffer); - free(in); - return res; - } - - if(conn->handler->protocol & CURLPROTO_HTTPS) { - /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk - when we speak HTTPS, as if only a fraction of it is sent now, this data - needs to fit into the normal read-callback buffer later on and that - buffer is using this size. - */ - - sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size; - - /* OpenSSL is very picky and we must send the SAME buffer pointer to the - library when we attempt to re-send this buffer. Sending the same data - is not enough, we must use the exact same address. For this reason, we - must copy the data to the uploadbuffer first, since that is the buffer - we will be using if this send is retried later. - */ - memcpy(conn->data->state.uploadbuffer, ptr, sendsize); - ptr = conn->data->state.uploadbuffer; - } - else - sendsize = size; - - res = Curl_write(conn, sockfd, ptr, sendsize, &amount); - - if(CURLE_OK == res) { - /* - * Note that we may not send the entire chunk at once, and we have a set - * number of data bytes at the end of the big buffer (out of which we may - * only send away a part). - */ - /* how much of the header that was sent */ - size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount; - size_t bodylen = amount - headlen; - - if(conn->data->set.verbose) { - /* this data _may_ contain binary stuff */ - Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn); - if((size_t)amount > headlen) { - /* there was body data sent beyond the initial header part, pass that - on to the debug callback too */ - Curl_debug(conn->data, CURLINFO_DATA_OUT, - ptr+headlen, bodylen, conn); - } - } - if(bodylen) - /* since we sent a piece of the body here, up the byte counter for it - accordingly */ - http->writebytecount += bodylen; - - /* 'amount' can never be a very large value here so typecasting it so a - signed 31 bit value should not cause problems even if ssize_t is - 64bit */ - *bytes_written += (long)amount; - - if(http) { - if((size_t)amount != size) { - /* The whole request could not be sent in one system call. We must - queue it up and send it later when we get the chance. We must not - loop here and wait until it might work again. */ - - size -= amount; - - ptr = in->buffer + amount; - - /* backup the currently set pointers */ - http->backup.fread_func = conn->fread_func; - http->backup.fread_in = conn->fread_in; - http->backup.postdata = http->postdata; - http->backup.postsize = http->postsize; - - /* set the new pointers for the request-sending */ - conn->fread_func = (curl_read_callback)readmoredata; - conn->fread_in = (void *)conn; - http->postdata = ptr; - http->postsize = (curl_off_t)size; - - http->send_buffer = in; - http->sending = HTTPSEND_REQUEST; - - return CURLE_OK; - } - http->sending = HTTPSEND_BODY; - /* the full buffer was sent, clean up and return */ - } - else { - if((size_t)amount != size) - /* We have no continue-send mechanism now, fail. This can only happen - when this function is used from the CONNECT sending function. We - currently (stupidly) assume that the whole request is always sent - away in the first single chunk. - - This needs FIXing. - */ - return CURLE_SEND_ERROR; - else - conn->writechannel_inuse = FALSE; - } - } - if(in->buffer) - free(in->buffer); - free(in); - - return res; -} - - -/* - * add_bufferf() add the formatted input to the buffer. - */ -CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...) -{ - char *s; - va_list ap; - va_start(ap, fmt); - s = vaprintf(fmt, ap); /* this allocs a new string to append */ - va_end(ap); - - if(s) { - CURLcode result = Curl_add_buffer(in, s, strlen(s)); - free(s); - return result; - } - /* If we failed, we cleanup the whole buffer and return error */ - if(in->buffer) - free(in->buffer); - free(in); - return CURLE_OUT_OF_MEMORY; -} - -/* - * add_buffer() appends a memory chunk to the existing buffer - */ -CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size) -{ - char *new_rb; - size_t new_size; - - if(~size < in->size_used) { - /* If resulting used size of send buffer would wrap size_t, cleanup - the whole buffer and return error. Otherwise the required buffer - size will fit into a single allocatable memory chunk */ - Curl_safefree(in->buffer); - free(in); - return CURLE_OUT_OF_MEMORY; - } - - if(!in->buffer || - ((in->size_used + size) > (in->size_max - 1))) { - - /* If current buffer size isn't enough to hold the result, use a - buffer size that doubles the required size. If this new size - would wrap size_t, then just use the largest possible one */ - - if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) || - (~(size*2) < (in->size_used*2))) - new_size = (size_t)-1; - else - new_size = (in->size_used+size)*2; - - if(in->buffer) - /* we have a buffer, enlarge the existing one */ - new_rb = realloc(in->buffer, new_size); - else - /* create a new buffer */ - new_rb = malloc(new_size); - - if(!new_rb) { - /* If we failed, we cleanup the whole buffer and return error */ - Curl_safefree(in->buffer); - free(in); - return CURLE_OUT_OF_MEMORY; - } - - in->buffer = new_rb; - in->size_max = new_size; - } - memcpy(&in->buffer[in->size_used], inptr, size); - - in->size_used += size; - - return CURLE_OK; -} - -/* end of the add_buffer functions */ -/* ------------------------------------------------------------------------- */ - - - -/* - * Curl_compareheader() - * - * Returns TRUE if 'headerline' contains the 'header' with given 'content'. - * Pass headers WITH the colon. - */ -bool -Curl_compareheader(const char *headerline, /* line to check */ - const char *header, /* header keyword _with_ colon */ - const char *content) /* content string to find */ -{ - /* RFC2616, section 4.2 says: "Each header field consists of a name followed - * by a colon (":") and the field value. Field names are case-insensitive. - * The field value MAY be preceded by any amount of LWS, though a single SP - * is preferred." */ - - size_t hlen = strlen(header); - size_t clen; - size_t len; - const char *start; - const char *end; - - if(!Curl_raw_nequal(headerline, header, hlen)) - return FALSE; /* doesn't start with header */ - - /* pass the header */ - start = &headerline[hlen]; - - /* pass all white spaces */ - while(*start && ISSPACE(*start)) - start++; - - /* find the end of the header line */ - end = strchr(start, '\r'); /* lines end with CRLF */ - if(!end) { - /* in case there's a non-standard compliant line here */ - end = strchr(start, '\n'); - - if(!end) - /* hm, there's no line ending here, use the zero byte! */ - end = strchr(start, '\0'); - } - - len = end-start; /* length of the content part of the input line */ - clen = strlen(content); /* length of the word to find */ - - /* find the content string in the rest of the line */ - for(;len>=clen;len--, start++) { - if(Curl_raw_nequal(start, content, clen)) - return TRUE; /* match! */ - } - - return FALSE; /* no match */ -} - -/* - * Curl_http_connect() performs HTTP stuff to do at connect-time, called from - * the generic Curl_connect(). - */ -CURLcode Curl_http_connect(struct connectdata *conn, bool *done) -{ - struct SessionHandle *data; - CURLcode result; - - data=conn->data; - - /* 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. */ - conn->bits.close = FALSE; - -#ifndef CURL_DISABLE_PROXY - /* If we are not using a proxy and we want a secure connection, perform SSL - * initialization & connection now. If using a proxy with https, then we - * must tell the proxy to CONNECT to the host we want to talk to. Only - * after the connect has occurred, can we start talking SSL - */ - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - - /* either SSL over proxy, or explicitly asked for */ - result = Curl_proxyCONNECT(conn, FIRSTSOCKET, - conn->host.name, - conn->remote_port); - if(CURLE_OK != result) - return result; - } - - if(conn->bits.tunnel_connecting) { - /* nothing else to do except wait right now - we're not done here. */ - return CURLE_OK; - } -#endif /* CURL_DISABLE_PROXY */ - - if(conn->given->protocol & CURLPROTO_HTTPS) { - /* perform SSL initialization */ - if(data->state.used_interface == Curl_if_multi) { - result = https_connecting(conn, done); - if(result) - return result; - } - else { - /* BLOCKING */ - result = Curl_ssl_connect(conn, FIRSTSOCKET); - if(result) - return result; - *done = TRUE; - } - } - else { - *done = TRUE; - } - - return CURLE_OK; -} - -/* this returns the socket to wait for in the DO and DOING state for the multi - interface and then we're always _sending_ a request and thus we wait for - the single socket to become writable only */ -static int http_getsock_do(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - /* write mode */ - (void)numsocks; /* unused, we trust it to be at least 1 */ - socks[0] = conn->sock[FIRSTSOCKET]; - return GETSOCK_WRITESOCK(0); -} - -#ifdef USE_SSL -static CURLcode https_connecting(struct connectdata *conn, bool *done) -{ - CURLcode result; - DEBUGASSERT((conn) && (conn->handler->protocol & CURLPROTO_HTTPS)); - - /* perform SSL initialization for this socket */ - result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done); - if(result) - conn->bits.close = TRUE; /* a failed connection is marked for closure - to prevent (bad) re-use or similar */ - return result; -} -#endif - -#if defined(USE_SSLEAY) || defined(USE_GNUTLS) -/* This function is for OpenSSL and GnuTLS only. It should be made to query - the generic SSL layer instead. */ -static int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - if(conn->handler->protocol & CURLPROTO_HTTPS) { - struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; - - if(!numsocks) - return GETSOCK_BLANK; - - if(connssl->connecting_state == ssl_connect_2_writing) { - /* write mode */ - socks[0] = conn->sock[FIRSTSOCKET]; - return GETSOCK_WRITESOCK(0); - } - else if(connssl->connecting_state == ssl_connect_2_reading) { - /* read mode */ - socks[0] = conn->sock[FIRSTSOCKET]; - return GETSOCK_READSOCK(0); - } - } - return CURLE_OK; -} -#else -#if defined(USE_NSS) || defined(USE_QSOSSL) || \ - defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_CYASSL) -static int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - (void)conn; - (void)socks; - (void)numsocks; - return GETSOCK_BLANK; -} -#endif /* USE_AXTLS || USE_POLARSSL || USE_QSOSSL || USE_NSS */ -#endif /* USE_SSLEAY || USE_GNUTLS */ - -/* - * Curl_http_done() gets called from Curl_done() after a single HTTP request - * has been performed. - */ - -CURLcode Curl_http_done(struct connectdata *conn, - CURLcode status, bool premature) -{ - struct SessionHandle *data = conn->data; - struct HTTP *http =data->state.proto.http; - - Curl_unencode_cleanup(conn); - - /* set the proper values (possibly modified on POST) */ - conn->fread_func = data->set.fread_func; /* restore */ - conn->fread_in = data->set.in; /* restore */ - conn->seek_func = data->set.seek_func; /* restore */ - conn->seek_client = data->set.seek_client; /* restore */ - - if(http == NULL) - return CURLE_OK; - - if(http->send_buffer) { - Curl_send_buffer *buff = http->send_buffer; - - free(buff->buffer); - free(buff); - http->send_buffer = NULL; /* clear the pointer */ - } - - if(HTTPREQ_POST_FORM == data->set.httpreq) { - data->req.bytecount = http->readbytecount + http->writebytecount; - - Curl_formclean(&http->sendit); /* Now free that whole lot */ - if(http->form.fp) { - /* a file being uploaded was left opened, close it! */ - fclose(http->form.fp); - http->form.fp = NULL; - } - } - else if(HTTPREQ_PUT == data->set.httpreq) - data->req.bytecount = http->readbytecount + http->writebytecount; - - if(status != CURLE_OK) - return (status); - - if(!premature && /* this check is pointless when DONE is called before the - entire operation is complete */ - !conn->bits.retry && - ((http->readbytecount + - data->req.headerbytecount - - data->req.deductheadercount)) <= 0) { - /* If this connection isn't simply closed to be retried, AND nothing was - read from the HTTP server (that counts), this can't be right so we - return an error here */ - failf(data, "Empty reply from server"); - return CURLE_GOT_NOTHING; - } - - return CURLE_OK; -} - - -/* Determine if we should use HTTP 1.1 for this request. Reasons to avoid it - are if the user specifically requested HTTP 1.0, if the server we are - connected to only supports 1.0, or if any server previously contacted to - handle this request only supports 1.0. */ -static bool use_http_1_1(const struct SessionHandle *data, - const struct connectdata *conn) -{ - return (bool)((data->set.httpversion == CURL_HTTP_VERSION_1_1) || - ((data->set.httpversion != CURL_HTTP_VERSION_1_0) && - ((conn->httpversion == 11) || - ((conn->httpversion != 10) && - (data->state.httpversion != 10))))); -} - -/* check and possibly add an Expect: header */ -static CURLcode expect100(struct SessionHandle *data, - struct connectdata *conn, - Curl_send_buffer *req_buffer) -{ - CURLcode result = CURLE_OK; - const char *ptr; - data->state.expect100header = FALSE; /* default to false unless it is set - to TRUE below */ - if(use_http_1_1(data, conn)) { - /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: - 100-continue to the headers which actually speeds up post operations - (as there is one packet coming back from the web server) */ - ptr = Curl_checkheaders(data, "Expect:"); - if (ptr) { - data->state.expect100header = - Curl_compareheader(ptr, "Expect:", "100-continue"); - } - else { - result = Curl_add_bufferf(req_buffer, - "Expect: 100-continue\r\n"); - if(result == CURLE_OK) - data->state.expect100header = TRUE; - } - } - return result; -} - -CURLcode Curl_add_custom_headers(struct connectdata *conn, - Curl_send_buffer *req_buffer) -{ - char *ptr; - struct curl_slist *headers=conn->data->set.headers; - - while(headers) { - ptr = strchr(headers->data, ':'); - if(ptr) { - /* we require a colon for this to be a true header */ - - ptr++; /* pass the colon */ - while(*ptr && ISSPACE(*ptr)) - ptr++; - - if(*ptr) { - /* only send this if the contents was non-blank */ - - if(conn->allocptr.host && - /* a Host: header was sent already, don't pass on any custom Host: - header as that will produce *two* in the same request! */ - checkprefix("Host:", headers->data)) - ; - else if(conn->data->set.httpreq == HTTPREQ_POST_FORM && - /* this header (extended by formdata.c) is sent later */ - checkprefix("Content-Type:", headers->data)) - ; - else if(conn->bits.authneg && - /* while doing auth neg, don't allow the custom length since - we will force length zero then */ - checkprefix("Content-Length", headers->data)) - ; - else if(conn->allocptr.te && - /* when asking for Transfer-Encoding, don't pass on a custom - Connection: */ - checkprefix("Connection", headers->data)) - ; - else { - CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n", - headers->data); - if(result) - return result; - } - } - } - headers = headers->next; - } - return CURLE_OK; -} - -CURLcode Curl_add_timecondition(struct SessionHandle *data, - Curl_send_buffer *req_buffer) -{ - const struct tm *tm; - char *buf = data->state.buffer; - CURLcode result = CURLE_OK; - struct tm keeptime; - - result = Curl_gmtime(data->set.timevalue, &keeptime); - if(result) { - failf(data, "Invalid TIMEVALUE\n"); - return result; - } - tm = &keeptime; - - /* The If-Modified-Since header family should have their times set in - * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be - * represented in Greenwich Mean Time (GMT), without exception. For the - * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal - * Time)." (see page 20 of RFC2616). - */ - - /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ - snprintf(buf, BUFSIZE-1, - "%s, %02d %s %4d %02d:%02d:%02d GMT", - Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], - tm->tm_mday, - Curl_month[tm->tm_mon], - tm->tm_year + 1900, - tm->tm_hour, - tm->tm_min, - tm->tm_sec); - - switch(data->set.timecondition) { - case CURL_TIMECOND_IFMODSINCE: - default: - result = Curl_add_bufferf(req_buffer, - "If-Modified-Since: %s\r\n", buf); - break; - case CURL_TIMECOND_IFUNMODSINCE: - result = Curl_add_bufferf(req_buffer, - "If-Unmodified-Since: %s\r\n", buf); - break; - case CURL_TIMECOND_LASTMOD: - result = Curl_add_bufferf(req_buffer, - "Last-Modified: %s\r\n", buf); - break; - } - - return result; -} - -/* - * Curl_http() gets called from the generic Curl_do() function when a HTTP - * request is to be performed. This creates and sends a properly constructed - * HTTP request. - */ -CURLcode Curl_http(struct connectdata *conn, bool *done) -{ - struct SessionHandle *data=conn->data; - CURLcode result=CURLE_OK; - struct HTTP *http; - const char *ppath = data->state.path; - bool paste_ftp_userpwd = FALSE; - char ftp_typecode[sizeof("/;type=?")] = ""; - const char *host = conn->host.name; - const char *te = ""; /* transfer-encoding */ - const char *ptr; - const char *request; - Curl_HttpReq httpreq = data->set.httpreq; - char *addcookies = NULL; - curl_off_t included_body = 0; - const char *httpstring; - Curl_send_buffer *req_buffer; - curl_off_t postsize; /* off_t type to be able to hold a large file size */ - int seekerr = CURL_SEEKFUNC_OK; - - /* Always consider the DO phase done after this function call, even if there - may be parts of the request that is not yet sent, since we can deal with - the rest of the request in the PERFORM phase. */ - *done = TRUE; - - /* If there already is a protocol-specific struct allocated for this - sessionhandle, deal with it */ - Curl_reset_reqproto(conn); - - if(!data->state.proto.http) { - /* Only allocate this struct if we don't already have it! */ - - http = calloc(1, sizeof(struct HTTP)); - if(!http) - return CURLE_OUT_OF_MEMORY; - data->state.proto.http = http; - } - else - http = data->state.proto.http; - - if(!data->state.this_is_a_follow) { - /* this is not a followed location, get the original host name */ - if(data->state.first_host) - /* Free to avoid leaking memory on multiple requests*/ - free(data->state.first_host); - - data->state.first_host = strdup(conn->host.name); - if(!data->state.first_host) - return CURLE_OUT_OF_MEMORY; - } - - if( (conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) && - data->set.upload) { - httpreq = HTTPREQ_PUT; - } - - /* Now set the 'request' pointer to the proper request string */ - if(data->set.str[STRING_CUSTOMREQUEST]) - request = data->set.str[STRING_CUSTOMREQUEST]; - else { - if(data->set.opt_no_body) - request = "HEAD"; - else { - DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST)); - switch(httpreq) { - case HTTPREQ_POST: - case HTTPREQ_POST_FORM: - request = "POST"; - break; - case HTTPREQ_PUT: - request = "PUT"; - break; - default: /* this should never happen */ - case HTTPREQ_GET: - request = "GET"; - break; - case HTTPREQ_HEAD: - request = "HEAD"; - break; - } - } - } - - /* The User-Agent string might have been allocated in url.c already, because - it might have been used in the proxy connect, but if we have got a header - with the user-agent string specified, we erase the previously made string - here. */ - if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) { - free(conn->allocptr.uagent); - conn->allocptr.uagent=NULL; - } - - /* setup the authentication headers */ - result = Curl_http_output_auth(conn, request, ppath, FALSE); - if(result) - return result; - - if((data->state.authhost.multi || data->state.authproxy.multi) && - (httpreq != HTTPREQ_GET) && - (httpreq != HTTPREQ_HEAD)) { - /* Auth is required and we are not authenticated yet. Make a PUT or POST - with content-length zero as a "probe". */ - conn->bits.authneg = TRUE; - } - else - conn->bits.authneg = FALSE; - - Curl_safefree(conn->allocptr.ref); - if(data->change.referer && !Curl_checkheaders(data, "Referer:")) - conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); - else - conn->allocptr.ref = NULL; - - if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie:")) - addcookies = data->set.str[STRING_COOKIE]; - - if(!Curl_checkheaders(data, "Accept-Encoding:") && - data->set.str[STRING_ENCODING]) { - Curl_safefree(conn->allocptr.accept_encoding); - conn->allocptr.accept_encoding = - aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); - if(!conn->allocptr.accept_encoding) - return CURLE_OUT_OF_MEMORY; - } - -#ifdef HAVE_LIBZ - /* we only consider transfer-encoding magic if libz support is built-in */ - - if(!Curl_checkheaders(data, "TE:") && data->set.http_transfer_encoding) { - /* When we are to insert a TE: header in the request, we must also insert - TE in a Connection: header, so we need to merge the custom provided - Connection: header and prevent the original to get sent. Note that if - the user has inserted his/hers own TE: header we don't do this magic - but then assume that the user will handle it all! */ - char *cptr = Curl_checkheaders(data, "Connection:"); -#define TE_HEADER "TE: gzip\r\n" - - Curl_safefree(conn->allocptr.te); - - /* Create the (updated) Connection: header */ - conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr): - strdup("Connection: TE\r\n" TE_HEADER); - - if(!conn->allocptr.te) - return CURLE_OUT_OF_MEMORY; - } -#endif - - ptr = Curl_checkheaders(data, "Transfer-Encoding:"); - if(ptr) { - /* Some kind of TE is requested, check if 'chunked' is chosen */ - data->req.upload_chunky = - Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); - } - else { - if((conn->handler->protocol&CURLPROTO_HTTP) && - data->set.upload && - (data->set.infilesize == -1)) { - if(conn->bits.authneg) - /* don't enable chunked during auth neg */ - ; - else if(use_http_1_1(data, conn)) { - /* HTTP, upload, unknown file size and not HTTP 1.0 */ - data->req.upload_chunky = TRUE; - } - else { - failf(data, "Chunky upload is not supported by HTTP 1.0"); - return CURLE_UPLOAD_FAILED; - } - } - else { - /* else, no chunky upload */ - data->req.upload_chunky = FALSE; - } - - if(data->req.upload_chunky) - te = "Transfer-Encoding: chunked\r\n"; - } - - Curl_safefree(conn->allocptr.host); - - ptr = Curl_checkheaders(data, "Host:"); - if(ptr && (!data->state.this_is_a_follow || - Curl_raw_equal(data->state.first_host, conn->host.name))) { -#if !defined(CURL_DISABLE_COOKIES) - /* If we have a given custom Host: header, we extract the host name in - order to possibly use it for cookie reasons later on. We only allow the - custom Host: header if this is NOT a redirect, as setting Host: in the - redirected request is being out on thin ice. Except if the host name - is the same as the first one! */ - char *cookiehost = Curl_copy_header_value(ptr); - if (!cookiehost) - return CURLE_OUT_OF_MEMORY; - if (!*cookiehost) - /* ignore empty data */ - free(cookiehost); - else { - char *colon = strchr(cookiehost, ':'); - if (colon) - *colon = 0; /* The host must not include an embedded port number */ - Curl_safefree(conn->allocptr.cookiehost); - conn->allocptr.cookiehost = cookiehost; - } -#endif - - conn->allocptr.host = NULL; - } - else { - /* When building Host: headers, we must put the host name within - [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ - - if(((conn->given->protocol&CURLPROTO_HTTPS) && - (conn->remote_port == PORT_HTTPS)) || - ((conn->given->protocol&CURLPROTO_HTTP) && - (conn->remote_port == PORT_HTTP)) ) - /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include - the port number in the host string */ - conn->allocptr.host = aprintf("Host: %s%s%s\r\n", - conn->bits.ipv6_ip?"[":"", - host, - conn->bits.ipv6_ip?"]":""); - else - conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n", - conn->bits.ipv6_ip?"[":"", - host, - conn->bits.ipv6_ip?"]":"", - conn->remote_port); - - if(!conn->allocptr.host) - /* without Host: we can't make a nice request */ - return CURLE_OUT_OF_MEMORY; - } - -#ifndef CURL_DISABLE_PROXY - if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) { - /* Using a proxy but does not tunnel through it */ - - /* The path sent to the proxy is in fact the entire URL. But if the remote - host is a IDN-name, we must make sure that the request we produce only - uses the encoded host name! */ - if(conn->host.dispname != conn->host.name) { - char *url = data->change.url; - ptr = strstr(url, conn->host.dispname); - if(ptr) { - /* This is where the display name starts in the URL, now replace this - part with the encoded name. TODO: This method of replacing the host - name is rather crude as I believe there's a slight risk that the - user has entered a user name or password that contain the host name - string. */ - size_t currlen = strlen(conn->host.dispname); - size_t newlen = strlen(conn->host.name); - size_t urllen = strlen(url); - - char *newurl; - - newurl = malloc(urllen + newlen - currlen + 1); - if(newurl) { - /* copy the part before the host name */ - memcpy(newurl, url, ptr - url); - /* append the new host name instead of the old */ - memcpy(newurl + (ptr - url), conn->host.name, newlen); - /* append the piece after the host name */ - memcpy(newurl + newlen + (ptr - url), - ptr + currlen, /* copy the trailing zero byte too */ - urllen - (ptr-url) - currlen + 1); - if(data->change.url_alloc) - free(data->change.url); - data->change.url = newurl; - data->change.url_alloc = TRUE; - } - else - return CURLE_OUT_OF_MEMORY; - } - } - ppath = data->change.url; - if(checkprefix("ftp://", ppath)) { - if (data->set.proxy_transfer_mode) { - /* when doing ftp, append ;type= if not present */ - char *type = strstr(ppath, ";type="); - if(type && type[6] && type[7] == 0) { - switch (Curl_raw_toupper(type[6])) { - case 'A': - case 'D': - case 'I': - break; - default: - type = NULL; - } - } - if(!type) { - char *p = ftp_typecode; - /* avoid sending invalid URLs like ftp://example.com;type=i if the - * user specified ftp://example.com without the slash */ - if (!*data->state.path && ppath[strlen(ppath) - 1] != '/') { - *p++ = '/'; - } - snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c", - data->set.prefer_ascii ? 'a' : 'i'); - } - } - if (conn->bits.user_passwd && !conn->bits.userpwd_in_url) - paste_ftp_userpwd = TRUE; - } - } -#endif /* CURL_DISABLE_PROXY */ - - if(HTTPREQ_POST_FORM == httpreq) { - /* we must build the whole post sequence first, so that we have a size of - the whole transfer before we start to send it */ - result = Curl_getformdata(data, &http->sendit, data->set.httppost, - Curl_checkheaders(data, "Content-Type:"), - &http->postsize); - if(result) - return result; - } - - http->p_accept = Curl_checkheaders(data, "Accept:")?NULL:"Accept: */*\r\n"; - - if(( (HTTPREQ_POST == httpreq) || - (HTTPREQ_POST_FORM == httpreq) || - (HTTPREQ_PUT == httpreq) ) && - data->state.resume_from) { - /********************************************************************** - * Resuming upload in HTTP means that we PUT or POST and that we have - * got a resume_from value set. The resume value has already created - * a Range: header that will be passed along. We need to "fast forward" - * the file the given number of bytes and decrease the assume upload - * file size before we continue this venture in the dark lands of HTTP. - *********************************************************************/ - - if(data->state.resume_from < 0 ) { - /* - * This is meant to get the size of the present remote-file by itself. - * We don't support this now. Bail out! - */ - data->state.resume_from = 0; - } - - if(data->state.resume_from && !data->state.this_is_a_follow) { - /* do we still game? */ - - /* Now, let's read off the proper amount of bytes from the - input. */ - if(conn->seek_func) { - seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, - SEEK_SET); - } - - if(seekerr != CURL_SEEKFUNC_OK) { - if(seekerr != CURL_SEEKFUNC_CANTSEEK) { - failf(data, "Could not seek stream"); - return CURLE_READ_ERROR; - } - /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ - else { - curl_off_t passed=0; - do { - size_t readthisamountnow = - (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? - BUFSIZE : curlx_sotouz(data->state.resume_from - passed); - - size_t actuallyread = - data->set.fread_func(data->state.buffer, 1, readthisamountnow, - data->set.in); - - passed += actuallyread; - if((actuallyread == 0) || (actuallyread > readthisamountnow)) { - /* this checks for greater-than only to make sure that the - CURL_READFUNC_ABORT return code still aborts */ - failf(data, "Could only read %" FORMAT_OFF_T - " bytes from the input", - passed); - return CURLE_READ_ERROR; - } - } while(passed < data->state.resume_from); - } - } - - /* now, decrease the size of the read */ - if(data->set.infilesize>0) { - data->set.infilesize -= data->state.resume_from; - - if(data->set.infilesize <= 0) { - failf(data, "File already completely uploaded"); - return CURLE_PARTIAL_FILE; - } - } - /* we've passed, proceed as normal */ - } - } - if(data->state.use_range) { - /* - * A range is selected. We use different headers whether we're downloading - * or uploading and we always let customized headers override our internal - * ones if any such are specified. - */ - if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && - !Curl_checkheaders(data, "Range:")) { - /* if a line like this was already allocated, free the previous one */ - if(conn->allocptr.rangeline) - free(conn->allocptr.rangeline); - conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", - data->state.range); - } - else if((httpreq != HTTPREQ_GET) && - !Curl_checkheaders(data, "Content-Range:")) { - - /* if a line like this was already allocated, free the previous one */ - if(conn->allocptr.rangeline) - free(conn->allocptr.rangeline); - - if(data->set.set_resume_from < 0) { - /* Upload resume was asked for, but we don't know the size of the - remote part so we tell the server (and act accordingly) that we - upload the whole file (again) */ - conn->allocptr.rangeline = - aprintf("Content-Range: bytes 0-%" FORMAT_OFF_T - "/%" FORMAT_OFF_T "\r\n", - data->set.infilesize - 1, data->set.infilesize); - - } - else if(data->state.resume_from) { - /* This is because "resume" was selected */ - curl_off_t total_expected_size= - data->state.resume_from + data->set.infilesize; - conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s%" FORMAT_OFF_T - "/%" FORMAT_OFF_T "\r\n", - data->state.range, total_expected_size-1, - total_expected_size); - } - else { - /* Range was selected and then we just pass the incoming range and - append total size */ - conn->allocptr.rangeline = - aprintf("Content-Range: bytes %s/%" FORMAT_OFF_T "\r\n", - data->state.range, data->set.infilesize); - } - if(!conn->allocptr.rangeline) - return CURLE_OUT_OF_MEMORY; - } - } - - /* Use 1.1 unless the user specifically asked for 1.0 or the server only - supports 1.0 */ - httpstring= use_http_1_1(data, conn)?"1.1":"1.0"; - - /* initialize a dynamic send-buffer */ - req_buffer = Curl_add_buffer_init(); - - if(!req_buffer) - return CURLE_OUT_OF_MEMORY; - - /* add the main request stuff */ - /* GET/HEAD/POST/PUT */ - result = Curl_add_bufferf(req_buffer, "%s ", request); - if (result) - return result; - - /* url */ - if (paste_ftp_userpwd) - result = Curl_add_bufferf(req_buffer, "ftp://%s:%s@%s", - conn->user, conn->passwd, - ppath + sizeof("ftp://") - 1); - else - result = Curl_add_buffer(req_buffer, ppath, strlen(ppath)); - if (result) - return result; - - result = Curl_add_bufferf(req_buffer, - "%s" /* ftp typecode (;type=x) */ - " HTTP/%s\r\n" /* HTTP version */ - "%s" /* proxyuserpwd */ - "%s" /* userpwd */ - "%s" /* range */ - "%s" /* user agent */ - "%s" /* host */ - "%s" /* accept */ - "%s" /* TE: */ - "%s" /* accept-encoding */ - "%s" /* referer */ - "%s" /* Proxy-Connection */ - "%s",/* transfer-encoding */ - - ftp_typecode, - httpstring, - conn->allocptr.proxyuserpwd? - conn->allocptr.proxyuserpwd:"", - conn->allocptr.userpwd?conn->allocptr.userpwd:"", - (data->state.use_range && conn->allocptr.rangeline)? - conn->allocptr.rangeline:"", - (data->set.str[STRING_USERAGENT] && - *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)? - conn->allocptr.uagent:"", - (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */ - http->p_accept?http->p_accept:"", - conn->allocptr.te?conn->allocptr.te:"", - (data->set.str[STRING_ENCODING] && - *data->set.str[STRING_ENCODING] && - conn->allocptr.accept_encoding)? - conn->allocptr.accept_encoding:"", - (data->change.referer && conn->allocptr.ref)? - conn->allocptr.ref:"" /* Referer: */, - (conn->bits.httpproxy && - !conn->bits.tunnel_proxy && - !Curl_checkheaders(data, "Proxy-Connection:"))? - "Proxy-Connection: Keep-Alive\r\n":"", - te - ); - - /* - * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM - * with basic and digest, it will be freed anyway by the next request - */ - - Curl_safefree (conn->allocptr.userpwd); - conn->allocptr.userpwd = NULL; - - if(result) - return result; - -#if !defined(CURL_DISABLE_COOKIES) - if(data->cookies || addcookies) { - struct Cookie *co=NULL; /* no cookies from start */ - int count=0; - - if(data->cookies) { - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - co = Curl_cookie_getlist(data->cookies, - conn->allocptr.cookiehost? - conn->allocptr.cookiehost:host, - data->state.path, - (bool)(conn->handler->protocol&CURLPROTO_HTTPS? - TRUE:FALSE)); - Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); - } - if(co) { - struct Cookie *store=co; - /* now loop through all cookies that matched */ - while(co) { - if(co->value) { - if(0 == count) { - result = Curl_add_bufferf(req_buffer, "Cookie: "); - if(result) - break; - } - result = Curl_add_bufferf(req_buffer, - "%s%s=%s", count?"; ":"", - co->name, co->value); - if(result) - break; - count++; - } - co = co->next; /* next cookie please */ - } - Curl_cookie_freelist(store, FALSE); /* free the cookie list */ - } - if(addcookies && (CURLE_OK == result)) { - if(!count) - result = Curl_add_bufferf(req_buffer, "Cookie: "); - if(CURLE_OK == result) { - result = Curl_add_bufferf(req_buffer, "%s%s", - count?"; ":"", - addcookies); - count++; - } - } - if(count && (CURLE_OK == result)) - result = Curl_add_buffer(req_buffer, "\r\n", 2); - - if(result) - return result; - } -#endif - - if(data->set.timecondition) { - result = Curl_add_timecondition(data, req_buffer); - if(result) - return result; - } - - result = Curl_add_custom_headers(conn, req_buffer); - if(result) - return result; - - http->postdata = NULL; /* nothing to post at this point */ - Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */ - - /* If 'authdone' is FALSE, we must not set the write socket index to the - Curl_transfer() call below, as we're not ready to actually upload any - data yet. */ - - switch(httpreq) { - - case HTTPREQ_POST_FORM: - if(!http->sendit || conn->bits.authneg) { - /* nothing to post! */ - result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n"); - if(result) - return result; - - result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); - if(result) - failf(data, "Failed sending POST request"); - else - /* setup variables for the upcoming transfer */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - -1, NULL); - break; - } - - if(Curl_FormInit(&http->form, http->sendit)) { - failf(data, "Internal HTTP POST error!"); - return CURLE_HTTP_POST_ERROR; - } - - /* Get the currently set callback function pointer and store that in the - form struct since we might want the actual user-provided callback later - on. The conn->fread_func pointer itself will be changed for the - multipart case to the function that returns a multipart formatted - stream. */ - http->form.fread_func = conn->fread_func; - - /* Set the read function to read from the generated form data */ - conn->fread_func = (curl_read_callback)Curl_FormReader; - conn->fread_in = &http->form; - - http->sending = HTTPSEND_BODY; - - if(!data->req.upload_chunky) { - /* only add Content-Length if not uploading chunked */ - result = Curl_add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T "\r\n", - http->postsize); - if(result) - return result; - } - - result = expect100(data, conn, req_buffer); - if(result) - return result; - - { - - /* Get Content-Type: line from Curl_formpostheader. - */ - char *contentType; - size_t linelength=0; - contentType = Curl_formpostheader((void *)&http->form, - &linelength); - if(!contentType) { - failf(data, "Could not get Content-Type header line!"); - return CURLE_HTTP_POST_ERROR; - } - - result = Curl_add_buffer(req_buffer, contentType, linelength); - if(result) - return result; - } - - /* make the request end in a true CRLF */ - result = Curl_add_buffer(req_buffer, "\r\n", 2); - if(result) - return result; - - /* set upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, http->postsize); - - /* fire away the whole request to the server */ - result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); - if(result) - failf(data, "Failed sending POST request"); - else - /* setup variables for the upcoming transfer */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, FIRSTSOCKET, - &http->writebytecount); - - if(result) { - Curl_formclean(&http->sendit); /* free that whole lot */ - return result; - } - - /* convert the form data */ - result = Curl_convert_form(data, http->sendit); - if(result) { - Curl_formclean(&http->sendit); /* free that whole lot */ - return result; - } - - break; - - case HTTPREQ_PUT: /* Let's PUT the data to the server! */ - - if(conn->bits.authneg) - postsize = 0; - else - postsize = data->set.infilesize; - - if((postsize != -1) && !data->req.upload_chunky) { - /* only add Content-Length if not uploading chunked */ - result = Curl_add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T "\r\n", - postsize ); - if(result) - return result; - } - - result = expect100(data, conn, req_buffer); - if(result) - return result; - - result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */ - if(result) - return result; - - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, postsize); - - /* this sends the buffer and frees all the buffer resources */ - result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); - if(result) - failf(data, "Failed sending PUT request"); - else - /* prepare for transfer */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, postsize?FIRSTSOCKET:-1, - postsize?&http->writebytecount:NULL); - if(result) - return result; - break; - - case HTTPREQ_POST: - /* this is the simple POST, using x-www-form-urlencoded style */ - - if(conn->bits.authneg) - postsize = 0; - else { - /* figure out the size of the postfields */ - postsize = (data->set.postfieldsize != -1)? - data->set.postfieldsize: - (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1); - } - if(!data->req.upload_chunky) { - /* We only set Content-Length and allow a custom Content-Length if - we don't upload data chunked, as RFC2616 forbids us to set both - kinds of headers (Transfer-Encoding: chunked and Content-Length) */ - - if(conn->bits.authneg || !Curl_checkheaders(data, "Content-Length:")) { - /* we allow replacing this header if not during auth negotiation, - although it isn't very wise to actually set your own */ - result = Curl_add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T"\r\n", - postsize); - if(result) - return result; - } - } - - if(!Curl_checkheaders(data, "Content-Type:")) { - result = Curl_add_bufferf(req_buffer, - "Content-Type: application/" - "x-www-form-urlencoded\r\n"); - if(result) - return result; - } - - /* For really small posts we don't use Expect: headers at all, and for - the somewhat bigger ones we allow the app to disable it. Just make - sure that the expect100header is always set to the preferred value - here. */ - ptr = Curl_checkheaders(data, "Expect:"); - if(ptr) { - data->state.expect100header = - Curl_compareheader(ptr, "Expect:", "100-continue"); - } - else if(postsize > TINY_INITIAL_POST_SIZE || postsize < 0) { - result = expect100(data, conn, req_buffer); - if(result) - return result; - } - else - data->state.expect100header = FALSE; - - if(data->set.postfields) { - - if(!data->state.expect100header && - (postsize < MAX_INITIAL_POST_SIZE)) { - /* if we don't use expect: 100 AND - postsize is less than MAX_INITIAL_POST_SIZE - - then append the post data to the HTTP request header. This limit - is no magic limit but only set to prevent really huge POSTs to - get the data duplicated with malloc() and family. */ - - result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ - if(result) - return result; - - if(!data->req.upload_chunky) { - /* We're not sending it 'chunked', append it to the request - already now to reduce the number if send() calls */ - result = Curl_add_buffer(req_buffer, data->set.postfields, - (size_t)postsize); - included_body = postsize; - } - else { - /* Append the POST data chunky-style */ - result = Curl_add_bufferf(req_buffer, "%x\r\n", (int)postsize); - if(CURLE_OK == result) - result = Curl_add_buffer(req_buffer, data->set.postfields, - (size_t)postsize); - if(CURLE_OK == result) - result = Curl_add_buffer(req_buffer, - "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); - /* CR LF 0 CR LF CR LF */ - included_body = postsize + 7; - } - if(result) - return result; - /* Make sure the progress information is accurate */ - Curl_pgrsSetUploadSize(data, postsize); - } - else { - /* A huge POST coming up, do data separate from the request */ - http->postsize = postsize; - http->postdata = data->set.postfields; - - http->sending = HTTPSEND_BODY; - - conn->fread_func = (curl_read_callback)readmoredata; - conn->fread_in = (void *)conn; - - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, http->postsize); - - result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ - if(result) - return result; - } - } - else { - result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ - if(result) - return result; - - if(data->req.upload_chunky && conn->bits.authneg) { - /* Chunky upload is selected and we're negotiating auth still, send - end-of-data only */ - result = Curl_add_buffer(req_buffer, - "\x0d\x0a\x30\x0d\x0a\x0d\x0a", 7); - /* CR LF 0 CR LF CR LF */ - if(result) - return result; - } - - else if(data->set.postfieldsize) { - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, postsize?postsize:-1); - - /* set the pointer to mark that we will send the post body using the - read callback, but only if we're not in authenticate - negotiation */ - if(!conn->bits.authneg) { - http->postdata = (char *)&http->postdata; - http->postsize = postsize; - } - } - } - /* issue the request */ - result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, - (size_t)included_body, FIRSTSOCKET); - - if(result) - failf(data, "Failed sending HTTP POST request"); - else - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); - break; - - default: - result = Curl_add_buffer(req_buffer, "\r\n", 2); - if(result) - return result; - - /* issue the request */ - result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); - - if(result) - failf(data, "Failed sending HTTP request"); - else - /* HTTP GET/HEAD download: */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); - } - if(result) - return result; - - if(http->writebytecount) { - /* if a request-body has been sent off, we make sure this progress is noted - properly */ - Curl_pgrsSetUploadCounter(data, http->writebytecount); - if(Curl_pgrsUpdate(conn)) - result = CURLE_ABORTED_BY_CALLBACK; - } - - return result; -} - -/* - * checkhttpprefix() - * - * Returns TRUE if member of the list matches prefix of string - */ -static bool -checkhttpprefix(struct SessionHandle *data, - const char *s) -{ - struct curl_slist *head = data->set.http200aliases; - bool rc = FALSE; -#ifdef CURL_DOES_CONVERSIONS - /* convert from the network encoding using a scratch area */ - char *scratch = strdup(s); - if(NULL == scratch) { - failf (data, "Failed to allocate memory for conversion!"); - return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ - } - if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { - /* Curl_convert_from_network calls failf if unsuccessful */ - free(scratch); - return FALSE; /* can't return CURLE_foobar so return FALSE */ - } - s = scratch; -#endif /* CURL_DOES_CONVERSIONS */ - - while(head) { - if(checkprefix(head->data, s)) { - rc = TRUE; - break; - } - head = head->next; - } - - if((rc != TRUE) && (checkprefix("HTTP/", s))) - rc = TRUE; - -#ifdef CURL_DOES_CONVERSIONS - free(scratch); -#endif /* CURL_DOES_CONVERSIONS */ - return rc; -} - -#ifndef CURL_DISABLE_RTSP -static bool -checkrtspprefix(struct SessionHandle *data, - const char *s) -{ - -#ifdef CURL_DOES_CONVERSIONS - /* convert from the network encoding using a scratch area */ - char *scratch = strdup(s); - if(NULL == scratch) { - failf (data, "Failed to allocate memory for conversion!"); - return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ - } - if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { - /* Curl_convert_from_network calls failf if unsuccessful */ - free(scratch); - return FALSE; /* can't return CURLE_foobar so return FALSE */ - } - s = scratch; -#else - (void)data; /* unused */ -#endif /* CURL_DOES_CONVERSIONS */ - if(checkprefix("RTSP/", s)) - return TRUE; - else - return FALSE; -} -#endif /* CURL_DISABLE_RTSP */ - -static bool -checkprotoprefix(struct SessionHandle *data, struct connectdata *conn, - const char *s) -{ -#ifndef CURL_DISABLE_RTSP - if(conn->handler->protocol & CURLPROTO_RTSP) - return checkrtspprefix(data, s); -#else - (void)conn; -#endif /* CURL_DISABLE_RTSP */ - - return checkhttpprefix(data, s); -} - -/* - * header_append() copies a chunk of data to the end of the already received - * header. We make sure that the full string fit in the allocated header - * buffer, or else we enlarge it. - */ -static CURLcode header_append(struct SessionHandle *data, - struct SingleRequest *k, - size_t length) -{ - if(k->hbuflen + length >= data->state.headersize) { - /* We enlarge the header buffer as it is too small */ - char *newbuff; - size_t hbufp_index; - size_t newsize; - - if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) { - /* The reason to have a max limit for this is to avoid the risk of a bad - server feeding libcurl with a never-ending header that will cause - reallocs infinitely */ - failf (data, "Avoided giant realloc for header (max is %d)!", - CURL_MAX_HTTP_HEADER); - return CURLE_OUT_OF_MEMORY; - } - - newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2); - hbufp_index = k->hbufp - data->state.headerbuff; - newbuff = realloc(data->state.headerbuff, newsize); - if(!newbuff) { - failf (data, "Failed to alloc memory for big header!"); - return CURLE_OUT_OF_MEMORY; - } - data->state.headersize=newsize; - data->state.headerbuff = newbuff; - k->hbufp = data->state.headerbuff + hbufp_index; - } - memcpy(k->hbufp, k->str_start, length); - k->hbufp += length; - k->hbuflen += length; - *k->hbufp = 0; - - return CURLE_OK; -} - - -/* - * Read any HTTP header lines from the server and pass them to the client app. - */ -CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, - struct connectdata *conn, - ssize_t *nread, - bool *stop_reading) -{ - CURLcode result; - struct SingleRequest *k = &data->req; - - /* header line within buffer loop */ - do { - size_t rest_length; - size_t full_length; - int writetype; - - /* str_start is start of line within buf */ - k->str_start = k->str; - - /* data is in network encoding so use 0x0a instead of '\n' */ - k->end_ptr = memchr(k->str_start, 0x0a, *nread); - - if(!k->end_ptr) { - /* Not a complete header line within buffer, append the data to - the end of the headerbuff. */ - result = header_append(data, k, *nread); - if(result) - return result; - - if(!k->headerline && (k->hbuflen>5)) { - /* make a first check that this looks like a protocol header */ - if(!checkprotoprefix(data, conn, data->state.headerbuff)) { - /* this is not the beginning of a protocol first header line */ - k->header = FALSE; - k->badheader = HEADER_ALLBAD; - break; - } - } - - break; /* read more and try again */ - } - - /* decrease the size of the remaining (supposed) header line */ - rest_length = (k->end_ptr - k->str)+1; - *nread -= (ssize_t)rest_length; - - k->str = k->end_ptr + 1; /* move past new line */ - - full_length = k->str - k->str_start; - - result = header_append(data, k, full_length); - if(result) - return result; - - k->end_ptr = k->hbufp; - k->p = data->state.headerbuff; - - /**** - * We now have a FULL header line that p points to - *****/ - - if(!k->headerline) { - /* the first read header */ - if((k->hbuflen>5) && - !checkprotoprefix(data, conn, data->state.headerbuff)) { - /* this is not the beginning of a protocol first header line */ - k->header = FALSE; - if(*nread) - /* since there's more, this is a partial bad header */ - k->badheader = HEADER_PARTHEADER; - else { - /* this was all we read so it's all a bad header */ - k->badheader = HEADER_ALLBAD; - *nread = (ssize_t)rest_length; - } - break; - } - } - - /* headers are in network encoding so - use 0x0a and 0x0d instead of '\n' and '\r' */ - if((0x0a == *k->p) || (0x0d == *k->p)) { - size_t headerlen; - /* Zero-length header line means end of headers! */ - -#ifdef CURL_DOES_CONVERSIONS - if(0x0d == *k->p) { - *k->p = '\r'; /* replace with CR in host encoding */ - k->p++; /* pass the CR byte */ - } - if(0x0a == *k->p) { - *k->p = '\n'; /* replace with LF in host encoding */ - k->p++; /* pass the LF byte */ - } -#else - if('\r' == *k->p) - k->p++; /* pass the \r byte */ - if('\n' == *k->p) - k->p++; /* pass the \n byte */ -#endif /* CURL_DOES_CONVERSIONS */ - - if(100 <= k->httpcode && 199 >= k->httpcode) { - /* - * We have made a HTTP PUT or POST and this is 1.1-lingo - * that tells us that the server is OK with this and ready - * to receive the data. - * However, we'll get more headers now so we must get - * back into the header-parsing state! - */ - k->header = TRUE; - k->headerline = 0; /* restart the header line counter */ - - /* if we did wait for this do enable write now! */ - if(k->exp100) { - k->exp100 = EXP100_SEND_DATA; - k->keepon |= KEEP_SEND; - } - } - else { - k->header = FALSE; /* no more header to parse! */ - - if((k->size == -1) && !k->chunk && !conn->bits.close && - (conn->httpversion >= 11) && - !(conn->handler->protocol & CURLPROTO_RTSP)) { - /* On HTTP 1.1, when connection is not to get closed, but no - Content-Length nor Content-Encoding chunked have been - received, according to RFC2616 section 4.4 point 5, we - assume that the server will close the connection to - signal the end of the document. */ - infof(data, "no chunk, no close, no size. Assume close to " - "signal end\n"); - conn->bits.close = TRUE; - } - } - - if(417 == k->httpcode) { - /* - * we got: "417 Expectation Failed" this means: - * we have made a HTTP call and our Expect Header - * seems to cause a problem => abort the write operations - * (or prevent them from starting). - */ - k->exp100 = EXP100_FAILED; - k->keepon &= ~KEEP_SEND; - } - - /* - * When all the headers have been parsed, see if we should give - * up and return an error. - */ - if(Curl_http_should_fail(conn)) { - failf (data, "The requested URL returned error: %d", - k->httpcode); - return CURLE_HTTP_RETURNED_ERROR; - } - - /* now, only output this if the header AND body are requested: - */ - writetype = CLIENTWRITE_HEADER; - if(data->set.include_header) - writetype |= CLIENTWRITE_BODY; - - headerlen = k->p - data->state.headerbuff; - - result = Curl_client_write(conn, writetype, - data->state.headerbuff, - headerlen); - if(result) - return result; - - data->info.header_size += (long)headerlen; - data->req.headerbytecount += (long)headerlen; - - data->req.deductheadercount = - (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0; - - if(!*stop_reading) { - /* Curl_http_auth_act() checks what authentication methods - * that are available and decides which one (if any) to - * use. It will set 'newurl' if an auth method was picked. */ - result = Curl_http_auth_act(conn); - - if(result) - return result; - - if(conn->bits.rewindaftersend) { - /* We rewind after a complete send, so thus we continue - sending now */ - infof(data, "Keep sending data to get tossed away!\n"); - k->keepon |= KEEP_SEND; - } - } - - if(!k->header) { - /* - * really end-of-headers. - * - * If we requested a "no body", this is a good time to get - * out and return home. - */ - if(data->set.opt_no_body) - *stop_reading = TRUE; - else { - /* If we know the expected size of this document, we set the - maximum download size to the size of the expected - document or else, we won't know when to stop reading! - - Note that we set the download maximum even if we read a - "Connection: close" header, to make sure that - "Content-Length: 0" still prevents us from attempting to - read the (missing) response-body. - */ - /* According to RFC2616 section 4.4, we MUST ignore - Content-Length: headers if we are now receiving data - using chunked Transfer-Encoding. - */ - if(k->chunk) - k->maxdownload = k->size = -1; - } - if(-1 != k->size) { - /* We do this operation even if no_body is true, since this - data might be retrieved later with curl_easy_getinfo() - and its CURLINFO_CONTENT_LENGTH_DOWNLOAD option. */ - - Curl_pgrsSetDownloadSize(data, k->size); - k->maxdownload = k->size; - } - - /* If max download size is *zero* (nothing) we already - have nothing and can safely return ok now! */ - if(0 == k->maxdownload) - *stop_reading = TRUE; - - if(*stop_reading) { - /* we make sure that this socket isn't read more now */ - k->keepon &= ~KEEP_RECV; - } - - if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, - k->str_start, headerlen, conn); - break; /* exit header line loop */ - } - - /* We continue reading headers, so reset the line-based - header parsing variables hbufp && hbuflen */ - k->hbufp = data->state.headerbuff; - k->hbuflen = 0; - continue; - } - - /* - * Checks for special headers coming up. - */ - - if(!k->headerline++) { - /* This is the first header, it MUST be the error code line - or else we consider this to be the body right away! */ - int httpversion_major; - int rtspversion_major; - int nc = 0; -#ifdef CURL_DOES_CONVERSIONS -#define HEADER1 scratch -#define SCRATCHSIZE 21 - CURLcode res; - char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */ - /* We can't really convert this yet because we - don't know if it's the 1st header line or the body. - So we do a partial conversion into a scratch area, - leaving the data at k->p as-is. - */ - strncpy(&scratch[0], k->p, SCRATCHSIZE); - scratch[SCRATCHSIZE] = 0; /* null terminate */ - res = Curl_convert_from_network(data, - &scratch[0], - SCRATCHSIZE); - if(res) - /* Curl_convert_from_network calls failf if unsuccessful */ - return res; -#else -#define HEADER1 k->p /* no conversion needed, just use k->p */ -#endif /* CURL_DOES_CONVERSIONS */ - - if(conn->handler->protocol & CURLPROTO_HTTP) { - nc = sscanf(HEADER1, - " HTTP/%d.%d %3d", - &httpversion_major, - &conn->httpversion, - &k->httpcode); - if(nc==3) { - conn->httpversion += 10 * httpversion_major; - } - else { - /* this is the real world, not a Nirvana - NCSA 1.5.x returns this crap when asked for HTTP/1.1 - */ - nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode); - conn->httpversion = 10; - - /* If user has set option HTTP200ALIASES, - compare header line against list of aliases - */ - if(!nc) { - if(checkhttpprefix(data, k->p)) { - nc = 1; - k->httpcode = 200; - conn->httpversion = 10; - } - } - } - } - else if(conn->handler->protocol & CURLPROTO_RTSP) { - nc = sscanf(HEADER1, - " RTSP/%d.%d %3d", - &rtspversion_major, - &conn->rtspversion, - &k->httpcode); - if(nc==3) { - conn->rtspversion += 10 * rtspversion_major; - conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */ - } - else { - /* TODO: do we care about the other cases here? */ - nc = 0; - } - } - - if(nc) { - data->info.httpcode = k->httpcode; - - data->info.httpversion = conn->httpversion; - if (!data->state.httpversion || - data->state.httpversion > conn->httpversion) - /* store the lowest server version we encounter */ - data->state.httpversion = conn->httpversion; - - /* - * This code executes as part of processing the header. As a - * result, it's not totally clear how to interpret the - * response code yet as that depends on what other headers may - * be present. 401 and 407 may be errors, but may be OK - * depending on how authentication is working. Other codes - * are definitely errors, so give up here. - */ - if(data->set.http_fail_on_error && (k->httpcode >= 400) && - ((k->httpcode != 401) || !conn->bits.user_passwd) && - ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) { - - if(data->state.resume_from && - (data->set.httpreq==HTTPREQ_GET) && - (k->httpcode == 416)) { - /* "Requested Range Not Satisfiable", just proceed and - pretend this is no error */ - } - else { - /* serious error, go home! */ - failf (data, "The requested URL returned error: %d", - k->httpcode); - return CURLE_HTTP_RETURNED_ERROR; - } - } - - if(conn->httpversion == 10) { - /* Default action for HTTP/1.0 must be to close, unless - we get one of those fancy headers that tell us the - server keeps it open for us! */ - infof(data, "HTTP 1.0, assume close after body\n"); - conn->bits.close = TRUE; - } - else if(conn->httpversion >= 11 && - !conn->bits.close) { - /* If HTTP version is >= 1.1 and connection is persistent - server supports pipelining. */ - DEBUGF(infof(data, - "HTTP 1.1 or later with persistent connection, " - "pipelining supported\n")); - conn->server_supports_pipelining = TRUE; - } - - switch(k->httpcode) { - case 204: - /* (quote from RFC2616, section 10.2.5): The server has - * fulfilled the request but does not need to return an - * entity-body ... The 204 response MUST NOT include a - * message-body, and thus is always terminated by the first - * empty line after the header fields. */ - /* FALLTHROUGH */ - case 304: - /* (quote from RFC2616, section 10.3.5): The 304 response - * MUST NOT contain a message-body, and thus is always - * terminated by the first empty line after the header - * fields. */ - if(data->set.timecondition) - data->info.timecond = TRUE; - k->size=0; - k->maxdownload=0; - k->ignorecl = TRUE; /* ignore Content-Length headers */ - break; - default: - /* nothing */ - break; - } - } - else { - k->header = FALSE; /* this is not a header line */ - break; - } - } - - result = Curl_convert_from_network(data, k->p, strlen(k->p)); - /* Curl_convert_from_network calls failf if unsuccessful */ - if(result) - return result; - - /* Check for Content-Length: header lines to get size */ - if(!k->ignorecl && !data->set.ignorecl && - checkprefix("Content-Length:", k->p)) { - curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10); - if(data->set.max_filesize && - contentlength > data->set.max_filesize) { - failf(data, "Maximum file size exceeded"); - return CURLE_FILESIZE_EXCEEDED; - } - if(contentlength >= 0) { - k->size = contentlength; - k->maxdownload = k->size; - /* we set the progress download size already at this point - just to make it easier for apps/callbacks to extract this - info as soon as possible */ - Curl_pgrsSetDownloadSize(data, k->size); - } - else { - /* Negative Content-Length is really odd, and we know it - happens for example when older Apache servers send large - files */ - conn->bits.close = TRUE; - infof(data, "Negative content-length: %" FORMAT_OFF_T - ", closing after transfer\n", contentlength); - } - } - /* check for Content-Type: header lines to get the MIME-type */ - else if(checkprefix("Content-Type:", k->p)) { - char *contenttype = Curl_copy_header_value(k->p); - if (!contenttype) - return CURLE_OUT_OF_MEMORY; - if (!*contenttype) - /* ignore empty data */ - free(contenttype); - else { - Curl_safefree(data->info.contenttype); - data->info.contenttype = contenttype; - } - } - else if((conn->httpversion == 10) && - conn->bits.httpproxy && - Curl_compareheader(k->p, - "Proxy-Connection:", "keep-alive")) { - /* - * When a HTTP/1.0 reply comes when using a proxy, the - * 'Proxy-Connection: keep-alive' line tells us the - * connection will be kept alive for our pleasure. - * Default action for 1.0 is to close. - */ - conn->bits.close = FALSE; /* don't close when done */ - infof(data, "HTTP/1.0 proxy connection set to keep alive!\n"); - } - else if((conn->httpversion == 11) && - conn->bits.httpproxy && - Curl_compareheader(k->p, - "Proxy-Connection:", "close")) { - /* - * We get a HTTP/1.1 response from a proxy and it says it'll - * close down after this transfer. - */ - conn->bits.close = TRUE; /* close when done */ - infof(data, "HTTP/1.1 proxy connection set close!\n"); - } - else if((conn->httpversion == 10) && - Curl_compareheader(k->p, "Connection:", "keep-alive")) { - /* - * A HTTP/1.0 reply with the 'Connection: keep-alive' line - * tells us the connection will be kept alive for our - * pleasure. Default action for 1.0 is to close. - * - * [RFC2068, section 19.7.1] */ - conn->bits.close = FALSE; /* don't close when done */ - infof(data, "HTTP/1.0 connection set to keep alive!\n"); - } - else if(Curl_compareheader(k->p, "Connection:", "close")) { - /* - * [RFC 2616, section 8.1.2.1] - * "Connection: close" is HTTP/1.1 language and means that - * the connection will close when this request has been - * served. - */ - conn->bits.close = TRUE; /* close when done */ - } - else if(checkprefix("Transfer-Encoding:", k->p)) { - /* One or more encodings. We check for chunked and/or a compression - algorithm. */ - /* - * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding - * means that the server will send a series of "chunks". Each - * chunk starts with line with info (including size of the - * coming block) (terminated with CRLF), then a block of data - * with the previously mentioned size. There can be any amount - * of chunks, and a chunk-data set to zero signals the - * end-of-chunks. */ - - char *start; - - /* Find the first non-space letter */ - start = k->p + 18; - - do { - /* skip whitespaces and commas */ - while(*start && (ISSPACE(*start) || (*start == ','))) - start++; - - if(checkprefix("chunked", start)) { - k->chunk = TRUE; /* chunks coming our way */ - - /* init our chunky engine */ - Curl_httpchunk_init(conn); - - start += 7; - } - - if(k->auto_decoding) - /* TODO: we only support the first mentioned compression for now */ - break; - - if(checkprefix("identity", start)) { - k->auto_decoding = IDENTITY; - start += 8; - } - else if(checkprefix("deflate", start)) { - k->auto_decoding = DEFLATE; - start += 7; - } - else if(checkprefix("gzip", start)) { - k->auto_decoding = GZIP; - start += 4; - } - else if(checkprefix("x-gzip", start)) { - k->auto_decoding = GZIP; - start += 6; - } - else if(checkprefix("compress", start)) { - k->auto_decoding = COMPRESS; - start += 8; - } - else if(checkprefix("x-compress", start)) { - k->auto_decoding = COMPRESS; - start += 10; - } - else - /* unknown! */ - break; - - } while(1); - - } - else if(checkprefix("Content-Encoding:", k->p) && - data->set.str[STRING_ENCODING]) { - /* - * Process Content-Encoding. Look for the values: identity, - * gzip, deflate, compress, x-gzip and x-compress. x-gzip and - * x-compress are the same as gzip and compress. (Sec 3.5 RFC - * 2616). zlib cannot handle compress. However, errors are - * handled further down when the response body is processed - */ - char *start; - - /* Find the first non-space letter */ - start = k->p + 17; - while(*start && ISSPACE(*start)) - start++; - - /* Record the content-encoding for later use */ - if(checkprefix("identity", start)) - k->auto_decoding = IDENTITY; - else if(checkprefix("deflate", start)) - k->auto_decoding = DEFLATE; - else if(checkprefix("gzip", start) - || checkprefix("x-gzip", start)) - k->auto_decoding = GZIP; - else if(checkprefix("compress", start) - || checkprefix("x-compress", start)) - k->auto_decoding = COMPRESS; - } - else if(checkprefix("Content-Range:", k->p)) { - /* Content-Range: bytes [num]- - Content-Range: bytes: [num]- - Content-Range: [num]- - - The second format was added since Sun's webserver - JavaWebServer/1.1.1 obviously sends the header this way! - The third added since some servers use that! - */ - - char *ptr = k->p + 14; - - /* Move forward until first digit */ - while(*ptr && !ISDIGIT(*ptr)) - ptr++; - - k->offset = curlx_strtoofft(ptr, NULL, 10); - - if(data->state.resume_from == k->offset) - /* we asked for a resume and we got it */ - k->content_range = TRUE; - } -#if !defined(CURL_DISABLE_COOKIES) - else if(data->cookies && - checkprefix("Set-Cookie:", k->p)) { - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, - CURL_LOCK_ACCESS_SINGLE); - Curl_cookie_add(data, - data->cookies, TRUE, k->p+11, - /* If there is a custom-set Host: name, use it - here, or else use real peer host name. */ - conn->allocptr.cookiehost? - conn->allocptr.cookiehost:conn->host.name, - data->state.path); - Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); - } -#endif - else if(checkprefix("Last-Modified:", k->p) && - (data->set.timecondition || data->set.get_filetime) ) { - time_t secs=time(NULL); - k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"), - &secs); - if(data->set.get_filetime) - data->info.filetime = (long)k->timeofdoc; - } - else if((checkprefix("WWW-Authenticate:", k->p) && - (401 == k->httpcode)) || - (checkprefix("Proxy-authenticate:", k->p) && - (407 == k->httpcode))) { - result = Curl_http_input_auth(conn, k->httpcode, k->p); - if(result) - return result; - } - else if((k->httpcode >= 300 && k->httpcode < 400) && - checkprefix("Location:", k->p) && - !data->req.location) { - /* this is the URL that the server advises us to use instead */ - char *location = Curl_copy_header_value(k->p); - if (!location) - return CURLE_OUT_OF_MEMORY; - if (!*location) - /* ignore empty data */ - free(location); - else { - data->req.location = location; - - if(data->set.http_follow_location) { - DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->req.location); /* clone */ - if(!data->req.newurl) - return CURLE_OUT_OF_MEMORY; - - /* some cases of POST and PUT etc needs to rewind the data - stream at this point */ - result = Curl_http_perhapsrewind(conn); - if(result) - return result; - } - } - } -#ifndef CURL_DISABLE_RTSP - else if(conn->handler->protocol & CURLPROTO_RTSP) { - result = Curl_rtsp_parseheader(conn, k->p); - if(result) - return result; - } -#endif - /* - * End of header-checks. Write them to the client. - */ - - writetype = CLIENTWRITE_HEADER; - if(data->set.include_header) - writetype |= CLIENTWRITE_BODY; - - if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, - k->p, (size_t)k->hbuflen, conn); - - result = Curl_client_write(conn, writetype, k->p, k->hbuflen); - if(result) - return result; - - data->info.header_size += (long)k->hbuflen; - data->req.headerbytecount += (long)k->hbuflen; - - /* reset hbufp pointer && hbuflen */ - k->hbufp = data->state.headerbuff; - k->hbuflen = 0; - } - while(!*stop_reading && *k->str); /* header line within buffer */ - - /* We might have reached the end of the header part here, but - there might be a non-header part left in the end of the read - buffer. */ - - return CURLE_OK; -} - -#endif /* CURL_DISABLE_HTTP */ diff --git a/third_party/curl/lib/http.h b/third_party/curl/lib/http.h deleted file mode 100644 index fab2bfd25..000000000 --- a/third_party/curl/lib/http.h +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef __HTTP_H -#define __HTTP_H - -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#ifndef CURL_DISABLE_HTTP - -extern const struct Curl_handler Curl_handler_http; - -#ifdef USE_SSL -extern const struct Curl_handler Curl_handler_https; -#endif - -bool Curl_compareheader(const char *headerline, /* line to check */ - const char *header, /* header keyword _with_ colon */ - const char *content); /* content string to find */ - -char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader); - -char *Curl_copy_header_value(const char *h); - - -/* ------------------------------------------------------------------------- */ -/* - * The add_buffer series of functions are used to build one large memory chunk - * from repeated function invokes. Used so that the entire HTTP request can - * be sent in one go. - */ -struct Curl_send_buffer { - char *buffer; - size_t size_max; - size_t size_used; -}; -typedef struct Curl_send_buffer Curl_send_buffer; - -Curl_send_buffer *Curl_add_buffer_init(void); -CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...); -CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size); -CURLcode Curl_add_buffer_send(Curl_send_buffer *in, - struct connectdata *conn, - long *bytes_written, - size_t included_body_bytes, - int socketindex); - -CURLcode Curl_add_timecondition(struct SessionHandle *data, - Curl_send_buffer *buf); -CURLcode Curl_add_custom_headers(struct connectdata *conn, - Curl_send_buffer *req_buffer); - -/* protocol-specific functions set up to be called by the main engine */ -CURLcode Curl_http(struct connectdata *conn, bool *done); -CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); -CURLcode Curl_http_connect(struct connectdata *conn, bool *done); - -/* The following functions are defined in http_chunks.c */ -void Curl_httpchunk_init(struct connectdata *conn); -CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, - ssize_t length, ssize_t *wrote); - -/* These functions are in http.c */ -void Curl_http_auth_stage(struct SessionHandle *data, int stage); -CURLcode Curl_http_input_auth(struct connectdata *conn, - int httpcode, const char *header); -CURLcode Curl_http_auth_act(struct connectdata *conn); -CURLcode Curl_http_perhapsrewind(struct connectdata *conn); - -int Curl_http_should_fail(struct connectdata *conn); - -/* If only the PICKNONE bit is set, there has been a round-trip and we - selected to use no auth at all. Ie, we actively select no auth, as opposed - to not having one selected. The other CURLAUTH_* defines are present in the - public curl/curl.h header. */ -#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */ - -/* MAX_INITIAL_POST_SIZE indicates the number of bytes that will make the POST - data get included in the initial data chunk sent to the server. If the - data is larger than this, it will automatically get split up in multiple - system calls. - - This value used to be fairly big (100K), but we must take into account that - if the server rejects the POST due for authentication reasons, this data - will always be uncondtionally sent and thus it may not be larger than can - always be afforded to send twice. - - It must not be greater than 64K to work on VMS. -*/ -#ifndef MAX_INITIAL_POST_SIZE -#define MAX_INITIAL_POST_SIZE (64*1024) -#endif - -#ifndef TINY_INITIAL_POST_SIZE -#define TINY_INITIAL_POST_SIZE 1024 -#endif - -#endif /* CURL_DISABLE_HTTP */ - -/**************************************************************************** - * HTTP unique setup - ***************************************************************************/ -struct HTTP { - struct FormData *sendit; - curl_off_t postsize; /* off_t to handle large file sizes */ - const char *postdata; - - const char *p_pragma; /* Pragma: string */ - const char *p_accept; /* Accept: string */ - curl_off_t readbytecount; - curl_off_t writebytecount; - - /* For FORM posting */ - struct Form form; - - struct back { - curl_read_callback fread_func; /* backup storage for fread pointer */ - void *fread_in; /* backup storage for fread_in pointer */ - const char *postdata; - curl_off_t postsize; - } backup; - - enum { - HTTPSEND_NADA, /* init */ - HTTPSEND_REQUEST, /* sending a request */ - HTTPSEND_BODY, /* sending body */ - HTTPSEND_LAST /* never use this */ - } sending; - - void *send_buffer; /* used if the request couldn't be sent in one chunk, - points to an allocated send_buffer struct */ -}; - -CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, - struct connectdata *conn, - ssize_t *nread, - bool *stop_reading); - -/** - * Curl_http_output_auth() setups the authentication headers for the - * host/proxy and the correct authentication - * method. conn->data->state.authdone is set to TRUE when authentication is - * done. - * - * @param conn all information about the current connection - * @param request pointer to the request keyword - * @param path pointer to the requested path - * @param proxytunnel boolean if this is the request setting up a "proxy - * tunnel" - * - * @returns CURLcode - */ -CURLcode -Curl_http_output_auth(struct connectdata *conn, - const char *request, - const char *path, - bool proxytunnel); /* TRUE if this is the request setting - up the proxy tunnel */ - -#endif diff --git a/third_party/curl/lib/http_chunks.c b/third_party/curl/lib/http_chunks.c deleted file mode 100644 index 821a861f4..000000000 --- a/third_party/curl/lib/http_chunks.c +++ /dev/null @@ -1,402 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef CURL_DISABLE_HTTP -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include - -#include "urldata.h" /* it includes http_chunks.h */ -#include "sendf.h" /* for the client write stuff */ - -#include "content_encoding.h" -#include "http.h" -#include "curl_memory.h" -#include "non-ascii.h" /* for Curl_convert_to_network prototype */ - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -/* - * Chunk format (simplified): - * - * [ chunk extension ] CRLF - * CRLF - * - * Highlights from RFC2616 section 3.6 say: - - The chunked encoding modifies the body of a message in order to - transfer it as a series of chunks, each with its own size indicator, - followed by an OPTIONAL trailer containing entity-header fields. This - allows dynamically produced content to be transferred along with the - information necessary for the recipient to verify that it has - received the full message. - - Chunked-Body = *chunk - last-chunk - trailer - CRLF - - chunk = chunk-size [ chunk-extension ] CRLF - chunk-data CRLF - chunk-size = 1*HEX - last-chunk = 1*("0") [ chunk-extension ] CRLF - - chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) - chunk-ext-name = token - chunk-ext-val = token | quoted-string - chunk-data = chunk-size(OCTET) - trailer = *(entity-header CRLF) - - The chunk-size field is a string of hex digits indicating the size of - the chunk. The chunked encoding is ended by any chunk whose size is - zero, followed by the trailer, which is terminated by an empty line. - - */ - -/* Check for an ASCII hex digit. - We avoid the use of isxdigit to accommodate non-ASCII hosts. */ -static bool Curl_isxdigit(char digit) -{ - return (bool)( (digit >= 0x30 && digit <= 0x39) /* 0-9 */ - || (digit >= 0x41 && digit <= 0x46) /* A-F */ - || (digit >= 0x61 && digit <= 0x66) ); /* a-f */ -} - -void Curl_httpchunk_init(struct connectdata *conn) -{ - struct Curl_chunker *chunk = &conn->chunk; - chunk->hexindex=0; /* start at 0 */ - chunk->dataleft=0; /* no data left yet! */ - chunk->state = CHUNK_HEX; /* we get hex first! */ -} - -/* - * chunk_read() returns a OK for normal operations, or a positive return code - * for errors. STOP means this sequence of chunks is complete. The 'wrote' - * argument is set to tell the caller how many bytes we actually passed to the - * client (for byte-counting and whatever). - * - * The states and the state-machine is further explained in the header file. - * - * This function always uses ASCII hex values to accommodate non-ASCII hosts. - * For example, 0x0d and 0x0a are used instead of '\r' and '\n'. - */ -CHUNKcode Curl_httpchunk_read(struct connectdata *conn, - char *datap, - ssize_t datalen, - ssize_t *wrotep) -{ - CURLcode result=CURLE_OK; - struct SessionHandle *data = conn->data; - struct Curl_chunker *ch = &conn->chunk; - struct SingleRequest *k = &data->req; - size_t piece; - size_t length = (size_t)datalen; - size_t *wrote = (size_t *)wrotep; - - *wrote = 0; /* nothing's written yet */ - - /* the original data is written to the client, but we go on with the - chunk read process, to properly calculate the content length*/ - if(data->set.http_te_skip && !k->ignorebody) { - result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen); - if(result) - return CHUNKE_WRITE_ERROR; - } - - while(length) { - switch(ch->state) { - case CHUNK_HEX: - if(Curl_isxdigit(*datap)) { - if(ch->hexindex < MAXNUM_SIZE) { - ch->hexbuffer[ch->hexindex] = *datap; - datap++; - length--; - ch->hexindex++; - } - else { - return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */ - } - } - else { - if(0 == ch->hexindex) { - /* This is illegal data, we received junk where we expected - a hexadecimal digit. */ - return CHUNKE_ILLEGAL_HEX; - } - /* length and datap are unmodified */ - ch->hexbuffer[ch->hexindex]=0; - - /* convert to host encoding before calling strtoul */ - result = Curl_convert_from_network(conn->data, ch->hexbuffer, - ch->hexindex); - if(result) { - /* Curl_convert_from_network calls failf if unsuccessful */ - /* Treat it as a bad hex character */ - return(CHUNKE_ILLEGAL_HEX); - } - - ch->datasize=strtoul(ch->hexbuffer, NULL, 16); - ch->state = CHUNK_POSTHEX; - } - break; - - case CHUNK_POSTHEX: - /* In this state, we're waiting for CRLF to arrive. We support - this to allow so called chunk-extensions to show up here - before the CRLF comes. */ - if(*datap == 0x0d) - ch->state = CHUNK_CR; - length--; - datap++; - break; - - case CHUNK_CR: - /* waiting for the LF */ - if(*datap == 0x0a) { - /* we're now expecting data to come, unless size was zero! */ - if(0 == ch->datasize) { - ch->state = CHUNK_TRAILER; /* now check for trailers */ - conn->trlPos=0; - } - else { - ch->state = CHUNK_DATA; - } - } - else - /* previously we got a fake CR, go back to CR waiting! */ - ch->state = CHUNK_CR; - datap++; - length--; - break; - - case CHUNK_DATA: - /* we get pure and fine data - - We expect another 'datasize' of data. We have 'length' right now, - it can be more or less than 'datasize'. Get the smallest piece. - */ - piece = (ch->datasize >= length)?length:ch->datasize; - - /* Write the data portion available */ -#ifdef HAVE_LIBZ - switch (conn->data->set.http_ce_skip? - IDENTITY : data->req.auto_decoding) { - case IDENTITY: -#endif - if(!k->ignorebody) { - if( !data->set.http_te_skip ) - result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, - piece); - else - result = CURLE_OK; - } -#ifdef HAVE_LIBZ - break; - - case DEFLATE: - /* update data->req.keep.str to point to the chunk data. */ - data->req.str = datap; - result = Curl_unencode_deflate_write(conn, &data->req, - (ssize_t)piece); - break; - - case GZIP: - /* update data->req.keep.str to point to the chunk data. */ - data->req.str = datap; - result = Curl_unencode_gzip_write(conn, &data->req, - (ssize_t)piece); - break; - - case COMPRESS: - default: - failf (conn->data, - "Unrecognized content encoding type. " - "libcurl understands `identity', `deflate' and `gzip' " - "content encodings."); - return CHUNKE_BAD_ENCODING; - } -#endif - - if(result) - return CHUNKE_WRITE_ERROR; - - *wrote += piece; - - ch->datasize -= piece; /* decrease amount left to expect */ - datap += piece; /* move read pointer forward */ - length -= piece; /* decrease space left in this round */ - - if(0 == ch->datasize) - /* end of data this round, we now expect a trailing CRLF */ - ch->state = CHUNK_POSTCR; - break; - - case CHUNK_POSTCR: - if(*datap == 0x0d) { - ch->state = CHUNK_POSTLF; - datap++; - length--; - } - else - return CHUNKE_BAD_CHUNK; - - break; - - case CHUNK_POSTLF: - if(*datap == 0x0a) { - /* - * The last one before we go back to hex state and start all - * over. - */ - Curl_httpchunk_init(conn); - datap++; - length--; - } - else - return CHUNKE_BAD_CHUNK; - - break; - - case CHUNK_TRAILER: - if(*datap == 0x0d) { - /* this is the end of a trailer, but if the trailer was zero bytes - there was no trailer and we move on */ - - if(conn->trlPos) { - /* we allocate trailer with 3 bytes extra room to fit this */ - conn->trailer[conn->trlPos++]=0x0d; - conn->trailer[conn->trlPos++]=0x0a; - conn->trailer[conn->trlPos]=0; - - /* Convert to host encoding before calling Curl_client_write */ - result = Curl_convert_from_network(conn->data, conn->trailer, - conn->trlPos); - if(result) - /* Curl_convert_from_network calls failf if unsuccessful */ - /* Treat it as a bad chunk */ - return CHUNKE_BAD_CHUNK; - - if(!data->set.http_te_skip) { - result = Curl_client_write(conn, CLIENTWRITE_HEADER, - conn->trailer, conn->trlPos); - if(result) - return CHUNKE_WRITE_ERROR; - } - conn->trlPos=0; - ch->state = CHUNK_TRAILER_CR; - } - else { - /* no trailer, we're on the final CRLF pair */ - ch->state = CHUNK_TRAILER_POSTCR; - break; /* don't advance the pointer */ - } - } - else { - /* conn->trailer is assumed to be freed in url.c on a - connection basis */ - if(conn->trlPos >= conn->trlMax) { - /* we always allocate three extra bytes, just because when the full - header has been received we append CRLF\0 */ - char *ptr; - if(conn->trlMax) { - conn->trlMax *= 2; - ptr = realloc(conn->trailer, conn->trlMax + 3); - } - else { - conn->trlMax=128; - ptr = malloc(conn->trlMax + 3); - } - if(!ptr) - return CHUNKE_OUT_OF_MEMORY; - conn->trailer = ptr; - } - conn->trailer[conn->trlPos++]=*datap; - } - datap++; - length--; - break; - - case CHUNK_TRAILER_CR: - if(*datap == 0x0a) { - ch->state = CHUNK_TRAILER_POSTCR; - datap++; - length--; - } - else - return CHUNKE_BAD_CHUNK; - break; - - case CHUNK_TRAILER_POSTCR: - /* We enter this state when a CR should arrive so we expect to - have to first pass a CR before we wait for LF */ - if(*datap != 0x0d) { - /* not a CR then it must be another header in the trailer */ - ch->state = CHUNK_TRAILER; - break; - } - datap++; - length--; - /* now wait for the final LF */ - ch->state = CHUNK_STOP; - break; - - case CHUNK_STOPCR: - /* Read the final CRLF that ends all chunk bodies */ - - if(*datap == 0x0d) { - ch->state = CHUNK_STOP; - datap++; - length--; - } - else - return CHUNKE_BAD_CHUNK; - break; - - case CHUNK_STOP: - if(*datap == 0x0a) { - length--; - - /* Record the length of any data left in the end of the buffer - even if there's no more chunks to read */ - - ch->dataleft = length; - return CHUNKE_STOP; /* return stop */ - } - else - return CHUNKE_BAD_CHUNK; - - default: - return CHUNKE_STATE_ERROR; - } - } - return CHUNKE_OK; -} -#endif /* CURL_DISABLE_HTTP */ diff --git a/third_party/curl/lib/http_chunks.h b/third_party/curl/lib/http_chunks.h deleted file mode 100644 index 6056e188c..000000000 --- a/third_party/curl/lib/http_chunks.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef __HTTP_CHUNKS_H -#define __HTTP_CHUNKS_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -/* - * The longest possible hexadecimal number we support in a chunked transfer. - * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul() - * to convert it, we "only" support 2^32 bytes chunk data. - */ -#define MAXNUM_SIZE 16 - -typedef enum { - CHUNK_FIRST, /* never use */ - - /* In this we await and buffer all hexadecimal digits until we get one - that isn't a hexadecimal digit. When done, we go POSTHEX */ - CHUNK_HEX, - - /* We have received the hexadecimal digit and we eat all characters until - we get a CRLF pair. When we see a CR we go to the CR state. */ - CHUNK_POSTHEX, - - /* A single CR has been found and we should get a LF right away in this - state or we go back to POSTHEX. When LF is received, we go to DATA. - If the size given was zero, we set state to STOP and return. */ - CHUNK_CR, - - /* We eat the amount of data specified. When done, we move on to the - POST_CR state. */ - CHUNK_DATA, - - /* POSTCR should get a CR and nothing else, then move to POSTLF */ - CHUNK_POSTCR, - - /* POSTLF should get a LF and nothing else, then move back to HEX as the - CRLF combination marks the end of a chunk */ - CHUNK_POSTLF, - - /* Each Chunk body should end with a CRLF. Read a CR and nothing else, - then move to CHUNK_STOP */ - CHUNK_STOPCR, - - /* This is mainly used to really mark that we're out of the game. - NOTE: that there's a 'dataleft' field in the struct that will tell how - many bytes that were not passed to the client in the end of the last - buffer! */ - CHUNK_STOP, - - /* At this point optional trailer headers can be found, unless the next line - is CRLF */ - CHUNK_TRAILER, - - /* A trailer CR has been found - next state is CHUNK_TRAILER_POSTCR. - Next char must be a LF */ - CHUNK_TRAILER_CR, - - /* A trailer LF must be found now, otherwise CHUNKE_BAD_CHUNK will be - signalled If this is an empty trailer CHUNKE_STOP will be signalled. - Otherwise the trailer will be broadcasted via Curl_client_write() and the - next state will be CHUNK_TRAILER */ - CHUNK_TRAILER_POSTCR, - - CHUNK_LAST /* never use */ - -} ChunkyState; - -typedef enum { - CHUNKE_STOP = -1, - CHUNKE_OK = 0, - CHUNKE_TOO_LONG_HEX = 1, - CHUNKE_ILLEGAL_HEX, - CHUNKE_BAD_CHUNK, - CHUNKE_WRITE_ERROR, - CHUNKE_STATE_ERROR, - CHUNKE_BAD_ENCODING, - CHUNKE_OUT_OF_MEMORY, - CHUNKE_LAST -} CHUNKcode; - -struct Curl_chunker { - char hexbuffer[ MAXNUM_SIZE + 1]; - int hexindex; - ChunkyState state; - size_t datasize; - size_t dataleft; /* untouched data amount at the end of the last buffer */ -}; - -#endif diff --git a/third_party/curl/lib/http_digest.c b/third_party/curl/lib/http_digest.c deleted file mode 100644 index 4993a987d..000000000 --- a/third_party/curl/lib/http_digest.c +++ /dev/null @@ -1,580 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include - -#include "urldata.h" -#include "sendf.h" -#include "rawstr.h" -#include "curl_base64.h" -#include "curl_md5.h" -#include "http_digest.h" -#include "strtok.h" -#include "url.h" /* for Curl_safefree() */ -#include "curl_memory.h" -#include "non-ascii.h" /* included for Curl_convert_... prototypes */ - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -#define MAX_VALUE_LENGTH 256 -#define MAX_CONTENT_LENGTH 1024 - -/* - * Return 0 on success and then the buffers are filled in fine. - * - * Non-zero means failure to parse. - */ -static int get_pair(const char *str, char *value, char *content, - const char **endptr) -{ - int c; - bool starts_with_quote = FALSE; - bool escape = FALSE; - - for(c=MAX_VALUE_LENGTH-1; (*str && (*str != '=') && c--); ) - *value++ = *str++; - *value=0; - - if('=' != *str++) - /* eek, no match */ - return 1; - - if('\"' == *str) { - /* this starts with a quote so it must end with one as well! */ - str++; - starts_with_quote = TRUE; - } - - for(c=MAX_CONTENT_LENGTH-1; *str && c--; str++) { - switch(*str) { - case '\\': - if(!escape) { - /* possibly the start of an escaped quote */ - escape = TRUE; - *content++ = '\\'; /* even though this is an escape character, we still - store it as-is in the target buffer */ - continue; - } - break; - case ',': - if(!starts_with_quote) { - /* this signals the end of the content if we didn't get a starting quote - and then we do "sloppy" parsing */ - c=0; /* the end */ - continue; - } - break; - case '\r': - case '\n': - /* end of string */ - c=0; - continue; - case '\"': - if(!escape && starts_with_quote) { - /* end of string */ - c=0; - continue; - } - break; - } - escape = FALSE; - *content++ = *str; - } - *content=0; - - *endptr = str; - - return 0; /* all is fine! */ -} - -/* Test example headers: - -WWW-Authenticate: Digest realm="testrealm", nonce="1053604598" -Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598" - -*/ - -CURLdigest Curl_input_digest(struct connectdata *conn, - bool proxy, - const char *header) /* rest of the *-authenticate: - header */ -{ - char *token = NULL; - char *tmp = NULL; - bool foundAuth = FALSE; - bool foundAuthInt = FALSE; - struct SessionHandle *data=conn->data; - bool before = FALSE; /* got a nonce before */ - struct digestdata *d; - - if(proxy) { - d = &data->state.proxydigest; - } - else { - d = &data->state.digest; - } - - /* skip initial whitespaces */ - while(*header && ISSPACE(*header)) - header++; - - if(checkprefix("Digest", header)) { - header += strlen("Digest"); - - /* If we already have received a nonce, keep that in mind */ - if(d->nonce) - before = TRUE; - - /* clear off any former leftovers and init to defaults */ - Curl_digest_cleanup_one(d); - - for(;;) { - char value[MAX_VALUE_LENGTH]; - char content[MAX_CONTENT_LENGTH]; - - while(*header && ISSPACE(*header)) - header++; - - /* extract a value=content pair */ - if(!get_pair(header, value, content, &header)) { - if(Curl_raw_equal(value, "nonce")) { - d->nonce = strdup(content); - if(!d->nonce) - return CURLDIGEST_NOMEM; - } - else if(Curl_raw_equal(value, "stale")) { - if(Curl_raw_equal(content, "true")) { - d->stale = TRUE; - d->nc = 1; /* we make a new nonce now */ - } - } - else if(Curl_raw_equal(value, "realm")) { - d->realm = strdup(content); - if(!d->realm) - return CURLDIGEST_NOMEM; - } - else if(Curl_raw_equal(value, "opaque")) { - d->opaque = strdup(content); - if(!d->opaque) - return CURLDIGEST_NOMEM; - } - else if(Curl_raw_equal(value, "qop")) { - char *tok_buf; - /* tokenize the list and choose auth if possible, use a temporary - clone of the buffer since strtok_r() ruins it */ - tmp = strdup(content); - if(!tmp) - return CURLDIGEST_NOMEM; - token = strtok_r(tmp, ",", &tok_buf); - while(token != NULL) { - if(Curl_raw_equal(token, "auth")) { - foundAuth = TRUE; - } - else if(Curl_raw_equal(token, "auth-int")) { - foundAuthInt = TRUE; - } - token = strtok_r(NULL, ",", &tok_buf); - } - free(tmp); - /*select only auth o auth-int. Otherwise, ignore*/ - if(foundAuth) { - d->qop = strdup("auth"); - if(!d->qop) - return CURLDIGEST_NOMEM; - } - else if(foundAuthInt) { - d->qop = strdup("auth-int"); - if(!d->qop) - return CURLDIGEST_NOMEM; - } - } - else if(Curl_raw_equal(value, "algorithm")) { - d->algorithm = strdup(content); - if(!d->algorithm) - return CURLDIGEST_NOMEM; - if(Curl_raw_equal(content, "MD5-sess")) - d->algo = CURLDIGESTALGO_MD5SESS; - else if(Curl_raw_equal(content, "MD5")) - d->algo = CURLDIGESTALGO_MD5; - else - return CURLDIGEST_BADALGO; - } - else { - /* unknown specifier, ignore it! */ - } - } - else - break; /* we're done here */ - - /* pass all additional spaces here */ - while(*header && ISSPACE(*header)) - header++; - if(',' == *header) - /* allow the list to be comma-separated */ - header++; - } - /* We had a nonce since before, and we got another one now without - 'stale=true'. This means we provided bad credentials in the previous - request */ - if(before && !d->stale) - return CURLDIGEST_BAD; - - /* We got this header without a nonce, that's a bad Digest line! */ - if(!d->nonce) - return CURLDIGEST_BAD; - } - else - /* else not a digest, get out */ - return CURLDIGEST_NONE; - - return CURLDIGEST_FINE; -} - -/* convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/ -static void md5_to_ascii(unsigned char *source, /* 16 bytes */ - unsigned char *dest) /* 33 bytes */ -{ - int i; - for(i=0; i<16; i++) - snprintf((char *)&dest[i*2], 3, "%02x", source[i]); -} - -CURLcode Curl_output_digest(struct connectdata *conn, - bool proxy, - const unsigned char *request, - const unsigned char *uripath) -{ - /* We have a Digest setup for this, use it! Now, to get all the details for - this sorted out, I must urge you dear friend to read up on the RFC2617 - section 3.2.2, */ - unsigned char md5buf[16]; /* 16 bytes/128 bits */ - unsigned char request_digest[33]; - unsigned char *md5this; - unsigned char *ha1; - unsigned char ha2[33];/* 32 digits and 1 zero byte */ - char cnoncebuf[7]; - char *cnonce; - char *tmp = NULL; - struct timeval now; - - char **allocuserpwd; - const char *userp; - const char *passwdp; - struct auth *authp; - - struct SessionHandle *data = conn->data; - struct digestdata *d; - CURLcode rc; -/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines. - It converts digest text to ASCII so the MD5 will be correct for - what ultimately goes over the network. -*/ -#define CURL_OUTPUT_DIGEST_CONV(a, b) \ - rc = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \ - if(rc != CURLE_OK) { \ - free(b); \ - return rc; \ - } - - if(proxy) { - d = &data->state.proxydigest; - allocuserpwd = &conn->allocptr.proxyuserpwd; - userp = conn->proxyuser; - passwdp = conn->proxypasswd; - authp = &data->state.authproxy; - } - else { - d = &data->state.digest; - allocuserpwd = &conn->allocptr.userpwd; - userp = conn->user; - passwdp = conn->passwd; - authp = &data->state.authhost; - } - - if(*allocuserpwd) { - Curl_safefree(*allocuserpwd); - *allocuserpwd = NULL; - } - - /* not set means empty */ - if(!userp) - userp=""; - - if(!passwdp) - passwdp=""; - - if(!d->nonce) { - authp->done = FALSE; - return CURLE_OK; - } - authp->done = TRUE; - - if(!d->nc) - d->nc = 1; - - if(!d->cnonce) { - /* Generate a cnonce */ - now = Curl_tvnow(); - snprintf(cnoncebuf, sizeof(cnoncebuf), "%06ld", (long)now.tv_sec); - if(Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), &cnonce)) - d->cnonce = cnonce; - else - return CURLE_OUT_OF_MEMORY; - } - - /* - if the algorithm is "MD5" or unspecified (which then defaults to MD5): - - A1 = unq(username-value) ":" unq(realm-value) ":" passwd - - if the algorithm is "MD5-sess" then: - - A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd ) - ":" unq(nonce-value) ":" unq(cnonce-value) - */ - - md5this = (unsigned char *) - aprintf("%s:%s:%s", userp, d->realm, passwdp); - if(!md5this) - return CURLE_OUT_OF_MEMORY; - - CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ - Curl_md5it(md5buf, md5this); - free(md5this); /* free this again */ - - ha1 = malloc(33); /* 32 digits and 1 zero byte */ - if(!ha1) - return CURLE_OUT_OF_MEMORY; - - md5_to_ascii(md5buf, ha1); - - if(d->algo == CURLDIGESTALGO_MD5SESS) { - /* nonce and cnonce are OUTSIDE the hash */ - tmp = aprintf("%s:%s:%s", ha1, d->nonce, d->cnonce); - if(!tmp) - return CURLE_OUT_OF_MEMORY; - CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */ - Curl_md5it(md5buf, (unsigned char *)tmp); - free(tmp); /* free this again */ - md5_to_ascii(md5buf, ha1); - } - - /* - If the "qop" directive's value is "auth" or is unspecified, then A2 is: - - A2 = Method ":" digest-uri-value - - If the "qop" value is "auth-int", then A2 is: - - A2 = Method ":" digest-uri-value ":" H(entity-body) - - (The "Method" value is the HTTP request method as specified in section - 5.1.1 of RFC 2616) - */ - - /* So IE browsers < v7 cut off the URI part at the query part when they - evaluate the MD5 and some (IIS?) servers work with them so we may need to - do the Digest IE-style. Note that the different ways cause different MD5 - sums to get sent. - - Apache servers can be set to do the Digest IE-style automatically using - the BrowserMatch feature: - http://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html#msie - - Further details on Digest implementation differences: - http://www.fngtps.com/2006/09/http-authentication - */ - if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) { - md5this = (unsigned char *)aprintf("%s:%.*s", request, - (int)(tmp - (char *)uripath), uripath); - } - else - md5this = (unsigned char *)aprintf("%s:%s", request, uripath); - - if(!md5this) { - free(ha1); - return CURLE_OUT_OF_MEMORY; - } - - if(d->qop && Curl_raw_equal(d->qop, "auth-int")) { - /* We don't support auth-int at the moment. I can't see a easy way to get - entity-body here */ - /* TODO: Append H(entity-body)*/ - } - CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ - Curl_md5it(md5buf, md5this); - free(md5this); /* free this again */ - md5_to_ascii(md5buf, ha2); - - if(d->qop) { - md5this = (unsigned char *)aprintf("%s:%s:%08x:%s:%s:%s", - ha1, - d->nonce, - d->nc, - d->cnonce, - d->qop, - ha2); - } - else { - md5this = (unsigned char *)aprintf("%s:%s:%s", - ha1, - d->nonce, - ha2); - } - free(ha1); - if(!md5this) - return CURLE_OUT_OF_MEMORY; - - CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */ - Curl_md5it(md5buf, md5this); - free(md5this); /* free this again */ - md5_to_ascii(md5buf, request_digest); - - /* for test case 64 (snooped from a Mozilla 1.3a request) - - Authorization: Digest username="testuser", realm="testrealm", \ - nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca" - */ - - if(d->qop) { - *allocuserpwd = - aprintf( "%sAuthorization: Digest " - "username=\"%s\", " - "realm=\"%s\", " - "nonce=\"%s\", " - "uri=\"%s\", " - "cnonce=\"%s\", " - "nc=%08x, " - "qop=\"%s\", " - "response=\"%s\"", - proxy?"Proxy-":"", - userp, - d->realm, - d->nonce, - uripath, /* this is the PATH part of the URL */ - d->cnonce, - d->nc, - d->qop, - request_digest); - - if(Curl_raw_equal(d->qop, "auth")) - d->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0 padded - which tells to the server how many times you are using the - same nonce in the qop=auth mode. */ - } - else { - *allocuserpwd = - aprintf( "%sAuthorization: Digest " - "username=\"%s\", " - "realm=\"%s\", " - "nonce=\"%s\", " - "uri=\"%s\", " - "response=\"%s\"", - proxy?"Proxy-":"", - userp, - d->realm, - d->nonce, - uripath, /* this is the PATH part of the URL */ - request_digest); - } - if(!*allocuserpwd) - return CURLE_OUT_OF_MEMORY; - - /* Add optional fields */ - if(d->opaque) { - /* append opaque */ - tmp = aprintf("%s, opaque=\"%s\"", *allocuserpwd, d->opaque); - if(!tmp) - return CURLE_OUT_OF_MEMORY; - free(*allocuserpwd); - *allocuserpwd = tmp; - } - - if(d->algorithm) { - /* append algorithm */ - tmp = aprintf("%s, algorithm=\"%s\"", *allocuserpwd, d->algorithm); - if(!tmp) - return CURLE_OUT_OF_MEMORY; - free(*allocuserpwd); - *allocuserpwd = tmp; - } - - /* append CRLF + zero (3 bytes) to the userpwd header */ - tmp = realloc(*allocuserpwd, strlen(*allocuserpwd) + 3); - if(!tmp) - return CURLE_OUT_OF_MEMORY; - strcat(tmp, "\r\n"); - *allocuserpwd = tmp; - - return CURLE_OK; -} - -void Curl_digest_cleanup_one(struct digestdata *d) -{ - if(d->nonce) - free(d->nonce); - d->nonce = NULL; - - if(d->cnonce) - free(d->cnonce); - d->cnonce = NULL; - - if(d->realm) - free(d->realm); - d->realm = NULL; - - if(d->opaque) - free(d->opaque); - d->opaque = NULL; - - if(d->qop) - free(d->qop); - d->qop = NULL; - - if(d->algorithm) - free(d->algorithm); - d->algorithm = NULL; - - d->nc = 0; - d->algo = CURLDIGESTALGO_MD5; /* default algorithm */ - d->stale = FALSE; /* default means normal, not stale */ -} - - -void Curl_digest_cleanup(struct SessionHandle *data) -{ - Curl_digest_cleanup_one(&data->state.digest); - Curl_digest_cleanup_one(&data->state.proxydigest); -} - -#endif diff --git a/third_party/curl/lib/http_digest.h b/third_party/curl/lib/http_digest.h deleted file mode 100644 index 8c96378d6..000000000 --- a/third_party/curl/lib/http_digest.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __HTTP_DIGEST_H -#define __HTTP_DIGEST_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -typedef enum { - CURLDIGEST_NONE, /* not a digest */ - CURLDIGEST_BAD, /* a digest, but one we don't like */ - CURLDIGEST_BADALGO, /* unsupported algorithm requested */ - CURLDIGEST_NOMEM, - CURLDIGEST_FINE, /* a digest we act on */ - - CURLDIGEST_LAST /* last entry in this enum, don't use */ -} CURLdigest; - -enum { - CURLDIGESTALGO_MD5, - CURLDIGESTALGO_MD5SESS -}; - -/* this is for digest header input */ -CURLdigest Curl_input_digest(struct connectdata *conn, - bool proxy, const char *header); - -/* this is for creating digest header output */ -CURLcode Curl_output_digest(struct connectdata *conn, - bool proxy, - const unsigned char *request, - const unsigned char *uripath); -void Curl_digest_cleanup_one(struct digestdata *dig); - -#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) -void Curl_digest_cleanup(struct SessionHandle *data); -#else -#define Curl_digest_cleanup(x) do {} while(0) -#endif - -#endif diff --git a/third_party/curl/lib/http_negotiate.c b/third_party/curl/lib/http_negotiate.c deleted file mode 100644 index 673f8c908..000000000 --- a/third_party/curl/lib/http_negotiate.c +++ /dev/null @@ -1,369 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_GSSAPI -#ifdef HAVE_OLD_GSSMIT -#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name -#endif - -#ifndef CURL_DISABLE_HTTP - /* -- WIN32 approved -- */ -#include -#include -#include -#include -#include - -#include "urldata.h" -#include "sendf.h" -#include "rawstr.h" -#include "curl_base64.h" -#include "http_negotiate.h" -#include "curl_memory.h" - -#ifdef HAVE_SPNEGO -# include -# ifdef USE_SSLEAY -# ifdef USE_OPENSSL -# include -# else -# include -# endif -# else -# error "Can't compile SPNEGO support without OpenSSL." -# endif -#endif - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -static int -get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server) -{ - struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: - &conn->data->state.negotiate; - OM_uint32 major_status, minor_status; - gss_buffer_desc token = GSS_C_EMPTY_BUFFER; - char name[2048]; - const char* service; - - /* GSSAPI implementation by Globus (known as GSI) requires the name to be - of form "/" instead of @ (ie. slash instead - of at-sign). Also GSI servers are often identified as 'host' not 'khttp'. - Change following lines if you want to use GSI */ - - /* IIS uses the @ form but uses 'http' as the service name */ - - if(neg_ctx->gss) - service = "KHTTP"; - else - service = "HTTP"; - - token.length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name : - conn->host.name) + 1; - if(token.length + 1 > sizeof(name)) - return EMSGSIZE; - - snprintf(name, sizeof(name), "%s@%s", service, proxy ? conn->proxy.name : - conn->host.name); - - token.value = (void *) name; - major_status = gss_import_name(&minor_status, - &token, - GSS_C_NT_HOSTBASED_SERVICE, - server); - - return GSS_ERROR(major_status) ? -1 : 0; -} - -static void -log_gss_error(struct connectdata *conn, OM_uint32 error_status, const char *prefix) -{ - OM_uint32 maj_stat, min_stat; - OM_uint32 msg_ctx = 0; - gss_buffer_desc status_string; - char buf[1024]; - size_t len; - - snprintf(buf, sizeof(buf), "%s", prefix); - len = strlen(buf); - do { - maj_stat = gss_display_status(&min_stat, - error_status, - GSS_C_MECH_CODE, - GSS_C_NO_OID, - &msg_ctx, - &status_string); - if(sizeof(buf) > len + status_string.length + 1) { - snprintf(buf + len, sizeof(buf) - len, - ": %s", (char*) status_string.value); - len += status_string.length; - } - gss_release_buffer(&min_stat, &status_string); - } while(!GSS_ERROR(maj_stat) && msg_ctx != 0); - - infof(conn->data, "%s", buf); -} - -/* returning zero (0) means success, everything else is treated as "failure" - with no care exactly what the failure was */ -int Curl_input_negotiate(struct connectdata *conn, bool proxy, - const char *header) -{ - struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: - &conn->data->state.negotiate; - OM_uint32 major_status, minor_status, minor_status2; - gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; - gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; - int ret; - size_t len, rawlen; - bool gss; - const char* protocol; - - while(*header && ISSPACE(*header)) - header++; - if(checkprefix("GSS-Negotiate", header)) { - protocol = "GSS-Negotiate"; - gss = TRUE; - } - else if(checkprefix("Negotiate", header)) { - protocol = "Negotiate"; - gss = FALSE; - } - else - return -1; - - if(neg_ctx->context) { - if(neg_ctx->gss != gss) { - return -1; - } - } - else { - neg_ctx->protocol = protocol; - neg_ctx->gss = gss; - } - - if(neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) { - /* We finished successfully our part of authentication, but server - * rejected it (since we're again here). Exit with an error since we - * can't invent anything better */ - Curl_cleanup_negotiate(conn->data); - return -1; - } - - if(neg_ctx->server_name == NULL && - (ret = get_gss_name(conn, proxy, &neg_ctx->server_name))) - return ret; - - header += strlen(neg_ctx->protocol); - while(*header && ISSPACE(*header)) - header++; - - len = strlen(header); - if(len > 0) { - rawlen = Curl_base64_decode(header, - (unsigned char **)&input_token.value); - if(rawlen == 0) - return -1; - input_token.length = rawlen; - -#ifdef HAVE_SPNEGO /* Handle SPNEGO */ - if(checkprefix("Negotiate", header)) { - ASN1_OBJECT * object = NULL; - int rc = 1; - unsigned char * spnegoToken = NULL; - size_t spnegoTokenLength = 0; - unsigned char * mechToken = NULL; - size_t mechTokenLength = 0; - - if(input_token.value == NULL) - return CURLE_OUT_OF_MEMORY; - - spnegoToken = malloc(input_token.length); - if(spnegoToken == NULL) - return CURLE_OUT_OF_MEMORY; - - spnegoTokenLength = input_token.length; - - object = OBJ_txt2obj ("1.2.840.113554.1.2.2", 1); - if(!parseSpnegoTargetToken(spnegoToken, - spnegoTokenLength, - NULL, - NULL, - &mechToken, - &mechTokenLength, - NULL, - NULL)) { - free(spnegoToken); - spnegoToken = NULL; - infof(conn->data, "Parse SPNEGO Target Token failed\n"); - } - else { - free(input_token.value); - input_token.value = malloc(mechTokenLength); - if (input_token.value == NULL) - return CURLE_OUT_OF_MEMORY; - - memcpy(input_token.value, mechToken,mechTokenLength); - input_token.length = mechTokenLength; - free(mechToken); - mechToken = NULL; - infof(conn->data, "Parse SPNEGO Target Token succeeded\n"); - } - } -#endif - } - - major_status = gss_init_sec_context(&minor_status, - GSS_C_NO_CREDENTIAL, - &neg_ctx->context, - neg_ctx->server_name, - GSS_C_NO_OID, - GSS_C_DELEG_FLAG, - 0, - GSS_C_NO_CHANNEL_BINDINGS, - &input_token, - NULL, - &output_token, - NULL, - NULL); - if(input_token.length > 0) - gss_release_buffer(&minor_status2, &input_token); - neg_ctx->status = major_status; - if(GSS_ERROR(major_status)) { - /* Curl_cleanup_negotiate(conn->data) ??? */ - log_gss_error(conn, minor_status, - "gss_init_sec_context() failed: "); - return -1; - } - - if(output_token.length == 0) { - return -1; - } - - neg_ctx->output_token = output_token; - /* conn->bits.close = FALSE; */ - - return 0; -} - - -CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) -{ - struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: - &conn->data->state.negotiate; - char *encoded = NULL; - size_t len; - char *userp; - -#ifdef HAVE_SPNEGO /* Handle SPNEGO */ - if(checkprefix("Negotiate", neg_ctx->protocol)) { - ASN1_OBJECT * object = NULL; - int rc = 1; - unsigned char * spnegoToken = NULL; - size_t spnegoTokenLength = 0; - unsigned char * responseToken = NULL; - size_t responseTokenLength = 0; - - responseToken = malloc(neg_ctx->output_token.length); - if( responseToken == NULL) - return CURLE_OUT_OF_MEMORY; - memcpy(responseToken, neg_ctx->output_token.value, - neg_ctx->output_token.length); - responseTokenLength = neg_ctx->output_token.length; - - object=OBJ_txt2obj ("1.2.840.113554.1.2.2", 1); - if(!makeSpnegoInitialToken (object, - responseToken, - responseTokenLength, - &spnegoToken, - &spnegoTokenLength)) { - free(responseToken); - responseToken = NULL; - infof(conn->data, "Make SPNEGO Initial Token failed\n"); - } - else { - free(responseToken); - responseToken = NULL; - free(neg_ctx->output_token.value); - neg_ctx->output_token.value = malloc(spnegoTokenLength); - if(neg_ctx->output_token.value == NULL) { - free(spnegoToken); - spnegoToken = NULL; - return CURLE_OUT_OF_MEMORY; - } - memcpy(neg_ctx->output_token.value, spnegoToken,spnegoTokenLength); - neg_ctx->output_token.length = spnegoTokenLength; - free(spnegoToken); - spnegoToken = NULL; - infof(conn->data, "Make SPNEGO Initial Token succeeded\n"); - } - } -#endif - len = Curl_base64_encode(conn->data, - neg_ctx->output_token.value, - neg_ctx->output_token.length, - &encoded); - - if(len == 0) - return CURLE_OUT_OF_MEMORY; - - userp = aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "", - neg_ctx->protocol, encoded); - - if(proxy) - conn->allocptr.proxyuserpwd = userp; - else - conn->allocptr.userpwd = userp; - free(encoded); - Curl_cleanup_negotiate (conn->data); - return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; -} - -static void cleanup(struct negotiatedata *neg_ctx) -{ - OM_uint32 minor_status; - if(neg_ctx->context != GSS_C_NO_CONTEXT) - gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER); - - if(neg_ctx->output_token.length != 0) - gss_release_buffer(&minor_status, &neg_ctx->output_token); - - if(neg_ctx->server_name != GSS_C_NO_NAME) - gss_release_name(&minor_status, &neg_ctx->server_name); - - memset(neg_ctx, 0, sizeof(*neg_ctx)); -} - -void Curl_cleanup_negotiate(struct SessionHandle *data) -{ - cleanup(&data->state.negotiate); - cleanup(&data->state.proxyneg); -} - - -#endif -#endif diff --git a/third_party/curl/lib/http_negotiate.h b/third_party/curl/lib/http_negotiate.h deleted file mode 100644 index e584d76fc..000000000 --- a/third_party/curl/lib/http_negotiate.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef HEADER_CURL_HTTP_NEGOTIATE_H -#define HEADER_CURL_HTTP_NEGOTIATE_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifdef USE_HTTP_NEGOTIATE - -/* this is for Negotiate header input */ -int Curl_input_negotiate(struct connectdata *conn, bool proxy, - const char *header); - -/* this is for creating Negotiate header output */ -CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy); - -void Curl_cleanup_negotiate(struct SessionHandle *data); - -#ifdef USE_WINDOWS_SSPI -#define GSS_ERROR(status) (status & 0x80000000) -#endif - -#endif /* USE_HTTP_NEGOTIATE */ - -#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */ diff --git a/third_party/curl/lib/http_negotiate_sspi.c b/third_party/curl/lib/http_negotiate_sspi.c deleted file mode 100644 index 5843ab251..000000000 --- a/third_party/curl/lib/http_negotiate_sspi.c +++ /dev/null @@ -1,293 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef USE_WINDOWS_SSPI - -#ifndef CURL_DISABLE_HTTP -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include - -#include "urldata.h" -#include "sendf.h" -#include "rawstr.h" -#include "curl_base64.h" -#include "http_negotiate.h" -#include "curl_memory.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -static int -get_gss_name(struct connectdata *conn, bool proxy, char *server) -{ - struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: - &conn->data->state.negotiate; - const char* service; - size_t length; - - /* GSSAPI implementation by Globus (known as GSI) requires the name to be - of form "/" instead of @ (ie. slash instead - of at-sign). Also GSI servers are often identified as 'host' not 'khttp'. - Change following lines if you want to use GSI */ - - /* IIS uses the @ form but uses 'http' as the service name, - and SSPI then generates an NTLM token. When using / a - Kerberos token is generated. */ - - if(neg_ctx->gss) - service = "KHTTP"; - else - service = "HTTP"; - - length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name : - conn->host.name) + 1; - if(length + 1 > sizeof(neg_ctx->server_name)) - return EMSGSIZE; - - snprintf(server, sizeof(neg_ctx->server_name), "%s/%s", - service, proxy ? conn->proxy.name : conn->host.name); - - return 0; -} - -/* returning zero (0) means success, everything else is treated as "failure" - with no care exactly what the failure was */ -int Curl_input_negotiate(struct connectdata *conn, bool proxy, - const char *header) -{ - struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: - &conn->data->state.negotiate; - BYTE *input_token = 0; - SecBufferDesc out_buff_desc; - SecBuffer out_sec_buff; - SecBufferDesc in_buff_desc; - SecBuffer in_sec_buff; - ULONG context_attributes; - TimeStamp lifetime; - - int ret; - size_t len = 0, input_token_len = 0; - bool gss = FALSE; - const char* protocol; - - while(*header && ISSPACE(*header)) - header++; - - if(checkprefix("GSS-Negotiate", header)) { - protocol = "GSS-Negotiate"; - gss = TRUE; - } - else if(checkprefix("Negotiate", header)) { - protocol = "Negotiate"; - gss = FALSE; - } - else - return -1; - - if(neg_ctx->context) { - if(neg_ctx->gss != gss) { - return -1; - } - } - else { - neg_ctx->protocol = protocol; - neg_ctx->gss = gss; - } - - if(neg_ctx->context && neg_ctx->status == SEC_E_OK) { - /* We finished successfully our part of authentication, but server - * rejected it (since we're again here). Exit with an error since we - * can't invent anything better */ - Curl_cleanup_negotiate(conn->data); - return -1; - } - - if(strlen(neg_ctx->server_name) == 0 && - (ret = get_gss_name(conn, proxy, neg_ctx->server_name))) - return ret; - - if (!neg_ctx->max_token_length) { - PSecPkgInfo SecurityPackage; - ret = s_pSecFn->QuerySecurityPackageInfo((SEC_CHAR *)"Negotiate", - &SecurityPackage); - if (ret != SEC_E_OK) - return -1; - - /* Allocate input and output buffers according to the max token size - as indicated by the security package */ - neg_ctx->max_token_length = SecurityPackage->cbMaxToken; - neg_ctx->output_token = (BYTE *)malloc(neg_ctx->max_token_length); - s_pSecFn->FreeContextBuffer(SecurityPackage); - } - - /* Obtain the input token, if any */ - header += strlen(neg_ctx->protocol); - while(*header && ISSPACE(*header)) - header++; - - len = strlen(header); - if(len > 0) { - input_token = malloc(neg_ctx->max_token_length); - if(!input_token) - return -1; - - input_token_len = Curl_base64_decode(header, - (unsigned char **)&input_token); - if(input_token_len == 0) - return -1; - } - - if ( !input_token ) { - /* first call in a new negotiation, we have to require credentials, - and allocate memory for the context */ - - neg_ctx->credentials = (CredHandle *)malloc(sizeof(CredHandle)); - neg_ctx->context = (CtxtHandle *)malloc(sizeof(CtxtHandle)); - - if ( !neg_ctx->credentials || !neg_ctx->context) - return -1; - - neg_ctx->status = - s_pSecFn->AcquireCredentialsHandle(NULL, (SEC_CHAR *)"Negotiate", - SECPKG_CRED_OUTBOUND, NULL, NULL, - NULL, NULL, neg_ctx->credentials, - &lifetime); - if ( neg_ctx->status != SEC_E_OK ) - return -1; - } - - /* prepare the output buffers, and input buffers if present */ - out_buff_desc.ulVersion = 0; - out_buff_desc.cBuffers = 1; - out_buff_desc.pBuffers = &out_sec_buff; - - out_sec_buff.cbBuffer = neg_ctx->max_token_length; - out_sec_buff.BufferType = SECBUFFER_TOKEN; - out_sec_buff.pvBuffer = neg_ctx->output_token; - - - if (input_token) { - in_buff_desc.ulVersion = 0; - in_buff_desc.cBuffers = 1; - in_buff_desc.pBuffers = &out_sec_buff; - - in_sec_buff.cbBuffer = input_token_len; - in_sec_buff.BufferType = SECBUFFER_TOKEN; - in_sec_buff.pvBuffer = input_token; - } - - neg_ctx->status = s_pSecFn->InitializeSecurityContext( - neg_ctx->credentials, - input_token ? neg_ctx->context : 0, - neg_ctx->server_name, - ISC_REQ_CONFIDENTIALITY, - 0, - SECURITY_NATIVE_DREP, - input_token ? &in_buff_desc : 0, - 0, - neg_ctx->context, - &out_buff_desc, - &context_attributes, - &lifetime); - - if ( GSS_ERROR(neg_ctx->status) ) - return -1; - - if ( neg_ctx->status == SEC_I_COMPLETE_NEEDED || - neg_ctx->status == SEC_I_COMPLETE_AND_CONTINUE ) { - neg_ctx->status = s_pSecFn->CompleteAuthToken(neg_ctx->context, - &out_buff_desc); - if ( GSS_ERROR(neg_ctx->status) ) - return -1; - } - - neg_ctx->output_token_length = out_sec_buff.cbBuffer; - - return 0; -} - - -CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) -{ - struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: - &conn->data->state.negotiate; - char *encoded = NULL; - size_t len; - char *userp; - - len = Curl_base64_encode(conn->data, - (const char*)neg_ctx->output_token, - neg_ctx->output_token_length, - &encoded); - - if(len == 0) - return CURLE_OUT_OF_MEMORY; - - userp = aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "", - neg_ctx->protocol, encoded); - - if(proxy) - conn->allocptr.proxyuserpwd = userp; - else - conn->allocptr.userpwd = userp; - free(encoded); - Curl_cleanup_negotiate (conn->data); - return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; -} - -static void cleanup(struct negotiatedata *neg_ctx) -{ - if(neg_ctx->context) { - s_pSecFn->DeleteSecurityContext(neg_ctx->context); - free(neg_ctx->context); - neg_ctx->context = 0; - } - - if(neg_ctx->credentials) { - s_pSecFn->FreeCredentialsHandle(neg_ctx->credentials); - free(neg_ctx->credentials); - neg_ctx->credentials = 0; - } - - if(neg_ctx->output_token) { - free(neg_ctx->output_token); - neg_ctx->output_token = 0; - } -} - -void Curl_cleanup_negotiate(struct SessionHandle *data) -{ - cleanup(&data->state.negotiate); - cleanup(&data->state.proxyneg); -} - - -#endif -#endif diff --git a/third_party/curl/lib/http_ntlm.c b/third_party/curl/lib/http_ntlm.c deleted file mode 100644 index fe2ffeac5..000000000 --- a/third_party/curl/lib/http_ntlm.c +++ /dev/null @@ -1,1295 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -/* NTLM details: - - http://davenport.sourceforge.net/ntlm.html - http://www.innovation.ch/java/ntlm.html - - Another implementation: - http://lxr.mozilla.org/mozilla/source/security/manager/ssl/src/nsNTLMAuthModule.cpp - -*/ - -#ifndef CURL_DISABLE_HTTP -#ifdef USE_NTLM - -#define DEBUG_ME 0 - -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) -#include -#endif - -#include "urldata.h" -#include "non-ascii.h" /* for Curl_convert_... prototypes */ -#include "sendf.h" -#include "rawstr.h" -#include "curl_base64.h" -#include "http_ntlm.h" -#include "url.h" -#include "curl_gethostname.h" -#include "curl_memory.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* "NTLMSSP" signature is always in ASCII regardless of the platform */ -#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50" - -#ifdef USE_SSLEAY -#include "ssluse.h" -# ifdef USE_OPENSSL -# include -# ifndef OPENSSL_NO_MD4 -# include -# endif -# include -# include -# include -# else -# include -# ifndef OPENSSL_NO_MD4 -# include -# endif -# include -# include -# include -# endif - -#if OPENSSL_VERSION_NUMBER < 0x00907001L -#define DES_key_schedule des_key_schedule -#define DES_cblock des_cblock -#define DES_set_odd_parity des_set_odd_parity -#define DES_set_key des_set_key -#define DES_ecb_encrypt des_ecb_encrypt - -/* This is how things were done in the old days */ -#define DESKEY(x) x -#define DESKEYARG(x) x -#else -/* Modern version */ -#define DESKEYARG(x) *x -#define DESKEY(x) &x -#endif - -#ifdef OPENSSL_NO_MD4 -/* This requires MD4, but OpenSSL was compiled without it */ -#define USE_NTRESPONSES 0 -#define USE_NTLM2SESSION 0 -#endif - -#elif defined(USE_GNUTLS) - -#include "gtls.h" -#include - -#define MD5_DIGEST_LENGTH 16 -#define MD4_DIGEST_LENGTH 16 - -#elif defined(USE_NSS) - -#include "curl_md4.h" -#include "nssg.h" -#include -#include -#include -#define MD5_DIGEST_LENGTH MD5_LENGTH - -#elif defined(USE_WINDOWS_SSPI) - -#include "curl_sspi.h" - -#else -# error "Can't compile NTLM support without a crypto library." -#endif - -/* The last #include file should be: */ -#include "memdebug.h" - -#ifndef USE_NTRESPONSES -/* Define this to make the type-3 message include the NT response message */ -#define USE_NTRESPONSES 1 - -/* Define this to make the type-3 message include the NTLM2Session response - message, requires USE_NTRESPONSES. */ -#define USE_NTLM2SESSION 1 -#endif - -#ifndef USE_WINDOWS_SSPI -/* this function converts from the little endian format used in the incoming - package to whatever endian format we're using natively */ -static unsigned int readint_le(unsigned char *buf) /* must point to a - 4 bytes buffer*/ -{ - return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) | - ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24); -} -#endif - -#if DEBUG_ME -# define DEBUG_OUT(x) x -static void print_flags(FILE *handle, unsigned long flags) -{ - if(flags & NTLMFLAG_NEGOTIATE_UNICODE) - fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE "); - if(flags & NTLMFLAG_NEGOTIATE_OEM) - fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM "); - if(flags & NTLMFLAG_REQUEST_TARGET) - fprintf(handle, "NTLMFLAG_REQUEST_TARGET "); - if(flags & (1<<3)) - fprintf(handle, "NTLMFLAG_UNKNOWN_3 "); - if(flags & NTLMFLAG_NEGOTIATE_SIGN) - fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN "); - if(flags & NTLMFLAG_NEGOTIATE_SEAL) - fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL "); - if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE) - fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE "); - if(flags & NTLMFLAG_NEGOTIATE_LM_KEY) - fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY "); - if(flags & NTLMFLAG_NEGOTIATE_NETWARE) - fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE "); - if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) - fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY "); - if(flags & (1<<10)) - fprintf(handle, "NTLMFLAG_UNKNOWN_10 "); - if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS) - fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS "); - if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED) - fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED "); - if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED) - fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED "); - if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL) - fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL "); - if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN) - fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN "); - if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN) - fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN "); - if(flags & NTLMFLAG_TARGET_TYPE_SERVER) - fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER "); - if(flags & NTLMFLAG_TARGET_TYPE_SHARE) - fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE "); - if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) - fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY "); - if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE) - fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE "); - if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE) - fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE "); - if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY) - fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY "); - if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) - fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO "); - if(flags & (1<<24)) - fprintf(handle, "NTLMFLAG_UNKNOWN_24 "); - if(flags & (1<<25)) - fprintf(handle, "NTLMFLAG_UNKNOWN_25 "); - if(flags & (1<<26)) - fprintf(handle, "NTLMFLAG_UNKNOWN_26 "); - if(flags & (1<<27)) - fprintf(handle, "NTLMFLAG_UNKNOWN_27 "); - if(flags & (1<<28)) - fprintf(handle, "NTLMFLAG_UNKNOWN_28 "); - if(flags & NTLMFLAG_NEGOTIATE_128) - fprintf(handle, "NTLMFLAG_NEGOTIATE_128 "); - if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE) - fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE "); - if(flags & NTLMFLAG_NEGOTIATE_56) - fprintf(handle, "NTLMFLAG_NEGOTIATE_56 "); -} - -static void print_hex(FILE *handle, const char *buf, size_t len) -{ - const char *p = buf; - fprintf(stderr, "0x"); - while(len-- > 0) - fprintf(stderr, "%02.2x", (unsigned int)*p++); -} -#else -# define DEBUG_OUT(x) -#endif - -/* - (*) = A "security buffer" is a triplet consisting of two shorts and one - long: - - 1. a 'short' containing the length of the buffer in bytes - 2. a 'short' containing the allocated space for the buffer in bytes - 3. a 'long' containing the offset to the start of the buffer from the - beginning of the NTLM message, in bytes. -*/ - - -CURLntlm Curl_input_ntlm(struct connectdata *conn, - bool proxy, /* if proxy or not */ - const char *header) /* rest of the www-authenticate: - header */ -{ - /* point to the correct struct with this */ - struct ntlmdata *ntlm; -#ifndef USE_WINDOWS_SSPI - static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; -#endif - -#ifdef USE_NSS - if(CURLE_OK != Curl_nss_force_init(conn->data)) - return CURLNTLM_BAD; -#endif - - ntlm = proxy?&conn->proxyntlm:&conn->ntlm; - - /* skip initial whitespaces */ - while(*header && ISSPACE(*header)) - header++; - - if(checkprefix("NTLM", header)) { - header += strlen("NTLM"); - - while(*header && ISSPACE(*header)) - header++; - - if(*header) { - /* We got a type-2 message here: - - Index Description Content - 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" - (0x4e544c4d53535000) - 8 NTLM Message Type long (0x02000000) - 12 Target Name security buffer(*) - 20 Flags long - 24 Challenge 8 bytes - (32) Context (optional) 8 bytes (two consecutive longs) - (40) Target Information (optional) security buffer(*) - 32 (48) start of data block - */ - size_t size; - unsigned char *buffer; - size = Curl_base64_decode(header, &buffer); - if(!buffer) - return CURLNTLM_BAD; - - ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */ - -#ifdef USE_WINDOWS_SSPI - ntlm->type_2 = malloc(size+1); - if(ntlm->type_2 == NULL) { - free(buffer); - return CURLE_OUT_OF_MEMORY; - } - ntlm->n_type_2 = size; - memcpy(ntlm->type_2, buffer, size); -#else - ntlm->flags = 0; - - if((size < 32) || - (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) || - (memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0)) { - /* This was not a good enough type-2 message */ - free(buffer); - return CURLNTLM_BAD; - } - - ntlm->flags = readint_le(&buffer[20]); - memcpy(ntlm->nonce, &buffer[24], 8); - - DEBUG_OUT({ - fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags); - print_flags(stderr, ntlm->flags); - fprintf(stderr, "\n nonce="); - print_hex(stderr, (char *)ntlm->nonce, 8); - fprintf(stderr, "\n****\n"); - fprintf(stderr, "**** Header %s\n ", header); - }); -#endif - free(buffer); - } - else { - if(ntlm->state >= NTLMSTATE_TYPE1) - return CURLNTLM_BAD; - - ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */ - } - } - return CURLNTLM_FINE; -} - -#ifndef USE_WINDOWS_SSPI - -#ifdef USE_SSLEAY -/* - * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The - * key schedule ks is also set. - */ -static void setup_des_key(const unsigned char *key_56, - DES_key_schedule DESKEYARG(ks)) -{ - DES_cblock key; - - key[0] = key_56[0]; - key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1)); - key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2)); - key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3)); - key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4)); - key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5)); - key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); - key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); - - DES_set_odd_parity(&key); - DES_set_key(&key, ks); -} - -#else /* defined(USE_SSLEAY) */ - -/* - * Turns a 56 bit key into the 64 bit, odd parity key. Used by GnuTLS and NSS. - */ -static void extend_key_56_to_64(const unsigned char *key_56, char *key) -{ - key[0] = key_56[0]; - key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1)); - key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2)); - key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3)); - key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4)); - key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5)); - key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); - key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); -} - -#if defined(USE_GNUTLS) - -/* - * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. - */ -static void setup_des_key(const unsigned char *key_56, - gcry_cipher_hd_t *des) -{ - char key[8]; - extend_key_56_to_64(key_56, key); - gcry_cipher_setkey(*des, key, 8); -} - -#elif defined(USE_NSS) - -/* - * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using - * the expanded key. The caller is responsible for giving 64 bit of valid - * data is IN and (at least) 64 bit large buffer as OUT. - */ -static bool encrypt_des(const unsigned char *in, unsigned char *out, - const unsigned char *key_56) -{ - const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */ - PK11SlotInfo *slot = NULL; - char key[8]; /* expanded 64 bit key */ - SECItem key_item; - PK11SymKey *symkey = NULL; - SECItem *param = NULL; - PK11Context *ctx = NULL; - int out_len; /* not used, required by NSS */ - bool rv = FALSE; - - /* use internal slot for DES encryption (requires NSS to be initialized) */ - slot = PK11_GetInternalKeySlot(); - if(!slot) - return FALSE; - - /* expand the 56 bit key to 64 bit and wrap by NSS */ - extend_key_56_to_64(key_56, key); - key_item.data = (unsigned char *)key; - key_item.len = /* hard-wired */ 8; - symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT, - &key_item, NULL); - if(!symkey) - goto fail; - - /* create DES encryption context */ - param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL); - if(!param) - goto fail; - ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param); - if(!ctx) - goto fail; - - /* perform the encryption */ - if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8, - (unsigned char *)in, /* inbuflen */ 8) - && SECSuccess == PK11_Finalize(ctx)) - rv = /* all OK */ TRUE; - -fail: - /* cleanup */ - if(ctx) - PK11_DestroyContext(ctx, PR_TRUE); - if(symkey) - PK11_FreeSymKey(symkey); - if(param) - SECITEM_FreeItem(param, PR_TRUE); - PK11_FreeSlot(slot); - return rv; -} - -#endif /* defined(USE_NSS) */ - -#endif /* defined(USE_SSLEAY) */ - - /* - * takes a 21 byte array and treats it as 3 56-bit DES keys. The - * 8 byte plaintext is encrypted with each key and the resulting 24 - * bytes are stored in the results array. - */ -static void lm_resp(const unsigned char *keys, - const unsigned char *plaintext, - unsigned char *results) -{ -#ifdef USE_SSLEAY - DES_key_schedule ks; - - setup_des_key(keys, DESKEY(ks)); - DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results, - DESKEY(ks), DES_ENCRYPT); - - setup_des_key(keys+7, DESKEY(ks)); - DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8), - DESKEY(ks), DES_ENCRYPT); - - setup_des_key(keys+14, DESKEY(ks)); - DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16), - DESKEY(ks), DES_ENCRYPT); -#elif defined(USE_GNUTLS) - gcry_cipher_hd_t des; - - gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - setup_des_key(keys, &des); - gcry_cipher_encrypt(des, results, 8, plaintext, 8); - gcry_cipher_close(des); - - gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - setup_des_key(keys+7, &des); - gcry_cipher_encrypt(des, results+8, 8, plaintext, 8); - gcry_cipher_close(des); - - gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - setup_des_key(keys+14, &des); - gcry_cipher_encrypt(des, results+16, 8, plaintext, 8); - gcry_cipher_close(des); -#elif defined(USE_NSS) - encrypt_des(plaintext, results, keys); - encrypt_des(plaintext, results+8, keys+7); - encrypt_des(plaintext, results+16, keys+14); -#endif -} - - -/* - * Set up lanmanager hashed password - */ -static void mk_lm_hash(struct SessionHandle *data, - const char *password, - unsigned char *lmbuffer /* 21 bytes */) -{ - unsigned char pw[14]; - static const unsigned char magic[] = { - 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */ - }; - size_t len = CURLMIN(strlen(password), 14); - - Curl_strntoupper((char *)pw, password, len); - memset(&pw[len], 0, 14-len); - - /* - * The LanManager hashed password needs to be created using the - * password in the network encoding not the host encoding. - */ - if(Curl_convert_to_network(data, (char *)pw, 14)) - return; - - { - /* Create LanManager hashed password. */ - -#ifdef USE_SSLEAY - DES_key_schedule ks; - - setup_des_key(pw, DESKEY(ks)); - DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer, - DESKEY(ks), DES_ENCRYPT); - - setup_des_key(pw+7, DESKEY(ks)); - DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8), - DESKEY(ks), DES_ENCRYPT); -#elif defined(USE_GNUTLS) - gcry_cipher_hd_t des; - - gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - setup_des_key(pw, &des); - gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8); - gcry_cipher_close(des); - - gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - setup_des_key(pw+7, &des); - gcry_cipher_encrypt(des, lmbuffer+8, 8, magic, 8); - gcry_cipher_close(des); -#elif defined(USE_NSS) - encrypt_des(magic, lmbuffer, pw); - encrypt_des(magic, lmbuffer+8, pw+7); -#endif - - memset(lmbuffer + 16, 0, 21 - 16); - } -} - -#if USE_NTRESPONSES -static void ascii_to_unicode_le(unsigned char *dest, const char *src, - size_t srclen) -{ - size_t i; - for (i=0; itype_2) { - free(ntlm->type_2); - ntlm->type_2 = NULL; - } - if(ntlm->has_handles) { - s_pSecFn->DeleteSecurityContext(&ntlm->c_handle); - s_pSecFn->FreeCredentialsHandle(&ntlm->handle); - ntlm->has_handles = 0; - } - if(ntlm->p_identity) { - if(ntlm->identity.User) free(ntlm->identity.User); - if(ntlm->identity.Password) free(ntlm->identity.Password); - if(ntlm->identity.Domain) free(ntlm->identity.Domain); - ntlm->p_identity = NULL; - } -} - -#endif - -#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff) -#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \ - (((x) >>16)&0xff), (((x)>>24) & 0xff) - -#define HOSTNAME_MAX 1024 - -/* this is for creating ntlm header output */ -CURLcode Curl_output_ntlm(struct connectdata *conn, - bool proxy) -{ - const char *domain=""; /* empty */ - char host [HOSTNAME_MAX+ 1] = ""; /* empty */ -#ifndef USE_WINDOWS_SSPI - size_t domlen = strlen(domain); - size_t hostlen = strlen(host); - size_t hostoff; /* host name offset */ - size_t domoff; /* domain name offset */ -#endif - size_t size; - char *base64=NULL; - unsigned char ntlmbuf[1024]; /* enough, unless the user+host+domain is very - long */ - - /* point to the address of the pointer that holds the string to sent to the - server, which is for a plain host or for a HTTP proxy */ - char **allocuserpwd; - - /* point to the name and password for this */ - const char *userp; - const char *passwdp; - /* point to the correct struct with this */ - struct ntlmdata *ntlm; - struct auth *authp; - - DEBUGASSERT(conn); - DEBUGASSERT(conn->data); - -#ifdef USE_NSS - if(CURLE_OK != Curl_nss_force_init(conn->data)) - return CURLE_OUT_OF_MEMORY; -#endif - - if(proxy) { - allocuserpwd = &conn->allocptr.proxyuserpwd; - userp = conn->proxyuser; - passwdp = conn->proxypasswd; - ntlm = &conn->proxyntlm; - authp = &conn->data->state.authproxy; - } - else { - allocuserpwd = &conn->allocptr.userpwd; - userp = conn->user; - passwdp = conn->passwd; - ntlm = &conn->ntlm; - authp = &conn->data->state.authhost; - } - authp->done = FALSE; - - /* not set means empty */ - if(!userp) - userp=""; - - if(!passwdp) - passwdp=""; - -#ifdef USE_WINDOWS_SSPI - if (s_hSecDll == NULL) { - /* not thread safe and leaks - use curl_global_init() to avoid */ - CURLcode err = Curl_sspi_global_init(); - if (s_hSecDll == NULL) - return err; - } -#endif - - switch(ntlm->state) { - case NTLMSTATE_TYPE1: - default: /* for the weird cases we (re)start here */ -#ifdef USE_WINDOWS_SSPI - { - SecBuffer buf; - SecBufferDesc desc; - SECURITY_STATUS status; - ULONG attrs; - const char *user; - int domlen; - TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */ - - ntlm_sspi_cleanup(ntlm); - - user = strchr(userp, '\\'); - if(!user) - user = strchr(userp, '/'); - - if(user) { - domain = userp; - domlen = user - userp; - user++; - } - else { - user = userp; - domain = ""; - domlen = 0; - } - - if(user && *user) { - /* note: initialize all of this before doing the mallocs so that - * it can be cleaned up later without leaking memory. - */ - ntlm->p_identity = &ntlm->identity; - memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity)); - if((ntlm->identity.User = (unsigned char *)strdup(user)) == NULL) - return CURLE_OUT_OF_MEMORY; - ntlm->identity.UserLength = strlen(user); - if((ntlm->identity.Password = (unsigned char *)strdup(passwdp)) == NULL) - return CURLE_OUT_OF_MEMORY; - ntlm->identity.PasswordLength = strlen(passwdp); - if((ntlm->identity.Domain = malloc(domlen+1)) == NULL) - return CURLE_OUT_OF_MEMORY; - strncpy((char *)ntlm->identity.Domain, domain, domlen); - ntlm->identity.Domain[domlen] = '\0'; - ntlm->identity.DomainLength = domlen; - ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; - } - else { - ntlm->p_identity = NULL; - } - - if(s_pSecFn->AcquireCredentialsHandleA( - NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity, - NULL, NULL, &ntlm->handle, &tsDummy - ) != SEC_E_OK) { - return CURLE_OUT_OF_MEMORY; - } - - desc.ulVersion = SECBUFFER_VERSION; - desc.cBuffers = 1; - desc.pBuffers = &buf; - buf.cbBuffer = sizeof(ntlmbuf); - buf.BufferType = SECBUFFER_TOKEN; - buf.pvBuffer = ntlmbuf; - - status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL, - (char *) host, - ISC_REQ_CONFIDENTIALITY | - ISC_REQ_REPLAY_DETECT | - ISC_REQ_CONNECTION, - 0, SECURITY_NETWORK_DREP, - NULL, 0, - &ntlm->c_handle, &desc, - &attrs, &tsDummy); - - if(status == SEC_I_COMPLETE_AND_CONTINUE || - status == SEC_I_CONTINUE_NEEDED) { - s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc); - } - else if(status != SEC_E_OK) { - s_pSecFn->FreeCredentialsHandle(&ntlm->handle); - return CURLE_RECV_ERROR; - } - - ntlm->has_handles = 1; - size = buf.cbBuffer; - } -#else - hostoff = 0; - domoff = hostoff + hostlen; /* This is 0: remember that host and domain - are empty */ - - /* Create and send a type-1 message: - - Index Description Content - 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" - (0x4e544c4d53535000) - 8 NTLM Message Type long (0x01000000) - 12 Flags long - 16 Supplied Domain security buffer(*) - 24 Supplied Workstation security buffer(*) - 32 start of data block - - */ -#if USE_NTLM2SESSION -#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY -#else -#define NTLM2FLAG 0 -#endif - snprintf((char *)ntlmbuf, sizeof(ntlmbuf), NTLMSSP_SIGNATURE "%c" - "\x01%c%c%c" /* 32-bit type = 1 */ - "%c%c%c%c" /* 32-bit NTLM flag field */ - "%c%c" /* domain length */ - "%c%c" /* domain allocated space */ - "%c%c" /* domain name offset */ - "%c%c" /* 2 zeroes */ - "%c%c" /* host length */ - "%c%c" /* host allocated space */ - "%c%c" /* host name offset */ - "%c%c" /* 2 zeroes */ - "%s" /* host name */ - "%s", /* domain string */ - 0, /* trailing zero */ - 0,0,0, /* part of type-1 long */ - - LONGQUARTET( - NTLMFLAG_NEGOTIATE_OEM| - NTLMFLAG_REQUEST_TARGET| - NTLMFLAG_NEGOTIATE_NTLM_KEY| - NTLM2FLAG| - NTLMFLAG_NEGOTIATE_ALWAYS_SIGN - ), - SHORTPAIR(domlen), - SHORTPAIR(domlen), - SHORTPAIR(domoff), - 0,0, - SHORTPAIR(hostlen), - SHORTPAIR(hostlen), - SHORTPAIR(hostoff), - 0,0, - host /* this is empty */, domain /* this is empty */); - - /* initial packet length */ - size = 32 + hostlen + domlen; -#endif - - DEBUG_OUT({ - fprintf(stderr, "**** TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ", - LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM| - NTLMFLAG_REQUEST_TARGET| - NTLMFLAG_NEGOTIATE_NTLM_KEY| - NTLM2FLAG| - NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), - NTLMFLAG_NEGOTIATE_OEM| - NTLMFLAG_REQUEST_TARGET| - NTLMFLAG_NEGOTIATE_NTLM_KEY| - NTLM2FLAG| - NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); - print_flags(stderr, - NTLMFLAG_NEGOTIATE_OEM| - NTLMFLAG_REQUEST_TARGET| - NTLMFLAG_NEGOTIATE_NTLM_KEY| - NTLM2FLAG| - NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); - fprintf(stderr, "\n****\n"); - }); - - /* now size is the size of the base64 encoded package size */ - size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64); - - if(size >0 ) { - Curl_safefree(*allocuserpwd); - *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", - proxy?"Proxy-":"", - base64); - DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); - free(base64); - } - else - return CURLE_OUT_OF_MEMORY; /* FIX TODO */ - - break; - - case NTLMSTATE_TYPE2: - /* We received the type-2 message already, create a type-3 message: - - Index Description Content - 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" - (0x4e544c4d53535000) - 8 NTLM Message Type long (0x03000000) - 12 LM/LMv2 Response security buffer(*) - 20 NTLM/NTLMv2 Response security buffer(*) - 28 Domain Name security buffer(*) - 36 User Name security buffer(*) - 44 Workstation Name security buffer(*) - (52) Session Key (optional) security buffer(*) - (60) Flags (optional) long - 52 (64) start of data block - - */ - - { -#ifdef USE_WINDOWS_SSPI - SecBuffer type_2, type_3; - SecBufferDesc type_2_desc, type_3_desc; - SECURITY_STATUS status; - ULONG attrs; - TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */ - - type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION; - type_2_desc.cBuffers = type_3_desc.cBuffers = 1; - type_2_desc.pBuffers = &type_2; - type_3_desc.pBuffers = &type_3; - - type_2.BufferType = SECBUFFER_TOKEN; - type_2.pvBuffer = ntlm->type_2; - type_2.cbBuffer = ntlm->n_type_2; - type_3.BufferType = SECBUFFER_TOKEN; - type_3.pvBuffer = ntlmbuf; - type_3.cbBuffer = sizeof(ntlmbuf); - - status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, &ntlm->c_handle, - (char *) host, - ISC_REQ_CONFIDENTIALITY | - ISC_REQ_REPLAY_DETECT | - ISC_REQ_CONNECTION, - 0, SECURITY_NETWORK_DREP, &type_2_desc, - 0, &ntlm->c_handle, &type_3_desc, - &attrs, &tsDummy); - - if(status != SEC_E_OK) - return CURLE_RECV_ERROR; - - size = type_3.cbBuffer; - - ntlm_sspi_cleanup(ntlm); - -#else - int lmrespoff; - unsigned char lmresp[24]; /* fixed-size */ -#if USE_NTRESPONSES - int ntrespoff; - unsigned char ntresp[24]; /* fixed-size */ -#endif - size_t useroff; - const char *user; - size_t userlen; - - user = strchr(userp, '\\'); - if(!user) - user = strchr(userp, '/'); - - if(user) { - domain = userp; - domlen = (user - domain); - user++; - } - else - user = userp; - userlen = strlen(user); - - if(Curl_gethostname(host, HOSTNAME_MAX)) { - infof(conn->data, "gethostname() failed, continuing without!"); - hostlen = 0; - } - else { - /* If the workstation if configured with a full DNS name (i.e. - * workstation.somewhere.net) gethostname() returns the fully qualified - * name, which NTLM doesn't like. - */ - char *dot = strchr(host, '.'); - if(dot) - *dot = '\0'; - hostlen = strlen(host); - } - -#if USE_NTLM2SESSION - /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ - if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) { - unsigned char ntbuffer[0x18]; - unsigned char tmp[0x18]; - unsigned char md5sum[MD5_DIGEST_LENGTH]; - unsigned char entropy[8]; - - /* Need to create 8 bytes random data */ -#ifdef USE_SSLEAY - MD5_CTX MD5pw; - Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */ - RAND_bytes(entropy,8); -#elif defined(USE_GNUTLS) - gcry_md_hd_t MD5pw; - Curl_gtls_seed(conn->data); /* Initiate the seed if not already done */ - gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM); -#elif defined(USE_NSS) - PK11Context *MD5pw; - unsigned int outlen; - Curl_nss_seed(conn->data); /* Initiate the seed if not already done */ - PK11_GenerateRandom(entropy, 8); -#endif - - /* 8 bytes random data as challenge in lmresp */ - memcpy(lmresp,entropy,8); - /* Pad with zeros */ - memset(lmresp+8,0,0x10); - - /* Fill tmp with challenge(nonce?) + entropy */ - memcpy(tmp,&ntlm->nonce[0],8); - memcpy(tmp+8,entropy,8); - -#ifdef USE_SSLEAY - MD5_Init(&MD5pw); - MD5_Update(&MD5pw, tmp, 16); - MD5_Final(md5sum, &MD5pw); -#elif defined(USE_GNUTLS) - gcry_md_open(&MD5pw, GCRY_MD_MD5, 0); - gcry_md_write(MD5pw, tmp, MD5_DIGEST_LENGTH); - memcpy(md5sum, gcry_md_read (MD5pw, 0), MD5_DIGEST_LENGTH); - gcry_md_close(MD5pw); -#elif defined(USE_NSS) - MD5pw = PK11_CreateDigestContext(SEC_OID_MD5); - PK11_DigestOp(MD5pw, tmp, 16); - PK11_DigestFinal(MD5pw, md5sum, &outlen, MD5_DIGEST_LENGTH); - PK11_DestroyContext(MD5pw, PR_TRUE); -#endif - - /* We shall only use the first 8 bytes of md5sum, - but the des code in lm_resp only encrypt the first 8 bytes */ - if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY) - return CURLE_OUT_OF_MEMORY; - lm_resp(ntbuffer, md5sum, ntresp); - - /* End of NTLM2 Session code */ - } - else -#endif - { - -#if USE_NTRESPONSES - unsigned char ntbuffer[0x18]; -#endif - unsigned char lmbuffer[0x18]; - -#if USE_NTRESPONSES - if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY) - return CURLE_OUT_OF_MEMORY; - lm_resp(ntbuffer, &ntlm->nonce[0], ntresp); -#endif - - mk_lm_hash(conn->data, passwdp, lmbuffer); - lm_resp(lmbuffer, &ntlm->nonce[0], lmresp); - /* A safer but less compatible alternative is: - * lm_resp(ntbuffer, &ntlm->nonce[0], lmresp); - * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */ - } - - lmrespoff = 64; /* size of the message header */ -#if USE_NTRESPONSES - ntrespoff = lmrespoff + 0x18; - domoff = ntrespoff + 0x18; -#else - domoff = lmrespoff + 0x18; -#endif - useroff = domoff + domlen; - hostoff = useroff + userlen; - - /* - * In the case the server sets the flag NTLMFLAG_NEGOTIATE_UNICODE, we - * need to filter it off because libcurl doesn't UNICODE encode the - * strings it packs into the NTLM authenticate packet. - */ - ntlm->flags &= ~NTLMFLAG_NEGOTIATE_UNICODE; - - /* Create the big type-3 message binary blob */ - size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf), - NTLMSSP_SIGNATURE "%c" - "\x03%c%c%c" /* type-3, 32 bits */ - - "%c%c" /* LanManager length */ - "%c%c" /* LanManager allocated space */ - "%c%c" /* LanManager offset */ - "%c%c" /* 2 zeroes */ - - "%c%c" /* NT-response length */ - "%c%c" /* NT-response allocated space */ - "%c%c" /* NT-response offset */ - "%c%c" /* 2 zeroes */ - - "%c%c" /* domain length */ - "%c%c" /* domain allocated space */ - "%c%c" /* domain name offset */ - "%c%c" /* 2 zeroes */ - - "%c%c" /* user length */ - "%c%c" /* user allocated space */ - "%c%c" /* user offset */ - "%c%c" /* 2 zeroes */ - - "%c%c" /* host length */ - "%c%c" /* host allocated space */ - "%c%c" /* host offset */ - "%c%c" /* 2 zeroes */ - - "%c%c" /* session key length (unknown purpose) */ - "%c%c" /* session key allocated space (unknown purpose) */ - "%c%c" /* session key offset (unknown purpose) */ - "%c%c" /* 2 zeroes */ - - "%c%c%c%c" /* flags */ - - /* domain string */ - /* user string */ - /* host string */ - /* LanManager response */ - /* NT response */ - , - 0, /* zero termination */ - 0,0,0, /* type-3 long, the 24 upper bits */ - - SHORTPAIR(0x18), /* LanManager response length, twice */ - SHORTPAIR(0x18), - SHORTPAIR(lmrespoff), - 0x0, 0x0, - -#if USE_NTRESPONSES - SHORTPAIR(0x18), /* NT-response length, twice */ - SHORTPAIR(0x18), - SHORTPAIR(ntrespoff), - 0x0, 0x0, -#else - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, -#endif - SHORTPAIR(domlen), - SHORTPAIR(domlen), - SHORTPAIR(domoff), - 0x0, 0x0, - - SHORTPAIR(userlen), - SHORTPAIR(userlen), - SHORTPAIR(useroff), - 0x0, 0x0, - - SHORTPAIR(hostlen), - SHORTPAIR(hostlen), - SHORTPAIR(hostoff), - 0x0, 0x0, - - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, - 0x0, 0x0, - - LONGQUARTET(ntlm->flags)); - DEBUGASSERT(size==64); - - DEBUGASSERT(size == (size_t)lmrespoff); - /* We append the binary hashes */ - if(size < (sizeof(ntlmbuf) - 0x18)) { - memcpy(&ntlmbuf[size], lmresp, 0x18); - size += 0x18; - } - - DEBUG_OUT({ - fprintf(stderr, "**** TYPE3 header lmresp="); - print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18); - }); - -#if USE_NTRESPONSES - if(size < (sizeof(ntlmbuf) - 0x18)) { - DEBUGASSERT(size == (size_t)ntrespoff); - memcpy(&ntlmbuf[size], ntresp, 0x18); - size += 0x18; - } - - DEBUG_OUT({ - fprintf(stderr, "\n ntresp="); - print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18); - }); - -#endif - - DEBUG_OUT({ - fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ", - LONGQUARTET(ntlm->flags), ntlm->flags); - print_flags(stderr, ntlm->flags); - fprintf(stderr, "\n****\n"); - }); - - - /* Make sure that the domain, user and host strings fit in the target - buffer before we copy them there. */ - if(size + userlen + domlen + hostlen >= sizeof(ntlmbuf)) { - failf(conn->data, "user + domain + host name too big"); - return CURLE_OUT_OF_MEMORY; - } - - DEBUGASSERT(size == domoff); - memcpy(&ntlmbuf[size], domain, domlen); - size += domlen; - - DEBUGASSERT(size == useroff); - memcpy(&ntlmbuf[size], user, userlen); - size += userlen; - - DEBUGASSERT(size == hostoff); - memcpy(&ntlmbuf[size], host, hostlen); - size += hostlen; - - /* convert domain, user, and host to ASCII but leave the rest as-is */ - if(Curl_convert_to_network(conn->data, (char *)&ntlmbuf[domoff], - size-domoff)) - return CURLE_CONV_FAILED; - -#endif - - /* convert the binary blob into base64 */ - size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64); - - if(size >0 ) { - Curl_safefree(*allocuserpwd); - *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", - proxy?"Proxy-":"", - base64); - DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); - free(base64); - } - else - return CURLE_OUT_OF_MEMORY; /* FIX TODO */ - - ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ - authp->done = TRUE; - } - break; - - case NTLMSTATE_TYPE3: - /* connection is already authenticated, - * don't send a header in future requests */ - if(*allocuserpwd) { - free(*allocuserpwd); - *allocuserpwd=NULL; - } - authp->done = TRUE; - break; - } - - return CURLE_OK; -} - - -void -Curl_ntlm_cleanup(struct connectdata *conn) -{ -#ifdef USE_WINDOWS_SSPI - ntlm_sspi_cleanup(&conn->ntlm); - ntlm_sspi_cleanup(&conn->proxyntlm); -#else - (void)conn; -#endif -} - - -#endif /* USE_NTLM */ -#endif /* !CURL_DISABLE_HTTP */ diff --git a/third_party/curl/lib/http_ntlm.h b/third_party/curl/lib/http_ntlm.h deleted file mode 100644 index c7422d701..000000000 --- a/third_party/curl/lib/http_ntlm.h +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef __HTTP_NTLM_H -#define __HTTP_NTLM_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -typedef enum { - CURLNTLM_NONE, /* not a ntlm */ - CURLNTLM_BAD, /* an ntlm, but one we don't like */ - CURLNTLM_FIRST, /* the first 401-reply we got with NTLM */ - CURLNTLM_FINE, /* an ntlm we act on */ - - CURLNTLM_LAST /* last entry in this enum, don't use */ -} CURLntlm; - -/* this is for ntlm header input */ -CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy, - const char *header); - -/* this is for creating ntlm header output */ -CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy); - -void Curl_ntlm_cleanup(struct connectdata *conn); -#ifndef USE_NTLM -#define Curl_ntlm_cleanup(x) -#endif - -/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */ - -#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0) -/* Indicates that Unicode strings are supported for use in security buffer - data. */ - -#define NTLMFLAG_NEGOTIATE_OEM (1<<1) -/* Indicates that OEM strings are supported for use in security buffer data. */ - -#define NTLMFLAG_REQUEST_TARGET (1<<2) -/* Requests that the server's authentication realm be included in the Type 2 - message. */ - -/* unknown (1<<3) */ -#define NTLMFLAG_NEGOTIATE_SIGN (1<<4) -/* Specifies that authenticated communication between the client and server - should carry a digital signature (message integrity). */ - -#define NTLMFLAG_NEGOTIATE_SEAL (1<<5) -/* Specifies that authenticated communication between the client and server - should be encrypted (message confidentiality). */ - -#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6) -/* Indicates that datagram authentication is being used. */ - -#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7) -/* Indicates that the LAN Manager session key should be used for signing and - sealing authenticated communications. */ - -#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8) -/* unknown purpose */ - -#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9) -/* Indicates that NTLM authentication is being used. */ - -/* unknown (1<<10) */ - -#define NTLMFLAG_NEGOTIATE_ANONYMOUS (1<<11) -/* Sent by the client in the Type 3 message to indicate that an anonymous - context has been established. This also affects the response fields. */ - -#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12) -/* Sent by the client in the Type 1 message to indicate that a desired - authentication realm is included in the message. */ - -#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13) -/* Sent by the client in the Type 1 message to indicate that the client - workstation's name is included in the message. */ - -#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14) -/* Sent by the server to indicate that the server and client are on the same - machine. Implies that the client may use a pre-established local security - context rather than responding to the challenge. */ - -#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15) -/* Indicates that authenticated communication between the client and server - should be signed with a "dummy" signature. */ - -#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16) -/* Sent by the server in the Type 2 message to indicate that the target - authentication realm is a domain. */ - -#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17) -/* Sent by the server in the Type 2 message to indicate that the target - authentication realm is a server. */ - -#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18) -/* Sent by the server in the Type 2 message to indicate that the target - authentication realm is a share. Presumably, this is for share-level - authentication. Usage is unclear. */ - -#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19) -/* Indicates that the NTLM2 signing and sealing scheme should be used for - protecting authenticated communications. */ - -#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20) -/* unknown purpose */ - -#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21) -/* unknown purpose */ - -#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22) -/* unknown purpose */ - -#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23) -/* Sent by the server in the Type 2 message to indicate that it is including a - Target Information block in the message. */ - -/* unknown (1<24) */ -/* unknown (1<25) */ -/* unknown (1<26) */ -/* unknown (1<27) */ -/* unknown (1<28) */ - -#define NTLMFLAG_NEGOTIATE_128 (1<<29) -/* Indicates that 128-bit encryption is supported. */ - -#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30) -/* Indicates that the client will provide an encrypted master key in - the "Session Key" field of the Type 3 message. */ - -#define NTLMFLAG_NEGOTIATE_56 (1<<31) -/* Indicates that 56-bit encryption is supported. */ -#endif diff --git a/third_party/curl/lib/http_proxy.c b/third_party/curl/lib/http_proxy.c deleted file mode 100644 index 89cfb72c8..000000000 --- a/third_party/curl/lib/http_proxy.c +++ /dev/null @@ -1,513 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) - -#ifdef HAVE_UNISTD_H -#include -#endif -#include "urldata.h" -#include -#include "http_proxy.h" -#include "sendf.h" -#include "http.h" -#include "url.h" -#include "select.h" -#include "rawstr.h" -#include "progress.h" -#include "non-ascii.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curlx.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -/* - * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This - * function will issue the necessary commands to get a seamless tunnel through - * this proxy. After that, the socket can be used just as a normal socket. - * - * This badly needs to be rewritten. CONNECT should be sent and dealt with - * like any ordinary HTTP request, and not specially crafted like this. This - * function only remains here like this for now since the rewrite is a bit too - * much work to do at the moment. - * - * This function is BLOCKING which is nasty for all multi interface using apps. - */ - -CURLcode Curl_proxyCONNECT(struct connectdata *conn, - int sockindex, - const char *hostname, - unsigned short remote_port) -{ - int subversion=0; - struct SessionHandle *data=conn->data; - struct SingleRequest *k = &data->req; - CURLcode result; - long timeout = - data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */ - curl_socket_t tunnelsocket = conn->sock[sockindex]; - curl_off_t cl=0; - bool closeConnection = FALSE; - bool chunked_encoding = FALSE; - long check; - -#define SELECT_OK 0 -#define SELECT_ERROR 1 -#define SELECT_TIMEOUT 2 - int error = SELECT_OK; - - conn->bits.proxy_connect_closed = FALSE; - - do { - if(!conn->bits.tunnel_connecting) { /* BEGIN CONNECT PHASE */ - char *host_port; - Curl_send_buffer *req_buffer; - - infof(data, "Establish HTTP proxy tunnel to %s:%hu\n", - hostname, remote_port); - - if(data->req.newurl) { - /* This only happens if we've looped here due to authentication - reasons, and we don't really use the newly cloned URL here - then. Just free() it. */ - free(data->req.newurl); - data->req.newurl = NULL; - } - - /* initialize a dynamic send-buffer */ - req_buffer = Curl_add_buffer_init(); - - if(!req_buffer) - return CURLE_OUT_OF_MEMORY; - - host_port = aprintf("%s:%hu", hostname, remote_port); - if(!host_port) { - free(req_buffer); - return CURLE_OUT_OF_MEMORY; - } - - /* Setup the proxy-authorization header, if any */ - result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE); - - if(CURLE_OK == result) { - char *host=(char *)""; - const char *proxyconn=""; - const char *useragent=""; - const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ? - "1.0" : "1.1"; - - if(!Curl_checkheaders(data, "Host:")) { - host = aprintf("Host: %s\r\n", host_port); - if(!host) { - free(req_buffer); - free(host_port); - return CURLE_OUT_OF_MEMORY; - } - } - if(!Curl_checkheaders(data, "Proxy-Connection:")) - proxyconn = "Proxy-Connection: Keep-Alive\r\n"; - - if(!Curl_checkheaders(data, "User-Agent:") && - data->set.str[STRING_USERAGENT]) - useragent = conn->allocptr.uagent; - - /* Send the connect request to the proxy */ - /* BLOCKING */ - result = - Curl_add_bufferf(req_buffer, - "CONNECT %s:%hu HTTP/%s\r\n" - "%s" /* Host: */ - "%s" /* Proxy-Authorization */ - "%s" /* User-Agent */ - "%s", /* Proxy-Connection */ - hostname, remote_port, http, - host, - conn->allocptr.proxyuserpwd? - conn->allocptr.proxyuserpwd:"", - useragent, - proxyconn); - - if(host && *host) - free(host); - - if(CURLE_OK == result) - result = Curl_add_custom_headers(conn, req_buffer); - - if(CURLE_OK == result) - /* CRLF terminate the request */ - result = Curl_add_bufferf(req_buffer, "\r\n"); - - if(CURLE_OK == result) { - /* Now send off the request */ - result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, sockindex); - } - req_buffer = NULL; - if(result) - failf(data, "Failed sending CONNECT to proxy"); - } - free(host_port); - Curl_safefree(req_buffer); - if(result) - return result; - - conn->bits.tunnel_connecting = TRUE; - } /* END CONNECT PHASE */ - - /* now we've issued the CONNECT and we're waiting to hear back - - we try not to block here in multi-mode because that might be a LONG - wait if the proxy cannot connect-through to the remote host. */ - - /* if timeout is requested, find out how much remaining time we have */ - check = timeout - /* timeout time */ - Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */ - if(check <= 0) { - failf(data, "Proxy CONNECT aborted due to timeout"); - return CURLE_RECV_ERROR; - } - - /* if we're in multi-mode and we would block, return instead for a retry */ - if(Curl_if_multi == data->state.used_interface) { - if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0)) - /* return so we'll be called again polling-style */ - return CURLE_OK; - else { - DEBUGF(infof(data, - "Multi mode finished polling for response from " - "proxy CONNECT.")); - } - } - else { - DEBUGF(infof(data, "Easy mode waiting response from proxy CONNECT.")); - } - - /* at this point, either: - 1) we're in easy-mode and so it's okay to block waiting for a CONNECT - response - 2) we're in multi-mode and we didn't block - it's either an error or we - now have some data waiting. - In any case, the tunnel_connecting phase is over. */ - conn->bits.tunnel_connecting = FALSE; - - { /* BEGIN NEGOTIATION PHASE */ - size_t nread; /* total size read */ - int perline; /* count bytes per line */ - int keepon=TRUE; - ssize_t gotbytes; - char *ptr; - char *line_start; - - ptr=data->state.buffer; - line_start = ptr; - - nread=0; - perline=0; - keepon=TRUE; - - while((nreadnow); /* spent time */ - if(check <= 0) { - failf(data, "Proxy CONNECT aborted due to timeout"); - error = SELECT_TIMEOUT; /* already too little time */ - break; - } - - /* loop every second at least, less if the timeout is near */ - switch (Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, - check<1000L?(int)check:1000)) { - case -1: /* select() error, stop reading */ - error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted due to select/poll error"); - break; - case 0: /* timeout */ - break; - default: - DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1); - result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, - &gotbytes); - if(result==CURLE_AGAIN) - continue; /* go loop yourself */ - else if(result) - keepon = FALSE; - else if(gotbytes <= 0) { - keepon = FALSE; - if(data->set.proxyauth && data->state.authproxy.avail) { - /* proxy auth was requested and there was proxy auth available, - then deem this as "mere" proxy disconnect */ - conn->bits.proxy_connect_closed = TRUE; - } - else { - error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted"); - } - } - else { - /* - * We got a whole chunk of data, which can be anything from one - * byte to a set of lines and possibly just a piece of the last - * line. - */ - int i; - - nread += gotbytes; - - if(keepon > TRUE) { - /* This means we are currently ignoring a response-body */ - - nread = 0; /* make next read start over in the read buffer */ - ptr=data->state.buffer; - if(cl) { - /* A Content-Length based body: simply count down the counter - and make sure to break out of the loop when we're done! */ - cl -= gotbytes; - if(cl<=0) { - keepon = FALSE; - break; - } - } - else { - /* chunked-encoded body, so we need to do the chunked dance - properly to know when the end of the body is reached */ - CHUNKcode r; - ssize_t tookcareof=0; - - /* now parse the chunked piece of data so that we can - properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof); - if(r == CHUNKE_STOP) { - /* we're done reading chunks! */ - infof(data, "chunk reading DONE\n"); - keepon = FALSE; - } - else - infof(data, "Read %zd bytes of chunk, continue\n", - tookcareof); - } - } - else - for(i = 0; i < gotbytes; ptr++, i++) { - perline++; /* amount of bytes in this line so far */ - if(*ptr == 0x0a) { - char letter; - int writetype; - - /* convert from the network encoding */ - result = Curl_convert_from_network(data, line_start, - perline); - /* Curl_convert_from_network calls failf if unsuccessful */ - if(result) - return result; - - /* output debug if that is requested */ - if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, - line_start, (size_t)perline, conn); - - /* send the header to the callback */ - writetype = CLIENTWRITE_HEADER; - if(data->set.include_header) - writetype |= CLIENTWRITE_BODY; - - result = Curl_client_write(conn, writetype, line_start, - perline); - if(result) - return result; - - /* Newlines are CRLF, so the CR is ignored as the line isn't - really terminated until the LF comes. Treat a following CR - as end-of-headers as well.*/ - - if(('\r' == line_start[0]) || - ('\n' == line_start[0])) { - /* end of response-headers from the proxy */ - nread = 0; /* make next read start over in the read - buffer */ - ptr=data->state.buffer; - if((407 == k->httpcode) && !data->state.authproblem) { - /* If we get a 407 response code with content length - when we have no auth problem, we must ignore the - whole response-body */ - keepon = 2; - - if(cl) { - - infof(data, "Ignore %" FORMAT_OFF_T - " bytes of response-body\n", cl); - /* remove the remaining chunk of what we already - read */ - cl -= (gotbytes - i); - - if(cl<=0) - /* if the whole thing was already read, we are done! - */ - keepon=FALSE; - } - else if(chunked_encoding) { - CHUNKcode r; - /* We set ignorebody true here since the chunked - decoder function will acknowledge that. Pay - attention so that this is cleared again when this - function returns! */ - k->ignorebody = TRUE; - infof(data, "%zd bytes of chunk left\n", gotbytes-i); - - if(line_start[1] == '\n') { - /* this can only be a LF if the letter at index 0 - was a CR */ - line_start++; - i++; - } - - /* now parse the chunked piece of data so that we can - properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, line_start+1, - gotbytes -i, &gotbytes); - if(r == CHUNKE_STOP) { - /* we're done reading chunks! */ - infof(data, "chunk reading DONE\n"); - keepon = FALSE; - } - else - infof(data, "Read %zd bytes of chunk, continue\n", - gotbytes); - } - else { - /* without content-length or chunked encoding, we - can't keep the connection alive since the close is - the end signal so we bail out at once instead */ - keepon=FALSE; - } - } - else - keepon = FALSE; - break; /* breaks out of for-loop, not switch() */ - } - - /* keep a backup of the position we are about to blank */ - letter = line_start[perline]; - line_start[perline]=0; /* zero terminate the buffer */ - if((checkprefix("WWW-Authenticate:", line_start) && - (401 == k->httpcode)) || - (checkprefix("Proxy-authenticate:", line_start) && - (407 == k->httpcode))) { - result = Curl_http_input_auth(conn, k->httpcode, - line_start); - if(result) - return result; - } - else if(checkprefix("Content-Length:", line_start)) { - cl = curlx_strtoofft(line_start + - strlen("Content-Length:"), NULL, 10); - } - else if(Curl_compareheader(line_start, - "Connection:", "close")) - closeConnection = TRUE; - else if(Curl_compareheader(line_start, - "Transfer-Encoding:", - "chunked")) { - infof(data, "CONNECT responded chunked\n"); - chunked_encoding = TRUE; - /* init our chunky engine */ - Curl_httpchunk_init(conn); - } - else if(Curl_compareheader(line_start, - "Proxy-Connection:", "close")) - closeConnection = TRUE; - else if(2 == sscanf(line_start, "HTTP/1.%d %d", - &subversion, - &k->httpcode)) { - /* store the HTTP code from the proxy */ - data->info.httpproxycode = k->httpcode; - } - /* put back the letter we blanked out before */ - line_start[perline]= letter; - - perline=0; /* line starts over here */ - line_start = ptr+1; /* this skips the zero byte we wrote */ - } - } - } - break; - } /* switch */ - if(Curl_pgrsUpdate(conn)) - return CURLE_ABORTED_BY_CALLBACK; - } /* while there's buffer left and loop is requested */ - - if(error) - return CURLE_RECV_ERROR; - - if(data->info.httpproxycode != 200) { - /* Deal with the possibly already received authenticate - headers. 'newurl' is set to a new URL if we must loop. */ - result = Curl_http_auth_act(conn); - if(result) - return result; - - if(conn->bits.close) - /* the connection has been marked for closure, most likely in the - Curl_http_auth_act() function and thus we can kill it at once - below - */ - closeConnection = TRUE; - } - - if(closeConnection && data->req.newurl) { - /* Connection closed by server. Don't use it anymore */ - sclose(conn->sock[sockindex]); - conn->sock[sockindex] = CURL_SOCKET_BAD; - break; - } - } /* END NEGOTIATION PHASE */ - } while(data->req.newurl); - - if(200 != data->req.httpcode) { - failf(data, "Received HTTP code %d from proxy after CONNECT", - data->req.httpcode); - - if(closeConnection && data->req.newurl) - conn->bits.proxy_connect_closed = TRUE; - - return CURLE_RECV_ERROR; - } - - /* If a proxy-authorization header was used for the proxy, then we should - make sure that it isn't accidentally used for the document request - after we've connected. So let's free and clear it here. */ - Curl_safefree(conn->allocptr.proxyuserpwd); - conn->allocptr.proxyuserpwd = NULL; - - data->state.authproxy.done = TRUE; - - infof (data, "Proxy replied OK to CONNECT request\n"); - data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */ - return CURLE_OK; -} -#endif /* CURL_DISABLE_PROXY */ diff --git a/third_party/curl/lib/http_proxy.h b/third_party/curl/lib/http_proxy.h deleted file mode 100644 index 5ea0a21af..000000000 --- a/third_party/curl/lib/http_proxy.h +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) -/* ftp can use this as well */ -CURLcode Curl_proxyCONNECT(struct connectdata *conn, - int tunnelsocket, - const char *hostname, unsigned short remote_port); - -/* Default proxy timeout in milliseconds */ -#define PROXY_TIMEOUT (3600*1000) - -#else -#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN -#endif diff --git a/third_party/curl/lib/idn_win32.c b/third_party/curl/lib/idn_win32.c deleted file mode 100644 index f2df51675..000000000 --- a/third_party/curl/lib/idn_win32.c +++ /dev/null @@ -1,127 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -/*************************************************************************** - * IDN Implementation using windows native APIs - * Pierre Joye - ***************************************************************************/ -#if defined(WIN32) && defined(USE_WIN32_IDN) -#include -#ifdef HAVE_NORMALIZATION_H -#define __in -#define __in_ecount(x) -#define __out_ecount(x) -#include -#endif -#include -#include -#define IDN_MAX_LENGTH 255 - -static wchar_t *_curl_win32_UTF8_to_wchar(const char *str_utf8) -{ - wchar_t *str_w = NULL; - - if (str_utf8) { - int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, - str_utf8, -1, NULL, 0); - if (str_w_len) { - str_w = (wchar_t *) malloc(str_w_len * sizeof(wchar_t)); - if (str_w) { - if (MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w, - str_w_len) == 0) { - free(str_w); - str_w = NULL; - } - } - } - } - - return str_w; -} - -static const char *_curl_win32_wchar_to_UTF8(const wchar_t *str_w) -{ - char *str_utf8 = NULL; - - if (str_w) { - size_t str_utf8_len = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL, - 0, NULL, NULL); - if (str_utf8_len) { - str_utf8 = (char *) malloc(str_utf8_len * sizeof(wchar_t)); - if (str_utf8) { - if (WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len, - NULL, FALSE) == 0) { - (void) GetLastError(); - free((void *)str_utf8); - str_utf8 = NULL; - } - } - } - else { - (void) GetLastError(); - } - } - - return str_utf8; -} - -int curl_win32_idn_to_ascii(const char *in, char **out) -{ - wchar_t *in_w = _curl_win32_UTF8_to_wchar(in); - if (in_w) { - wchar_t punycode[IDN_MAX_LENGTH]; - if (IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH) == 0) { - wprintf(L"ERROR %d converting to Punycode\n", GetLastError()); - free(in_w); - return 0; - } - free(in_w); - - *out = (char *)_curl_win32_wchar_to_UTF8(punycode); - if (!(*out)) { - return 0; - } - } - return 1; -} - -int curl_win32_ascii_to_idn(const char *in, size_t in_len, char **out_utf8) -{ - if (in) { - WCHAR unicode[IDN_MAX_LENGTH]; - - if (IdnToUnicode(0, (wchar_t *)in, -1, unicode, IDN_MAX_LENGTH) == 0) { - wprintf(L"ERROR %d converting to Punycode\n", GetLastError()); - return 0; - } - else { - const char *out_utf8 = _curl_win32_wchar_to_UTF8(unicode); - if (!out_utf8) { - return 0; - } - } - } - return 1; -} -#else -typedef int dummy; /* because ISO C forbids an empty translation unit! */ -#endif - /* WIN32 */ diff --git a/third_party/curl/lib/if2ip.c b/third_party/curl/lib/if2ip.c deleted file mode 100644 index 19504d1fd..000000000 --- a/third_party/curl/lib/if2ip.c +++ /dev/null @@ -1,160 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_ARPA_INET_H -# include -#endif -#ifdef HAVE_NET_IF_H -# include -#endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif -#ifdef HAVE_NETDB_H -# include -#endif -#ifdef HAVE_SYS_SOCKIO_H -# include -#endif -#ifdef HAVE_IFADDRS_H -# include -#endif -#ifdef HAVE_STROPTS_H -# include -#endif -#ifdef __VMS -# include -#endif - -#include "inet_ntop.h" -#include "strequal.h" -#include "if2ip.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* ------------------------------------------------------------------ */ - -#if defined(HAVE_GETIFADDRS) - -char *Curl_if2ip(int af, const char *interface, char *buf, int buf_size) -{ - struct ifaddrs *iface, *head; - char *ip=NULL; - - if (getifaddrs(&head) >= 0) { - for (iface=head; iface != NULL; iface=iface->ifa_next) { - if ((iface->ifa_addr != NULL) && - (iface->ifa_addr->sa_family == af) && - curl_strequal(iface->ifa_name, interface)) { - void *addr; - char scope[12]=""; -#ifdef ENABLE_IPV6 - if (af == AF_INET6) { - unsigned int scopeid = 0; - addr = &((struct sockaddr_in6 *)iface->ifa_addr)->sin6_addr; -#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID - /* Include the scope of this interface as part of the address */ - scopeid = ((struct sockaddr_in6 *)iface->ifa_addr)->sin6_scope_id; -#endif - if (scopeid) - snprintf(scope, sizeof(scope), "%%%u", scopeid); - } - else -#endif - addr = &((struct sockaddr_in *)iface->ifa_addr)->sin_addr; - ip = (char *) Curl_inet_ntop(af, addr, buf, buf_size); - strlcat(buf, scope, buf_size); - break; - } - } - freeifaddrs(head); - } - return ip; -} - -#elif defined(HAVE_IOCTL_SIOCGIFADDR) - -char *Curl_if2ip(int af, const char *interface, char *buf, int buf_size) -{ - struct ifreq req; - struct in_addr in; - struct sockaddr_in *s; - curl_socket_t dummy; - size_t len; - char *ip; - - if(!interface || (af != AF_INET)) - return NULL; - - len = strlen(interface); - if(len >= sizeof(req.ifr_name)) - return NULL; - - dummy = socket(AF_INET, SOCK_STREAM, 0); - if(CURL_SOCKET_BAD == dummy) - return NULL; - - memset(&req, 0, sizeof(req)); - memcpy(req.ifr_name, interface, len+1); - req.ifr_addr.sa_family = AF_INET; - - if(ioctl(dummy, SIOCGIFADDR, &req) < 0) { - sclose(dummy); - return NULL; - } - - s = (struct sockaddr_in *)&req.ifr_addr; - memcpy(&in, &s->sin_addr, sizeof(in)); - ip = (char *) Curl_inet_ntop(s->sin_family, &in, buf, buf_size); - - sclose(dummy); - return ip; -} - -#else - -char *Curl_if2ip(int af, const char *interf, char *buf, int buf_size) -{ - (void) af; - (void) interf; - (void) buf; - (void) buf_size; - return NULL; -} - -#endif diff --git a/third_party/curl/lib/if2ip.h b/third_party/curl/lib/if2ip.h deleted file mode 100644 index cdf2638ae..000000000 --- a/third_party/curl/lib/if2ip.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef __IF2IP_H -#define __IF2IP_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -extern char *Curl_if2ip(int af, const char *interf, char *buf, int buf_size); - -#ifdef __INTERIX -#include - -/* Nedelcho Stanev's work-around for SFU 3.0 */ -struct ifreq { -#define IFNAMSIZ 16 -#define IFHWADDRLEN 6 - union { - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - } ifr_ifrn; - - union { - struct sockaddr ifru_addr; - struct sockaddr ifru_broadaddr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; - short ifru_flags; - int ifru_metric; - int ifru_mtu; - } ifr_ifru; -}; - -/* This define was added by Daniel to avoid an extra #ifdef INTERIX in the - C code. */ - -#define ifr_name ifr_ifrn.ifrn_name /* interface name */ -#define ifr_addr ifr_ifru.ifru_addr /* address */ -#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ -#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ -#define ifr_flags ifr_ifru.ifru_flags /* flags */ -#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ -#define ifr_metric ifr_ifru.ifru_metric /* metric */ -#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ - -#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */ -#endif /* interix */ - -#endif diff --git a/third_party/curl/lib/imap.c b/third_party/curl/lib/imap.c deleted file mode 100644 index 78c412e13..000000000 --- a/third_party/curl/lib/imap.c +++ /dev/null @@ -1,1073 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * RFC3501 IMAPv4 protocol - * RFC5092 IMAP URL Scheme - * - ***************************************************************************/ - -#include "setup.h" - -#ifndef CURL_DISABLE_IMAP -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_UTSNAME_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef __VMS -#include -#include -#endif - -#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) -#undef in_addr_t -#define in_addr_t unsigned long -#endif - -#include -#include "urldata.h" -#include "sendf.h" -#include "if2ip.h" -#include "hostip.h" -#include "progress.h" -#include "transfer.h" -#include "escape.h" -#include "http.h" /* for HTTP proxy tunnel stuff */ -#include "socks.h" -#include "imap.h" - -#include "strtoofft.h" -#include "strequal.h" -#include "sslgen.h" -#include "connect.h" -#include "strerror.h" -#include "select.h" -#include "multiif.h" -#include "url.h" -#include "rawstr.h" -#include "strtoofft.h" -#include "http_proxy.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* Local API functions */ -static CURLcode imap_parse_url_path(struct connectdata *conn); -static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done); -static CURLcode imap_do(struct connectdata *conn, bool *done); -static CURLcode imap_done(struct connectdata *conn, - CURLcode, bool premature); -static CURLcode imap_connect(struct connectdata *conn, bool *done); -static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection); -static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done); -static int imap_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks); -static CURLcode imap_doing(struct connectdata *conn, - bool *dophase_done); -static CURLcode imap_setup_connection(struct connectdata * conn); -static CURLcode imap_state_upgrade_tls(struct connectdata *conn); - -/* - * IMAP protocol handler. - */ - -const struct Curl_handler Curl_handler_imap = { - "IMAP", /* scheme */ - imap_setup_connection, /* setup_connection */ - imap_do, /* do_it */ - imap_done, /* done */ - ZERO_NULL, /* do_more */ - imap_connect, /* connect_it */ - imap_multi_statemach, /* connecting */ - imap_doing, /* doing */ - imap_getsock, /* proto_getsock */ - imap_getsock, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - imap_disconnect, /* disconnect */ - PORT_IMAP, /* defport */ - CURLPROTO_IMAP, /* protocol */ - PROTOPT_CLOSEACTION /* flags */ -}; - - -#ifdef USE_SSL -/* - * IMAPS protocol handler. - */ - -const struct Curl_handler Curl_handler_imaps = { - "IMAPS", /* scheme */ - imap_setup_connection, /* setup_connection */ - imap_do, /* do_it */ - imap_done, /* done */ - ZERO_NULL, /* do_more */ - imap_connect, /* connect_it */ - imap_multi_statemach, /* connecting */ - imap_doing, /* doing */ - imap_getsock, /* proto_getsock */ - imap_getsock, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - imap_disconnect, /* disconnect */ - PORT_IMAPS, /* defport */ - CURLPROTO_IMAP | CURLPROTO_IMAPS, /* protocol */ - PROTOPT_CLOSEACTION | PROTOPT_SSL /* flags */ -}; -#endif - -#ifndef CURL_DISABLE_HTTP -/* - * HTTP-proxyed IMAP protocol handler. - */ - -static const struct Curl_handler Curl_handler_imap_proxy = { - "IMAP", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_IMAP, /* defport */ - CURLPROTO_HTTP, /* protocol */ - PROTOPT_NONE /* flags */ -}; - - -#ifdef USE_SSL -/* - * HTTP-proxyed IMAPS protocol handler. - */ - -static const struct Curl_handler Curl_handler_imaps_proxy = { - "IMAPS", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_IMAPS, /* defport */ - CURLPROTO_HTTP, /* protocol */ - PROTOPT_NONE /* flags */ -}; -#endif -#endif - -/*********************************************************************** - * - * imapsendf() - * - * Sends the formated string as an IMAP command to a server - * - * NOTE: we build the command in a fixed-length buffer, which sets length - * restrictions on the command! - * - * Designed to never block. - */ -static CURLcode imapsendf(struct connectdata *conn, - const char *idstr, /* id to wait for at the - completion of this command */ - const char *fmt, ...) -{ - CURLcode res; - struct imap_conn *imapc = &conn->proto.imapc; - va_list ap; - va_start(ap, fmt); - - imapc->idstr = idstr; /* this is the thing */ - - res = Curl_pp_vsendf(&imapc->pp, fmt, ap); - - va_end(ap); - - return res; -} - -static const char *getcmdid(struct connectdata *conn) -{ - static const char * const ids[]= { - "A", - "B", - "C", - "D" - }; - - struct imap_conn *imapc = &conn->proto.imapc; - - /* get the next id, but wrap at end of table */ - imapc->cmdid = (int)((imapc->cmdid+1) % (sizeof(ids)/sizeof(ids[0]))); - - return ids[imapc->cmdid]; -} - -/* For the IMAP "protocol connect" and "doing" phases only */ -static int imap_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - return Curl_pp_getsock(&conn->proto.imapc.pp, socks, numsocks); -} - -/* function that checks for an imap status code at the start of the - given string */ -static int imap_endofresp(struct pingpong *pp, int *resp) -{ - char *line = pp->linestart_resp; - size_t len = pp->nread_resp; - struct imap_conn *imapc = &pp->conn->proto.imapc; - const char *id = imapc->idstr; - size_t id_len = strlen(id); - - if(len >= id_len + 3) { - if(!memcmp(id, line, id_len) && (line[id_len] == ' ') ) { - /* end of response */ - *resp = line[id_len+1]; /* O, N or B */ - return TRUE; - } - else if((imapc->state == IMAP_FETCH) && - !memcmp("* ", line, 2) ) { - /* FETCH response we're interested in */ - *resp = '*'; - return TRUE; - } - } - return FALSE; /* nothing for us */ -} - -/* This is the ONLY way to change IMAP state! */ -static void state(struct connectdata *conn, - imapstate newstate) -{ -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - /* for debug purposes */ - static const char * const names[]={ - "STOP", - "SERVERGREET", - "LOGIN", - "STARTTLS", - "UPGRADETLS", - "SELECT", - "FETCH", - "LOGOUT", - /* LAST */ - }; -#endif - struct imap_conn *imapc = &conn->proto.imapc; -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - if(imapc->state != newstate) - infof(conn->data, "IMAP %p state change from %s to %s\n", - imapc, names[imapc->state], names[newstate]); -#endif - imapc->state = newstate; -} - -static CURLcode imap_state_login(struct connectdata *conn) -{ - CURLcode result; - struct FTP *imap = conn->data->state.proto.imap; - const char *str; - - str = getcmdid(conn); - - /* send USER and password */ - result = imapsendf(conn, str, "%s LOGIN %s %s", str, - imap->user?imap->user:"", - imap->passwd?imap->passwd:""); - if(result) - return result; - - state(conn, IMAP_LOGIN); - - return CURLE_OK; -} - -#ifdef USE_SSL -static void imap_to_imaps(struct connectdata *conn) -{ - conn->handler = &Curl_handler_imaps; -} -#else -#define imap_to_imaps(x) -#endif - -/* for STARTTLS responses */ -static CURLcode imap_state_starttls_resp(struct connectdata *conn, - int imapcode, - imapstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - (void)instate; /* no use for this yet */ - - if(imapcode != 'O') { - failf(data, "STARTTLS denied. %c", imapcode); - result = CURLE_LOGIN_DENIED; - } - else { - if(data->state.used_interface == Curl_if_multi) { - state(conn, IMAP_UPGRADETLS); - return imap_state_upgrade_tls(conn); - } - else { - result = Curl_ssl_connect(conn, FIRSTSOCKET); - if(CURLE_OK == result) { - imap_to_imaps(conn); - result = imap_state_login(conn); - } - } - } - state(conn, IMAP_STOP); - return result; -} - -static CURLcode imap_state_upgrade_tls(struct connectdata *conn) -{ - struct imap_conn *imapc = &conn->proto.imapc; - CURLcode result; - - result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); - - if(imapc->ssldone) { - imap_to_imaps(conn); - result = imap_state_login(conn); - state(conn, IMAP_STOP); - } - - return result; -} - -/* for LOGIN responses */ -static CURLcode imap_state_login_resp(struct connectdata *conn, - int imapcode, - imapstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - (void)instate; /* no use for this yet */ - - if(imapcode != 'O') { - failf(data, "Access denied. %c", imapcode); - result = CURLE_LOGIN_DENIED; - } - - state(conn, IMAP_STOP); - return result; -} - -/* for the (first line of) FETCH BODY[TEXT] response */ -static CURLcode imap_state_fetch_resp(struct connectdata *conn, - int imapcode, - imapstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - struct imap_conn *imapc = &conn->proto.imapc; - struct FTP *imap = data->state.proto.imap; - struct pingpong *pp = &imapc->pp; - const char *ptr = data->state.buffer; - (void)instate; /* no use for this yet */ - - if('*' != imapcode) { - Curl_pgrsSetDownloadSize(data, 0); - state(conn, IMAP_STOP); - return CURLE_OK; - } - - /* Something like this comes "* 1 FETCH (BODY[TEXT] {2021}\r" */ - while(*ptr && (*ptr != '{')) - ptr++; - - if(*ptr == '{') { - curl_off_t filesize = curlx_strtoofft(ptr+1, NULL, 10); - if(filesize) - Curl_pgrsSetDownloadSize(data, filesize); - - infof(data, "Found %" FORMAT_OFF_TU " bytes to download\n", filesize); - - if(pp->cache) { - /* At this point there is a bunch of data in the header "cache" that is - actually body content, send it as body and then skip it. Do note - that there may even be additional "headers" after the body. */ - size_t chunk = pp->cache_size; - - if(chunk > (size_t)filesize) - /* the conversion from curl_off_t to size_t is always fine here */ - chunk = (size_t)filesize; - - result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk); - if(result) - return result; - - filesize -= chunk; - - /* we've now used parts of or the entire cache */ - if(pp->cache_size > chunk) { - /* part of, move the trailing data to the start and reduce the size */ - memmove(pp->cache, pp->cache+chunk, - pp->cache_size - chunk); - pp->cache_size -= chunk; - } - else { - /* cache is drained */ - free(pp->cache); - pp->cache = NULL; - pp->cache_size = 0; - } - } - - infof(data, "Filesize left: %" FORMAT_OFF_T "\n", filesize); - - if(!filesize) - /* the entire data is already transferred! */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - else - /* IMAP download */ - Curl_setup_transfer(conn, FIRSTSOCKET, filesize, FALSE, - imap->bytecountp, -1, NULL); /* no upload here */ - - data->req.maxdownload = filesize; - } - else - /* We don't know how to parse this line */ - result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */ - - state(conn, IMAP_STOP); - return result; -} - -/* start the DO phase */ -static CURLcode imap_select(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct imap_conn *imapc = &conn->proto.imapc; - const char *str; - - str = getcmdid(conn); - - result = imapsendf(conn, str, "%s SELECT %s", str, - imapc->mailbox?imapc->mailbox:""); - if(result) - return result; - - state(conn, IMAP_SELECT); - return result; -} - -static CURLcode imap_fetch(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - const char *str; - - str = getcmdid(conn); - - /* TODO: make this select the correct mail - * Use "1 body[text]" to get the full mail body of mail 1 - */ - result = imapsendf(conn, str, "%s FETCH 1 BODY[TEXT]", str); - if(result) - return result; - - /* - * When issued, the server will respond with a single line similar to - * '* 1 FETCH (BODY[TEXT] {2021}' - * - * Identifying the fetch and how many bytes of contents we can expect. We - * must extract that number before continuing to "download as usual". - */ - - state(conn, IMAP_FETCH); - return result; -} - -/* for SELECT responses */ -static CURLcode imap_state_select_resp(struct connectdata *conn, - int imapcode, - imapstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - (void)instate; /* no use for this yet */ - - if(imapcode != 'O') { - failf(data, "Select failed"); - result = CURLE_LOGIN_DENIED; - } - else - result = imap_fetch(conn); - return result; -} - -static CURLcode imap_statemach_act(struct connectdata *conn) -{ - CURLcode result; - curl_socket_t sock = conn->sock[FIRSTSOCKET]; - struct SessionHandle *data=conn->data; - int imapcode; - struct imap_conn *imapc = &conn->proto.imapc; - struct pingpong *pp = &imapc->pp; - size_t nread = 0; - - /* busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */ - if(imapc->state == IMAP_UPGRADETLS) - return imap_state_upgrade_tls(conn); - - if(pp->sendleft) - return Curl_pp_flushsend(pp); - - /* we read a piece of response */ - result = Curl_pp_readresp(sock, pp, &imapcode, &nread); - if(result) - return result; - - if(imapcode) - /* we have now received a full IMAP server response */ - switch(imapc->state) { - case IMAP_SERVERGREET: - if(imapcode != 'O') { - failf(data, "Got unexpected imap-server response"); - return CURLE_FTP_WEIRD_SERVER_REPLY; - } - - if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) { - /* We don't have a SSL/TLS connection yet, but SSL is requested. Switch - to TLS connection now */ - const char *str; - - str = getcmdid(conn); - result = imapsendf(conn, str, "%s STARTTLS", str); - state(conn, IMAP_STARTTLS); - } - else - result = imap_state_login(conn); - if(result) - return result; - break; - - case IMAP_LOGIN: - result = imap_state_login_resp(conn, imapcode, imapc->state); - break; - - case IMAP_STARTTLS: - result = imap_state_starttls_resp(conn, imapcode, imapc->state); - break; - - case IMAP_FETCH: - result = imap_state_fetch_resp(conn, imapcode, imapc->state); - break; - - case IMAP_SELECT: - result = imap_state_select_resp(conn, imapcode, imapc->state); - break; - - case IMAP_LOGOUT: - /* fallthrough, just stop! */ - default: - /* internal error */ - state(conn, IMAP_STOP); - break; - } - - return result; -} - -/* called repeatedly until done from multi.c */ -static CURLcode imap_multi_statemach(struct connectdata *conn, - bool *done) -{ - struct imap_conn *imapc = &conn->proto.imapc; - CURLcode result; - - if((conn->handler->protocol & CURLPROTO_IMAPS) && !imapc->ssldone) { - result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); - } - else { - result = Curl_pp_multi_statemach(&imapc->pp); - } - - *done = (bool)(imapc->state == IMAP_STOP); - - return result; -} - -static CURLcode imap_easy_statemach(struct connectdata *conn) -{ - struct imap_conn *imapc = &conn->proto.imapc; - struct pingpong *pp = &imapc->pp; - CURLcode result = CURLE_OK; - - while(imapc->state != IMAP_STOP) { - result = Curl_pp_easy_statemach(pp); - if(result) - break; - } - - return result; -} - -/* - * Allocate and initialize the struct IMAP for the current SessionHandle. If - * need be. - */ -static CURLcode imap_init(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - struct FTP *imap = data->state.proto.imap; - if(!imap) { - imap = data->state.proto.imap = calloc(sizeof(struct FTP), 1); - if(!imap) - return CURLE_OUT_OF_MEMORY; - } - - /* get some initial data into the imap struct */ - imap->bytecountp = &data->req.bytecount; - - /* 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. - */ - imap->user = conn->user; - imap->passwd = conn->passwd; - - return CURLE_OK; -} - -/* - * imap_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 is not. When called as - * a part of the easy interface, it will always be TRUE. - */ -static CURLcode imap_connect(struct connectdata *conn, - bool *done) /* see description above */ -{ - CURLcode result; - struct imap_conn *imapc = &conn->proto.imapc; - struct SessionHandle *data=conn->data; - struct pingpong *pp = &imapc->pp; - - *done = FALSE; /* default to not done yet */ - - /* If there already is a protocol-specific struct allocated for this - sessionhandle, deal with it */ - Curl_reset_reqproto(conn); - - result = imap_init(conn); - if(CURLE_OK != result) - return result; - - /* We always support persistent connections on imap */ - conn->bits.close = FALSE; - - pp->response_time = RESP_TIMEOUT; /* set default response time-out */ - pp->statemach_act = imap_statemach_act; - pp->endofresp = imap_endofresp; - pp->conn = conn; - - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - /* for IMAP over HTTP proxy */ - struct HTTP http_proxy; - struct FTP *imap_save; - - /* BLOCKING */ - /* We want "seamless" IMAP operations through HTTP proxy tunnel */ - - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member - * conn->proto.http; we want IMAP through HTTP and we have to change the - * member temporarily for connecting to the HTTP proxy. After - * Curl_proxyCONNECT we have to set back the member to the original struct - * IMAP pointer - */ - imap_save = data->state.proto.imap; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->state.proto.http = &http_proxy; - - result = Curl_proxyCONNECT(conn, FIRSTSOCKET, - conn->host.name, conn->remote_port); - - data->state.proto.imap = imap_save; - - if(CURLE_OK != result) - return result; - } - - if((conn->handler->protocol & CURLPROTO_IMAPS) && - data->state.used_interface != Curl_if_multi) { - /* BLOCKING */ - /* IMAPS is simply imap with SSL for the control channel */ - /* now, perform the SSL initialization for this socket */ - result = Curl_ssl_connect(conn, FIRSTSOCKET); - if(result) - return result; - } - - Curl_pp_init(pp); /* init generic pingpong data */ - - /* When we connect, we start in the state where we await the server greeting - response */ - state(conn, IMAP_SERVERGREET); - imapc->idstr = "*"; /* we start off waiting for a '*' response */ - - if(data->state.used_interface == Curl_if_multi) - result = imap_multi_statemach(conn, done); - else { - result = imap_easy_statemach(conn); - if(!result) - *done = TRUE; - } - - return result; -} - -/*********************************************************************** - * - * imap_done() - * - * The DONE function. This does what needs to be done after a single DO has - * performed. - * - * Input argument is already checked for validity. - */ -static CURLcode imap_done(struct connectdata *conn, CURLcode status, - bool premature) -{ - struct SessionHandle *data = conn->data; - struct FTP *imap = data->state.proto.imap; - CURLcode result=CURLE_OK; - (void)premature; - - if(!imap) - /* When the easy handle is removed from the multi while libcurl is still - * trying to resolve the host name, it seems that the imap struct is not - * yet initialized, but the removal action calls Curl_done() which calls - * this function. So we simply return success if no imap pointer is set. - */ - return CURLE_OK; - - if(status) { - conn->bits.close = TRUE; /* marked for closure */ - result = status; /* use the already set error code */ - } - - /* clear these for next connection */ - imap->transfer = FTPTRANSFER_BODY; - - return result; -} - -/*********************************************************************** - * - * imap_perform() - * - * This is the actual DO function for IMAP. Get a file/directory according to - * the options previously setup. - */ - -static -CURLcode imap_perform(struct connectdata *conn, - bool *connected, /* connect status after PASV / PORT */ - bool *dophase_done) -{ - /* this is IMAP 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 *imap = conn->data->state.proto.imap; - imap->transfer = FTPTRANSFER_INFO; - } - - *dophase_done = FALSE; /* not done yet */ - - /* start the first command in the DO phase */ - result = imap_select(conn); - if(result) - return result; - - /* run the state-machine */ - if(conn->data->state.used_interface == Curl_if_multi) - result = imap_multi_statemach(conn, dophase_done); - else { - result = imap_easy_statemach(conn); - *dophase_done = TRUE; /* with the easy interface we are done here */ - } - *connected = conn->bits.tcpconnect; - - if(*dophase_done) - DEBUGF(infof(conn->data, "DO phase is complete\n")); - - return result; -} - -/*********************************************************************** - * - * imap_do() - * - * This function is registered as 'curl_do' function. It decodes the path - * parts etc as a wrapper to the actual DO function (imap_perform). - * - * The input argument is already checked for validity. - */ -static CURLcode imap_do(struct connectdata *conn, bool *done) -{ - CURLcode retcode = CURLE_OK; - - *done = FALSE; /* default to false */ - - /* - Since connections can be re-used between SessionHandles, this might be a - connection already existing but on a fresh SessionHandle struct so we must - make sure we have a good 'struct IMAP' to play with. For new connections, - the struct IMAP is allocated and setup in the imap_connect() function. - */ - Curl_reset_reqproto(conn); - retcode = imap_init(conn); - if(retcode) - return retcode; - - retcode = imap_parse_url_path(conn); - if(retcode) - return retcode; - - retcode = imap_regular_transfer(conn, done); - - return retcode; -} - -/*********************************************************************** - * - * imap_logout() - * - * This should be called before calling sclose(). We should then wait for the - * response from the server before returning. The calling code should then try - * to close the connection. - * - */ -static CURLcode imap_logout(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - const char *str; - - str = getcmdid(conn); - - result = imapsendf(conn, str, "%s LOGOUT", str, NULL); - if(result) - return result; - state(conn, IMAP_LOGOUT); - - result = imap_easy_statemach(conn); - - return result; -} - -/*********************************************************************** - * - * imap_disconnect() - * - * Disconnect from an IMAP server. Cleanup protocol-specific per-connection - * resources. BLOCKING. - */ -static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) -{ - struct imap_conn *imapc= &conn->proto.imapc; - - /* The IMAP session may or may not have been allocated/setup at this - point! */ - if(!dead_connection && imapc->pp.conn) - (void)imap_logout(conn); /* ignore errors on the LOGOUT */ - - Curl_pp_disconnect(&imapc->pp); - - Curl_safefree(imapc->mailbox); - - return CURLE_OK; -} - -/*********************************************************************** - * - * imap_parse_url_path() - * - * Parse the URL path into separate path components. - * - */ -static CURLcode imap_parse_url_path(struct connectdata *conn) -{ - /* the imap struct is already inited in imap_connect() */ - struct imap_conn *imapc = &conn->proto.imapc; - struct SessionHandle *data = conn->data; - const char *path = data->state.path; - int len; - - if(!*path) - path = "INBOX"; - - /* url decode the path and use this mailbox */ - imapc->mailbox = curl_easy_unescape(data, path, 0, &len); - if(!imapc->mailbox) - return CURLE_OUT_OF_MEMORY; - - return CURLE_OK; -} - -/* call this when the DO phase has completed */ -static CURLcode imap_dophase_done(struct connectdata *conn, - bool connected) -{ - struct FTP *imap = conn->data->state.proto.imap; - (void)connected; - - if(imap->transfer != FTPTRANSFER_BODY) - /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - - return CURLE_OK; -} - -/* called from multi.c while DOing */ -static CURLcode imap_doing(struct connectdata *conn, - bool *dophase_done) -{ - CURLcode result; - result = imap_multi_statemach(conn, dophase_done); - - if(*dophase_done) { - result = imap_dophase_done(conn, FALSE /* not connected */); - - DEBUGF(infof(conn->data, "DO phase is complete\n")); - } - return result; -} - -/*********************************************************************** - * - * imap_regular_transfer() - * - * The input argument is already checked for validity. - * - * Performs all commands done before a regular transfer between a local and a - * remote host. - * - */ -static -CURLcode imap_regular_transfer(struct connectdata *conn, - bool *dophase_done) -{ - CURLcode result=CURLE_OK; - bool connected=FALSE; - struct SessionHandle *data = conn->data; - data->req.size = -1; /* make sure this is unknown at this point */ - - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - Curl_pgrsSetUploadSize(data, 0); - Curl_pgrsSetDownloadSize(data, 0); - - result = imap_perform(conn, - &connected, /* have we connected after PASV/PORT */ - dophase_done); /* all commands in the DO-phase done? */ - - if(CURLE_OK == result) { - - if(!*dophase_done) - /* the DO phase has not completed yet */ - return CURLE_OK; - - result = imap_dophase_done(conn, connected); - if(result) - return result; - } - - return result; -} - -static CURLcode imap_setup_connection(struct connectdata * conn) -{ - struct SessionHandle *data = conn->data; - - if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { - /* Unless we have asked to tunnel imap operations through the proxy, we - switch and use HTTP operations only */ -#ifndef CURL_DISABLE_HTTP - if(conn->handler == &Curl_handler_imap) - conn->handler = &Curl_handler_imap_proxy; - else { -#ifdef USE_SSL - conn->handler = &Curl_handler_imaps_proxy; -#else - failf(data, "IMAPS not supported!"); - return CURLE_UNSUPPORTED_PROTOCOL; -#endif - } - /* - * We explicitly mark this connection as persistent here as we're doing - * IMAP over HTTP and thus we accidentally avoid setting this value - * otherwise. - */ - conn->bits.close = FALSE; -#else - failf(data, "IMAP over http proxy requires HTTP support built-in!"); - return CURLE_UNSUPPORTED_PROTOCOL; -#endif - } - - data->state.path++; /* don't include the initial slash */ - - return CURLE_OK; -} - -#endif /* CURL_DISABLE_IMAP */ diff --git a/third_party/curl/lib/imap.h b/third_party/curl/lib/imap.h deleted file mode 100644 index c1395160a..000000000 --- a/third_party/curl/lib/imap.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __IMAP_H -#define __IMAP_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#include "pingpong.h" - -/**************************************************************************** - * IMAP unique setup - ***************************************************************************/ -typedef enum { - IMAP_STOP, /* do nothing state, stops the state machine */ - IMAP_SERVERGREET, /* waiting for the initial greeting immediately after - a connect */ - IMAP_LOGIN, - IMAP_STARTTLS, - IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS (multi mode only) */ - IMAP_SELECT, - IMAP_FETCH, - IMAP_LOGOUT, - IMAP_LAST /* never used */ -} imapstate; - -/* imap_conn is used for struct connection-oriented data in the connectdata - struct */ -struct imap_conn { - struct pingpong pp; - char *mailbox; /* what to FETCH */ - imapstate state; /* always use imap.c:state() to change state! */ - int cmdid; /* id number/index */ - const char *idstr; /* pointer to a string for which to wait for as id */ - bool ssldone; /* is connect() over SSL done? only relevant in multi mode */ -}; - -extern const struct Curl_handler Curl_handler_imap; -extern const struct Curl_handler Curl_handler_imaps; - -#endif /* __IMAP_H */ diff --git a/third_party/curl/lib/inet_ntop.c b/third_party/curl/lib/inet_ntop.c deleted file mode 100644 index 5012fbc4c..000000000 --- a/third_party/curl/lib/inet_ntop.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 1996-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM - * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL - * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Original code by Paul Vixie. "curlified" by Gisle Vanem. - */ - -#include "setup.h" - -#ifndef HAVE_INET_NTOP - -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#include -#include - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "inet_ntop.h" - -#define IN6ADDRSZ 16 -#define INADDRSZ 4 -#define INT16SZ 2 - -/* - * Format an IPv4 address, more or less like inet_ntoa(). - * - * Returns `dst' (as a const) - * Note: - * - uses no statics - * - takes a unsigned char* not an in_addr as input - */ -static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size) -{ - char tmp[sizeof "255.255.255.255"]; - size_t len; - - DEBUGASSERT(size >= 16); - - tmp[0] = '\0'; - (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d", - ((int)((unsigned char)src[0])) & 0xff, - ((int)((unsigned char)src[1])) & 0xff, - ((int)((unsigned char)src[2])) & 0xff, - ((int)((unsigned char)src[3])) & 0xff); - - len = strlen(tmp); - if(len == 0 || len >= size) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - strcpy(dst, tmp); - return dst; -} - -#ifdef ENABLE_IPV6 -/* - * Convert IPv6 binary address into presentation (printable) format. - */ -static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) -{ - /* - * Note that int32_t and int16_t need only be "at least" large enough - * to contain a value of the specified size. On some systems, like - * Crays, there is no such thing as an integer variable with 16 bits. - * Keep this in mind if you think this function should have been coded - * to use pointer overlays. All the world's not a VAX. - */ - char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; - char *tp; - struct { - long base; - long len; - } best, cur; - unsigned long words[IN6ADDRSZ / INT16SZ]; - int i; - - /* Preprocess: - * Copy the input (bytewise) array into a wordwise array. - * Find the longest run of 0x00's in src[] for :: shorthanding. - */ - memset(words, '\0', sizeof(words)); - for (i = 0; i < IN6ADDRSZ; i++) - words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); - - best.base = -1; - cur.base = -1; - best.len = 0; - cur.len = 0; - - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) - { - if(words[i] == 0) - { - if(cur.base == -1) - cur.base = i, cur.len = 1; - else - cur.len++; - } - else if(cur.base != -1) - { - if(best.base == -1 || cur.len > best.len) - best = cur; - cur.base = -1; - } - } - if((cur.base != -1) && (best.base == -1 || cur.len > best.len)) - best = cur; - if(best.base != -1 && best.len < 2) - best.base = -1; - - /* Format the result. - */ - tp = tmp; - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) - { - /* Are we inside the best run of 0x00's? - */ - if(best.base != -1 && i >= best.base && i < (best.base + best.len)) - { - if(i == best.base) - *tp++ = ':'; - continue; - } - - /* Are we following an initial run of 0x00s or any real hex? - */ - if(i != 0) - *tp++ = ':'; - - /* Is this address an encapsulated IPv4? - */ - if(i == 6 && best.base == 0 && - (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) - { - if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - tp += strlen(tp); - break; - } - tp += snprintf(tp, 5, "%lx", words[i]); - } - - /* Was it a trailing run of 0x00's? - */ - if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) - *tp++ = ':'; - *tp++ = '\0'; - - /* Check for overflow, copy, and we're done. - */ - if((size_t)(tp - tmp) > size) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - strcpy(dst, tmp); - return dst; -} -#endif /* ENABLE_IPV6 */ - -/* - * Convert a network format address to presentation format. - * - * Returns pointer to presentation format address (`buf'). - * Returns NULL on error and errno set with the specific - * error, EAFNOSUPPORT or ENOSPC. - * - * On Windows we store the error in the thread errno, not - * in the winsock error code. This is to avoid losing the - * actual last winsock error. So use macro ERRNO to fetch the - * errno this function sets when returning NULL, not SOCKERRNO. - */ -char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size) -{ - switch (af) { - case AF_INET: - return inet_ntop4((const unsigned char*)src, buf, size); -#ifdef ENABLE_IPV6 - case AF_INET6: - return inet_ntop6((const unsigned char*)src, buf, size); -#endif - default: - SET_ERRNO(EAFNOSUPPORT); - return NULL; - } -} -#endif /* HAVE_INET_NTOP */ diff --git a/third_party/curl/lib/inet_ntop.h b/third_party/curl/lib/inet_ntop.h deleted file mode 100644 index 8db9775c8..000000000 --- a/third_party/curl/lib/inet_ntop.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __INET_NTOP_H -#define __INET_NTOP_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size); - -#ifdef HAVE_INET_NTOP -#ifdef HAVE_ARPA_INET_H -#include -#endif -#define Curl_inet_ntop(af,addr,buf,size) \ - inet_ntop(af,addr,buf,(curl_socklen_t)size) -#endif - -#endif /* __INET_NTOP_H */ diff --git a/third_party/curl/lib/inet_pton.c b/third_party/curl/lib/inet_pton.c deleted file mode 100644 index d2a54e9f3..000000000 --- a/third_party/curl/lib/inet_pton.c +++ /dev/null @@ -1,239 +0,0 @@ -/* This is from the BIND 4.9.4 release, modified to compile by itself */ - -/* Copyright (c) 1996 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include "setup.h" - -#ifndef HAVE_INET_PTON - -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#include -#include - -#include "inet_pton.h" - -#define IN6ADDRSZ 16 -#define INADDRSZ 4 -#define INT16SZ 2 - -/* - * WARNING: Don't even consider trying to compile this on a system where - * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. - */ - -static int inet_pton4(const char *src, unsigned char *dst); -#ifdef ENABLE_IPV6 -static int inet_pton6(const char *src, unsigned char *dst); -#endif - -/* int - * inet_pton(af, src, dst) - * convert from presentation format (which usually means ASCII printable) - * to network format (which is usually some kind of binary format). - * return: - * 1 if the address was valid for the specified address family - * 0 if the address wasn't valid (`dst' is untouched in this case) - * -1 if some other error occurred (`dst' is untouched in this case, too) - * notice: - * On Windows we store the error in the thread errno, not - * in the winsock error code. This is to avoid losing the - * actual last winsock error. So use macro ERRNO to fetch the - * errno this function sets when returning (-1), not SOCKERRNO. - * author: - * Paul Vixie, 1996. - */ -int -Curl_inet_pton(int af, const char *src, void *dst) -{ - switch (af) { - case AF_INET: - return (inet_pton4(src, (unsigned char *)dst)); -#ifdef ENABLE_IPV6 - case AF_INET6: - return (inet_pton6(src, (unsigned char *)dst)); -#endif - default: - SET_ERRNO(EAFNOSUPPORT); - return (-1); - } - /* NOTREACHED */ -} - -/* int - * inet_pton4(src, dst) - * like inet_aton() but without all the hexadecimal and shorthand. - * return: - * 1 if `src' is a valid dotted quad, else 0. - * notice: - * does not touch `dst' unless it's returning 1. - * author: - * Paul Vixie, 1996. - */ -static int -inet_pton4(const char *src, unsigned char *dst) -{ - static const char digits[] = "0123456789"; - int saw_digit, octets, ch; - unsigned char tmp[INADDRSZ], *tp; - - saw_digit = 0; - octets = 0; - tp = tmp; - *tp = 0; - while((ch = *src++) != '\0') { - const char *pch; - - if((pch = strchr(digits, ch)) != NULL) { - unsigned int val = *tp * 10 + (unsigned int)(pch - digits); - - if(saw_digit && *tp == 0) - return (0); - if(val > 255) - return (0); - *tp = (unsigned char)val; - if(! saw_digit) { - if(++octets > 4) - return (0); - saw_digit = 1; - } - } - else if(ch == '.' && saw_digit) { - if(octets == 4) - return (0); - *++tp = 0; - saw_digit = 0; - } - else - return (0); - } - if(octets < 4) - return (0); - memcpy(dst, tmp, INADDRSZ); - return (1); -} - -#ifdef ENABLE_IPV6 -/* int - * inet_pton6(src, dst) - * convert presentation level address to network order binary form. - * return: - * 1 if `src' is a valid [RFC1884 2.2] address, else 0. - * notice: - * (1) does not touch `dst' unless it's returning 1. - * (2) :: in a full address is silently ignored. - * credit: - * inspired by Mark Andrews. - * author: - * Paul Vixie, 1996. - */ -static int -inet_pton6(const char *src, unsigned char *dst) -{ - static const char xdigits_l[] = "0123456789abcdef", - xdigits_u[] = "0123456789ABCDEF"; - unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; - const char *xdigits, *curtok; - int ch, saw_xdigit; - size_t val; - - memset((tp = tmp), 0, IN6ADDRSZ); - endp = tp + IN6ADDRSZ; - colonp = NULL; - /* Leading :: requires some special handling. */ - if(*src == ':') - if(*++src != ':') - return (0); - curtok = src; - saw_xdigit = 0; - val = 0; - while((ch = *src++) != '\0') { - const char *pch; - - if((pch = strchr((xdigits = xdigits_l), ch)) == NULL) - pch = strchr((xdigits = xdigits_u), ch); - if(pch != NULL) { - val <<= 4; - val |= (pch - xdigits); - if(++saw_xdigit > 4) - return (0); - continue; - } - if(ch == ':') { - curtok = src; - if(!saw_xdigit) { - if(colonp) - return (0); - colonp = tp; - continue; - } - if(tp + INT16SZ > endp) - return (0); - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - saw_xdigit = 0; - val = 0; - continue; - } - if(ch == '.' && ((tp + INADDRSZ) <= endp) && - inet_pton4(curtok, tp) > 0) { - tp += INADDRSZ; - saw_xdigit = 0; - break; /* '\0' was seen by inet_pton4(). */ - } - return (0); - } - if(saw_xdigit) { - if(tp + INT16SZ > endp) - return (0); - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - } - if(colonp != NULL) { - /* - * Since some memmove()'s erroneously fail to handle - * overlapping regions, we'll do the shift by hand. - */ - const ssize_t n = tp - colonp; - ssize_t i; - - if(tp == endp) - return (0); - for (i = 1; i <= n; i++) { - *(endp - i) = *(colonp + n - i); - *(colonp + n - i) = 0; - } - tp = endp; - } - if(tp != endp) - return (0); - memcpy(dst, tmp, IN6ADDRSZ); - return (1); -} -#endif /* ENABLE_IPV6 */ - -#endif /* HAVE_INET_PTON */ diff --git a/third_party/curl/lib/inet_pton.h b/third_party/curl/lib/inet_pton.h deleted file mode 100644 index d53fddff8..000000000 --- a/third_party/curl/lib/inet_pton.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __INET_PTON_H -#define __INET_PTON_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -int Curl_inet_pton(int, const char *, void *); - -#ifdef HAVE_INET_PTON -#ifdef HAVE_ARPA_INET_H -#include -#endif -#define Curl_inet_pton(x,y,z) inet_pton(x,y,z) -#endif - -#endif /* __INET_PTON_H */ diff --git a/third_party/curl/lib/krb4.c b/third_party/curl/lib/krb4.c deleted file mode 100644 index 2895cedaa..000000000 --- a/third_party/curl/lib/krb4.c +++ /dev/null @@ -1,431 +0,0 @@ -/* This source code was modified by Martin Hedenfalk for - * use in Curl. Martin's latest changes were done 2000-09-18. - * - * It has since been patched away like a madman by Daniel Stenberg to make it - * better applied to curl conditions, and to make it not use globals, pollute - * name space and more. - * - * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * Copyright (c) 2004 - 2010 Daniel Stenberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include "setup.h" - -#ifndef CURL_DISABLE_FTP -#ifdef HAVE_KRB4 - -#include -#ifdef HAVE_NETDB_H -#include -#endif -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include /* for getpid() */ -#endif - -#include "urldata.h" -#include "curl_base64.h" -#include "ftp.h" -#include "sendf.h" -#include "krb4.h" -#include "inet_ntop.h" -#include "curl_memory.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -#define LOCAL_ADDR (&conn->local_addr) -#define REMOTE_ADDR conn->ip_addr->ai_addr -#define myctladdr LOCAL_ADDR -#define hisctladdr REMOTE_ADDR - -struct krb4_data { - des_cblock key; - des_key_schedule schedule; - char name[ANAME_SZ]; - char instance[INST_SZ]; - char realm[REALM_SZ]; -}; - -#ifndef HAVE_STRLCPY -/* if it ever goes non-static, make it Curl_ prefixed! */ -static size_t -strlcpy (char *dst, const char *src, size_t dst_sz) -{ - size_t n; - char *p; - - for (p = dst, n = 0; - n + 1 < dst_sz && *src != '\0'; - ++p, ++src, ++n) - *p = *src; - *p = '\0'; - if(*src == '\0') - return n; - else - return n + strlen (src); -} -#else -size_t strlcpy (char *dst, const char *src, size_t dst_sz); -#endif - -static int -krb4_check_prot(void *app_data, int level) -{ - app_data = NULL; /* prevent compiler warning */ - if(level == PROT_CONFIDENTIAL) - return -1; - return 0; -} - -static int -krb4_decode(void *app_data, void *buf, int len, int level, - struct connectdata *conn) -{ - MSG_DAT m; - int e; - struct krb4_data *d = app_data; - - if(level == PROT_SAFE) - e = krb_rd_safe(buf, len, &d->key, - (struct sockaddr_in *)REMOTE_ADDR, - (struct sockaddr_in *)LOCAL_ADDR, &m); - else - e = krb_rd_priv(buf, len, d->schedule, &d->key, - (struct sockaddr_in *)REMOTE_ADDR, - (struct sockaddr_in *)LOCAL_ADDR, &m); - if(e) { - struct SessionHandle *data = conn->data; - infof(data, "krb4_decode: %s\n", krb_get_err_text(e)); - return -1; - } - memmove(buf, m.app_data, m.app_length); - return m.app_length; -} - -static int -krb4_overhead(void *app_data, int level, int len) -{ - /* no arguments are used, just init them to prevent compiler warnings */ - app_data = NULL; - level = 0; - len = 0; - return 31; -} - -static int -krb4_encode(void *app_data, const void *from, int length, int level, void **to, - struct connectdata *conn) -{ - struct krb4_data *d = app_data; - *to = malloc(length + 31); - if(!*to) - return -1; - if(level == PROT_SAFE) - /* NOTE that the void* cast is safe, krb_mk_safe/priv don't modify the - * input buffer - */ - return krb_mk_safe((void*)from, *to, length, &d->key, - (struct sockaddr_in *)LOCAL_ADDR, - (struct sockaddr_in *)REMOTE_ADDR); - else if(level == PROT_PRIVATE) - return krb_mk_priv((void*)from, *to, length, d->schedule, &d->key, - (struct sockaddr_in *)LOCAL_ADDR, - (struct sockaddr_in *)REMOTE_ADDR); - else - return -1; -} - -static int -mk_auth(struct krb4_data *d, KTEXT adat, - const char *service, char *host, int checksum) -{ - int ret; - CREDENTIALS cred; - char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ]; - - strlcpy(sname, service, sizeof(sname)); - strlcpy(inst, krb_get_phost(host), sizeof(inst)); - strlcpy(realm, krb_realmofhost(host), sizeof(realm)); - ret = krb_mk_req(adat, sname, inst, realm, checksum); - if(ret) - return ret; - strlcpy(sname, service, sizeof(sname)); - strlcpy(inst, krb_get_phost(host), sizeof(inst)); - strlcpy(realm, krb_realmofhost(host), sizeof(realm)); - ret = krb_get_cred(sname, inst, realm, &cred); - memmove(&d->key, &cred.session, sizeof(des_cblock)); - des_key_sched(&d->key, d->schedule); - memset(&cred, 0, sizeof(cred)); - return ret; -} - -#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM -int krb_get_our_ip_for_realm(char *, struct in_addr *); -#endif - -static int -krb4_auth(void *app_data, struct connectdata *conn) -{ - int ret; - char *p; - unsigned char *ptr; - size_t len; - KTEXT_ST adat; - MSG_DAT msg_data; - int checksum; - u_int32_t cs; - struct krb4_data *d = app_data; - char *host = conn->host.name; - ssize_t nread; - int l = sizeof(conn->local_addr); - struct SessionHandle *data = conn->data; - CURLcode result; - - if(getsockname(conn->sock[FIRSTSOCKET], - (struct sockaddr *)LOCAL_ADDR, &l) < 0) - perror("getsockname()"); - - checksum = getpid(); - ret = mk_auth(d, &adat, "ftp", host, checksum); - if(ret == KDC_PR_UNKNOWN) - ret = mk_auth(d, &adat, "rcmd", host, checksum); - if(ret) { - infof(data, "%s\n", krb_get_err_text(ret)); - return AUTH_CONTINUE; - } - -#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM - if(krb_get_config_bool("nat_in_use")) { - struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR; - struct in_addr natAddr; - - if(krb_get_our_ip_for_realm(krb_realmofhost(host), - &natAddr) != KSUCCESS - && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS) - infof(data, "Can't get address for realm %s\n", - krb_realmofhost(host)); - else { - if(natAddr.s_addr != localaddr->sin_addr.s_addr) { - char addr_buf[128]; - if(Curl_inet_ntop(AF_INET, natAddr, addr_buf, sizeof(addr_buf))) - infof(data, "Using NAT IP address (%s) for kerberos 4\n", addr_buf); - localaddr->sin_addr = natAddr; - } - } - } -#endif - - if(Curl_base64_encode(conn->data, (char *)adat.dat, adat.length, &p) < 1) { - Curl_failf(data, "Out of memory base64-encoding"); - return AUTH_CONTINUE; - } - - result = Curl_ftpsendf(conn, "ADAT %s", p); - - free(p); - - if(result) - return -2; - - if(Curl_GetFTPResponse(&nread, conn, NULL)) - return -1; - - if(data->state.buffer[0] != '2'){ - Curl_failf(data, "Server didn't accept auth data"); - return AUTH_ERROR; - } - - p = strstr(data->state.buffer, "ADAT="); - if(!p) { - Curl_failf(data, "Remote host didn't send adat reply"); - return AUTH_ERROR; - } - p += 5; - len = Curl_base64_decode(p, &ptr); - if(len > sizeof(adat.dat)-1) { - free(ptr); - len=0; - } - if(!len || !ptr) { - Curl_failf(data, "Failed to decode base64 from server"); - return AUTH_ERROR; - } - memcpy((char *)adat.dat, ptr, len); - free(ptr); - adat.length = len; - ret = krb_rd_safe(adat.dat, adat.length, &d->key, - (struct sockaddr_in *)hisctladdr, - (struct sockaddr_in *)myctladdr, &msg_data); - if(ret) { - Curl_failf(data, "Error reading reply from server: %s", - krb_get_err_text(ret)); - return AUTH_ERROR; - } - krb_get_int(msg_data.app_data, &cs, 4, 0); - if(cs - checksum != 1) { - Curl_failf(data, "Bad checksum returned from server"); - return AUTH_ERROR; - } - return AUTH_OK; -} - -struct Curl_sec_client_mech Curl_krb4_client_mech = { - "KERBEROS_V4", - sizeof(struct krb4_data), - NULL, /* init */ - krb4_auth, - NULL, /* end */ - krb4_check_prot, - krb4_overhead, - krb4_encode, - krb4_decode -}; - -static enum protection_level -krb4_set_command_prot(struct connectdata *conn, enum protection_level level) -{ - enum protection_level old = conn->command_prot; - DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); - conn->command_prot = level; - return old; -} - -CURLcode Curl_krb_kauth(struct connectdata *conn) -{ - des_cblock key; - des_key_schedule schedule; - KTEXT_ST tkt, tktcopy; - char *name; - char *p; - char passwd[100]; - size_t tmp; - ssize_t nread; - enum protection_level save; - CURLcode result; - unsigned char *ptr; - - save = krb4_set_command_prot(conn, PROT_PRIVATE); - - result = Curl_ftpsendf(conn, "SITE KAUTH %s", conn->user); - - if(result) - return result; - - result = Curl_GetFTPResponse(&nread, conn, NULL); - if(result) - return result; - - if(conn->data->state.buffer[0] != '3'){ - krb4_set_command_prot(conn, save); - return CURLE_FTP_WEIRD_SERVER_REPLY; - } - - p = strstr(conn->data->state.buffer, "T="); - if(!p) { - Curl_failf(conn->data, "Bad reply from server"); - krb4_set_command_prot(conn, save); - return CURLE_FTP_WEIRD_SERVER_REPLY; - } - - p += 2; - tmp = Curl_base64_decode(p, &ptr); - if(tmp >= sizeof(tkt.dat)) { - free(ptr); - tmp=0; - } - if(!tmp || !ptr) { - Curl_failf(conn->data, "Failed to decode base64 in reply"); - krb4_set_command_prot(conn, save); - return CURLE_FTP_WEIRD_SERVER_REPLY; - } - memcpy((char *)tkt.dat, ptr, tmp); - free(ptr); - tkt.length = tmp; - tktcopy.length = tkt.length; - - p = strstr(conn->data->state.buffer, "P="); - if(!p) { - Curl_failf(conn->data, "Bad reply from server"); - krb4_set_command_prot(conn, save); - return CURLE_FTP_WEIRD_SERVER_REPLY; - } - name = p + 2; - for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++); - *p = 0; - - des_string_to_key (conn->passwd, &key); - des_key_sched(&key, schedule); - - des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat, - tkt.length, - schedule, &key, DES_DECRYPT); - if(strcmp ((char*)tktcopy.dat + 8, - KRB_TICKET_GRANTING_TICKET) != 0) { - afs_string_to_key(passwd, - krb_realmofhost(conn->host.name), - &key); - des_key_sched(&key, schedule); - des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat, - tkt.length, - schedule, &key, DES_DECRYPT); - } - memset(key, 0, sizeof(key)); - memset(schedule, 0, sizeof(schedule)); - memset(passwd, 0, sizeof(passwd)); - if(Curl_base64_encode(conn->data, (char *)tktcopy.dat, tktcopy.length, &p) - < 1) { - failf(conn->data, "Out of memory base64-encoding."); - krb4_set_command_prot(conn, save); - return CURLE_OUT_OF_MEMORY; - } - memset (tktcopy.dat, 0, tktcopy.length); - - result = Curl_ftpsendf(conn, "SITE KAUTH %s %s", name, p); - free(p); - if(result) - return result; - - result = Curl_GetFTPResponse(&nread, conn, NULL); - if(result) - return result; - krb4_set_command_prot(conn, save); - - return CURLE_OK; -} - -#endif /* HAVE_KRB4 */ -#endif /* CURL_DISABLE_FTP */ diff --git a/third_party/curl/lib/krb4.h b/third_party/curl/lib/krb4.h deleted file mode 100644 index b3b5ea763..000000000 --- a/third_party/curl/lib/krb4.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __KRB4_H -#define __KRB4_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -struct Curl_sec_client_mech { - const char *name; - size_t size; - int (*init)(void *); - int (*auth)(void *, struct connectdata *); - void (*end)(void *); - int (*check_prot)(void *, int); - int (*overhead)(void *, int, int); - int (*encode)(void *, const void*, int, int, void**, struct connectdata *); - int (*decode)(void *, void*, int, int, struct connectdata *); -}; - - -#define AUTH_OK 0 -#define AUTH_CONTINUE 1 -#define AUTH_ERROR 2 - -#ifdef HAVE_KRB4 -extern struct Curl_sec_client_mech Curl_krb4_client_mech; -#endif -#ifdef HAVE_GSSAPI -extern struct Curl_sec_client_mech Curl_krb5_client_mech; -#endif - -CURLcode Curl_krb_kauth(struct connectdata *conn); -int Curl_sec_read_msg (struct connectdata *conn, char *, enum protection_level); -void Curl_sec_end (struct connectdata *); -CURLcode Curl_sec_login (struct connectdata *); -int Curl_sec_request_prot (struct connectdata *conn, const char *level); - -#endif diff --git a/third_party/curl/lib/krb5.c b/third_party/curl/lib/krb5.c deleted file mode 100644 index e711431cc..000000000 --- a/third_party/curl/lib/krb5.c +++ /dev/null @@ -1,349 +0,0 @@ -/* GSSAPI/krb5 support for FTP - loosely based on old krb4.c - * - * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * Copyright (c) 2004 - 2011 Daniel Stenberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. */ - -#include "setup.h" - -#ifndef CURL_DISABLE_FTP -#ifdef HAVE_GSSAPI - -#ifdef HAVE_OLD_GSSMIT -#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name -#endif - -#include -#ifdef HAVE_NETDB_H -#include -#endif -#include - -#ifdef HAVE_GSSGNU -# include -#elif defined HAVE_GSSMIT - /* MIT style */ -# include -# include -# include -#else - /* Heimdal-style */ -# include -#endif - -#include "urldata.h" -#include "curl_base64.h" -#include "ftp.h" -#include "sendf.h" -#include "krb4.h" -#include "curl_memory.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -#define LOCAL_ADDR (&conn->local_addr) -#define REMOTE_ADDR conn->ip_addr->ai_addr - -static int -krb5_init(void *app_data) -{ - gss_ctx_id_t *context = app_data; - /* Make sure our context is initialized for krb5_end. */ - *context = GSS_C_NO_CONTEXT; - return 0; -} - -static int -krb5_check_prot(void *app_data, int level) -{ - (void)app_data; /* unused */ - if(level == PROT_CONFIDENTIAL) - return -1; - return 0; -} - -static int -krb5_decode(void *app_data, void *buf, int len, int level, - struct connectdata *conn) -{ - gss_ctx_id_t *context = app_data; - OM_uint32 maj, min; - gss_buffer_desc enc, dec; - - /* shut gcc up */ - level = 0; - conn = NULL; - - enc.value = buf; - enc.length = len; - maj = gss_unseal(&min, *context, &enc, &dec, NULL, NULL); - if(maj != GSS_S_COMPLETE) { - if(len >= 4) - strcpy(buf, "599 "); - return -1; - } - - memcpy(buf, dec.value, dec.length); - len = dec.length; - gss_release_buffer(&min, &dec); - - return len; -} - -static int -krb5_overhead(void *app_data, int level, int len) -{ - /* no arguments are used */ - (void)app_data; - (void)level; - (void)len; - return 0; -} - -static int -krb5_encode(void *app_data, const void *from, int length, int level, void **to, - struct connectdata *conn) -{ - gss_ctx_id_t *context = app_data; - gss_buffer_desc dec, enc; - OM_uint32 maj, min; - int state; - int len; - - /* shut gcc up */ - conn = NULL; - - /* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal - * libraries modify the input buffer in gss_seal() - */ - dec.value = (void*)from; - dec.length = length; - maj = gss_seal(&min, *context, - level == PROT_PRIVATE, - GSS_C_QOP_DEFAULT, - &dec, &state, &enc); - - if(maj != GSS_S_COMPLETE) - return -1; - - /* malloc a new buffer, in case gss_release_buffer doesn't work as expected */ - *to = malloc(enc.length); - if(!*to) - return -1; - memcpy(*to, enc.value, enc.length); - len = enc.length; - gss_release_buffer(&min, &enc); - return len; -} - -static int -krb5_auth(void *app_data, struct connectdata *conn) -{ - int ret = AUTH_OK; - char *p; - const char *host = conn->host.name; - ssize_t nread; - curl_socklen_t l = sizeof(conn->local_addr); - struct SessionHandle *data = conn->data; - CURLcode result; - const char *service = "ftp", *srv_host = "host"; - gss_buffer_desc input_buffer, output_buffer, _gssresp, *gssresp; - OM_uint32 maj, min; - gss_name_t gssname; - gss_ctx_id_t *context = app_data; - struct gss_channel_bindings_struct chan; - - if(getsockname(conn->sock[FIRSTSOCKET], - (struct sockaddr *)LOCAL_ADDR, &l) < 0) - perror("getsockname()"); - - chan.initiator_addrtype = GSS_C_AF_INET; - chan.initiator_address.length = l - 4; - chan.initiator_address.value = - &((struct sockaddr_in *)LOCAL_ADDR)->sin_addr.s_addr; - chan.acceptor_addrtype = GSS_C_AF_INET; - chan.acceptor_address.length = l - 4; - chan.acceptor_address.value = - &((struct sockaddr_in *)REMOTE_ADDR)->sin_addr.s_addr; - chan.application_data.length = 0; - chan.application_data.value = NULL; - - /* this loop will execute twice (once for service, once for host) */ - while(1) { - /* this really shouldn't be repeated here, but can't help it */ - if(service == srv_host) { - result = Curl_ftpsendf(conn, "AUTH GSSAPI"); - - if(result) - return -2; - if(Curl_GetFTPResponse(&nread, conn, NULL)) - return -1; - - if(data->state.buffer[0] != '3') - return -1; - } - - input_buffer.value = data->state.buffer; - input_buffer.length = snprintf(input_buffer.value, BUFSIZE, "%s@%s", - service, host); - maj = gss_import_name(&min, &input_buffer, GSS_C_NT_HOSTBASED_SERVICE, - &gssname); - if(maj != GSS_S_COMPLETE) { - gss_release_name(&min, &gssname); - if(service == srv_host) { - Curl_failf(data, "Error importing service name %s", input_buffer.value); - return AUTH_ERROR; - } - service = srv_host; - continue; - } - /* We pass NULL as |output_name_type| to avoid a leak. */ - gss_display_name(&min, gssname, &output_buffer, NULL); - Curl_infof(data, "Trying against %s\n", output_buffer.value); - gssresp = GSS_C_NO_BUFFER; - *context = GSS_C_NO_CONTEXT; - - do { - /* Release the buffer at each iteration to avoid leaking: the first time - we are releasing the memory from gss_display_name. The last item is - taken care by a final gss_release_buffer. */ - gss_release_buffer(&min, &output_buffer); - ret = AUTH_OK; - maj = gss_init_sec_context(&min, - GSS_C_NO_CREDENTIAL, - context, - gssname, - GSS_C_NO_OID, - GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG, - 0, - &chan, - gssresp, - NULL, - &output_buffer, - NULL, - NULL); - - if(gssresp) { - free(_gssresp.value); - gssresp = NULL; - } - - if(GSS_ERROR(maj)) { - Curl_infof(data, "Error creating security context\n"); - ret = AUTH_ERROR; - break; - } - - if(output_buffer.length != 0) { - if(Curl_base64_encode(data, (char *)output_buffer.value, - output_buffer.length, &p) < 1) { - Curl_infof(data, "Out of memory base64-encoding\n"); - ret = AUTH_CONTINUE; - break; - } - - result = Curl_ftpsendf(conn, "ADAT %s", p); - - free(p); - - if(result) { - ret = -2; - break; - } - - if(Curl_GetFTPResponse(&nread, conn, NULL)) { - ret = -1; - break; - } - - if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3'){ - Curl_infof(data, "Server didn't accept auth data\n"); - ret = AUTH_ERROR; - break; - } - - p = data->state.buffer + 4; - p = strstr(p, "ADAT="); - if(p) { - _gssresp.length = Curl_base64_decode(p + 5, (unsigned char **) - &_gssresp.value); - if(_gssresp.length < 1) { - Curl_failf(data, "Out of memory base64-encoding\n"); - ret = AUTH_CONTINUE; - break; - } - } - - gssresp = &_gssresp; - } - } while(maj == GSS_S_CONTINUE_NEEDED); - - gss_release_name(&min, &gssname); - gss_release_buffer(&min, &output_buffer); - - if(gssresp) - free(_gssresp.value); - - if(ret == AUTH_OK || service == srv_host) - return ret; - - service = srv_host; - } - return ret; -} - -static void krb5_end(void *app_data) -{ - OM_uint32 maj, min; - gss_ctx_id_t *context = app_data; - if (*context != GSS_C_NO_CONTEXT) { - maj = gss_delete_sec_context(&min, context, GSS_C_NO_BUFFER); - DEBUGASSERT(maj == GSS_S_COMPLETE); - } -} - -struct Curl_sec_client_mech Curl_krb5_client_mech = { - "GSSAPI", - sizeof(gss_ctx_id_t), - krb5_init, - krb5_auth, - krb5_end, - krb5_check_prot, - krb5_overhead, - krb5_encode, - krb5_decode -}; - -#endif /* HAVE_GSSAPI */ -#endif /* CURL_DISABLE_FTP */ diff --git a/third_party/curl/lib/ldap.c b/third_party/curl/lib/ldap.c deleted file mode 100644 index 3f067230f..000000000 --- a/third_party/curl/lib/ldap.c +++ /dev/null @@ -1,724 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#if !defined(CURL_DISABLE_LDAP) && !defined(USE_OPENLDAP) - -/* - * Notice that USE_OPENLDAP is only a source code selection switch. When - * libcurl is built with USE_OPENLDAP defined the libcurl source code that - * gets compiled is the code from openldap.c, otherwise the code that gets - * compiled is the code from ldap.c. - * - * When USE_OPENLDAP is defined a recent version of the OpenLDAP library - * might be required for compilation and runtime. In order to use ancient - * OpenLDAP library versions, USE_OPENLDAP shall not be defined. - */ - -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include -#include - -#ifdef CURL_LDAP_WIN /* Use Windows LDAP implementation. */ -# include -# ifndef LDAP_VENDOR_NAME -# error Your Platform SDK is NOT sufficient for LDAP support! Update your Platform SDK, or disable LDAP support! -# else -# include -# endif -#else -# define LDAP_DEPRECATED 1 /* Be sure ldap_init() is defined. */ -# ifdef HAVE_LBER_H -# include -# endif -# include -# if (defined(HAVE_LDAP_SSL) && defined(HAVE_LDAP_SSL_H)) -# include -# endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */ -#endif - -#ifdef HAVE_UNISTD_H -# include -#endif - -#include "urldata.h" -#include -#include "sendf.h" -#include "escape.h" -#include "progress.h" -#include "transfer.h" -#include "strequal.h" -#include "strtok.h" -#include "curl_ldap.h" -#include "curl_memory.h" -#include "curl_base64.h" -#include "rawstr.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "memdebug.h" - -#ifndef HAVE_LDAP_URL_PARSE - -/* Use our own implementation. */ - -typedef struct { - char *lud_host; - int lud_port; - char *lud_dn; - char **lud_attrs; - int lud_scope; - char *lud_filter; - char **lud_exts; -} CURL_LDAPURLDesc; - -#undef LDAPURLDesc -#define LDAPURLDesc CURL_LDAPURLDesc - -static int _ldap_url_parse (const struct connectdata *conn, - LDAPURLDesc **ludp); -static void _ldap_free_urldesc (LDAPURLDesc *ludp); - -#undef ldap_free_urldesc -#define ldap_free_urldesc _ldap_free_urldesc -#endif - -#ifdef DEBUG_LDAP - #define LDAP_TRACE(x) do { \ - _ldap_trace ("%u: ", __LINE__); \ - _ldap_trace x; \ - } while(0) - - static void _ldap_trace (const char *fmt, ...); -#else - #define LDAP_TRACE(x) ((void)0) -#endif - - -static CURLcode Curl_ldap(struct connectdata *conn, bool *done); - -/* - * LDAP protocol handler. - */ - -const struct Curl_handler Curl_handler_ldap = { - "LDAP", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_ldap, /* do_it */ - ZERO_NULL, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_LDAP, /* defport */ - CURLPROTO_LDAP, /* protocol */ - PROTOPT_NONE /* flags */ -}; - -#ifdef HAVE_LDAP_SSL -/* - * LDAPS protocol handler. - */ - -const struct Curl_handler Curl_handler_ldaps = { - "LDAPS", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_ldap, /* do_it */ - ZERO_NULL, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_LDAPS, /* defport */ - CURLPROTO_LDAP | CURLPROTO_LDAPS, /* protocol */ - PROTOPT_SSL /* flags */ -}; -#endif - - -static CURLcode Curl_ldap(struct connectdata *conn, bool *done) -{ - CURLcode status = CURLE_OK; - int rc = 0; - LDAP *server = NULL; - LDAPURLDesc *ludp = NULL; - LDAPMessage *result = NULL; - LDAPMessage *entryIterator; - int num = 0; - struct SessionHandle *data=conn->data; - int ldap_proto = LDAP_VERSION3; - int ldap_ssl = 0; - char *val_b64; - size_t val_b64_sz; - curl_off_t dlsize=0; -#ifdef LDAP_OPT_NETWORK_TIMEOUT - struct timeval ldap_timeout = {10,0}; /* 10 sec connection/search timeout */ -#endif - - *done = TRUE; /* unconditionally */ - infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n", - LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION); - infof(data, "LDAP local: %s\n", data->change.url); - -#ifdef HAVE_LDAP_URL_PARSE - rc = ldap_url_parse(data->change.url, &ludp); -#else - rc = _ldap_url_parse(conn, &ludp); -#endif - if(rc != 0) { - failf(data, "LDAP local: %s", ldap_err2string(rc)); - status = CURLE_LDAP_INVALID_URL; - goto quit; - } - - /* Get the URL scheme ( either ldap or ldaps ) */ - if(conn->given->protocol & CURLPROTO_LDAPS) - ldap_ssl = 1; - infof(data, "LDAP local: trying to establish %s connection\n", - ldap_ssl ? "encrypted" : "cleartext"); - -#ifdef LDAP_OPT_NETWORK_TIMEOUT - ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout); -#endif - ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); - - if(ldap_ssl) { -#ifdef HAVE_LDAP_SSL -#ifdef CURL_LDAP_WIN - /* Win32 LDAP SDK doesn't support insecure mode without CA! */ - server = ldap_sslinit(conn->host.name, (int)conn->port, 1); - ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON); -#else - int ldap_option; - char* ldap_ca = data->set.str[STRING_SSL_CAFILE]; -#if defined(CURL_HAS_NOVELL_LDAPSDK) - rc = ldapssl_client_init(NULL, NULL); - if(rc != LDAP_SUCCESS) { - failf(data, "LDAP local: ldapssl_client_init %s", ldap_err2string(rc)); - status = CURLE_SSL_CERTPROBLEM; - goto quit; - } - if(data->set.ssl.verifypeer) { - /* Novell SDK supports DER or BASE64 files. */ - int cert_type = LDAPSSL_CERT_FILETYPE_B64; - if((data->set.str[STRING_CERT_TYPE]) && - (Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "DER"))) - cert_type = LDAPSSL_CERT_FILETYPE_DER; - if(!ldap_ca) { - failf(data, "LDAP local: ERROR %s CA cert not set!", - (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM")); - status = CURLE_SSL_CERTPROBLEM; - goto quit; - } - infof(data, "LDAP local: using %s CA cert '%s'\n", - (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), - ldap_ca); - rc = ldapssl_add_trusted_cert(ldap_ca, cert_type); - if(rc != LDAP_SUCCESS) { - failf(data, "LDAP local: ERROR setting %s CA cert: %s", - (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), - ldap_err2string(rc)); - status = CURLE_SSL_CERTPROBLEM; - goto quit; - } - ldap_option = LDAPSSL_VERIFY_SERVER; - } else { - ldap_option = LDAPSSL_VERIFY_NONE; - } - rc = ldapssl_set_verify_mode(ldap_option); - if(rc != LDAP_SUCCESS) { - failf(data, "LDAP local: ERROR setting cert verify mode: %s", - ldap_err2string(rc)); - status = CURLE_SSL_CERTPROBLEM; - goto quit; - } - server = ldapssl_init(conn->host.name, (int)conn->port, 1); - if(server == NULL) { - failf(data, "LDAP local: Cannot connect to %s:%hu", - conn->host.name, conn->port); - status = CURLE_COULDNT_CONNECT; - goto quit; - } -#elif defined(LDAP_OPT_X_TLS) - if(data->set.ssl.verifypeer) { - /* OpenLDAP SDK supports BASE64 files. */ - if((data->set.str[STRING_CERT_TYPE]) && - (!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) { - failf(data, "LDAP local: ERROR OpenLDAP does only support PEM cert-type!"); - status = CURLE_SSL_CERTPROBLEM; - goto quit; - } - if(!ldap_ca) { - failf(data, "LDAP local: ERROR PEM CA cert not set!"); - status = CURLE_SSL_CERTPROBLEM; - goto quit; - } - infof(data, "LDAP local: using PEM CA cert: %s\n", ldap_ca); - rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca); - if(rc != LDAP_SUCCESS) { - failf(data, "LDAP local: ERROR setting PEM CA cert: %s", - ldap_err2string(rc)); - status = CURLE_SSL_CERTPROBLEM; - goto quit; - } - ldap_option = LDAP_OPT_X_TLS_DEMAND; - } else { - ldap_option = LDAP_OPT_X_TLS_NEVER; - } - rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option); - if(rc != LDAP_SUCCESS) { - failf(data, "LDAP local: ERROR setting cert verify mode: %s", - ldap_err2string(rc)); - status = CURLE_SSL_CERTPROBLEM; - goto quit; - } - server = ldap_init(conn->host.name, (int)conn->port); - if(server == NULL) { - failf(data, "LDAP local: Cannot connect to %s:%hu", - conn->host.name, conn->port); - status = CURLE_COULDNT_CONNECT; - goto quit; - } - ldap_option = LDAP_OPT_X_TLS_HARD; - rc = ldap_set_option(server, LDAP_OPT_X_TLS, &ldap_option); - if(rc != LDAP_SUCCESS) { - failf(data, "LDAP local: ERROR setting SSL/TLS mode: %s", - ldap_err2string(rc)); - status = CURLE_SSL_CERTPROBLEM; - goto quit; - } -/* - rc = ldap_start_tls_s(server, NULL, NULL); - if(rc != LDAP_SUCCESS) { - failf(data, "LDAP local: ERROR starting SSL/TLS mode: %s", - ldap_err2string(rc)); - status = CURLE_SSL_CERTPROBLEM; - goto quit; - } -*/ -#else - /* we should probably never come up to here since configure - should check in first place if we can support LDAP SSL/TLS */ - failf(data, "LDAP local: SSL/TLS not supported with this version " - "of the OpenLDAP toolkit\n"); - status = CURLE_SSL_CERTPROBLEM; - goto quit; -#endif -#endif -#endif /* CURL_LDAP_USE_SSL */ - } else { - server = ldap_init(conn->host.name, (int)conn->port); - if(server == NULL) { - failf(data, "LDAP local: Cannot connect to %s:%hu", - conn->host.name, conn->port); - status = CURLE_COULDNT_CONNECT; - goto quit; - } - } -#ifdef CURL_LDAP_WIN - ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); -#endif - - rc = ldap_simple_bind_s(server, - conn->bits.user_passwd ? conn->user : NULL, - conn->bits.user_passwd ? conn->passwd : NULL); - if(!ldap_ssl && rc != 0) { - ldap_proto = LDAP_VERSION2; - ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); - rc = ldap_simple_bind_s(server, - conn->bits.user_passwd ? conn->user : NULL, - conn->bits.user_passwd ? conn->passwd : NULL); - } - if(rc != 0) { - failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc)); - status = CURLE_LDAP_CANNOT_BIND; - goto quit; - } - - rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope, - ludp->lud_filter, ludp->lud_attrs, 0, &result); - - if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) { - failf(data, "LDAP remote: %s", ldap_err2string(rc)); - status = CURLE_LDAP_SEARCH_FAILED; - goto quit; - } - - for(num = 0, entryIterator = ldap_first_entry(server, result); - entryIterator; - entryIterator = ldap_next_entry(server, entryIterator), num++) - { - BerElement *ber = NULL; - char *attribute; /*! suspicious that this isn't 'const' */ - char *dn = ldap_get_dn(server, entryIterator); - int i; - - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)dn, 0); - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); - - dlsize += strlen(dn)+5; - - for (attribute = ldap_first_attribute(server, entryIterator, &ber); - attribute; - attribute = ldap_next_attribute(server, entryIterator, ber)) - { - BerValue **vals = ldap_get_values_len(server, entryIterator, attribute); - - if(vals != NULL) - { - for (i = 0; (vals[i] != NULL); i++) - { - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); - Curl_client_write(conn, CLIENTWRITE_BODY, (char *) attribute, 0); - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2); - dlsize += strlen(attribute)+3; - - if((strlen(attribute) > 7) && - (strcmp(";binary", - (char *)attribute + - (strlen((char *)attribute) - 7)) == 0)) { - /* Binary attribute, encode to base64. */ - val_b64_sz = Curl_base64_encode(data, - vals[i]->bv_val, - vals[i]->bv_len, - &val_b64); - if(val_b64_sz > 0) { - Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz); - free(val_b64); - dlsize += val_b64_sz; - } - } - else { - Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val, - vals[i]->bv_len); - dlsize += vals[i]->bv_len; - } - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); - dlsize++; - } - - /* Free memory used to store values */ - ldap_value_free_len(vals); - } - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); - dlsize++; - Curl_pgrsSetDownloadCounter(data, dlsize); - ldap_memfree(attribute); - } - ldap_memfree(dn); - if(ber) - ber_free(ber, 0); - } - -quit: - if(result) { - ldap_msgfree(result); - LDAP_TRACE (("Received %d entries\n", num)); - } - if(rc == LDAP_SIZELIMIT_EXCEEDED) - infof(data, "There are more than %d entries\n", num); - if(ludp) - ldap_free_urldesc(ludp); - if(server) - ldap_unbind_s(server); -#if defined(HAVE_LDAP_SSL) && defined(CURL_HAS_NOVELL_LDAPSDK) - if(ldap_ssl) - ldapssl_client_deinit(); -#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */ - - /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - conn->bits.close = TRUE; - - return status; -} - -#ifdef DEBUG_LDAP -static void _ldap_trace (const char *fmt, ...) -{ - static int do_trace = -1; - va_list args; - - if(do_trace == -1) { - const char *env = getenv("CURL_TRACE"); - do_trace = (env && strtol(env, NULL, 10) > 0); - } - if(!do_trace) - return; - - va_start (args, fmt); - vfprintf (stderr, fmt, args); - va_end (args); -} -#endif - -#ifndef HAVE_LDAP_URL_PARSE - -/* - * Return scope-value for a scope-string. - */ -static int str2scope (const char *p) -{ - if(strequal(p, "one")) - return LDAP_SCOPE_ONELEVEL; - if(strequal(p, "onetree")) - return LDAP_SCOPE_ONELEVEL; - if(strequal(p, "base")) - return LDAP_SCOPE_BASE; - if(strequal(p, "sub")) - return LDAP_SCOPE_SUBTREE; - if(strequal( p, "subtree")) - return LDAP_SCOPE_SUBTREE; - return (-1); -} - -/* - * Split 'str' into strings separated by commas. - * Note: res[] points into 'str'. - */ -static char **split_str (char *str) -{ - char **res, *lasts, *s; - int i; - - for (i = 2, s = strchr(str,','); s; i++) - s = strchr(++s,','); - - res = calloc(i, sizeof(char*)); - if(!res) - return NULL; - - for (i = 0, s = strtok_r(str, ",", &lasts); s; - s = strtok_r(NULL, ",", &lasts), i++) - res[i] = s; - return res; -} - -/* - * Unescape the LDAP-URL components - */ -static bool unescape_elements (void *data, LDAPURLDesc *ludp) -{ - int i; - - if(ludp->lud_filter) { - ludp->lud_filter = curl_easy_unescape(data, ludp->lud_filter, 0, NULL); - if(!ludp->lud_filter) - return (FALSE); - } - - for (i = 0; ludp->lud_attrs && ludp->lud_attrs[i]; i++) { - ludp->lud_attrs[i] = curl_easy_unescape(data, ludp->lud_attrs[i], 0, NULL); - if(!ludp->lud_attrs[i]) - return (FALSE); - } - - for (i = 0; ludp->lud_exts && ludp->lud_exts[i]; i++) { - ludp->lud_exts[i] = curl_easy_unescape(data, ludp->lud_exts[i], 0, NULL); - if(!ludp->lud_exts[i]) - return (FALSE); - } - - if(ludp->lud_dn) { - char *dn = ludp->lud_dn; - char *new_dn = curl_easy_unescape(data, dn, 0, NULL); - - free(dn); - ludp->lud_dn = new_dn; - if(!new_dn) - return (FALSE); - } - return (TRUE); -} - -/* - * Break apart the pieces of an LDAP URL. - * Syntax: - * ldap://:/???? - * - * already known from 'conn->host.name'. - * already known from 'conn->remote_port'. - * extract the rest from 'conn->data->state.path+1'. All fields are optional. - * e.g. - * ldap://:/??? - * yields ludp->lud_dn = "". - * - * Defined in RFC4516 section 2. - */ -static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp) -{ - char *p, *q; - int i; - - if(!conn->data || - !conn->data->state.path || - conn->data->state.path[0] != '/' || - !checkprefix("LDAP", conn->data->change.url)) - return LDAP_INVALID_SYNTAX; - - ludp->lud_scope = LDAP_SCOPE_BASE; - ludp->lud_port = conn->remote_port; - ludp->lud_host = conn->host.name; - - /* parse DN (Distinguished Name). - */ - ludp->lud_dn = strdup(conn->data->state.path+1); - if(!ludp->lud_dn) - return LDAP_NO_MEMORY; - - p = strchr(ludp->lud_dn, '?'); - LDAP_TRACE (("DN '%.*s'\n", p ? (size_t)(p-ludp->lud_dn) : - strlen(ludp->lud_dn), ludp->lud_dn)); - - if(!p) - goto success; - - *p++ = '\0'; - - /* parse attributes. skip "??". - */ - q = strchr(p, '?'); - if(q) - *q++ = '\0'; - - if(*p && *p != '?') { - ludp->lud_attrs = split_str(p); - if(!ludp->lud_attrs) - return LDAP_NO_MEMORY; - - for (i = 0; ludp->lud_attrs[i]; i++) - LDAP_TRACE (("attr[%d] '%s'\n", i, ludp->lud_attrs[i])); - } - - p = q; - if(!p) - goto success; - - /* parse scope. skip "??" - */ - q = strchr(p, '?'); - if(q) - *q++ = '\0'; - - if(*p && *p != '?') { - ludp->lud_scope = str2scope(p); - if(ludp->lud_scope == -1) - return LDAP_INVALID_SYNTAX; - LDAP_TRACE (("scope %d\n", ludp->lud_scope)); - } - - p = q; - if(!p) - goto success; - - /* parse filter - */ - q = strchr(p, '?'); - if(q) - *q++ = '\0'; - if(!*p) - return LDAP_INVALID_SYNTAX; - - ludp->lud_filter = p; - LDAP_TRACE (("filter '%s'\n", ludp->lud_filter)); - - p = q; - if(!p) - goto success; - - /* parse extensions - */ - ludp->lud_exts = split_str(p); - if(!ludp->lud_exts) - return LDAP_NO_MEMORY; - - for (i = 0; ludp->lud_exts[i]; i++) - LDAP_TRACE (("exts[%d] '%s'\n", i, ludp->lud_exts[i])); - - success: - if(!unescape_elements(conn->data, ludp)) - return LDAP_NO_MEMORY; - return LDAP_SUCCESS; -} - -static int _ldap_url_parse (const struct connectdata *conn, - LDAPURLDesc **ludpp) -{ - LDAPURLDesc *ludp = calloc(1, sizeof(*ludp)); - int rc; - - *ludpp = NULL; - if(!ludp) - return LDAP_NO_MEMORY; - - rc = _ldap_url_parse2 (conn, ludp); - if(rc != LDAP_SUCCESS) { - _ldap_free_urldesc(ludp); - ludp = NULL; - } - *ludpp = ludp; - return (rc); -} - -static void _ldap_free_urldesc (LDAPURLDesc *ludp) -{ - int i; - - if(!ludp) - return; - - if(ludp->lud_dn) - free(ludp->lud_dn); - - if(ludp->lud_filter) - free(ludp->lud_filter); - - if(ludp->lud_attrs) { - for (i = 0; ludp->lud_attrs[i]; i++) - free(ludp->lud_attrs[i]); - free(ludp->lud_attrs); - } - - if(ludp->lud_exts) { - for (i = 0; ludp->lud_exts[i]; i++) - free(ludp->lud_exts[i]); - free(ludp->lud_exts); - } - free (ludp); -} -#endif /* !HAVE_LDAP_URL_PARSE */ -#endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */ diff --git a/third_party/curl/lib/libcurl.rc b/third_party/curl/lib/libcurl.rc deleted file mode 100644 index 47b944ac8..000000000 --- a/third_party/curl/lib/libcurl.rc +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 -#include "../include/curl/curlver.h" - -LANGUAGE 0x09,0x01 - -#define RC_VERSION LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0 - -VS_VERSION_INFO VERSIONINFO - FILEVERSION RC_VERSION - PRODUCTVERSION RC_VERSION - FILEFLAGSMASK 0x3fL -#if defined(DEBUGBUILD) || defined(_DEBUG) - FILEFLAGS 1 -#else - FILEFLAGS 0 -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0x0L - -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", "The cURL library, http://curl.haxx.se/\0" - VALUE "FileDescription", "libcurl Shared Library\0" - VALUE "FileVersion", LIBCURL_VERSION "\0" - VALUE "InternalName", "libcurl\0" - VALUE "OriginalFilename", "libcurl.dll\0" - VALUE "ProductName", "The cURL library\0" - VALUE "ProductVersion", LIBCURL_VERSION "\0" - VALUE "LegalCopyright", "© " LIBCURL_COPYRIGHT "\0" - VALUE "License", "http://curl.haxx.se/docs/copyright.html\0" - END - END - - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END diff --git a/third_party/curl/lib/llist.c b/third_party/curl/lib/llist.c deleted file mode 100644 index 71238fa73..000000000 --- a/third_party/curl/lib/llist.c +++ /dev/null @@ -1,198 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include - -#include "llist.h" -#include "curl_memory.h" - -/* this must be the last include file */ -#include "memdebug.h" - -static void -llist_init(struct curl_llist *l, curl_llist_dtor dtor) -{ - l->size = 0; - l->dtor = dtor; - l->head = NULL; - l->tail = NULL; -} - -struct curl_llist * -Curl_llist_alloc(curl_llist_dtor dtor) -{ - struct curl_llist *list; - - list = malloc(sizeof(struct curl_llist)); - if(NULL == list) - return NULL; - - llist_init(list, dtor); - - return list; -} - -/* - * Curl_llist_insert_next() - * - * Inserts a new list element after the given one 'e'. If the given existing - * entry is NULL and the list already has elements, the new one will be - * inserted first in the list. - * - * Returns: 1 on success and 0 on failure. - */ -int -Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e, - const void *p) -{ - struct curl_llist_element *ne = malloc(sizeof(struct curl_llist_element)); - if(!ne) - return 0; - - ne->ptr = (void *) p; - if(list->size == 0) { - list->head = ne; - list->head->prev = NULL; - list->head->next = NULL; - list->tail = ne; - } - else { - /* if 'e' is NULL here, we insert the new element first in the list */ - ne->next = e?e->next:list->head; - ne->prev = e; - if(!e) { - list->head->prev = ne; - list->head = ne; - } - else if(e->next) { - e->next->prev = ne; - } - else { - list->tail = ne; - } - if(e) - e->next = ne; - } - - ++list->size; - - return 1; -} - -int -Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e, - void *user) -{ - if(e == NULL || list->size == 0) - return 1; - - if(e == list->head) { - list->head = e->next; - - if(list->head == NULL) - list->tail = NULL; - else - e->next->prev = NULL; - } else { - e->prev->next = e->next; - if(!e->next) - list->tail = e->prev; - else - e->next->prev = e->prev; - } - - list->dtor(user, e->ptr); - - free(e); - --list->size; - - return 1; -} - -void -Curl_llist_destroy(struct curl_llist *list, void *user) -{ - if(list) { - while(list->size > 0) - Curl_llist_remove(list, list->tail, user); - - free(list); - } -} - -size_t -Curl_llist_count(struct curl_llist *list) -{ - return list->size; -} - -int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, - struct curl_llist *to_list, struct curl_llist_element *to_e) -{ - /* Remove element from list */ - if(e == NULL || list->size == 0) - return 0; - - if(e == list->head) { - list->head = e->next; - - if(list->head == NULL) - list->tail = NULL; - else - e->next->prev = NULL; - } - else { - e->prev->next = e->next; - if(!e->next) - list->tail = e->prev; - else - e->next->prev = e->prev; - } - - --list->size; - - /* Add element to to_list after to_e */ - if(to_list->size == 0) { - to_list->head = e; - to_list->head->prev = NULL; - to_list->head->next = NULL; - to_list->tail = e; - } - else { - e->next = to_e->next; - e->prev = to_e; - if(to_e->next) { - to_e->next->prev = e; - } - else { - to_list->tail = e; - } - to_e->next = e; - } - - ++to_list->size; - - return 1; -} diff --git a/third_party/curl/lib/llist.h b/third_party/curl/lib/llist.h deleted file mode 100644 index c33912a4b..000000000 --- a/third_party/curl/lib/llist.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __LLIST_H -#define __LLIST_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" -#include - -typedef void (*curl_llist_dtor)(void *, void *); - -struct curl_llist_element { - void *ptr; - - struct curl_llist_element *prev; - struct curl_llist_element *next; -}; - -struct curl_llist { - struct curl_llist_element *head; - struct curl_llist_element *tail; - - curl_llist_dtor dtor; - - size_t size; -}; - -struct curl_llist *Curl_llist_alloc(curl_llist_dtor); -int Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *, - const void *); -int Curl_llist_remove(struct curl_llist *, struct curl_llist_element *, - void *); -size_t Curl_llist_count(struct curl_llist *); -void Curl_llist_destroy(struct curl_llist *, void *); -int Curl_llist_move(struct curl_llist *, struct curl_llist_element *, - struct curl_llist *, struct curl_llist_element *); - -#endif diff --git a/third_party/curl/lib/md4.c b/third_party/curl/lib/md4.c deleted file mode 100644 index ecf3bfcd8..000000000 --- a/third_party/curl/lib/md4.c +++ /dev/null @@ -1,281 +0,0 @@ -/*- - Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. - - License to copy and use this software is granted provided that it - is identified as the "RSA Data Security, Inc. MD4 Message-Digest - Algorithm" in all material mentioning or referencing this software - or this function. - - License is also granted to make and use derivative works provided - that such works are identified as "derived from the RSA Data - Security, Inc. MD4 Message-Digest Algorithm" in all material - mentioning or referencing the derived work. - - RSA Data Security, Inc. makes no representations concerning either - the merchantability of this software or the suitability of this - software for any particular purpose. It is provided "as is" - without express or implied warranty of any kind. - - These notices must be retained in any copies of any part of this - documentation and/or software. - */ - -#include "setup.h" - -/* NSS crypto library does not provide the MD4 hash algorithm, so that we have - * a local implementation of it */ -#ifdef USE_NSS - -#include "curl_md4.h" -#include - -typedef unsigned int UINT4; - -typedef struct MD4Context { - UINT4 state[4]; /* state (ABCD) */ - UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ - unsigned char buffer[64]; /* input buffer */ -} MD4_CTX; - -/* Constants for MD4Transform routine. - */ -#define S11 3 -#define S12 7 -#define S13 11 -#define S14 19 -#define S21 3 -#define S22 5 -#define S23 9 -#define S24 13 -#define S31 3 -#define S32 9 -#define S33 11 -#define S34 15 - -static void MD4Transform(UINT4 [4], const unsigned char [64]); -static void Encode(unsigned char *, UINT4 *, unsigned int); -static void Decode(UINT4 *, const unsigned char *, unsigned int); - -static unsigned char PADDING[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* F, G and H are basic MD4 functions. - */ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) - -/* ROTATE_LEFT rotates x left n bits. - */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - -/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ -/* Rotation is separate from addition to prevent recomputation */ -#define FF(a, b, c, d, x, s) { \ - (a) += F ((b), (c), (d)) + (x); \ - (a) = ROTATE_LEFT ((a), (s)); \ - } -#define GG(a, b, c, d, x, s) { \ - (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \ - (a) = ROTATE_LEFT ((a), (s)); \ - } -#define HH(a, b, c, d, x, s) { \ - (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \ - (a) = ROTATE_LEFT ((a), (s)); \ - } - -/* MD4 initialization. Begins an MD4 operation, writing a new context. - */ -static void MD4Init(MD4_CTX *context) -{ - context->count[0] = context->count[1] = 0; - - /* Load magic initialization constants. - */ - context->state[0] = 0x67452301; - context->state[1] = 0xefcdab89; - context->state[2] = 0x98badcfe; - context->state[3] = 0x10325476; -} - -/* MD4 block update operation. Continues an MD4 message-digest - operation, processing another message block, and updating the - context. - */ -static void MD4Update(MD4_CTX *context, const unsigned char *input, - unsigned int inputLen) -{ - unsigned int i, bufindex, partLen; - - /* Compute number of bytes mod 64 */ - bufindex = (unsigned int)((context->count[0] >> 3) & 0x3F); - /* Update number of bits */ - if ((context->count[0] += ((UINT4)inputLen << 3)) - < ((UINT4)inputLen << 3)) - context->count[1]++; - context->count[1] += ((UINT4)inputLen >> 29); - - partLen = 64 - bufindex; - /* Transform as many times as possible. - */ - if (inputLen >= partLen) { - memcpy(&context->buffer[bufindex], input, partLen); - MD4Transform (context->state, context->buffer); - - for (i = partLen; i + 63 < inputLen; i += 64) - MD4Transform (context->state, &input[i]); - - bufindex = 0; - } - else - i = 0; - - /* Buffer remaining input */ - memcpy(&context->buffer[bufindex], &input[i], inputLen-i); -} - -/* MD4 padding. */ -static void MD4Pad(MD4_CTX *context) -{ - unsigned char bits[8]; - unsigned int bufindex, padLen; - - /* Save number of bits */ - Encode (bits, context->count, 8); - - /* Pad out to 56 mod 64. - */ - bufindex = (unsigned int)((context->count[0] >> 3) & 0x3f); - padLen = (bufindex < 56) ? (56 - bufindex) : (120 - bufindex); - MD4Update (context, PADDING, padLen); - - /* Append length (before padding) */ - MD4Update (context, bits, 8); -} - -/* MD4 finalization. Ends an MD4 message-digest operation, writing the - the message digest and zeroizing the context. - */ -static void MD4Final (unsigned char digest[16], MD4_CTX *context) -{ - /* Do padding */ - MD4Pad (context); - - /* Store state in digest */ - Encode (digest, context->state, 16); - - /* Zeroize sensitive information. - */ - memset(context, 0, sizeof(*context)); -} - -/* MD4 basic transformation. Transforms state based on block. - */ -static void MD4Transform (UINT4 state[4], const unsigned char block[64]) -{ - UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - - Decode (x, block, 64); - - /* Round 1 */ - FF (a, b, c, d, x[ 0], S11); /* 1 */ - FF (d, a, b, c, x[ 1], S12); /* 2 */ - FF (c, d, a, b, x[ 2], S13); /* 3 */ - FF (b, c, d, a, x[ 3], S14); /* 4 */ - FF (a, b, c, d, x[ 4], S11); /* 5 */ - FF (d, a, b, c, x[ 5], S12); /* 6 */ - FF (c, d, a, b, x[ 6], S13); /* 7 */ - FF (b, c, d, a, x[ 7], S14); /* 8 */ - FF (a, b, c, d, x[ 8], S11); /* 9 */ - FF (d, a, b, c, x[ 9], S12); /* 10 */ - FF (c, d, a, b, x[10], S13); /* 11 */ - FF (b, c, d, a, x[11], S14); /* 12 */ - FF (a, b, c, d, x[12], S11); /* 13 */ - FF (d, a, b, c, x[13], S12); /* 14 */ - FF (c, d, a, b, x[14], S13); /* 15 */ - FF (b, c, d, a, x[15], S14); /* 16 */ - - /* Round 2 */ - GG (a, b, c, d, x[ 0], S21); /* 17 */ - GG (d, a, b, c, x[ 4], S22); /* 18 */ - GG (c, d, a, b, x[ 8], S23); /* 19 */ - GG (b, c, d, a, x[12], S24); /* 20 */ - GG (a, b, c, d, x[ 1], S21); /* 21 */ - GG (d, a, b, c, x[ 5], S22); /* 22 */ - GG (c, d, a, b, x[ 9], S23); /* 23 */ - GG (b, c, d, a, x[13], S24); /* 24 */ - GG (a, b, c, d, x[ 2], S21); /* 25 */ - GG (d, a, b, c, x[ 6], S22); /* 26 */ - GG (c, d, a, b, x[10], S23); /* 27 */ - GG (b, c, d, a, x[14], S24); /* 28 */ - GG (a, b, c, d, x[ 3], S21); /* 29 */ - GG (d, a, b, c, x[ 7], S22); /* 30 */ - GG (c, d, a, b, x[11], S23); /* 31 */ - GG (b, c, d, a, x[15], S24); /* 32 */ - - /* Round 3 */ - HH (a, b, c, d, x[ 0], S31); /* 33 */ - HH (d, a, b, c, x[ 8], S32); /* 34 */ - HH (c, d, a, b, x[ 4], S33); /* 35 */ - HH (b, c, d, a, x[12], S34); /* 36 */ - HH (a, b, c, d, x[ 2], S31); /* 37 */ - HH (d, a, b, c, x[10], S32); /* 38 */ - HH (c, d, a, b, x[ 6], S33); /* 39 */ - HH (b, c, d, a, x[14], S34); /* 40 */ - HH (a, b, c, d, x[ 1], S31); /* 41 */ - HH (d, a, b, c, x[ 9], S32); /* 42 */ - HH (c, d, a, b, x[ 5], S33); /* 43 */ - HH (b, c, d, a, x[13], S34); /* 44 */ - HH (a, b, c, d, x[ 3], S31); /* 45 */ - HH (d, a, b, c, x[11], S32); /* 46 */ - HH (c, d, a, b, x[ 7], S33); /* 47 */ - HH (b, c, d, a, x[15], S34); /* 48 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - - /* Zeroize sensitive information. - */ - memset(x, 0, sizeof(x)); -} - -/* Encodes input (UINT4) into output (unsigned char). Assumes len is - a multiple of 4. - */ -static void Encode(unsigned char *output, UINT4 *input, unsigned int len) -{ - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char)(input[i] & 0xff); - output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); - output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); - output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); - } -} - -/* Decodes input (unsigned char) into output (UINT4). Assumes len is - a multiple of 4. - */ -static void Decode (UINT4 *output, const unsigned char *input, unsigned int len) -{ - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | - (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); -} - -void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len) -{ - MD4_CTX ctx; - MD4Init(&ctx); - MD4Update(&ctx, input, (unsigned int)len); - MD4Final(output, &ctx); -} -#endif /* USE_NSS */ diff --git a/third_party/curl/lib/md5.c b/third_party/curl/lib/md5.c deleted file mode 100644 index b3912c583..000000000 --- a/third_party/curl/lib/md5.c +++ /dev/null @@ -1,395 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef CURL_DISABLE_CRYPTO_AUTH - -#include - -#include "curl_md5.h" -#include "curl_hmac.h" - -#ifdef USE_GNUTLS - -#include - -typedef gcry_md_hd_t MD5_CTX; - -static void MD5_Init(MD5_CTX * ctx) -{ - gcry_md_open(ctx, GCRY_MD_MD5, 0); -} - -static void MD5_Update(MD5_CTX * ctx, - const unsigned char * input, - unsigned int inputLen) -{ - gcry_md_write(*ctx, input, inputLen); -} - -static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx) -{ - memcpy(digest, gcry_md_read(*ctx, 0), 16); - gcry_md_close(*ctx); -} - -#else - -#ifdef USE_SSLEAY -/* When OpenSSL is available we use the MD5-function from OpenSSL */ - -# ifdef USE_OPENSSL -# include -# else -# include -# endif - -#else /* USE_SSLEAY */ -/* When OpenSSL is not available we use this code segment */ - -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. - -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. - -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. - */ - -/* UINT4 defines a four byte word */ -typedef unsigned int UINT4; - -/* MD5 context. */ -struct md5_ctx { - UINT4 state[4]; /* state (ABCD) */ - UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ - unsigned char buffer[64]; /* input buffer */ -}; - -typedef struct md5_ctx MD5_CTX; - -static void MD5_Init(struct md5_ctx *); -static void MD5_Update(struct md5_ctx *, const unsigned char *, unsigned int); -static void MD5_Final(unsigned char [16], struct md5_ctx *); - -/* Constants for MD5Transform routine. - */ - -#define S11 7 -#define S12 12 -#define S13 17 -#define S14 22 -#define S21 5 -#define S22 9 -#define S23 14 -#define S24 20 -#define S31 4 -#define S32 11 -#define S33 16 -#define S34 23 -#define S41 6 -#define S42 10 -#define S43 15 -#define S44 21 - -static void MD5Transform(UINT4 [4], const unsigned char [64]); -static void Encode(unsigned char *, UINT4 *, unsigned int); -static void Decode(UINT4 *, const unsigned char *, unsigned int); - -static const unsigned char PADDING[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* F, G, H and I are basic MD5 functions. - */ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | (~z))) - -/* ROTATE_LEFT rotates x left n bits. - */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - -/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. -Rotation is separate from addition to prevent recomputation. - */ -#define FF(a, b, c, d, x, s, ac) { \ - (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define GG(a, b, c, d, x, s, ac) { \ - (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define HH(a, b, c, d, x, s, ac) { \ - (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define II(a, b, c, d, x, s, ac) { \ - (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } - -/* MD5 initialization. Begins an MD5 operation, writing a new context. - */ -static void MD5_Init(struct md5_ctx *context) -{ - context->count[0] = context->count[1] = 0; - /* Load magic initialization constants. */ - context->state[0] = 0x67452301; - context->state[1] = 0xefcdab89; - context->state[2] = 0x98badcfe; - context->state[3] = 0x10325476; -} - -/* MD5 block update operation. Continues an MD5 message-digest - operation, processing another message block, and updating the - context. - */ -static void MD5_Update (struct md5_ctx *context, /* context */ - const unsigned char *input, /* input block */ - unsigned int inputLen) /* length of input block */ -{ - unsigned int i, bufindex, partLen; - - /* Compute number of bytes mod 64 */ - bufindex = (unsigned int)((context->count[0] >> 3) & 0x3F); - - /* Update number of bits */ - if((context->count[0] += ((UINT4)inputLen << 3)) - < ((UINT4)inputLen << 3)) - context->count[1]++; - context->count[1] += ((UINT4)inputLen >> 29); - - partLen = 64 - bufindex; - - /* Transform as many times as possible. */ - if(inputLen >= partLen) { - memcpy(&context->buffer[bufindex], input, partLen); - MD5Transform(context->state, context->buffer); - - for (i = partLen; i + 63 < inputLen; i += 64) - MD5Transform(context->state, &input[i]); - - bufindex = 0; - } - else - i = 0; - - /* Buffer remaining input */ - memcpy(&context->buffer[bufindex], &input[i], inputLen-i); -} - -/* MD5 finalization. Ends an MD5 message-digest operation, writing the - the message digest and zeroizing the context. -*/ -static void MD5_Final(unsigned char digest[16], /* message digest */ - struct md5_ctx *context) /* context */ -{ - unsigned char bits[8]; - unsigned int count, padLen; - - /* Save number of bits */ - Encode (bits, context->count, 8); - - /* Pad out to 56 mod 64. */ - count = (unsigned int)((context->count[0] >> 3) & 0x3f); - padLen = (count < 56) ? (56 - count) : (120 - count); - MD5_Update (context, PADDING, padLen); - - /* Append length (before padding) */ - MD5_Update (context, bits, 8); - - /* Store state in digest */ - Encode (digest, context->state, 16); - - /* Zeroize sensitive information. */ - memset ((void *)context, 0, sizeof (*context)); -} - -/* MD5 basic transformation. Transforms state based on block. */ -static void MD5Transform(UINT4 state[4], - const unsigned char block[64]) -{ - UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - - Decode (x, block, 64); - - /* Round 1 */ - FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ - FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ - FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ - FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ - FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ - FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ - FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ - FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ - FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ - FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ - FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ - FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ - FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ - FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ - FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ - FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - - /* Round 2 */ - GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ - GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ - GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ - GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ - GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ - GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ - GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - - /* Round 3 */ - HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ - HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ - HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ - HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ - HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ - HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ - HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ - II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ - II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ - II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - - /* Zeroize sensitive information. */ - memset((void *)x, 0, sizeof (x)); -} - -/* Encodes input (UINT4) into output (unsigned char). Assumes len is - a multiple of 4. - */ -static void Encode (unsigned char *output, - UINT4 *input, - unsigned int len) -{ - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char)(input[i] & 0xff); - output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); - output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); - output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); - } -} - -/* Decodes input (unsigned char) into output (UINT4). Assumes len is - a multiple of 4. -*/ -static void Decode (UINT4 *output, - const unsigned char *input, - unsigned int len) -{ - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | - (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); -} - -#endif /* USE_SSLEAY */ - -#endif /* USE_GNUTLS */ - -const HMAC_params Curl_HMAC_MD5[] = { - { - (HMAC_hinit_func) MD5_Init, /* Hash initialization function. */ - (HMAC_hupdate_func) MD5_Update, /* Hash update function. */ - (HMAC_hfinal_func) MD5_Final, /* Hash computation end function. */ - sizeof(MD5_CTX), /* Size of hash context structure. */ - 64, /* Maximum key length. */ - 16 /* Result size. */ - } -}; - - -void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */ - const unsigned char *input) -{ - MD5_CTX ctx; - MD5_Init(&ctx); - MD5_Update(&ctx, input, (unsigned int)strlen((char *)input)); - MD5_Final(outbuffer, &ctx); -} - -#endif /* CURL_DISABLE_CRYPTO_AUTH */ diff --git a/third_party/curl/lib/memdebug.c b/third_party/curl/lib/memdebug.c deleted file mode 100644 index 69e204b6a..000000000 --- a/third_party/curl/lib/memdebug.c +++ /dev/null @@ -1,394 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef CURLDEBUG -#include - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#define _MPRINTF_REPLACE -#include -#include "urldata.h" -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */ -#include "curl_memory.h" -#include "memdebug.h" - -#ifndef HAVE_ASSERT_H -# define assert(x) do { } while (0) -#endif - -struct memdebug { - size_t size; - union { - double d; - void * p; - } mem[1]; - /* I'm hoping this is the thing with the strictest alignment - * requirements. That also means we waste some space :-( */ -}; - -/* - * Note that these debug functions are very simple and they are meant to - * remain so. For advanced analysis, record a log file and write perl scripts - * to analyze them! - * - * Don't use these with multithreaded test programs! - */ - -#define logfile curl_debuglogfile -FILE *curl_debuglogfile = NULL; -static bool memlimit = FALSE; /* enable memory limit */ -static long memsize = 0; /* set number of mallocs allowed */ - -/* this sets the log file name */ -void curl_memdebug(const char *logname) -{ - if(!logfile) { - if(logname) - logfile = fopen(logname, "w"); - else - logfile = stderr; -#ifdef MEMDEBUG_LOG_SYNC - /* Flush the log file after every line so the log isn't lost in a crash */ - setvbuf(logfile, (char *)NULL, _IOLBF, 0); -#endif - } -} - -/* This function sets the number of malloc() calls that should return - successfully! */ -void curl_memlimit(long limit) -{ - if(!memlimit) { - memlimit = TRUE; - memsize = limit; - } -} - -/* returns TRUE if this isn't allowed! */ -static bool countcheck(const char *func, int line, const char *source) -{ - /* if source is NULL, then the call is made internally and this check - should not be made */ - if(memlimit && source) { - if(!memsize) { - if(source) { - /* log to file */ - curl_memlog("LIMIT %s:%d %s reached memlimit\n", - source, line, func); - /* log to stderr also */ - fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n", - source, line, func); - } - SET_ERRNO(ENOMEM); - return TRUE; /* RETURN ERROR! */ - } - else - memsize--; /* countdown */ - - /* log the countdown */ - if(source) - curl_memlog("LIMIT %s:%d %ld ALLOCS left\n", - source, line, memsize); - - } - - return FALSE; /* allow this */ -} - -void *curl_domalloc(size_t wantedsize, int line, const char *source) -{ - struct memdebug *mem; - size_t size; - - assert(wantedsize != 0); - - if(countcheck("malloc", line, source)) - return NULL; - - /* alloc at least 64 bytes */ - size = sizeof(struct memdebug)+wantedsize; - - mem = (Curl_cmalloc)(size); - if(mem) { - /* fill memory with junk */ - memset(mem->mem, 0xA5, wantedsize); - mem->size = wantedsize; - } - - if(source) - curl_memlog("MEM %s:%d malloc(%zd) = %p\n", - source, line, wantedsize, mem ? mem->mem : 0); - return (mem ? mem->mem : NULL); -} - -void *curl_docalloc(size_t wanted_elements, size_t wanted_size, - int line, const char *source) -{ - struct memdebug *mem; - size_t size, user_size; - - assert(wanted_elements != 0); - assert(wanted_size != 0); - - if(countcheck("calloc", line, source)) - return NULL; - - /* alloc at least 64 bytes */ - user_size = wanted_size * wanted_elements; - size = sizeof(struct memdebug) + user_size; - - mem = (Curl_cmalloc)(size); - if(mem) { - /* fill memory with zeroes */ - memset(mem->mem, 0, user_size); - mem->size = user_size; - } - - if(source) - curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n", - source, line, wanted_elements, wanted_size, mem?mem->mem:0); - return (mem ? mem->mem : NULL); -} - -char *curl_dostrdup(const char *str, int line, const char *source) -{ - char *mem; - size_t len; - - assert(str != NULL); - - if(countcheck("strdup", line, source)) - return NULL; - - len=strlen(str)+1; - - mem=curl_domalloc(len, 0, NULL); /* NULL prevents logging */ - if(mem) - memcpy(mem, str, len); - - if(source) - curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n", - source, line, str, len, mem); - - return mem; -} - -/* We provide a realloc() that accepts a NULL as pointer, which then - performs a malloc(). In order to work with ares. */ -void *curl_dorealloc(void *ptr, size_t wantedsize, - int line, const char *source) -{ - struct memdebug *mem=NULL; - - size_t size = sizeof(struct memdebug)+wantedsize; - - assert(wantedsize != 0); - - if(countcheck("realloc", line, source)) - return NULL; - -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:1684) - /* 1684: conversion from pointer to same-sized integral type */ -#endif - - if(ptr) - mem = (void *)((char *)ptr - offsetof(struct memdebug, mem)); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif - - mem = (Curl_crealloc)(mem, size); - if(source) - curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n", - source, line, ptr, wantedsize, mem?mem->mem:NULL); - - if(mem) { - mem->size = wantedsize; - return mem->mem; - } - - return NULL; -} - -void curl_dofree(void *ptr, int line, const char *source) -{ - struct memdebug *mem; - - assert(ptr != NULL); - -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:1684) - /* 1684: conversion from pointer to same-sized integral type */ -#endif - - mem = (void *)((char *)ptr - offsetof(struct memdebug, mem)); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif - - /* destroy */ - memset(mem->mem, 0x13, mem->size); - - /* free for real */ - (Curl_cfree)(mem); - - if(source) - curl_memlog("MEM %s:%d free(%p)\n", source, line, ptr); -} - -curl_socket_t curl_socket(int domain, int type, int protocol, - int line, const char *source) -{ - const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? - "FD %s:%d socket() = %d\n" : - (sizeof(curl_socket_t) == sizeof(long)) ? - "FD %s:%d socket() = %ld\n" : - "FD %s:%d socket() = %zd\n" ; - - curl_socket_t sockfd = socket(domain, type, protocol); - if(source && (sockfd != CURL_SOCKET_BAD)) - curl_memlog(fmt, source, line, sockfd); - return sockfd; -} - -curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen, - int line, const char *source) -{ - const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? - "FD %s:%d accept() = %d\n" : - (sizeof(curl_socket_t) == sizeof(long)) ? - "FD %s:%d accept() = %ld\n" : - "FD %s:%d accept() = %zd\n" ; - - struct sockaddr *addr = (struct sockaddr *)saddr; - curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen; - curl_socket_t sockfd = accept(s, addr, addrlen); - if(source && (sockfd != CURL_SOCKET_BAD)) - curl_memlog(fmt, source, line, sockfd); - return sockfd; -} - -/* separate function to allow libcurl to mark a "faked" close */ -void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source) -{ - const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? - "FD %s:%d sclose(%d)\n" : - (sizeof(curl_socket_t) == sizeof(long)) ? - "FD %s:%d sclose(%ld)\n" : - "FD %s:%d sclose(%zd)\n" ; - - if(source) - curl_memlog(fmt, source, line, sockfd); -} - -/* this is our own defined way to close sockets on *ALL* platforms */ -int curl_sclose(curl_socket_t sockfd, int line, const char *source) -{ - int res=sclose(sockfd); - curl_mark_sclose(sockfd, line, source); - return res; -} - -FILE *curl_fopen(const char *file, const char *mode, - int line, const char *source) -{ - FILE *res=fopen(file, mode); - if(source) - curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n", - source, line, file, mode, res); - return res; -} - -#ifdef HAVE_FDOPEN -FILE *curl_fdopen(int filedes, const char *mode, - int line, const char *source) -{ - FILE *res=fdopen(filedes, mode); - if(source) - curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n", - source, line, filedes, mode, res); - return res; -} -#endif - -int curl_fclose(FILE *file, int line, const char *source) -{ - int res; - - assert(file != NULL); - - res=fclose(file); - if(source) - curl_memlog("FILE %s:%d fclose(%p)\n", - source, line, file); - return res; -} - -#define LOGLINE_BUFSIZE 1024 - -/* this does the writting to the memory tracking log file */ -void curl_memlog(const char *format, ...) -{ - char *buf; - int nchars; - va_list ap; - - if(!logfile) - return; - - buf = (Curl_cmalloc)(LOGLINE_BUFSIZE); - if(!buf) - return; - - va_start(ap, format); - nchars = vsnprintf(buf, LOGLINE_BUFSIZE, format, ap); - va_end(ap); - - if(nchars > LOGLINE_BUFSIZE - 1) - nchars = LOGLINE_BUFSIZE - 1; - - if(nchars > 0) - fwrite(buf, 1, nchars, logfile); - - (Curl_cfree)(buf); -} - -#endif /* CURLDEBUG */ diff --git a/third_party/curl/lib/memdebug.h b/third_party/curl/lib/memdebug.h deleted file mode 100644 index 56b9f12b2..000000000 --- a/third_party/curl/lib/memdebug.h +++ /dev/null @@ -1,139 +0,0 @@ -#ifdef CURLDEBUG -#ifndef _CURL_MEMDEBUG_H -#define _CURL_MEMDEBUG_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * CAUTION: this header is designed to work when included by the app-side - * as well as the library. Do not mix with library internals! - */ - -#include "setup.h" - -#include - -#ifdef HAVE_SYS_TYPES_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#include - -#define logfile curl_debuglogfile - -extern FILE *logfile; - -/* memory functions */ -CURL_EXTERN void *curl_domalloc(size_t size, int line, const char *source); -CURL_EXTERN void *curl_docalloc(size_t elements, size_t size, int line, const char *source); -CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line, const char *source); -CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source); -CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source); -CURL_EXTERN void curl_memdebug(const char *logname); -CURL_EXTERN void curl_memlimit(long limit); -CURL_EXTERN void curl_memlog(const char *format, ...); - -/* file descriptor manipulators */ -CURL_EXTERN curl_socket_t curl_socket(int domain, int type, int protocol, - int line , const char *source); -CURL_EXTERN void curl_mark_sclose(curl_socket_t sockfd, - int line , const char *source); -CURL_EXTERN int curl_sclose(curl_socket_t sockfd, - int line , const char *source); -CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen, - int line, const char *source); - -/* FILE functions */ -CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line, - const char *source); -#ifdef HAVE_FDOPEN -CURL_EXTERN FILE *curl_fdopen(int filedes, const char *mode, int line, - const char *source); -#endif -CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source); - -#ifndef MEMDEBUG_NODEFINES - -/* Set this symbol on the command-line, recompile all lib-sources */ -#undef strdup -#define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__) -#define malloc(size) curl_domalloc(size, __LINE__, __FILE__) -#define calloc(nbelem,size) curl_docalloc(nbelem, size, __LINE__, __FILE__) -#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__) -#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__) - -#define socket(domain,type,protocol)\ - curl_socket(domain,type,protocol,__LINE__,__FILE__) -#undef accept /* for those with accept as a macro */ -#define accept(sock,addr,len)\ - curl_accept(sock,addr,len,__LINE__,__FILE__) - -#ifdef HAVE_GETADDRINFO -#if defined(getaddrinfo) && defined(__osf__) -/* OSF/1 and Tru64 have getaddrinfo as a define already, so we cannot define - our macro as for other platforms. Instead, we redefine the new name they - define getaddrinfo to become! */ -#define ogetaddrinfo(host,serv,hint,res) \ - curl_dogetaddrinfo(host,serv,hint,res,__LINE__,__FILE__) -#else -#undef getaddrinfo -#define getaddrinfo(host,serv,hint,res) \ - curl_dogetaddrinfo(host,serv,hint,res,__LINE__,__FILE__) -#endif -#endif /* HAVE_GETADDRINFO */ - -#ifdef HAVE_GETNAMEINFO -#undef getnameinfo -#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \ - curl_dogetnameinfo(sa,salen,host,hostlen,serv,servlen,flags, __LINE__, \ - __FILE__) -#endif /* HAVE_GETNAMEINFO */ - -#ifdef HAVE_FREEADDRINFO -#undef freeaddrinfo -#define freeaddrinfo(data) \ - curl_dofreeaddrinfo(data,__LINE__,__FILE__) -#endif /* HAVE_FREEADDRINFO */ - -/* sclose is probably already defined, redefine it! */ -#undef sclose -#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__) - -#define fake_sclose(sockfd) curl_mark_sclose(sockfd,__LINE__,__FILE__) - -#undef fopen -#define fopen(file,mode) curl_fopen(file,mode,__LINE__,__FILE__) -#undef fdopen -#define fdopen(file,mode) curl_fdopen(file,mode,__LINE__,__FILE__) -#define fclose(file) curl_fclose(file,__LINE__,__FILE__) - -#endif /* MEMDEBUG_NODEFINES */ - -#endif /* _CURL_MEMDEBUG_H */ -#endif /* CURLDEBUG */ - -#ifndef fake_sclose -#define fake_sclose(x) -#endif diff --git a/third_party/curl/lib/mprintf.c b/third_party/curl/lib/mprintf.c deleted file mode 100644 index b02b50253..000000000 --- a/third_party/curl/lib/mprintf.c +++ /dev/null @@ -1,1246 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1999 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * - * Purpose: - * A merge of Bjorn Reese's format() function and Daniel's dsprintf() - * 1.0. A full blooded printf() clone with full support for $ - * everywhere (parameters, widths and precisions) including variabled - * sized parameters (like doubles, long longs, long doubles and even - * void * in 64-bit architectures). - * - * Current restrictions: - * - Max 128 parameters - * - No 'long double' support. - * - * If you ever want truly portable and good *printf() clones, the project that - * took on from here is named 'Trio' and you find more details on the trio web - * page at http://daniel.haxx.se/trio/ - */ - -#include "setup.h" -#include -#include -#include -#include -#include - -#if defined(DJGPP) && (DJGPP_MINOR < 4) -#undef _MPRINTF_REPLACE /* don't use x_was_used() here */ -#endif - -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -#ifndef SIZEOF_LONG_DOUBLE -#define SIZEOF_LONG_DOUBLE 0 -#endif - -/* - * If SIZEOF_SIZE_T has not been defined, default to the size of long. - */ - -#ifndef SIZEOF_SIZE_T -# define SIZEOF_SIZE_T CURL_SIZEOF_LONG -#endif - -#ifdef HAVE_LONGLONG -# define LONG_LONG_TYPE long long -# define HAVE_LONG_LONG_TYPE -#else -# if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) -# define LONG_LONG_TYPE __int64 -# define HAVE_LONG_LONG_TYPE -# else -# undef LONG_LONG_TYPE -# undef HAVE_LONG_LONG_TYPE -# endif -#endif - -/* - * Max integer data types that mprintf.c is capable - */ - -#ifdef HAVE_LONG_LONG_TYPE -# define mp_intmax_t LONG_LONG_TYPE -# define mp_uintmax_t unsigned LONG_LONG_TYPE -#else -# define mp_intmax_t long -# define mp_uintmax_t unsigned long -#endif - -#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */ -#define MAX_PARAMETERS 128 /* lame static limit */ - -#ifdef __AMIGA__ -# undef FORMAT_INT -#endif - -/* Lower-case digits. */ -static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - -/* Upper-case digits. */ -static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -#define OUTCHAR(x) \ - do{ \ - if(stream((unsigned char)(x), (FILE *)data) != -1) \ - done++; \ - else \ - return done; /* return immediately on failure */ \ - } while(0) - -/* Data type to read from the arglist */ -typedef enum { - FORMAT_UNKNOWN = 0, - FORMAT_STRING, - FORMAT_PTR, - FORMAT_INT, - FORMAT_INTPTR, - FORMAT_LONG, - FORMAT_LONGLONG, - FORMAT_DOUBLE, - FORMAT_LONGDOUBLE, - FORMAT_WIDTH /* For internal use */ -} FormatType; - -/* conversion and display flags */ -enum { - FLAGS_NEW = 0, - FLAGS_SPACE = 1<<0, - FLAGS_SHOWSIGN = 1<<1, - FLAGS_LEFT = 1<<2, - FLAGS_ALT = 1<<3, - FLAGS_SHORT = 1<<4, - FLAGS_LONG = 1<<5, - FLAGS_LONGLONG = 1<<6, - FLAGS_LONGDOUBLE = 1<<7, - FLAGS_PAD_NIL = 1<<8, - FLAGS_UNSIGNED = 1<<9, - FLAGS_OCTAL = 1<<10, - FLAGS_HEX = 1<<11, - FLAGS_UPPER = 1<<12, - FLAGS_WIDTH = 1<<13, /* '*' or '*$' used */ - FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */ - FLAGS_PREC = 1<<15, /* precision was specified */ - FLAGS_PRECPARAM = 1<<16, /* precision PARAMETER was specified */ - FLAGS_CHAR = 1<<17, /* %c story */ - FLAGS_FLOATE = 1<<18, /* %e or %E */ - FLAGS_FLOATG = 1<<19 /* %g or %G */ -}; - -typedef struct { - FormatType type; - int flags; - long width; /* width OR width parameter number */ - long precision; /* precision OR precision parameter number */ - union { - char *str; - void *ptr; - union { - mp_intmax_t as_signed; - mp_uintmax_t as_unsigned; - } num; - double dnum; - } data; -} va_stack_t; - -struct nsprintf { - char *buffer; - size_t length; - size_t max; -}; - -struct asprintf { - char *buffer; /* allocated buffer */ - size_t len; /* length of string */ - size_t alloc; /* length of alloc */ - int fail; /* (!= 0) if an alloc has failed and thus - the output is not the complete data */ -}; - -static long dprintf_DollarString(char *input, char **end) -{ - int number=0; - while(ISDIGIT(*input)) { - number *= 10; - number += *input-'0'; - input++; - } - if(number && ('$'==*input++)) { - *end = input; - return number; - } - return 0; -} - -static int dprintf_IsQualifierNoDollar(char c) -{ - switch (c) { - case '-': case '+': case ' ': case '#': case '.': - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case 'h': case 'l': case 'L': case 'z': case 'q': - case '*': case 'O': - return 1; /* true */ - default: - return 0; /* false */ - } -} - -#ifdef DPRINTF_DEBUG2 -static void dprintf_Pass1Report(va_stack_t *vto, int max) -{ - int i; - char buffer[256]; - int bit; - int flags; - - for(i=0; i max_param) - max_param = this_param; - - /* - * The parameter with number 'i' should be used. Next, we need - * to get SIZE and TYPE of the parameter. Add the information - * to our array. - */ - - width = 0; - precision = 0; - - /* Handle the flags */ - - while(dprintf_IsQualifierNoDollar(*fmt)) { - switch (*fmt++) { - case ' ': - flags |= FLAGS_SPACE; - break; - case '+': - flags |= FLAGS_SHOWSIGN; - break; - case '-': - flags |= FLAGS_LEFT; - flags &= ~FLAGS_PAD_NIL; - break; - case '#': - flags |= FLAGS_ALT; - break; - case '.': - flags |= FLAGS_PREC; - if('*' == *fmt) { - /* The precision is picked from a specified parameter */ - - flags |= FLAGS_PRECPARAM; - fmt++; - param_num++; - - i = dprintf_DollarString(fmt, &fmt); - if(i) - precision = i; - else - precision = param_num; - - if(precision > max_param) - max_param = precision; - } - else { - flags |= FLAGS_PREC; - precision = strtol(fmt, &fmt, 10); - } - break; - case 'h': - flags |= FLAGS_SHORT; - break; - case 'l': - if(flags & FLAGS_LONG) - flags |= FLAGS_LONGLONG; - else - flags |= FLAGS_LONG; - break; - case 'L': - flags |= FLAGS_LONGDOUBLE; - break; - case 'q': - flags |= FLAGS_LONGLONG; - break; - case 'z': - /* the code below generates a warning if -Wunreachable-code is - used */ -#if (SIZEOF_SIZE_T > CURL_SIZEOF_LONG) - flags |= FLAGS_LONGLONG; -#else - flags |= FLAGS_LONG; -#endif - break; - case 'O': -#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) - flags |= FLAGS_LONGLONG; -#else - flags |= FLAGS_LONG; -#endif - break; - case '0': - if(!(flags & FLAGS_LEFT)) - flags |= FLAGS_PAD_NIL; - /* FALLTHROUGH */ - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - flags |= FLAGS_WIDTH; - width = strtol(fmt-1, &fmt, 10); - break; - case '*': /* Special case */ - flags |= FLAGS_WIDTHPARAM; - param_num++; - - i = dprintf_DollarString(fmt, &fmt); - if(i) - width = i; - else - width = param_num; - if(width > max_param) - max_param=width; - break; - default: - break; - } - } /* switch */ - - /* Handle the specifier */ - - i = this_param - 1; - - switch (*fmt) { - case 'S': - flags |= FLAGS_ALT; - /* FALLTHROUGH */ - case 's': - vto[i].type = FORMAT_STRING; - break; - case 'n': - vto[i].type = FORMAT_INTPTR; - break; - case 'p': - vto[i].type = FORMAT_PTR; - break; - case 'd': case 'i': - vto[i].type = FORMAT_INT; - break; - case 'u': - vto[i].type = FORMAT_INT; - flags |= FLAGS_UNSIGNED; - break; - case 'o': - vto[i].type = FORMAT_INT; - flags |= FLAGS_OCTAL; - break; - case 'x': - vto[i].type = FORMAT_INT; - flags |= FLAGS_HEX; - break; - case 'X': - vto[i].type = FORMAT_INT; - flags |= FLAGS_HEX|FLAGS_UPPER; - break; - case 'c': - vto[i].type = FORMAT_INT; - flags |= FLAGS_CHAR; - break; - case 'f': - vto[i].type = FORMAT_DOUBLE; - break; - case 'e': - vto[i].type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATE; - break; - case 'E': - vto[i].type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATE|FLAGS_UPPER; - break; - case 'g': - vto[i].type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATG; - break; - case 'G': - vto[i].type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATG|FLAGS_UPPER; - break; - default: - vto[i].type = FORMAT_UNKNOWN; - break; - } /* switch */ - - vto[i].flags = flags; - vto[i].width = width; - vto[i].precision = precision; - - if(flags & FLAGS_WIDTHPARAM) { - /* we have the width specified from a parameter, so we make that - parameter's info setup properly */ - vto[i].width = width - 1; - i = width - 1; - vto[i].type = FORMAT_WIDTH; - vto[i].flags = FLAGS_NEW; - vto[i].precision = vto[i].width = 0; /* can't use width or precision - of width! */ - } - if(flags & FLAGS_PRECPARAM) { - /* we have the precision specified from a parameter, so we make that - parameter's info setup properly */ - vto[i].precision = precision - 1; - i = precision - 1; - vto[i].type = FORMAT_WIDTH; - vto[i].flags = FLAGS_NEW; - vto[i].precision = vto[i].width = 0; /* can't use width or precision - of width! */ - } - *endpos++ = fmt + 1; /* end of this sequence */ - } - } - -#ifdef DPRINTF_DEBUG2 - dprintf_Pass1Report(vto, max_param); -#endif - - /* Read the arg list parameters into our data list */ - for (i=0; i$ sequence */ - param=dprintf_DollarString(f, &f); - - if(!param) - param = param_num; - else - --param; - - param_num++; /* increase this always to allow "%2$s %1$s %s" and then the - third %s will pick the 3rd argument */ - - p = &vto[param]; - - /* pick up the specified width */ - if(p->flags & FLAGS_WIDTHPARAM) - width = (long)vto[p->width].data.num.as_signed; - else - width = p->width; - - /* pick up the specified precision */ - if(p->flags & FLAGS_PRECPARAM) { - prec = (long)vto[p->precision].data.num.as_signed; - param_num++; /* since the precision is extraced from a parameter, we - must skip that to get to the next one properly */ - } - else if(p->flags & FLAGS_PREC) - prec = p->precision; - else - prec = -1; - - is_alt = (p->flags & FLAGS_ALT) ? 1 : 0; - - switch (p->type) { - case FORMAT_INT: - num = p->data.num.as_unsigned; - if(p->flags & FLAGS_CHAR) { - /* Character. */ - if(!(p->flags & FLAGS_LEFT)) - while(--width > 0) - OUTCHAR(' '); - OUTCHAR((char) num); - if(p->flags & FLAGS_LEFT) - while(--width > 0) - OUTCHAR(' '); - break; - } - if(p->flags & FLAGS_UNSIGNED) { - /* Decimal unsigned integer. */ - base = 10; - goto unsigned_number; - } - if(p->flags & FLAGS_OCTAL) { - /* Octal unsigned integer. */ - base = 8; - goto unsigned_number; - } - if(p->flags & FLAGS_HEX) { - /* Hexadecimal unsigned integer. */ - - digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; - base = 16; - goto unsigned_number; - } - - /* Decimal integer. */ - base = 10; - - is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0; - if(is_neg) { - /* signed_num might fail to hold absolute negative minimum by 1 */ - signed_num = p->data.num.as_signed + (mp_intmax_t)1; - signed_num = -signed_num; - num = (mp_uintmax_t)signed_num; - num += (mp_uintmax_t)1; - } - - goto number; - - unsigned_number: - /* Unsigned number of base BASE. */ - is_neg = 0; - - number: - /* Number of base BASE. */ - { - char *workend = &work[sizeof(work) - 1]; - char *w; - - /* Supply a default precision if none was given. */ - if(prec == -1) - prec = 1; - - /* Put the number in WORK. */ - w = workend; - while(num > 0) { - *w-- = digits[num % base]; - num /= base; - } - width -= (long)(workend - w); - prec -= (long)(workend - w); - - if(is_alt && base == 8 && prec <= 0) { - *w-- = '0'; - --width; - } - - if(prec > 0) { - width -= prec; - while(prec-- > 0) - *w-- = '0'; - } - - if(is_alt && base == 16) - width -= 2; - - if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE)) - --width; - - if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL)) - while(width-- > 0) - OUTCHAR(' '); - - if(is_neg) - OUTCHAR('-'); - else if(p->flags & FLAGS_SHOWSIGN) - OUTCHAR('+'); - else if(p->flags & FLAGS_SPACE) - OUTCHAR(' '); - - if(is_alt && base == 16) { - OUTCHAR('0'); - if(p->flags & FLAGS_UPPER) - OUTCHAR('X'); - else - OUTCHAR('x'); - } - - if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL)) - while(width-- > 0) - OUTCHAR('0'); - - /* Write the number. */ - while(++w <= workend) { - OUTCHAR(*w); - } - - if(p->flags & FLAGS_LEFT) - while(width-- > 0) - OUTCHAR(' '); - } - break; - - case FORMAT_STRING: - /* String. */ - { - static const char null[] = "(nil)"; - const char *str; - size_t len; - - str = (char *) p->data.str; - if( str == NULL) { - /* Write null[] if there's space. */ - if(prec == -1 || prec >= (long) sizeof(null) - 1) { - str = null; - len = sizeof(null) - 1; - /* Disable quotes around (nil) */ - p->flags &= (~FLAGS_ALT); - } - else { - str = ""; - len = 0; - } - } - else - len = strlen(str); - - if(prec != -1 && (size_t) prec < len) - len = (size_t)prec; - width -= (long)len; - - if(p->flags & FLAGS_ALT) - OUTCHAR('"'); - - if(!(p->flags&FLAGS_LEFT)) - while(width-- > 0) - OUTCHAR(' '); - - while(len-- > 0) - OUTCHAR(*str++); - if(p->flags&FLAGS_LEFT) - while(width-- > 0) - OUTCHAR(' '); - - if(p->flags & FLAGS_ALT) - OUTCHAR('"'); - } - break; - - case FORMAT_PTR: - /* Generic pointer. */ - { - void *ptr; - ptr = (void *) p->data.ptr; - if(ptr != NULL) { - /* If the pointer is not NULL, write it as a %#x spec. */ - base = 16; - digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; - is_alt = 1; - num = (size_t) ptr; - is_neg = 0; - goto number; - } - else { - /* Write "(nil)" for a nil pointer. */ - static const char strnil[] = "(nil)"; - const char *point; - - width -= (long)(sizeof(strnil) - 1); - if(p->flags & FLAGS_LEFT) - while(width-- > 0) - OUTCHAR(' '); - for (point = strnil; *point != '\0'; ++point) - OUTCHAR(*point); - if(! (p->flags & FLAGS_LEFT)) - while(width-- > 0) - OUTCHAR(' '); - } - } - break; - - case FORMAT_DOUBLE: - { - char formatbuf[32]="%"; - char *fptr; - size_t left = sizeof(formatbuf)-strlen(formatbuf); - int len; - - width = -1; - if(p->flags & FLAGS_WIDTH) - width = p->width; - else if(p->flags & FLAGS_WIDTHPARAM) - width = (long)vto[p->width].data.num.as_signed; - - prec = -1; - if(p->flags & FLAGS_PREC) - prec = p->precision; - else if(p->flags & FLAGS_PRECPARAM) - prec = (long)vto[p->precision].data.num.as_signed; - - if(p->flags & FLAGS_LEFT) - strcat(formatbuf, "-"); - if(p->flags & FLAGS_SHOWSIGN) - strcat(formatbuf, "+"); - if(p->flags & FLAGS_SPACE) - strcat(formatbuf, " "); - if(p->flags & FLAGS_ALT) - strcat(formatbuf, "#"); - - fptr=&formatbuf[strlen(formatbuf)]; - - if(width >= 0) { - /* RECURSIVE USAGE */ - len = curl_msnprintf(fptr, left, "%ld", width); - fptr += len; - left -= len; - } - if(prec >= 0) { - /* RECURSIVE USAGE */ - len = curl_msnprintf(fptr, left, ".%ld", prec); - fptr += len; - } - if(p->flags & FLAGS_LONG) - *fptr++ = 'l'; - - if(p->flags & FLAGS_FLOATE) - *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e'); - else if(p->flags & FLAGS_FLOATG) - *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g'); - else - *fptr++ = 'f'; - - *fptr = 0; /* and a final zero termination */ - - /* NOTE NOTE NOTE!! Not all sprintf() implementations returns number - of output characters */ - (sprintf)(work, formatbuf, p->data.dnum); - - for(fptr=work; *fptr; fptr++) - OUTCHAR(*fptr); - } - break; - - case FORMAT_INTPTR: - /* Answer the count of characters written. */ -#ifdef HAVE_LONG_LONG_TYPE - if(p->flags & FLAGS_LONGLONG) - *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done; - else -#endif - if(p->flags & FLAGS_LONG) - *(long *) p->data.ptr = (long)done; - else if(!(p->flags & FLAGS_SHORT)) - *(int *) p->data.ptr = (int)done; - else - *(short *) p->data.ptr = (short)done; - break; - - default: - break; - } - f = *end++; /* goto end of %-code */ - - } - return done; -} - -/* fputc() look-alike */ -static int addbyter(int output, FILE *data) -{ - struct nsprintf *infop=(struct nsprintf *)data; - unsigned char outc = (unsigned char)output; - - if(infop->length < infop->max) { - /* only do this if we haven't reached max length yet */ - infop->buffer[0] = outc; /* store */ - infop->buffer++; /* increase pointer */ - infop->length++; /* we are now one byte larger */ - return outc; /* fputc() returns like this on success */ - } - return -1; -} - -int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, - va_list ap_save) -{ - int retcode; - struct nsprintf info; - - info.buffer = buffer; - info.length = 0; - info.max = maxlength; - - retcode = dprintf_formatf(&info, addbyter, format, ap_save); - if(info.max) { - /* we terminate this with a zero byte */ - if(info.max == info.length) - /* we're at maximum, scrap the last letter */ - info.buffer[-1] = 0; - else - info.buffer[0] = 0; - } - return retcode; -} - -int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...) -{ - int retcode; - va_list ap_save; /* argument pointer */ - va_start(ap_save, format); - retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save); - va_end(ap_save); - return retcode; -} - -/* fputc() look-alike */ -static int alloc_addbyter(int output, FILE *data) -{ - struct asprintf *infop=(struct asprintf *)data; - unsigned char outc = (unsigned char)output; - - if(!infop->buffer) { - infop->buffer = malloc(32); - if(!infop->buffer) { - infop->fail = 1; - return -1; /* fail */ - } - infop->alloc = 32; - infop->len =0; - } - else if(infop->len+1 >= infop->alloc) { - char *newptr; - - newptr = realloc(infop->buffer, infop->alloc*2); - - if(!newptr) { - infop->fail = 1; - return -1; /* fail */ - } - infop->buffer = newptr; - infop->alloc *= 2; - } - - infop->buffer[ infop->len ] = outc; - - infop->len++; - - return outc; /* fputc() returns like this on success */ -} - -char *curl_maprintf(const char *format, ...) -{ - va_list ap_save; /* argument pointer */ - int retcode; - struct asprintf info; - - info.buffer = NULL; - info.len = 0; - info.alloc = 0; - info.fail = 0; - - va_start(ap_save, format); - retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); - va_end(ap_save); - if((-1 == retcode) || info.fail) { - if(info.alloc) - free(info.buffer); - return NULL; - } - if(info.alloc) { - info.buffer[info.len] = 0; /* we terminate this with a zero byte */ - return info.buffer; - } - else - return strdup(""); -} - -char *curl_mvaprintf(const char *format, va_list ap_save) -{ - int retcode; - struct asprintf info; - - info.buffer = NULL; - info.len = 0; - info.alloc = 0; - info.fail = 0; - - retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); - if((-1 == retcode) || info.fail) { - if(info.alloc) - free(info.buffer); - return NULL; - } - - if(info.alloc) { - info.buffer[info.len] = 0; /* we terminate this with a zero byte */ - return info.buffer; - } - else - return strdup(""); -} - -static int storebuffer(int output, FILE *data) -{ - char **buffer = (char **)data; - unsigned char outc = (unsigned char)output; - **buffer = outc; - (*buffer)++; - return outc; /* act like fputc() ! */ -} - -int curl_msprintf(char *buffer, const char *format, ...) -{ - va_list ap_save; /* argument pointer */ - int retcode; - va_start(ap_save, format); - retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save); - va_end(ap_save); - *buffer=0; /* we terminate this with a zero byte */ - return retcode; -} - -int curl_mprintf(const char *format, ...) -{ - int retcode; - va_list ap_save; /* argument pointer */ - va_start(ap_save, format); - - retcode = dprintf_formatf(stdout, fputc, format, ap_save); - va_end(ap_save); - return retcode; -} - -int curl_mfprintf(FILE *whereto, const char *format, ...) -{ - int retcode; - va_list ap_save; /* argument pointer */ - va_start(ap_save, format); - retcode = dprintf_formatf(whereto, fputc, format, ap_save); - va_end(ap_save); - return retcode; -} - -int curl_mvsprintf(char *buffer, const char *format, va_list ap_save) -{ - int retcode; - retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save); - *buffer=0; /* we terminate this with a zero byte */ - return retcode; -} - -int curl_mvprintf(const char *format, va_list ap_save) -{ - return dprintf_formatf(stdout, fputc, format, ap_save); -} - -int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save) -{ - return dprintf_formatf(whereto, fputc, format, ap_save); -} - -#ifdef DPRINTF_DEBUG -int main() -{ - char buffer[129]; - char *ptr; -#ifdef HAVE_LONG_LONG_TYPE - LONG_LONG_TYPE one=99; - LONG_LONG_TYPE two=100; - LONG_LONG_TYPE test = 0x1000000000LL; - curl_mprintf("%lld %lld %lld\n", one, two, test); -#endif - - curl_mprintf("%3d %5d\n", 10, 1998); - - ptr=curl_maprintf("test this then baby %s%s%s%s%s%s %d %d %d loser baby get a kiss in yer face now!", "", "pretty long string pretty long string pretty long string pretty long string pretty long string", "/", "/", "/", "pretty long string", 1998, 1999, 2001); - - puts(ptr); - - memset(ptr, 55, strlen(ptr)+1); - - free(ptr); - -#if 1 - curl_mprintf(buffer, "%s %s %d", "daniel", "stenberg", 19988); - puts(buffer); - - curl_mfprintf(stderr, "%s %#08x\n", "dummy", 65); - - printf("%s %#08x\n", "dummy", 65); - { - double tryout = 3.14156592; - curl_mprintf(buffer, "%.2g %G %f %e %E", tryout, tryout, tryout, tryout, tryout); - puts(buffer); - printf("%.2g %G %f %e %E\n", tryout, tryout, tryout, tryout, tryout); - } -#endif - - return 0; -} - -#endif diff --git a/third_party/curl/lib/multi.c b/third_party/curl/lib/multi.c deleted file mode 100644 index 40a341d29..000000000 --- a/third_party/curl/lib/multi.c +++ /dev/null @@ -1,2805 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif - -#include - -#include "urldata.h" -#include "transfer.h" -#include "url.h" -#include "connect.h" -#include "progress.h" -#include "easyif.h" -#include "multiif.h" -#include "sendf.h" -#include "timeval.h" -#include "http.h" -#include "warnless.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* - CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97 - to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every - CURL handle takes 45-50 K memory, therefore this 3K are not significant. -*/ -#ifndef CURL_SOCKET_HASH_TABLE_SIZE -#define CURL_SOCKET_HASH_TABLE_SIZE 911 -#endif - -struct Curl_message { - /* the 'CURLMsg' is the part that is visible to the external user */ - struct CURLMsg extmsg; -}; - -/* NOTE: if you add a state here, add the name to the statename[] array as - well! -*/ -typedef enum { - CURLM_STATE_INIT, /* 0 - start in this state */ - CURLM_STATE_CONNECT, /* 1 - resolve/connect has been sent off */ - CURLM_STATE_WAITRESOLVE, /* 2 - awaiting the resolve to finalize */ - CURLM_STATE_WAITCONNECT, /* 3 - awaiting the connect to finalize */ - CURLM_STATE_WAITPROXYCONNECT, /* 4 - awaiting proxy CONNECT to finalize */ - CURLM_STATE_PROTOCONNECT, /* 5 - completing the protocol-specific connect - phase */ - CURLM_STATE_WAITDO, /* 6 - wait for our turn to send the request */ - CURLM_STATE_DO, /* 7 - start send off the request (part 1) */ - CURLM_STATE_DOING, /* 8 - sending off the request (part 1) */ - CURLM_STATE_DO_MORE, /* 9 - send off the request (part 2) */ - CURLM_STATE_DO_DONE, /* 10 - done sending off request */ - CURLM_STATE_WAITPERFORM, /* 11 - wait for our turn to read the response */ - CURLM_STATE_PERFORM, /* 12 - transfer data */ - CURLM_STATE_TOOFAST, /* 13 - wait because limit-rate exceeded */ - CURLM_STATE_DONE, /* 14 - post data transfer operation */ - CURLM_STATE_COMPLETED, /* 15 - operation complete */ - CURLM_STATE_MSGSENT, /* 16 - the operation complete message is sent */ - CURLM_STATE_LAST /* 17 - not a true state, never use this */ -} CURLMstate; - -/* we support N sockets per easy handle. Set the corresponding bit to what - action we should wait for */ -#define MAX_SOCKSPEREASYHANDLE 5 -#define GETSOCK_READABLE (0x00ff) -#define GETSOCK_WRITABLE (0xff00) - -struct closure { - struct closure *next; /* a simple one-way list of structs */ - struct SessionHandle *easy_handle; -}; - -struct Curl_one_easy { - /* first, two fields for the linked list of these */ - struct Curl_one_easy *next; - struct Curl_one_easy *prev; - - struct SessionHandle *easy_handle; /* the easy handle for this unit */ - struct connectdata *easy_conn; /* the "unit's" connection */ - - CURLMstate state; /* the handle's state */ - CURLcode result; /* previous result */ - - struct Curl_message msg; /* A single posted message. */ - - /* Array with the plain socket numbers this handle takes care of, in no - particular order. Note that all sockets are added to the sockhash, where - the state etc are also kept. This array is mostly used to detect when a - socket is to be removed from the hash. See singlesocket(). */ - curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE]; - int numsocks; -}; - -#define CURL_MULTI_HANDLE 0x000bab1e - -#define GOOD_MULTI_HANDLE(x) \ - ((x)&&(((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE)) -#define GOOD_EASY_HANDLE(x) \ - (((struct SessionHandle *)(x))->magic == CURLEASY_MAGIC_NUMBER) - -/* This is the struct known as CURLM on the outside */ -struct Curl_multi { - /* First a simple identifier to easier detect if a user mix up - this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */ - long type; - - /* We have a linked list with easy handles */ - struct Curl_one_easy easy; - - int num_easy; /* amount of entries in the linked list above. */ - int num_alive; /* amount of easy handles that are added but have not yet - reached COMPLETE state */ - - struct curl_llist *msglist; /* a list of messages from completed transfers */ - - /* callback function and user data pointer for the *socket() API */ - curl_socket_callback socket_cb; - void *socket_userp; - - /* Hostname cache */ - struct curl_hash *hostcache; - - /* timetree points to the splay-tree of time nodes to figure out expire - times of all currently set timers */ - struct Curl_tree *timetree; - - /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note - the pluralis form, there can be more than one easy handle waiting on the - same actual socket) */ - struct curl_hash *sockhash; - - /* Whether pipelining is enabled for this multi handle */ - bool pipelining_enabled; - - /* shared connection cache */ - struct conncache *connc; - long maxconnects; /* if >0, a fixed limit of the maximum number of entries - we're allowed to grow the connection cache to */ - - /* list of easy handles kept around for doing nice connection closures */ - struct closure *closure; - - /* timer callback and user data pointer for the *socket() API */ - curl_multi_timer_callback timer_cb; - void *timer_userp; - struct timeval timer_lastcall; /* the fixed time for the timeout for the - previous callback */ -}; - -static void multi_connc_remove_handle(struct Curl_multi *multi, - struct SessionHandle *data); -static void singlesocket(struct Curl_multi *multi, - struct Curl_one_easy *easy); -static CURLMcode add_closure(struct Curl_multi *multi, - struct SessionHandle *data); -static int update_timer(struct Curl_multi *multi); - -static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle, - struct connectdata *conn); -static int checkPendPipeline(struct connectdata *conn); -static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle, - struct connectdata *conn); -static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle, - struct connectdata *conn); -static bool isHandleAtHead(struct SessionHandle *handle, - struct curl_llist *pipeline); -static CURLMcode add_next_timeout(struct timeval now, - struct Curl_multi *multi, - struct SessionHandle *d); - -#ifdef DEBUGBUILD -static const char * const statename[]={ - "INIT", - "CONNECT", - "WAITRESOLVE", - "WAITCONNECT", - "WAITPROXYCONNECT", - "PROTOCONNECT", - "WAITDO", - "DO", - "DOING", - "DO_MORE", - "DO_DONE", - "WAITPERFORM", - "PERFORM", - "TOOFAST", - "DONE", - "COMPLETED", - "MSGSENT", -}; -#endif - -static void multi_freetimeout(void *a, void *b); - -/* always use this function to change state, to make debugging easier */ -static void multistate(struct Curl_one_easy *easy, CURLMstate state) -{ -#ifdef DEBUGBUILD - long connectindex = -5000; -#endif - CURLMstate oldstate = easy->state; - - if(oldstate == state) - /* don't bother when the new state is the same as the old state */ - return; - - easy->state = state; - -#ifdef DEBUGBUILD - if(easy->easy_conn) { - if(easy->state > CURLM_STATE_CONNECT && - easy->state < CURLM_STATE_COMPLETED) - connectindex = easy->easy_conn->connectindex; - - infof(easy->easy_handle, - "STATE: %s => %s handle %p; (connection #%ld) \n", - statename[oldstate], statename[easy->state], - (char *)easy, connectindex); - } -#endif - if(state == CURLM_STATE_COMPLETED) - /* changing to COMPLETED means there's one less easy handle 'alive' */ - easy->easy_handle->multi->num_alive--; -} - -/* - * We add one of these structs to the sockhash for a particular socket - */ - -struct Curl_sh_entry { - struct SessionHandle *easy; - time_t timestamp; - int action; /* what action READ/WRITE this socket waits for */ - curl_socket_t socket; /* mainly to ease debugging */ - void *socketp; /* settable by users with curl_multi_assign() */ -}; -/* bits for 'action' having no bits means this socket is not expecting any - action */ -#define SH_READ 1 -#define SH_WRITE 2 - -/* make sure this socket is present in the hash for this handle */ -static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh, - curl_socket_t s, - struct SessionHandle *data) -{ - struct Curl_sh_entry *there = - Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t)); - struct Curl_sh_entry *check; - - if(there) - /* it is present, return fine */ - return there; - - /* not present, add it */ - check = calloc(1, sizeof(struct Curl_sh_entry)); - if(!check) - return NULL; /* major failure */ - check->easy = data; - check->socket = s; - - /* make/add new hash entry */ - if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) { - free(check); - return NULL; /* major failure */ - } - - return check; /* things are good in sockhash land */ -} - - -/* delete the given socket + handle from the hash */ -static void sh_delentry(struct curl_hash *sh, curl_socket_t s) -{ - struct Curl_sh_entry *there = - Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t)); - - if(there) { - /* this socket is in the hash */ - /* We remove the hash entry. (This'll end up in a call to - sh_freeentry().) */ - Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t)); - } -} - -/* - * free a sockhash entry - */ -static void sh_freeentry(void *freethis) -{ - struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis; - - if(p) - free(p); -} - -static size_t fd_key_compare(void*k1, size_t k1_len, void*k2, size_t k2_len) -{ - (void) k1_len; (void) k2_len; - - return (*((int* ) k1)) == (*((int* ) k2)); -} - -static size_t hash_fd(void* key, size_t key_length, size_t slots_num) -{ - int fd = * ((int* ) key); - (void) key_length; - - return (fd % (int)slots_num); -} - -/* - * sh_init() creates a new socket hash and returns the handle for it. - * - * Quote from README.multi_socket: - * - * "Some tests at 7000 and 9000 connections showed that the socket hash lookup - * is somewhat of a bottle neck. Its current implementation may be a bit too - * limiting. It simply has a fixed-size array, and on each entry in the array - * it has a linked list with entries. So the hash only checks which list to - * scan through. The code I had used so for used a list with merely 7 slots - * (as that is what the DNS hash uses) but with 7000 connections that would - * make an average of 1000 nodes in each list to run through. I upped that to - * 97 slots (I believe a prime is suitable) and noticed a significant speed - * increase. I need to reconsider the hash implementation or use a rather - * large default value like this. At 9000 connections I was still below 10us - * per call." - * - */ -static struct curl_hash *sh_init(void) -{ - return Curl_hash_alloc(CURL_SOCKET_HASH_TABLE_SIZE, hash_fd, fd_key_compare, - sh_freeentry); -} - -/* - * multi_addmsg() - * - * Called when a transfer is completed. Adds the given msg pointer to - * the list kept in the multi handle. - */ -static CURLMcode multi_addmsg(struct Curl_multi *multi, - struct Curl_message *msg) -{ - if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg)) - return CURLM_OUT_OF_MEMORY; - - return CURLM_OK; -} - -/* - * multi_freeamsg() - * - * Callback used by the llist system when a single list entry is destroyed. - */ -static void multi_freeamsg(void *a, void *b) -{ - (void)a; - (void)b; -} - - -CURLM *curl_multi_init(void) -{ - struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi)); - - if(!multi) - return NULL; - - multi->type = CURL_MULTI_HANDLE; - - multi->hostcache = Curl_mk_dnscache(); - if(!multi->hostcache) - goto error; - - multi->sockhash = sh_init(); - if(!multi->sockhash) - goto error; - - multi->connc = Curl_mk_connc(CONNCACHE_MULTI, -1L); - if(!multi->connc) - goto error; - - multi->msglist = Curl_llist_alloc(multi_freeamsg); - if(!multi->msglist) - goto error; - - /* Let's make the doubly-linked list a circular list. This makes - the linked list code simpler and allows inserting at the end - with less work (we didn't keep a tail pointer before). */ - multi->easy.next = &multi->easy; - multi->easy.prev = &multi->easy; - - return (CURLM *) multi; - - error: - if(multi->sockhash) - Curl_hash_destroy(multi->sockhash); - if(multi->hostcache) - Curl_hash_destroy(multi->hostcache); - if(multi->connc) - Curl_rm_connc(multi->connc); - - free(multi); - return NULL; -} - -CURLMcode curl_multi_add_handle(CURLM *multi_handle, - CURL *easy_handle) -{ - struct Curl_multi *multi=(struct Curl_multi *)multi_handle; - struct Curl_one_easy *easy; - struct closure *cl; - struct closure *prev=NULL; - struct SessionHandle *data = easy_handle; - - /* First, make some basic checks that the CURLM handle is a good handle */ - if(!GOOD_MULTI_HANDLE(multi)) - return CURLM_BAD_HANDLE; - - /* Verify that we got a somewhat good easy handle too */ - if(!GOOD_EASY_HANDLE(easy_handle)) - return CURLM_BAD_EASY_HANDLE; - - /* Prevent users to add the same handle more than once! */ - if(((struct SessionHandle *)easy_handle)->multi) - /* possibly we should create a new unique error code for this condition */ - return CURLM_BAD_EASY_HANDLE; - - data->state.timeoutlist = Curl_llist_alloc(multi_freetimeout); - if(!data->state.timeoutlist) - return CURLM_OUT_OF_MEMORY; - - /* Now, time to add an easy handle to the multi stack */ - easy = calloc(1, sizeof(struct Curl_one_easy)); - if(!easy) - return CURLM_OUT_OF_MEMORY; - - cl = multi->closure; - while(cl) { - struct closure *next = cl->next; - if(cl->easy_handle == (struct SessionHandle *)easy_handle) { - /* remove this handle from the closure list */ - free(cl); - if(prev) - prev->next = next; - else - multi->closure = next; - break; /* no need to continue since this handle can only be present once - in the list */ - } - prev = cl; - cl = next; - } - - /* set the easy handle */ - easy->easy_handle = easy_handle; - multistate(easy, CURLM_STATE_INIT); - - /* set the back pointer to one_easy to assist in removal */ - easy->easy_handle->multi_pos = easy; - - /* for multi interface connections, we share DNS cache automatically if the - easy handle's one is currently private. */ - if(easy->easy_handle->dns.hostcache && - (easy->easy_handle->dns.hostcachetype == HCACHE_PRIVATE)) { - Curl_hash_destroy(easy->easy_handle->dns.hostcache); - easy->easy_handle->dns.hostcache = NULL; - easy->easy_handle->dns.hostcachetype = HCACHE_NONE; - } - - if(!easy->easy_handle->dns.hostcache || - (easy->easy_handle->dns.hostcachetype == HCACHE_NONE)) { - easy->easy_handle->dns.hostcache = multi->hostcache; - easy->easy_handle->dns.hostcachetype = HCACHE_MULTI; - } - - if(easy->easy_handle->state.connc) { - if(easy->easy_handle->state.connc->type == CONNCACHE_PRIVATE) { - /* kill old private version */ - Curl_rm_connc(easy->easy_handle->state.connc); - /* point out our shared one instead */ - easy->easy_handle->state.connc = multi->connc; - } - /* else it is already using multi? */ - } - else - /* point out our shared one */ - easy->easy_handle->state.connc = multi->connc; - - /* Make sure the type is setup correctly */ - easy->easy_handle->state.connc->type = CONNCACHE_MULTI; - - /* This adds the new entry at the back of the list - to try and maintain a FIFO queue so the pipelined - requests are in order. */ - - /* We add this new entry last in the list. We make our 'next' point to the - 'first' struct and our 'prev' point to the previous 'prev' */ - easy->next = &multi->easy; - easy->prev = multi->easy.prev; - - /* make 'easy' the last node in the chain */ - multi->easy.prev = easy; - - /* if there was a prev node, make sure its 'next' pointer links to - the new node */ - easy->prev->next = easy; - - Curl_easy_addmulti(easy_handle, multi_handle); - - /* make the SessionHandle struct refer back to this struct */ - easy->easy_handle->set.one_easy = easy; - - /* Set the timeout for this handle to expire really soon so that it will - be taken care of even when this handle is added in the midst of operation - when only the curl_multi_socket() API is used. During that flow, only - sockets that time-out or have actions will be dealt with. Since this - handle has no action yet, we make sure it times out to get things to - happen. */ - Curl_expire(easy->easy_handle, 1); - - /* increase the node-counter */ - multi->num_easy++; - - if((multi->num_easy * 4) > multi->connc->num) { - /* We want the connection cache to have plenty room. Before we supported - the shared cache every single easy handle had 5 entries in their cache - by default. */ - long newmax = multi->num_easy * 4; - - if(multi->maxconnects && (multi->maxconnects < newmax)) - /* don't grow beyond the allowed size */ - newmax = multi->maxconnects; - - if(newmax > multi->connc->num) { - /* we only do this is we can in fact grow the cache */ - CURLcode res = Curl_ch_connc(easy_handle, multi->connc, newmax); - if(res != CURLE_OK) { - /* FIXME: may need to do more cleanup here */ - curl_multi_remove_handle(multi_handle, easy_handle); - return CURLM_OUT_OF_MEMORY; - } - } - } - - /* increase the alive-counter */ - multi->num_alive++; - - /* A somewhat crude work-around for a little glitch in update_timer() that - happens if the lastcall time is set to the same time when the handle is - removed as when the next handle is added, as then the check in - update_timer() that prevents calling the application multiple times with - the same timer infor will not trigger and then the new handle's timeout - will not be notified to the app. - - The work-around is thus simply to clear the 'lastcall' variable to force - update_timer() to always trigger a callback to the app when a new easy - handle is added */ - memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall)); - - update_timer(multi); - return CURLM_OK; -} - -#if 0 -/* Debug-function, used like this: - * - * Curl_hash_print(multi->sockhash, debug_print_sock_hash); - * - * Enable the hash print function first by editing hash.c - */ -static void debug_print_sock_hash(void *p) -{ - struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p; - - fprintf(stderr, " [easy %p/magic %x/socket %d]", - (void *)sh->easy, sh->easy->magic, (int)sh->socket); -} -#endif - -CURLMcode curl_multi_remove_handle(CURLM *multi_handle, - CURL *curl_handle) -{ - struct Curl_multi *multi=(struct Curl_multi *)multi_handle; - struct Curl_one_easy *easy; - struct SessionHandle *data = curl_handle; - - /* First, make some basic checks that the CURLM handle is a good handle */ - if(!GOOD_MULTI_HANDLE(multi)) - return CURLM_BAD_HANDLE; - - /* Verify that we got a somewhat good easy handle too */ - if(!GOOD_EASY_HANDLE(curl_handle)) - return CURLM_BAD_EASY_HANDLE; - - /* pick-up from the 'curl_handle' the kept position in the list */ - easy = data->multi_pos; - - if(easy) { - bool premature = (bool)(easy->state < CURLM_STATE_COMPLETED); - bool easy_owns_conn = (bool)(easy->easy_conn && - (easy->easy_conn->data == easy->easy_handle)); - - /* If the 'state' is not INIT or COMPLETED, we might need to do something - nice to put the easy_handle in a good known state when this returns. */ - if(premature) - /* this handle is "alive" so we need to count down the total number of - alive connections when this is removed */ - multi->num_alive--; - - if(easy->easy_conn && - (easy->easy_conn->send_pipe->size + - easy->easy_conn->recv_pipe->size > 1) && - easy->state > CURLM_STATE_WAITDO && - easy->state < CURLM_STATE_COMPLETED) { - /* If the handle is in a pipeline and has started sending off its - request but not received its response yet, we need to close - connection. */ - easy->easy_conn->bits.close = TRUE; - /* Set connection owner so that Curl_done() closes it. - We can sefely do this here since connection is killed. */ - easy->easy_conn->data = easy->easy_handle; - } - - /* The timer must be shut down before easy->multi is set to NULL, - else the timenode will remain in the splay tree after - curl_easy_cleanup is called. */ - Curl_expire(easy->easy_handle, 0); - - /* destroy the timeout list that is held in the easy handle */ - if(data->state.timeoutlist) { - Curl_llist_destroy(data->state.timeoutlist, NULL); - data->state.timeoutlist = NULL; - } - - if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) { - /* clear out the usage of the shared DNS cache */ - easy->easy_handle->dns.hostcache = NULL; - easy->easy_handle->dns.hostcachetype = HCACHE_NONE; - } - - if(easy->easy_conn) { - - /* we must call Curl_done() here (if we still "own it") so that we don't - leave a half-baked one around */ - if (easy_owns_conn) { - - /* Curl_done() clears the conn->data field to lose the association - between the easy handle and the connection - - Note that this ignores the return code simply because there's - nothing really useful to do with it anyway! */ - (void)Curl_done(&easy->easy_conn, easy->result, premature); - - if(easy->easy_conn) - /* the connection is still alive, set back the association to enable - the check below to trigger TRUE */ - easy->easy_conn->data = easy->easy_handle; - } - else - /* Clear connection pipelines, if Curl_done above was not called */ - Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn); - } - - /* figure out if the easy handle is used by one or more connections in the - cache */ - multi_connc_remove_handle(multi, easy->easy_handle); - - if(easy->easy_handle->state.connc->type == CONNCACHE_MULTI) { - /* if this was using the shared connection cache we clear the pointer - to that since we're not part of that handle anymore */ - easy->easy_handle->state.connc = NULL; - - /* Since we return the connection back to the communal connection pool - we mark the last connection as inaccessible */ - easy->easy_handle->state.lastconnect = -1; - - /* Modify the connectindex since this handle can't point to the - connection cache anymore. - - TODO: consider if this is really what we want. The connection cache - is within the multi handle and that owns the connections so we should - not need to touch connections like this when we just remove an easy - handle... - */ - if(easy->easy_conn && easy_owns_conn && - (easy->easy_conn->send_pipe->size + - easy->easy_conn->recv_pipe->size == 0)) - easy->easy_conn->connectindex = -1; - } - - /* change state without using multistate(), only to make singlesocket() do - what we want */ - easy->state = CURLM_STATE_COMPLETED; - singlesocket(multi, easy); /* to let the application know what sockets - that vanish with this handle */ - - Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association - to this multi handle */ - - { - /* make sure there's no pending message in the queue sent from this easy - handle */ - struct curl_llist_element *e; - - for(e = multi->msglist->head; e; e = e->next) { - struct Curl_message *msg = e->ptr; - - if(msg->extmsg.easy_handle == easy->easy_handle) { - Curl_llist_remove(multi->msglist, e, NULL); - /* there can only be one from this specific handle */ - break; - } - } - } - - /* make the previous node point to our next */ - if(easy->prev) - easy->prev->next = easy->next; - /* make our next point to our previous node */ - if(easy->next) - easy->next->prev = easy->prev; - - easy->easy_handle->set.one_easy = NULL; /* detached */ - - /* Null the position in the controlling structure */ - easy->easy_handle->multi_pos = NULL; - - /* NOTE NOTE NOTE - We do not touch the easy handle here! */ - free(easy); - - multi->num_easy--; /* one less to care about now */ - - update_timer(multi); - return CURLM_OK; - } - else - return CURLM_BAD_EASY_HANDLE; /* twasn't found */ -} - -bool Curl_multi_canPipeline(const struct Curl_multi* multi) -{ - return multi->pipelining_enabled; -} - -void Curl_multi_handlePipeBreak(struct SessionHandle *data) -{ - struct Curl_one_easy *one_easy = data->set.one_easy; - - if(one_easy) - one_easy->easy_conn = NULL; -} - -static int waitconnect_getsock(struct connectdata *conn, - curl_socket_t *sock, - int numsocks) -{ - if(!numsocks) - return GETSOCK_BLANK; - - sock[0] = conn->sock[FIRSTSOCKET]; - - /* when we've sent a CONNECT to a proxy, we should rather wait for the - socket to become readable to be able to get the response headers */ - if(conn->bits.tunnel_connecting) - return GETSOCK_READSOCK(0); - - return GETSOCK_WRITESOCK(0); -} - -static int domore_getsock(struct connectdata *conn, - curl_socket_t *sock, - int numsocks) -{ - 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. It makes a difference in the way: if we - connect to the site we wait for the socket to become writable, if - the site connects to us we wait for it to become readable */ - sock[0] = conn->sock[SECONDARYSOCKET]; - - return GETSOCK_WRITESOCK(0); -} - -/* returns bitmapped flags for this handle and its sockets */ -static int multi_getsock(struct Curl_one_easy *easy, - curl_socket_t *socks, /* points to numsocks number - of sockets */ - int numsocks) -{ - /* If the pipe broke, or if there's no connection left for this easy handle, - then we MUST bail out now with no bitmask set. The no connection case can - happen when this is called from curl_multi_remove_handle() => - singlesocket() => multi_getsock(). - */ - if(easy->easy_handle->state.pipe_broke || !easy->easy_conn) - return 0; - - if(easy->state > CURLM_STATE_CONNECT && - easy->state < CURLM_STATE_COMPLETED) { - /* Set up ownership correctly */ - easy->easy_conn->data = easy->easy_handle; - } - - switch(easy->state) { - default: -#if 0 /* switch back on these cases to get the compiler to check for all enums - to be present */ - case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */ - case CURLM_STATE_COMPLETED: - case CURLM_STATE_MSGSENT: - case CURLM_STATE_INIT: - case CURLM_STATE_CONNECT: - case CURLM_STATE_WAITDO: - case CURLM_STATE_DONE: - case CURLM_STATE_LAST: - /* this will get called with CURLM_STATE_COMPLETED when a handle is - removed */ -#endif - return 0; - - case CURLM_STATE_WAITRESOLVE: - return Curl_resolv_getsock(easy->easy_conn, socks, numsocks); - - case CURLM_STATE_PROTOCONNECT: - return Curl_protocol_getsock(easy->easy_conn, socks, numsocks); - - case CURLM_STATE_DO: - case CURLM_STATE_DOING: - return Curl_doing_getsock(easy->easy_conn, socks, numsocks); - - case CURLM_STATE_WAITPROXYCONNECT: - case CURLM_STATE_WAITCONNECT: - return waitconnect_getsock(easy->easy_conn, socks, numsocks); - - case CURLM_STATE_DO_MORE: - return domore_getsock(easy->easy_conn, socks, numsocks); - - case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch - to waiting for the same as the *PERFORM - states */ - case CURLM_STATE_PERFORM: - case CURLM_STATE_WAITPERFORM: - return Curl_single_getsock(easy->easy_conn, socks, numsocks); - } - -} - -CURLMcode curl_multi_fdset(CURLM *multi_handle, - fd_set *read_fd_set, fd_set *write_fd_set, - fd_set *exc_fd_set, int *max_fd) -{ - /* Scan through all the easy handles to get the file descriptors set. - Some easy handles may not have connected to the remote host yet, - and then we must make sure that is done. */ - struct Curl_multi *multi=(struct Curl_multi *)multi_handle; - struct Curl_one_easy *easy; - int this_max_fd=-1; - curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; - int bitmap; - int i; - (void)exc_fd_set; /* not used */ - - if(!GOOD_MULTI_HANDLE(multi)) - return CURLM_BAD_HANDLE; - - easy=multi->easy.next; - while(easy != &multi->easy) { - bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE); - - for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) { - curl_socket_t s = CURL_SOCKET_BAD; - - if(bitmap & GETSOCK_READSOCK(i)) { - FD_SET(sockbunch[i], read_fd_set); - s = sockbunch[i]; - } - if(bitmap & GETSOCK_WRITESOCK(i)) { - FD_SET(sockbunch[i], write_fd_set); - s = sockbunch[i]; - } - if(s == CURL_SOCKET_BAD) - /* this socket is unused, break out of loop */ - break; - else { - if((int)s > this_max_fd) - this_max_fd = (int)s; - } - } - - easy = easy->next; /* check next handle */ - } - - *max_fd = this_max_fd; - - return CURLM_OK; -} - -static CURLMcode multi_runsingle(struct Curl_multi *multi, - struct timeval now, - struct Curl_one_easy *easy) -{ - struct Curl_message *msg = NULL; - bool connected; - bool async; - bool protocol_connect = FALSE; - bool dophase_done; - bool done = FALSE; - CURLMcode result = CURLM_OK; - struct SingleRequest *k; - struct SessionHandle *data; - long timeout_ms; - - if(!GOOD_EASY_HANDLE(easy->easy_handle)) - return CURLM_BAD_EASY_HANDLE; - - data = easy->easy_handle; - - do { - /* this is a do-while loop just to allow a break to skip to the end - of it */ - bool disconnect_conn = FALSE; - - /* Handle the case when the pipe breaks, i.e., the connection - we're using gets cleaned up and we're left with nothing. */ - if(data->state.pipe_broke) { - infof(data, "Pipe broke: handle 0x%p, url = %s\n", - easy, data->state.path); - - if(easy->state < CURLM_STATE_COMPLETED) { - /* Head back to the CONNECT state */ - multistate(easy, CURLM_STATE_CONNECT); - result = CURLM_CALL_MULTI_PERFORM; - easy->result = CURLE_OK; - } - - data->state.pipe_broke = FALSE; - easy->easy_conn = NULL; - break; - } - - if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT && - easy->state < CURLM_STATE_COMPLETED) - /* Make sure we set the connection's current owner */ - easy->easy_conn->data = data; - - if(easy->easy_conn && - (easy->state >= CURLM_STATE_CONNECT) && - (easy->state < 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, - (easy->state <= CURLM_STATE_WAITDO)? - TRUE:FALSE); - - if(timeout_ms < 0) { - /* Handle timed out */ - if(easy->state == CURLM_STATE_WAITRESOLVE) - failf(data, "Resolving timed out after %ld milliseconds", - Curl_tvdiff(now, data->progress.t_startsingle)); - else if(easy->state == CURLM_STATE_WAITCONNECT) - failf(data, "Connection timed out after %ld milliseconds", - Curl_tvdiff(now, data->progress.t_startsingle)); - else { - k = &data->req; - failf(data, "Operation timed out after %ld milliseconds with %" - FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received", - Curl_tvdiff(now, data->progress.t_startsingle), k->bytecount, - k->size); - } - - /* Force the connection closed because the server could continue to - send us stuff at any time. (The disconnect_conn logic used below - doesn't work at this point). */ - easy->easy_conn->bits.close = TRUE; - easy->result = CURLE_OPERATION_TIMEDOUT; - multistate(easy, CURLM_STATE_COMPLETED); - break; - } - } - - switch(easy->state) { - case CURLM_STATE_INIT: - /* init this transfer. */ - easy->result=Curl_pretransfer(data); - - if(CURLE_OK == easy->result) { - /* after init, go CONNECT */ - multistate(easy, CURLM_STATE_CONNECT); - result = CURLM_CALL_MULTI_PERFORM; - - data->state.used_interface = Curl_if_multi; - } - break; - - case CURLM_STATE_CONNECT: - /* Connect. We get a connection identifier filled in. */ - Curl_pgrsTime(data, TIMER_STARTSINGLE); - easy->result = Curl_connect(data, &easy->easy_conn, - &async, &protocol_connect); - - if(CURLE_OK == easy->result) { - /* Add this handle to the send or pend pipeline */ - easy->result = addHandleToSendOrPendPipeline(data, - easy->easy_conn); - if(CURLE_OK == easy->result) { - if(async) - /* We're now waiting for an asynchronous name lookup */ - multistate(easy, CURLM_STATE_WAITRESOLVE); - else { - /* after the connect has been sent off, go WAITCONNECT unless the - protocol connect is already done and we can go directly to - WAITDO or DO! */ - result = CURLM_CALL_MULTI_PERFORM; - - if(protocol_connect) - multistate(easy, multi->pipelining_enabled? - CURLM_STATE_WAITDO:CURLM_STATE_DO); - else { -#ifndef CURL_DISABLE_HTTP - if(easy->easy_conn->bits.tunnel_connecting) - multistate(easy, CURLM_STATE_WAITPROXYCONNECT); - else -#endif - multistate(easy, CURLM_STATE_WAITCONNECT); - } - } - } - } - break; - - case CURLM_STATE_WAITRESOLVE: - /* awaiting an asynch name resolve to complete */ - { - struct Curl_dns_entry *dns = NULL; - - /* check if we have the name resolved by now */ - easy->result = Curl_is_resolved(easy->easy_conn, &dns); - - if(dns) { - /* Update sockets here. Mainly because the socket(s) may have been - closed and the application thus needs to be told, even if it is - likely that the same socket(s) will again be used further down. */ - singlesocket(multi, easy); - - /* Perform the next step in the connection phase, and then move on - to the WAITCONNECT state */ - easy->result = Curl_async_resolved(easy->easy_conn, - &protocol_connect); - - if(CURLE_OK != easy->result) - /* if Curl_async_resolved() returns failure, the connection struct - is already freed and gone */ - easy->easy_conn = NULL; /* no more connection */ - else { - /* call again please so that we get the next socket setup */ - result = CURLM_CALL_MULTI_PERFORM; - if(protocol_connect) - multistate(easy, multi->pipelining_enabled? - CURLM_STATE_WAITDO:CURLM_STATE_DO); - else { -#ifndef CURL_DISABLE_HTTP - if(easy->easy_conn->bits.tunnel_connecting) - multistate(easy, CURLM_STATE_WAITPROXYCONNECT); - else -#endif - multistate(easy, CURLM_STATE_WAITCONNECT); - } - } - } - - if(CURLE_OK != easy->result) { - /* failure detected */ - disconnect_conn = TRUE; - break; - } - } - break; - -#ifndef CURL_DISABLE_HTTP - case CURLM_STATE_WAITPROXYCONNECT: - /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */ - easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect); - - if(easy->easy_conn->bits.proxy_connect_closed) { - /* reset the error buffer */ - if(data->set.errorbuffer) - data->set.errorbuffer[0] = '\0'; - data->state.errorbuf = FALSE; - - easy->result = CURLE_OK; - result = CURLM_CALL_MULTI_PERFORM; - multistate(easy, CURLM_STATE_CONNECT); - } - else if (CURLE_OK == easy->result) { - if(!easy->easy_conn->bits.tunnel_connecting) - multistate(easy, CURLM_STATE_WAITCONNECT); - } - break; -#endif - - case CURLM_STATE_WAITCONNECT: - /* awaiting a completion of an asynch connect */ - easy->result = Curl_is_connected(easy->easy_conn, - FIRSTSOCKET, - &connected); - if(connected) { - /* see if we need to do any proxy magic first once we connected */ - easy->result = Curl_connected_proxy(easy->easy_conn); - - if(!easy->result) - /* if everything is still fine we do the protocol-specific connect - setup */ - easy->result = Curl_protocol_connect(easy->easy_conn, - &protocol_connect); - } - - if(CURLE_OK != easy->result) { - /* failure detected */ - /* Just break, the cleaning up is handled all in one place */ - disconnect_conn = TRUE; - break; - } - - if(connected) { - if(!protocol_connect) { - /* We have a TCP connection, but 'protocol_connect' may be false - and then we continue to 'STATE_PROTOCONNECT'. If protocol - connect is TRUE, we move on to STATE_DO. - BUT if we are using a proxy we must change to WAITPROXYCONNECT - */ -#ifndef CURL_DISABLE_HTTP - if(easy->easy_conn->bits.tunnel_connecting) - multistate(easy, CURLM_STATE_WAITPROXYCONNECT); - else -#endif - multistate(easy, CURLM_STATE_PROTOCONNECT); - - } - else - /* after the connect has completed, go WAITDO or DO */ - multistate(easy, multi->pipelining_enabled? - CURLM_STATE_WAITDO:CURLM_STATE_DO); - - result = CURLM_CALL_MULTI_PERFORM; - } - break; - - case CURLM_STATE_PROTOCONNECT: - /* protocol-specific connect phase */ - easy->result = Curl_protocol_connecting(easy->easy_conn, - &protocol_connect); - if((easy->result == CURLE_OK) && protocol_connect) { - /* after the connect has completed, go WAITDO or DO */ - multistate(easy, multi->pipelining_enabled? - CURLM_STATE_WAITDO:CURLM_STATE_DO); - result = CURLM_CALL_MULTI_PERFORM; - } - else if(easy->result) { - /* failure detected */ - Curl_posttransfer(data); - Curl_done(&easy->easy_conn, easy->result, TRUE); - disconnect_conn = TRUE; - } - break; - - case CURLM_STATE_WAITDO: - /* Wait for our turn to DO when we're pipelining requests */ -#ifdef DEBUGBUILD - infof(data, "Conn %ld send pipe %zu inuse %d athead %d\n", - easy->easy_conn->connectindex, - easy->easy_conn->send_pipe->size, - easy->easy_conn->writechannel_inuse?1:0, - isHandleAtHead(data, - easy->easy_conn->send_pipe)?1:0); -#endif - if(!easy->easy_conn->writechannel_inuse && - isHandleAtHead(data, - easy->easy_conn->send_pipe)) { - /* Grab the channel */ - easy->easy_conn->writechannel_inuse = TRUE; - multistate(easy, CURLM_STATE_DO); - result = CURLM_CALL_MULTI_PERFORM; - } - break; - - case CURLM_STATE_DO: - if(data->set.connect_only) { - /* keep connection open for application to use the socket */ - easy->easy_conn->bits.close = FALSE; - multistate(easy, CURLM_STATE_DONE); - easy->result = CURLE_OK; - result = CURLM_OK; - } - else { - /* Perform the protocol's DO action */ - easy->result = Curl_do(&easy->easy_conn, - &dophase_done); - - if(CURLE_OK == easy->result) { - if(!dophase_done) { - /* some steps needed for wildcard matching */ - if(data->set.wildcardmatch) { - struct WildcardData *wc = &data->wildcard; - if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) { - /* skip some states if it is important */ - Curl_done(&easy->easy_conn, CURLE_OK, FALSE); - multistate(easy, CURLM_STATE_DONE); - result = CURLM_CALL_MULTI_PERFORM; - break; - } - } - /* DO was not completed in one function call, we must continue - DOING... */ - multistate(easy, CURLM_STATE_DOING); - result = CURLM_OK; - } - - /* after DO, go DO_DONE... or DO_MORE */ - else if(easy->easy_conn->bits.do_more) { - /* we're supposed to do more, but we need to sit down, relax - and wait a little while first */ - multistate(easy, CURLM_STATE_DO_MORE); - result = CURLM_OK; - } - else { - /* we're done with the DO, now DO_DONE */ - multistate(easy, CURLM_STATE_DO_DONE); - result = CURLM_CALL_MULTI_PERFORM; - } - } - else if ((CURLE_SEND_ERROR == easy->result) && - easy->easy_conn->bits.reuse) { - /* - * In this situation, a connection that we were trying to use - * may have unexpectedly died. If possible, send the connection - * back to the CONNECT phase so we can try again. - */ - char *newurl = NULL; - followtype follow=FOLLOW_NONE; - CURLcode drc; - bool retry = FALSE; - - drc = Curl_retry_request(easy->easy_conn, &newurl); - if(drc) { - /* a failure here pretty much implies an out of memory */ - easy->result = drc; - disconnect_conn = TRUE; - } - else - retry = (bool)(newurl?TRUE:FALSE); - - Curl_posttransfer(data); - drc = Curl_done(&easy->easy_conn, easy->result, FALSE); - - /* When set to retry the connection, we must to go back to - * the CONNECT state */ - if(retry) { - if ((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) { - follow = FOLLOW_RETRY; - drc = Curl_follow(data, newurl, follow); - if(drc == CURLE_OK) { - multistate(easy, CURLM_STATE_CONNECT); - result = CURLM_CALL_MULTI_PERFORM; - easy->result = CURLE_OK; - } - else { - /* Follow failed */ - easy->result = drc; - free(newurl); - } - } - else { - /* done didn't return OK or SEND_ERROR */ - easy->result = drc; - free(newurl); - } - } - else { - /* Have error handler disconnect conn if we can't retry */ - disconnect_conn = TRUE; - } - } - else { - /* failure detected */ - Curl_posttransfer(data); - Curl_done(&easy->easy_conn, easy->result, FALSE); - disconnect_conn = TRUE; - } - } - break; - - case CURLM_STATE_DOING: - /* we continue DOING until the DO phase is complete */ - easy->result = Curl_protocol_doing(easy->easy_conn, - &dophase_done); - if(CURLE_OK == easy->result) { - if(dophase_done) { - /* after DO, go PERFORM... or DO_MORE */ - if(easy->easy_conn->bits.do_more) { - /* we're supposed to do more, but we need to sit down, relax - and wait a little while first */ - multistate(easy, CURLM_STATE_DO_MORE); - result = CURLM_OK; - } - else { - /* we're done with the DO, now DO_DONE */ - multistate(easy, CURLM_STATE_DO_DONE); - result = CURLM_CALL_MULTI_PERFORM; - } - } /* dophase_done */ - } - else { - /* failure detected */ - Curl_posttransfer(data); - Curl_done(&easy->easy_conn, easy->result, FALSE); - disconnect_conn = TRUE; - } - break; - - case CURLM_STATE_DO_MORE: - /* Ready to do more? */ - easy->result = Curl_is_connected(easy->easy_conn, - SECONDARYSOCKET, - &connected); - if(connected) { - /* - * When we are connected, DO MORE and then go DO_DONE - */ - easy->result = Curl_do_more(easy->easy_conn); - - /* No need to remove ourselves from the send pipeline here since that - is done for us in Curl_done() */ - - if(CURLE_OK == easy->result) { - multistate(easy, CURLM_STATE_DO_DONE); - result = CURLM_CALL_MULTI_PERFORM; - } - else { - /* failure detected */ - Curl_posttransfer(data); - Curl_done(&easy->easy_conn, easy->result, FALSE); - disconnect_conn = TRUE; - } - } - break; - - case CURLM_STATE_DO_DONE: - /* Move ourselves from the send to recv pipeline */ - moveHandleFromSendToRecvPipeline(data, easy->easy_conn); - /* Check if we can move pending requests to send pipe */ - checkPendPipeline(easy->easy_conn); - multistate(easy, CURLM_STATE_WAITPERFORM); - result = CURLM_CALL_MULTI_PERFORM; - break; - - case CURLM_STATE_WAITPERFORM: - /* Wait for our turn to PERFORM */ - if(!easy->easy_conn->readchannel_inuse && - isHandleAtHead(data, - easy->easy_conn->recv_pipe)) { - /* Grab the channel */ - easy->easy_conn->readchannel_inuse = TRUE; - multistate(easy, CURLM_STATE_PERFORM); - result = CURLM_CALL_MULTI_PERFORM; - } -#ifdef DEBUGBUILD - else { - infof(data, "Conn %ld recv pipe %zu inuse %d athead %d\n", - easy->easy_conn->connectindex, - easy->easy_conn->recv_pipe->size, - easy->easy_conn->readchannel_inuse?1:0, - isHandleAtHead(data, - easy->easy_conn->recv_pipe)?1:0); - } -#endif - break; - - case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */ - /* if both rates are within spec, resume transfer */ - Curl_pgrsUpdate(easy->easy_conn); - if( ( (data->set.max_send_speed == 0) || - (data->progress.ulspeed < data->set.max_send_speed )) && - ( (data->set.max_recv_speed == 0) || - (data->progress.dlspeed < data->set.max_recv_speed) ) ) - multistate(easy, CURLM_STATE_PERFORM); - break; - - case CURLM_STATE_PERFORM: - /* check if over send speed */ - if( (data->set.max_send_speed > 0) && - (data->progress.ulspeed > data->set.max_send_speed) ) { - int buffersize; - - multistate(easy, CURLM_STATE_TOOFAST); - - /* calculate upload rate-limitation timeout. */ - buffersize = (int)(data->set.buffer_size ? - data->set.buffer_size : BUFSIZE); - timeout_ms = Curl_sleep_time(data->set.max_send_speed, - data->progress.ulspeed, buffersize); - Curl_expire(data, timeout_ms); - break; - } - - /* check if over recv speed */ - if( (data->set.max_recv_speed > 0) && - (data->progress.dlspeed > data->set.max_recv_speed) ) { - int buffersize; - - multistate(easy, CURLM_STATE_TOOFAST); - - /* Calculate download rate-limitation timeout. */ - buffersize = (int)(data->set.buffer_size ? - data->set.buffer_size : BUFSIZE); - timeout_ms = Curl_sleep_time(data->set.max_recv_speed, - data->progress.dlspeed, buffersize); - Curl_expire(data, timeout_ms); - break; - } - - /* read/write data if it is ready to do so */ - easy->result = Curl_readwrite(easy->easy_conn, &done); - - k = &data->req; - - if(!(k->keepon & KEEP_RECV)) { - /* We're done receiving */ - easy->easy_conn->readchannel_inuse = FALSE; - } - - if(!(k->keepon & KEEP_SEND)) { - /* We're done sending */ - easy->easy_conn->writechannel_inuse = FALSE; - } - - if(easy->result) { - /* The transfer phase returned error, we mark the connection to get - * closed to prevent being re-used. This is because we can't possibly - * know if the connection is in a good shape or not now. Unless it is - * a protocol which uses two "channels" like FTP, as then the error - * happened in the data connection. - */ - if(!(easy->easy_conn->handler->flags & PROTOPT_DUAL)) - easy->easy_conn->bits.close = TRUE; - - Curl_posttransfer(data); - Curl_done(&easy->easy_conn, easy->result, FALSE); - } - else if(TRUE == done) { - char *newurl = NULL; - bool retry = FALSE; - followtype follow=FOLLOW_NONE; - - easy->result = Curl_retry_request(easy->easy_conn, &newurl); - if(!easy->result) - retry = (bool)(newurl?TRUE:FALSE); - - /* call this even if the readwrite function returned error */ - Curl_posttransfer(data); - - /* we're no longer receiving */ - moveHandleFromRecvToDonePipeline(data, - easy->easy_conn); - - /* expire the new receiving pipeline head */ - if(easy->easy_conn->recv_pipe->head) - Curl_expire(easy->easy_conn->recv_pipe->head->ptr, 1); - - /* Check if we can move pending requests to send pipe */ - checkPendPipeline(easy->easy_conn); - - /* When we follow redirects or is set to retry the connection, we must - to go back to the CONNECT state */ - if(data->req.newurl || retry) { - if(!retry) { - /* if the URL is a follow-location and not just a retried request - then figure out the URL here */ - newurl = data->req.newurl; - data->req.newurl = NULL; - follow = FOLLOW_REDIR; - } - else - follow = FOLLOW_RETRY; - easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE); - if(easy->result == CURLE_OK) - easy->result = Curl_follow(data, newurl, follow); - if(CURLE_OK == easy->result) { - multistate(easy, CURLM_STATE_CONNECT); - result = CURLM_CALL_MULTI_PERFORM; - } - else if(newurl) - /* Since we "took it", we are in charge of freeing this on - failure */ - free(newurl); - } - else { - /* after the transfer is done, go DONE */ - - /* but first check to see if we got a location info even though we're - not following redirects */ - if (data->req.location) { - newurl = data->req.location; - data->req.location = NULL; - easy->result = Curl_follow(data, newurl, FOLLOW_FAKE); - if (easy->result) - free(newurl); - } - - multistate(easy, CURLM_STATE_DONE); - result = CURLM_CALL_MULTI_PERFORM; - } - } - - break; - - case CURLM_STATE_DONE: - - if(easy->easy_conn) { - /* Remove ourselves from the receive and done pipelines. Handle - should be on one of these lists, depending upon how we got here. */ - Curl_removeHandleFromPipeline(data, - easy->easy_conn->recv_pipe); - Curl_removeHandleFromPipeline(data, - easy->easy_conn->done_pipe); - /* Check if we can move pending requests to send pipe */ - checkPendPipeline(easy->easy_conn); - - if(easy->easy_conn->bits.stream_was_rewound) { - /* This request read past its response boundary so we quickly let - the other requests consume those bytes since there is no - guarantee that the socket will become active again */ - result = CURLM_CALL_MULTI_PERFORM; - } - - /* post-transfer command */ - easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE); - /* - * If there are other handles on the pipeline, Curl_done won't set - * easy_conn to NULL. In such a case, curl_multi_remove_handle() can - * access free'd data, if the connection is free'd and the handle - * removed before we perform the processing in CURLM_STATE_COMPLETED - */ - if (easy->easy_conn) - easy->easy_conn = NULL; - } - - if(data->set.wildcardmatch) { - if(data->wildcard.state != CURLWC_DONE) { - /* if a wildcard is set and we are not ending -> lets start again - with CURLM_STATE_INIT */ - result = CURLM_CALL_MULTI_PERFORM; - multistate(easy, CURLM_STATE_INIT); - break; - } - } - - /* after we have DONE what we're supposed to do, go COMPLETED, and - it doesn't matter what the Curl_done() returned! */ - multistate(easy, CURLM_STATE_COMPLETED); - - break; - - case CURLM_STATE_COMPLETED: - /* this is a completed transfer, it is likely to still be connected */ - - /* This node should be delinked from the list now and we should post - an information message that we are complete. */ - - /* Important: reset the conn pointer so that we don't point to memory - that could be freed anytime */ - easy->easy_conn = NULL; - - Curl_expire(data, 0); /* stop all timers */ - break; - - case CURLM_STATE_MSGSENT: - return CURLM_OK; /* do nothing */ - - default: - return CURLM_INTERNAL_ERROR; - } - - if(CURLM_STATE_COMPLETED > easy->state) { - if(CURLE_OK != easy->result) { - /* - * If an error was returned, and we aren't in completed state now, - * then we go to completed and consider this transfer aborted. - */ - - /* NOTE: no attempt to disconnect connections must be made - in the case blocks above - cleanup happens only here */ - - data->state.pipe_broke = FALSE; - - if(easy->easy_conn) { - /* if this has a connection, unsubscribe from the pipelines */ - easy->easy_conn->writechannel_inuse = FALSE; - easy->easy_conn->readchannel_inuse = FALSE; - Curl_removeHandleFromPipeline(data, - easy->easy_conn->send_pipe); - Curl_removeHandleFromPipeline(data, - easy->easy_conn->recv_pipe); - Curl_removeHandleFromPipeline(data, - easy->easy_conn->done_pipe); - /* Check if we can move pending requests to send pipe */ - checkPendPipeline(easy->easy_conn); - } - - if(disconnect_conn) { - /* disconnect properly */ - Curl_disconnect(easy->easy_conn, /* dead_connection */ FALSE); - - /* This is where we make sure that the easy_conn pointer is reset. - We don't have to do this in every case block above where a - failure is detected */ - easy->easy_conn = NULL; - } - - multistate(easy, CURLM_STATE_COMPLETED); - } - /* if there's still a connection to use, call the progress function */ - else if(easy->easy_conn && Curl_pgrsUpdate(easy->easy_conn)) - easy->result = CURLE_ABORTED_BY_CALLBACK; - } - } while(0); - - if(CURLM_STATE_COMPLETED == easy->state) { - if(data->dns.hostcachetype == HCACHE_MULTI) { - /* clear out the usage of the shared DNS cache */ - data->dns.hostcache = NULL; - data->dns.hostcachetype = HCACHE_NONE; - } - - /* now fill in the Curl_message with this info */ - msg = &easy->msg; - - msg->extmsg.msg = CURLMSG_DONE; - msg->extmsg.easy_handle = data; - msg->extmsg.data.result = easy->result; - - result = multi_addmsg(multi, msg); - - multistate(easy, CURLM_STATE_MSGSENT); - } - - return result; -} - - -CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) -{ - struct Curl_multi *multi=(struct Curl_multi *)multi_handle; - struct Curl_one_easy *easy; - CURLMcode returncode=CURLM_OK; - struct Curl_tree *t; - struct timeval now = Curl_tvnow(); - - if(!GOOD_MULTI_HANDLE(multi)) - return CURLM_BAD_HANDLE; - - easy=multi->easy.next; - while(easy != &multi->easy) { - CURLMcode result; - struct WildcardData *wc = &easy->easy_handle->wildcard; - - if(easy->easy_handle->set.wildcardmatch) { - if(!wc->filelist) { - CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */ - if(ret) - return CURLM_OUT_OF_MEMORY; - } - } - - do - result = multi_runsingle(multi, now, easy); - while (CURLM_CALL_MULTI_PERFORM == result); - - if(easy->easy_handle->set.wildcardmatch) { - /* destruct wildcard structures if it is needed */ - if(wc->state == CURLWC_DONE || result) - Curl_wildcard_dtor(wc); - } - - if(result) - returncode = result; - - easy = easy->next; /* operate on next handle */ - } - - /* - * Simply remove all expired timers from the splay since handles are dealt - * with unconditionally by this function and curl_multi_timeout() requires - * that already passed/handled expire times are removed from the splay. - * - * It is important that the 'now' value is set at the entry of this function - * and not for the current time as it may have ticked a little while since - * then and then we risk this loop to remove timers that actually have not - * been handled! - */ - do { - multi->timetree = Curl_splaygetbest(now, multi->timetree, &t); - if(t) - /* the removed may have another timeout in queue */ - (void)add_next_timeout(now, multi, t->payload); - - } while(t); - - *running_handles = multi->num_alive; - - if( CURLM_OK >= returncode ) - update_timer(multi); - - return returncode; -} - -CURLMcode curl_multi_cleanup(CURLM *multi_handle) -{ - struct Curl_multi *multi=(struct Curl_multi *)multi_handle; - struct Curl_one_easy *easy; - struct Curl_one_easy *nexteasy; - int i; - struct closure *cl; - struct closure *n; - - if(GOOD_MULTI_HANDLE(multi)) { - multi->type = 0; /* not good anymore */ - Curl_hash_destroy(multi->hostcache); - Curl_hash_destroy(multi->sockhash); - multi->hostcache = NULL; - multi->sockhash = NULL; - - /* go over all connections that have close actions */ - for(i=0; i< multi->connc->num; i++) { - if(multi->connc->connects[i] && - multi->connc->connects[i]->handler->flags & PROTOPT_CLOSEACTION) { - Curl_disconnect(multi->connc->connects[i], FALSE); - multi->connc->connects[i] = NULL; - } - } - /* now walk through the list of handles we kept around only to be - able to close connections "properly" */ - cl = multi->closure; - while(cl) { - cl->easy_handle->state.shared_conn = NULL; /* no more shared */ - if(cl->easy_handle->state.closed) - /* close handle only if curl_easy_cleanup() already has been called - for this easy handle */ - Curl_close(cl->easy_handle); - n = cl->next; - free(cl); - cl= n; - } - - Curl_rm_connc(multi->connc); - - /* remove the pending list of messages */ - Curl_llist_destroy(multi->msglist, NULL); - - /* remove all easy handles */ - easy = multi->easy.next; - while(easy != &multi->easy) { - nexteasy=easy->next; - if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) { - /* clear out the usage of the shared DNS cache */ - easy->easy_handle->dns.hostcache = NULL; - easy->easy_handle->dns.hostcachetype = HCACHE_NONE; - } - - /* Clear the pointer to the connection cache */ - easy->easy_handle->state.connc = NULL; - - Curl_easy_addmulti(easy->easy_handle, NULL); /* clear the association */ - - free(easy); - easy = nexteasy; - } - - free(multi); - - return CURLM_OK; - } - else - return CURLM_BAD_HANDLE; -} - -/* - * curl_multi_info_read() - * - * This function is the primary way for a multi/multi_socket application to - * figure out if a transfer has ended. We MUST make this function as fast as - * possible as it will be polled frequently and we MUST NOT scan any lists in - * here to figure out things. We must scale fine to thousands of handles and - * beyond. The current design is fully O(1). - */ - -CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue) -{ - struct Curl_multi *multi=(struct Curl_multi *)multi_handle; - struct Curl_message *msg; - - *msgs_in_queue = 0; /* default to none */ - - if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) { - /* there is one or more messages in the list */ - struct curl_llist_element *e; - - /* extract the head of the list to return */ - e = multi->msglist->head; - - msg = e->ptr; - - /* remove the extracted entry */ - Curl_llist_remove(multi->msglist, e, NULL); - - *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist)); - - return &msg->extmsg; - } - else - return NULL; -} - -/* - * singlesocket() checks what sockets we deal with and their "action state" - * and if we have a different state in any of those sockets from last time we - * call the callback accordingly. - */ -static void singlesocket(struct Curl_multi *multi, - struct Curl_one_easy *easy) -{ - curl_socket_t socks[MAX_SOCKSPEREASYHANDLE]; - int i; - struct Curl_sh_entry *entry; - curl_socket_t s; - int num; - unsigned int curraction; - struct Curl_one_easy *easy_by_hash; - bool remove_sock_from_hash; - - for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) - socks[i] = CURL_SOCKET_BAD; - - /* Fill in the 'current' struct with the state as it is now: what sockets to - supervise and for what actions */ - curraction = multi_getsock(easy, socks, MAX_SOCKSPEREASYHANDLE); - - /* We have 0 .. N sockets already and we get to know about the 0 .. M - sockets we should have from now on. Detect the differences, remove no - longer supervised ones and add new ones */ - - /* walk over the sockets we got right now */ - for(i=0; (i< MAX_SOCKSPEREASYHANDLE) && - (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))); - i++) { - int action = CURL_POLL_NONE; - - s = socks[i]; - - /* get it from the hash */ - entry = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); - - if(curraction & GETSOCK_READSOCK(i)) - action |= CURL_POLL_IN; - if(curraction & GETSOCK_WRITESOCK(i)) - action |= CURL_POLL_OUT; - - if(entry) { - /* yeps, already present so check if it has the same action set */ - if(entry->action == action) - /* same, continue */ - continue; - } - else { - /* this is a socket we didn't have before, add it! */ - entry = sh_addentry(multi->sockhash, s, easy->easy_handle); - if(!entry) - /* fatal */ - return; - } - - /* we know (entry != NULL) at this point, see the logic above */ - multi->socket_cb(easy->easy_handle, - s, - action, - multi->socket_userp, - entry->socketp); - - entry->action = action; /* store the current action state */ - } - - num = i; /* number of sockets */ - - /* when we've walked over all the sockets we should have right now, we must - make sure to detect sockets that are removed */ - for(i=0; i< easy->numsocks; i++) { - int j; - s = easy->sockets[i]; - for(j=0; jsockhash, (char *)&s, sizeof(s)); - if(entry) { - /* check if the socket to be removed serves a connection which has - other easy-s in a pipeline. In this case the socket should not be - removed. */ - struct connectdata *easy_conn; - - easy_by_hash = entry->easy->multi_pos; - easy_conn = easy_by_hash->easy_conn; - if(easy_conn) { - if (easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) { - /* the handle should not be removed from the pipe yet */ - remove_sock_from_hash = FALSE; - - /* Update the sockhash entry to instead point to the next in line - for the recv_pipe, or the first (in case this particular easy - isn't already) */ - if (entry->easy == easy->easy_handle) { - if (isHandleAtHead(easy->easy_handle, easy_conn->recv_pipe)) - entry->easy = easy_conn->recv_pipe->head->next->ptr; - else - entry->easy = easy_conn->recv_pipe->head->ptr; - } - } - if (easy_conn->send_pipe && easy_conn->send_pipe->size > 1) { - /* the handle should not be removed from the pipe yet */ - remove_sock_from_hash = FALSE; - - /* Update the sockhash entry to instead point to the next in line - for the send_pipe, or the first (in case this particular easy - isn't already) */ - if (entry->easy == easy->easy_handle) { - if (isHandleAtHead(easy->easy_handle, easy_conn->send_pipe)) - entry->easy = easy_conn->send_pipe->head->next->ptr; - else - entry->easy = easy_conn->send_pipe->head->ptr; - } - } - /* Don't worry about overwriting recv_pipe head with send_pipe_head, - when action will be asked on the socket (see multi_socket()), the - head of the correct pipe will be taken according to the - action. */ - } - } - else - /* just a precaution, this socket really SHOULD be in the hash already - but in case it isn't, we don't have to tell the app to remove it - either since it never got to know about it */ - remove_sock_from_hash = FALSE; - - if (remove_sock_from_hash) { - multi->socket_cb(easy->easy_handle, - s, - CURL_POLL_REMOVE, - multi->socket_userp, - entry ? entry->socketp : NULL); - sh_delentry(multi->sockhash, s); - } - - } - } - - memcpy(easy->sockets, socks, num*sizeof(curl_socket_t)); - easy->numsocks = num; -} - -/* - * add_next_timeout() - * - * Each SessionHandle has a list of timeouts. The add_next_timeout() is called - * when it has just been removed from the splay tree because the timeout has - * expired. This function is then to advance in the list to pick the next - * timeout to use (skip the already expired ones) and add this node back to - * the splay tree again. - * - * The splay tree only has each sessionhandle as a single node and the nearest - * timeout is used to sort it on. - */ -static CURLMcode add_next_timeout(struct timeval now, - struct Curl_multi *multi, - struct SessionHandle *d) -{ - struct timeval *tv = &d->state.expiretime; - struct curl_llist *list = d->state.timeoutlist; - struct curl_llist_element *e; - - /* move over the timeout list for this specific handle and remove all - timeouts that are now passed tense and store the next pending - timeout in *tv */ - for(e = list->head; e; ) { - struct curl_llist_element *n = e->next; - long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now); - if(diff <= 0) - /* remove outdated entry */ - Curl_llist_remove(list, e, NULL); - else - /* the list is sorted so get out on the first mismatch */ - break; - e = n; - } - if(!list->size) { - /* clear the expire times within the handles that we remove from the - splay tree */ - tv->tv_sec = 0; - tv->tv_usec = 0; - } - else { - e = list->head; - /* copy the first entry to 'tv' */ - memcpy(tv, e->ptr, sizeof(*tv)); - - /* remove first entry from list */ - Curl_llist_remove(list, e, NULL); - - /* insert this node again into the splay */ - multi->timetree = Curl_splayinsert(*tv, multi->timetree, - &d->state.timenode); - } - return CURLM_OK; -} - - -static CURLMcode multi_socket(struct Curl_multi *multi, - bool checkall, - curl_socket_t s, - int ev_bitmask, - int *running_handles) -{ - CURLMcode result = CURLM_OK; - struct SessionHandle *data = NULL; - struct Curl_tree *t; - struct timeval now = Curl_tvnow(); - - if(checkall) { - struct Curl_one_easy *easyp; - /* *perform() deals with running_handles on its own */ - result = curl_multi_perform(multi, running_handles); - - /* walk through each easy handle and do the socket state change magic - and callbacks */ - easyp=multi->easy.next; - while(easyp != &multi->easy) { - singlesocket(multi, easyp); - easyp = easyp->next; - } - - /* or should we fall-through and do the timer-based stuff? */ - return result; - } - else if(s != CURL_SOCKET_TIMEOUT) { - - struct Curl_sh_entry *entry = - Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); - - if(!entry) - /* Unmatched socket, we can't act on it but we ignore this fact. In - real-world tests it has been proved that libevent can in fact give - the application actions even though the socket was just previously - asked to get removed, so thus we better survive stray socket actions - and just move on. */ - ; - else { - data = entry->easy; - - if(data->magic != CURLEASY_MAGIC_NUMBER) - /* bad bad bad bad bad bad bad */ - return CURLM_INTERNAL_ERROR; - - /* If the pipeline is enabled, take the handle which is in the head of - the pipeline. If we should write into the socket, take the send_pipe - head. If we should read from the socket, take the recv_pipe head. */ - if(data->set.one_easy->easy_conn) { - if ((ev_bitmask & CURL_POLL_OUT) && - data->set.one_easy->easy_conn->send_pipe && - data->set.one_easy->easy_conn->send_pipe->head) - data = data->set.one_easy->easy_conn->send_pipe->head->ptr; - else if ((ev_bitmask & CURL_POLL_IN) && - data->set.one_easy->easy_conn->recv_pipe && - data->set.one_easy->easy_conn->recv_pipe->head) - data = data->set.one_easy->easy_conn->recv_pipe->head->ptr; - } - - if(data->set.one_easy->easy_conn && - !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK)) - /* set socket event bitmask if they're not locked */ - data->set.one_easy->easy_conn->cselect_bits = ev_bitmask; - - do - result = multi_runsingle(multi, now, data->set.one_easy); - while (CURLM_CALL_MULTI_PERFORM == result); - - if(data->set.one_easy->easy_conn && - !(data->set.one_easy->easy_conn->handler->flags & PROTOPT_DIRLOCK)) - /* clear the bitmask only if not locked */ - data->set.one_easy->easy_conn->cselect_bits = 0; - - if(CURLM_OK >= result) - /* get the socket(s) and check if the state has been changed since - last */ - singlesocket(multi, data->set.one_easy); - - /* Now we fall-through and do the timer-based stuff, since we don't want - to force the user to have to deal with timeouts as long as at least - one connection in fact has traffic. */ - - data = NULL; /* set data to NULL again to avoid calling - multi_runsingle() in case there's no need to */ - } - } - - now.tv_usec += 40000; /* compensate for bad precision timers that might've - triggered too early */ - if(now.tv_usec >= 1000000) { - now.tv_sec++; - now.tv_usec -= 1000000; - } - - /* - * The loop following here will go on as long as there are expire-times left - * to process in the splay and 'data' will be re-assigned for every expired - * handle we deal with. - */ - do { - /* the first loop lap 'data' can be NULL */ - if(data) { - do - result = multi_runsingle(multi, now, data->set.one_easy); - while (CURLM_CALL_MULTI_PERFORM == result); - - if(CURLM_OK >= result) - /* get the socket(s) and check if the state has been changed since - last */ - singlesocket(multi, data->set.one_easy); - } - - /* Check if there's one (more) expired timer to deal with! This function - extracts a matching node if there is one */ - - multi->timetree = Curl_splaygetbest(now, multi->timetree, &t); - if(t) { - data = t->payload; /* assign this for next loop */ - (void)add_next_timeout(now, multi, t->payload); - } - - } while(t); - - *running_handles = multi->num_alive; - return result; -} - -#undef curl_multi_setopt -CURLMcode curl_multi_setopt(CURLM *multi_handle, - CURLMoption option, ...) -{ - struct Curl_multi *multi=(struct Curl_multi *)multi_handle; - CURLMcode res = CURLM_OK; - va_list param; - - if(!GOOD_MULTI_HANDLE(multi)) - return CURLM_BAD_HANDLE; - - va_start(param, option); - - switch(option) { - case CURLMOPT_SOCKETFUNCTION: - multi->socket_cb = va_arg(param, curl_socket_callback); - break; - case CURLMOPT_SOCKETDATA: - multi->socket_userp = va_arg(param, void *); - break; - case CURLMOPT_PIPELINING: - multi->pipelining_enabled = (bool)(0 != va_arg(param, long)); - break; - case CURLMOPT_TIMERFUNCTION: - multi->timer_cb = va_arg(param, curl_multi_timer_callback); - break; - case CURLMOPT_TIMERDATA: - multi->timer_userp = va_arg(param, void *); - break; - case CURLMOPT_MAXCONNECTS: - multi->maxconnects = va_arg(param, long); - break; - default: - res = CURLM_UNKNOWN_OPTION; - break; - } - va_end(param); - return res; -} - -/* we define curl_multi_socket() in the public multi.h header */ -#undef curl_multi_socket - -CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, - int *running_handles) -{ - CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s, - 0, running_handles); - if(CURLM_OK >= result) - update_timer((struct Curl_multi *)multi_handle); - return result; -} - -CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s, - int ev_bitmask, int *running_handles) -{ - CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s, - ev_bitmask, running_handles); - if(CURLM_OK >= result) - update_timer((struct Curl_multi *)multi_handle); - return result; -} - -CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles) - -{ - CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, - TRUE, CURL_SOCKET_BAD, 0, running_handles); - if(CURLM_OK >= result) - update_timer((struct Curl_multi *)multi_handle); - return result; -} - -static CURLMcode multi_timeout(struct Curl_multi *multi, - long *timeout_ms) -{ - static struct timeval tv_zero = {0,0}; - - if(multi->timetree) { - /* we have a tree of expire times */ - struct timeval now = Curl_tvnow(); - - /* splay the lowest to the bottom */ - multi->timetree = Curl_splay(tv_zero, multi->timetree); - - if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) { - /* some time left before expiration */ - *timeout_ms = curlx_tvdiff(multi->timetree->key, now); - if(!*timeout_ms) - /* - * Since we only provide millisecond resolution on the returned value - * and the diff might be less than one millisecond here, we don't - * return zero as that may cause short bursts of busyloops on fast - * processors while the diff is still present but less than one - * millisecond! instead we return 1 until the time is ripe. - */ - *timeout_ms=1; - } - else - /* 0 means immediately */ - *timeout_ms = 0; - } - else - *timeout_ms = -1; - - return CURLM_OK; -} - -CURLMcode curl_multi_timeout(CURLM *multi_handle, - long *timeout_ms) -{ - struct Curl_multi *multi=(struct Curl_multi *)multi_handle; - - /* First, make some basic checks that the CURLM handle is a good handle */ - if(!GOOD_MULTI_HANDLE(multi)) - return CURLM_BAD_HANDLE; - - return multi_timeout(multi, timeout_ms); -} - -/* - * Tell the application it should update its timers, if it subscribes to the - * update timer callback. - */ -static int update_timer(struct Curl_multi *multi) -{ - long timeout_ms; - - if(!multi->timer_cb) - return 0; - if(multi_timeout(multi, &timeout_ms)) { - return -1; - } - if( timeout_ms < 0 ) { - static const struct timeval none={0,0}; - if(Curl_splaycomparekeys(none, multi->timer_lastcall)) { - multi->timer_lastcall = none; - /* there's no timeout now but there was one previously, tell the app to - disable it */ - return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp); - } - return 0; - } - - /* When multi_timeout() is done, multi->timetree points to the node with the - * timeout we got the (relative) time-out time for. We can thus easily check - * if this is the same (fixed) time as we got in a previous call and then - * avoid calling the callback again. */ - if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0) - return 0; - - multi->timer_lastcall = multi->timetree->key; - - return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp); -} - -static CURLcode addHandleToSendOrPendPipeline(struct SessionHandle *handle, - struct connectdata *conn) -{ - size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size; - struct curl_llist_element *sendhead = conn->send_pipe->head; - struct curl_llist *pipeline; - CURLcode rc; - - if(!Curl_isPipeliningEnabled(handle) || - pipeLen == 0) - pipeline = conn->send_pipe; - else { - if(conn->server_supports_pipelining && - pipeLen < MAX_PIPELINE_LENGTH) - pipeline = conn->send_pipe; - else - pipeline = conn->pend_pipe; - } - - rc = Curl_addHandleToPipeline(handle, pipeline); - - if (pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) { - /* this is a new one as head, expire it */ - conn->writechannel_inuse = FALSE; /* not in use yet */ -#ifdef DEBUGBUILD - infof(conn->data, "%p is at send pipe head!\n", - conn->send_pipe->head->ptr); -#endif - Curl_expire(conn->send_pipe->head->ptr, 1); - } - - return rc; -} - -static int checkPendPipeline(struct connectdata *conn) -{ - int result = 0; - struct curl_llist_element *sendhead = conn->send_pipe->head; - - size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size; - if (conn->server_supports_pipelining || pipeLen == 0) { - struct curl_llist_element *curr = conn->pend_pipe->head; - const size_t maxPipeLen = - conn->server_supports_pipelining ? MAX_PIPELINE_LENGTH : 1; - - while(pipeLen < maxPipeLen && curr) { - Curl_llist_move(conn->pend_pipe, curr, - conn->send_pipe, conn->send_pipe->tail); - Curl_pgrsTime(curr->ptr, TIMER_PRETRANSFER); - ++result; /* count how many handles we moved */ - curr = conn->pend_pipe->head; - ++pipeLen; - } - } - - if (result) { - conn->now = Curl_tvnow(); - /* something moved, check for a new send pipeline leader */ - if(sendhead != conn->send_pipe->head) { - /* this is a new one as head, expire it */ - conn->writechannel_inuse = FALSE; /* not in use yet */ -#ifdef DEBUGBUILD - infof(conn->data, "%p is at send pipe head!\n", - conn->send_pipe->head->ptr); -#endif - Curl_expire(conn->send_pipe->head->ptr, 1); - } - } - - return result; -} - -/* Move this transfer from the sending list to the receiving list. - - Pay special attention to the new sending list "leader" as it needs to get - checked to update what sockets it acts on. - -*/ -static void moveHandleFromSendToRecvPipeline(struct SessionHandle *handle, - struct connectdata *conn) -{ - struct curl_llist_element *curr; - - curr = conn->send_pipe->head; - while(curr) { - if(curr->ptr == handle) { - Curl_llist_move(conn->send_pipe, curr, - conn->recv_pipe, conn->recv_pipe->tail); - - if(conn->send_pipe->head) { - /* Since there's a new easy handle at the start of the send pipeline, - set its timeout value to 1ms to make it trigger instantly */ - conn->writechannel_inuse = FALSE; /* not used now */ -#ifdef DEBUGBUILD - infof(conn->data, "%p is at send pipe head B!\n", - conn->send_pipe->head->ptr); -#endif - Curl_expire(conn->send_pipe->head->ptr, 1); - } - - /* The receiver's list is not really interesting here since either this - handle is now first in the list and we'll deal with it soon, or - another handle is already first and thus is already taken care of */ - - break; /* we're done! */ - } - curr = curr->next; - } -} - -static void moveHandleFromRecvToDonePipeline(struct SessionHandle *handle, - struct connectdata *conn) -{ - struct curl_llist_element *curr; - - curr = conn->recv_pipe->head; - while(curr) { - if(curr->ptr == handle) { - Curl_llist_move(conn->recv_pipe, curr, - conn->done_pipe, conn->done_pipe->tail); - break; - } - curr = curr->next; - } -} -static bool isHandleAtHead(struct SessionHandle *handle, - struct curl_llist *pipeline) -{ - struct curl_llist_element *curr = pipeline->head; - if(curr) - return (bool)(curr->ptr == handle); - - return FALSE; -} - -/* - * multi_freetimeout() - * - * Callback used by the llist system when a single timeout list entry is - * destroyed. - */ -static void multi_freetimeout(void *user, void *entryptr) -{ - (void)user; - - /* the entry was plain malloc()'ed */ - free(entryptr); -} - -/* - * multi_addtimeout() - * - * Add a timestamp to the list of timeouts. Keep the list sorted so that head - * of list is always the timeout nearest in time. - * - */ -static CURLMcode -multi_addtimeout(struct curl_llist *timeoutlist, - struct timeval *stamp) -{ - struct curl_llist_element *e; - struct timeval *timedup; - struct curl_llist_element *prev = NULL; - - timedup = malloc(sizeof(*timedup)); - if(!timedup) - return CURLM_OUT_OF_MEMORY; - - /* copy the timestamp */ - memcpy(timedup, stamp, sizeof(*timedup)); - - if(Curl_llist_count(timeoutlist)) { - /* find the correct spot in the list */ - for(e = timeoutlist->head; e; e = e->next) { - struct timeval *checktime = e->ptr; - long diff = curlx_tvdiff(*checktime, *timedup); - if(diff > 0) - break; - prev = e; - } - - } - /* else - this is the first timeout on the list */ - - if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) { - free(timedup); - return CURLM_OUT_OF_MEMORY; - } - - return CURLM_OK; -} - -/* - * Curl_expire() - * - * given a number of milliseconds from now to use to set the 'act before - * this'-time for the transfer, to be extracted by curl_multi_timeout() - * - * Note that the timeout will be added to a queue of timeouts if it defines a - * moment in time that is later than the current head of queue. - * - * Pass zero to clear all timeout values for this handle. -*/ -void Curl_expire(struct SessionHandle *data, long milli) -{ - struct Curl_multi *multi = data->multi; - struct timeval *nowp = &data->state.expiretime; - int rc; - - /* this is only interesting for multi-interface using libcurl, and only - while there is still a multi interface struct remaining! */ - if(!multi) - return; - - if(!milli) { - /* No timeout, clear the time data. */ - if(nowp->tv_sec || nowp->tv_usec) { - /* Since this is an cleared time, we must remove the previous entry from - the splay tree */ - struct curl_llist *list = data->state.timeoutlist; - - rc = Curl_splayremovebyaddr(multi->timetree, - &data->state.timenode, - &multi->timetree); - if(rc) - infof(data, "Internal error clearing splay node = %d\n", rc); - - /* flush the timeout list too */ - while(list->size > 0) - Curl_llist_remove(list, list->tail, NULL); - -#ifdef DEBUGBUILD - infof(data, "Expire cleared\n"); -#endif - nowp->tv_sec = 0; - nowp->tv_usec = 0; - } - } - else { - struct timeval set; - - set = Curl_tvnow(); - set.tv_sec += milli/1000; - set.tv_usec += (milli%1000)*1000; - - if(set.tv_usec >= 1000000) { - set.tv_sec++; - set.tv_usec -= 1000000; - } - - if(nowp->tv_sec || nowp->tv_usec) { - /* This means that the struct is added as a node in the splay tree. - Compare if the new time is earlier, and only remove-old/add-new if it - is. */ - long diff = curlx_tvdiff(set, *nowp); - if(diff > 0) { - /* the new expire time was later so just add it to the queue - and get out */ - multi_addtimeout(data->state.timeoutlist, &set); - return; - } - - /* the new time is newer than the presently set one, so add the current - to the queue and update the head */ - multi_addtimeout(data->state.timeoutlist, nowp); - - /* Since this is an updated time, we must remove the previous entry from - the splay tree first and then re-add the new value */ - rc = Curl_splayremovebyaddr(multi->timetree, - &data->state.timenode, - &multi->timetree); - if(rc) - infof(data, "Internal error removing splay node = %d\n", rc); - } - - *nowp = set; - data->state.timenode.payload = data; - multi->timetree = Curl_splayinsert(*nowp, - multi->timetree, - &data->state.timenode); - } -#if 0 - Curl_splayprint(multi->timetree, 0, TRUE); -#endif -} - -CURLMcode curl_multi_assign(CURLM *multi_handle, - curl_socket_t s, void *hashp) -{ - struct Curl_sh_entry *there = NULL; - struct Curl_multi *multi = (struct Curl_multi *)multi_handle; - - if(s != CURL_SOCKET_BAD) - there = Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(curl_socket_t)); - - if(!there) - return CURLM_BAD_SOCKET; - - there->socketp = hashp; - - return CURLM_OK; -} - -static void multi_connc_remove_handle(struct Curl_multi *multi, - struct SessionHandle *data) -{ - /* a connection in the connection cache pointing to the given 'data' ? */ - int i; - - for(i=0; i< multi->connc->num; i++) { - struct connectdata * conn = multi->connc->connects[i]; - - if(conn && conn->data == data) { - /* If this easy_handle was the last one in charge for one or more - connections in the shared connection cache, we might need to keep - this handle around until either A) the connection is closed and - killed properly, or B) another easy_handle uses the connection. - - The reason why we need to have a easy_handle associated with a live - connection is simply that some connections will need a handle to get - closed down properly. Currently, the only connections that need to - keep a easy_handle handle around are using FTP(S). Such connections - have the PROT_CLOSEACTION bit set. - - Thus, we need to check for all connections in the shared cache that - points to this handle and are using PROT_CLOSEACTION. If there's any, - we need to add this handle to the list of "easy handles kept around - for nice connection closures". - */ - - if(conn->handler->flags & PROTOPT_CLOSEACTION) { - /* this handle is still being used by a shared connection and - thus we leave it around for now */ - if(add_closure(multi, data) == CURLM_OK) - data->state.shared_conn = multi; - else { - /* out of memory - so much for graceful shutdown */ - Curl_disconnect(conn, /* dead_connection */ FALSE); - multi->connc->connects[i] = NULL; - } - } - else - /* disconect the easy handle from the connection since the connection - will now remain but this easy handle is going */ - conn->data = NULL; - } - } -} - -/* Add the given data pointer to the list of 'closure handles' that are kept - around only to be able to close some connections nicely - just make sure - that this handle isn't already added, like for the cases when an easy - handle is removed, added and removed again... */ -static CURLMcode add_closure(struct Curl_multi *multi, - struct SessionHandle *data) -{ - struct closure *cl = multi->closure; - struct closure *p = NULL; - bool add = TRUE; - - /* Before adding, scan through all the other currently kept handles and see - if there are any connections still referring to them and kill them if - not. */ - while(cl) { - struct closure *n; - bool inuse = FALSE; - int i; - - for(i=0; i< multi->connc->num; i++) { - if(multi->connc->connects[i] && - (multi->connc->connects[i]->data == cl->easy_handle)) { - inuse = TRUE; - break; - } - } - - n = cl->next; - - if(!inuse) { - /* cl->easy_handle is now killable */ - - /* unmark it as not having a connection around that uses it anymore */ - cl->easy_handle->state.shared_conn= NULL; - - if(cl->easy_handle->state.closed) { - infof(data, "Delayed kill of easy handle %p\n", cl->easy_handle); - /* close handle only if curl_easy_cleanup() already has been called - for this easy handle */ - Curl_close(cl->easy_handle); - } - if(p) - p->next = n; - else - multi->closure = n; - free(cl); - } else { - if(cl->easy_handle == data) - add = FALSE; - - p = cl; - } - - cl = n; - } - - if (add) { - cl = calloc(1, sizeof(struct closure)); - if(!cl) - return CURLM_OUT_OF_MEMORY; - - cl->easy_handle = data; - cl->next = multi->closure; - multi->closure = cl; - } - - return CURLM_OK; -} - -#ifdef DEBUGBUILD -void Curl_multi_dump(const struct Curl_multi *multi_handle) -{ - struct Curl_multi *multi=(struct Curl_multi *)multi_handle; - struct Curl_one_easy *easy; - int i; - fprintf(stderr, "* Multi status: %d handles, %d alive\n", - multi->num_easy, multi->num_alive); - for(easy=multi->easy.next; easy != &multi->easy; easy = easy->next) { - if(easy->state < CURLM_STATE_COMPLETED) { - /* only display handles that are not completed */ - fprintf(stderr, "handle %p, state %s, %d sockets\n", - (void *)easy->easy_handle, - statename[easy->state], easy->numsocks); - for(i=0; i < easy->numsocks; i++) { - curl_socket_t s = easy->sockets[i]; - struct Curl_sh_entry *entry = - Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s)); - - fprintf(stderr, "%d ", (int)s); - if(!entry) { - fprintf(stderr, "INTERNAL CONFUSION\n"); - continue; - } - fprintf(stderr, "[%s %s] ", - entry->action&CURL_POLL_IN?"RECVING":"", - entry->action&CURL_POLL_OUT?"SENDING":""); - } - if(easy->numsocks) - fprintf(stderr, "\n"); - } - } -} -#endif diff --git a/third_party/curl/lib/multiif.h b/third_party/curl/lib/multiif.h deleted file mode 100644 index 76918181e..000000000 --- a/third_party/curl/lib/multiif.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __MULTIIF_H -#define __MULTIIF_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Prototypes for library-wide functions provided by multi.c - */ -void Curl_expire(struct SessionHandle *data, long milli); - -bool Curl_multi_canPipeline(const struct Curl_multi* multi); -void Curl_multi_handlePipeBreak(struct SessionHandle *data); - -/* the write bits start at bit 16 for the *getsock() bitmap */ -#define GETSOCK_WRITEBITSTART 16 - -#define GETSOCK_BLANK 0 /* no bits set */ - -/* set the bit for the given sock number to make the bitmap for writable */ -#define GETSOCK_WRITESOCK(x) (1 << (GETSOCK_WRITEBITSTART + (x))) - -/* set the bit for the given sock number to make the bitmap for readable */ -#define GETSOCK_READSOCK(x) (1 << (x)) - -#ifdef DEBUGBUILD - /* - * Curl_multi_dump is not a stable public function, this is only meant to - * allow easier tracking of the internal handle's state and what sockets - * they use. Only for research and development DEBUGBUILD enabled builds. - */ -void Curl_multi_dump(const struct Curl_multi *multi_handle); -#endif - -#endif /* __MULTIIF_H */ diff --git a/third_party/curl/lib/netrc.c b/third_party/curl/lib/netrc.c deleted file mode 100644 index efb4076bb..000000000 --- a/third_party/curl/lib/netrc.c +++ /dev/null @@ -1,197 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_PWD_H -#include -#endif -#ifdef __VMS -#include -#endif - -#include -#include "netrc.h" - -#include "strequal.h" -#include "strtok.h" -#include "curl_memory.h" -#include "rawstr.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -/* Get user and password from .netrc when given a machine name */ - -enum host_lookup_state { - NOTHING, - HOSTFOUND, /* the 'machine' keyword was found */ - HOSTCOMPLETE, /* the machine name following the keyword was found too */ - HOSTVALID, /* this is "our" machine! */ - - HOSTEND /* LAST enum */ -}; - -int Curl_parsenetrc(const char *host, - char *login, - char *password, - char *netrcfile) -{ - FILE *file; - int retcode=1; - int specific_login = (login[0] != 0); - char *home = NULL; - bool home_alloc = FALSE; - bool netrc_alloc = FALSE; - enum host_lookup_state state=NOTHING; - - char state_login=0; /* Found a login keyword */ - char state_password=0; /* Found a password keyword */ - int state_our_login=FALSE; /* With specific_login, found *our* login name */ - -#define NETRC DOT_CHAR "netrc" - - if(!netrcfile) { - home = curl_getenv("HOME"); /* portable environment reader */ - if(home) { - home_alloc = TRUE; -#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID) - } - else { - struct passwd *pw; - pw= getpwuid(geteuid()); - if(pw) { -#ifdef __VMS - home = decc_translate_vms(pw->pw_dir); -#else - home = pw->pw_dir; -#endif - } -#endif - } - - if(!home) - return -1; - - netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC); - if(!netrcfile) { - if(home_alloc) - free(home); - return -1; - } - netrc_alloc = TRUE; - } - - file = fopen(netrcfile, "r"); - if(file) { - char *tok; - char *tok_buf; - bool done=FALSE; - char netrcbuffer[256]; - int netrcbuffsize = (int)sizeof(netrcbuffer); - - while(!done && fgets(netrcbuffer, netrcbuffsize, file)) { - tok=strtok_r(netrcbuffer, " \t\n", &tok_buf); - while(!done && tok) { - - if(login[0] && password[0]) { - done=TRUE; - break; - } - - switch(state) { - case NOTHING: - if(Curl_raw_equal("machine", tok)) { - /* the next tok is the machine name, this is in itself the - delimiter that starts the stuff entered for this machine, - after this we need to search for 'login' and - 'password'. */ - state=HOSTFOUND; - } - break; - case HOSTFOUND: - if(Curl_raw_equal(host, tok)) { - /* and yes, this is our host! */ - state=HOSTVALID; - retcode=0; /* we did find our host */ - } - else - /* not our host */ - state=NOTHING; - break; - case HOSTVALID: - /* we are now parsing sub-keywords concerning "our" host */ - if(state_login) { - if(specific_login) { - state_our_login = Curl_raw_equal(login, tok); - } - else { - strncpy(login, tok, LOGINSIZE-1); - } - state_login=0; - } - else if(state_password) { - if(state_our_login || !specific_login) { - strncpy(password, tok, PASSWORDSIZE-1); - } - state_password=0; - } - else if(Curl_raw_equal("login", tok)) - state_login=1; - else if(Curl_raw_equal("password", tok)) - state_password=1; - else if(Curl_raw_equal("machine", tok)) { - /* ok, there's machine here go => */ - state = HOSTFOUND; - state_our_login = FALSE; - } - break; - case HOSTCOMPLETE: - case HOSTEND: - /* Should not be reached. */ - DEBUGASSERT(0); - } /* switch (state) */ - - tok = strtok_r(NULL, " \t\n", &tok_buf); - } /* while(tok) */ - } /* while fgets() */ - - fclose(file); - } - - if(home_alloc) - free(home); - if(netrc_alloc) - free(netrcfile); - - return retcode; -} diff --git a/third_party/curl/lib/netrc.h b/third_party/curl/lib/netrc.h deleted file mode 100644 index 4db764df2..000000000 --- a/third_party/curl/lib/netrc.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef HEADER_CURL_NETRC_H -#define HEADER_CURL_NETRC_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* Make sure we have room for at least this size: */ -#define LOGINSIZE 64 -#define PASSWORDSIZE 64 - -/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */ -int Curl_parsenetrc(const char *host, - char *login, - char *password, - char *filename); - /* Assume: password[0]=0, host[0] != 0. - * If login[0] = 0, search for login and password within a machine section - * in the netrc. - * If login[0] != 0, search for password within machine and login. - */ - -#endif /* HEADER_CURL_NETRC_H */ diff --git a/third_party/curl/lib/non-ascii.c b/third_party/curl/lib/non-ascii.c deleted file mode 100644 index 7e6ad37bf..000000000 --- a/third_party/curl/lib/non-ascii.c +++ /dev/null @@ -1,339 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef CURL_DOES_CONVERSIONS - -#include "non-ascii.h" -#include "formdata.h" -#include "sendf.h" -#include "urldata.h" - -#include - -#ifdef HAVE_ICONV -#include -/* set default codesets for iconv */ -#ifndef CURL_ICONV_CODESET_OF_NETWORK -#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1" -#endif -#ifndef CURL_ICONV_CODESET_FOR_UTF8 -#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8" -#endif -#define ICONV_ERROR (size_t)-1 -#endif /* HAVE_ICONV */ - -/* - * Curl_convert_clone() returns a malloced copy of the source string (if - * returning CURLE_OK), with the data converted to network format. - */ -CURLcode Curl_convert_clone(struct SessionHandle *data, - const char *indata, - size_t insize, - char **outbuf) -{ - char *convbuf; - CURLcode result; - - convbuf = malloc(insize); - if(!convbuf) - return CURLE_OUT_OF_MEMORY; - - memcpy(convbuf, indata, insize); - result = Curl_convert_to_network(data, convbuf, insize); - if(result) { - free(convbuf); - return result; - } - - *outbuf = convbuf; /* return the converted buffer */ - - return CURLE_OK; -} - -/* - * Curl_convert_to_network() is an internal function for performing ASCII - * conversions on non-ASCII platforms. It convers the buffer _in place_. - */ -CURLcode Curl_convert_to_network(struct SessionHandle *data, - char *buffer, size_t length) -{ - CURLcode rc; - - if(data->set.convtonetwork) { - /* use translation callback */ - rc = data->set.convtonetwork(buffer, length); - if(rc != CURLE_OK) { - failf(data, - "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s", - (int)rc, curl_easy_strerror(rc)); - } - return rc; - } - else { -#ifdef HAVE_ICONV - /* do the translation ourselves */ - char *input_ptr, *output_ptr; - size_t in_bytes, out_bytes, rc; - int error; - - /* open an iconv conversion descriptor if necessary */ - if(data->outbound_cd == (iconv_t)-1) { - data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK, - CURL_ICONV_CODESET_OF_HOST); - if(data->outbound_cd == (iconv_t)-1) { - error = ERRNO; - failf(data, - "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", - CURL_ICONV_CODESET_OF_NETWORK, - CURL_ICONV_CODESET_OF_HOST, - error, strerror(error)); - return CURLE_CONV_FAILED; - } - } - /* call iconv */ - input_ptr = output_ptr = buffer; - in_bytes = out_bytes = length; - rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes, - &output_ptr, &out_bytes); - if((rc == ICONV_ERROR) || (in_bytes != 0)) { - error = ERRNO; - failf(data, - "The Curl_convert_to_network iconv call failed with errno %i: %s", - error, strerror(error)); - return CURLE_CONV_FAILED; - } -#else - failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required"); - return CURLE_CONV_REQD; -#endif /* HAVE_ICONV */ - } - - return CURLE_OK; -} - -/* - * Curl_convert_from_network() is an internal function for performing ASCII - * conversions on non-ASCII platforms. It convers the buffer _in place_. - */ -CURLcode Curl_convert_from_network(struct SessionHandle *data, - char *buffer, size_t length) -{ - CURLcode rc; - - if(data->set.convfromnetwork) { - /* use translation callback */ - rc = data->set.convfromnetwork(buffer, length); - if(rc != CURLE_OK) { - failf(data, - "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s", - (int)rc, curl_easy_strerror(rc)); - } - return rc; - } - else { -#ifdef HAVE_ICONV - /* do the translation ourselves */ - char *input_ptr, *output_ptr; - size_t in_bytes, out_bytes, rc; - int error; - - /* open an iconv conversion descriptor if necessary */ - if(data->inbound_cd == (iconv_t)-1) { - data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, - CURL_ICONV_CODESET_OF_NETWORK); - if(data->inbound_cd == (iconv_t)-1) { - error = ERRNO; - failf(data, - "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", - CURL_ICONV_CODESET_OF_HOST, - CURL_ICONV_CODESET_OF_NETWORK, - error, strerror(error)); - return CURLE_CONV_FAILED; - } - } - /* call iconv */ - input_ptr = output_ptr = buffer; - in_bytes = out_bytes = length; - rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes, - &output_ptr, &out_bytes); - if((rc == ICONV_ERROR) || (in_bytes != 0)) { - error = ERRNO; - failf(data, - "The Curl_convert_from_network iconv call failed with errno %i: %s", - error, strerror(error)); - return CURLE_CONV_FAILED; - } -#else - failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required"); - return CURLE_CONV_REQD; -#endif /* HAVE_ICONV */ - } - - return CURLE_OK; -} - -/* - * Curl_convert_from_utf8() is an internal function for performing UTF-8 - * conversions on non-ASCII platforms. - */ -CURLcode Curl_convert_from_utf8(struct SessionHandle *data, - char *buffer, size_t length) -{ - CURLcode rc; - - if(data->set.convfromutf8) { - /* use translation callback */ - rc = data->set.convfromutf8(buffer, length); - if(rc != CURLE_OK) { - failf(data, - "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s", - (int)rc, curl_easy_strerror(rc)); - } - return rc; - } - else { -#ifdef HAVE_ICONV - /* do the translation ourselves */ - const char *input_ptr; - char *output_ptr; - size_t in_bytes, out_bytes, rc; - int error; - - /* open an iconv conversion descriptor if necessary */ - if(data->utf8_cd == (iconv_t)-1) { - data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, - CURL_ICONV_CODESET_FOR_UTF8); - if(data->utf8_cd == (iconv_t)-1) { - error = ERRNO; - failf(data, - "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s", - CURL_ICONV_CODESET_OF_HOST, - CURL_ICONV_CODESET_FOR_UTF8, - error, strerror(error)); - return CURLE_CONV_FAILED; - } - } - /* call iconv */ - input_ptr = output_ptr = buffer; - in_bytes = out_bytes = length; - rc = iconv(data->utf8_cd, &input_ptr, &in_bytes, - &output_ptr, &out_bytes); - if((rc == ICONV_ERROR) || (in_bytes != 0)) { - error = ERRNO; - failf(data, - "The Curl_convert_from_utf8 iconv call failed with errno %i: %s", - error, strerror(error)); - return CURLE_CONV_FAILED; - } - if(output_ptr < input_ptr) { - /* null terminate the now shorter output string */ - *output_ptr = 0x00; - } -#else - failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required"); - return CURLE_CONV_REQD; -#endif /* HAVE_ICONV */ - } - - return CURLE_OK; -} - -/* - * Init conversion stuff for a SessionHandle - */ -void Curl_convert_init(struct SessionHandle *data) -{ -#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) - /* conversion descriptors for iconv calls */ - data->outbound_cd = (iconv_t)-1; - data->inbound_cd = (iconv_t)-1; - data->utf8_cd = (iconv_t)-1; -#else - (void)data; -#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ -} - -/* - * Setup conversion stuff for a SessionHandle - */ -void Curl_convert_setup(struct SessionHandle *data) -{ - data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, - CURL_ICONV_CODESET_OF_NETWORK); - data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK, - CURL_ICONV_CODESET_OF_HOST); - data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST, - CURL_ICONV_CODESET_FOR_UTF8); -} - -/* - * Close conversion stuff for a SessionHandle - */ - -void Curl_convert_close(struct SessionHandle *data) -{ -#ifdef HAVE_ICONV - /* close iconv conversion descriptors */ - if(data->inbound_cd != (iconv_t)-1) { - iconv_close(data->inbound_cd); - } - if(data->outbound_cd != (iconv_t)-1) { - iconv_close(data->outbound_cd); - } - if(data->utf8_cd != (iconv_t)-1) { - iconv_close(data->utf8_cd); - } -#else - (void)data; -#endif /* HAVE_ICONV */ -} - -/* - * Curl_convert_form() is used from http.c, this converts any form items that - need to be sent in the network encoding. Returns CURLE_OK on success. - */ -CURLcode Curl_convert_form(struct SessionHandle *data, struct FormData *form) -{ - struct FormData *next; - CURLcode rc; - - if(!form) - return CURLE_OK; - - if(!data) - return CURLE_BAD_FUNCTION_ARGUMENT; - - do { - next=form->next; /* the following form line */ - if(form->type == FORM_DATA) { - rc = Curl_convert_to_network(data, form->line, form->length); - /* Curl_convert_to_network calls failf if unsuccessful */ - if(rc != CURLE_OK) - return rc; - } - } while((form = next) != NULL); /* continue */ - return CURLE_OK; -} - -#endif /* CURL_DOES_CONVERSIONS */ diff --git a/third_party/curl/lib/non-ascii.h b/third_party/curl/lib/non-ascii.h deleted file mode 100644 index 89899bedd..000000000 --- a/third_party/curl/lib/non-ascii.h +++ /dev/null @@ -1,60 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef CURL_DOES_CONVERSIONS - -#include "urldata.h" - -/* - * Curl_convert_clone() returns a malloced copy of the source string (if - * returning CURLE_OK), with the data converted to network format. - * - * If no conversion was needed *outbuf may be NULL. - */ -CURLcode Curl_convert_clone(struct SessionHandle *data, - const char *indata, - size_t insize, - char **outbuf); - -void Curl_convert_init(struct SessionHandle *data); -void Curl_convert_setup(struct SessionHandle *data); -void Curl_convert_close(struct SessionHandle *data); - -CURLcode Curl_convert_to_network(struct SessionHandle *data, - char *buffer, size_t length); -CURLcode Curl_convert_from_network(struct SessionHandle *data, - char *buffer, size_t length); -CURLcode Curl_convert_from_utf8(struct SessionHandle *data, - char *buffer, size_t length); -CURLcode Curl_convert_form(struct SessionHandle *data, struct FormData *form); -#else -#define Curl_convert_clone(a,b,c,d) \ - ((void)a, (void)b, (void)c, *(d)=NULL, CURLE_OK) -#define Curl_convert_init(x) -#define Curl_convert_setup(x) -#define Curl_convert_close(x) -#define Curl_convert_to_network(a,b,c) ((void)a, CURLE_OK) -#define Curl_convert_from_network(a,b,c) ((void)a, CURLE_OK) -#define Curl_convert_from_utf8(a,b,c) ((void)a, CURLE_OK) -#define Curl_convert_form(a,b) CURLE_OK -#endif diff --git a/third_party/curl/lib/nonblock.c b/third_party/curl/lib/nonblock.c deleted file mode 100644 index cd819506c..000000000 --- a/third_party/curl/lib/nonblock.c +++ /dev/null @@ -1,101 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif - -#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) -#include -#endif -#ifdef __VMS -#include -#include -#endif - -#include "nonblock.h" - -/* - * curlx_nonblock() set the given socket to either blocking or non-blocking - * mode based on the 'nonblock' boolean argument. This function is highly - * portable. - */ -int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ - int nonblock /* TRUE or FALSE */) -{ -#if defined(USE_BLOCKING_SOCKETS) - - return 0; /* returns success */ - -#elif defined(HAVE_FCNTL_O_NONBLOCK) - - /* most recent unix versions */ - int flags; - flags = fcntl(sockfd, F_GETFL, 0); - if(FALSE != nonblock) - return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); - else - return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); - -#elif defined(HAVE_IOCTL_FIONBIO) - - /* older unix versions */ - int flags; - flags = nonblock; - return ioctl(sockfd, FIONBIO, &flags); - -#elif defined(HAVE_IOCTLSOCKET_FIONBIO) - - /* Windows */ - unsigned long flags; - flags = nonblock; - return ioctlsocket(sockfd, FIONBIO, &flags); - -#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO) - - /* Amiga */ - return IoctlSocket(sockfd, FIONBIO, (long)nonblock); - -#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK) - - /* BeOS */ - long b = nonblock ? 1 : 0; - return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); - -#else -# error "no non-blocking method was found/used/set" -#endif -} diff --git a/third_party/curl/lib/nonblock.h b/third_party/curl/lib/nonblock.h deleted file mode 100644 index adcd2c15e..000000000 --- a/third_party/curl/lib/nonblock.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __NONBLOCK_H -#define __NONBLOCK_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 /* for curl_socket_t */ - -int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ - int nonblock /* TRUE or FALSE */); - -#endif diff --git a/third_party/curl/lib/nss.c b/third_party/curl/lib/nss.c deleted file mode 100644 index 3677043f0..000000000 --- a/third_party/curl/lib/nss.c +++ /dev/null @@ -1,1510 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Source file for all NSS-specific code for the TLS/SSL layer. No code - * but sslgen.c should ever call or use these functions. - */ - -#include "setup.h" - -#include -#include -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#include "urldata.h" -#include "sendf.h" -#include "formdata.h" /* for the boundary function */ -#include "url.h" /* for the ssl config check function */ -#include "connect.h" -#include "strequal.h" -#include "select.h" -#include "sslgen.h" -#include "llist.h" - -#define _MPRINTF_REPLACE /* use the internal *printf() functions */ -#include - -#ifdef USE_NSS - -#include "nssg.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "curl_memory.h" -#include "rawstr.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -#define SSL_DIR "/etc/pki/nssdb" - -/* enough to fit the string "PEM Token #[0|1]" */ -#define SLOTSIZE 13 - -PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd); - -PRLock * nss_initlock = NULL; -PRLock * nss_crllock = NULL; - -volatile int initialized = 0; - -typedef struct { - const char *name; - int num; - PRInt32 version; /* protocol version valid for this cipher */ -} cipher_s; - -#define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do { \ - CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++); \ - ptr->type = (_type); \ - ptr->pValue = (_val); \ - ptr->ulValueLen = (_len); \ -} while(0) - -#define CERT_NewTempCertificate __CERT_NewTempCertificate - -enum sslversion { SSL2 = 1, SSL3 = 2, TLS = 4 }; - -#define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0]) -static const cipher_s cipherlist[] = { - /* SSL2 cipher suites */ - {"rc4", SSL_EN_RC4_128_WITH_MD5, SSL2}, - {"rc4-md5", SSL_EN_RC4_128_WITH_MD5, SSL2}, - {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL2}, - {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5, SSL2}, - {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL2}, - {"des", SSL_EN_DES_64_CBC_WITH_MD5, SSL2}, - {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL2}, - /* SSL3/TLS cipher suites */ - {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, SSL3 | TLS}, - {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, SSL3 | TLS}, - {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL3 | TLS}, - {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA, SSL3 | TLS}, - {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL3 | TLS}, - {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL3 | TLS}, - {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5, SSL3 | TLS}, - {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA, SSL3 | TLS}, - {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL3 | TLS}, - {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL3 | TLS}, - {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, SSL3 | TLS}, - {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, SSL3 | TLS}, - {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA, SSL3 | TLS}, - /* TLS 1.0: Exportable 56-bit Cipher Suites. */ - {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL3 | TLS}, - {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL3 | TLS}, - /* AES ciphers. */ - {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA, SSL3 | TLS}, - {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA, SSL3 | TLS}, -#ifdef NSS_ENABLE_ECC - /* ECC ciphers. */ - {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA, TLS}, - {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS}, - {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS}, - {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS}, - {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS}, - {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS}, - {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS}, - {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS}, - {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS}, - {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS}, - {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA, TLS}, - {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS}, - {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLS}, - {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS}, - {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS}, - {"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA, TLS}, - {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS}, - {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS}, - {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS}, - {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS}, - {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA, TLS}, - {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA, TLS}, - {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, TLS}, - {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA, TLS}, - {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA, TLS}, -#endif -}; - -/* following ciphers are new in NSS 3.4 and not enabled by default, therefore - they are enabled explicitly */ -static const int enable_ciphers_by_default[] = { - TLS_DHE_DSS_WITH_AES_128_CBC_SHA, - TLS_DHE_DSS_WITH_AES_256_CBC_SHA, - TLS_DHE_RSA_WITH_AES_128_CBC_SHA, - TLS_DHE_RSA_WITH_AES_256_CBC_SHA, - TLS_RSA_WITH_AES_128_CBC_SHA, - TLS_RSA_WITH_AES_256_CBC_SHA, - SSL_NULL_WITH_NULL_NULL -}; - -#ifdef HAVE_PK11_CREATEGENERICOBJECT -static const char* pem_library = "libnsspem.so"; -#endif -SECMODModule* mod = NULL; - -static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model, - char *cipher_list) -{ - unsigned int i; - PRBool cipher_state[NUM_OF_CIPHERS]; - PRBool found; - char *cipher; - SECStatus rv; - - /* First disable all ciphers. This uses a different max value in case - * NSS adds more ciphers later we don't want them available by - * accident - */ - for(i=0; iset.str[cert_kind]; - const char *n; - *is_nickname = TRUE; - - if(!is_file(str)) - /* no such file exists, use the string as nickname */ - return strdup(str); - - /* search the last slash; we require at least one slash in a file name */ - n = strrchr(str, '/'); - if(!n) { - infof(data, "warning: certificate file name \"%s\" handled as nickname; " - "please use \"./%s\" to force file name\n", str, str); - return strdup(str); - } - - /* we'll use the PEM reader to read the certificate from file */ - *is_nickname = FALSE; - - n++; /* skip last slash */ - return aprintf("PEM Token #%d:%s", 1, n); -} - -#ifdef HAVE_PK11_CREATEGENERICOBJECT -/* Call PK11_CreateGenericObject() with the given obj_class and filename. If - * the call succeeds, append the object handle to the list of objects so that - * the object can be destroyed in Curl_nss_close(). */ -static CURLcode nss_create_object(struct ssl_connect_data *ssl, - CK_OBJECT_CLASS obj_class, - const char *filename, bool cacert) -{ - PK11SlotInfo *slot; - PK11GenericObject *obj; - CK_BBOOL cktrue = CK_TRUE; - CK_BBOOL ckfalse = CK_FALSE; - CK_ATTRIBUTE attrs[/* max count of attributes */ 4]; - int attr_cnt = 0; - - const int slot_id = (cacert) ? 0 : 1; - char *slot_name = aprintf("PEM Token #%d", slot_id); - if(!slot_name) - return CURLE_OUT_OF_MEMORY; - - slot = PK11_FindSlotByName(slot_name); - free(slot_name); - if(!slot) - return CURLE_SSL_CERTPROBLEM; - - PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class)); - PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); - PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename, - strlen(filename) + 1); - - if(CKO_CERTIFICATE == obj_class) { - CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse); - PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval)); - } - - obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE); - PK11_FreeSlot(slot); - if(!obj) - return CURLE_SSL_CERTPROBLEM; - - if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) { - PK11_DestroyGenericObject(obj); - return CURLE_OUT_OF_MEMORY; - } - - return CURLE_OK; -} - -/* Destroy the NSS object whose handle is given by ptr. This function is - * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy - * NSS objects in Curl_nss_close() */ -static void nss_destroy_object(void *user, void *ptr) -{ - PK11GenericObject *obj = (PK11GenericObject *)ptr; - (void) user; - PK11_DestroyGenericObject(obj); -} -#endif - -static int nss_load_cert(struct ssl_connect_data *ssl, - const char *filename, PRBool cacert) -{ -#ifdef HAVE_PK11_CREATEGENERICOBJECT - /* All CA and trust objects go into slot 0. Other slots are used - * for storing certificates. - */ - const int slot_id = (cacert) ? 0 : 1; -#endif - CERTCertificate *cert; - char *nickname = NULL; - char *n = NULL; - - /* If there is no slash in the filename it is assumed to be a regular - * NSS nickname. - */ - if(is_file(filename)) { - n = strrchr(filename, '/'); - if(n) - n++; - if(!mod) - return 1; - } - else { - /* A nickname from the NSS internal database */ - if(cacert) - return 0; /* You can't specify an NSS CA nickname this way */ - nickname = strdup(filename); - if(!nickname) - return 0; - goto done; - } - -#ifdef HAVE_PK11_CREATEGENERICOBJECT - nickname = aprintf("PEM Token #%d:%s", slot_id, n); - if(!nickname) - return 0; - - if(CURLE_OK != nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert)) { - free(nickname); - return 0; - } - -#else - /* We don't have PK11_CreateGenericObject but a file-based cert was passed - * in. We need to fail. - */ - return 0; -#endif - - done: - /* Double-check that the certificate or nickname requested exists in - * either the token or the NSS certificate database. - */ - if(!cacert) { - cert = PK11_FindCertFromNickname((char *)nickname, NULL); - - /* An invalid nickname was passed in */ - if(cert == NULL) { - free(nickname); - PR_SetError(SEC_ERROR_UNKNOWN_CERT, 0); - return 0; - } - - CERT_DestroyCertificate(cert); - } - - free(nickname); - - return 1; -} - -/* add given CRL to cache if it is not already there */ -static SECStatus nss_cache_crl(SECItem *crlDER) -{ - CERTCertDBHandle *db = CERT_GetDefaultCertDB(); - CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crlDER, 0); - if(crl) { - /* CRL already cached */ - SEC_DestroyCrl(crl); - SECITEM_FreeItem(crlDER, PR_FALSE); - return SECSuccess; - } - - /* acquire lock before call of CERT_CacheCRL() */ - PR_Lock(nss_crllock); - if(SECSuccess != CERT_CacheCRL(db, crlDER)) { - /* unable to cache CRL */ - PR_Unlock(nss_crllock); - SECITEM_FreeItem(crlDER, PR_FALSE); - return SECFailure; - } - - /* we need to clear session cache, so that the CRL could take effect */ - SSL_ClearSessionCache(); - PR_Unlock(nss_crllock); - return SECSuccess; -} - -static SECStatus nss_load_crl(const char* crlfilename) -{ - PRFileDesc *infile; - PRFileInfo info; - SECItem filedata = { 0, NULL, 0 }; - SECItem crlDER = { 0, NULL, 0 }; - char *body; - - infile = PR_Open(crlfilename, PR_RDONLY, 0); - if(!infile) - return SECFailure; - - if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info)) - goto fail; - - if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1)) - goto fail; - - if(info.size != PR_Read(infile, filedata.data, info.size)) - goto fail; - - /* place a trailing zero right after the visible data */ - body = (char*)filedata.data; - body[--filedata.len] = '\0'; - - body = strstr(body, "-----BEGIN"); - if(body) { - /* assume ASCII */ - char *trailer; - char *begin = PORT_Strchr(body, '\n'); - if(!begin) - begin = PORT_Strchr(body, '\r'); - if(!begin) - goto fail; - - trailer = strstr(++begin, "-----END"); - if(!trailer) - goto fail; - - /* retrieve DER from ASCII */ - *trailer = '\0'; - if(ATOB_ConvertAsciiToItem(&crlDER, begin)) - goto fail; - - SECITEM_FreeItem(&filedata, PR_FALSE); - } - else - /* assume DER */ - crlDER = filedata; - - PR_Close(infile); - return nss_cache_crl(&crlDER); - -fail: - PR_Close(infile); - SECITEM_FreeItem(&filedata, PR_FALSE); - return SECFailure; -} - -static int nss_load_key(struct connectdata *conn, int sockindex, - char *key_file) -{ -#ifdef HAVE_PK11_CREATEGENERICOBJECT - PK11SlotInfo *slot; - SECStatus status; - struct ssl_connect_data *ssl = conn->ssl; - (void)sockindex; /* unused */ - - if(CURLE_OK != nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE)) { - PR_SetError(SEC_ERROR_BAD_KEY, 0); - return 0; - } - - slot = PK11_FindSlotByName("PEM Token #1"); - if(!slot) - return 0; - - /* This will force the token to be seen as re-inserted */ - SECMOD_WaitForAnyTokenEvent(mod, 0, 0); - PK11_IsPresent(slot); - - status = PK11_Authenticate(slot, PR_TRUE, - conn->data->set.str[STRING_KEY_PASSWD]); - PK11_FreeSlot(slot); - return (SECSuccess == status) ? 1 : 0; -#else - /* If we don't have PK11_CreateGenericObject then we can't load a file-based - * key. - */ - (void)conn; /* unused */ - (void)key_file; /* unused */ - (void)sockindex; /* unused */ - return 0; -#endif -} - -static int display_error(struct connectdata *conn, PRInt32 err, - const char *filename) -{ - switch(err) { - case SEC_ERROR_BAD_PASSWORD: - failf(conn->data, "Unable to load client key: Incorrect password"); - return 1; - case SEC_ERROR_UNKNOWN_CERT: - failf(conn->data, "Unable to load certificate %s", filename); - return 1; - default: - break; - } - return 0; /* The caller will print a generic error */ -} - -static int cert_stuff(struct connectdata *conn, - int sockindex, char *cert_file, char *key_file) -{ - struct SessionHandle *data = conn->data; - int rv = 0; - - if(cert_file) { - rv = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE); - if(!rv) { - if(!display_error(conn, PR_GetError(), cert_file)) - failf(data, "Unable to load client cert %d.", PR_GetError()); - return 0; - } - } - if(key_file || (is_file(cert_file))) { - if(key_file) - rv = nss_load_key(conn, sockindex, key_file); - else - /* In case the cert file also has the key */ - rv = nss_load_key(conn, sockindex, cert_file); - if(!rv) { - if(!display_error(conn, PR_GetError(), key_file)) - failf(data, "Unable to load client key %d.", PR_GetError()); - - return 0; - } - } - return 1; -} - -static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg) -{ - (void)slot; /* unused */ - if(retry || NULL == arg) - return NULL; - else - return (char *)PORT_Strdup((char *)arg); -} - -/* bypass the default SSL_AuthCertificate() hook in case we do not want to - * verify peer */ -static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, - PRBool isServer) -{ - struct connectdata *conn = (struct connectdata *)arg; - if(!conn->data->set.ssl.verifypeer) { - infof(conn->data, "skipping SSL peer certificate verification\n"); - return SECSuccess; - } - - return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer); -} - -static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) -{ - SECStatus result = SECFailure; - struct connectdata *conn = (struct connectdata *)arg; - PRErrorCode err = PR_GetError(); - CERTCertificate *cert = NULL; - char *subject, *subject_cn, *issuer; - - conn->data->set.ssl.certverifyresult=err; - cert = SSL_PeerCertificate(sock); - subject = CERT_NameToAscii(&cert->subject); - subject_cn = CERT_GetCommonName(&cert->subject); - issuer = CERT_NameToAscii(&cert->issuer); - CERT_DestroyCertificate(cert); - - switch(err) { - case SEC_ERROR_CA_CERT_INVALID: - infof(conn->data, "Issuer certificate is invalid: '%s'\n", issuer); - break; - case SEC_ERROR_UNTRUSTED_ISSUER: - infof(conn->data, "Certificate is signed by an untrusted issuer: '%s'\n", - issuer); - break; - case SSL_ERROR_BAD_CERT_DOMAIN: - if(conn->data->set.ssl.verifyhost) { - failf(conn->data, "SSL: certificate subject name '%s' does not match " - "target host name '%s'", subject_cn, conn->host.dispname); - } else { - result = SECSuccess; - infof(conn->data, "warning: SSL: certificate subject name '%s' does not " - "match target host name '%s'\n", subject_cn, conn->host.dispname); - } - break; - case SEC_ERROR_EXPIRED_CERTIFICATE: - infof(conn->data, "Remote Certificate has expired.\n"); - break; - case SEC_ERROR_UNKNOWN_ISSUER: - infof(conn->data, "Peer's certificate issuer is not recognized: '%s'\n", - issuer); - break; - default: - infof(conn->data, "Bad certificate received. Subject = '%s', " - "Issuer = '%s'\n", subject, issuer); - break; - } - if(result == SECSuccess) - infof(conn->data, "SSL certificate verify ok.\n"); - PR_Free(subject); - PR_Free(subject_cn); - PR_Free(issuer); - - return result; -} - -/** - * Inform the application that the handshake is complete. - */ -static SECStatus HandshakeCallback(PRFileDesc *sock, void *arg) -{ - (void)sock; - (void)arg; - return SECSuccess; -} - -static void display_cert_info(struct SessionHandle *data, - CERTCertificate *cert) -{ - char *subject, *issuer, *common_name; - PRExplodedTime printableTime; - char timeString[256]; - PRTime notBefore, notAfter; - - subject = CERT_NameToAscii(&cert->subject); - issuer = CERT_NameToAscii(&cert->issuer); - common_name = CERT_GetCommonName(&cert->subject); - infof(data, "\tsubject: %s\n", subject); - - CERT_GetCertTimes(cert, ¬Before, ¬After); - PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime); - PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); - infof(data, "\tstart date: %s\n", timeString); - PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime); - PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); - infof(data, "\texpire date: %s\n", timeString); - infof(data, "\tcommon name: %s\n", common_name); - infof(data, "\tissuer: %s\n", issuer); - - PR_Free(subject); - PR_Free(issuer); - PR_Free(common_name); -} - -static void display_conn_info(struct connectdata *conn, PRFileDesc *sock) -{ - SSLChannelInfo channel; - SSLCipherSuiteInfo suite; - CERTCertificate *cert; - - if(SSL_GetChannelInfo(sock, &channel, sizeof channel) == - SECSuccess && channel.length == sizeof channel && - channel.cipherSuite) { - if(SSL_GetCipherSuiteInfo(channel.cipherSuite, - &suite, sizeof suite) == SECSuccess) { - infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName); - } - } - - infof(conn->data, "Server certificate:\n"); - - cert = SSL_PeerCertificate(sock); - display_cert_info(conn->data, cert); - CERT_DestroyCertificate(cert); - - return; -} - -/** - * - * Check that the Peer certificate's issuer certificate matches the one found - * by issuer_nickname. This is not exactly the way OpenSSL and GNU TLS do the - * issuer check, so we provide comments that mimic the OpenSSL - * X509_check_issued function (in x509v3/v3_purp.c) - */ -static SECStatus check_issuer_cert(PRFileDesc *sock, - char *issuer_nickname) -{ - CERTCertificate *cert,*cert_issuer,*issuer; - SECStatus res=SECSuccess; - void *proto_win = NULL; - - /* - PRArenaPool *tmpArena = NULL; - CERTAuthKeyID *authorityKeyID = NULL; - SECITEM *caname = NULL; - */ - - cert = SSL_PeerCertificate(sock); - cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner); - - proto_win = SSL_RevealPinArg(sock); - issuer = NULL; - issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win); - - if ((!cert_issuer) || (!issuer)) - res = SECFailure; - else if (SECITEM_CompareItem(&cert_issuer->derCert, - &issuer->derCert)!=SECEqual) - res = SECFailure; - - CERT_DestroyCertificate(cert); - CERT_DestroyCertificate(issuer); - CERT_DestroyCertificate(cert_issuer); - return res; -} - -/** - * - * Callback to pick the SSL client certificate. - */ -static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, - struct CERTDistNamesStr *caNames, - struct CERTCertificateStr **pRetCert, - struct SECKEYPrivateKeyStr **pRetKey) -{ - static const char pem_nickname[] = "PEM Token #1"; - const char *pem_slotname = pem_nickname; - - struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; - struct SessionHandle *data = connssl->data; - const char *nickname = connssl->client_nickname; - - if (mod && nickname && - 0 == strncmp(nickname, pem_nickname, /* length of "PEM Token" */ 9)) { - - /* use the cert/key provided by PEM reader */ - PK11SlotInfo *slot; - void *proto_win = SSL_RevealPinArg(sock); - *pRetKey = NULL; - - *pRetCert = PK11_FindCertFromNickname(nickname, proto_win); - if (NULL == *pRetCert) { - failf(data, "NSS: client certificate not found: %s", nickname); - return SECFailure; - } - - slot = PK11_FindSlotByName(pem_slotname); - if (NULL == slot) { - failf(data, "NSS: PK11 slot not found: %s", pem_slotname); - return SECFailure; - } - - *pRetKey = PK11_FindPrivateKeyFromCert(slot, *pRetCert, NULL); - PK11_FreeSlot(slot); - if (NULL == *pRetKey) { - failf(data, "NSS: private key not found for certificate: %s", nickname); - return SECFailure; - } - - infof(data, "NSS: client certificate: %s\n", nickname); - display_cert_info(data, *pRetCert); - return SECSuccess; - } - - /* use the default NSS hook */ - if (SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames, - pRetCert, pRetKey) - || NULL == *pRetCert) { - - if (NULL == nickname) - failf(data, "NSS: client certificate not found (nickname not " - "specified)"); - else - failf(data, "NSS: client certificate not found: %s", nickname); - - return SECFailure; - } - - /* get certificate nickname if any */ - nickname = (*pRetCert)->nickname; - if (NULL == nickname) - nickname = "[unknown]"; - - if (NULL == *pRetKey) { - failf(data, "NSS: private key not found for certificate: %s", nickname); - return SECFailure; - } - - infof(data, "NSS: using client certificate: %s\n", nickname); - display_cert_info(data, *pRetCert); - return SECSuccess; -} - -/* This function is supposed to decide, which error codes should be used - * to conclude server is TLS intolerant. - * - * taken from xulrunner - nsNSSIOLayer.cpp - */ -static PRBool -isTLSIntoleranceError(PRInt32 err) -{ - switch (err) { - case SSL_ERROR_BAD_MAC_ALERT: - case SSL_ERROR_BAD_MAC_READ: - case SSL_ERROR_HANDSHAKE_FAILURE_ALERT: - case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT: - case SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE: - case SSL_ERROR_ILLEGAL_PARAMETER_ALERT: - case SSL_ERROR_NO_CYPHER_OVERLAP: - case SSL_ERROR_BAD_SERVER: - case SSL_ERROR_BAD_BLOCK_PADDING: - case SSL_ERROR_UNSUPPORTED_VERSION: - case SSL_ERROR_PROTOCOL_VERSION_ALERT: - case SSL_ERROR_RX_MALFORMED_FINISHED: - case SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE: - case SSL_ERROR_DECODE_ERROR_ALERT: - case SSL_ERROR_RX_UNKNOWN_ALERT: - return PR_TRUE; - default: - return PR_FALSE; - } -} - -static CURLcode init_nss(struct SessionHandle *data) -{ - char *cert_dir; - struct_stat st; - if(initialized) - return CURLE_OK; - - /* First we check if $SSL_DIR points to a valid dir */ - cert_dir = getenv("SSL_DIR"); - if(cert_dir) { - if((stat(cert_dir, &st) != 0) || - (!S_ISDIR(st.st_mode))) { - cert_dir = NULL; - } - } - - /* Now we check if the default location is a valid dir */ - if(!cert_dir) { - if((stat(SSL_DIR, &st) == 0) && - (S_ISDIR(st.st_mode))) { - cert_dir = (char *)SSL_DIR; - } - } - - if(!NSS_IsInitialized()) { - SECStatus rv; - initialized = 1; - infof(data, "Initializing NSS with certpath: %s\n", - cert_dir ? cert_dir : "none"); - if(!cert_dir) { - rv = NSS_NoDB_Init(NULL); - } - else { - char *certpath = - PR_smprintf("%s%s", NSS_VersionCheck("3.12.0") ? "sql:" : "", cert_dir); - rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY); - PR_smprintf_free(certpath); - } - if(rv != SECSuccess) { - infof(data, "Unable to initialize NSS database\n"); - initialized = 0; - return CURLE_SSL_CACERT_BADFILE; - } - } - - if(num_enabled_ciphers() == 0) - NSS_SetDomesticPolicy(); - - return CURLE_OK; -} - -/** - * Global SSL init - * - * @retval 0 error initializing SSL - * @retval 1 SSL initialized successfully - */ -int Curl_nss_init(void) -{ - /* curl_global_init() is not thread-safe so this test is ok */ - if (nss_initlock == NULL) { - PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256); - nss_initlock = PR_NewLock(); - nss_crllock = PR_NewLock(); - } - - /* We will actually initialize NSS later */ - - return 1; -} - -CURLcode Curl_nss_force_init(struct SessionHandle *data) -{ - CURLcode rv; - if(!nss_initlock) { - failf(data, "unable to initialize NSS, curl_global_init() should have been " - "called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL"); - return CURLE_OUT_OF_MEMORY; - } - - PR_Lock(nss_initlock); - rv = init_nss(data); - PR_Unlock(nss_initlock); - return rv; -} - -/* Global cleanup */ -void Curl_nss_cleanup(void) -{ - /* This function isn't required to be threadsafe and this is only done - * as a safety feature. - */ - PR_Lock(nss_initlock); - if (initialized) { - /* Free references to client certificates held in the SSL session cache. - * Omitting this hampers destruction of the security module owning - * the certificates. */ - SSL_ClearSessionCache(); - - if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) { - SECMOD_DestroyModule(mod); - mod = NULL; - } - NSS_Shutdown(); - } - PR_Unlock(nss_initlock); - - PR_DestroyLock(nss_initlock); - PR_DestroyLock(nss_crllock); - nss_initlock = NULL; - - initialized = 0; -} - -/* - * This function uses SSL_peek to determine connection status. - * - * Return codes: - * 1 means the connection is still in place - * 0 means the connection has been closed - * -1 means the connection status is unknown - */ -int -Curl_nss_check_cxn(struct connectdata *conn) -{ - int rc; - char buf; - - rc = - PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK, - PR_SecondsToInterval(1)); - if(rc > 0) - return 1; /* connection still in place */ - - if(rc == 0) - return 0; /* connection has been closed */ - - return -1; /* connection status unknown */ -} - -/* - * This function is called when an SSL connection is closed. - */ -void Curl_nss_close(struct connectdata *conn, int sockindex) -{ - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - if(connssl->handle) { - /* NSS closes the socket we previously handed to it, so we must mark it - as closed to avoid double close */ - fake_sclose(conn->sock[sockindex]); - conn->sock[sockindex] = CURL_SOCKET_BAD; - if(connssl->client_nickname != NULL) { - free(connssl->client_nickname); - connssl->client_nickname = NULL; - - /* force NSS to ask again for a client cert when connecting - * next time to the same server */ - SSL_InvalidateSession(connssl->handle); - } -#ifdef HAVE_PK11_CREATEGENERICOBJECT - /* destroy all NSS objects in order to avoid failure of NSS shutdown */ - Curl_llist_destroy(connssl->obj_list, NULL); - connssl->obj_list = NULL; -#endif - PR_Close(connssl->handle); - connssl->handle = NULL; - } -} - -/* - * This function is called when the 'data' struct is going away. Close - * down everything and free all resources! - */ -int Curl_nss_close_all(struct SessionHandle *data) -{ - (void)data; - return 0; -} - -/* handle client certificate related errors if any; return false otherwise */ -static bool handle_cc_error(PRInt32 err, struct SessionHandle *data) -{ - switch(err) { - case SSL_ERROR_BAD_CERT_ALERT: - failf(data, "SSL error: SSL_ERROR_BAD_CERT_ALERT"); - return true; - - case SSL_ERROR_REVOKED_CERT_ALERT: - failf(data, "SSL error: SSL_ERROR_REVOKED_CERT_ALERT"); - return true; - - case SSL_ERROR_EXPIRED_CERT_ALERT: - failf(data, "SSL error: SSL_ERROR_EXPIRED_CERT_ALERT"); - return true; - - default: - return false; - } -} - -static Curl_recv nss_recv; -static Curl_send nss_send; - -static CURLcode nss_load_ca_certificates(struct connectdata *conn, - int sockindex) -{ - struct SessionHandle *data = conn->data; - const char *cafile = data->set.ssl.CAfile; - const char *capath = data->set.ssl.CApath; - - if(cafile && !nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE)) - return CURLE_SSL_CACERT_BADFILE; - - if(capath) { - struct_stat st; - if(stat(capath, &st) == -1) - return CURLE_SSL_CACERT_BADFILE; - - if(S_ISDIR(st.st_mode)) { - PRDirEntry *entry; - PRDir *dir = PR_OpenDir(capath); - if(!dir) - return CURLE_SSL_CACERT_BADFILE; - - while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) { - char *fullpath = aprintf("%s/%s", capath, entry->name); - if(!fullpath) { - PR_CloseDir(dir); - return CURLE_OUT_OF_MEMORY; - } - - if(!nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE)) - /* This is purposefully tolerant of errors so non-PEM files can - * be in the same directory */ - infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath); - - free(fullpath); - } - - PR_CloseDir(dir); - } - else - infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath); - } - - infof(data, " CAfile: %s\n CApath: %s\n", - cafile ? cafile : "none", - capath ? capath : "none"); - - return CURLE_OK; -} - -CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) -{ - PRInt32 err; - PRFileDesc *model = NULL; - PRBool ssl2 = PR_FALSE; - PRBool ssl3 = PR_FALSE; - PRBool tlsv1 = PR_FALSE; - PRBool ssl_no_cache; - struct SessionHandle *data = conn->data; - curl_socket_t sockfd = conn->sock[sockindex]; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - CURLcode curlerr; - const int *cipher_to_enable; - PRSocketOptionData sock_opt; - long time_left; - PRUint32 timeout; - - if (connssl->state == ssl_connection_complete) - return CURLE_OK; - - connssl->data = data; - -#ifdef HAVE_PK11_CREATEGENERICOBJECT - /* list of all NSS objects we need to destroy in Curl_nss_close() */ - connssl->obj_list = Curl_llist_alloc(nss_destroy_object); - if(!connssl->obj_list) - return CURLE_OUT_OF_MEMORY; -#endif - - /* FIXME. NSS doesn't support multiple databases open at the same time. */ - PR_Lock(nss_initlock); - curlerr = init_nss(conn->data); - if(CURLE_OK != curlerr) { - PR_Unlock(nss_initlock); - goto error; - } - - curlerr = CURLE_SSL_CONNECT_ERROR; - -#ifdef HAVE_PK11_CREATEGENERICOBJECT - if(!mod) { - char *configstring = aprintf("library=%s name=PEM", pem_library); - if(!configstring) { - PR_Unlock(nss_initlock); - goto error; - } - mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE); - free(configstring); - - if(!mod || !mod->loaded) { - if(mod) { - SECMOD_DestroyModule(mod); - mod = NULL; - } - infof(data, "WARNING: failed to load NSS PEM library %s. Using " - "OpenSSL PEM certificates will not work.\n", pem_library); - } - } -#endif - - PK11_SetPasswordFunc(nss_get_password); - PR_Unlock(nss_initlock); - - model = PR_NewTCPSocket(); - if(!model) - goto error; - model = SSL_ImportFD(NULL, model); - - /* make the socket nonblocking */ - sock_opt.option = PR_SockOpt_Nonblocking; - sock_opt.value.non_blocking = PR_TRUE; - if(PR_SetSocketOption(model, &sock_opt) != PR_SUCCESS) - goto error; - - if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess) - goto error; - if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess) - goto error; - if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess) - goto error; - - /* do not use SSL cache if we are not going to verify peer */ - ssl_no_cache = (data->set.ssl.verifypeer) ? PR_FALSE : PR_TRUE; - if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess) - goto error; - - switch (data->set.ssl.version) { - default: - case CURL_SSLVERSION_DEFAULT: - ssl3 = PR_TRUE; - if (data->state.ssl_connect_retry) - infof(data, "TLS disabled due to previous handshake failure\n"); - else - tlsv1 = PR_TRUE; - break; - case CURL_SSLVERSION_TLSv1: - tlsv1 = PR_TRUE; - break; - case CURL_SSLVERSION_SSLv2: - ssl2 = PR_TRUE; - break; - case CURL_SSLVERSION_SSLv3: - ssl3 = PR_TRUE; - break; - } - - if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess) - goto error; - if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess) - goto error; - if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess) - goto error; - - if(SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess) - goto error; - - /* reset the flag to avoid an infinite loop */ - data->state.ssl_connect_retry = FALSE; - - /* enable all ciphers from enable_ciphers_by_default */ - cipher_to_enable = enable_ciphers_by_default; - while (SSL_NULL_WITH_NULL_NULL != *cipher_to_enable) { - if (SSL_CipherPrefSet(model, *cipher_to_enable, PR_TRUE) != SECSuccess) { - curlerr = CURLE_SSL_CIPHER; - goto error; - } - cipher_to_enable++; - } - - if(data->set.ssl.cipher_list) { - if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) { - curlerr = CURLE_SSL_CIPHER; - goto error; - } - } - - if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost) - infof(data, "warning: ignoring value of ssl.verifyhost\n"); - else if(data->set.ssl.verifyhost == 1) - infof(data, "warning: ignoring unsupported value (1) of ssl.verifyhost\n"); - - /* bypass the default SSL_AuthCertificate() hook in case we do not want to - * verify peer */ - if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess) - goto error; - - data->set.ssl.certverifyresult=0; /* not checked yet */ - if(SSL_BadCertHook(model, (SSLBadCertHandler) BadCertHandler, conn) - != SECSuccess) { - goto error; - } - if(SSL_HandshakeCallback(model, (SSLHandshakeCallback) HandshakeCallback, - NULL) != SECSuccess) - goto error; - - if(data->set.ssl.verifypeer) { - const CURLcode rv = nss_load_ca_certificates(conn, sockindex); - if(CURLE_OK != rv) { - curlerr = rv; - goto error; - } - } - - if (data->set.ssl.CRLfile) { - if(SECSuccess != nss_load_crl(data->set.ssl.CRLfile)) { - curlerr = CURLE_SSL_CRL_BADFILE; - goto error; - } - infof(data, - " CRLfile: %s\n", - data->set.ssl.CRLfile ? data->set.ssl.CRLfile : "none"); - } - - if(data->set.str[STRING_CERT]) { - bool is_nickname; - char *nickname = fmt_nickname(data, STRING_CERT, &is_nickname); - if(!nickname) - return CURLE_OUT_OF_MEMORY; - - if(!is_nickname && !cert_stuff(conn, sockindex, data->set.str[STRING_CERT], - data->set.str[STRING_KEY])) { - /* failf() is already done in cert_stuff() */ - free(nickname); - return CURLE_SSL_CERTPROBLEM; - } - - /* store the nickname for SelectClientCert() called during handshake */ - connssl->client_nickname = nickname; - } - else - connssl->client_nickname = NULL; - - if(SSL_GetClientAuthDataHook(model, SelectClientCert, - (void *)connssl) != SECSuccess) { - curlerr = CURLE_SSL_CERTPROBLEM; - goto error; - } - - /* Import our model socket onto the existing file descriptor */ - connssl->handle = PR_ImportTCPSocket(sockfd); - connssl->handle = SSL_ImportFD(model, connssl->handle); - if(!connssl->handle) - goto error; - - PR_Close(model); /* We don't need this any more */ - model = NULL; - - /* This is the password associated with the cert that we're using */ - if (data->set.str[STRING_KEY_PASSWD]) { - SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]); - } - - /* Force handshake on next I/O */ - SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE); - - SSL_SetURL(connssl->handle, conn->host.name); - - /* check timeout situation */ - time_left = Curl_timeleft(data, NULL, TRUE); - if(time_left < 0L) { - failf(data, "timed out before SSL handshake"); - goto error; - } - timeout = PR_MillisecondsToInterval((PRUint32) time_left); - - /* Force the handshake now */ - if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) { - if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) - curlerr = CURLE_PEER_FAILED_VERIFICATION; - else if(conn->data->set.ssl.certverifyresult!=0) - curlerr = CURLE_SSL_CACERT; - goto error; - } - - connssl->state = ssl_connection_complete; - conn->recv[sockindex] = nss_recv; - conn->send[sockindex] = nss_send; - - display_conn_info(conn, connssl->handle); - - if (data->set.str[STRING_SSL_ISSUERCERT]) { - SECStatus ret = SECFailure; - bool is_nickname; - char *nickname = fmt_nickname(data, STRING_SSL_ISSUERCERT, &is_nickname); - if(!nickname) - return CURLE_OUT_OF_MEMORY; - - if(is_nickname) - /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */ - ret = check_issuer_cert(connssl->handle, nickname); - - free(nickname); - - if(SECFailure == ret) { - infof(data,"SSL certificate issuer check failed\n"); - curlerr = CURLE_SSL_ISSUER_ERROR; - goto error; - } - else { - infof(data, "SSL certificate issuer check ok\n"); - } - } - - return CURLE_OK; - - error: - /* reset the flag to avoid an infinite loop */ - data->state.ssl_connect_retry = FALSE; - - err = PR_GetError(); - if(handle_cc_error(err, data)) - curlerr = CURLE_SSL_CERTPROBLEM; - else - infof(data, "NSS error %d\n", err); - - if(model) - PR_Close(model); - -#ifdef HAVE_PK11_CREATEGENERICOBJECT - /* cleanup on connection failure */ - Curl_llist_destroy(connssl->obj_list, NULL); - connssl->obj_list = NULL; -#endif - - if (ssl3 && tlsv1 && isTLSIntoleranceError(err)) { - /* schedule reconnect through Curl_retry_request() */ - data->state.ssl_connect_retry = TRUE; - infof(data, "Error in TLS handshake, trying SSLv3...\n"); - return CURLE_OK; - } - - return curlerr; -} - -static ssize_t nss_send(struct connectdata *conn, /* connection data */ - int sockindex, /* socketindex */ - const void *mem, /* send this data */ - size_t len, /* amount to write */ - CURLcode *curlcode) -{ - int rc; - - rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, -1); - - if(rc < 0) { - PRInt32 err = PR_GetError(); - if(err == PR_WOULD_BLOCK_ERROR) - *curlcode = CURLE_AGAIN; - else if(handle_cc_error(err, conn->data)) - *curlcode = CURLE_SSL_CERTPROBLEM; - else { - failf(conn->data, "SSL write: error %d", err); - *curlcode = CURLE_SEND_ERROR; - } - return -1; - } - return rc; /* number of bytes */ -} - -static ssize_t nss_recv(struct connectdata * conn, /* connection data */ - int num, /* socketindex */ - char *buf, /* store read data here */ - size_t buffersize, /* max amount to read */ - CURLcode *curlcode) -{ - ssize_t nread; - - nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0, -1); - if(nread < 0) { - /* failed SSL read */ - PRInt32 err = PR_GetError(); - - if(err == PR_WOULD_BLOCK_ERROR) - *curlcode = CURLE_AGAIN; - else if(handle_cc_error(err, conn->data)) - *curlcode = CURLE_SSL_CERTPROBLEM; - else { - failf(conn->data, "SSL read: errno %d", err); - *curlcode = CURLE_RECV_ERROR; - } - return -1; - } - return nread; -} - -size_t Curl_nss_version(char *buffer, size_t size) -{ - return snprintf(buffer, size, "NSS/%s", NSS_VERSION); -} - -int Curl_nss_seed(struct SessionHandle *data) -{ - /* TODO: implement? */ - (void) data; - return 0; -} - -#endif /* USE_NSS */ diff --git a/third_party/curl/lib/nssg.h b/third_party/curl/lib/nssg.h deleted file mode 100644 index 438d5a636..000000000 --- a/third_party/curl/lib/nssg.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __NSSG_H -#define __NSSG_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifdef USE_NSS -/* - * This header should only be needed to get included by sslgen.c and nss.c - */ - -#include "urldata.h" -CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex); -CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, - int sockindex, - bool *done); -/* close a SSL connection */ -void Curl_nss_close(struct connectdata *conn, int sockindex); - -/* tell NSS to close down all open information regarding connections (and - thus session ID caching etc) */ -int Curl_nss_close_all(struct SessionHandle *data); - -int Curl_nss_init(void); -void Curl_nss_cleanup(void); - -size_t Curl_nss_version(char *buffer, size_t size); -int Curl_nss_check_cxn(struct connectdata *cxn); -int Curl_nss_seed(struct SessionHandle *data); - -/* initialize NSS library if not already */ -CURLcode Curl_nss_force_init(struct SessionHandle *data); - -/* API setup for NSS */ -#define curlssl_init Curl_nss_init -#define curlssl_cleanup Curl_nss_cleanup -#define curlssl_connect Curl_nss_connect - -/* NSS has its own session ID cache */ -#define curlssl_session_free(x) -#define curlssl_close_all Curl_nss_close_all -#define curlssl_close Curl_nss_close -/* NSS has no shutdown function provided and thus always fail */ -#define curlssl_shutdown(x,y) (x=x, y=y, 1) -#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN) -#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN) -#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL) -#define curlssl_version Curl_nss_version -#define curlssl_check_cxn(x) Curl_nss_check_cxn(x) -#define curlssl_data_pending(x,y) (x=x, y=y, 0) - -#endif /* USE_NSS */ -#endif diff --git a/third_party/curl/lib/nwlib.c b/third_party/curl/lib/nwlib.c deleted file mode 100644 index f9c8a4298..000000000 --- a/third_party/curl/lib/nwlib.c +++ /dev/null @@ -1,327 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifdef NETWARE /* Novell NetWare */ - -#include - -#ifdef __NOVELL_LIBC__ -/* For native LibC-based NLM we need to register as a real lib. */ -#include -#include -#include -#include -#include -#include -#include - - -typedef struct -{ - int _errno; - void *twentybytes; -} libthreaddata_t; - -typedef struct -{ - int x; - int y; - int z; - void *tenbytes; - NXKey_t perthreadkey; /* if -1, no key obtained... */ - NXMutex_t *lock; -} libdata_t; - -int gLibId = -1; -void *gLibHandle = (void *) NULL; -rtag_t gAllocTag = (rtag_t) NULL; -NXMutex_t *gLibLock = (NXMutex_t *) NULL; - -/* internal library function prototypes... */ -int DisposeLibraryData ( void * ); -void DisposeThreadData ( void * ); -int GetOrSetUpData ( int id, libdata_t **data, libthreaddata_t **threaddata ); - - -int _NonAppStart( void *NLMHandle, - void *errorScreen, - const char *cmdLine, - const char *loadDirPath, - size_t uninitializedDataLength, - void *NLMFileHandle, - int (*readRoutineP)( int conn, - void *fileHandle, size_t offset, - size_t nbytes, - size_t *bytesRead, - void *buffer ), - size_t customDataOffset, - size_t customDataSize, - int messageCount, - const char **messages ) -{ - NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0); - -#ifndef __GNUC__ -#pragma unused(cmdLine) -#pragma unused(loadDirPath) -#pragma unused(uninitializedDataLength) -#pragma unused(NLMFileHandle) -#pragma unused(readRoutineP) -#pragma unused(customDataOffset) -#pragma unused(customDataSize) -#pragma unused(messageCount) -#pragma unused(messages) -#endif - -/* -** Here we process our command line, post errors (to the error screen), -** perform initializations and anything else we need to do before being able -** to accept calls into us. If we succeed, we return non-zero and the NetWare -** Loader will leave us up, otherwise we fail to load and get dumped. -*/ - gAllocTag = AllocateResourceTag(NLMHandle, - " memory allocations", - AllocSignature); - - if(!gAllocTag) { - OutputToScreen(errorScreen, "Unable to allocate resource tag for " - "library memory allocations.\n"); - return -1; - } - - gLibId = register_library(DisposeLibraryData); - - if(gLibId < -1) { - OutputToScreen(errorScreen, "Unable to register library with kernel.\n"); - return -1; - } - - gLibHandle = NLMHandle; - - gLibLock = NXMutexAlloc(0, 0, &liblock); - - if(!gLibLock) { - OutputToScreen(errorScreen, "Unable to allocate library data lock.\n"); - return -1; - } - - return 0; -} - -/* -** Here we clean up any resources we allocated. Resource tags is a big part -** of what we created, but NetWare doesn't ask us to free those. -*/ -void _NonAppStop( void ) -{ - (void) unregister_library(gLibId); - NXMutexFree(gLibLock); -} - -/* -** This function cannot be the first in the file for if the file is linked -** first, then the check-unload function's offset will be nlmname.nlm+0 -** which is how to tell that there isn't one. When the check function is -** first in the linked objects, it is ambiguous. For this reason, we will -** put it inside this file after the stop function. -** -** Here we check to see if it's alright to ourselves to be unloaded. If not, -** we return a non-zero value. Right now, there isn't any reason not to allow -** it. -*/ -int _NonAppCheckUnload( void ) -{ - return 0; -} - -int GetOrSetUpData(int id, libdata_t **appData, - libthreaddata_t **threadData ) -{ - int err; - libdata_t *app_data; - libthreaddata_t *thread_data; - NXKey_t key; - NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0); - - err = 0; - thread_data = (libthreaddata_t *) NULL; - -/* -** Attempt to get our data for the application calling us. This is where we -** store whatever application-specific information we need to carry in support -** of calling applications. -*/ - app_data = (libdata_t *) get_app_data(id); - - if(!app_data) { -/* -** This application hasn't called us before; set up application AND per-thread -** data. Of course, just in case a thread from this same application is calling -** us simultaneously, we better lock our application data-creation mutex. We -** also need to recheck for data after we acquire the lock because WE might be -** that other thread that was too late to create the data and the first thread -** in will have created it. -*/ - NXLock(gLibLock); - - if(!(app_data = (libdata_t *) get_app_data(id))) { - app_data = malloc(sizeof(libdata_t)); - - if(app_data) { - memset(app_data, 0, sizeof(libdata_t)); - - app_data->tenbytes = malloc(10); - app_data->lock = NXMutexAlloc(0, 0, &liblock); - - if(!app_data->tenbytes || !app_data->lock) { - if(app_data->lock) - NXMutexFree(app_data->lock); - - free(app_data); - app_data = (libdata_t *) NULL; - err = ENOMEM; - } - - if(app_data) { -/* -** Here we burn in the application data that we were trying to get by calling -** get_app_data(). Next time we call the first function, we'll get this data -** we're just now setting. We also go on here to establish the per-thread data -** for the calling thread, something we'll have to do on each application -** thread the first time it calls us. -*/ - err = set_app_data(gLibId, app_data); - - if(err) { - free(app_data); - app_data = (libdata_t *) NULL; - err = ENOMEM; - } - else { - /* create key for thread-specific data... */ - err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key); - - if(err) /* (no more keys left?) */ - key = -1; - - app_data->perthreadkey = key; - } - } - } - } - - NXUnlock(gLibLock); - } - - if(app_data) { - key = app_data->perthreadkey; - - if(key != -1 /* couldn't create a key? no thread data */ - && !(err = NXKeyGetValue(key, (void **) &thread_data)) - && !thread_data) { -/* -** Allocate the per-thread data for the calling thread. Regardless of whether -** there was already application data or not, this may be the first call by a -** a new thread. The fact that we allocation 20 bytes on a pointer is not very -** important, this just helps to demonstrate that we can have arbitrarily -** complex per-thread data. -*/ - thread_data = malloc(sizeof(libthreaddata_t)); - - if(thread_data) { - thread_data->_errno = 0; - thread_data->twentybytes = malloc(20); - - if(!thread_data->twentybytes) { - free(thread_data); - thread_data = (libthreaddata_t *) NULL; - err = ENOMEM; - } - - if((err = NXKeySetValue(key, thread_data))) { - free(thread_data->twentybytes); - free(thread_data); - thread_data = (libthreaddata_t *) NULL; - } - } - } - } - - if(appData) - *appData = app_data; - - if(threadData) - *threadData = thread_data; - - return err; -} - -int DisposeLibraryData( void *data ) -{ - if(data) { - void *tenbytes = ((libdata_t *) data)->tenbytes; - - if(tenbytes) - free(tenbytes); - - free(data); - } - - return 0; -} - -void DisposeThreadData( void *data ) -{ - if(data) { - void *twentybytes = ((libthreaddata_t *) data)->twentybytes; - - if(twentybytes) - free(twentybytes); - - free(data); - } -} - -#else /* __NOVELL_LIBC__ */ -/* For native CLib-based NLM seems we can do a bit more simple. */ -#include - -int main ( void ) -{ - /* initialize any globals here... */ - - /* do this if any global initializing was done - SynchronizeStart(); - */ - ExitThread (TSR_THREAD, 0); - return 0; -} - -#endif /* __NOVELL_LIBC__ */ - -#else /* NETWARE */ - -#ifdef __POCC__ -# pragma warn(disable:2024) /* Disable warning #2024: Empty input file */ -#endif - -#endif /* NETWARE */ diff --git a/third_party/curl/lib/nwos.c b/third_party/curl/lib/nwos.c deleted file mode 100644 index ac365124f..000000000 --- a/third_party/curl/lib/nwos.c +++ /dev/null @@ -1,95 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifdef NETWARE /* Novell NetWare */ - -#include - -#ifdef __NOVELL_LIBC__ -/* For native LibC-based NLM we need to do nothing. */ -int netware_init ( void ) -{ - return 0; -} - -#else /* __NOVELL_LIBC__ */ - -/* For native CLib-based NLM we need to initialize the LONG namespace. */ -#include -#include -#include -#include -/* Make the CLIB Ctx stuff link */ -#include -NETDB_DEFINE_CONTEXT -/* Make the CLIB Inet stuff link */ -#include -#include -NETINET_DEFINE_CONTEXT - -int netware_init ( void ) -{ - int rc = 0; - unsigned int myHandle = GetNLMHandle(); - /* import UnAugmentAsterisk dynamically for NW4.x compatibility */ - void (*pUnAugmentAsterisk)(int) = (void(*)(int)) - ImportSymbol(myHandle, "UnAugmentAsterisk"); - /* import UseAccurateCaseForPaths dynamically for NW3.x compatibility */ - void (*pUseAccurateCaseForPaths)(int) = (void(*)(int)) - ImportSymbol(myHandle, "UseAccurateCaseForPaths"); - if(pUnAugmentAsterisk) - pUnAugmentAsterisk(1); - if(pUseAccurateCaseForPaths) - pUseAccurateCaseForPaths(1); - UnimportSymbol(myHandle, "UnAugmentAsterisk"); - UnimportSymbol(myHandle, "UseAccurateCaseForPaths"); - /* set long name space */ - if((SetCurrentNameSpace(4) == 255)) { - rc = 1; - } - if((SetTargetNameSpace(4) == 255)) { - rc = rc + 2; - } - return rc; -} - -/* dummy function to satisfy newer prelude */ -int __init_environment ( void ) -{ - return 0; -} - -/* dummy function to satisfy newer prelude */ -int __deinit_environment ( void ) -{ - return 0; -} - -#endif /* __NOVELL_LIBC__ */ - -#else /* NETWARE */ - -#ifdef __POCC__ -# pragma warn(disable:2024) /* Disable warning #2024: Empty input file */ -#endif - -#endif /* NETWARE */ diff --git a/third_party/curl/lib/openldap.c b/third_party/curl/lib/openldap.c deleted file mode 100644 index 3cb796380..000000000 --- a/third_party/curl/lib/openldap.c +++ /dev/null @@ -1,647 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, Howard Chu, - * Copyright (C) 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#if !defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP) - -/* - * Notice that USE_OPENLDAP is only a source code selection switch. When - * libcurl is built with USE_OPENLDAP defined the libcurl source code that - * gets compiled is the code from openldap.c, otherwise the code that gets - * compiled is the code from ldap.c. - * - * When USE_OPENLDAP is defined a recent version of the OpenLDAP library - * might be required for compilation and runtime. In order to use ancient - * OpenLDAP library versions, USE_OPENLDAP shall not be defined. - */ - -#include - -#include "urldata.h" -#include -#include "sendf.h" -#include "sslgen.h" -#include "transfer.h" -#include "curl_ldap.h" -#include "curl_memory.h" -#include "curl_base64.h" -#include "http_proxy.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "memdebug.h" - -#ifndef _LDAP_PVT_H -extern int ldap_pvt_url_scheme2proto(const char *); -extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, LDAP **ld); -#endif - -static CURLcode ldap_setup(struct connectdata *conn); -static CURLcode ldap_do(struct connectdata *conn, bool *done); -static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool); -static CURLcode ldap_connect(struct connectdata *conn, bool *done); -static CURLcode ldap_connecting(struct connectdata *conn, bool *done); -static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection); - -static Curl_recv ldap_recv; - -/* - * LDAP protocol handler. - */ - -const struct Curl_handler Curl_handler_ldap = { - "LDAP", /* scheme */ - ldap_setup, /* setup_connection */ - ldap_do, /* do_it */ - ldap_done, /* done */ - ZERO_NULL, /* do_more */ - ldap_connect, /* connect_it */ - ldap_connecting, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ldap_disconnect, /* disconnect */ - PORT_LDAP, /* defport */ - CURLPROTO_LDAP, /* protocol */ - PROTOPT_NONE /* flags */ -}; - -#ifdef USE_SSL -/* - * LDAPS protocol handler. - */ - -const struct Curl_handler Curl_handler_ldaps = { - "LDAPS", /* scheme */ - ldap_setup, /* setup_connection */ - ldap_do, /* do_it */ - ldap_done, /* done */ - ZERO_NULL, /* do_more */ - ldap_connect, /* connect_it */ - ldap_connecting, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ldap_disconnect, /* disconnect */ - PORT_LDAPS, /* defport */ - CURLPROTO_LDAP, /* protocol */ - PROTOPT_SSL /* flags */ -}; -#endif - -static const char *url_errs[] = { - "success", - "out of memory", - "bad parameter", - "unrecognized scheme", - "unbalanced delimiter", - "bad URL", - "bad host or port", - "bad or missing attributes", - "bad or missing scope", - "bad or missing filter", - "bad or missing extensions" -}; - -typedef struct ldapconninfo { - LDAP *ld; - Curl_recv *recv; /* for stacking SSL handler */ - Curl_send *send; - int proto; - int msgid; - bool ssldone; - bool sslinst; - bool didbind; -} ldapconninfo; - -typedef struct ldapreqinfo { - int msgid; - int nument; -} ldapreqinfo; - -static CURLcode ldap_setup(struct connectdata *conn) -{ - ldapconninfo *li; - LDAPURLDesc *lud; - struct SessionHandle *data=conn->data; - int rc, proto; - CURLcode status; - - rc = ldap_url_parse(data->change.url, &lud); - if (rc != LDAP_URL_SUCCESS) { - const char *msg = "url parsing problem"; - status = CURLE_URL_MALFORMAT; - if (rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { - if (rc == LDAP_URL_ERR_MEM) - status = CURLE_OUT_OF_MEMORY; - msg = url_errs[rc]; - } - failf(conn->data, "LDAP local: %s", msg); - return status; - } - proto = ldap_pvt_url_scheme2proto(lud->lud_scheme); - ldap_free_urldesc(lud); - - li = calloc(1, sizeof(ldapconninfo)); - li->proto = proto; - conn->proto.generic = li; - conn->bits.close = FALSE; - /* TODO: - * - provide option to choose SASL Binds instead of Simple - */ - return CURLE_OK; -} - -#ifdef USE_SSL -static Sockbuf_IO ldapsb_tls; -#endif - -static CURLcode ldap_connect(struct connectdata *conn, bool *done) -{ - ldapconninfo *li = conn->proto.generic; - struct SessionHandle *data=conn->data; - int rc, proto = LDAP_VERSION3; - char hosturl[1024], *ptr; - - strcpy(hosturl, "ldap"); - ptr = hosturl+4; - if (conn->handler->flags & PROTOPT_SSL) - *ptr++ = 's'; - snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d", - conn->host.name, conn->remote_port); - - rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld); - if (rc) { - failf(data, "LDAP local: Cannot connect to %s, %s", - hosturl, ldap_err2string(rc)); - return CURLE_COULDNT_CONNECT; - } - - ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); - - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - /* for LDAP over HTTP proxy */ - struct HTTP http_proxy; - ldapconninfo *li_save; - CURLcode result; - - /* BLOCKING */ - /* We want "seamless" LDAP operations through HTTP proxy tunnel */ - - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member - * conn->proto.http; we want LDAP through HTTP and we have to change the - * member temporarily for connecting to the HTTP proxy. After - * Curl_proxyCONNECT we have to set back the member to the original struct - * LDAP pointer - */ - li_save = data->state.proto.generic; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->state.proto.http = &http_proxy; - result = Curl_proxyCONNECT(conn, FIRSTSOCKET, - conn->host.name, conn->remote_port); - - data->state.proto.generic = li_save; - - if(CURLE_OK != result) - return result; - } - -#ifdef USE_SSL - if (conn->handler->flags & PROTOPT_SSL) { - CURLcode res; - if (data->state.used_interface == Curl_if_easy) { - res = Curl_ssl_connect(conn, FIRSTSOCKET); - if (res) - return res; - li->ssldone = TRUE; - } else { - res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); - if (res) - return res; - } - } -#endif - - if (data->state.used_interface == Curl_if_easy) - return ldap_connecting(conn, done); - - return CURLE_OK; -} - -static CURLcode ldap_connecting(struct connectdata *conn, bool *done) -{ - ldapconninfo *li = conn->proto.generic; - struct SessionHandle *data=conn->data; - LDAPMessage *result = NULL; - struct timeval tv = {0,1}, *tvp; - int rc, err; - char *info = NULL; - -#ifdef USE_SSL - if (conn->handler->flags & PROTOPT_SSL) { - /* Is the SSL handshake complete yet? */ - if (!li->ssldone) { - CURLcode res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone); - if (res || !li->ssldone) - return res; - } - /* Have we installed the libcurl SSL handlers into the sockbuf yet? */ - if (!li->sslinst) { - Sockbuf *sb; - ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb); - ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn); - li->sslinst = TRUE; - li->recv = conn->recv[FIRSTSOCKET]; - li->send = conn->send[FIRSTSOCKET]; - } - } -#endif - - if (data->state.used_interface == Curl_if_easy) - tvp = NULL; /* let ldap_result block indefinitely */ - else - tvp = &tv; - -retry: - if (!li->didbind) { - char *binddn; - struct berval passwd; - - if (conn->bits.user_passwd) { - binddn = conn->user; - passwd.bv_val = conn->passwd; - passwd.bv_len = strlen(passwd.bv_val); - } else { - binddn = NULL; - passwd.bv_val = NULL; - passwd.bv_len = 0; - } - rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd, - NULL, NULL, &li->msgid); - if (rc) - return CURLE_LDAP_CANNOT_BIND; - li->didbind = TRUE; - if (tvp) - return CURLE_OK; - } - - rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, tvp, &result); - if (rc < 0) { - failf(data, "LDAP local: bind ldap_result %s", ldap_err2string(rc)); - return CURLE_LDAP_CANNOT_BIND; - } - if (rc == 0) { - /* timed out */ - return CURLE_OK; - } - rc = ldap_parse_result(li->ld, result, &err, NULL, &info, NULL, NULL, 1); - if (rc) { - failf(data, "LDAP local: bind ldap_parse_result %s", ldap_err2string(rc)); - return CURLE_LDAP_CANNOT_BIND; - } - /* Try to fallback to LDAPv2? */ - if (err == LDAP_PROTOCOL_ERROR) { - int proto; - ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); - if (proto == LDAP_VERSION3) { - ldap_memfree(info); - proto = LDAP_VERSION2; - ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto); - li->didbind = FALSE; - goto retry; - } - } - - if (err) { - failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc), - info ? info : ""); - return CURLE_LOGIN_DENIED; - } - conn->recv[FIRSTSOCKET] = ldap_recv; - *done = TRUE; - return CURLE_OK; -} - -static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection) -{ - ldapconninfo *li = conn->proto.generic; - (void) dead_connection; - - if (li) { - if (li->ld) { - ldap_unbind_ext(li->ld, NULL, NULL); - li->ld = NULL; - } - conn->proto.generic = NULL; - free(li); - } - return CURLE_OK; -} - -static CURLcode ldap_do(struct connectdata *conn, bool *done) -{ - ldapconninfo *li = conn->proto.generic; - ldapreqinfo *lr; - CURLcode status = CURLE_OK; - int rc = 0; - LDAPURLDesc *ludp = NULL; - int msgid; - struct SessionHandle *data=conn->data; - - conn->bits.close = FALSE; - - infof(data, "LDAP local: %s\n", data->change.url); - - rc = ldap_url_parse(data->change.url, &ludp); - if (rc != LDAP_URL_SUCCESS) { - const char *msg = "url parsing problem"; - status = CURLE_URL_MALFORMAT; - if (rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { - if (rc == LDAP_URL_ERR_MEM) - status = CURLE_OUT_OF_MEMORY; - msg = url_errs[rc]; - } - failf(conn->data, "LDAP local: %s", msg); - return status; - } - - rc = ldap_search_ext(li->ld, ludp->lud_dn, ludp->lud_scope, - ludp->lud_filter, ludp->lud_attrs, 0, - NULL, NULL, NULL, 0, &msgid); - ldap_free_urldesc(ludp); - if (rc != LDAP_SUCCESS) { - failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc)); - return CURLE_LDAP_SEARCH_FAILED; - } - lr = calloc(1,sizeof(ldapreqinfo)); - lr->msgid = msgid; - data->state.proto.generic = lr; - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); - *done = TRUE; - return CURLE_OK; -} - -static CURLcode ldap_done(struct connectdata *conn, CURLcode res, - bool premature) -{ - ldapreqinfo *lr = conn->data->state.proto.generic; - (void)res; - (void)premature; - - if (lr) { - /* if there was a search in progress, abandon it */ - if (lr->msgid) { - ldapconninfo *li = conn->proto.generic; - ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL); - lr->msgid = 0; - } - conn->data->state.proto.generic = NULL; - free(lr); - } - return CURLE_OK; -} - -static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, - size_t len, CURLcode *err) -{ - ldapconninfo *li = conn->proto.generic; - struct SessionHandle *data=conn->data; - ldapreqinfo *lr = data->state.proto.generic; - int rc, ret; - LDAPMessage *result = NULL; - LDAPMessage *ent; - BerElement *ber = NULL; - struct timeval tv = {0,1}; - (void)len; - (void)buf; - (void)sockindex; - - rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &result); - if (rc < 0) { - failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc)); - *err = CURLE_RECV_ERROR; - return -1; - } - - *err = CURLE_AGAIN; - ret = -1; - - /* timed out */ - if (result == NULL) - return ret; - - for (ent = ldap_first_message(li->ld, result); ent; - ent = ldap_next_message(li->ld, ent)) { - struct berval bv, *bvals, **bvp = &bvals; - int binary = 0, msgtype; - - msgtype = ldap_msgtype(ent); - if (msgtype == LDAP_RES_SEARCH_RESULT) { - int code; - char *info = NULL; - rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0); - if (rc) { - failf(data, "LDAP local: search ldap_parse_result %s", - ldap_err2string(rc)); - *err = CURLE_LDAP_SEARCH_FAILED; - } else if (code && code != LDAP_SIZELIMIT_EXCEEDED) { - failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc), - info ? info : ""); - *err = CURLE_LDAP_SEARCH_FAILED; - } else { - /* successful */ - if (code == LDAP_SIZELIMIT_EXCEEDED) - infof(data, "There are more than %d entries\n", lr->nument); - data->req.size = data->req.bytecount; - *err = CURLE_OK; - ret = 0; - } - lr->msgid = 0; - ldap_memfree(info); - break; - } else if (msgtype != LDAP_RES_SEARCH_ENTRY) { - continue; - } - - lr->nument++; - rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv); - if(rc < 0) { - /* TODO: verify that this is really how this return code should be - handled */ - *err = CURLE_RECV_ERROR; - return -1; - } - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); - data->req.bytecount += bv.bv_len + 5; - - for (rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp); - rc == LDAP_SUCCESS; - rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) { - int i; - - if (bv.bv_val == NULL) break; - - if (bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) - binary = 1; - else - binary = 0; - - for (i=0; bvals[i].bv_val != NULL; i++) { - int binval = 0; - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1); - data->req.bytecount += bv.bv_len + 2; - - if (!binary) { - /* check for leading or trailing whitespace */ - if (ISSPACE(bvals[i].bv_val[0]) || - ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1])) { - binval = 1; - } else { - /* check for unprintable characters */ - unsigned int j; - for (j=0; jreq.bytecount += 2; - if(val_b64_sz > 0) { - Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz); - free(val_b64); - data->req.bytecount += val_b64_sz; - } - } else { - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1); - Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val, - bvals[i].bv_len); - data->req.bytecount += bvals[i].bv_len + 1; - } - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); - data->req.bytecount++; - } - ber_memfree(bvals); - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); - data->req.bytecount++; - } - Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); - data->req.bytecount++; - ber_free(ber, 0); - } - ldap_msgfree(result); - return ret; -} - -#ifdef USE_SSL -static int -ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg) -{ - sbiod->sbiod_pvt = arg; - return 0; -} - -static int -ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod) -{ - sbiod->sbiod_pvt = NULL; - return 0; -} - -/* We don't need to do anything because libcurl does it already */ -static int -ldapsb_tls_close(Sockbuf_IO_Desc *sbiod) -{ - (void)sbiod; - return 0; -} - -static int -ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) -{ - (void)arg; - if (opt == LBER_SB_OPT_DATA_READY) { - struct connectdata *conn = sbiod->sbiod_pvt; - return Curl_ssl_data_pending(conn, FIRSTSOCKET); - } - return 0; -} - -static ber_slen_t -ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) -{ - struct connectdata *conn = sbiod->sbiod_pvt; - ldapconninfo *li = conn->proto.generic; - ber_slen_t ret; - CURLcode err = CURLE_RECV_ERROR; - - ret = li->recv(conn, FIRSTSOCKET, buf, len, &err); - if (ret < 0 && err == CURLE_AGAIN) { - SET_SOCKERRNO(EWOULDBLOCK); - } - return ret; -} - -static ber_slen_t -ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) -{ - struct connectdata *conn = sbiod->sbiod_pvt; - ldapconninfo *li = conn->proto.generic; - ber_slen_t ret; - CURLcode err = CURLE_SEND_ERROR; - - ret = li->send(conn, FIRSTSOCKET, buf, len, &err); - if (ret < 0 && err == CURLE_AGAIN) { - SET_SOCKERRNO(EWOULDBLOCK); - } - return ret; -} - -static Sockbuf_IO ldapsb_tls = -{ - ldapsb_tls_setup, - ldapsb_tls_remove, - ldapsb_tls_ctrl, - ldapsb_tls_read, - ldapsb_tls_write, - ldapsb_tls_close -}; -#endif /* USE_SSL */ - -#endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */ diff --git a/third_party/curl/lib/parsedate.c b/third_party/curl/lib/parsedate.c deleted file mode 100644 index 298481701..000000000 --- a/third_party/curl/lib/parsedate.c +++ /dev/null @@ -1,542 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -/* - A brief summary of the date string formats this parser groks: - - RFC 2616 3.3.1 - - Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 - Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 - Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format - - we support dates without week day name: - - 06 Nov 1994 08:49:37 GMT - 06-Nov-94 08:49:37 GMT - Nov 6 08:49:37 1994 - - without the time zone: - - 06 Nov 1994 08:49:37 - 06-Nov-94 08:49:37 - - weird order: - - 1994 Nov 6 08:49:37 (GNU date fails) - GMT 08:49:37 06-Nov-94 Sunday - 94 6 Nov 08:49:37 (GNU date fails) - - time left out: - - 1994 Nov 6 - 06-Nov-94 - Sun Nov 6 94 - - unusual separators: - - 1994.Nov.6 - Sun/Nov/6/94/GMT - - commonly used time zone names: - - Sun, 06 Nov 1994 08:49:37 CET - 06 Nov 1994 08:49:37 EST - - time zones specified using RFC822 style: - - Sun, 12 Sep 2004 15:05:58 -0700 - Sat, 11 Sep 2004 21:32:11 +0200 - - compact numerical date strings: - - 20040912 15:05:58 -0700 - 20040911 +0200 - -*/ -#include "setup.h" -#include -#include -#include - -#ifdef HAVE_STDLIB_H -#include /* for strtol() */ -#endif - -#include -#include "rawstr.h" -#include "warnless.h" -#include "parsedate.h" - -const char * const Curl_wkday[] = -{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; -static const char * const weekday[] = -{ "Monday", "Tuesday", "Wednesday", "Thursday", - "Friday", "Saturday", "Sunday" }; -const char * const Curl_month[]= -{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - -struct tzinfo { - char name[5]; - int offset; /* +/- in minutes */ -}; - -/* Here's a bunch of frequently used time zone names. These were supported - by the old getdate parser. */ -#define tDAYZONE -60 /* offset for daylight savings time */ -static const struct tzinfo tz[]= { - {"GMT", 0}, /* Greenwich Mean */ - {"UTC", 0}, /* Universal (Coordinated) */ - {"WET", 0}, /* Western European */ - {"BST", 0 tDAYZONE}, /* British Summer */ - {"WAT", 60}, /* West Africa */ - {"AST", 240}, /* Atlantic Standard */ - {"ADT", 240 tDAYZONE}, /* Atlantic Daylight */ - {"EST", 300}, /* Eastern Standard */ - {"EDT", 300 tDAYZONE}, /* Eastern Daylight */ - {"CST", 360}, /* Central Standard */ - {"CDT", 360 tDAYZONE}, /* Central Daylight */ - {"MST", 420}, /* Mountain Standard */ - {"MDT", 420 tDAYZONE}, /* Mountain Daylight */ - {"PST", 480}, /* Pacific Standard */ - {"PDT", 480 tDAYZONE}, /* Pacific Daylight */ - {"YST", 540}, /* Yukon Standard */ - {"YDT", 540 tDAYZONE}, /* Yukon Daylight */ - {"HST", 600}, /* Hawaii Standard */ - {"HDT", 600 tDAYZONE}, /* Hawaii Daylight */ - {"CAT", 600}, /* Central Alaska */ - {"AHST", 600}, /* Alaska-Hawaii Standard */ - {"NT", 660}, /* Nome */ - {"IDLW", 720}, /* International Date Line West */ - {"CET", -60}, /* Central European */ - {"MET", -60}, /* Middle European */ - {"MEWT", -60}, /* Middle European Winter */ - {"MEST", -60 tDAYZONE}, /* Middle European Summer */ - {"CEST", -60 tDAYZONE}, /* Central European Summer */ - {"MESZ", -60 tDAYZONE}, /* Middle European Summer */ - {"FWT", -60}, /* French Winter */ - {"FST", -60 tDAYZONE}, /* French Summer */ - {"EET", -120}, /* Eastern Europe, USSR Zone 1 */ - {"WAST", -420}, /* West Australian Standard */ - {"WADT", -420 tDAYZONE}, /* West Australian Daylight */ - {"CCT", -480}, /* China Coast, USSR Zone 7 */ - {"JST", -540}, /* Japan Standard, USSR Zone 8 */ - {"EAST", -600}, /* Eastern Australian Standard */ - {"EADT", -600 tDAYZONE}, /* Eastern Australian Daylight */ - {"GST", -600}, /* Guam Standard, USSR Zone 9 */ - {"NZT", -720}, /* New Zealand */ - {"NZST", -720}, /* New Zealand Standard */ - {"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */ - {"IDLE", -720}, /* International Date Line East */ - /* Next up: Military timezone names. RFC822 allowed these, but (as noted in - RFC 1123) had their signs wrong. Here we use the correct signs to match - actual military usage. - */ - {"A", +1 * 60}, /* Alpha */ - {"B", +2 * 60}, /* Bravo */ - {"C", +3 * 60}, /* Charlie */ - {"D", +4 * 60}, /* Delta */ - {"E", +5 * 60}, /* Echo */ - {"F", +6 * 60}, /* Foxtrot */ - {"G", +7 * 60}, /* Golf */ - {"H", +8 * 60}, /* Hotel */ - {"I", +9 * 60}, /* India */ - /* "J", Juliet is not used as a timezone, to indicate the observer's local time */ - {"K", +10 * 60}, /* Kilo */ - {"L", +11 * 60}, /* Lima */ - {"M", +12 * 60}, /* Mike */ - {"N", -1 * 60}, /* November */ - {"O", -2 * 60}, /* Oscar */ - {"P", -3 * 60}, /* Papa */ - {"Q", -4 * 60}, /* Quebec */ - {"R", -5 * 60}, /* Romeo */ - {"S", -6 * 60}, /* Sierra */ - {"T", -7 * 60}, /* Tango */ - {"U", -8 * 60}, /* Uniform */ - {"V", -9 * 60}, /* Victor */ - {"W", -10 * 60}, /* Whiskey */ - {"X", -11 * 60}, /* X-ray */ - {"Y", -12 * 60}, /* Yankee */ - {"Z", 0}, /* Zulu, zero meridian, a.k.a. UTC */ -}; - -/* returns: - -1 no day - 0 monday - 6 sunday -*/ - -static int checkday(const char *check, size_t len) -{ - int i; - const char * const *what; - bool found= FALSE; - if(len > 3) - what = &weekday[0]; - else - what = &Curl_wkday[0]; - for(i=0; i<7; i++) { - if(Curl_raw_equal(check, what[0])) { - found=TRUE; - break; - } - what++; - } - return found?i:-1; -} - -static int checkmonth(const char *check) -{ - int i; - const char * const *what; - bool found= FALSE; - - what = &Curl_month[0]; - for(i=0; i<12; i++) { - if(Curl_raw_equal(check, what[0])) { - found=TRUE; - break; - } - what++; - } - return found?i:-1; /* return the offset or -1, no real offset is -1 */ -} - -/* return the time zone offset between GMT and the input one, in number - of seconds or -1 if the timezone wasn't found/legal */ - -static int checktz(const char *check) -{ - unsigned int i; - const struct tzinfo *what; - bool found= FALSE; - - what = tz; - for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) { - if(Curl_raw_equal(check, what->name)) { - found=TRUE; - break; - } - what++; - } - return found?what->offset*60:-1; -} - -static void skip(const char **date) -{ - /* skip everything that aren't letters or digits */ - while(**date && !ISALNUM(**date)) - (*date)++; -} - -enum assume { - DATE_MDAY, - DATE_YEAR, - DATE_TIME -}; - -/* this is a clone of 'struct tm' but with all fields we don't need or use - cut out */ -struct my_tm { - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - int tm_year; -}; - -/* struct tm to time since epoch in GMT time zone. - * This is similar to the standard mktime function but for GMT only, and - * doesn't suffer from the various bugs and portability problems that - * some systems' implementations have. - */ -static time_t my_timegm(struct my_tm *tm) -{ - static const int month_days_cumulative [12] = - { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; - int month, year, leap_days; - - if(tm->tm_year < 70) - /* we don't support years before 1970 as they will cause this function - to return a negative value */ - return -1; - - year = tm->tm_year + 1900; - month = tm->tm_mon; - if (month < 0) { - year += (11 - month) / 12; - month = 11 - (11 - month) % 12; - } - else if (month >= 12) { - year -= month / 12; - month = month % 12; - } - - leap_days = year - (tm->tm_mon <= 1); - leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400) - - (1969 / 4) + (1969 / 100) - (1969 / 400)); - - return ((((time_t) (year - 1970) * 365 - + leap_days + month_days_cumulative [month] + tm->tm_mday - 1) * 24 - + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec; -} - -/* - * Curl_parsedate() - * - * Returns: - * - * PARSEDATE_OK - a fine conversion - * PARSEDATE_FAIL - failed to convert - * PARSEDATE_LATER - time overflow at the far end of time_t - * PARSEDATE_SOONER - time underflow at the low end of time_t - */ - -int Curl_parsedate(const char *date, time_t *output) -{ - time_t t = 0; - int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */ - int monnum=-1; /* month of the year number, 0-11 */ - int mdaynum=-1; /* day of month, 1 - 31 */ - int hournum=-1; - int minnum=-1; - int secnum=-1; - int yearnum=-1; - int tzoff=-1; - struct my_tm tm; - enum assume dignext = DATE_MDAY; - const char *indate = date; /* save the original pointer */ - int part = 0; /* max 6 parts */ - - while(*date && (part < 6)) { - bool found=FALSE; - - skip(&date); - - if(ISALPHA(*date)) { - /* a name coming up */ - char buf[32]=""; - size_t len; - sscanf(date, "%31[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]", - buf); - len = strlen(buf); - - if(wdaynum == -1) { - wdaynum = checkday(buf, len); - if(wdaynum != -1) - found = TRUE; - } - if(!found && (monnum == -1)) { - monnum = checkmonth(buf); - if(monnum != -1) - found = TRUE; - } - - if(!found && (tzoff == -1)) { - /* this just must be a time zone string */ - tzoff = checktz(buf); - if(tzoff != -1) - found = TRUE; - } - - if(!found) - return PARSEDATE_FAIL; /* bad string */ - - date += len; - } - else if(ISDIGIT(*date)) { - /* a digit */ - int val; - char *end; - if((secnum == -1) && - (3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) { - /* time stamp! */ - date += 8; - } - else if((secnum == -1) && - (2 == sscanf(date, "%02d:%02d", &hournum, &minnum))) { - /* time stamp without seconds */ - date += 5; - secnum = 0; - } - else { - val = curlx_sltosi(strtol(date, &end, 10)); - - if((tzoff == -1) && - ((end - date) == 4) && - (val <= 1400) && - (indate< date) && - ((date[-1] == '+' || date[-1] == '-'))) { - /* four digits and a value less than or equal to 1400 (to take into - account all sorts of funny time zone diffs) and it is preceded - with a plus or minus. This is a time zone indication. 1400 is - picked since +1300 is frequently used and +1400 is mentioned as - an edge number in the document "ISO C 200X Proposal: Timezone - Functions" at http://david.tribble.com/text/c0xtimezone.html If - anyone has a more authoritative source for the exact maximum time - zone offsets, please speak up! */ - found = TRUE; - tzoff = (val/100 * 60 + val%100)*60; - - /* the + and - prefix indicates the local time compared to GMT, - this we need ther reversed math to get what we want */ - tzoff = date[-1]=='+'?-tzoff:tzoff; - } - - if(((end - date) == 8) && - (yearnum == -1) && - (monnum == -1) && - (mdaynum == -1)) { - /* 8 digits, no year, month or day yet. This is YYYYMMDD */ - found = TRUE; - yearnum = val/10000; - monnum = (val%10000)/100-1; /* month is 0 - 11 */ - mdaynum = val%100; - } - - if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) { - if((val > 0) && (val<32)) { - mdaynum = val; - found = TRUE; - } - dignext = DATE_YEAR; - } - - if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) { - yearnum = val; - found = TRUE; - if(yearnum < 1900) { - if(yearnum > 70) - yearnum += 1900; - else - yearnum += 2000; - } - if(mdaynum == -1) - dignext = DATE_MDAY; - } - - if(!found) - return PARSEDATE_FAIL; - - date = end; - } - } - - part++; - } - - if(-1 == secnum) - secnum = minnum = hournum = 0; /* no time, make it zero */ - - if((-1 == mdaynum) || - (-1 == monnum) || - (-1 == yearnum)) - /* lacks vital info, fail */ - return PARSEDATE_FAIL; - -#if SIZEOF_TIME_T < 5 - /* 32 bit time_t can only hold dates to the beginning of 2038 */ - if(yearnum > 2037) { - *output = 0x7fffffff; - return PARSEDATE_LATER; - } -#endif - - if(yearnum < 1970) { - *output = 0; - return PARSEDATE_SOONER; - } - - tm.tm_sec = secnum; - tm.tm_min = minnum; - tm.tm_hour = hournum; - tm.tm_mday = mdaynum; - tm.tm_mon = monnum; - tm.tm_year = yearnum - 1900; - - /* my_timegm() returns a time_t. time_t is often 32 bits, even on many - architectures that feature 64 bit 'long'. - - Some systems have 64 bit time_t and deal with years beyond 2038. However, - even on some of the systems with 64 bit time_t mktime() returns -1 for - dates beyond 03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06) - */ - t = my_timegm(&tm); - - /* time zone adjust (cast t to int to compare to negative one) */ - if(-1 != (int)t) { - - /* Add the time zone diff between local time zone and GMT. */ - long delta = (long)(tzoff!=-1?tzoff:0); - - if((delta>0) && (t + delta < t)) - return -1; /* time_t overflow */ - - t += delta; - } - - *output = t; - - return PARSEDATE_OK; -} - -time_t curl_getdate(const char *p, const time_t *now) -{ - time_t parsed; - int rc = Curl_parsedate(p, &parsed); - (void)now; /* legacy argument from the past that we ignore */ - - switch(rc) { - case PARSEDATE_OK: - case PARSEDATE_LATER: - case PARSEDATE_SOONER: - return parsed; - } - /* everything else is fail */ - return -1; -} - -/* - * Curl_gmtime() is a gmtime() replacement for portability. Do not use the - * gmtime_r() or gmtime() functions anywhere else but here. - * - * To make sure no such function calls slip in, we define them to cause build - * errors, which is why we use the name within parentheses in this function. - * - */ - -CURLcode Curl_gmtime(time_t intime, struct tm *store) -{ - const struct tm *tm; -#ifdef HAVE_GMTIME_R - /* thread-safe version */ - tm = (struct tm *)gmtime_r(&intime, store); -#else - tm = gmtime(&intime); - if(tm) - *store = *tm; /* copy the pointed struct to the local copy */ -#endif - - if(!tm) - return CURLE_BAD_FUNCTION_ARGUMENT; - return CURLE_OK; -} diff --git a/third_party/curl/lib/parsedate.h b/third_party/curl/lib/parsedate.h deleted file mode 100644 index 421befea0..000000000 --- a/third_party/curl/lib/parsedate.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __CURL_PARSEDATE_H -#define __CURL_PARSEDATE_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -extern const char * const Curl_wkday[7]; -extern const char * const Curl_month[12]; - -/* - * Curl_parsedate() - * - * Returns: - * - * PARSEDATE_OK - a fine conversion - * PARSEDATE_FAIL - failed to convert - * PARSEDATE_LATER - time overflow at the far end of time_t - * PARSEDATE_SOONER - time underflow at the low end of time_t - */ - -int Curl_parsedate(const char *date, time_t *output); - -#define PARSEDATE_OK 0 -#define PARSEDATE_FAIL -1 -#define PARSEDATE_LATER 1 -#define PARSEDATE_SOONER 2 - -CURLcode Curl_gmtime(time_t intime, struct tm *store); - -#endif diff --git a/third_party/curl/lib/pingpong.c b/third_party/curl/lib/pingpong.c deleted file mode 100644 index a49aad960..000000000 --- a/third_party/curl/lib/pingpong.c +++ /dev/null @@ -1,535 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * 'pingpong' is for generic back-and-forth support functions used by FTP, - * IMAP, POP3, SMTP and whatever more that likes them. - * - ***************************************************************************/ - -#include "setup.h" - -#include "urldata.h" -#include "sendf.h" -#include "select.h" -#include "progress.h" -#include "speedcheck.h" -#include "pingpong.h" -#include "multiif.h" -#include "non-ascii.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -#ifdef USE_PINGPONG - -/* Returns timeout in ms. 0 or negative number means the timeout has already - triggered */ -long Curl_pp_state_timeout(struct pingpong *pp) -{ - struct connectdata *conn = pp->conn; - struct SessionHandle *data=conn->data; - long timeout_ms; /* in milliseconds */ - long timeout2_ms; /* in milliseconds */ - long response_time= (data->set.server_response_timeout)? - data->set.server_response_timeout: pp->response_time; - - /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine - remaining time, or use pp->response because SERVER_RESPONSE_TIMEOUT is - supposed to govern the response for any given server response, not for - the time from connect to the given server response. */ - - /* Without a requested timeout, we only wait 'response_time' seconds for the - full response to arrive before we bail out */ - timeout_ms = response_time - - Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */ - - if(data->set.timeout) { - /* if timeout is requested, find out how much remaining time we have */ - timeout2_ms = data->set.timeout - /* timeout time */ - Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */ - - /* pick the lowest number */ - timeout_ms = CURLMIN(timeout_ms, timeout2_ms); - } - - return timeout_ms; -} - - -/* - * Curl_pp_multi_statemach() - * - * called repeatedly until done when the multi interface is used. - */ -CURLcode Curl_pp_multi_statemach(struct pingpong *pp) -{ - struct connectdata *conn = pp->conn; - curl_socket_t sock = conn->sock[FIRSTSOCKET]; - int rc; - struct SessionHandle *data=conn->data; - CURLcode result = CURLE_OK; - long timeout_ms = Curl_pp_state_timeout(pp); - - if(timeout_ms <= 0) { - failf(data, "server response timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */ - pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */ - 0); - - if(rc == -1) { - failf(data, "select/poll error"); - return CURLE_OUT_OF_MEMORY; - } - else if(rc != 0) - result = pp->statemach_act(conn); - - /* if rc == 0, then select() timed out */ - - return result; -} - -/* - * Curl_pp_easy_statemach() - * - * called repeatedly until done when the easy interface is used. - */ -CURLcode Curl_pp_easy_statemach(struct pingpong *pp) -{ - struct connectdata *conn = pp->conn; - curl_socket_t sock = conn->sock[FIRSTSOCKET]; - int rc; - long interval_ms; - long timeout_ms = Curl_pp_state_timeout(pp); - struct SessionHandle *data=conn->data; - CURLcode result; - - if(timeout_ms <=0 ) { - failf(data, "server response timeout"); - return CURLE_OPERATION_TIMEDOUT; /* already too little time */ - } - - interval_ms = 1000; /* use 1 second timeout intervals */ - if(timeout_ms < interval_ms) - interval_ms = timeout_ms; - - rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */ - pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */ - (int)interval_ms); - - if(Curl_pgrsUpdate(conn)) - result = CURLE_ABORTED_BY_CALLBACK; - else - result = Curl_speedcheck(data, Curl_tvnow()); - - if(result) - ; - else if(rc == -1) { - failf(data, "select/poll error"); - result = CURLE_OUT_OF_MEMORY; - } - else if(rc) - result = pp->statemach_act(conn); - - return result; -} - -/* initialize stuff to prepare for reading a fresh new response */ -void Curl_pp_init(struct pingpong *pp) -{ - struct connectdata *conn = pp->conn; - pp->nread_resp = 0; - pp->linestart_resp = conn->data->state.buffer; - pp->pending_resp = TRUE; - pp->response = Curl_tvnow(); /* start response time-out now! */ -} - - - -/*********************************************************************** - * - * Curl_pp_vsendf() - * - * Send the formated string as a command to a pingpong server. Note that - * the string should not have any CRLF appended, as this function will - * append the necessary things itself. - * - * NOTE: we build the command in a fixed-length buffer, which sets length - * restrictions on the command! - * - * made to never block - */ -CURLcode Curl_pp_vsendf(struct pingpong *pp, - const char *fmt, - va_list args) -{ - ssize_t bytes_written; -/* may still not be big enough for some krb5 tokens */ -#define SBUF_SIZE 1024 - char s[SBUF_SIZE]; - size_t write_len; - char *sptr=s; - CURLcode res = CURLE_OK; - struct connectdata *conn = pp->conn; - struct SessionHandle *data = conn->data; - -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - enum protection_level data_sec = conn->data_prot; -#endif - - vsnprintf(s, SBUF_SIZE-3, fmt, args); - - strcat(s, "\r\n"); /* append a trailing CRLF */ - - bytes_written=0; - write_len = strlen(s); - - Curl_pp_init(pp); - - res = Curl_convert_to_network(data, s, write_len); - /* Curl_convert_to_network calls failf if unsuccessful */ - if(res) - return res; - -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - conn->data_prot = PROT_CMD; -#endif - res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, - &bytes_written); -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); - conn->data_prot = data_sec; -#endif - - if(CURLE_OK != res) - return res; - - 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) { - /* the whole chunk was not sent, store the rest of the data */ - write_len -= bytes_written; - sptr += bytes_written; - pp->sendthis = malloc(write_len); - if(pp->sendthis) { - memcpy(pp->sendthis, sptr, write_len); - pp->sendsize = pp->sendleft = write_len; - } - else { - failf(data, "out of memory"); - res = CURLE_OUT_OF_MEMORY; - } - } - else - pp->response = Curl_tvnow(); - - return res; -} - - -/*********************************************************************** - * - * Curl_pp_sendf() - * - * Send the formated string as a command to a pingpong server. Note that - * the string should not have any CRLF appended, as this function will - * append the necessary things itself. - * - * NOTE: we build the command in a fixed-length buffer, which sets length - * restrictions on the command! - * - * made to never block - */ -CURLcode Curl_pp_sendf(struct pingpong *pp, - const char *fmt, ...) -{ - CURLcode res; - va_list ap; - va_start(ap, fmt); - - res = Curl_pp_vsendf(pp, fmt, ap); - - va_end(ap); - - return res; -} - -/* - * Curl_pp_readresp() - * - * Reads a piece of a server response. - */ -CURLcode Curl_pp_readresp(curl_socket_t sockfd, - struct pingpong *pp, - int *code, /* return the server code if done */ - size_t *size) /* size of the response */ -{ - ssize_t perline; /* count bytes per line */ - bool keepon=TRUE; - ssize_t gotbytes; - char *ptr; - struct connectdata *conn = pp->conn; - struct SessionHandle *data = conn->data; - char * const buf = data->state.buffer; - CURLcode result = CURLE_OK; - - *code = 0; /* 0 for errors or not done */ - *size = 0; - - ptr=buf + pp->nread_resp; - - /* number of bytes in the current line, so far */ - perline = (ssize_t)(ptr-pp->linestart_resp); - - keepon=TRUE; - - while((pp->nread_respcache) { - /* we had data in the "cache", copy that instead of doing an actual - * read - * - * ftp->cache_size is cast to int here. This should be safe, - * because it would have been populated with something of size - * int to begin with, even though its datatype may be larger - * than an int. - */ - DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1)); - memcpy(ptr, pp->cache, pp->cache_size); - gotbytes = (ssize_t)pp->cache_size; - free(pp->cache); /* free the cache */ - pp->cache = NULL; /* clear the pointer */ - pp->cache_size = 0; /* zero the size just in case */ - } - else { - int res; -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - enum protection_level prot = conn->data_prot; - conn->data_prot = PROT_CLEAR; -#endif - DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1)); - res = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp, - &gotbytes); -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST); - conn->data_prot = prot; -#endif - if(res == CURLE_AGAIN) - return CURLE_OK; /* return */ - - if((res == CURLE_OK) && (gotbytes > 0)) - /* convert from the network encoding */ - res = Curl_convert_from_network(data, ptr, gotbytes); - /* Curl_convert_from_network calls failf if unsuccessful */ - - if(CURLE_OK != res) { - result = (CURLcode)res; /* Set outer result variable to this error. */ - keepon = FALSE; - } - } - - if(!keepon) - ; - else if(gotbytes <= 0) { - keepon = FALSE; - result = CURLE_RECV_ERROR; - failf(data, "response reading failed"); - } - else { - /* we got a whole chunk of data, which can be anything from one - * byte to a set of lines and possible just a piece of the last - * line */ - ssize_t i; - ssize_t clipamount = 0; - bool restart = FALSE; - - data->req.headerbytecount += (long)gotbytes; - - pp->nread_resp += gotbytes; - for(i = 0; i < gotbytes; ptr++, i++) { - perline++; - if(*ptr=='\n') { - /* a newline is CRLF in ftp-talk, so the CR is ignored as - the line isn't really terminated until the LF comes */ - - /* output debug output if that is requested */ -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - if(!conn->sec_complete) -#endif - if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, - pp->linestart_resp, (size_t)perline, conn); - - /* - * We pass all response-lines to the callback function registered - * for "headers". The response lines can be seen as a kind of - * headers. - */ - result = Curl_client_write(conn, CLIENTWRITE_HEADER, - pp->linestart_resp, perline); - if(result) - return result; - - if(pp->endofresp(pp, code)) { - /* This is the end of the last line, copy the last line to the - start of the buffer and zero terminate, for old times sake (and - krb4)! */ - char *meow; - int n; - for(meow=pp->linestart_resp, n=0; meowlinestart_resp = ptr+1; /* advance pointer */ - i++; /* skip this before getting out */ - - *size = pp->nread_resp; /* size of the response */ - pp->nread_resp = 0; /* restart */ - break; - } - perline=0; /* line starts over here */ - pp->linestart_resp = ptr+1; - } - } - - if(!keepon && (i != gotbytes)) { - /* We found the end of the response lines, but we didn't parse the - full chunk of data we have read from the server. We therefore need - to store the rest of the data to be checked on the next invoke as - it may actually contain another end of response already! */ - clipamount = gotbytes - i; - restart = TRUE; - } - else if(keepon) { - - if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) { - /* We got an excessive line without newlines and we need to deal - with it. We keep the first bytes of the line then we throw - away the rest. */ - infof(data, "Excessive server response line length received, %zd bytes." - " Stripping\n", gotbytes); - restart = TRUE; - - /* we keep 40 bytes since all our pingpong protocols are only - interested in the first piece */ - clipamount = 40; - } - else if(pp->nread_resp > BUFSIZE/2) { - /* We got a large chunk of data and there's potentially still trailing - data to take care of, so we put any such part in the "cache", clear - the buffer to make space and restart. */ - clipamount = perline; - restart = TRUE; - } - } - else if(i == gotbytes) - restart = TRUE; - - if(clipamount) { - pp->cache_size = clipamount; - pp->cache = malloc(pp->cache_size); - if(pp->cache) - memcpy(pp->cache, pp->linestart_resp, pp->cache_size); - else - return CURLE_OUT_OF_MEMORY; - } - if(restart) { - /* now reset a few variables to start over nicely from the start of - the big buffer */ - pp->nread_resp = 0; /* start over from scratch in the buffer */ - ptr = pp->linestart_resp = buf; - perline = 0; - } - - } /* there was data */ - - } /* while there's buffer left and loop is requested */ - - pp->pending_resp = FALSE; - - return result; -} - -int Curl_pp_getsock(struct pingpong *pp, - curl_socket_t *socks, - int numsocks) -{ - struct connectdata *conn = pp->conn; - - if(!numsocks) - return GETSOCK_BLANK; - - socks[0] = conn->sock[FIRSTSOCKET]; - - if(pp->sendleft) { - /* write mode */ - return GETSOCK_WRITESOCK(0); - } - - /* read mode */ - return GETSOCK_READSOCK(0); -} - -CURLcode Curl_pp_flushsend(struct pingpong *pp) -{ - /* we have a piece of a command still left to send */ - struct connectdata *conn = pp->conn; - ssize_t written; - CURLcode result = CURLE_OK; - curl_socket_t sock = conn->sock[FIRSTSOCKET]; - - result = Curl_write(conn, sock, pp->sendthis + pp->sendsize - - pp->sendleft, pp->sendleft, &written); - if(result) - return result; - - if(written != (ssize_t)pp->sendleft) { - /* only a fraction was sent */ - pp->sendleft -= written; - } - else { - free(pp->sendthis); - pp->sendthis=NULL; - pp->sendleft = pp->sendsize = 0; - pp->response = Curl_tvnow(); - } - return CURLE_OK; -} - -CURLcode Curl_pp_disconnect(struct pingpong *pp) -{ - if(pp->cache) { - free(pp->cache); - pp->cache = NULL; - } - return CURLE_OK; -} - - - -#endif diff --git a/third_party/curl/lib/pingpong.h b/third_party/curl/lib/pingpong.h deleted file mode 100644 index cbbff8f3e..000000000 --- a/third_party/curl/lib/pingpong.h +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef __PINGPONG_H -#define __PINGPONG_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 - -#include "setup.h" - -#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_FTP) || \ - !defined(CURL_DISABLE_POP3) || !defined(CURL_DISABLE_SMTP) -#define USE_PINGPONG -#endif - -/* forward-declaration, this is defined in urldata.h */ -struct connectdata; - -/* - * 'pingpong' is the generic struct used for protocols doing server<->client - * conversations in a back-and-forth style such as FTP, IMAP, POP3, SMTP etc. - * - * It holds response cache and non-blocking sending data. - */ -struct pingpong { - char *cache; /* data cache between getresponse()-calls */ - size_t cache_size; /* size of cache in bytes */ - size_t nread_resp; /* number of bytes currently read of a server response */ - char *linestart_resp; /* line start pointer for the server response - reader function */ - bool pending_resp; /* set TRUE when a server response is pending or in - progress, and is cleared once the last response is - read */ - char *sendthis; /* allocated pointer to a buffer that is to be sent to the - server */ - size_t sendleft; /* number of bytes left to send from the sendthis buffer */ - size_t sendsize; /* total size of the sendthis buffer */ - struct timeval response; /* set to Curl_tvnow() when a command has been sent - off, used to time-out response reading */ - long response_time; /* When no timeout is given, this is the amount of - milliseconds we await for a server response. */ - - struct connectdata *conn; /* points to the connectdata struct that this - belongs to */ - - /* Function pointers the protocols MUST implement and provide for the - pingpong layer to function */ - - CURLcode (*statemach_act)(struct connectdata *conn); - - int (*endofresp)(struct pingpong *pp, int *code); -}; - -/* - * Curl_pp_multi_statemach() - * - * called repeatedly until done when the multi interface is used. - */ -CURLcode Curl_pp_multi_statemach(struct pingpong *pp); - -/* - * Curl_pp_easy_statemach() - * - * called repeatedly until done when the easy interface is used. - */ -CURLcode Curl_pp_easy_statemach(struct pingpong *pp); - - -/* initialize stuff to prepare for reading a fresh new response */ -void Curl_pp_init(struct pingpong *pp); - -/* Returns timeout in ms. 0 or negative number means the timeout has already - triggered */ -long Curl_pp_state_timeout(struct pingpong *pp); - - -/*********************************************************************** - * - * Curl_pp_sendf() - * - * Send the formated string as a command to a pingpong server. Note that - * the string should not have any CRLF appended, as this function will - * append the necessary things itself. - * - * NOTE: we build the command in a fixed-length buffer, which sets length - * restrictions on the command! - * - * made to never block - */ -CURLcode Curl_pp_sendf(struct pingpong *pp, - const char *fmt, ...); - -/*********************************************************************** - * - * Curl_pp_vsendf() - * - * Send the formated string as a command to a pingpong server. Note that - * the string should not have any CRLF appended, as this function will - * append the necessary things itself. - * - * NOTE: we build the command in a fixed-length buffer, which sets length - * restrictions on the command! - * - * made to never block - */ -CURLcode Curl_pp_vsendf(struct pingpong *pp, - const char *fmt, - va_list args); - -/* - * Curl_pp_readresp() - * - * Reads a piece of a server response. - */ -CURLcode Curl_pp_readresp(curl_socket_t sockfd, - struct pingpong *pp, - int *code, /* return the server code if done */ - size_t *size); /* size of the response */ - - -CURLcode Curl_pp_flushsend(struct pingpong *pp); - -/* call this when a pingpong connection is disconnected */ -CURLcode Curl_pp_disconnect(struct pingpong *pp); - -int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks, - int numsocks); - -#endif /* __PINGPONG_H */ diff --git a/third_party/curl/lib/polarssl.c b/third_party/curl/lib/polarssl.c deleted file mode 100644 index 51e35db87..000000000 --- a/third_party/curl/lib/polarssl.c +++ /dev/null @@ -1,378 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, 2011, Hoi-Ho Chan, - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Source file for all PolarSSL-specific code for the TLS/SSL layer. No code - * but sslgen.c should ever call or use these functions. - * - */ - -#include "setup.h" -#ifdef USE_POLARSSL - -#include -#include -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "urldata.h" -#include "sendf.h" -#include "inet_pton.h" -#include "polarssl.h" -#include "sslgen.h" -#include "parsedate.h" -#include "connect.h" /* for the connect timeout */ -#include "select.h" -#include "rawstr.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* Define this to enable lots of debugging for PolarSSL */ -#undef POLARSSL_DEBUG - -#ifdef POLARSSL_DEBUG -static void polarssl_debug(void *context, int level, char *line) -{ - struct SessionHandle *data = NULL; - - if(!context) - return; - - data = (struct SessionHandle *)context; - - infof(data, "%s", line); -} -#else -#endif - -static Curl_recv polarssl_recv; -static Curl_send polarssl_send; - -/* - * This function loads all the client/CA certificates and CRLs. Setup the TLS - * layer and do all necessary magic. - */ -CURLcode -Curl_polarssl_connect(struct connectdata *conn, - int sockindex) -{ - struct SessionHandle *data = conn->data; - bool sni = TRUE; /* default is SNI enabled */ - int ret = -1; -#ifdef ENABLE_IPV6 - struct in6_addr addr; -#else - struct in_addr addr; -#endif - void *old_session = NULL; - size_t old_session_size = 0; - char buffer[1024]; - - if(conn->ssl[sockindex].state == ssl_connection_complete) - return CURLE_OK; - - /* PolarSSL only supports SSLv3 and TLSv1 */ - if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { - failf(data, "PolarSSL does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) { - sni = FALSE; /* SSLv3 has no SNI */ - } - - havege_init(&conn->ssl[sockindex].hs); - - /* Load the trusted CA */ - memset(&conn->ssl[sockindex].cacert, 0, sizeof(x509_cert)); - - if(data->set.str[STRING_SSL_CAFILE]) { - ret = x509parse_crtfile(&conn->ssl[sockindex].cacert, - data->set.str[STRING_SSL_CAFILE]); - - if(ret) { - failf(data, "Error reading ca cert file %s: -0x%04X", - data->set.str[STRING_SSL_CAFILE], -ret); - - if(data->set.ssl.verifypeer) - return CURLE_SSL_CACERT_BADFILE; - } - } - - /* Load the client certificate */ - memset(&conn->ssl[sockindex].clicert, 0, sizeof(x509_cert)); - - if(data->set.str[STRING_CERT]) { - ret = x509parse_crtfile(&conn->ssl[sockindex].clicert, - data->set.str[STRING_CERT]); - - if(ret) { - failf(data, "Error reading client cert file %s: -0x%04X", - data->set.str[STRING_CERT], -ret); - return CURLE_SSL_CERTPROBLEM; - } - } - - /* Load the client private key */ - if(data->set.str[STRING_KEY]) { - ret = x509parse_keyfile(&conn->ssl[sockindex].rsa, - data->set.str[STRING_KEY], - data->set.str[STRING_KEY_PASSWD]); - - if(ret) { - failf(data, "Error reading private key %s: -0x%04X", - data->set.str[STRING_KEY], -ret); - return CURLE_SSL_CERTPROBLEM; - } - } - - /* Load the CRL */ - memset(&conn->ssl[sockindex].crl, 0, sizeof(x509_crl)); - - if(data->set.str[STRING_SSL_CRLFILE]) { - ret = x509parse_crlfile(&conn->ssl[sockindex].crl, - data->set.str[STRING_SSL_CRLFILE]); - - if(ret) { - failf(data, "Error reading CRL file %s: -0x%04X", - data->set.str[STRING_SSL_CRLFILE], -ret); - return CURLE_SSL_CRL_BADFILE; - } - } - - infof(data, "PolarSSL: Connected to %s:%d\n", - conn->host.name, conn->remote_port); - - havege_init(&conn->ssl[sockindex].hs); - - if(ssl_init(&conn->ssl[sockindex].ssl)) { - failf(data, "PolarSSL: ssl_init failed"); - return CURLE_SSL_CONNECT_ERROR; - } - - ssl_set_endpoint(&conn->ssl[sockindex].ssl, SSL_IS_CLIENT); - ssl_set_authmode(&conn->ssl[sockindex].ssl, SSL_VERIFY_OPTIONAL); - - ssl_set_rng(&conn->ssl[sockindex].ssl, havege_rand, - &conn->ssl[sockindex].hs); - ssl_set_bio(&conn->ssl[sockindex].ssl, - net_recv, &conn->sock[sockindex], - net_send, &conn->sock[sockindex]); - - ssl_set_ciphers(&conn->ssl[sockindex].ssl, ssl_default_ciphers); - - if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) { - memcpy(&conn->ssl[sockindex].ssn, old_session, old_session_size); - infof(data, "PolarSSL re-using session\n"); - } - - ssl_set_session(&conn->ssl[sockindex].ssl, 1, 600, - &conn->ssl[sockindex].ssn); - - ssl_set_ca_chain(&conn->ssl[sockindex].ssl, - &conn->ssl[sockindex].cacert, - &conn->ssl[sockindex].crl, - conn->host.name); - - ssl_set_own_cert(&conn->ssl[sockindex].ssl, - &conn->ssl[sockindex].clicert, &conn->ssl[sockindex].rsa); - - if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) && -#ifdef ENABLE_IPV6 - !Curl_inet_pton(AF_INET6, conn->host.name, &addr) && -#endif - sni && ssl_set_hostname(&conn->ssl[sockindex].ssl, conn->host.name)) { - infof(data, "WARNING: failed to configure " - "server name indication (SNI) TLS extension\n"); - } - - infof(data, "PolarSSL: performing SSL/TLS handshake...\n"); - -#ifdef POLARSSL_DEBUG - ssl_set_dbg(&conn->ssl[sockindex].ssl, polarssl_debug, data); -#endif - - for(;;) { - if (!(ret = ssl_handshake(&conn->ssl[sockindex].ssl))) { - break; - } else if(ret != POLARSSL_ERR_NET_TRY_AGAIN) { - failf(data, "ssl_handshake returned -0x%04X", -ret); - return CURLE_SSL_CONNECT_ERROR; - } else { - /* wait for data from server... */ - long timeout_ms = Curl_timeleft(data, NULL, TRUE); - - if(timeout_ms < 0) { - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - switch(Curl_socket_ready(conn->sock[sockindex], - CURL_SOCKET_BAD, timeout_ms)) { - case 0: - failf(data, "SSL handshake timeout"); - return CURLE_OPERATION_TIMEDOUT; - break; - case CURL_CSELECT_IN: - continue; - break; - default: - return CURLE_SSL_CONNECT_ERROR; - break; - } - } - } - - infof(data, "PolarSSL: Handshake complete, cipher is %s\n", - ssl_get_cipher(&conn->ssl[sockindex].ssl)); - - ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl); - - if(ret && data->set.ssl.verifypeer) { - if(ret & BADCERT_EXPIRED) - failf(data, "Cert verify failed: BADCERT_EXPIRED\n"); - - if(ret & BADCERT_REVOKED) - failf(data, "Cert verify failed: BADCERT_REVOKED"); - - if(ret & BADCERT_CN_MISMATCH) - failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); - - if(ret & BADCERT_NOT_TRUSTED) - failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); - - return CURLE_SSL_CACERT; - } - - if(conn->ssl[sockindex].ssl.peer_cert) { - /* If the session was resumed, there will be no peer certs */ - memset(buffer, 0, sizeof(buffer)); - - if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ", - conn->ssl[sockindex].ssl.peer_cert) != -1) - infof(data, "Dumping cert info:\n%s\n", buffer); - } - - conn->ssl[sockindex].state = ssl_connection_complete; - conn->recv[sockindex] = polarssl_recv; - conn->send[sockindex] = polarssl_send; - - /* Save the current session data for possible re-use */ - { - void *new_session = malloc(sizeof(conn->ssl[sockindex].ssn)); - - if(new_session) { - memcpy(new_session, &conn->ssl[sockindex].ssn, - sizeof(conn->ssl[sockindex].ssn)); - - if(old_session) - Curl_ssl_delsessionid(conn, old_session); - - return Curl_ssl_addsessionid(conn, new_session, - sizeof(conn->ssl[sockindex].ssn)); - } - } - - return CURLE_OK; -} - -static ssize_t polarssl_send(struct connectdata *conn, - int sockindex, - const void *mem, - size_t len, - CURLcode *curlcode) -{ - int ret = -1; - - ret = ssl_write(&conn->ssl[sockindex].ssl, - (unsigned char *)mem, len); - - if(ret < 0) { - *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? - CURLE_AGAIN : CURLE_SEND_ERROR; - ret = -1; - } - - return ret; -} - -void Curl_polarssl_close_all(struct SessionHandle *data) -{ - (void)data; -} - -void Curl_polarssl_close(struct connectdata *conn, int sockindex) -{ - rsa_free(&conn->ssl[sockindex].rsa); - x509_free(&conn->ssl[sockindex].clicert); - x509_free(&conn->ssl[sockindex].cacert); - x509_crl_free(&conn->ssl[sockindex].crl); - ssl_free(&conn->ssl[sockindex].ssl); -} - -static ssize_t polarssl_recv(struct connectdata *conn, - int num, - char *buf, - size_t buffersize, - CURLcode *curlcode) -{ - int ret = -1; - ssize_t len = -1; - - memset(buf, 0, buffersize); - ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize); - - if(ret <= 0) { - if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) - return 0; - - *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? - CURLE_AGAIN : CURLE_RECV_ERROR; - return -1; - } - - len = ret; - - return len; -} - -void Curl_polarssl_session_free(void *ptr) -{ - free(ptr); -} - -size_t Curl_polarssl_version(char *buffer, size_t size) -{ - return snprintf(buffer, size, "PolarSSL"); -} - -#endif diff --git a/third_party/curl/lib/polarssl.h b/third_party/curl/lib/polarssl.h deleted file mode 100644 index 9e983aac9..000000000 --- a/third_party/curl/lib/polarssl.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef HEADER_CURL_POLARSSL_H -#define HEADER_CURL_POLARSSL_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, Hoi-Ho Chan, - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * $Id: polarssl.h,v 1.10 2009-02-12 20:48:43 danf Exp $ - ***************************************************************************/ - -#ifdef USE_POLARSSL - -CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex); - -/* tell PolarSSL to close down all open information regarding connections (and - thus session ID caching etc) */ -void Curl_polarssl_close_all(struct SessionHandle *data); - - /* close a SSL connection */ -void Curl_polarssl_close(struct connectdata *conn, int sockindex); - -void Curl_polarssl_session_free(void *ptr); -size_t Curl_polarssl_version(char *buffer, size_t size); -int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex); - -/* API setup for PolarSSL */ -#define curlssl_init() (1) -#define curlssl_cleanup() -#define curlssl_connect Curl_polarssl_connect -#define curlssl_session_free(x) Curl_polarssl_session_free(x) -#define curlssl_close_all Curl_polarssl_close_all -#define curlssl_close Curl_polarssl_close -#define curlssl_shutdown(x,y) 0 -#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN) -#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN) -#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL) -#define curlssl_version Curl_polarssl_version -#define curlssl_check_cxn(x) (x=x, -1) -#define curlssl_data_pending(x,y) (x=x, y=y, 0) - -#endif /* USE_POLARSSL */ -#endif /* HEADER_CURL_POLARSSL_H */ diff --git a/third_party/curl/lib/pop3.c b/third_party/curl/lib/pop3.c deleted file mode 100644 index d0aba352b..000000000 --- a/third_party/curl/lib/pop3.c +++ /dev/null @@ -1,1063 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * RFC1939 POP3 protocol - * RFC2384 POP URL Scheme - * RFC2595 Using TLS with IMAP, POP3 and ACAP - * - ***************************************************************************/ - -#include "setup.h" - -#ifndef CURL_DISABLE_POP3 -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_UTSNAME_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef __VMS -#include -#include -#endif - -#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) -#undef in_addr_t -#define in_addr_t unsigned long -#endif - -#include -#include "urldata.h" -#include "sendf.h" -#include "if2ip.h" -#include "hostip.h" -#include "progress.h" -#include "transfer.h" -#include "escape.h" -#include "http.h" /* for HTTP proxy tunnel stuff */ -#include "socks.h" -#include "pop3.h" - -#include "strtoofft.h" -#include "strequal.h" -#include "sslgen.h" -#include "connect.h" -#include "strerror.h" -#include "select.h" -#include "multiif.h" -#include "url.h" -#include "rawstr.h" -#include "strtoofft.h" -#include "http_proxy.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* Local API functions */ -static CURLcode pop3_parse_url_path(struct connectdata *conn); -static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done); -static CURLcode pop3_do(struct connectdata *conn, bool *done); -static CURLcode pop3_done(struct connectdata *conn, - CURLcode, bool premature); -static CURLcode pop3_connect(struct connectdata *conn, bool *done); -static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection); -static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done); -static int pop3_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks); -static CURLcode pop3_doing(struct connectdata *conn, - bool *dophase_done); -static CURLcode pop3_setup_connection(struct connectdata * conn); - -/* - * POP3 protocol handler. - */ - -const struct Curl_handler Curl_handler_pop3 = { - "POP3", /* scheme */ - pop3_setup_connection, /* setup_connection */ - pop3_do, /* do_it */ - pop3_done, /* done */ - ZERO_NULL, /* do_more */ - pop3_connect, /* connect_it */ - pop3_multi_statemach, /* connecting */ - pop3_doing, /* doing */ - pop3_getsock, /* proto_getsock */ - pop3_getsock, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - pop3_disconnect, /* disconnect */ - PORT_POP3, /* defport */ - CURLPROTO_POP3, /* protocol */ - PROTOPT_CLOSEACTION /* flags */ -}; - - -#ifdef USE_SSL -/* - * POP3S protocol handler. - */ - -const struct Curl_handler Curl_handler_pop3s = { - "POP3S", /* scheme */ - pop3_setup_connection, /* setup_connection */ - pop3_do, /* do_it */ - pop3_done, /* done */ - ZERO_NULL, /* do_more */ - pop3_connect, /* connect_it */ - pop3_multi_statemach, /* connecting */ - pop3_doing, /* doing */ - pop3_getsock, /* proto_getsock */ - pop3_getsock, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - pop3_disconnect, /* disconnect */ - PORT_POP3S, /* defport */ - CURLPROTO_POP3 | CURLPROTO_POP3S, /* protocol */ - PROTOPT_CLOSEACTION | PROTOPT_SSL /* flags */ -}; -#endif - -#ifndef CURL_DISABLE_HTTP -/* - * HTTP-proxyed POP3 protocol handler. - */ - -static const struct Curl_handler Curl_handler_pop3_proxy = { - "POP3", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_POP3, /* defport */ - CURLPROTO_HTTP, /* protocol */ - PROTOPT_NONE /* flags */ -}; - - -#ifdef USE_SSL -/* - * HTTP-proxyed POP3S protocol handler. - */ - -static const struct Curl_handler Curl_handler_pop3s_proxy = { - "POP3S", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_POP3S, /* defport */ - CURLPROTO_HTTP, /* protocol */ - PROTOPT_NONE /* flags */ -}; -#endif -#endif - - -/* function that checks for a pop3 status code at the start of the given - string */ -static int pop3_endofresp(struct pingpong *pp, - int *resp) -{ - char *line = pp->linestart_resp; - size_t len = pp->nread_resp; - - if( ((len >= 3) && !memcmp("+OK", line, 3)) || - ((len >= 4) && !memcmp("-ERR", line, 4)) ) { - *resp=line[1]; /* O or E */ - return TRUE; - } - - return FALSE; /* nothing for us */ -} - -/* This is the ONLY way to change POP3 state! */ -static void state(struct connectdata *conn, - pop3state newstate) -{ -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - /* for debug purposes */ - static const char * const names[]={ - "STOP", - "SERVERGREET", - "USER", - "PASS", - "STARTTLS", - "LIST", - "LIST_SINGLE", - "RETR", - "QUIT", - /* LAST */ - }; -#endif - struct pop3_conn *pop3c = &conn->proto.pop3c; -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - if(pop3c->state != newstate) - infof(conn->data, "POP3 %p state change from %s to %s\n", - pop3c, names[pop3c->state], names[newstate]); -#endif - pop3c->state = newstate; -} - -static CURLcode pop3_state_user(struct connectdata *conn) -{ - CURLcode result; - struct FTP *pop3 = conn->data->state.proto.pop3; - - /* send USER */ - result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s", - pop3->user?pop3->user:""); - if(result) - return result; - - state(conn, POP3_USER); - - return CURLE_OK; -} - -/* For the POP3 "protocol connect" and "doing" phases only */ -static int pop3_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - return Curl_pp_getsock(&conn->proto.pop3c.pp, socks, numsocks); -} - -#ifdef USE_SSL -static void pop3_to_pop3s(struct connectdata *conn) -{ - conn->handler = &Curl_handler_pop3s; -} -#else -#define pop3_to_pop3s(x) -#endif - -/* for STARTTLS responses */ -static CURLcode pop3_state_starttls_resp(struct connectdata *conn, - int pop3code, - pop3state instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - (void)instate; /* no use for this yet */ - - if(pop3code != 'O') { - failf(data, "STARTTLS denied. %c", pop3code); - result = CURLE_LOGIN_DENIED; - state(conn, POP3_STOP); - } - else { - /* Curl_ssl_connect is BLOCKING */ - result = Curl_ssl_connect(conn, FIRSTSOCKET); - if(CURLE_OK == result) { - pop3_to_pop3s(conn); - result = pop3_state_user(conn); - } - else { - state(conn, POP3_STOP); - } - } - return result; -} - -/* for USER responses */ -static CURLcode pop3_state_user_resp(struct connectdata *conn, - int pop3code, - pop3state instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - struct FTP *pop3 = data->state.proto.pop3; - - (void)instate; /* no use for this yet */ - - if(pop3code != 'O') { - failf(data, "Access denied. %c", pop3code); - result = CURLE_LOGIN_DENIED; - } - else - /* send PASS */ - result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s", - pop3->passwd?pop3->passwd:""); - if(result) - return result; - - state(conn, POP3_PASS); - return result; -} - -/* for PASS responses */ -static CURLcode pop3_state_pass_resp(struct connectdata *conn, - int pop3code, - pop3state instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - (void)instate; /* no use for this yet */ - - if(pop3code != 'O') { - failf(data, "Access denied. %c", pop3code); - result = CURLE_LOGIN_DENIED; - } - - state(conn, POP3_STOP); - return result; -} - -/* for the retr response */ -static CURLcode pop3_state_retr_resp(struct connectdata *conn, - int pop3code, - pop3state instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - struct FTP *pop3 = data->state.proto.pop3; - struct pop3_conn *pop3c = &conn->proto.pop3c; - struct pingpong *pp = &pop3c->pp; - - (void)instate; /* no use for this yet */ - - if('O' != pop3code) { - state(conn, POP3_STOP); - return CURLE_RECV_ERROR; - } - - /* POP3 download */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, - pop3->bytecountp, -1, NULL); /* no upload here */ - - if(pp->cache) { - /* At this point there is a bunch of data in the header "cache" that is - actually body content, send it as body and then skip it. Do note - that there may even be additional "headers" after the body. */ - - /* we may get the EOB already here! */ - result = Curl_pop3_write(conn, pp->cache, pp->cache_size); - if(result) - return result; - - /* cache is drained */ - free(pp->cache); - pp->cache = NULL; - pp->cache_size = 0; - } - - state(conn, POP3_STOP); - return result; -} - - -/* for the list response */ -static CURLcode pop3_state_list_resp(struct connectdata *conn, - int pop3code, - pop3state instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - struct FTP *pop3 = data->state.proto.pop3; - struct pop3_conn *pop3c = &conn->proto.pop3c; - struct pingpong *pp = &pop3c->pp; - - (void)instate; /* no use for this yet */ - - if('O' != pop3code) { - state(conn, POP3_STOP); - return CURLE_RECV_ERROR; - } - - /* POP3 download */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, pop3->bytecountp, - -1, NULL); /* no upload here */ - - if(pp->cache) { - /* cache holds the email ID listing */ - - /* we may get the EOB already here! */ - result = Curl_pop3_write(conn, pp->cache, pp->cache_size); - if(result) - return result; - - /* cache is drained */ - free(pp->cache); - pp->cache = NULL; - pp->cache_size = 0; - } - - state(conn, POP3_STOP); - return result; -} - -/* for LIST response with a given message */ -static CURLcode pop3_state_list_single_resp(struct connectdata *conn, - int pop3code, - pop3state instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - (void)instate; /* no use for this yet */ - - if(pop3code != 'O') { - failf(data, "Invalid message. %c", pop3code); - result = CURLE_REMOTE_FILE_NOT_FOUND; - } - - state(conn, POP3_STOP); - return result; -} - -/* start the DO phase for RETR */ -static CURLcode pop3_retr(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct pop3_conn *pop3c = &conn->proto.pop3c; - - result = Curl_pp_sendf(&conn->proto.pop3c.pp, "RETR %s", pop3c->mailbox); - if(result) - return result; - - state(conn, POP3_RETR); - return result; -} - -/* start the DO phase for LIST */ -static CURLcode pop3_list(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct pop3_conn *pop3c = &conn->proto.pop3c; - - result = Curl_pp_sendf(&conn->proto.pop3c.pp, "LIST %s", pop3c->mailbox); - if(result) - return result; - - if (strlen(pop3c->mailbox)) - state(conn, POP3_LIST_SINGLE); - else - state(conn, POP3_LIST); - return result; -} - -static CURLcode pop3_statemach_act(struct connectdata *conn) -{ - CURLcode result; - curl_socket_t sock = conn->sock[FIRSTSOCKET]; - struct SessionHandle *data=conn->data; - int pop3code; - struct pop3_conn *pop3c = &conn->proto.pop3c; - struct pingpong *pp = &pop3c->pp; - size_t nread = 0; - - if(pp->sendleft) - return Curl_pp_flushsend(pp); - - /* we read a piece of response */ - result = Curl_pp_readresp(sock, pp, &pop3code, &nread); - if(result) - return result; - - if(pop3code) { - /* we have now received a full POP3 server response */ - switch(pop3c->state) { - case POP3_SERVERGREET: - if(pop3code != 'O') { - failf(data, "Got unexpected pop3-server response"); - return CURLE_FTP_WEIRD_SERVER_REPLY; - } - - if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) { - /* We don't have a SSL/TLS connection yet, but SSL is requested. Switch - to TLS connection now */ - result = Curl_pp_sendf(&pop3c->pp, "STLS"); - state(conn, POP3_STARTTLS); - } - else - result = pop3_state_user(conn); - if(result) - return result; - break; - - case POP3_USER: - result = pop3_state_user_resp(conn, pop3code, pop3c->state); - break; - - case POP3_PASS: - result = pop3_state_pass_resp(conn, pop3code, pop3c->state); - break; - - case POP3_STARTTLS: - result = pop3_state_starttls_resp(conn, pop3code, pop3c->state); - break; - - case POP3_RETR: - result = pop3_state_retr_resp(conn, pop3code, pop3c->state); - break; - - case POP3_LIST: - result = pop3_state_list_resp(conn, pop3code, pop3c->state); - break; - - case POP3_LIST_SINGLE: - result = pop3_state_list_single_resp(conn, pop3code, pop3c->state); - break; - - case POP3_QUIT: - /* fallthrough, just stop! */ - default: - /* internal error */ - state(conn, POP3_STOP); - break; - } - } - return result; -} - -/* called repeatedly until done from multi.c */ -static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done) -{ - struct pop3_conn *pop3c = &conn->proto.pop3c; - CURLcode result = Curl_pp_multi_statemach(&pop3c->pp); - - *done = (bool)(pop3c->state == POP3_STOP); - - return result; -} - -static CURLcode pop3_easy_statemach(struct connectdata *conn) -{ - struct pop3_conn *pop3c = &conn->proto.pop3c; - struct pingpong *pp = &pop3c->pp; - CURLcode result = CURLE_OK; - - while(pop3c->state != POP3_STOP) { - result = Curl_pp_easy_statemach(pp); - if(result) - break; - } - - return result; -} - -/* - * Allocate and initialize the struct POP3 for the current SessionHandle. If - * need be. - */ -static CURLcode pop3_init(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - struct FTP *pop3 = data->state.proto.pop3; - if(!pop3) { - pop3 = data->state.proto.pop3 = calloc(sizeof(struct FTP), 1); - if(!pop3) - return CURLE_OUT_OF_MEMORY; - } - - /* get some initial data into the pop3 struct */ - pop3->bytecountp = &data->req.bytecount; - - /* 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. - */ - pop3->user = conn->user; - pop3->passwd = conn->passwd; - - return CURLE_OK; -} - -/* - * pop3_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 is not. When called as - * a part of the easy interface, it will always be TRUE. - */ -static CURLcode pop3_connect(struct connectdata *conn, - bool *done) /* see description above */ -{ - CURLcode result; - struct pop3_conn *pop3c = &conn->proto.pop3c; - struct SessionHandle *data=conn->data; - struct pingpong *pp = &pop3c->pp; - - *done = FALSE; /* default to not done yet */ - - /* If there already is a protocol-specific struct allocated for this - sessionhandle, deal with it */ - Curl_reset_reqproto(conn); - - result = pop3_init(conn); - if(CURLE_OK != result) - return result; - - /* We always support persistent connections on pop3 */ - conn->bits.close = FALSE; - - pp->response_time = RESP_TIMEOUT; /* set default response time-out */ - pp->statemach_act = pop3_statemach_act; - pp->endofresp = pop3_endofresp; - pp->conn = conn; - - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - /* for POP3 over HTTP proxy */ - struct HTTP http_proxy; - struct FTP *pop3_save; - - /* BLOCKING */ - /* We want "seamless" POP3 operations through HTTP proxy tunnel */ - - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member - * conn->proto.http; we want POP3 through HTTP and we have to change the - * member temporarily for connecting to the HTTP proxy. After - * Curl_proxyCONNECT we have to set back the member to the original struct - * POP3 pointer - */ - pop3_save = data->state.proto.pop3; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->state.proto.http = &http_proxy; - - result = Curl_proxyCONNECT(conn, FIRSTSOCKET, - conn->host.name, conn->remote_port); - - data->state.proto.pop3 = pop3_save; - - if(CURLE_OK != result) - return result; - } - - if(conn->handler->protocol & CURLPROTO_POP3S) { - /* BLOCKING */ - /* POP3S is simply pop3 with SSL for the control channel */ - /* now, perform the SSL initialization for this socket */ - result = Curl_ssl_connect(conn, FIRSTSOCKET); - if(result) - return result; - } - - Curl_pp_init(pp); /* init the response reader stuff */ - - /* When we connect, we start in the state where we await the server greet - response */ - state(conn, POP3_SERVERGREET); - - if(data->state.used_interface == Curl_if_multi) - result = pop3_multi_statemach(conn, done); - else { - result = pop3_easy_statemach(conn); - if(!result) - *done = TRUE; - } - - return result; -} - -/*********************************************************************** - * - * pop3_done() - * - * The DONE function. This does what needs to be done after a single DO has - * performed. - * - * Input argument is already checked for validity. - */ -static CURLcode pop3_done(struct connectdata *conn, CURLcode status, - bool premature) -{ - struct SessionHandle *data = conn->data; - struct FTP *pop3 = data->state.proto.pop3; - struct pop3_conn *pop3c = &conn->proto.pop3c; - CURLcode result=CURLE_OK; - (void)premature; - - if(!pop3) - /* When the easy handle is removed from the multi while libcurl is still - * trying to resolve the host name, it seems that the pop3 struct is not - * yet initialized, but the removal action calls Curl_done() which calls - * this function. So we simply return success if no pop3 pointer is set. - */ - return CURLE_OK; - - if(status) { - conn->bits.close = TRUE; /* marked for closure */ - result = status; /* use the already set error code */ - } - - Curl_safefree(pop3c->mailbox); - pop3c->mailbox = NULL; - - /* clear these for next connection */ - pop3->transfer = FTPTRANSFER_BODY; - - return result; -} - -/*********************************************************************** - * - * pop3_perform() - * - * This is the actual DO function for POP3. Get a file/directory according to - * the options previously setup. - */ - -static -CURLcode pop3_perform(struct connectdata *conn, - bool *connected, /* connect status after PASV / PORT */ - bool *dophase_done) -{ - /* this is POP3 and no proxy */ - CURLcode result=CURLE_OK; - struct pop3_conn *pop3c = &conn->proto.pop3c; - - DEBUGF(infof(conn->data, "DO phase starts\n")); - - if(conn->data->set.opt_no_body) { - /* requested no body means no transfer... */ - struct FTP *pop3 = conn->data->state.proto.pop3; - pop3->transfer = FTPTRANSFER_INFO; - } - - *dophase_done = FALSE; /* not done yet */ - - /* start the first command in the DO phase */ - /* If mailbox is empty, then assume user wants listing for mail IDs, - * otherwise, attempt to retrieve the mail-id stored in mailbox - */ - if (strlen(pop3c->mailbox) && !conn->data->set.ftp_list_only) - result = pop3_retr(conn); - else - result = pop3_list(conn); - if(result) - return result; - - /* run the state-machine */ - if(conn->data->state.used_interface == Curl_if_multi) - result = pop3_multi_statemach(conn, dophase_done); - else { - result = pop3_easy_statemach(conn); - *dophase_done = TRUE; /* with the easy interface we are done here */ - } - *connected = conn->bits.tcpconnect; - - if(*dophase_done) - DEBUGF(infof(conn->data, "DO phase is complete\n")); - - return result; -} - -/*********************************************************************** - * - * pop3_do() - * - * This function is registered as 'curl_do' function. It decodes the path - * parts etc as a wrapper to the actual DO function (pop3_perform). - * - * The input argument is already checked for validity. - */ -static CURLcode pop3_do(struct connectdata *conn, bool *done) -{ - CURLcode retcode = CURLE_OK; - - *done = FALSE; /* default to false */ - - /* - Since connections can be re-used between SessionHandles, this might be a - connection already existing but on a fresh SessionHandle struct so we must - make sure we have a good 'struct POP3' to play with. For new connections, - the struct POP3 is allocated and setup in the pop3_connect() function. - */ - Curl_reset_reqproto(conn); - retcode = pop3_init(conn); - if(retcode) - return retcode; - - retcode = pop3_parse_url_path(conn); - if(retcode) - return retcode; - - retcode = pop3_regular_transfer(conn, done); - - return retcode; -} - -/*********************************************************************** - * - * pop3_quit() - * - * This should be called before calling sclose(). We should then wait for the - * response from the server before returning. The calling code should then try - * to close the connection. - * - */ -static CURLcode pop3_quit(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - - result = Curl_pp_sendf(&conn->proto.pop3c.pp, "QUIT", NULL); - if(result) - return result; - state(conn, POP3_QUIT); - - result = pop3_easy_statemach(conn); - - return result; -} - -/*********************************************************************** - * - * pop3_disconnect() - * - * Disconnect from an POP3 server. Cleanup protocol-specific per-connection - * resources. BLOCKING. - */ -static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection) -{ - struct pop3_conn *pop3c= &conn->proto.pop3c; - - /* We cannot send quit unconditionally. If this connection is stale or - bad in any way, sending quit and waiting around here will make the - disconnect wait in vain and cause more problems than we need to. - */ - - /* The POP3 session may or may not have been allocated/setup at this - point! */ - if(!dead_connection && pop3c->pp.conn) - (void)pop3_quit(conn); /* ignore errors on the LOGOUT */ - - - Curl_pp_disconnect(&pop3c->pp); - - return CURLE_OK; -} - -/*********************************************************************** - * - * pop3_parse_url_path() - * - * Parse the URL path into separate path components. - * - */ -static CURLcode pop3_parse_url_path(struct connectdata *conn) -{ - /* the pop3 struct is already inited in pop3_connect() */ - struct pop3_conn *pop3c = &conn->proto.pop3c; - struct SessionHandle *data = conn->data; - const char *path = data->state.path; - - /* url decode the path and use this mailbox */ - pop3c->mailbox = curl_easy_unescape(data, path, 0, NULL); - if (!pop3c->mailbox) - return CURLE_OUT_OF_MEMORY; - - return CURLE_OK; -} - -/* call this when the DO phase has completed */ -static CURLcode pop3_dophase_done(struct connectdata *conn, - bool connected) -{ - struct FTP *pop3 = conn->data->state.proto.pop3; - (void)connected; - - if(pop3->transfer != FTPTRANSFER_BODY) - /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - - return CURLE_OK; -} - -/* called from multi.c while DOing */ -static CURLcode pop3_doing(struct connectdata *conn, - bool *dophase_done) -{ - CURLcode result; - result = pop3_multi_statemach(conn, dophase_done); - - if(*dophase_done) { - result = pop3_dophase_done(conn, FALSE /* not connected */); - - DEBUGF(infof(conn->data, "DO phase is complete\n")); - } - return result; -} - -/*********************************************************************** - * - * pop3_regular_transfer() - * - * The input argument is already checked for validity. - * - * Performs all commands done before a regular transfer between a local and a - * remote host. - * - */ -static -CURLcode pop3_regular_transfer(struct connectdata *conn, - bool *dophase_done) -{ - CURLcode result=CURLE_OK; - bool connected=FALSE; - struct SessionHandle *data = conn->data; - data->req.size = -1; /* make sure this is unknown at this point */ - - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - Curl_pgrsSetUploadSize(data, 0); - Curl_pgrsSetDownloadSize(data, 0); - - result = pop3_perform(conn, - &connected, /* have we connected after PASV/PORT */ - dophase_done); /* all commands in the DO-phase done? */ - - if(CURLE_OK == result) { - - if(!*dophase_done) - /* the DO phase has not completed yet */ - return CURLE_OK; - - result = pop3_dophase_done(conn, connected); - if(result) - return result; - } - - return result; -} - -static CURLcode pop3_setup_connection(struct connectdata * conn) -{ - struct SessionHandle *data = conn->data; - - if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { - /* Unless we have asked to tunnel pop3 operations through the proxy, we - switch and use HTTP operations only */ -#ifndef CURL_DISABLE_HTTP - if(conn->handler == &Curl_handler_pop3) - conn->handler = &Curl_handler_pop3_proxy; - else { -#ifdef USE_SSL - conn->handler = &Curl_handler_pop3s_proxy; -#else - failf(data, "POP3S not supported!"); - return CURLE_UNSUPPORTED_PROTOCOL; -#endif - } - /* - * We explicitly mark this connection as persistent here as we're doing - * POP3 over HTTP and thus we accidentally avoid setting this value - * otherwise. - */ - conn->bits.close = FALSE; -#else - failf(data, "POP3 over http proxy requires HTTP support built-in!"); - return CURLE_UNSUPPORTED_PROTOCOL; -#endif - } - - data->state.path++; /* don't include the initial slash */ - - return CURLE_OK; -} - -/* this is the 5-bytes End-Of-Body marker for POP3 */ -#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a" -#define POP3_EOB_LEN 5 - -/* - * This function scans the body after the end-of-body and writes everything - * until the end is found. - */ -CURLcode Curl_pop3_write(struct connectdata *conn, - char *str, - size_t nread) -{ - /* This code could be made into a special function in the handler struct. */ - CURLcode result; - struct SessionHandle *data = conn->data; - struct SingleRequest *k = &data->req; - - /* Detect the end-of-body marker, which is 5 bytes: - 0d 0a 2e 0d 0a. This marker can of course be spread out - over up to 5 different data chunks. Deal with it! */ - struct pop3_conn *pop3c = &conn->proto.pop3c; - size_t checkmax = (nread >= POP3_EOB_LEN?POP3_EOB_LEN:nread); - size_t checkleft = POP3_EOB_LEN-pop3c->eob; - size_t check = (checkmax >= checkleft?checkleft:checkmax); - - if(!memcmp(POP3_EOB, &str[nread - check], check)) { - /* substring match */ - pop3c->eob += check; - if(pop3c->eob == POP3_EOB_LEN) { - /* full match, the transfer is done! */ - str[nread - check] = '\0'; - nread -= check; - k->keepon &= ~KEEP_RECV; - pop3c->eob = 0; - } - } - else if(pop3c->eob) { - /* not a match, but we matched a piece before so we must now - send that part as body first, before we move on and send - this buffer */ - result = Curl_client_write(conn, CLIENTWRITE_BODY, - (char *)POP3_EOB, pop3c->eob); - if(result) - return result; - pop3c->eob = 0; - } - - result = Curl_client_write(conn, CLIENTWRITE_BODY, str, nread); - - return result; -} - -#endif /* CURL_DISABLE_POP3 */ diff --git a/third_party/curl/lib/pop3.h b/third_party/curl/lib/pop3.h deleted file mode 100644 index 15256738e..000000000 --- a/third_party/curl/lib/pop3.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef __POP3_H -#define __POP3_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/**************************************************************************** - * POP3 unique setup - ***************************************************************************/ -typedef enum { - POP3_STOP, /* do nothing state, stops the state machine */ - POP3_SERVERGREET, /* waiting for the initial greeting immediately after - a connect */ - POP3_USER, - POP3_PASS, - POP3_STARTTLS, - POP3_LIST, - POP3_LIST_SINGLE, - POP3_RETR, - POP3_QUIT, - POP3_LAST /* never used */ -} pop3state; - -/* pop3_conn is used for struct connection-oriented data in the connectdata - struct */ -struct pop3_conn { - struct pingpong pp; - char *mailbox; /* what to RETR */ - size_t eob; /* number of bytes of the EOB (End Of Body) that has been - received thus far */ - pop3state state; /* always use pop3.c:state() to change state! */ -}; - -extern const struct Curl_handler Curl_handler_pop3; -extern const struct Curl_handler Curl_handler_pop3s; - -/* - * This function scans the body after the end-of-body and writes everything - * until the end is found. - */ -CURLcode Curl_pop3_write(struct connectdata *conn, - char *str, - size_t nread); - -#endif /* __POP3_H */ diff --git a/third_party/curl/lib/progress.c b/third_party/curl/lib/progress.c deleted file mode 100644 index e37c34d99..000000000 --- a/third_party/curl/lib/progress.c +++ /dev/null @@ -1,454 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include "urldata.h" -#include "sendf.h" -#include "progress.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero - byte) */ -static void time2str(char *r, curl_off_t seconds) -{ - curl_off_t d, h, m, s; - if(seconds <= 0) { - strcpy(r, "--:--:--"); - return; - } - h = seconds / CURL_OFF_T_C(3600); - if(h <= CURL_OFF_T_C(99)) { - m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60); - s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60)); - snprintf(r, 9, "%2" FORMAT_OFF_T ":%02" FORMAT_OFF_T ":%02" FORMAT_OFF_T, - h, m, s); - } - else { - /* this equals to more than 99 hours, switch to a more suitable output - format to fit within the limits. */ - d = seconds / CURL_OFF_T_C(86400); - h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600); - if(d <= CURL_OFF_T_C(999)) - snprintf(r, 9, "%3" FORMAT_OFF_T "d %02" FORMAT_OFF_T "h", d, h); - else - snprintf(r, 9, "%7" FORMAT_OFF_T "d", d); - } -} - -/* The point of this function would be to return a string of the input data, - but never longer than 5 columns (+ one zero byte). - Add suffix k, M, G when suitable... */ -static char *max5data(curl_off_t bytes, char *max5) -{ -#define ONE_KILOBYTE CURL_OFF_T_C(1024) -#define ONE_MEGABYTE (CURL_OFF_T_C(1024) * ONE_KILOBYTE) -#define ONE_GIGABYTE (CURL_OFF_T_C(1024) * ONE_MEGABYTE) -#define ONE_TERABYTE (CURL_OFF_T_C(1024) * ONE_GIGABYTE) -#define ONE_PETABYTE (CURL_OFF_T_C(1024) * ONE_TERABYTE) - - if(bytes < CURL_OFF_T_C(100000)) - snprintf(max5, 6, "%5" FORMAT_OFF_T, bytes); - - else if(bytes < CURL_OFF_T_C(10000) * ONE_KILOBYTE) - snprintf(max5, 6, "%4" FORMAT_OFF_T "k", bytes/ONE_KILOBYTE); - - else if(bytes < CURL_OFF_T_C(100) * ONE_MEGABYTE) - /* 'XX.XM' is good as long as we're less than 100 megs */ - snprintf(max5, 6, "%2" FORMAT_OFF_T ".%0" FORMAT_OFF_T "M", - bytes/ONE_MEGABYTE, - (bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) ); - -#if (CURL_SIZEOF_CURL_OFF_T > 4) - - else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE) - /* 'XXXXM' is good until we're at 10000MB or above */ - snprintf(max5, 6, "%4" FORMAT_OFF_T "M", bytes/ONE_MEGABYTE); - - else if(bytes < CURL_OFF_T_C(100) * ONE_GIGABYTE) - /* 10000 MB - 100 GB, we show it as XX.XG */ - snprintf(max5, 6, "%2" FORMAT_OFF_T ".%0" FORMAT_OFF_T "G", - bytes/ONE_GIGABYTE, - (bytes%ONE_GIGABYTE) / (ONE_GIGABYTE/CURL_OFF_T_C(10)) ); - - else if(bytes < CURL_OFF_T_C(10000) * ONE_GIGABYTE) - /* up to 10000GB, display without decimal: XXXXG */ - snprintf(max5, 6, "%4" FORMAT_OFF_T "G", bytes/ONE_GIGABYTE); - - else if(bytes < CURL_OFF_T_C(10000) * ONE_TERABYTE) - /* up to 10000TB, display without decimal: XXXXT */ - snprintf(max5, 6, "%4" FORMAT_OFF_T "T", bytes/ONE_TERABYTE); - - else - /* up to 10000PB, display without decimal: XXXXP */ - snprintf(max5, 6, "%4" FORMAT_OFF_T "P", bytes/ONE_PETABYTE); - - /* 16384 petabytes (16 exabytes) is the maximum a 64 bit unsigned number - can hold, but our data type is signed so 8192PB will be the maximum. */ - -#else - - else - snprintf(max5, 6, "%4" FORMAT_OFF_T "M", bytes/ONE_MEGABYTE); - -#endif - - return max5; -} - -/* - - New proposed interface, 9th of February 2000: - - pgrsStartNow() - sets start time - pgrsSetDownloadSize(x) - known expected download size - pgrsSetUploadSize(x) - known expected upload size - pgrsSetDownloadCounter() - amount of data currently downloaded - pgrsSetUploadCounter() - amount of data currently uploaded - pgrsUpdate() - show progress - pgrsDone() - transfer complete - -*/ - -void Curl_pgrsDone(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - data->progress.lastshow=0; - Curl_pgrsUpdate(conn); /* the final (forced) update */ - - if(!(data->progress.flags & PGRS_HIDE) && - !data->progress.callback) - /* only output if we don't use a progress callback and we're not - * hidden */ - fprintf(data->set.err, "\n"); - - data->progress.speeder_c = 0; /* reset the progress meter display */ -} - -/* reset all times except redirect */ -void Curl_pgrsResetTimes(struct SessionHandle *data) -{ - data->progress.t_nslookup = 0.0; - data->progress.t_connect = 0.0; - data->progress.t_pretransfer = 0.0; - data->progress.t_starttransfer = 0.0; -} - -void Curl_pgrsTime(struct SessionHandle *data, timerid timer) -{ - switch(timer) { - default: - case TIMER_NONE: - /* mistake filter */ - break; - case TIMER_STARTSINGLE: - /* This is set at the start of a single fetch */ - data->progress.t_startsingle = Curl_tvnow(); - break; - - case TIMER_NAMELOOKUP: - data->progress.t_nslookup = - Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle); - break; - case TIMER_CONNECT: - data->progress.t_connect = - Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle); - break; - case TIMER_APPCONNECT: - data->progress.t_appconnect = - Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle); - break; - case TIMER_PRETRANSFER: - data->progress.t_pretransfer = - Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle); - break; - case TIMER_STARTTRANSFER: - data->progress.t_starttransfer = - Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle); - break; - case TIMER_POSTRANSFER: - /* this is the normal end-of-transfer thing */ - break; - case TIMER_REDIRECT: - data->progress.t_redirect = - Curl_tvdiff_secs(Curl_tvnow(), data->progress.start); - break; - } -} - -void Curl_pgrsStartNow(struct SessionHandle *data) -{ - data->progress.speeder_c = 0; /* reset the progress meter display */ - data->progress.start = Curl_tvnow(); -} - -void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size) -{ - data->progress.downloaded = size; -} - -void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size) -{ - data->progress.uploaded = size; -} - -void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size) -{ - data->progress.size_dl = size; - if(size >= 0) - data->progress.flags |= PGRS_DL_SIZE_KNOWN; - else - data->progress.flags &= ~PGRS_DL_SIZE_KNOWN; -} - -void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size) -{ - data->progress.size_ul = size; - if(size >= 0) - data->progress.flags |= PGRS_UL_SIZE_KNOWN; - else - data->progress.flags &= ~PGRS_UL_SIZE_KNOWN; -} - -int Curl_pgrsUpdate(struct connectdata *conn) -{ - struct timeval now; - int result; - char max5[6][10]; - curl_off_t dlpercen=0; - curl_off_t ulpercen=0; - curl_off_t total_percen=0; - curl_off_t total_transfer; - curl_off_t total_expected_transfer; - curl_off_t timespent; - struct SessionHandle *data = conn->data; - int nowindex = data->progress.speeder_c% CURR_TIME; - int checkindex; - int countindex; /* amount of seconds stored in the speeder array */ - char time_left[10]; - char time_total[10]; - char time_spent[10]; - curl_off_t ulestimate=0; - curl_off_t dlestimate=0; - curl_off_t total_estimate; - bool shownow=FALSE; - - now = Curl_tvnow(); /* what time is it */ - - /* The time spent so far (from the start) */ - data->progress.timespent = - (double)(now.tv_sec - data->progress.start.tv_sec) + - (double)(now.tv_usec - data->progress.start.tv_usec)/1000000.0; - timespent = (curl_off_t)data->progress.timespent; - - /* The average download speed this far */ - data->progress.dlspeed = (curl_off_t) - ((double)data->progress.downloaded/ - (data->progress.timespent>0?data->progress.timespent:1)); - - /* The average upload speed this far */ - data->progress.ulspeed = (curl_off_t) - ((double)data->progress.uploaded/ - (data->progress.timespent>0?data->progress.timespent:1)); - - /* Calculations done at most once a second, unless end is reached */ - if(data->progress.lastshow != (long)now.tv_sec) { - shownow = TRUE; - - data->progress.lastshow = now.tv_sec; - - /* Let's do the "current speed" thing, which should use the fastest - of the dl/ul speeds. Store the faster speed at entry 'nowindex'. */ - data->progress.speeder[ nowindex ] = - data->progress.downloaded>data->progress.uploaded? - data->progress.downloaded:data->progress.uploaded; - - /* remember the exact time for this moment */ - data->progress.speeder_time [ nowindex ] = now; - - /* advance our speeder_c counter, which is increased every time we get - here and we expect it to never wrap as 2^32 is a lot of seconds! */ - data->progress.speeder_c++; - - /* figure out how many index entries of data we have stored in our speeder - array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of - transfer. Imagine, after one second we have filled in two entries, - after two seconds we've filled in three entries etc. */ - countindex = ((data->progress.speeder_c>=CURR_TIME)? - CURR_TIME:data->progress.speeder_c) - 1; - - /* first of all, we don't do this if there's no counted seconds yet */ - if(countindex) { - long span_ms; - - /* Get the index position to compare with the 'nowindex' position. - Get the oldest entry possible. While we have less than CURR_TIME - entries, the first entry will remain the oldest. */ - checkindex = (data->progress.speeder_c>=CURR_TIME)? - data->progress.speeder_c%CURR_TIME:0; - - /* Figure out the exact time for the time span */ - span_ms = Curl_tvdiff(now, - data->progress.speeder_time[checkindex]); - if(0 == span_ms) - span_ms=1; /* at least one millisecond MUST have passed */ - - /* Calculate the average speed the last 'span_ms' milliseconds */ - { - curl_off_t amount = data->progress.speeder[nowindex]- - data->progress.speeder[checkindex]; - - if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */) - /* the 'amount' value is bigger than would fit in 32 bits if - multiplied with 1000, so we use the double math for this */ - data->progress.current_speed = (curl_off_t) - ((double)amount/((double)span_ms/1000.0)); - else - /* the 'amount' value is small enough to fit within 32 bits even - when multiplied with 1000 */ - data->progress.current_speed = amount*CURL_OFF_T_C(1000)/span_ms; - } - } - else - /* the first second we use the main average */ - data->progress.current_speed = - (data->progress.ulspeed>data->progress.dlspeed)? - data->progress.ulspeed:data->progress.dlspeed; - - } /* Calculations end */ - - if(!(data->progress.flags & PGRS_HIDE)) { - - /* progress meter has not been shut off */ - - if(data->set.fprogress) { - /* There's a callback set, so we call that instead of writing - anything ourselves. This really is the way to go. */ - result= data->set.fprogress(data->set.progress_client, - (double)data->progress.size_dl, - (double)data->progress.downloaded, - (double)data->progress.size_ul, - (double)data->progress.uploaded); - if(result) - failf(data, "Callback aborted"); - return result; - } - - if(!shownow) - /* only show the internal progress meter once per second */ - return 0; - - /* If there's no external callback set, use internal code to show - progress */ - - if(!(data->progress.flags & PGRS_HEADERS_OUT)) { - if(data->state.resume_from) { - fprintf(data->set.err, - "** Resuming transfer from byte position %" FORMAT_OFF_T "\n", - data->state.resume_from); - } - fprintf(data->set.err, - " %% Total %% Received %% Xferd Average Speed Time Time Time Current\n" - " Dload Upload Total Spent Left Speed\n"); - data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */ - } - - /* Figure out the estimated time of arrival for the upload */ - if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && - (data->progress.ulspeed > CURL_OFF_T_C(0))) { - ulestimate = data->progress.size_ul / data->progress.ulspeed; - - if(data->progress.size_ul > CURL_OFF_T_C(10000)) - ulpercen = data->progress.uploaded / - (data->progress.size_ul/CURL_OFF_T_C(100)); - else if(data->progress.size_ul > CURL_OFF_T_C(0)) - ulpercen = (data->progress.uploaded*100) / - data->progress.size_ul; - } - - /* ... and the download */ - if((data->progress.flags & PGRS_DL_SIZE_KNOWN) && - (data->progress.dlspeed > CURL_OFF_T_C(0))) { - dlestimate = data->progress.size_dl / data->progress.dlspeed; - - if(data->progress.size_dl > CURL_OFF_T_C(10000)) - dlpercen = data->progress.downloaded / - (data->progress.size_dl/CURL_OFF_T_C(100)); - else if(data->progress.size_dl > CURL_OFF_T_C(0)) - dlpercen = (data->progress.downloaded*100) / - data->progress.size_dl; - } - - /* Now figure out which of them is slower and use that one for the - total estimate! */ - total_estimate = ulestimate>dlestimate?ulestimate:dlestimate; - - /* create the three time strings */ - time2str(time_left, total_estimate > 0?(total_estimate - timespent):0); - time2str(time_total, total_estimate); - time2str(time_spent, timespent); - - /* Get the total amount of data expected to get transferred */ - total_expected_transfer = - (data->progress.flags & PGRS_UL_SIZE_KNOWN? - data->progress.size_ul:data->progress.uploaded)+ - (data->progress.flags & PGRS_DL_SIZE_KNOWN? - data->progress.size_dl:data->progress.downloaded); - - /* We have transferred this much so far */ - total_transfer = data->progress.downloaded + data->progress.uploaded; - - /* Get the percentage of data transferred so far */ - if(total_expected_transfer > CURL_OFF_T_C(10000)) - total_percen = total_transfer / - (total_expected_transfer/CURL_OFF_T_C(100)); - else if(total_expected_transfer > CURL_OFF_T_C(0)) - total_percen = (total_transfer*100) / total_expected_transfer; - - fprintf(data->set.err, - "\r" - "%3" FORMAT_OFF_T " %s " - "%3" FORMAT_OFF_T " %s " - "%3" FORMAT_OFF_T " %s %s %s %s %s %s %s", - total_percen, /* 3 letters */ /* total % */ - max5data(total_expected_transfer, max5[2]), /* total size */ - dlpercen, /* 3 letters */ /* rcvd % */ - max5data(data->progress.downloaded, max5[0]), /* rcvd size */ - ulpercen, /* 3 letters */ /* xfer % */ - max5data(data->progress.uploaded, max5[1]), /* xfer size */ - max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */ - max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */ - time_total, /* 8 letters */ /* total time */ - time_spent, /* 8 letters */ /* time spent */ - time_left, /* 8 letters */ /* time left */ - max5data(data->progress.current_speed, max5[5]) /* current speed */ - ); - - /* we flush the output stream to make it appear as soon as possible */ - fflush(data->set.err); - - } /* !(data->progress.flags & PGRS_HIDE) */ - - return 0; -} diff --git a/third_party/curl/lib/progress.h b/third_party/curl/lib/progress.h deleted file mode 100644 index 95944f0ba..000000000 --- a/third_party/curl/lib/progress.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef __PROGRESS_H -#define __PROGRESS_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#include "timeval.h" - - -typedef enum { - TIMER_NONE, - TIMER_NAMELOOKUP, - TIMER_CONNECT, - TIMER_APPCONNECT, - TIMER_PRETRANSFER, - TIMER_STARTTRANSFER, - TIMER_POSTRANSFER, - TIMER_STARTSINGLE, - TIMER_REDIRECT, - TIMER_LAST /* must be last */ -} timerid; - -void Curl_pgrsDone(struct connectdata *); -void Curl_pgrsStartNow(struct SessionHandle *data); -void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size); -void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size); -void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size); -void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size); -int Curl_pgrsUpdate(struct connectdata *); -void Curl_pgrsResetTimes(struct SessionHandle *data); -void Curl_pgrsTime(struct SessionHandle *data, timerid timer); - - -/* Don't show progress for sizes smaller than: */ -#define LEAST_SIZE_PROGRESS BUFSIZE - -#define PROGRESS_DOWNLOAD (1<<0) -#define PROGRESS_UPLOAD (1<<1) -#define PROGRESS_DOWN_AND_UP (PROGRESS_UPLOAD | PROGRESS_DOWNLOAD) - -#define PGRS_SHOW_DL (1<<0) -#define PGRS_SHOW_UL (1<<1) -#define PGRS_DONE_DL (1<<2) -#define PGRS_DONE_UL (1<<3) -#define PGRS_HIDE (1<<4) -#define PGRS_UL_SIZE_KNOWN (1<<5) -#define PGRS_DL_SIZE_KNOWN (1<<6) - -#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */ - - -#endif /* __PROGRESS_H */ diff --git a/third_party/curl/lib/qssl.c b/third_party/curl/lib/qssl.c deleted file mode 100644 index 55031491e..000000000 --- a/third_party/curl/lib/qssl.c +++ /dev/null @@ -1,501 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef USE_QSOSSL -#include -#include -#include -#ifdef HAVE_LIMITS_H -# include -#endif - -#include -#include "urldata.h" -#include "sendf.h" -#include "qssl.h" -#include "sslgen.h" -#include "connect.h" /* for the connect timeout */ -#include "select.h" -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - - -int Curl_qsossl_init(void) - -{ - /* Nothing to do here. We must have connection data to initialize ssl, so - * defer. - */ - - return 1; -} - - -void Curl_qsossl_cleanup(void) - -{ - /* Nothing to do. */ -} - - -static CURLcode Curl_qsossl_init_session(struct SessionHandle * data) - -{ - int rc; - char * certname; - SSLInit initstr; - SSLInitApp initappstr; - - /* Initialize the job for SSL according to the current parameters. - * QsoSSL offers two ways to do it: SSL_Init_Application() that uses an - * application identifier to select certificates in the main certificate - * store, and SSL_Init() that uses named keyring files and a password. - * It is not possible to have different keyrings for the CAs and the - * local certificate. We thus use the certificate name to identify the - * keyring if given, else the CA file name. - * If the key file name is given, it is taken as the password for the - * keyring in certificate file. - * We first try to SSL_Init_Application(), then SSL_Init() if it failed. - */ - - certname = data->set.str[STRING_CERT]; - - if(!certname) { - certname = data->set.str[STRING_SSL_CAFILE]; - - if(!certname) - return CURLE_OK; /* Use previous setup. */ - } - - memset((char *) &initappstr, 0, sizeof initappstr); - initappstr.applicationID = certname; - initappstr.applicationIDLen = strlen(certname); - initappstr.protocol = SSL_VERSION_CURRENT; /* TLSV1 compat. SSLV[23]. */ - initappstr.sessionType = SSL_REGISTERED_AS_CLIENT; - rc = SSL_Init_Application(&initappstr); - - if(rc == SSL_ERROR_NOT_REGISTERED) { - initstr.keyringFileName = certname; - initstr.keyringPassword = data->set.str[STRING_KEY]; - initstr.cipherSuiteList = NULL; /* Use default. */ - initstr.cipherSuiteListLen = 0; - rc = SSL_Init(&initstr); - } - - switch (rc) { - - case 0: /* No error. */ - break; - - case SSL_ERROR_IO: - failf(data, "SSL_Init() I/O error: %s", strerror(errno)); - return CURLE_SSL_CONNECT_ERROR; - - case SSL_ERROR_BAD_CIPHER_SUITE: - return CURLE_SSL_CIPHER; - - case SSL_ERROR_KEYPASSWORD_EXPIRED: - case SSL_ERROR_NOT_REGISTERED: - return CURLE_SSL_CONNECT_ERROR; - - case SSL_ERROR_NO_KEYRING: - return CURLE_SSL_CACERT; - - case SSL_ERROR_CERT_EXPIRED: - return CURLE_SSL_CERTPROBLEM; - - default: - failf(data, "SSL_Init(): %s", SSL_Strerror(rc, NULL)); - return CURLE_SSL_CONNECT_ERROR; - } - - return CURLE_OK; -} - - -static CURLcode Curl_qsossl_create(struct connectdata * conn, int sockindex) - -{ - SSLHandle * h; - struct ssl_connect_data * connssl = &conn->ssl[sockindex]; - - h = SSL_Create(conn->sock[sockindex], SSL_ENCRYPT); - - if(!h) { - failf(conn->data, "SSL_Create() I/O error: %s", strerror(errno)); - return CURLE_SSL_CONNECT_ERROR; - } - - connssl->handle = h; - return CURLE_OK; -} - - -static int Curl_qsossl_trap_cert(SSLHandle * h) - -{ - return 1; /* Accept certificate. */ -} - - -static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex) - -{ - int rc; - struct SessionHandle * data = conn->data; - struct ssl_connect_data * connssl = &conn->ssl[sockindex]; - SSLHandle * h = connssl->handle; - long timeout_ms; - - h->exitPgm = NULL; - - if(!data->set.ssl.verifyhost) - h->exitPgm = Curl_qsossl_trap_cert; - - /* figure out how long time we should wait at maximum */ - timeout_ms = Curl_timeleft(data, NULL, TRUE); - - if(timeout_ms < 0) { - /* time-out, bail out, go home */ - failf(data, "Connection time-out"); - return CURLE_OPERATION_TIMEDOUT; - } - - /* SSL_Handshake() timeout resolution is second, so round up. */ - h->timeout = (timeout_ms + 1000 - 1) / 1000; - - /* Set-up protocol. */ - - switch (data->set.ssl.version) { - - default: - case CURL_SSLVERSION_DEFAULT: - h->protocol = SSL_VERSION_CURRENT; /* TLSV1 compat. SSLV[23]. */ - break; - - case CURL_SSLVERSION_TLSv1: - h->protocol = TLS_VERSION_1; - break; - - case CURL_SSLVERSION_SSLv2: - h->protocol = SSL_VERSION_2; - break; - - case CURL_SSLVERSION_SSLv3: - h->protocol = SSL_VERSION_3; - break; - } - - rc = SSL_Handshake(h, SSL_HANDSHAKE_AS_CLIENT); - - switch (rc) { - - case 0: /* No error. */ - break; - - case SSL_ERROR_BAD_CERTIFICATE: - case SSL_ERROR_BAD_CERT_SIG: - case SSL_ERROR_NOT_TRUSTED_ROOT: - return CURLE_PEER_FAILED_VERIFICATION; - - case SSL_ERROR_BAD_CIPHER_SUITE: - case SSL_ERROR_NO_CIPHERS: - return CURLE_SSL_CIPHER; - - case SSL_ERROR_CERTIFICATE_REJECTED: - case SSL_ERROR_CERT_EXPIRED: - case SSL_ERROR_NO_CERTIFICATE: - return CURLE_SSL_CERTPROBLEM; - - case SSL_ERROR_IO: - failf(data, "SSL_Handshake() I/O error: %s", strerror(errno)); - return CURLE_SSL_CONNECT_ERROR; - - default: - failf(data, "SSL_Handshake(): %s", SSL_Strerror(rc, NULL)); - return CURLE_SSL_CONNECT_ERROR; - } - - return CURLE_OK; -} - - -static Curl_recv qsossl_recv; -static Curl_send qsossl_send; - -CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex) - -{ - struct SessionHandle * data = conn->data; - struct ssl_connect_data * connssl = &conn->ssl[sockindex]; - int rc; - - rc = Curl_qsossl_init_session(data); - - if(rc == CURLE_OK) { - rc = Curl_qsossl_create(conn, sockindex); - - if(rc == CURLE_OK) - rc = Curl_qsossl_handshake(conn, sockindex); - else { - SSL_Destroy(connssl->handle); - connssl->handle = NULL; - connssl->use = FALSE; - connssl->state = ssl_connection_none; - } - } - if (rc == CURLE_OK) { - connssl->state = ssl_connection_complete; - conn->recv[sockindex] = qsossl_recv; - conn->send[sockindex] = qsossl_send; - } - - return rc; -} - - -static int Curl_qsossl_close_one(struct ssl_connect_data * conn, - struct SessionHandle * data) - -{ - int rc; - - if(!conn->handle) - return 0; - - rc = SSL_Destroy(conn->handle); - - if(rc) { - if(rc == SSL_ERROR_IO) { - failf(data, "SSL_Destroy() I/O error: %s", strerror(errno)); - return -1; - } - - /* An SSL error. */ - failf(data, "SSL_Destroy() returned error %s", SSL_Strerror(rc, NULL)); - return -1; - } - - conn->handle = NULL; - return 0; -} - - -void Curl_qsossl_close(struct connectdata *conn, int sockindex) - -{ - struct SessionHandle *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - if(connssl->use) - (void) Curl_qsossl_close_one(connssl, data); -} - - -int Curl_qsossl_close_all(struct SessionHandle * data) - -{ - /* Unimplemented. */ - (void) data; - return 0; -} - - -int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex) - -{ - struct ssl_connect_data * connssl = &conn->ssl[sockindex]; - struct SessionHandle *data = conn->data; - ssize_t nread; - int what; - int rc; - char buf[120]; - - if(!connssl->handle) - return 0; - - if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) - return 0; - - if(Curl_qsossl_close_one(connssl, data)) - return -1; - - rc = 0; - - what = Curl_socket_ready(conn->sock[sockindex], - CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); - - for (;;) { - if(what < 0) { - /* anything that gets here is fatally bad */ - failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); - rc = -1; - break; - } - - if(!what) { /* timeout */ - failf(data, "SSL shutdown timeout"); - break; - } - - /* Something to read, let's do it and hope that it is the close - notify alert from the server. No way to SSL_Read now, so use read(). */ - - nread = read(conn->sock[sockindex], buf, sizeof(buf)); - - if(nread < 0) { - failf(data, "read: %s", strerror(errno)); - rc = -1; - } - - if(nread <= 0) - break; - - what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0); - } - - return rc; -} - - -static ssize_t qsossl_send(struct connectdata * conn, int sockindex, - const void * mem, size_t len, CURLcode * curlcode) - -{ - /* SSL_Write() is said to return 'int' while write() and send() returns - 'size_t' */ - int rc; - - rc = SSL_Write(conn->ssl[sockindex].handle, (void *) mem, (int) len); - - if(rc < 0) { - switch(rc) { - - case SSL_ERROR_BAD_STATE: - /* The operation did not complete; the same SSL I/O function - should be called again later. This is basically an EWOULDBLOCK - equivalent. */ - *curlcode = CURLE_AGAIN; - return -1; - - case SSL_ERROR_IO: - switch (errno) { - case EWOULDBLOCK: - case EINTR: - *curlcode = CURLE_AGAIN; - return -1; - } - - failf(conn->data, "SSL_Write() I/O error: %s", strerror(errno)); - *curlcode = CURLE_SEND_ERROR; - return -1; - } - - /* An SSL error. */ - failf(conn->data, "SSL_Write() returned error %s", - SSL_Strerror(rc, NULL)); - *curlcode = CURLE_SEND_ERROR; - return -1; - } - - return (ssize_t) rc; /* number of bytes */ -} - - -static ssize_t qsossl_recv(struct connectdata * conn, int num, char * buf, - size_t buffersize, CURLcode * curlcode) - -{ - char error_buffer[120]; /* OpenSSL documents that this must be at - least 120 bytes long. */ - unsigned long sslerror; - int buffsize; - int nread; - - buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; - nread = SSL_Read(conn->ssl[num].handle, buf, buffsize); - - if(nread < 0) { - /* failed SSL_read */ - - switch (nread) { - - case SSL_ERROR_BAD_STATE: - /* there's data pending, re-invoke SSL_Read(). */ - *curlcode = CURLE_AGAIN; - return -1; - - case SSL_ERROR_IO: - switch (errno) { - case EWOULDBLOCK: - *curlcode = CURLE_AGAIN; - return -1; - } - - failf(conn->data, "SSL_Read() I/O error: %s", strerror(errno)); - *curlcode = CURLE_RECV_ERROR; - return -1; - - default: - failf(conn->data, "SSL read error: %s", SSL_Strerror(nread, NULL)); - *curlcode = CURLE_RECV_ERROR; - return -1; - } - } - return (ssize_t) nread; -} - - -size_t Curl_qsossl_version(char * buffer, size_t size) - -{ - strncpy(buffer, "IBM OS/400 SSL", size); - return strlen(buffer); -} - - -int Curl_qsossl_check_cxn(struct connectdata * cxn) - -{ - int err; - int errlen; - - /* The only thing that can be tested here is at the socket level. */ - - if(!cxn->ssl[FIRSTSOCKET].handle) - return 0; /* connection has been closed */ - - err = 0; - errlen = sizeof err; - - if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR, - (unsigned char *) &err, &errlen) || - errlen != sizeof err || err) - return 0; /* connection has been closed */ - - return -1; /* connection status unknown */ -} - -#endif /* USE_QSOSSL */ diff --git a/third_party/curl/lib/qssl.h b/third_party/curl/lib/qssl.h deleted file mode 100644 index bd195ff7b..000000000 --- a/third_party/curl/lib/qssl.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef __QSSL_H -#define __QSSL_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 should only be needed to get included by sslgen.c and qssl.c - */ - -#include "urldata.h" - -#ifdef USE_QSOSSL -int Curl_qsossl_init(void); -void Curl_qsossl_cleanup(void); -CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex); -void Curl_qsossl_close(struct connectdata *conn, int sockindex); -int Curl_qsossl_close_all(struct SessionHandle * data); -int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex); - -size_t Curl_qsossl_version(char * buffer, size_t size); -int Curl_qsossl_check_cxn(struct connectdata * cxn); - -/* API setup for QsoSSL */ -#define curlssl_init Curl_qsossl_init -#define curlssl_cleanup Curl_qsossl_cleanup -#define curlssl_connect Curl_qsossl_connect - -/* No session handling for QsoSSL */ -#define curlssl_session_free(x) -#define curlssl_close_all Curl_qsossl_close_all -#define curlssl_close Curl_qsossl_close -#define curlssl_shutdown(x,y) Curl_qsossl_shutdown(x,y) -#define curlssl_set_engine(x,y) CURLE_NOT_BUILT_IN -#define curlssl_set_engine_default(x) CURLE_NOT_BUILT_IN -#define curlssl_engines_list(x) NULL -#define curlssl_version Curl_qsossl_version -#define curlssl_check_cxn(x) Curl_qsossl_check_cxn(x) -#define curlssl_data_pending(x,y) 0 -#endif /* USE_QSOSSL */ -#endif diff --git a/third_party/curl/lib/rawstr.c b/third_party/curl/lib/rawstr.c deleted file mode 100644 index f3b302dc1..000000000 --- a/third_party/curl/lib/rawstr.c +++ /dev/null @@ -1,142 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include "rawstr.h" - -/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because - its behavior is altered by the current locale. */ -char Curl_raw_toupper(char in) -{ - switch (in) { - case 'a': - return 'A'; - case 'b': - return 'B'; - case 'c': - return 'C'; - case 'd': - return 'D'; - case 'e': - return 'E'; - case 'f': - return 'F'; - case 'g': - return 'G'; - case 'h': - return 'H'; - case 'i': - return 'I'; - case 'j': - return 'J'; - case 'k': - return 'K'; - case 'l': - return 'L'; - case 'm': - return 'M'; - case 'n': - return 'N'; - case 'o': - return 'O'; - case 'p': - return 'P'; - case 'q': - return 'Q'; - case 'r': - return 'R'; - case 's': - return 'S'; - case 't': - return 'T'; - case 'u': - return 'U'; - case 'v': - return 'V'; - case 'w': - return 'W'; - case 'x': - return 'X'; - case 'y': - return 'Y'; - case 'z': - return 'Z'; - } - return in; -} - -/* - * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant - * to be locale independent and only compare strings we know are safe for - * this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for - * some further explanation to why this function is necessary. - * - * The function is capable of comparing a-z case insensitively even for - * non-ascii. - */ - -int Curl_raw_equal(const char *first, const char *second) -{ - while(*first && *second) { - if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) - /* get out of the loop as soon as they don't match */ - break; - first++; - second++; - } - /* we do the comparison here (possibly again), just to make sure that if the - loop above is skipped because one of the strings reached zero, we must not - return this as a successful match */ - return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second)); -} - -int Curl_raw_nequal(const char *first, const char *second, size_t max) -{ - while(*first && *second && max) { - if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) { - break; - } - max--; - first++; - second++; - } - if(0 == max) - return 1; /* they are equal this far */ - - return Curl_raw_toupper(*first) == Curl_raw_toupper(*second); -} - -/* Copy an upper case version of the string from src to dest. The - * strings may overlap. No more than n characters of the string are copied - * (including any NUL) and the destination string will NOT be - * NUL-terminated if that limit is reached. - */ -void Curl_strntoupper(char *dest, const char *src, size_t n) -{ - if (n < 1) - return; - - do { - *dest++ = Curl_raw_toupper(*src); - } while (*src++ && --n); -} diff --git a/third_party/curl/lib/rawstr.h b/third_party/curl/lib/rawstr.h deleted file mode 100644 index 59633b7f5..000000000 --- a/third_party/curl/lib/rawstr.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __RAWSTR_H -#define __RAWSTR_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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_raw_equal() is for doing "raw" case insensitive strings. This is meant - * to be locale independent and only compare strings we know are safe for - * this. - * - * The function is capable of comparing a-z case insensitively even for non-ascii. - */ -int Curl_raw_equal(const char *first, const char *second); -int Curl_raw_nequal(const char *first, const char *second, size_t max); - -char Curl_raw_toupper(char in); - -/* checkprefix() is a shorter version of the above, used when the first - argument is zero-byte terminated */ -#define checkprefix(a,b) Curl_raw_nequal(a,b,strlen(a)) - -void Curl_strntoupper(char *dest, const char *src, size_t n); -#endif diff --git a/third_party/curl/lib/rtsp.c b/third_party/curl/lib/rtsp.c deleted file mode 100644 index 14f430c88..000000000 --- a/third_party/curl/lib/rtsp.c +++ /dev/null @@ -1,788 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef CURL_DISABLE_RTSP - -#include "urldata.h" -#include -#include "transfer.h" -#include "sendf.h" -#include "multiif.h" -#include "http.h" -#include "url.h" -#include "progress.h" -#include "rtsp.h" -#include "rawstr.h" -#include "curl_memory.h" -#include "select.h" -#include "connect.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -/* - * TODO (general) - * -incoming server requests - * -server CSeq counter - * -digest authentication - * -connect thru proxy - * -pipelining? - */ - - -#define RTP_PKT_CHANNEL(p) ((int)((unsigned char)((p)[1]))) - -#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \ - ((int)((unsigned char)((p)[3])))) - -static int rtsp_getsock_do(struct connectdata *conn, - curl_socket_t *socks, - int numsocks); - -/* this returns the socket to wait for in the DO and DOING state for the multi - interface and then we're always _sending_ a request and thus we wait for - the single socket to become writable only */ -static int rtsp_getsock_do(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - /* write mode */ - (void)numsocks; /* unused, we trust it to be at least 1 */ - socks[0] = conn->sock[FIRSTSOCKET]; - return GETSOCK_WRITESOCK(0); -} - -static -CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len); - - -/* - * RTSP handler interface. - */ -const struct Curl_handler Curl_handler_rtsp = { - "RTSP", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_rtsp, /* do_it */ - Curl_rtsp_done, /* done */ - ZERO_NULL, /* do_more */ - Curl_rtsp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - rtsp_getsock_do, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - Curl_rtsp_disconnect, /* disconnect */ - PORT_RTSP, /* defport */ - CURLPROTO_RTSP, /* protocol */ - PROTOPT_NONE /* flags */ -}; - -/* - * The server may send us RTP data at any point, and RTSPREQ_RECEIVE does not - * want to block the application forever while receiving a stream. Therefore, - * we cannot assume that an RTSP socket is dead just because it is readable. - * - * Instead, if it is readable, run Curl_getconnectinfo() to peek at the socket - * and distinguish between closed and data. - */ -bool Curl_rtsp_connisdead(struct connectdata *check) -{ - int sval; - bool ret_val = TRUE; - - sval = Curl_socket_ready(check->sock[FIRSTSOCKET], CURL_SOCKET_BAD, 0); - if(sval == 0) { - /* timeout */ - ret_val = FALSE; - } - else if (sval & CURL_CSELECT_ERR) { - /* socket is in an error state */ - ret_val = TRUE; - } - else if ((sval & CURL_CSELECT_IN) && check->data) { - /* readable with no error. could be closed or could be alive but we can - only check if we have a proper SessionHandle for the connection */ - curl_socket_t connectinfo = Curl_getconnectinfo(check->data, &check); - if(connectinfo != CURL_SOCKET_BAD) - ret_val = FALSE; - } - - return ret_val; -} - -CURLcode Curl_rtsp_connect(struct connectdata *conn, bool *done) -{ - CURLcode httpStatus; - struct SessionHandle *data = conn->data; - - httpStatus = Curl_http_connect(conn, done); - - /* Initialize the CSeq if not already done */ - if(data->state.rtsp_next_client_CSeq == 0) - data->state.rtsp_next_client_CSeq = 1; - if(data->state.rtsp_next_server_CSeq == 0) - data->state.rtsp_next_server_CSeq = 1; - - conn->proto.rtspc.rtp_channel = -1; - - return httpStatus; -} - -CURLcode Curl_rtsp_disconnect(struct connectdata *conn, bool dead_connection) -{ - (void) dead_connection; - Curl_safefree(conn->proto.rtspc.rtp_buf); - return CURLE_OK; -} - - -CURLcode Curl_rtsp_done(struct connectdata *conn, - CURLcode status, bool premature) -{ - struct SessionHandle *data = conn->data; - struct RTSP *rtsp = data->state.proto.rtsp; - CURLcode httpStatus; - long CSeq_sent; - long CSeq_recv; - - /* Bypass HTTP empty-reply checks on receive */ - if(data->set.rtspreq == RTSPREQ_RECEIVE) - premature = TRUE; - - httpStatus = Curl_http_done(conn, status, premature); - - if(rtsp) { - /* Check the sequence numbers */ - CSeq_sent = rtsp->CSeq_sent; - CSeq_recv = rtsp->CSeq_recv; - if((data->set.rtspreq != RTSPREQ_RECEIVE) && (CSeq_sent != CSeq_recv)) { - failf(data, "The CSeq of this request %ld did not match the response %ld", - CSeq_sent, CSeq_recv); - return CURLE_RTSP_CSEQ_ERROR; - } - else if(data->set.rtspreq == RTSPREQ_RECEIVE && - (conn->proto.rtspc.rtp_channel == -1)) { - infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv); - /* TODO CPC: Server -> Client logic here */ - } - } - - return httpStatus; -} - -CURLcode Curl_rtsp(struct connectdata *conn, bool *done) -{ - struct SessionHandle *data = conn->data; - CURLcode result=CURLE_OK; - Curl_RtspReq rtspreq = data->set.rtspreq; - struct RTSP *rtsp; - struct HTTP *http; - Curl_send_buffer *req_buffer; - curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */ - curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */ - - const char *p_request = NULL; - const char *p_session_id = NULL; - const char *p_accept = NULL; - const char *p_accept_encoding = NULL; - const char *p_range = NULL; - const char *p_referrer = NULL; - const char *p_stream_uri = NULL; - const char *p_transport = NULL; - const char *p_uagent = NULL; - - *done = TRUE; - - Curl_reset_reqproto(conn); - - if(!data->state.proto.rtsp) { - /* Only allocate this struct if we don't already have it! */ - - rtsp = calloc(1, sizeof(struct RTSP)); - if(!rtsp) - return CURLE_OUT_OF_MEMORY; - data->state.proto.rtsp = rtsp; - } - else { - rtsp = data->state.proto.rtsp; - } - - http = &(rtsp->http_wrapper); - /* Assert that no one has changed the RTSP struct in an evil way */ - DEBUGASSERT((void *)http == (void *)rtsp); - - rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq; - rtsp->CSeq_recv = 0; - - /* Setup the 'p_request' pointer to the proper p_request string - * Since all RTSP requests are included here, there is no need to - * support custom requests like HTTP. - **/ - DEBUGASSERT((rtspreq > RTSPREQ_NONE && rtspreq < RTSPREQ_LAST)); - data->set.opt_no_body = TRUE; /* most requests don't contain a body */ - switch(rtspreq) { - case RTSPREQ_NONE: - failf(data, "Got invalid RTSP request: RTSPREQ_NONE"); - return CURLE_BAD_FUNCTION_ARGUMENT; - case RTSPREQ_OPTIONS: - p_request = "OPTIONS"; - break; - case RTSPREQ_DESCRIBE: - p_request = "DESCRIBE"; - data->set.opt_no_body = FALSE; - break; - case RTSPREQ_ANNOUNCE: - p_request = "ANNOUNCE"; - break; - case RTSPREQ_SETUP: - p_request = "SETUP"; - break; - case RTSPREQ_PLAY: - p_request = "PLAY"; - break; - case RTSPREQ_PAUSE: - p_request = "PAUSE"; - break; - case RTSPREQ_TEARDOWN: - p_request = "TEARDOWN"; - break; - case RTSPREQ_GET_PARAMETER: - /* GET_PARAMETER's no_body status is determined later */ - p_request = "GET_PARAMETER"; - break; - case RTSPREQ_SET_PARAMETER: - p_request = "SET_PARAMETER"; - break; - case RTSPREQ_RECORD: - p_request = "RECORD"; - break; - case RTSPREQ_RECEIVE: - p_request = ""; - /* Treat interleaved RTP as body*/ - data->set.opt_no_body = FALSE; - break; - case RTSPREQ_LAST: - failf(data, "Got invalid RTSP request: RTSPREQ_LAST"); - return CURLE_BAD_FUNCTION_ARGUMENT; - } - - if(rtspreq == RTSPREQ_RECEIVE) { - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, -1, NULL); - - return result; - } - - p_session_id = data->set.str[STRING_RTSP_SESSION_ID]; - if(!p_session_id && - (rtspreq & ~(RTSPREQ_OPTIONS | RTSPREQ_DESCRIBE | RTSPREQ_SETUP))) { - failf(data, "Refusing to issue an RTSP request [%s] without a session ID.", - p_request ? p_request : ""); - return CURLE_BAD_FUNCTION_ARGUMENT; - } - - /* TODO: auth? */ - /* TODO: proxy? */ - - /* Stream URI. Default to server '*' if not specified */ - if(data->set.str[STRING_RTSP_STREAM_URI]) { - p_stream_uri = data->set.str[STRING_RTSP_STREAM_URI]; - } - else { - p_stream_uri = "*"; - } - - /* Transport Header for SETUP requests */ - p_transport = Curl_checkheaders(data, "Transport:"); - if(rtspreq == RTSPREQ_SETUP && !p_transport) { - /* New Transport: setting? */ - if(data->set.str[STRING_RTSP_TRANSPORT]) { - Curl_safefree(conn->allocptr.rtsp_transport); - - conn->allocptr.rtsp_transport = - aprintf("Transport: %s\r\n", - data->set.str[STRING_RTSP_TRANSPORT]); - if(!conn->allocptr.rtsp_transport) - return CURLE_OUT_OF_MEMORY; - } - else { - failf(data, - "Refusing to issue an RTSP SETUP without a Transport: header."); - return CURLE_BAD_FUNCTION_ARGUMENT; - } - - p_transport = conn->allocptr.rtsp_transport; - } - - /* Accept Headers for DESCRIBE requests */ - if(rtspreq == RTSPREQ_DESCRIBE) { - /* Accept Header */ - p_accept = Curl_checkheaders(data, "Accept:")? - NULL:"Accept: application/sdp\r\n"; - - /* Accept-Encoding header */ - if(!Curl_checkheaders(data, "Accept-Encoding:") && - data->set.str[STRING_ENCODING]) { - Curl_safefree(conn->allocptr.accept_encoding); - conn->allocptr.accept_encoding = - aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); - - if(!conn->allocptr.accept_encoding) - return CURLE_OUT_OF_MEMORY; - - p_accept_encoding = conn->allocptr.accept_encoding; - } - } - - /* The User-Agent string might have been allocated in url.c already, because - it might have been used in the proxy connect, but if we have got a header - with the user-agent string specified, we erase the previously made string - here. */ - if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) { - Curl_safefree(conn->allocptr.uagent); - conn->allocptr.uagent = NULL; - } - else if(!Curl_checkheaders(data, "User-Agent:") && - data->set.str[STRING_USERAGENT]) { - p_uagent = conn->allocptr.uagent; - } - - /* Referrer */ - Curl_safefree(conn->allocptr.ref); - if(data->change.referer && !Curl_checkheaders(data, "Referer:")) - conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); - else - conn->allocptr.ref = NULL; - - p_referrer = conn->allocptr.ref; - - /* - * Range Header - * Only applies to PLAY, PAUSE, RECORD - * - * Go ahead and use the Range stuff supplied for HTTP - */ - if(data->state.use_range && - (rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) { - - /* Check to see if there is a range set in the custom headers */ - if(!Curl_checkheaders(data, "Range:") && data->state.range) { - Curl_safefree(conn->allocptr.rangeline); - conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range); - p_range = conn->allocptr.rangeline; - } - } - - /* - * Sanity check the custom headers - */ - if(Curl_checkheaders(data, "CSeq:")) { - failf(data, "CSeq cannot be set as a custom header."); - return CURLE_RTSP_CSEQ_ERROR; - } - if(Curl_checkheaders(data, "Session:")) { - failf(data, "Session ID cannot be set as a custom header."); - return CURLE_BAD_FUNCTION_ARGUMENT; - } - - /* Initialize a dynamic send buffer */ - req_buffer = Curl_add_buffer_init(); - - if(!req_buffer) - return CURLE_OUT_OF_MEMORY; - - result = - Curl_add_bufferf(req_buffer, - "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */ - "CSeq: %ld\r\n", /* CSeq */ - (p_request ? p_request : ""), p_stream_uri, - rtsp->CSeq_sent); - if(result) - return result; - - /* - * Rather than do a normal alloc line, keep the session_id unformatted - * to make comparison easier - */ - if(p_session_id) { - result = Curl_add_bufferf(req_buffer, "Session: %s\r\n", p_session_id); - if(result) - return result; - } - - /* - * Shared HTTP-like options - */ - result = Curl_add_bufferf(req_buffer, - "%s" /* transport */ - "%s" /* accept */ - "%s" /* accept-encoding */ - "%s" /* range */ - "%s" /* referrer */ - "%s" /* user-agent */ - , - p_transport ? p_transport : "", - p_accept ? p_accept : "", - p_accept_encoding ? p_accept_encoding : "", - p_range ? p_range : "", - p_referrer ? p_referrer : "", - p_uagent ? p_uagent : ""); - if(result) - return result; - - if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) { - result = Curl_add_timecondition(data, req_buffer); - if(result) - return result; - } - - result = Curl_add_custom_headers(conn, req_buffer); - if(result) - return result; - - if(rtspreq == RTSPREQ_ANNOUNCE || - rtspreq == RTSPREQ_SET_PARAMETER || - rtspreq == RTSPREQ_GET_PARAMETER) { - - if(data->set.upload) { - putsize = data->set.infilesize; - data->set.httpreq = HTTPREQ_PUT; - - } - else { - postsize = (data->set.postfieldsize != -1)? - data->set.postfieldsize: - (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); - data->set.httpreq = HTTPREQ_POST; - } - - if(putsize > 0 || postsize > 0) { - /* As stated in the http comments, it is probably not wise to - * actually set a custom Content-Length in the headers */ - if(!Curl_checkheaders(data, "Content-Length:")) { - result = Curl_add_bufferf(req_buffer, - "Content-Length: %" FORMAT_OFF_T"\r\n", - (data->set.upload ? putsize : postsize)); - if(result) - return result; - } - - if(rtspreq == RTSPREQ_SET_PARAMETER || - rtspreq == RTSPREQ_GET_PARAMETER) { - if(!Curl_checkheaders(data, "Content-Type:")) { - result = Curl_add_bufferf(req_buffer, - "Content-Type: text/parameters\r\n"); - if(result) - return result; - } - } - - if(rtspreq == RTSPREQ_ANNOUNCE) { - if(!Curl_checkheaders(data, "Content-Type:")) { - result = Curl_add_bufferf(req_buffer, - "Content-Type: application/sdp\r\n"); - if(result) - return result; - } - } - - data->state.expect100header = FALSE; /* RTSP posts are simple/small */ - } else if(rtspreq == RTSPREQ_GET_PARAMETER) { - /* Check for an empty GET_PARAMETER (heartbeat) request */ - data->set.httpreq = HTTPREQ_HEAD; - data->set.opt_no_body = TRUE; - } - } - - /* RTSP never allows chunked transfer */ - data->req.forbidchunk = TRUE; - /* Finish the request buffer */ - result = Curl_add_buffer(req_buffer, "\r\n", 2); - if(result) - return result; - - if(postsize > 0) { - result = Curl_add_buffer(req_buffer, data->set.postfields, - (size_t)postsize); - if(result) - return result; - } - - /* issue the request */ - result = Curl_add_buffer_send(req_buffer, conn, - &data->info.request_size, 0, FIRSTSOCKET); - if(result) { - failf(data, "Failed sending RTSP request"); - return result; - } - - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - putsize?FIRSTSOCKET:-1, - putsize?&http->writebytecount:NULL); - - /* Increment the CSeq on success */ - data->state.rtsp_next_client_CSeq++; - - if(http->writebytecount) { - /* if a request-body has been sent off, we make sure this progress is - noted properly */ - Curl_pgrsSetUploadCounter(data, http->writebytecount); - if(Curl_pgrsUpdate(conn)) - result = CURLE_ABORTED_BY_CALLBACK; - } - - return result; -} - -CURLcode Curl_rtsp_rtp_readwrite(struct SessionHandle *data, - struct connectdata *conn, - ssize_t *nread, - bool *readmore) { - struct SingleRequest *k = &data->req; - struct rtsp_conn *rtspc = &(conn->proto.rtspc); - - char *rtp; /* moving pointer to rtp data */ - ssize_t rtp_dataleft; /* how much data left to parse in this round */ - char *scratch; - CURLcode result; - - if(rtspc->rtp_buf) { - /* There was some leftover data the last time. Merge buffers */ - char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread); - if(!newptr) { - Curl_safefree(rtspc->rtp_buf); - rtspc->rtp_buf = NULL; - rtspc->rtp_bufsize = 0; - return CURLE_OUT_OF_MEMORY; - } - rtspc->rtp_buf = newptr; - memcpy(rtspc->rtp_buf + rtspc->rtp_bufsize, k->str, *nread); - rtspc->rtp_bufsize += *nread; - rtp = rtspc->rtp_buf; - rtp_dataleft = rtspc->rtp_bufsize; - } - else { - /* Just parse the request buffer directly */ - rtp = k->str; - rtp_dataleft = *nread; - } - - while((rtp_dataleft > 0) && - (rtp[0] == '$')) { - if(rtp_dataleft > 4) { - int rtp_length; - - /* Parse the header */ - /* The channel identifier immediately follows and is 1 byte */ - rtspc->rtp_channel = RTP_PKT_CHANNEL(rtp); - - /* The length is two bytes */ - rtp_length = RTP_PKT_LENGTH(rtp); - - if(rtp_dataleft < rtp_length + 4) { - /* Need more - incomplete payload*/ - *readmore = TRUE; - break; - } - else { - /* We have the full RTP interleaved packet - * Write out the header including the leading '$' */ - DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n", - rtspc->rtp_channel, rtp_length)); - result = rtp_client_write(conn, &rtp[0], rtp_length + 4); - if(result) { - failf(data, "Got an error writing an RTP packet"); - *readmore = FALSE; - Curl_safefree(rtspc->rtp_buf); - rtspc->rtp_buf = NULL; - rtspc->rtp_bufsize = 0; - return result; - } - - /* Move forward in the buffer */ - rtp_dataleft -= rtp_length + 4; - rtp += rtp_length + 4; - - if(data->set.rtspreq == RTSPREQ_RECEIVE) { - /* If we are in a passive receive, give control back - * to the app as often as we can. - */ - k->keepon &= ~KEEP_RECV; - } - } - } - else { - /* Need more - incomplete header */ - *readmore = TRUE; - break; - } - } - - if(rtp_dataleft != 0 && rtp[0] == '$') { - DEBUGF(infof(data, "RTP Rewinding %zu %s\n", rtp_dataleft, - *readmore ? "(READMORE)" : "")); - - /* Store the incomplete RTP packet for a "rewind" */ - scratch = malloc(rtp_dataleft); - if(!scratch) { - Curl_safefree(rtspc->rtp_buf); - rtspc->rtp_buf = NULL; - rtspc->rtp_bufsize = 0; - return CURLE_OUT_OF_MEMORY; - } - memcpy(scratch, rtp, rtp_dataleft); - Curl_safefree(rtspc->rtp_buf); - rtspc->rtp_buf = scratch; - rtspc->rtp_bufsize = rtp_dataleft; - - /* As far as the transfer is concerned, this data is consumed */ - *nread = 0; - return CURLE_OK; - } - else { - /* Fix up k->str to point just after the last RTP packet */ - k->str += *nread - rtp_dataleft; - - /* either all of the data has been read or... - * rtp now points at the next byte to parse - */ - if(rtp_dataleft > 0) - DEBUGASSERT(k->str[0] == rtp[0]); - - DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */ - - *nread = rtp_dataleft; - } - - /* If we get here, we have finished with the leftover/merge buffer */ - Curl_safefree(rtspc->rtp_buf); - rtspc->rtp_buf = NULL; - rtspc->rtp_bufsize = 0; - - return CURLE_OK; -} - -static -CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len) -{ - struct SessionHandle *data = conn->data; - size_t wrote; - curl_write_callback writeit; - - if(len == 0) { - failf (data, "Cannot write a 0 size RTP packet."); - return CURLE_WRITE_ERROR; - } - - writeit = data->set.fwrite_rtp?data->set.fwrite_rtp:data->set.fwrite_func; - wrote = writeit(ptr, 1, len, data->set.rtp_out); - - if(CURL_WRITEFUNC_PAUSE == wrote) { - failf (data, "Cannot pause RTP"); - return CURLE_WRITE_ERROR; - } - - if(wrote != len) { - failf (data, "Failed writing RTP data"); - return CURLE_WRITE_ERROR; - } - - return CURLE_OK; -} - -CURLcode Curl_rtsp_parseheader(struct connectdata *conn, - char *header) -{ - struct SessionHandle *data = conn->data; - long CSeq = 0; - - if(checkprefix("CSeq:", header)) { - /* Store the received CSeq. Match is verified in rtsp_done */ - int nc; - char *temp = strdup(header); - if(!temp) - return CURLE_OUT_OF_MEMORY; - Curl_strntoupper(temp, temp, sizeof(temp)); - nc = sscanf(temp, "CSEQ: %ld", &CSeq); - free(temp); - if(nc == 1) { - data->state.proto.rtsp->CSeq_recv = CSeq; /* mark the request */ - data->state.rtsp_CSeq_recv = CSeq; /* update the handle */ - } - else { - failf(data, "Unable to read the CSeq header: [%s]", header); - return CURLE_RTSP_CSEQ_ERROR; - } - } - else if(checkprefix("Session:", header)) { - char *start; - - /* Find the first non-space letter */ - start = header + 9; - while(*start && ISSPACE(*start)) - start++; - - if(!*start) { - failf(data, "Got a blank Session ID"); - } - else if(data->set.str[STRING_RTSP_SESSION_ID]) { - /* If the Session ID is set, then compare */ - if(strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], - strlen(data->set.str[STRING_RTSP_SESSION_ID])) != 0) { - failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]", - start, data->set.str[STRING_RTSP_SESSION_ID]); - return CURLE_RTSP_SESSION_ERROR; - } - } - else { - /* If the Session ID is not set, and we find it in a response, then - set it */ - - /* The session ID can be an alphanumeric or a 'safe' character - * - * RFC 2326 15.1 Base Syntax: - * safe = "\$" | "-" | "_" | "." | "+" - * */ - char *end = start; - while(*end && - (ISALNUM(*end) || *end == '-' || *end == '_' || *end == '.' || - *end == '+' || - (*end == '\\' && *(end + 1) && *(end + 1) == '$' && (++end, 1)))) - end++; - - /* Copy the id substring into a new buffer */ - data->set.str[STRING_RTSP_SESSION_ID] = malloc(end - start + 1); - if(data->set.str[STRING_RTSP_SESSION_ID] == NULL) - return CURLE_OUT_OF_MEMORY; - memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, end - start); - (data->set.str[STRING_RTSP_SESSION_ID])[end - start] = '\0'; - } - } - return CURLE_OK; -} - -#endif /* CURL_DISABLE_RTSP */ diff --git a/third_party/curl/lib/rtsp.h b/third_party/curl/lib/rtsp.h deleted file mode 100644 index 2e2074edc..000000000 --- a/third_party/curl/lib/rtsp.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef __RTSP_H_ -#define __RTSP_H_ - -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#ifndef CURL_DISABLE_RTSP - -extern const struct Curl_handler Curl_handler_rtsp; - -/* - * Parse and write out any available RTP data. - * - * nread: amount of data left after k->str. will be modified if RTP - * data is parsed and k->str is moved up - * readmore: whether or not the RTP parser needs more data right away - */ -CURLcode Curl_rtsp_rtp_readwrite(struct SessionHandle *data, - struct connectdata *conn, - ssize_t *nread, - bool *readmore); - - -/* protocol-specific functions set up to be called by the main engine */ -CURLcode Curl_rtsp(struct connectdata *conn, bool *done); -CURLcode Curl_rtsp_done(struct connectdata *conn, CURLcode, bool premature); -CURLcode Curl_rtsp_connect(struct connectdata *conn, bool *done); -CURLcode Curl_rtsp_disconnect(struct connectdata *conn, bool dead_connection); - -CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header); -bool Curl_rtsp_connisdead(struct connectdata *check); - -#else -/* disabled */ -#define Curl_rtsp_connisdead(x) TRUE - -#endif /* CURL_DISABLE_RTSP */ - -/* - * RTSP Connection data - * - * Currently, only used for tracking incomplete RTP data reads - */ -struct rtsp_conn { - char *rtp_buf; - ssize_t rtp_bufsize; - int rtp_channel; -}; - -/**************************************************************************** - * RTSP unique setup - ***************************************************************************/ -struct RTSP { - /* - * http_wrapper MUST be the first element of this structure for the wrap - * logic to work. In this way, we get a cheap polymorphism because - * &(data->state.proto.rtsp) == &(data->state.proto.http) per the C spec - * - * HTTP functions can safely treat this as an HTTP struct, but RTSP aware - * functions can also index into the later elements. - */ - struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */ - - long CSeq_sent; /* CSeq of this request */ - long CSeq_recv; /* CSeq received */ -}; - - -#endif /* __RTSP_H_ */ diff --git a/third_party/curl/lib/security.c b/third_party/curl/lib/security.c deleted file mode 100644 index c4fc88af8..000000000 --- a/third_party/curl/lib/security.c +++ /dev/null @@ -1,591 +0,0 @@ -/* This source code was modified by Martin Hedenfalk for - * use in Curl. His latest changes were done 2000-09-18. - * - * It has since been patched and modified a lot by Daniel Stenberg - * to make it better applied to curl conditions, and to make - * it not use globals, pollute name space and more. This source code awaits a - * rewrite to work around the paragraph 2 in the BSD licenses as explained - * below. - * - * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * - * Copyright (C) 2001 - 2010, Daniel Stenberg, , et al. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. */ - -#include "setup.h" - -#ifndef CURL_DISABLE_FTP -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - -#include -#include - -#ifdef HAVE_NETDB_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include "urldata.h" -#include "curl_base64.h" -#include "curl_memory.h" -#include "krb4.h" -#include "ftp.h" -#include "sendf.h" -#include "rawstr.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -static const struct { - enum protection_level level; - const char *name; -} level_names[] = { - { PROT_CLEAR, "clear" }, - { PROT_SAFE, "safe" }, - { PROT_CONFIDENTIAL, "confidential" }, - { PROT_PRIVATE, "private" } -}; - -static enum protection_level -name_to_level(const char *name) -{ - int i; - for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++) - if(checkprefix(name, level_names[i].name)) - return level_names[i].level; - return PROT_NONE; -} - -/* Convert a protocol |level| to its char representation. - We take an int to catch programming mistakes. */ -static char level_to_char(int level) { - switch(level) { - case PROT_CLEAR: - return 'C'; - case PROT_SAFE: - return 'S'; - case PROT_CONFIDENTIAL: - return 'E'; - case PROT_PRIVATE: - return 'P'; - case PROT_CMD: - /* Fall through */ - default: - /* Those 2 cases should not be reached! */ - break; - } - DEBUGASSERT(0); - /* Default to the most secure alternative. */ - return 'P'; -} - -static const struct Curl_sec_client_mech * const mechs[] = { -#if defined(HAVE_GSSAPI) - &Curl_krb5_client_mech, -#endif -#if defined(HAVE_KRB4) - &Curl_krb4_client_mech, -#endif - NULL -}; - -/* Send an FTP command defined by |message| and the optional arguments. The - function returns the ftp_code. If an error occurs, -1 is returned. */ -static int ftp_send_command(struct connectdata *conn, const char *message, ...) -{ - int ftp_code; - ssize_t nread; - va_list args; - char print_buffer[50]; - - va_start(args, message); - vsnprintf(print_buffer, sizeof(print_buffer), message, args); - va_end(args); - - if(Curl_ftpsendf(conn, print_buffer) != CURLE_OK) { - ftp_code = -1; - } - else { - if(Curl_GetFTPResponse(&nread, conn, &ftp_code) != CURLE_OK) - ftp_code = -1; - } - - (void)nread; /* Unused */ - return ftp_code; -} - -/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode - saying whether an error occurred or CURLE_OK if |len| was read. */ -static CURLcode -socket_read(curl_socket_t fd, void *to, size_t len) -{ - char *to_p = to; - CURLcode code; - ssize_t nread; - - while(len > 0) { - code = Curl_read_plain(fd, to_p, len, &nread); - if(code == CURLE_OK) { - len -= nread; - to_p += nread; - } - else { - /* FIXME: We are doing a busy wait */ - if(code == CURLE_AGAIN) - continue; - return code; - } - } - return CURLE_OK; -} - - -/* Write |len| bytes from the buffer |to| to the socket |fd|. Return a - CURLcode saying whether an error occurred or CURLE_OK if |len| was - written. */ -static CURLcode -socket_write(struct connectdata *conn, curl_socket_t fd, const void *to, - size_t len) -{ - const char *to_p = to; - CURLcode code; - ssize_t written; - - while(len > 0) { - code = Curl_write_plain(conn, fd, to_p, len, &written); - if(code == CURLE_OK) { - len -= written; - to_p += written; - } - else { - /* FIXME: We are doing a busy wait */ - if(code == CURLE_AGAIN) - continue; - return code; - } - } - return CURLE_OK; -} - -static CURLcode read_data(struct connectdata *conn, - curl_socket_t fd, - struct krb4buffer *buf) -{ - int len; - void* tmp; - CURLcode ret; - - ret = socket_read(fd, &len, sizeof(len)); - if (ret != CURLE_OK) - return ret; - - len = ntohl(len); - tmp = realloc(buf->data, len); - if (tmp == NULL) - return CURLE_OUT_OF_MEMORY; - - buf->data = tmp; - ret = socket_read(fd, buf->data, len); - if (ret != CURLE_OK) - return ret; - buf->size = conn->mech->decode(conn->app_data, buf->data, len, - conn->data_prot, conn); - buf->index = 0; - return CURLE_OK; -} - -static size_t -buffer_read(struct krb4buffer *buf, void *data, size_t len) -{ - if(buf->size - buf->index < len) - len = buf->size - buf->index; - memcpy(data, (char*)buf->data + buf->index, len); - buf->index += len; - return len; -} - -/* Matches Curl_recv signature */ -static ssize_t sec_recv(struct connectdata *conn, int sockindex, - char *buffer, size_t len, CURLcode *err) -{ - size_t bytes_read; - size_t total_read = 0; - curl_socket_t fd = conn->sock[sockindex]; - - *err = CURLE_OK; - - /* Handle clear text response. */ - if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR) - return read(fd, buffer, len); - - if(conn->in_buffer.eof_flag) { - conn->in_buffer.eof_flag = 0; - return 0; - } - - bytes_read = buffer_read(&conn->in_buffer, buffer, len); - len -= bytes_read; - total_read += bytes_read; - buffer += bytes_read; - - while(len > 0) { - if(read_data(conn, fd, &conn->in_buffer) != CURLE_OK) - return -1; - if(conn->in_buffer.size == 0) { - if(bytes_read > 0) - conn->in_buffer.eof_flag = 1; - return bytes_read; - } - bytes_read = buffer_read(&conn->in_buffer, buffer, len); - len -= bytes_read; - total_read += bytes_read; - buffer += bytes_read; - } - /* FIXME: Check for overflow */ - return total_read; -} - -/* Send |length| bytes from |from| to the |fd| socket taking care of encoding - and negociating with the server. |from| can be NULL. */ -/* FIXME: We don't check for errors nor report any! */ -static void do_sec_send(struct connectdata *conn, curl_socket_t fd, - const char *from, int length) -{ - size_t bytes; - size_t htonl_bytes; - char *buffer; - char *cmd_buffer; - enum protection_level prot_level = conn->data_prot; - bool iscmd = prot_level == PROT_CMD; - - DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST); - - if(iscmd) { - if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5)) - prot_level = PROT_PRIVATE; - else - prot_level = conn->command_prot; - } - bytes = conn->mech->encode(conn->app_data, from, length, prot_level, - (void**)&buffer, conn); - if(iscmd) { - bytes = Curl_base64_encode(conn->data, buffer, bytes, &cmd_buffer); - if(bytes > 0) { - static const char *enc = "ENC "; - static const char *mic = "MIC "; - if(prot_level == PROT_PRIVATE) - socket_write(conn, fd, enc, 4); - else - socket_write(conn, fd, mic, 4); - - socket_write(conn, fd, cmd_buffer, bytes); - socket_write(conn, fd, "\r\n", 2); - infof(conn->data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic, - cmd_buffer); - free(cmd_buffer); - } - } - else { - htonl_bytes = htonl(bytes); - socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes)); - socket_write(conn, fd, buffer, bytes); - } - free(buffer); -} - -static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd, - const char *buffer, size_t length) -{ - /* FIXME: Check for overflow */ - ssize_t len = conn->buffer_size; - int tx = 0; - - len -= conn->mech->overhead(conn->app_data, conn->data_prot, len); - if(len <= 0) - len = length; - while(length) { - if(len >= 0 || length < (size_t)len) { - /* FIXME: Check for overflow. */ - len = length; - } - do_sec_send(conn, fd, buffer, len); - length -= len; - buffer += len; - tx += len; - } - return tx; -} - -/* Matches Curl_send signature */ -static ssize_t sec_send(struct connectdata *conn, int sockindex, - const void *buffer, size_t len, CURLcode *err) -{ - curl_socket_t fd = conn->sock[sockindex]; - *err = CURLE_OK; - return sec_write(conn, fd, buffer, len); -} - -int Curl_sec_read_msg(struct connectdata *conn, char *buffer, - enum protection_level level) -{ - /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an - int */ - int decoded_len; - char *buf; - int ret_code; - - DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); - - decoded_len = Curl_base64_decode(buffer + 4, (unsigned char **)&buf); - if(decoded_len <= 0) { - free(buf); - return -1; - } - - decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len, - level, conn); - if(decoded_len <= 0) { - free(buf); - return -1; - } - - if(conn->data->set.verbose) { - buf[decoded_len] = '\n'; - Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1, conn); - } - - buf[decoded_len] = '\0'; - DEBUGASSERT(decoded_len > 3); - if(buf[3] == '-') - ret_code = 0; - else { - /* Check for error? */ - sscanf(buf, "%d", &ret_code); - } - - if(buf[decoded_len - 1] == '\n') - buf[decoded_len - 1] = '\0'; - /* FIXME: Is |buffer| length always greater than |decoded_len|? */ - strcpy(buffer, buf); - free(buf); - return ret_code; -} - -/* FIXME: The error code returned here is never checked. */ -static int sec_set_protection_level(struct connectdata *conn) -{ - int code; - char* pbsz; - static unsigned int buffer_size = 1 << 20; /* 1048576 */ - enum protection_level level = conn->request_data_prot; - - DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); - - if(!conn->sec_complete) { - infof(conn->data, "Trying to change the protection level after the" - "completion of the data exchange.\n"); - return -1; - } - - /* Bail out if we try to set up the same level */ - if(conn->data_prot == level) - return 0; - - if(level) { - code = ftp_send_command(conn, "PBSZ %u", buffer_size); - if(code < 0) - return -1; - - if(code/100 != 2) { - failf(conn->data, "Failed to set the protection's buffer size."); - return -1; - } - conn->buffer_size = buffer_size; - - pbsz = strstr(conn->data->state.buffer, "PBSZ="); - if(pbsz) { - /* FIXME: Checks for errors in sscanf? */ - sscanf(pbsz, "PBSZ=%u", &buffer_size); - if(buffer_size < conn->buffer_size) - conn->buffer_size = buffer_size; - } - } - - /* Now try to negiociate the protection level. */ - code = ftp_send_command(conn, "PROT %c", level_to_char(level)); - - if(code < 0) - return -1; - - if(code/100 != 2) { - failf(conn->data, "Failed to set the protection level."); - return -1; - } - - conn->data_prot = level; - if(level == PROT_PRIVATE) - conn->command_prot = level; - - return 0; -} - -int -Curl_sec_request_prot(struct connectdata *conn, const char *level) -{ - enum protection_level l = name_to_level(level); - if(l == PROT_NONE) - return -1; - DEBUGASSERT(l > PROT_NONE && l < PROT_LAST); - conn->request_data_prot = l; - return 0; -} - -static CURLcode choose_mech(struct connectdata *conn) -{ - int ret; - struct SessionHandle *data = conn->data; - const struct Curl_sec_client_mech * const *mech; - void *tmp_allocation; - const char *mech_name; - - for(mech = mechs; (*mech); ++mech) { - mech_name = (*mech)->name; - /* We have no mechanism with a NULL name but keep this check */ - DEBUGASSERT(mech_name != NULL); - if(mech_name == NULL) { - infof(data, "Skipping mechanism with empty name (%p)\n", mech); - continue; - } - tmp_allocation = realloc(conn->app_data, (*mech)->size); - if(tmp_allocation == NULL) { - failf(data, "Failed realloc of size %u", (*mech)->size); - mech = NULL; - return CURLE_OUT_OF_MEMORY; - } - conn->app_data = tmp_allocation; - - if((*mech)->init) { - ret = (*mech)->init(conn->app_data); - if(ret != 0) { - infof(data, "Failed initialization for %s. Skipping it.\n", mech_name); - continue; - } - } - - infof(data, "Trying mechanism %s...\n", mech_name); - ret = ftp_send_command(conn, "AUTH %s", mech_name); - if(ret < 0) - /* FIXME: This error is too generic but it is OK for now. */ - return CURLE_COULDNT_CONNECT; - - if(ret/100 != 3) { - switch(ret) { - case 504: - infof(data, "Mechanism %s is not supported by the server (server " - "returned ftp code: 504).\n", mech_name); - break; - case 534: - infof(data, "Mechanism %s was rejected by the server (server returned " - "ftp code: 534).\n", mech_name); - break; - default: - if(ret/100 == 5) { - infof(data, "The server does not support the security extensions.\n"); - return CURLE_USE_SSL_FAILED; - } - break; - } - continue; - } - - /* Authenticate */ - ret = (*mech)->auth(conn->app_data, conn); - - if(ret == AUTH_CONTINUE) - continue; - else if(ret != AUTH_OK) { - /* Mechanism has dumped the error to stderr, don't error here. */ - return -1; - } - DEBUGASSERT(ret == AUTH_OK); - - conn->mech = *mech; - conn->sec_complete = 1; - conn->recv[FIRSTSOCKET] = sec_recv; - conn->send[FIRSTSOCKET] = sec_send; - conn->recv[SECONDARYSOCKET] = sec_recv; - conn->send[SECONDARYSOCKET] = sec_send; - conn->command_prot = PROT_SAFE; - /* Set the requested protection level */ - /* BLOCKING */ - (void)sec_set_protection_level(conn); - break; - } - - return mech != NULL ? CURLE_OK : CURLE_FAILED_INIT; -} - -CURLcode -Curl_sec_login(struct connectdata *conn) -{ - return choose_mech(conn); -} - - -void -Curl_sec_end(struct connectdata *conn) -{ - if(conn->mech != NULL && conn->mech->end) - conn->mech->end(conn->app_data); - if(conn->app_data) { - free(conn->app_data); - conn->app_data = NULL; - } - if(conn->in_buffer.data) { - free(conn->in_buffer.data); - conn->in_buffer.data = NULL; - conn->in_buffer.size = 0; - conn->in_buffer.index = 0; - /* FIXME: Is this really needed? */ - conn->in_buffer.eof_flag = 0; - } - conn->sec_complete = 0; - conn->data_prot = PROT_CLEAR; - conn->mech = NULL; -} - -#endif /* HAVE_KRB4 || HAVE_GSSAPI */ - -#endif /* CURL_DISABLE_FTP */ diff --git a/third_party/curl/lib/select.c b/third_party/curl/lib/select.c deleted file mode 100644 index e6882da7a..000000000 --- a/third_party/curl/lib/select.c +++ /dev/null @@ -1,506 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_SYS_SELECT_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE) -#error "We can't compile without select() or poll() support." -#endif - -#if defined(__BEOS__) && !defined(__HAIKU__) -/* BeOS has FD_SET defined in socket.h */ -#include -#endif - -#ifdef MSDOS -#include /* delay() */ -#endif - -#include - -#include "urldata.h" -#include "connect.h" -#include "select.h" - -/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1] */ - -#if defined(USE_WINSOCK) || defined(TPF) -#define VERIFY_SOCK(x) do { } while(0) -#else -#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE)) -#define VERIFY_SOCK(x) do { \ - if(!VALID_SOCK(x)) { \ - SET_SOCKERRNO(EINVAL); \ - return -1; \ - } \ -} while(0) -#endif - -/* Convenience local macros */ - -#define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv) - -#ifdef CURL_ACKNOWLEDGE_EINTR -#define error_not_EINTR (1) -#else -#define error_not_EINTR (error != EINTR) -#endif - -/* - * Internal function used for waiting a specific amount of ms - * in Curl_socket_ready() and Curl_poll() when no file descriptor - * is provided to wait on, just being used to delay execution. - * WinSock select() and poll() timeout mechanisms need a valid - * socket descriptor in a not null file descriptor set to work. - * Waiting indefinitely with this function is not allowed, a - * zero or negative timeout value will return immediately. - * Timeout resolution, accuracy, as well as maximum supported - * value is system dependent, neither factor is a citical issue - * for the intended use of this function in the library. - * On non-DOS and non-Winsock platforms, when compiled with - * CURL_ACKNOWLEDGE_EINTR defined, EINTR condition is honored - * and function might exit early without awaiting full timeout, - * otherwise EINTR will be ignored and full timeout will elapse. - * - * Return values: - * -1 = system call error, invalid timeout value, or interrupted - * 0 = specified timeout has elapsed - */ -static int wait_ms(int timeout_ms) -{ -#if !defined(MSDOS) && !defined(USE_WINSOCK) -#ifndef HAVE_POLL_FINE - struct timeval pending_tv; -#endif - struct timeval initial_tv; - int pending_ms; - int error; -#endif - int r = 0; - - if(!timeout_ms) - return 0; - if(timeout_ms < 0) { - SET_SOCKERRNO(EINVAL); - return -1; - } -#if defined(MSDOS) - delay(timeout_ms); -#elif defined(USE_WINSOCK) - Sleep(timeout_ms); -#else - pending_ms = timeout_ms; - initial_tv = curlx_tvnow(); - do { -#if defined(HAVE_POLL_FINE) - r = poll(NULL, 0, pending_ms); -#else - pending_tv.tv_sec = pending_ms / 1000; - pending_tv.tv_usec = (pending_ms % 1000) * 1000; - r = select(0, NULL, NULL, NULL, &pending_tv); -#endif /* HAVE_POLL_FINE */ - if(r != -1) - break; - error = SOCKERRNO; - if(error && error_not_EINTR) - break; - pending_ms = timeout_ms - elapsed_ms; - if(pending_ms <= 0) - break; - } while(r == -1); -#endif /* USE_WINSOCK */ - if(r) - r = -1; - return r; -} - -/* - * This is an internal function used for waiting for read or write - * events on a pair of file descriptors. It uses poll() when a fine - * poll() is available, in order to avoid limits with FD_SETSIZE, - * otherwise select() is used. An error is returned if select() is - * being used and a file descriptor is too large for FD_SETSIZE. - * A negative timeout value makes this function wait indefinitely, - * unles no valid file descriptor is given, when this happens the - * negative timeout is ignored and the function times out immediately. - * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition - * is honored and function might exit early without awaiting timeout, - * otherwise EINTR will be ignored. - * - * Return values: - * -1 = system call error or fd >= FD_SETSIZE - * 0 = timeout - * CURL_CSELECT_IN | CURL_CSELECT_OUT | CURL_CSELECT_ERR - */ -int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, - int timeout_ms) -{ -#ifdef HAVE_POLL_FINE - struct pollfd pfd[2]; - int num; -#else - struct timeval pending_tv; - struct timeval *ptimeout; - fd_set fds_read; - fd_set fds_write; - fd_set fds_err; - curl_socket_t maxfd; -#endif - struct timeval initial_tv = {0,0}; - int pending_ms = 0; - int error; - int r; - int ret; - - if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) { - r = wait_ms(timeout_ms); - return r; - } - - /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed - time in this function does not need to be measured. This happens - when function is called with a zero timeout or a negative timeout - value indicating a blocking call should be performed. */ - - if(timeout_ms > 0) { - pending_ms = timeout_ms; - initial_tv = curlx_tvnow(); - } - -#ifdef HAVE_POLL_FINE - - num = 0; - if(readfd != CURL_SOCKET_BAD) { - pfd[num].fd = readfd; - pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; - pfd[num].revents = 0; - num++; - } - if(writefd != CURL_SOCKET_BAD) { - pfd[num].fd = writefd; - pfd[num].events = POLLWRNORM|POLLOUT; - pfd[num].revents = 0; - num++; - } - - do { - if(timeout_ms < 0) - pending_ms = -1; - else if(!timeout_ms) - pending_ms = 0; - r = poll(pfd, num, pending_ms); - if(r != -1) - break; - error = SOCKERRNO; - if(error && error_not_EINTR) - break; - if(timeout_ms > 0) { - pending_ms = timeout_ms - elapsed_ms; - if(pending_ms <= 0) - break; - } - } while(r == -1); - - if(r < 0) - return -1; - if(r == 0) - return 0; - - ret = 0; - num = 0; - if(readfd != 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(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(readfd != CURL_SOCKET_BAD) { - VERIFY_SOCK(readfd); - FD_SET(readfd, &fds_read); - FD_SET(readfd, &fds_err); - maxfd = readfd; - } - - 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; - } - r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); - if(r != -1) - break; - error = SOCKERRNO; - if(error && error_not_EINTR) - break; - if(timeout_ms > 0) { - pending_ms = timeout_ms - elapsed_ms; - if(pending_ms <= 0) - break; - } - } while(r == -1); - - if(r < 0) - return -1; - if(r == 0) - return 0; - - ret = 0; - if(readfd != CURL_SOCKET_BAD) { - if(FD_ISSET(readfd, &fds_read)) - ret |= CURL_CSELECT_IN; - if(FD_ISSET(readfd, &fds_err)) - ret |= CURL_CSELECT_ERR; - } - if(writefd != CURL_SOCKET_BAD) { - if(FD_ISSET(writefd, &fds_write)) - ret |= CURL_CSELECT_OUT; - if(FD_ISSET(writefd, &fds_err)) - ret |= CURL_CSELECT_ERR; - } - - return ret; - -#endif /* HAVE_POLL_FINE */ - -} - -/* - * This is a wrapper around poll(). If poll() does not exist, then - * select() is used instead. An error is returned if select() is - * being used and a file descriptor is too large for FD_SETSIZE. - * A negative timeout value makes this function wait indefinitely, - * unles no valid file descriptor is given, when this happens the - * negative timeout is ignored and the function times out immediately. - * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition - * is honored and function might exit early without awaiting timeout, - * otherwise EINTR will be ignored. - * - * Return values: - * -1 = system call error or fd >= FD_SETSIZE - * 0 = timeout - * N = number of structures with non zero revent fields - */ -int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) -{ -#ifndef HAVE_POLL_FINE - struct timeval pending_tv; - struct timeval *ptimeout; - fd_set fds_read; - fd_set fds_write; - fd_set fds_err; - curl_socket_t maxfd; -#endif - struct timeval initial_tv = {0,0}; - bool fds_none = TRUE; - unsigned int i; - int pending_ms = 0; - int error; - int r; - - if(ufds) { - for (i = 0; i < nfds; i++) { - if(ufds[i].fd != CURL_SOCKET_BAD) { - fds_none = FALSE; - break; - } - } - } - if(fds_none) { - r = wait_ms(timeout_ms); - return r; - } - - /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed - time in this function does not need to be measured. This happens - when function is called with a zero timeout or a negative timeout - value indicating a blocking call should be performed. */ - - if(timeout_ms > 0) { - pending_ms = timeout_ms; - initial_tv = curlx_tvnow(); - } - -#ifdef HAVE_POLL_FINE - - do { - if(timeout_ms < 0) - pending_ms = -1; - else if(!timeout_ms) - pending_ms = 0; - r = poll(ufds, nfds, pending_ms); - if(r != -1) - break; - error = SOCKERRNO; - if(error && error_not_EINTR) - break; - if(timeout_ms > 0) { - pending_ms = timeout_ms - elapsed_ms; - if(pending_ms <= 0) - 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); - } - } - - ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; - - do { - if(timeout_ms > 0) { - pending_tv.tv_sec = pending_ms / 1000; - pending_tv.tv_usec = (pending_ms % 1000) * 1000; - } - else if(!timeout_ms) { - pending_tv.tv_sec = 0; - pending_tv.tv_usec = 0; - } - r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); - if(r != -1) - break; - error = SOCKERRNO; - if(error && error_not_EINTR) - break; - if(timeout_ms > 0) { - pending_ms = timeout_ms - elapsed_ms; - if(pending_ms <= 0) - break; - } - } while(r == -1); - - if(r < 0) - return -1; - if(r == 0) - return 0; - - r = 0; - for (i = 0; i < nfds; i++) { - ufds[i].revents = 0; - if(ufds[i].fd == CURL_SOCKET_BAD) - continue; - if(FD_ISSET(ufds[i].fd, &fds_read)) - ufds[i].revents |= POLLIN; - if(FD_ISSET(ufds[i].fd, &fds_write)) - ufds[i].revents |= POLLOUT; - if(FD_ISSET(ufds[i].fd, &fds_err)) - ufds[i].revents |= POLLPRI; - if(ufds[i].revents != 0) - r++; - } - -#endif /* HAVE_POLL_FINE */ - - return r; -} - -#ifdef TPF -/* - * This is a replacement for select() on the TPF platform. - * It is used whenever libcurl calls select(). - * The call below to tpf_process_signals() is required because - * TPF's select calls are not signal interruptible. - * - * Return values are the same as select's. - */ -int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, - fd_set* excepts, struct timeval* tv) -{ - int rc; - - rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv); - tpf_process_signals(); - return(rc); -} -#endif /* TPF */ diff --git a/third_party/curl/lib/select.h b/third_party/curl/lib/select.h deleted file mode 100644 index e431e5f07..000000000 --- a/third_party/curl/lib/select.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef __SELECT_H -#define __SELECT_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_SYS_POLL_H -#include -#elif defined(HAVE_POLL_H) -#include -#endif - -/* - * poll() function on Windows Vista and later is called WSAPoll() - */ - -#if defined(USE_WINSOCK) && (USE_WINSOCK > 1) && \ - defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) -# undef HAVE_POLL -# define HAVE_POLL 1 -# undef HAVE_POLL_FINE -# define HAVE_POLL_FINE 1 -# define poll(x,y,z) WSAPoll((x),(y),(z)) -# if defined(_MSC_VER) && defined(POLLRDNORM) -# undef POLLPRI -# define POLLPRI POLLRDBAND -# define HAVE_STRUCT_POLLFD 1 -# endif -#endif - -/* - * Definition of pollfd struct and constants for platforms lacking them. - */ - -#if !defined(HAVE_STRUCT_POLLFD) && \ - !defined(HAVE_SYS_POLL_H) && \ - !defined(HAVE_POLL_H) - -#define POLLIN 0x01 -#define POLLPRI 0x02 -#define POLLOUT 0x04 -#define POLLERR 0x08 -#define POLLHUP 0x10 -#define POLLNVAL 0x20 - -struct pollfd -{ - curl_socket_t fd; - short events; - short revents; -}; - -#endif - -#ifndef POLLRDNORM -#define POLLRDNORM POLLIN -#endif - -#ifndef POLLWRNORM -#define POLLWRNORM POLLOUT -#endif - -#ifndef POLLRDBAND -#define POLLRDBAND POLLPRI -#endif - -int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, - int timeout_ms); - -int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms); - -#ifdef TPF -int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, - fd_set* excepts, struct timeval* tv); -#endif - -#endif /* __SELECT_H */ diff --git a/third_party/curl/lib/sendf.c b/third_party/curl/lib/sendf.c deleted file mode 100644 index 3edac5a90..000000000 --- a/third_party/curl/lib/sendf.c +++ /dev/null @@ -1,699 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include -#include -#include - -#ifdef HAVE_SYS_SOCKET_H -#include /* required for send() & recv() prototypes */ -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include -#include "urldata.h" -#include "sendf.h" -#include "connect.h" -#include "sslgen.h" -#include "ssh.h" -#include "multiif.h" -#include "rtsp.h" -#include "non-ascii.h" - -#define _MPRINTF_REPLACE /* use the internal *printf() functions */ -#include - -/* the krb4 functions only exists for FTP and if krb4 or gssapi is defined */ -#if !defined(CURL_DISABLE_FTP) && (defined(HAVE_KRB4) || defined(HAVE_GSSAPI)) -#include "krb4.h" -#else -#define Curl_sec_send(a,b,c,d) -1 -#define Curl_sec_read(a,b,c,d) -1 -#endif - -#include -#include "curl_memory.h" -#include "strerror.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -#ifdef CURL_DO_LINEEND_CONV -/* - * convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF - * (\n), with special processing for CRLF sequences that are split between two - * blocks of data. Remaining, bare CRs are changed to LFs. The possibly new - * size of the data is returned. - */ -static size_t convert_lineends(struct SessionHandle *data, - char *startPtr, size_t size) -{ - char *inPtr, *outPtr; - - /* sanity check */ - if((startPtr == NULL) || (size < 1)) { - return(size); - } - - if(data->state.prev_block_had_trailing_cr == TRUE) { - /* The previous block of incoming data - had a trailing CR, which was turned into a LF. */ - if(*startPtr == '\n') { - /* This block of incoming data starts with the - previous block's LF so get rid of it */ - memmove(startPtr, startPtr+1, size-1); - size--; - /* and it wasn't a bare CR but a CRLF conversion instead */ - data->state.crlf_conversions++; - } - data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */ - } - - /* find 1st CR, if any */ - inPtr = outPtr = memchr(startPtr, '\r', size); - if(inPtr) { - /* at least one CR, now look for CRLF */ - while(inPtr < (startPtr+size-1)) { - /* note that it's size-1, so we'll never look past the last byte */ - if(memcmp(inPtr, "\r\n", 2) == 0) { - /* CRLF found, bump past the CR and copy the NL */ - inPtr++; - *outPtr = *inPtr; - /* keep track of how many CRLFs we converted */ - data->state.crlf_conversions++; - } - else { - if(*inPtr == '\r') { - /* lone CR, move LF instead */ - *outPtr = '\n'; - } - else { - /* not a CRLF nor a CR, just copy whatever it is */ - *outPtr = *inPtr; - } - } - outPtr++; - inPtr++; - } /* end of while loop */ - - if(inPtr < startPtr+size) { - /* handle last byte */ - if(*inPtr == '\r') { - /* deal with a CR at the end of the buffer */ - *outPtr = '\n'; /* copy a NL instead */ - /* note that a CRLF might be split across two blocks */ - data->state.prev_block_had_trailing_cr = TRUE; - } - else { - /* copy last byte */ - *outPtr = *inPtr; - } - outPtr++; - } - if(outPtr < startPtr+size) - /* tidy up by null terminating the now shorter data */ - *outPtr = '\0'; - - return(outPtr - startPtr); - } - return(size); -} -#endif /* CURL_DO_LINEEND_CONV */ - -/* Curl_infof() is for info message along the way */ - -void Curl_infof(struct SessionHandle *data, const char *fmt, ...) -{ - if(data && data->set.verbose) { - va_list ap; - size_t len; - char print_buffer[2048 + 1]; - va_start(ap, fmt); - vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap); - va_end(ap); - len = strlen(print_buffer); - Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL); - } -} - -/* Curl_failf() is for messages stating why we failed. - * The message SHALL NOT include any LF or CR. - */ - -void Curl_failf(struct SessionHandle *data, const char *fmt, ...) -{ - va_list ap; - size_t len; - va_start(ap, fmt); - - vsnprintf(data->state.buffer, BUFSIZE, fmt, ap); - - if(data->set.errorbuffer && !data->state.errorbuf) { - snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer); - data->state.errorbuf = TRUE; /* wrote error string */ - } - if(data->set.verbose) { - len = strlen(data->state.buffer); - if(len < BUFSIZE - 1) { - data->state.buffer[len] = '\n'; - data->state.buffer[++len] = '\0'; - } - Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL); - } - - va_end(ap); -} - -/* Curl_sendf() sends formated data to the server */ -CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn, - const char *fmt, ...) -{ - struct SessionHandle *data = conn->data; - ssize_t bytes_written; - size_t write_len; - CURLcode res = CURLE_OK; - char *s; - char *sptr; - va_list ap; - va_start(ap, fmt); - s = vaprintf(fmt, ap); /* returns an allocated string */ - va_end(ap); - if(!s) - return CURLE_OUT_OF_MEMORY; /* failure */ - - bytes_written=0; - write_len = strlen(s); - sptr = s; - - for(;;) { - /* Write the buffer to the socket */ - res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written); - - if(CURLE_OK != res) - break; - - if(data->set.verbose) - Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn); - - if((size_t)bytes_written != write_len) { - /* if not all was written at once, we must advance the pointer, decrease - the size left and try again! */ - write_len -= bytes_written; - sptr += bytes_written; - } - else - break; - } - - free(s); /* free the output string */ - - return res; -} - -/* - * Curl_write() is an internal write function that sends data to the - * server. Works with plain sockets, SCP, SSL or kerberos. - * - * If the write would block (CURLE_AGAIN), we return CURLE_OK and - * (*written == 0). Otherwise we return regular CURLcode value. - */ -CURLcode Curl_write(struct connectdata *conn, - curl_socket_t sockfd, - const void *mem, - size_t len, - ssize_t *written) -{ - ssize_t bytes_written; - CURLcode curlcode = CURLE_OK; - int num = (sockfd == conn->sock[SECONDARYSOCKET]); - - bytes_written = conn->send[num](conn, num, mem, len, &curlcode); - - *written = bytes_written; - if(bytes_written >= 0) - /* we completely ignore the curlcode value when subzero is not returned */ - return CURLE_OK; - - /* handle CURLE_AGAIN or a send failure */ - switch(curlcode) { - case CURLE_AGAIN: - *written = 0; - return CURLE_OK; - - case CURLE_OK: - /* general send failure */ - return CURLE_SEND_ERROR; - - default: - /* we got a specific curlcode, forward it */ - return (CURLcode)curlcode; - } -} - -ssize_t Curl_send_plain(struct connectdata *conn, int num, - const void *mem, size_t len, CURLcode *code) -{ - curl_socket_t sockfd = conn->sock[num]; - ssize_t bytes_written = swrite(sockfd, mem, len); - - *code = CURLE_OK; - if(-1 == bytes_written) { - int err = SOCKERRNO; - - if( -#ifdef WSAEWOULDBLOCK - /* This is how Windows does it */ - (WSAEWOULDBLOCK == err) -#else - /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned - due to its inability to send off data without blocking. We therefor - treat both error codes the same here */ - (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) -#endif - ) { - /* this is just a case of EWOULDBLOCK */ - bytes_written=0; - *code = CURLE_AGAIN; - } else { - failf(conn->data, "Send failure: %s", - Curl_strerror(conn, err)); - conn->data->state.os_errno = err; - *code = CURLE_SEND_ERROR; - } - } - return bytes_written; -} - -/* - * Curl_write_plain() is an internal write function that sends data to the - * server using plain sockets only. Otherwise meant to have the exact same - * proto as Curl_write() - */ -CURLcode Curl_write_plain(struct connectdata *conn, - curl_socket_t sockfd, - const void *mem, - size_t len, - ssize_t *written) -{ - ssize_t bytes_written; - CURLcode retcode; - int num = (sockfd == conn->sock[SECONDARYSOCKET]); - - bytes_written = Curl_send_plain(conn, num, mem, len, &retcode); - - *written = bytes_written; - - return retcode; -} - -ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, - size_t len, CURLcode *code) -{ - curl_socket_t sockfd = conn->sock[num]; - ssize_t nread = sread(sockfd, buf, len); - - *code = CURLE_OK; - if(-1 == nread) { - int err = SOCKERRNO; - - if( -#ifdef WSAEWOULDBLOCK - /* This is how Windows does it */ - (WSAEWOULDBLOCK == err) -#else - /* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned - due to its inability to send off data without blocking. We therefor - treat both error codes the same here */ - (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) -#endif - ) { - /* this is just a case of EWOULDBLOCK */ - *code = CURLE_AGAIN; - } else { - failf(conn->data, "Recv failure: %s", - Curl_strerror(conn, err)); - conn->data->state.os_errno = err; - *code = CURLE_RECV_ERROR; - } - } - return nread; -} - -static CURLcode pausewrite(struct SessionHandle *data, - int type, /* what type of data */ - const char *ptr, - size_t len) -{ - /* signalled to pause sending on this connection, but since we have data - we want to send we need to dup it to save a copy for when the sending - is again enabled */ - struct SingleRequest *k = &data->req; - char *dupl = malloc(len); - if(!dupl) - return CURLE_OUT_OF_MEMORY; - - memcpy(dupl, ptr, len); - - /* store this information in the state struct for later use */ - data->state.tempwrite = dupl; - data->state.tempwritesize = len; - data->state.tempwritetype = type; - - /* mark the connection as RECV paused */ - k->keepon |= KEEP_RECV_PAUSE; - - DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n", - len, type)); - - return CURLE_OK; -} - - -/* Curl_client_write() sends data to the write callback(s) - - The bit pattern defines to what "streams" to write to. Body and/or header. - The defines are in sendf.h of course. - - If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the - local character encoding. This is a problem and should be changed in - the future to leave the original data alone. - */ -CURLcode Curl_client_write(struct connectdata *conn, - int type, - char *ptr, - size_t len) -{ - struct SessionHandle *data = conn->data; - size_t wrote; - - if(0 == len) - len = strlen(ptr); - - /* If reading is actually paused, we're forced to append this chunk of data - to the already held data, but only if it is the same type as otherwise it - can't work and it'll return error instead. */ - if(data->req.keepon & KEEP_RECV_PAUSE) { - size_t newlen; - char *newptr; - if(type != data->state.tempwritetype) - /* major internal confusion */ - return CURLE_RECV_ERROR; - - DEBUGASSERT(data->state.tempwrite); - - /* figure out the new size of the data to save */ - newlen = len + data->state.tempwritesize; - /* allocate the new memory area */ - newptr = realloc(data->state.tempwrite, newlen); - if(!newptr) - return CURLE_OUT_OF_MEMORY; - /* copy the new data to the end of the new area */ - memcpy(newptr + data->state.tempwritesize, ptr, len); - /* update the pointer and the size */ - data->state.tempwrite = newptr; - data->state.tempwritesize = newlen; - - return CURLE_OK; - } - - if(type & CLIENTWRITE_BODY) { - if((conn->handler->protocol&CURLPROTO_FTP) && - conn->proto.ftpc.transfertype == 'A') { - /* convert from the network encoding */ - size_t rc = Curl_convert_from_network(data, ptr, len); - /* Curl_convert_from_network calls failf if unsuccessful */ - if(rc) - return rc; - -#ifdef CURL_DO_LINEEND_CONV - /* convert end-of-line markers */ - len = convert_lineends(data, ptr, len); -#endif /* CURL_DO_LINEEND_CONV */ - } - /* If the previous block of data ended with CR and this block of data is - just a NL, then the length might be zero */ - if(len) { - wrote = data->set.fwrite_func(ptr, 1, len, data->set.out); - } - else { - wrote = len; - } - - if(CURL_WRITEFUNC_PAUSE == wrote) - return pausewrite(data, type, ptr, len); - - if(wrote != len) { - failf(data, "Failed writing body (%zu != %zu)", wrote, len); - return CURLE_WRITE_ERROR; - } - } - - if((type & CLIENTWRITE_HEADER) && - (data->set.fwrite_header || data->set.writeheader) ) { - /* - * Write headers to the same callback or to the especially setup - * header callback function (added after version 7.7.1). - */ - curl_write_callback writeit= - data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite_func; - - /* Note: The header is in the host encoding - regardless of the ftp transfer mode (ASCII/Image) */ - - wrote = writeit(ptr, 1, len, data->set.writeheader); - if(CURL_WRITEFUNC_PAUSE == wrote) - /* here we pass in the HEADER bit only since if this was body as well - then it was passed already and clearly that didn't trigger the pause, - so this is saved for later with the HEADER bit only */ - return pausewrite(data, CLIENTWRITE_HEADER, ptr, len); - - if(wrote != len) { - failf (data, "Failed writing header"); - return CURLE_WRITE_ERROR; - } - } - - return CURLE_OK; -} - -CURLcode Curl_read_plain(curl_socket_t sockfd, - char *buf, - size_t bytesfromsocket, - ssize_t *n) -{ - ssize_t nread = sread(sockfd, buf, bytesfromsocket); - - if(-1 == nread) { - int err = SOCKERRNO; -#ifdef USE_WINSOCK - if(WSAEWOULDBLOCK == err) -#else - if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)) -#endif - return CURLE_AGAIN; - else - return CURLE_RECV_ERROR; - } - - /* we only return number of bytes read when we return OK */ - *n = nread; - return CURLE_OK; -} - -/* - * Internal read-from-socket function. This is meant to deal with plain - * sockets, SSL sockets and kerberos sockets. - * - * Returns a regular CURLcode value. - */ -CURLcode Curl_read(struct connectdata *conn, /* connection data */ - curl_socket_t sockfd, /* read from this socket */ - char *buf, /* store read data here */ - size_t sizerequested, /* max amount to read */ - ssize_t *n) /* amount bytes read */ -{ - CURLcode curlcode = CURLE_RECV_ERROR; - ssize_t nread = 0; - size_t bytesfromsocket = 0; - char *buffertofill = NULL; - bool pipelining = (bool)(conn->data->multi && - Curl_multi_canPipeline(conn->data->multi)); - - /* Set 'num' to 0 or 1, depending on which socket that has been sent here. - If it is the second socket, we set num to 1. Otherwise to 0. This lets - us use the correct ssl handle. */ - int num = (sockfd == conn->sock[SECONDARYSOCKET]); - - *n=0; /* reset amount to zero */ - - /* If session can pipeline, check connection buffer */ - if(pipelining) { - size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos, - sizerequested); - - /* Copy from our master buffer first if we have some unread data there*/ - if(bytestocopy > 0) { - memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy); - conn->read_pos += bytestocopy; - conn->bits.stream_was_rewound = FALSE; - - *n = (ssize_t)bytestocopy; - return CURLE_OK; - } - /* If we come here, it means that there is no data to read from the buffer, - * so we read from the socket */ - bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char)); - buffertofill = conn->master_buffer; - } - else { - bytesfromsocket = CURLMIN((long)sizerequested, - conn->data->set.buffer_size ? - conn->data->set.buffer_size : BUFSIZE); - buffertofill = buf; - } - - nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &curlcode); - if(nread < 0) - return curlcode; - - if(pipelining) { - memcpy(buf, conn->master_buffer, nread); - conn->buf_len = nread; - conn->read_pos = nread; - } - - *n += nread; - - return CURLE_OK; -} - -/* return 0 on success */ -static int showit(struct SessionHandle *data, curl_infotype type, - char *ptr, size_t size) -{ - static const char s_infotype[CURLINFO_END][3] = { - "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; - -#ifdef CURL_DOES_CONVERSIONS - char buf[BUFSIZE+1]; - size_t conv_size = 0; - - switch(type) { - case CURLINFO_HEADER_OUT: - /* assume output headers are ASCII */ - /* copy the data into my buffer so the original is unchanged */ - if(size > BUFSIZE) { - size = BUFSIZE; /* truncate if necessary */ - buf[BUFSIZE] = '\0'; - } - conv_size = size; - memcpy(buf, ptr, size); - /* Special processing is needed for this block if it - * contains both headers and data (separated by CRLFCRLF). - * We want to convert just the headers, leaving the data as-is. - */ - if(size > 4) { - size_t i; - for(i = 0; i < size-4; i++) { - if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) { - /* convert everything through this CRLFCRLF but no further */ - conv_size = i + 4; - break; - } - } - } - - Curl_convert_from_network(data, buf, conv_size); - /* Curl_convert_from_network calls failf if unsuccessful */ - /* we might as well continue even if it fails... */ - ptr = buf; /* switch pointer to use my buffer instead */ - break; - default: - /* leave everything else as-is */ - break; - } -#endif /* CURL_DOES_CONVERSIONS */ - - if(data->set.fdebug) - return (*data->set.fdebug)(data, type, ptr, size, - data->set.debugdata); - - switch(type) { - case CURLINFO_TEXT: - case CURLINFO_HEADER_OUT: - case CURLINFO_HEADER_IN: - fwrite(s_infotype[type], 2, 1, data->set.err); - fwrite(ptr, size, 1, data->set.err); -#ifdef CURL_DOES_CONVERSIONS - if(size != conv_size) { - /* we had untranslated data so we need an explicit newline */ - fwrite("\n", 1, 1, data->set.err); - } -#endif - break; - default: /* nada */ - break; - } - return 0; -} - -int Curl_debug(struct SessionHandle *data, curl_infotype type, - char *ptr, size_t size, - struct connectdata *conn) -{ - int rc; - if(data->set.printhost && conn && conn->host.dispname) { - char buffer[160]; - const char *t=NULL; - const char *w="Data"; - switch (type) { - case CURLINFO_HEADER_IN: - w = "Header"; - case CURLINFO_DATA_IN: - t = "from"; - break; - case CURLINFO_HEADER_OUT: - w = "Header"; - case CURLINFO_DATA_OUT: - t = "to"; - break; - default: - break; - } - - if(t) { - snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t, - conn->host.dispname); - rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer)); - if(rc) - return rc; - } - } - rc = showit(data, type, ptr, size); - return rc; -} diff --git a/third_party/curl/lib/sendf.h b/third_party/curl/lib/sendf.h deleted file mode 100644 index 8f0ea24d7..000000000 --- a/third_party/curl/lib/sendf.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef HEADER_CURL_SENDF_H -#define HEADER_CURL_SENDF_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *, - const char *fmt, ...); -void Curl_infof(struct SessionHandle *, const char *fmt, ...); -void Curl_failf(struct SessionHandle *, const char *fmt, ...); - -#if defined(CURL_DISABLE_VERBOSE_STRINGS) - -#if defined(HAVE_VARIADIC_MACROS_C99) -#define infof(...) do { } while (0) -#elif defined(HAVE_VARIADIC_MACROS_GCC) -#define infof(x...) do { } while (0) -#else -#define infof (void) -#endif - -#else /* CURL_DISABLE_VERBOSE_STRINGS */ - -#define infof Curl_infof - -#endif /* CURL_DISABLE_VERBOSE_STRINGS */ - -#define failf Curl_failf - -#define CLIENTWRITE_BODY (1<<0) -#define CLIENTWRITE_HEADER (1<<1) -#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER) - -CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, - size_t len); - -/* internal read-function, does plain socket only */ -CURLcode Curl_read_plain(curl_socket_t sockfd, - char *buf, - size_t bytesfromsocket, - ssize_t *n); - -ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, - size_t len, CURLcode *code); -ssize_t Curl_send_plain(struct connectdata *conn, int num, - const void *mem, size_t len, CURLcode *code); - -/* internal read-function, does plain socket, SSL and krb4 */ -CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd, - char *buf, size_t buffersize, - ssize_t *n); -/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */ -CURLcode Curl_write(struct connectdata *conn, - curl_socket_t sockfd, - const void *mem, size_t len, - ssize_t *written); - -/* internal write-function, does plain sockets ONLY */ -CURLcode Curl_write_plain(struct connectdata *conn, - curl_socket_t sockfd, - const void *mem, size_t len, - ssize_t *written); - -/* the function used to output verbose information */ -int Curl_debug(struct SessionHandle *handle, curl_infotype type, - char *data, size_t size, - struct connectdata *conn); - - -#endif /* HEADER_CURL_SENDF_H */ diff --git a/third_party/curl/lib/setup-os400.h b/third_party/curl/lib/setup-os400.h deleted file mode 100644 index cdeefe3dd..000000000 --- a/third_party/curl/lib/setup-os400.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef HEADER_CURL_SETUP_OS400_H -#define HEADER_CURL_SETUP_OS400_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - - -/* OS/400 netdb.h does not define NI_MAXHOST. */ -#define NI_MAXHOST 1025 - -/* OS/400 netdb.h does not define NI_MAXSERV. */ -#define NI_MAXSERV 32 - -/* No OS/400 header file defines u_int32_t. */ -typedef unsigned long u_int32_t; - - -/* System API wrapper prototypes and definitions to support ASCII parameters. */ - -#include -#include -#include -#include - -extern int Curl_getaddrinfo_a(const char * nodename, const char * servname, - const struct addrinfo * hints, - struct addrinfo * * res); -#define getaddrinfo Curl_getaddrinfo_a - - -extern int Curl_getnameinfo_a(const struct sockaddr * sa, - curl_socklen_t salen, - char * nodename, curl_socklen_t nodenamelen, - char * servname, curl_socklen_t servnamelen, - int flags); -#define getnameinfo Curl_getnameinfo_a - - -/* SSL wrappers. */ - -extern int Curl_SSL_Init_Application_a(SSLInitApp * init_app); -#define SSL_Init_Application Curl_SSL_Init_Application_a - - -extern int Curl_SSL_Init_a(SSLInit * init); -#define SSL_Init Curl_SSL_Init_a - - -extern char * Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp); -#define SSL_Strerror Curl_SSL_Strerror_a - - -/* GSSAPI wrappers. */ - -extern OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status, - gss_buffer_t in_name, - gss_OID in_name_type, - gss_name_t * out_name); -#define gss_import_name Curl_gss_import_name_a - - -extern OM_uint32 Curl_gss_display_status_a(OM_uint32 * minor_status, - OM_uint32 status_value, - int status_type, gss_OID mech_type, - gss_msg_ctx_t * message_context, - gss_buffer_t status_string); -#define gss_display_status Curl_gss_display_status_a - - -extern OM_uint32 Curl_gss_init_sec_context_a(OM_uint32 * minor_status, - gss_cred_id_t cred_handle, - gss_ctx_id_t * context_handle, - gss_name_t target_name, - gss_OID mech_type, - gss_flags_t req_flags, - OM_uint32 time_req, - gss_channel_bindings_t - input_chan_bindings, - gss_buffer_t input_token, - gss_OID * actual_mech_type, - gss_buffer_t output_token, - gss_flags_t * ret_flags, - OM_uint32 * time_rec); -#define gss_init_sec_context Curl_gss_init_sec_context_a - - -extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - gss_buffer_t output_token); -#define gss_delete_sec_context Curl_gss_delete_sec_context_a - -/* LDAP wrappers. */ - -#define BerValue struct berval - -#define ldap_url_parse ldap_url_parse_utf8 -#define ldap_init Curl_ldap_init_a -#define ldap_simple_bind_s Curl_ldap_simple_bind_s_a -#define ldap_search_s Curl_ldap_search_s_a -#define ldap_get_values_len Curl_ldap_get_values_len_a -#define ldap_err2string Curl_ldap_err2string_a -#define ldap_get_dn Curl_ldap_get_dn_a -#define ldap_first_attribute Curl_ldap_first_attribute_a -#define ldap_next_attribute Curl_ldap_next_attribute_a - -/* Some socket functions must be wrapped to process textual addresses - like AF_UNIX. */ - -extern int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen); -extern int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen); -extern int Curl_os400_sendto(int sd, char * buffer, int buflen, int flags, - struct sockaddr * dstaddr, int addrlen); -extern int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags, - struct sockaddr * fromaddr, int * addrlen); - -#define connect Curl_os400_connect -#define bind Curl_os400_bind -#define sendto Curl_os400_sendto -#define recvfrom Curl_os400_recvfrom - - -#endif /* HEADER_CURL_SETUP_OS400_H */ diff --git a/third_party/curl/lib/setup.h b/third_party/curl/lib/setup.h deleted file mode 100644 index 477d4690b..000000000 --- a/third_party/curl/lib/setup.h +++ /dev/null @@ -1,586 +0,0 @@ -#ifndef HEADER_CURL_LIB_SETUP_H -#define HEADER_CURL_LIB_SETUP_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Define WIN32 when build target is Win32 API - */ - -#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && !defined(__SYMBIAN32__) -#define WIN32 -#endif - -/* - * Include configuration script results or hand-crafted - * configuration file for platforms which lack config tool. - */ - -#ifdef HAVE_CONFIG_H - -#include "curl_config.h" - -#else /* HAVE_CONFIG_H */ - -#ifdef _WIN32_WCE -# include "config-win32ce.h" -#else -# ifdef WIN32 -# include "config-win32.h" -# endif -#endif - -#if defined(macintosh) && defined(__MRC__) -# include "config-mac.h" -#endif - -#ifdef __AMIGA__ -# include "amigaos.h" -#endif - -#ifdef __SYMBIAN32__ -# include "config-symbian.h" -#endif - -#ifdef __OS400__ -# include "config-os400.h" -#endif - -#ifdef TPF -# include "config-tpf.h" -#endif - -#ifdef __VXWORKS__ -# include "config-vxworks.h" -#endif - -#endif /* HAVE_CONFIG_H */ - -/* ================================================================ */ -/* Definition of preprocessor macros/symbols which modify compiler */ -/* behavior or generated code characteristics must be done here, */ -/* as appropriate, before any system header file is included. It is */ -/* also possible to have them defined in the config file included */ -/* before this point. As a result of all this we frown inclusion of */ -/* system header files in our config files, avoid this at any cost. */ -/* ================================================================ */ - -/* - * AIX 4.3 and newer needs _THREAD_SAFE defined to build - * proper reentrant code. Others may also need it. - */ - -#ifdef NEED_THREAD_SAFE -# ifndef _THREAD_SAFE -# define _THREAD_SAFE -# endif -#endif - -/* - * Tru64 needs _REENTRANT set for a few function prototypes and - * things to appear in the system header files. Unixware needs it - * to build proper reentrant code. Others may also need it. - */ - -#ifdef NEED_REENTRANT -# ifndef _REENTRANT -# define _REENTRANT -# endif -#endif - -/* ================================================================ */ -/* If you need to include a system header file for your platform, */ -/* please, do it beyond the point further indicated in this file. */ -/* ================================================================ */ - -/* - * libcurl's external interface definitions are also used internally, - * and might also include required system header files to define them. - */ - -#include - -/* - * Compile time sanity checks must also be done when building the library. - */ - -#include - -/* - * Ensure that no one is using the old SIZEOF_CURL_OFF_T macro - */ - -#ifdef SIZEOF_CURL_OFF_T -# error "SIZEOF_CURL_OFF_T shall not be defined!" - Error Compilation_aborted_SIZEOF_CURL_OFF_T_shall_not_be_defined -#endif - -/* - * Set up internal curl_off_t formatting string directives for - * exclusive use with libcurl's internal *printf functions. - */ - -#ifdef FORMAT_OFF_T -# error "FORMAT_OFF_T shall not be defined before this point!" - Error Compilation_aborted_FORMAT_OFF_T_already_defined -#endif - -#ifdef FORMAT_OFF_TU -# error "FORMAT_OFF_TU shall not be defined before this point!" - Error Compilation_aborted_FORMAT_OFF_TU_already_defined -#endif - -#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) -# define FORMAT_OFF_T "lld" -# define FORMAT_OFF_TU "llu" -#else -# define FORMAT_OFF_T "ld" -# define FORMAT_OFF_TU "lu" -#endif - -/* - * Disable other protocols when http is the only one desired. - */ - -#ifdef HTTP_ONLY -# ifndef CURL_DISABLE_TFTP -# define CURL_DISABLE_TFTP -# endif -# ifndef CURL_DISABLE_FTP -# define CURL_DISABLE_FTP -# endif -# ifndef CURL_DISABLE_LDAP -# define CURL_DISABLE_LDAP -# endif -# ifndef CURL_DISABLE_TELNET -# define CURL_DISABLE_TELNET -# endif -# ifndef CURL_DISABLE_DICT -# define CURL_DISABLE_DICT -# endif -# ifndef CURL_DISABLE_FILE -# define CURL_DISABLE_FILE -# endif -# ifndef CURL_DISABLE_RTSP -# define CURL_DISABLE_RTSP -# endif -#endif - -/* - * When http is disabled rtsp is not supported. - */ - -#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP) -# define CURL_DISABLE_RTSP -#endif - -/* ================================================================ */ -/* No system header file shall be included in this file before this */ -/* point. The only allowed ones are those included from curlbuild.h */ -/* ================================================================ */ - -/* - * OS/400 setup file includes some system headers. - */ - -#ifdef __OS400__ -# include "setup-os400.h" -#endif - -/* - * 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. ) 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 -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -# include -# ifdef HAVE_WINSOCK2_H -# include -# ifdef HAVE_WS2TCPIP_H -# include -# endif -# else -# ifdef HAVE_WINSOCK_H -# include -# endif -# 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 HAVE_EXTRA_STRICMP_H -# include -#endif - -#ifdef HAVE_EXTRA_STRDUP_H -# include -#endif - -#ifdef TPF -# include /* for bzero, strcasecmp, and strncasecmp */ -# include /* for strcpy and strlen */ -# include /* for rand and srand */ -# include /* for select and ioctl*/ -# include /* for in_addr_t definition */ -# include /* 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 /* for generic BSD socket functions */ -# include /* for basic I/O interface functions */ -#endif - -#include -#ifdef HAVE_ASSERT_H -#include -#endif -#include - -#ifdef __TANDEM /* for nsr-tandem-nsk systems */ -#include -#endif - -#ifndef STDC_HEADERS /* no standard C headers! */ -#include -#endif - -#ifdef __POCC__ -# include -# include -# 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 -#endif - -/* - * Large file (>2Gb) support using WIN32 functions. - */ - -#ifdef USE_WIN32_LARGE_FILES -# include -# include -# include -# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence) -# define fstat(fdes,stp) _fstati64(fdes, stp) -# 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 -# include -# include -# 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 -# define LSEEK_ERROR (long)-1 -#endif - -#ifndef struct_stat -# define struct_stat struct stat -#endif - -#ifndef LSEEK_ERROR -# define LSEEK_ERROR (off_t)-1 -#endif - -/* - * Default sizeof(off_t) in case it hasn't been defined in config file. - */ - -#ifndef SIZEOF_OFF_T -# if defined(__VMS) && !defined(__VAX) -# if defined(_LARGEFILE) -# define SIZEOF_OFF_T 8 -# endif -# elif defined(__OS400__) && defined(__ILEC400__) -# if defined(_LARGE_FILES) -# define SIZEOF_OFF_T 8 -# endif -# elif defined(__MVS__) && defined(__IBMC__) -# if defined(_LP64) || defined(_LARGE_FILES) -# define SIZEOF_OFF_T 8 -# endif -# elif defined(__370__) && defined(__IBMC__) -# if defined(_LP64) || defined(_LARGE_FILES) -# define SIZEOF_OFF_T 8 -# endif -# endif -# ifndef SIZEOF_OFF_T -# define SIZEOF_OFF_T 4 -# endif -#endif - -/* - * Arg 2 type for gethostname in case it hasn't been defined in config file. - */ - -#ifndef GETHOSTNAME_TYPE_ARG2 -# ifdef USE_WINSOCK -# define GETHOSTNAME_TYPE_ARG2 int -# else -# define GETHOSTNAME_TYPE_ARG2 size_t -# endif -#endif - -/* Below we define some functions. They should - - 4. set the SIGALRM signal timeout - 5. set dir/file naming defines - */ - -#ifdef WIN32 - -# define DIR_CHAR "\\" -# define DOT_CHAR "_" - -#else /* WIN32 */ - -# ifdef MSDOS /* Watt-32 */ - -# include -# 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 -# ifdef word -# undef word -# endif -# ifdef byte -# undef byte -# endif - -# endif /* MSDOS */ - -# ifdef __minix - /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */ - extern char * strtok_r(char *s, const char *delim, char **last); - extern struct tm * gmtime_r(const time_t * const timep, struct tm *tmp); -# endif - -# define DIR_CHAR "/" -# ifndef DOT_CHAR -# define DOT_CHAR "." -# endif - -# ifdef MSDOS -# undef DOT_CHAR -# define DOT_CHAR "_" -# endif - -# ifndef fileno /* sunos 4 have this as a macro! */ - int fileno( FILE *stream); -# endif - -#endif /* WIN32 */ - -/* - * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN - * defined in ws2tcpip.h as well as to provide IPv6 support. - */ - -#if defined(_MSC_VER) && !defined(__POCC__) -# if !defined(HAVE_WS2TCPIP_H) || \ - ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN)) -# undef HAVE_GETADDRINFO_THREADSAFE -# undef HAVE_FREEADDRINFO -# undef HAVE_GETADDRINFO -# undef HAVE_GETNAMEINFO -# undef ENABLE_IPV6 -# endif -#endif - -/* ---------------------------------------------------------------- */ -/* resolver specialty compile-time defines */ -/* CURLRES_* defines to use in the host*.c sources */ -/* ---------------------------------------------------------------- */ - -/* - * lcc-win32 doesn't have _beginthreadex(), lacks threads support. - */ - -#if defined(__LCC__) && defined(WIN32) -# undef USE_THREADS_POSIX -# undef USE_THREADS_WIN32 -#endif - -/* - * MSVC threads support requires a multi-threaded runtime library. - * _beginthreadex() is not available in single-threaded ones. - */ - -#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT) -# undef USE_THREADS_POSIX -# undef USE_THREADS_WIN32 -#endif - -/* - * Mutually exclusive CURLRES_* definitions. - */ - -#ifdef USE_ARES -# define CURLRES_ASYNCH -# define CURLRES_ARES -#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 -#include -#endif -#endif - -#if defined(HAVE_LIBIDN) && defined(HAVE_TLD_H) -/* The lib was present and the tld.h header (which is missing in libidn 0.3.X - but we only work with libidn 0.4.1 or later) */ -#define USE_LIBIDN -#endif - -#ifndef SIZEOF_TIME_T -/* assume default size of time_t to be 32 bit */ -#define SIZEOF_TIME_T 4 -#endif - -#define LIBIDN_REQUIRED_VERSION "0.4.1" - -#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || defined(USE_QSOSSL) || defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_CYASSL) -#define USE_SSL /* SSL support has been enabled */ -#endif - -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) -#define USE_HTTP_NEGOTIATE -#endif - -#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM) -#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) || defined(USE_GNUTLS) || defined(USE_NSS) -#define USE_NTLM -#endif -#endif - -/* non-configure builds may define CURL_WANTS_CA_BUNDLE_ENV */ -#if defined(CURL_WANTS_CA_BUNDLE_ENV) && !defined(CURL_CA_BUNDLE) -#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE") -#endif - -/* 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 - -/* - * Include macros and defines that should only be processed once. - */ - -#ifndef __SETUP_ONCE_H -#include "setup_once.h" -#endif - -#endif /* HEADER_CURL_LIB_SETUP_H */ diff --git a/third_party/curl/lib/setup_once.h b/third_party/curl/lib/setup_once.h deleted file mode 100644 index e90fbd839..000000000 --- a/third_party/curl/lib/setup_once.h +++ /dev/null @@ -1,491 +0,0 @@ -#ifndef __SETUP_ONCE_H -#define __SETUP_ONCE_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - - -/******************************************************************** - * NOTICE * - * ======== * - * * - * Content of header files lib/setup_once.h and ares/setup_once.h * - * must be kept in sync. Modify the other one if you change this. * - * * - ********************************************************************/ - - -/* - * Inclusion of common header files. - */ - -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_SYS_TYPES_H -#include -#endif - -#ifdef NEED_MALLOC_H -#include -#endif - -#ifdef NEED_MEMORY_H -#include -#endif - -#ifdef HAVE_SYS_STAT_H -#include -#endif - -#ifdef HAVE_SYS_TIME_H -#include -#ifdef TIME_WITH_SYS_TIME -#include -#endif -#else -#ifdef HAVE_TIME_H -#include -#endif -#endif - -#ifdef WIN32 -#include -#include -#endif - -#ifdef HAVE_STDBOOL_H -#include -#endif - - -/* - * Definition of timeval struct for platforms that don't have it. - */ - -#ifndef HAVE_STRUCT_TIMEVAL -struct timeval { - long tv_sec; - long tv_usec; -}; -#endif - - -/* - * If we have the MSG_NOSIGNAL define, make sure we use - * it as the fourth argument of function send() - */ - -#ifdef HAVE_MSG_NOSIGNAL -#define SEND_4TH_ARG MSG_NOSIGNAL -#else -#define SEND_4TH_ARG 0 -#endif - - -#if defined(__minix) -/* Minix doesn't support recv on TCP sockets */ -#define sread(x,y,z) (ssize_t)read((RECV_TYPE_ARG1)(x), \ - (RECV_TYPE_ARG2)(y), \ - (RECV_TYPE_ARG3)(z)) - -#elif defined(HAVE_RECV) -/* - * The definitions for the return type and arguments types - * of functions recv() and send() belong and come from the - * configuration file. Do not define them in any other place. - * - * HAVE_RECV is defined if you have a function named recv() - * which is used to read incoming data from sockets. If your - * function has another name then don't define HAVE_RECV. - * - * If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2, - * RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also - * be defined. - * - * HAVE_SEND is defined if you have a function named send() - * which is used to write outgoing data on a connected socket. - * If yours has another name then don't define HAVE_SEND. - * - * If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2, - * SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and - * SEND_TYPE_RETV must also be defined. - */ - -#if !defined(RECV_TYPE_ARG1) || \ - !defined(RECV_TYPE_ARG2) || \ - !defined(RECV_TYPE_ARG3) || \ - !defined(RECV_TYPE_ARG4) || \ - !defined(RECV_TYPE_RETV) - /* */ - Error Missing_definition_of_return_and_arguments_types_of_recv - /* */ -#else -#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \ - (RECV_TYPE_ARG2)(y), \ - (RECV_TYPE_ARG3)(z), \ - (RECV_TYPE_ARG4)(0)) -#endif -#else /* HAVE_RECV */ -#ifndef sread - /* */ - Error Missing_definition_of_macro_sread - /* */ -#endif -#endif /* HAVE_RECV */ - - -#if defined(__minix) -/* Minix doesn't support send on TCP sockets */ -#define swrite(x,y,z) (ssize_t)write((SEND_TYPE_ARG1)(x), \ - (SEND_TYPE_ARG2)(y), \ - (SEND_TYPE_ARG3)(z)) - -#elif defined(HAVE_SEND) -#if !defined(SEND_TYPE_ARG1) || \ - !defined(SEND_QUAL_ARG2) || \ - !defined(SEND_TYPE_ARG2) || \ - !defined(SEND_TYPE_ARG3) || \ - !defined(SEND_TYPE_ARG4) || \ - !defined(SEND_TYPE_RETV) - /* */ - Error Missing_definition_of_return_and_arguments_types_of_send - /* */ -#else -#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \ - (SEND_TYPE_ARG2)(y), \ - (SEND_TYPE_ARG3)(z), \ - (SEND_TYPE_ARG4)(SEND_4TH_ARG)) -#endif -#else /* HAVE_SEND */ -#ifndef swrite - /* */ - Error Missing_definition_of_macro_swrite - /* */ -#endif -#endif /* HAVE_SEND */ - - -#if 0 -#if defined(HAVE_RECVFROM) -/* - * Currently recvfrom is only used on udp sockets. - */ -#if !defined(RECVFROM_TYPE_ARG1) || \ - !defined(RECVFROM_TYPE_ARG2) || \ - !defined(RECVFROM_TYPE_ARG3) || \ - !defined(RECVFROM_TYPE_ARG4) || \ - !defined(RECVFROM_TYPE_ARG5) || \ - !defined(RECVFROM_TYPE_ARG6) || \ - !defined(RECVFROM_TYPE_RETV) - /* */ - Error Missing_definition_of_return_and_arguments_types_of_recvfrom - /* */ -#else -#define sreadfrom(s,b,bl,f,fl) (ssize_t)recvfrom((RECVFROM_TYPE_ARG1) (s), \ - (RECVFROM_TYPE_ARG2 *)(b), \ - (RECVFROM_TYPE_ARG3) (bl), \ - (RECVFROM_TYPE_ARG4) (0), \ - (RECVFROM_TYPE_ARG5 *)(f), \ - (RECVFROM_TYPE_ARG6 *)(fl)) -#endif -#else /* HAVE_RECVFROM */ -#ifndef sreadfrom - /* */ - Error Missing_definition_of_macro_sreadfrom - /* */ -#endif -#endif /* HAVE_RECVFROM */ - - -#ifdef RECVFROM_TYPE_ARG6_IS_VOID -# define RECVFROM_ARG6_T int -#else -# define RECVFROM_ARG6_T RECVFROM_TYPE_ARG6 -#endif -#endif /* if 0 */ - - -/* - * Function-like macro definition used to close a socket. - */ - -#if defined(HAVE_CLOSESOCKET) -# define sclose(x) closesocket((x)) -#elif defined(HAVE_CLOSESOCKET_CAMEL) -# define sclose(x) CloseSocket((x)) -#else -# define sclose(x) close((x)) -#endif - - -/* - * Uppercase macro versions of ANSI/ISO is*() functions/macros which - * avoid negative number inputs with argument byte codes > 127. - */ - -#define ISSPACE(x) (isspace((int) ((unsigned char)x))) -#define ISDIGIT(x) (isdigit((int) ((unsigned char)x))) -#define ISALNUM(x) (isalnum((int) ((unsigned char)x))) -#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x))) -#define ISGRAPH(x) (isgraph((int) ((unsigned char)x))) -#define ISALPHA(x) (isalpha((int) ((unsigned char)x))) -#define ISPRINT(x) (isprint((int) ((unsigned char)x))) -#define ISUPPER(x) (isupper((int) ((unsigned char)x))) -#define ISLOWER(x) (islower((int) ((unsigned char)x))) - -#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \ - (((unsigned char)x) == '\t')) - - -/* - * 'bool' exists on platforms with , i.e. C99 platforms. - * On non-C99 platforms there's no bool, so define an enum for that. - * On C99 platforms 'false' and 'true' also exist. Enum uses a - * global namespace though, so use bool_false and bool_true. - */ - -#ifndef HAVE_BOOL_T - typedef enum { - bool_false = 0, - bool_true = 1 - } bool; - -/* - * Use a define to let 'true' and 'false' use those enums. There - * are currently no use of true and false in libcurl proper, but - * there are some in the examples. This will cater for any later - * code happening to use true and false. - */ -# define false bool_false -# define true bool_true -# define HAVE_BOOL_T -#endif - - -/* - * Redefine TRUE and FALSE too, to catch current use. With this - * change, 'bool found = 1' will give a warning on MIPSPro, but - * 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro, - * AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too. - */ - -#ifndef TRUE -#define TRUE true -#endif -#ifndef FALSE -#define FALSE false -#endif - - -/* - * Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type. - */ - -#ifndef HAVE_SIG_ATOMIC_T -typedef int sig_atomic_t; -#define HAVE_SIG_ATOMIC_T -#endif - - -/* - * Convenience SIG_ATOMIC_T definition - */ - -#ifdef HAVE_SIG_ATOMIC_T_VOLATILE -#define SIG_ATOMIC_T static sig_atomic_t -#else -#define SIG_ATOMIC_T static volatile sig_atomic_t -#endif - - -/* - * Default return type for signal handlers. - */ - -#ifndef RETSIGTYPE -#define RETSIGTYPE void -#endif - - -/* - * Macro used to include code only in debug builds. - */ - -#ifdef DEBUGBUILD -#define DEBUGF(x) x -#else -#define DEBUGF(x) do { } while (0) -#endif - - -/* - * Macro used to include assertion code only in debug builds. - */ - -#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H) -#define DEBUGASSERT(x) assert(x) -#else -#define DEBUGASSERT(x) do { } while (0) -#endif - - -/* - * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno - * (or equivalent) on this platform to hide platform details to code using it. - */ - -#ifdef USE_WINSOCK -#define SOCKERRNO ((int)WSAGetLastError()) -#define SET_SOCKERRNO(x) (WSASetLastError((int)(x))) -#else -#define SOCKERRNO (errno) -#define SET_SOCKERRNO(x) (errno = (x)) -#endif - - -/* - * Macro ERRNO / SET_ERRNO() returns / sets the NOT *socket-related* errno - * (or equivalent) on this platform to hide platform details to code using it. - */ - -#ifdef WIN32 -#define ERRNO ((int)GetLastError()) -#define SET_ERRNO(x) (SetLastError((DWORD)(x))) -#else -#define ERRNO (errno) -#define SET_ERRNO(x) (errno = (x)) -#endif - - -/* - * Portable error number symbolic names defined to Winsock error codes. - */ - -#ifdef USE_WINSOCK -#undef EBADF /* override definition in errno.h */ -#define EBADF WSAEBADF -#undef EINTR /* override definition in errno.h */ -#define EINTR WSAEINTR -#undef EINVAL /* override definition in errno.h */ -#define EINVAL WSAEINVAL -#undef EWOULDBLOCK /* override definition in errno.h */ -#define EWOULDBLOCK WSAEWOULDBLOCK -#undef EINPROGRESS /* override definition in errno.h */ -#define EINPROGRESS WSAEINPROGRESS -#undef EALREADY /* override definition in errno.h */ -#define EALREADY WSAEALREADY -#undef ENOTSOCK /* override definition in errno.h */ -#define ENOTSOCK WSAENOTSOCK -#undef EDESTADDRREQ /* override definition in errno.h */ -#define EDESTADDRREQ WSAEDESTADDRREQ -#undef EMSGSIZE /* override definition in errno.h */ -#define EMSGSIZE WSAEMSGSIZE -#undef EPROTOTYPE /* override definition in errno.h */ -#define EPROTOTYPE WSAEPROTOTYPE -#undef ENOPROTOOPT /* override definition in errno.h */ -#define ENOPROTOOPT WSAENOPROTOOPT -#undef EPROTONOSUPPORT /* override definition in errno.h */ -#define EPROTONOSUPPORT WSAEPROTONOSUPPORT -#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT -#undef EOPNOTSUPP /* override definition in errno.h */ -#define EOPNOTSUPP WSAEOPNOTSUPP -#define EPFNOSUPPORT WSAEPFNOSUPPORT -#undef EAFNOSUPPORT /* override definition in errno.h */ -#define EAFNOSUPPORT WSAEAFNOSUPPORT -#undef EADDRINUSE /* override definition in errno.h */ -#define EADDRINUSE WSAEADDRINUSE -#undef EADDRNOTAVAIL /* override definition in errno.h */ -#define EADDRNOTAVAIL WSAEADDRNOTAVAIL -#undef ENETDOWN /* override definition in errno.h */ -#define ENETDOWN WSAENETDOWN -#undef ENETUNREACH /* override definition in errno.h */ -#define ENETUNREACH WSAENETUNREACH -#undef ENETRESET /* override definition in errno.h */ -#define ENETRESET WSAENETRESET -#undef ECONNABORTED /* override definition in errno.h */ -#define ECONNABORTED WSAECONNABORTED -#undef ECONNRESET /* override definition in errno.h */ -#define ECONNRESET WSAECONNRESET -#undef ENOBUFS /* override definition in errno.h */ -#define ENOBUFS WSAENOBUFS -#undef EISCONN /* override definition in errno.h */ -#define EISCONN WSAEISCONN -#undef ENOTCONN /* override definition in errno.h */ -#define ENOTCONN WSAENOTCONN -#define ESHUTDOWN WSAESHUTDOWN -#define ETOOMANYREFS WSAETOOMANYREFS -#undef ETIMEDOUT /* override definition in errno.h */ -#define ETIMEDOUT WSAETIMEDOUT -#undef ECONNREFUSED /* override definition in errno.h */ -#define ECONNREFUSED WSAECONNREFUSED -#undef ELOOP /* override definition in errno.h */ -#define ELOOP WSAELOOP -#ifndef ENAMETOOLONG /* possible previous definition in errno.h */ -#define ENAMETOOLONG WSAENAMETOOLONG -#endif -#define EHOSTDOWN WSAEHOSTDOWN -#undef EHOSTUNREACH /* override definition in errno.h */ -#define EHOSTUNREACH WSAEHOSTUNREACH -#ifndef ENOTEMPTY /* possible previous definition in errno.h */ -#define ENOTEMPTY WSAENOTEMPTY -#endif -#define EPROCLIM WSAEPROCLIM -#define EUSERS WSAEUSERS -#define EDQUOT WSAEDQUOT -#define ESTALE WSAESTALE -#define EREMOTE WSAEREMOTE -#endif - - -/* - * Actually use __32_getpwuid() on 64-bit VMS builds for getpwuid() - */ - -#if defined(__VMS) && \ - defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64) -#define getpwuid __32_getpwuid -#endif - - -/* - * Macro argv_item_t hides platform details to code using it. - */ - -#ifdef __VMS -#define argv_item_t __char_ptr32 -#else -#define argv_item_t char * -#endif - - -/* - * We use this ZERO_NULL to avoid picky compiler warnings, - * when assigning a NULL pointer to a function pointer var. - */ - -#define ZERO_NULL 0 - -#endif /* __SETUP_ONCE_H */ diff --git a/third_party/curl/lib/share.c b/third_party/curl/lib/share.c deleted file mode 100644 index 146228551..000000000 --- a/third_party/curl/lib/share.c +++ /dev/null @@ -1,216 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" -#include -#include -#include -#include -#include "urldata.h" -#include "share.h" -#include "curl_memory.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -CURLSH * -curl_share_init(void) -{ - struct Curl_share *share = calloc(1, sizeof(struct Curl_share)); - if(share) - share->specifier |= (1<dirty) - /* don't allow setting options while one or more handles are already - using this share */ - return CURLSHE_IN_USE; - - va_start(param, option); - - switch(option) { - case CURLSHOPT_SHARE: - /* this is a type this share will share */ - type = va_arg(param, int); - share->specifier |= (1<hostcache) { - share->hostcache = Curl_mk_dnscache(); - if(!share->hostcache) - return CURLSHE_NOMEM; - } - break; - -#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) - case CURL_LOCK_DATA_COOKIE: - if(!share->cookies) { - share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE ); - if(!share->cookies) - return CURLSHE_NOMEM; - } - break; -#endif /* CURL_DISABLE_HTTP */ - - case CURL_LOCK_DATA_SSL_SESSION: /* not supported (yet) */ - case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */ - - default: - return CURLSHE_BAD_OPTION; - } - break; - - case CURLSHOPT_UNSHARE: - /* this is a type this share will no longer share */ - type = va_arg(param, int); - share->specifier &= ~(1<hostcache) { - Curl_hash_destroy(share->hostcache); - share->hostcache = NULL; - } - break; - -#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) - case CURL_LOCK_DATA_COOKIE: - if(share->cookies) { - Curl_cookie_cleanup(share->cookies); - share->cookies = NULL; - } - break; -#endif /* CURL_DISABLE_HTTP */ - - case CURL_LOCK_DATA_SSL_SESSION: - break; - - case CURL_LOCK_DATA_CONNECT: - break; - - default: - return CURLSHE_BAD_OPTION; - } - break; - - case CURLSHOPT_LOCKFUNC: - lockfunc = va_arg(param, curl_lock_function); - share->lockfunc = lockfunc; - break; - - case CURLSHOPT_UNLOCKFUNC: - unlockfunc = va_arg(param, curl_unlock_function); - share->unlockfunc = unlockfunc; - break; - - case CURLSHOPT_USERDATA: - ptr = va_arg(param, void *); - share->clientdata = ptr; - break; - - default: - return CURLSHE_BAD_OPTION; - } - - return CURLSHE_OK; -} - -CURLSHcode -curl_share_cleanup(CURLSH *sh) -{ - struct Curl_share *share = (struct Curl_share *)sh; - - if(share == NULL) - return CURLSHE_INVALID; - - if(share->lockfunc) - share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE, - share->clientdata); - - if(share->dirty) { - if(share->unlockfunc) - share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); - return CURLSHE_IN_USE; - } - - if(share->hostcache) { - Curl_hash_destroy(share->hostcache); - share->hostcache = NULL; - } - - if(share->cookies) - Curl_cookie_cleanup(share->cookies); - - if(share->unlockfunc) - share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); - free(share); - - return CURLSHE_OK; -} - - -CURLSHcode -Curl_share_lock(struct SessionHandle *data, curl_lock_data type, - curl_lock_access accesstype) -{ - struct Curl_share *share = data->share; - - if(share == NULL) - return CURLSHE_INVALID; - - if(share->specifier & (1<lockfunc) /* only call this if set! */ - share->lockfunc(data, type, accesstype, share->clientdata); - } - /* else if we don't share this, pretend successful lock */ - - return CURLSHE_OK; -} - -CURLSHcode -Curl_share_unlock(struct SessionHandle *data, curl_lock_data type) -{ - struct Curl_share *share = data->share; - - if(share == NULL) - return CURLSHE_INVALID; - - if(share->specifier & (1<unlockfunc) /* only call this if set! */ - share->unlockfunc (data, type, share->clientdata); - } - - return CURLSHE_OK; -} diff --git a/third_party/curl/lib/share.h b/third_party/curl/lib/share.h deleted file mode 100644 index ea8e233d2..000000000 --- a/third_party/curl/lib/share.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __CURL_SHARE_H -#define __CURL_SHARE_H - -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2005, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" -#include -#include "cookie.h" - -/* SalfordC says "A structure member may not be volatile". Hence: - */ -#ifdef __SALFORDC__ -#define CURL_VOLATILE -#else -#define CURL_VOLATILE volatile -#endif - -/* this struct is libcurl-private, don't export details */ -struct Curl_share { - unsigned int specifier; - CURL_VOLATILE unsigned int dirty; - - curl_lock_function lockfunc; - curl_unlock_function unlockfunc; - void *clientdata; - - struct curl_hash *hostcache; - struct CookieInfo *cookies; -}; - -CURLSHcode Curl_share_lock (struct SessionHandle *, curl_lock_data, - curl_lock_access); -CURLSHcode Curl_share_unlock (struct SessionHandle *, curl_lock_data); - -#endif /* __CURL_SHARE_H */ diff --git a/third_party/curl/lib/slist.c b/third_party/curl/lib/slist.c deleted file mode 100644 index 1850d12c0..000000000 --- a/third_party/curl/lib/slist.c +++ /dev/null @@ -1,134 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include -#include - -#include -#include "curl_memory.h" -#include "slist.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -/* returns last node in linked list */ -static struct curl_slist *slist_get_last(struct curl_slist *list) -{ - struct curl_slist *item; - - /* if caller passed us a NULL, return now */ - if(!list) - return NULL; - - /* loop through to find the last item */ - item = list; - while(item->next) { - item = item->next; - } - return item; -} - -/* - * curl_slist_append() appends a string to the linked list. It always returns - * the address of the first record, so that you can use this function as an - * initialization function as well as an append function. If you find this - * bothersome, then simply create a separate _init function and call it - * appropriately from within the program. - */ -struct curl_slist *curl_slist_append(struct curl_slist *list, - const char *data) -{ - struct curl_slist *last; - struct curl_slist *new_item; - - new_item = malloc(sizeof(struct curl_slist)); - if(new_item) { - char *dupdata = strdup(data); - if(dupdata) { - new_item->next = NULL; - new_item->data = dupdata; - } - else { - free(new_item); - return NULL; - } - } - else - return NULL; - - if(list) { - last = slist_get_last(list); - last->next = new_item; - return list; - } - - /* if this is the first item, then new_item *is* the list */ - return new_item; -} - -/* - * Curl_slist_duplicate() duplicates a linked list. It always returns the - * address of the first record of the cloned list or NULL in case of an - * error (or if the input list was NULL). - */ -struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist) -{ - struct curl_slist *outlist = NULL; - struct curl_slist *tmp; - - while(inlist) { - tmp = curl_slist_append(outlist, inlist->data); - - if (!tmp) { - curl_slist_free_all(outlist); - return NULL; - } - - outlist = tmp; - inlist = inlist->next; - } - return outlist; -} - -/* be nice and clean up resources */ -void curl_slist_free_all(struct curl_slist *list) -{ - struct curl_slist *next; - struct curl_slist *item; - - if(!list) - return; - - item = list; - do { - next = item->next; - - if(item->data) { - free(item->data); - } - free(item); - item = next; - } while(next); -} diff --git a/third_party/curl/lib/slist.h b/third_party/curl/lib/slist.h deleted file mode 100644 index 161b1509e..000000000 --- a/third_party/curl/lib/slist.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __SLIST_H -#define __SLIST_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Curl_slist_duplicate() duplicates a linked list. It always returns the - * address of the first record of the cloned list or NULL in case of an - * error (or if the input list was NULL). - */ -struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist); - -#endif /* __SLIST_H */ diff --git a/third_party/curl/lib/smtp.c b/third_party/curl/lib/smtp.c deleted file mode 100644 index 5790fe744..000000000 --- a/third_party/curl/lib/smtp.c +++ /dev/null @@ -1,1554 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * RFC2821 SMTP protocol - * RFC3207 SMTP over TLS - * RFC4954 SMTP Authentication - * RFC2195 CRAM-MD5 authentication - * RFC4616 PLAIN authentication - * - ***************************************************************************/ - -#include "setup.h" - -#ifndef CURL_DISABLE_SMTP -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_UTSNAME_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef __VMS -#include -#include -#endif - -#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) -#undef in_addr_t -#define in_addr_t unsigned long -#endif - -#include -#include "urldata.h" -#include "sendf.h" -#include "if2ip.h" -#include "hostip.h" -#include "progress.h" -#include "transfer.h" -#include "escape.h" -#include "http.h" /* for HTTP proxy tunnel stuff */ -#include "socks.h" -#include "smtp.h" - -#include "strtoofft.h" -#include "strequal.h" -#include "sslgen.h" -#include "connect.h" -#include "strerror.h" -#include "select.h" -#include "multiif.h" -#include "url.h" -#include "rawstr.h" -#include "strtoofft.h" -#include "curl_base64.h" -#include "curl_md5.h" -#include "curl_hmac.h" -#include "curl_gethostname.h" -#include "warnless.h" -#include "http_proxy.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* Local API functions */ -static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *done); -static CURLcode smtp_do(struct connectdata *conn, bool *done); -static CURLcode smtp_done(struct connectdata *conn, - CURLcode, bool premature); -static CURLcode smtp_connect(struct connectdata *conn, bool *done); -static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection); -static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done); -static int smtp_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks); -static CURLcode smtp_doing(struct connectdata *conn, - bool *dophase_done); -static CURLcode smtp_setup_connection(struct connectdata * conn); -static CURLcode smtp_state_upgrade_tls(struct connectdata *conn); - - -/* - * SMTP protocol handler. - */ - -const struct Curl_handler Curl_handler_smtp = { - "SMTP", /* scheme */ - smtp_setup_connection, /* setup_connection */ - smtp_do, /* do_it */ - smtp_done, /* done */ - ZERO_NULL, /* do_more */ - smtp_connect, /* connect_it */ - smtp_multi_statemach, /* connecting */ - smtp_doing, /* doing */ - smtp_getsock, /* proto_getsock */ - smtp_getsock, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - smtp_disconnect, /* disconnect */ - PORT_SMTP, /* defport */ - CURLPROTO_SMTP, /* protocol */ - PROTOPT_CLOSEACTION /* flags */ -}; - - -#ifdef USE_SSL -/* - * SMTPS protocol handler. - */ - -const struct Curl_handler Curl_handler_smtps = { - "SMTPS", /* scheme */ - smtp_setup_connection, /* setup_connection */ - smtp_do, /* do_it */ - smtp_done, /* done */ - ZERO_NULL, /* do_more */ - smtp_connect, /* connect_it */ - smtp_multi_statemach, /* connecting */ - smtp_doing, /* doing */ - smtp_getsock, /* proto_getsock */ - smtp_getsock, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - smtp_disconnect, /* disconnect */ - PORT_SMTPS, /* defport */ - CURLPROTO_SMTP | CURLPROTO_SMTPS, /* protocol */ - PROTOPT_CLOSEACTION | PROTOPT_SSL /* flags */ -}; -#endif - -#ifndef CURL_DISABLE_HTTP -/* - * HTTP-proxyed SMTP protocol handler. - */ - -static const struct Curl_handler Curl_handler_smtp_proxy = { - "SMTP", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_SMTP, /* defport */ - CURLPROTO_HTTP, /* protocol */ - PROTOPT_NONE /* flags */ -}; - - -#ifdef USE_SSL -/* - * HTTP-proxyed SMTPS protocol handler. - */ - -static const struct Curl_handler Curl_handler_smtps_proxy = { - "SMTPS", /* scheme */ - ZERO_NULL, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_SMTPS, /* defport */ - CURLPROTO_HTTP, /* protocol */ - PROTOPT_NONE /* flags */ -}; -#endif -#endif - - -/* Function that checks for an ending smtp status code at the start of the - given string. - As a side effect, it also flags allowed authentication mechanisms according - to EHLO AUTH response. */ -static int smtp_endofresp(struct pingpong *pp, int *resp) -{ - char *line = pp->linestart_resp; - size_t len = pp->nread_resp; - struct connectdata *conn = pp->conn; - struct smtp_conn *smtpc = &conn->proto.smtpc; - int result; - size_t wordlen; - - if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2])) - return FALSE; /* Nothing for us. */ - - if((result = (line[3] == ' ')) != 0) - *resp = curlx_sltosi(strtol(line, NULL, 10)); - - line += 4; - len -= 4; - - if(smtpc->state == SMTP_EHLO && len >= 5 && !memcmp(line, "AUTH ", 5)) { - line += 5; - len -= 5; - - for (;;) { - while (len && - (*line == ' ' || *line == '\t' || - *line == '\r' || *line == '\n')) { - line++; - len--; - } - - if(!len) - break; - - for (wordlen = 0; wordlen < len && line[wordlen] != ' ' && - line[wordlen] != '\t' && line[wordlen] != '\r' && - line[wordlen] != '\n';) - wordlen++; - - if(wordlen == 5 && !memcmp(line, "LOGIN", 5)) - smtpc->authmechs |= SMTP_AUTH_LOGIN; - else if(wordlen == 5 && !memcmp(line, "PLAIN", 5)) - smtpc->authmechs |= SMTP_AUTH_PLAIN; - else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8)) - smtpc->authmechs |= SMTP_AUTH_CRAM_MD5; - else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10)) - smtpc->authmechs |= SMTP_AUTH_DIGEST_MD5; - else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6)) - smtpc->authmechs |= SMTP_AUTH_GSSAPI; - else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8)) - smtpc->authmechs |= SMTP_AUTH_EXTERNAL; - - line += wordlen; - len -= wordlen; - } - } - - return result; -} - -/* This is the ONLY way to change SMTP state! */ -static void state(struct connectdata *conn, - smtpstate newstate) -{ - struct smtp_conn *smtpc = &conn->proto.smtpc; -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - /* for debug purposes */ - static const char * const names[]={ - "STOP", - "SERVERGREET", - "EHLO", - "HELO", - "STARTTLS", - "UPGRADETLS", - "AUTHPLAIN", - "AUTHLOGIN", - "AUTHPASSWD", - "AUTHCRAM", - "AUTH", - "MAIL", - "RCPT", - "DATA", - "POSTDATA", - "QUIT", - /* LAST */ - }; - if(smtpc->state != newstate) - infof(conn->data, "SMTP %p state change from %s to %s\n", - smtpc, names[smtpc->state], names[newstate]); -#endif - smtpc->state = newstate; -} - -static CURLcode smtp_state_ehlo(struct connectdata *conn) -{ - CURLcode result; - struct smtp_conn *smtpc = &conn->proto.smtpc; - - smtpc->authmechs = 0; /* No known authentication mechanisms yet. */ - - /* send EHLO */ - result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain); - - if(result) - return result; - - state(conn, SMTP_EHLO); - return CURLE_OK; -} - -static CURLcode smtp_state_helo(struct connectdata *conn) -{ - CURLcode result; - struct smtp_conn *smtpc = &conn->proto.smtpc; - - /* send HELO */ - result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain); - - if(result) - return result; - - state(conn, SMTP_HELO); - return CURLE_OK; -} - -static size_t smtp_auth_plain_data(struct connectdata * conn, char * * outptr) -{ - char plainauth[2 * MAX_CURL_USER_LENGTH + MAX_CURL_PASSWORD_LENGTH]; - size_t ulen; - size_t plen; - - ulen = strlen(conn->user); - plen = strlen(conn->passwd); - - if(2 * ulen + plen + 2 > sizeof plainauth) - return 0; - - memcpy(plainauth, conn->user, ulen); - plainauth[ulen] = '\0'; - memcpy(plainauth + ulen + 1, conn->user, ulen); - plainauth[2 * ulen + 1] = '\0'; - memcpy(plainauth + 2 * ulen + 2, conn->passwd, plen); - return Curl_base64_encode(conn->data, plainauth, 2 * ulen + plen + 2, outptr); -} - -static size_t smtp_auth_login_user(struct connectdata * conn, char * * outptr) -{ - size_t ulen; - - ulen = strlen(conn->user); - - if(!ulen) { - *outptr = strdup("="); - return *outptr? 1: 0; - } - - return Curl_base64_encode(conn->data, conn->user, ulen, outptr); -} - -static CURLcode smtp_authenticate(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct smtp_conn *smtpc = &conn->proto.smtpc; - char * initresp; - const char * mech; - size_t l; - smtpstate state1; - smtpstate state2; - - if(!conn->bits.user_passwd) - state(conn, SMTP_STOP); /* End of connect phase. */ - else { - initresp = (char *) NULL; - l = 1; - - /* Check supported authentication mechanisms by decreasing order of - preference. */ - mech = (const char *) NULL; /* Avoid compiler warnings. */ - state1 = SMTP_STOP; - state2 = SMTP_STOP; - -#ifndef CURL_DISABLE_CRYPTO_AUTH - if(smtpc->authmechs & SMTP_AUTH_CRAM_MD5) { - mech = "CRAM-MD5"; - state1 = SMTP_AUTHCRAM; - } - else -#endif - if(smtpc->authmechs & SMTP_AUTH_PLAIN) { - mech = "PLAIN"; - state1 = SMTP_AUTHPLAIN; - state2 = SMTP_AUTH; - l = smtp_auth_plain_data(conn, &initresp); - } - else if(smtpc->authmechs & SMTP_AUTH_LOGIN) { - mech = "LOGIN"; - state1 = SMTP_AUTHLOGIN; - state2 = SMTP_AUTHPASSWD; - l = smtp_auth_login_user(conn, &initresp); - } - else { - infof(conn->data, "No known auth mechanisms supported!\n"); - result = CURLE_LOGIN_DENIED; /* Other mechanisms not supported. */ - } - - if(!result) { - if(!l) - result = CURLE_OUT_OF_MEMORY; - else if(initresp && - l + strlen(mech) <= 512 - 8) { /* AUTH ... */ - result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp); - free(initresp); - - if(!result) - state(conn, state2); - } - else { - Curl_safefree(initresp); - - result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech); - - if(!result) - state(conn, state1); - } - } - } - - return result; -} - -/* For the SMTP "protocol connect" and "doing" phases only */ -static int smtp_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - return Curl_pp_getsock(&conn->proto.smtpc.pp, socks, numsocks); -} - -#ifdef USE_SSL -static void smtp_to_smtps(struct connectdata *conn) -{ - conn->handler = &Curl_handler_smtps; -} -#else -#define smtp_to_smtps(x) -#endif - -/* for STARTTLS responses */ -static CURLcode smtp_state_starttls_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - (void)instate; /* no use for this yet */ - - if(smtpcode != 220) { - if(data->set.ftp_ssl != CURLUSESSL_TRY) { - failf(data, "STARTTLS denied. %c", smtpcode); - result = CURLE_LOGIN_DENIED; - } - else - result = smtp_authenticate(conn); - } - else { - if(data->state.used_interface == Curl_if_multi) { - state(conn, SMTP_UPGRADETLS); - return smtp_state_upgrade_tls(conn); - } - else { - result = Curl_ssl_connect(conn, FIRSTSOCKET); - if(CURLE_OK == result) { - smtp_to_smtps(conn); - result = smtp_state_ehlo(conn); - } - } - } - return result; -} - -static CURLcode smtp_state_upgrade_tls(struct connectdata *conn) -{ - struct smtp_conn *smtpc = &conn->proto.smtpc; - CURLcode result; - - result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); - - if(smtpc->ssldone) { - smtp_to_smtps(conn); - result = smtp_state_ehlo(conn); - } - - return result; -} - -/* for EHLO responses */ -static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - - (void)instate; /* no use for this yet */ - - if(smtpcode/100 != 2) { - if((data->set.ftp_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) && - !conn->bits.user_passwd) - result = smtp_state_helo(conn); - else { - failf(data, "Access denied: %d", smtpcode); - result = CURLE_LOGIN_DENIED; - } - } - else if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) { - /* We don't have a SSL/TLS connection yet, but SSL is requested. Switch - to TLS connection now */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "STARTTLS"); - state(conn, SMTP_STARTTLS); - } - else - result = smtp_authenticate(conn); - - return result; -} - -/* for HELO responses */ -static CURLcode smtp_state_helo_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - - (void)instate; /* no use for this yet */ - - if(smtpcode/100 != 2) { - failf(data, "Access denied: %d", smtpcode); - result = CURLE_LOGIN_DENIED; - } - else { - /* end the connect phase */ - state(conn, SMTP_STOP); - } - return result; -} - -/* for AUTH PLAIN (without initial response) responses */ -static CURLcode smtp_state_authplain_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - size_t l; - char * plainauth; - - (void)instate; /* no use for this yet */ - - if(smtpcode != 334) { - failf(data, "Access denied: %d", smtpcode); - result = CURLE_LOGIN_DENIED; - } - else { - l = smtp_auth_plain_data(conn, &plainauth); - - if(!l) - result = CURLE_OUT_OF_MEMORY; - else { - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth); - free(plainauth); - - if(!result) - state(conn, SMTP_AUTH); - } - } - - return result; -} - -/* for AUTH LOGIN (without initial response) responses */ -static CURLcode smtp_state_authlogin_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - size_t l; - char * authuser; - - (void)instate; /* no use for this yet */ - - if(smtpcode != 334) { - failf(data, "Access denied: %d", smtpcode); - result = CURLE_LOGIN_DENIED; - } - else { - l = smtp_auth_login_user(conn, &authuser); - - if(!l) - result = CURLE_OUT_OF_MEMORY; - else { - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser); - free(authuser); - - if(!result) - state(conn, SMTP_AUTHPASSWD); - } - } - - return result; -} - -/* for responses to user entry of AUTH LOGIN. */ -static CURLcode smtp_state_authpasswd_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - size_t plen; - size_t l; - char *authpasswd; - - (void)instate; /* no use for this yet */ - - if(smtpcode != 334) { - failf(data, "Access denied: %d", smtpcode); - result = CURLE_LOGIN_DENIED; - } - else { - plen = strlen(conn->passwd); - - if(!plen) - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "="); - else { - l = Curl_base64_encode(data, conn->passwd, plen, &authpasswd); - - if(!l) - result = CURLE_OUT_OF_MEMORY; - else { - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd); - free(authpasswd); - - if(!result) - state(conn, SMTP_AUTH); - } - } - } - - return result; -} - -#ifndef CURL_DISABLE_CRYPTO_AUTH - -/* for AUTH CRAM-MD5 responses. */ -static CURLcode smtp_state_authcram_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - char * chlg64 = data->state.buffer; - unsigned char * chlg; - size_t chlglen; - size_t l; - char * rplyb64; - HMAC_context * ctxt; - unsigned char digest[16]; - char reply[MAX_CURL_USER_LENGTH + 32 /* 2 * size of MD5 digest */ + 1]; - - (void)instate; /* no use for this yet */ - - if(smtpcode != 334) { - failf(data, "Access denied: %d", smtpcode); - return CURLE_LOGIN_DENIED; - } - - /* Get the challenge. */ - for (chlg64 += 4; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++) - ; - - chlg = (unsigned char *) NULL; - chlglen = 0; - - if(*chlg64 != '=') { - for (l = strlen(chlg64); l--;) - if(chlg64[l] != '\r' && chlg64[l] != '\n' && chlg64[l] != ' ' && - chlg64[l] != '\t') - break; - - if(++l) { - chlg64[l] = '\0'; - - chlglen = Curl_base64_decode(chlg64, &chlg); - if(!chlglen) - return CURLE_OUT_OF_MEMORY; - } - } - - /* Compute digest. */ - ctxt = Curl_HMAC_init(Curl_HMAC_MD5, - (const unsigned char *) conn->passwd, - (unsigned int)(strlen(conn->passwd))); - - if(!ctxt) { - if(chlg) - free(chlg); - - return CURLE_OUT_OF_MEMORY; - } - - if(chlglen > 0) - Curl_HMAC_update(ctxt, chlg, (unsigned int)(chlglen)); - - if(chlg) - free(chlg); - - Curl_HMAC_final(ctxt, digest); - - /* Prepare the reply. */ - snprintf(reply, sizeof reply, - "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - conn->user, digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], - digest[6], digest[7], digest[8], digest[9], digest[10], digest[11], - digest[12], digest[13], digest[14], digest[15]); - - /* Encode it to base64 and send it. */ - l = Curl_base64_encode(data, reply, 0, &rplyb64); - - if(!l) - result = CURLE_OUT_OF_MEMORY; - else { - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64); - free(rplyb64); - - if(!result) - state(conn, SMTP_AUTH); - } - - return result; -} - -#endif - -/* for final responses to AUTH sequences. */ -static CURLcode smtp_state_auth_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - - (void)instate; /* no use for this yet */ - - if(smtpcode != 235) { - failf(data, "Authentication failed: %d", smtpcode); - result = CURLE_LOGIN_DENIED; - } - else - state(conn, SMTP_STOP); /* End of connect phase. */ - - return result; -} - -/* start the DO phase */ -static CURLcode smtp_mail(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - - /* send MAIL FROM */ - if (data->set.str[STRING_MAIL_FROM][0] == '<') - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:%s", - data->set.str[STRING_MAIL_FROM]); - else - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:<%s>", - data->set.str[STRING_MAIL_FROM]); - if(result) - return result; - - state(conn, SMTP_MAIL); - return result; -} - -static CURLcode smtp_rcpt_to(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct smtp_conn *smtpc = &conn->proto.smtpc; - - /* send RCPT TO */ - if(smtpc->rcpt) { - if(smtpc->rcpt->data[0] == '<') - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s", - smtpc->rcpt->data); - else - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", - smtpc->rcpt->data); - if(!result) - state(conn, SMTP_RCPT); - } - return result; -} - -/* for MAIL responses */ -static CURLcode smtp_state_mail_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - (void)instate; /* no use for this yet */ - - if(smtpcode/100 != 2) { - failf(data, "Access denied: %d", smtpcode); - result = CURLE_LOGIN_DENIED; - state(conn, SMTP_STOP); - } - else { - struct smtp_conn *smtpc = &conn->proto.smtpc; - smtpc->rcpt = data->set.mail_rcpt; - - result = smtp_rcpt_to(conn); - } - - return result; -} - -/* for RCPT responses */ -static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - (void)instate; /* no use for this yet */ - - if(smtpcode/100 != 2) { - failf(data, "Access denied: %d", smtpcode); - result = CURLE_LOGIN_DENIED; - state(conn, SMTP_STOP); - } - else { - struct smtp_conn *smtpc = &conn->proto.smtpc; - - if(smtpc->rcpt) { - smtpc->rcpt = smtpc->rcpt->next; - result = smtp_rcpt_to(conn); - - /* if we failed or still is in RCPT sending, return */ - if(result || smtpc->rcpt) - return result; - } - - /* send DATA */ - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "DATA"); - if(result) - return result; - - state(conn, SMTP_DATA); - } - return result; -} - -/* for the DATA response */ -static CURLcode smtp_state_data_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - struct SessionHandle *data = conn->data; - struct FTP *smtp = data->state.proto.smtp; - - (void)instate; /* no use for this yet */ - - if(smtpcode != 354) { - state(conn, SMTP_STOP); - return CURLE_RECV_ERROR; - } - - /* SMTP upload */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */ - FIRSTSOCKET, smtp->bytecountp); - - state(conn, SMTP_STOP); - return CURLE_OK; -} - -/* for the POSTDATA response, which is received after the entire DATA - part has been sent off to the server */ -static CURLcode smtp_state_postdata_resp(struct connectdata *conn, - int smtpcode, - smtpstate instate) -{ - CURLcode result = CURLE_OK; - - (void)instate; /* no use for this yet */ - - if(smtpcode != 250) - result = CURLE_RECV_ERROR; - - state(conn, SMTP_STOP); - return result; -} - -static CURLcode smtp_statemach_act(struct connectdata *conn) -{ - CURLcode result; - curl_socket_t sock = conn->sock[FIRSTSOCKET]; - struct SessionHandle *data=conn->data; - int smtpcode; - struct smtp_conn *smtpc = &conn->proto.smtpc; - struct pingpong *pp = &smtpc->pp; - size_t nread = 0; - - if(smtpc->state == SMTP_UPGRADETLS) - return smtp_state_upgrade_tls(conn); - - if(pp->sendleft) - /* we have a piece of a command still left to send */ - return Curl_pp_flushsend(pp); - - /* we read a piece of response */ - result = Curl_pp_readresp(sock, pp, &smtpcode, &nread); - if(result) - return result; - - if(smtpcode) { - /* we have now received a full SMTP server response */ - switch(smtpc->state) { - case SMTP_SERVERGREET: - if(smtpcode/100 != 2) { - failf(data, "Got unexpected smtp-server response: %d", smtpcode); - return CURLE_FTP_WEIRD_SERVER_REPLY; - } - - result = smtp_state_ehlo(conn); - if(result) - return result; - break; - - case SMTP_EHLO: - result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state); - break; - - case SMTP_HELO: - result = smtp_state_helo_resp(conn, smtpcode, smtpc->state); - break; - - case SMTP_STARTTLS: - result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state); - break; - - case SMTP_AUTHPLAIN: - result = smtp_state_authplain_resp(conn, smtpcode, smtpc->state); - break; - - case SMTP_AUTHLOGIN: - result = smtp_state_authlogin_resp(conn, smtpcode, smtpc->state); - break; - - case SMTP_AUTHPASSWD: - result = smtp_state_authpasswd_resp(conn, smtpcode, smtpc->state); - break; - -#ifndef CURL_DISABLE_CRYPTO_AUTH - case SMTP_AUTHCRAM: - result = smtp_state_authcram_resp(conn, smtpcode, smtpc->state); - break; -#endif - - case SMTP_AUTH: - result = smtp_state_auth_resp(conn, smtpcode, smtpc->state); - break; - - case SMTP_MAIL: - result = smtp_state_mail_resp(conn, smtpcode, smtpc->state); - break; - - case SMTP_RCPT: - result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state); - break; - - case SMTP_DATA: - result = smtp_state_data_resp(conn, smtpcode, smtpc->state); - break; - - case SMTP_POSTDATA: - result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state); - break; - - case SMTP_QUIT: - /* fallthrough, just stop! */ - default: - /* internal error */ - state(conn, SMTP_STOP); - break; - } - } - return result; -} - -/* called repeatedly until done from multi.c */ -static CURLcode smtp_multi_statemach(struct connectdata *conn, - bool *done) -{ - struct smtp_conn *smtpc = &conn->proto.smtpc; - CURLcode result; - - if((conn->handler->protocol & CURLPROTO_SMTPS) && !smtpc->ssldone) { - result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone); - } - else { - result = Curl_pp_multi_statemach(&smtpc->pp); - } - - *done = (bool)(smtpc->state == SMTP_STOP); - - return result; -} - -static CURLcode smtp_easy_statemach(struct connectdata *conn) -{ - struct smtp_conn *smtpc = &conn->proto.smtpc; - struct pingpong *pp = &smtpc->pp; - CURLcode result = CURLE_OK; - - while(smtpc->state != SMTP_STOP) { - result = Curl_pp_easy_statemach(pp); - if(result) - break; - } - - return result; -} - -/* - * Allocate and initialize the struct SMTP for the current SessionHandle. If - * need be. - */ -static CURLcode smtp_init(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - struct FTP *smtp = data->state.proto.smtp; - if(!smtp) { - smtp = data->state.proto.smtp = calloc(sizeof(struct FTP), 1); - if(!smtp) - return CURLE_OUT_OF_MEMORY; - } - - /* get some initial data into the smtp struct */ - smtp->bytecountp = &data->req.bytecount; - - /* 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. - */ - smtp->user = conn->user; - smtp->passwd = conn->passwd; - - return CURLE_OK; -} - -/* - * smtp_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 is not. When called as - * a part of the easy interface, it will always be TRUE. - */ -static CURLcode smtp_connect(struct connectdata *conn, - bool *done) /* see description above */ -{ - CURLcode result; - struct smtp_conn *smtpc = &conn->proto.smtpc; - struct SessionHandle *data=conn->data; - struct pingpong *pp=&smtpc->pp; - const char *path = conn->data->state.path; - int len; - char localhost[1024 + 1]; - - *done = FALSE; /* default to not done yet */ - - /* If there already is a protocol-specific struct allocated for this - sessionhandle, deal with it */ - Curl_reset_reqproto(conn); - - result = smtp_init(conn); - if(CURLE_OK != result) - return result; - - /* We always support persistent connections on smtp */ - conn->bits.close = FALSE; - - pp->response_time = RESP_TIMEOUT; /* set default response time-out */ - pp->statemach_act = smtp_statemach_act; - pp->endofresp = smtp_endofresp; - pp->conn = conn; - - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - /* for SMTP over HTTP proxy */ - struct HTTP http_proxy; - struct FTP *smtp_save; - - /* BLOCKING */ - /* We want "seamless" SMTP operations through HTTP proxy tunnel */ - - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member - * conn->proto.http; we want SMTP through HTTP and we have to change the - * member temporarily for connecting to the HTTP proxy. After - * Curl_proxyCONNECT we have to set back the member to the original struct - * SMTP pointer - */ - smtp_save = data->state.proto.smtp; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->state.proto.http = &http_proxy; - - result = Curl_proxyCONNECT(conn, FIRSTSOCKET, - conn->host.name, conn->remote_port); - - data->state.proto.smtp = smtp_save; - - if(CURLE_OK != result) - return result; - } - - if((conn->handler->protocol & CURLPROTO_SMTPS) && - data->state.used_interface != Curl_if_multi) { - /* SMTPS is simply smtp with SSL for the control channel */ - /* now, perform the SSL initialization for this socket */ - result = Curl_ssl_connect(conn, FIRSTSOCKET); - if(result) - return result; - } - - Curl_pp_init(pp); /* init the response reader stuff */ - - pp->response_time = RESP_TIMEOUT; /* set default response time-out */ - pp->statemach_act = smtp_statemach_act; - pp->endofresp = smtp_endofresp; - pp->conn = conn; - - if(!*path) { - if(!Curl_gethostname(localhost, sizeof localhost)) - path = localhost; - else - path = "localhost"; - } - - /* url decode the path and use it as domain with EHLO */ - smtpc->domain = curl_easy_unescape(conn->data, path, 0, &len); - if(!smtpc->domain) - return CURLE_OUT_OF_MEMORY; - - /* When we connect, we start in the state where we await the server greeting - */ - state(conn, SMTP_SERVERGREET); - - if(data->state.used_interface == Curl_if_multi) - result = smtp_multi_statemach(conn, done); - else { - result = smtp_easy_statemach(conn); - if(!result) - *done = TRUE; - } - - return result; -} - -/*********************************************************************** - * - * smtp_done() - * - * The DONE function. This does what needs to be done after a single DO has - * performed. - * - * Input argument is already checked for validity. - */ -static CURLcode smtp_done(struct connectdata *conn, CURLcode status, - bool premature) -{ - struct SessionHandle *data = conn->data; - struct FTP *smtp = data->state.proto.smtp; - CURLcode result=CURLE_OK; - ssize_t bytes_written; - (void)premature; - - if(!smtp) - /* When the easy handle is removed from the multi while libcurl is still - * trying to resolve the host name, it seems that the smtp struct is not - * yet initialized, but the removal action calls Curl_done() which calls - * this function. So we simply return success if no smtp pointer is set. - */ - return CURLE_OK; - - if(status) { - conn->bits.close = TRUE; /* marked for closure */ - result = status; /* use the already set error code */ - } - else - /* TODO: make this work even when the socket is EWOULDBLOCK in this call! */ - - /* write to socket (send away data) */ - result = Curl_write(conn, - conn->writesockfd, /* socket to send to */ - SMTP_EOB, /* buffer pointer */ - SMTP_EOB_LEN, /* buffer size */ - &bytes_written); /* actually sent away */ - - - if(status == CURLE_OK) { - struct smtp_conn *smtpc = &conn->proto.smtpc; - struct pingpong *pp= &smtpc->pp; - pp->response = Curl_tvnow(); /* timeout relative now */ - - state(conn, SMTP_POSTDATA); - /* run the state-machine - - TODO: when the multi interface is used, this _really_ should be using - the smtp_multi_statemach function but we have no general support for - non-blocking DONE operations, not in the multi state machine and with - Curl_done() invokes on several places in the code! - */ - result = smtp_easy_statemach(conn); - } - - /* clear these for next connection */ - smtp->transfer = FTPTRANSFER_BODY; - - return result; -} - -/*********************************************************************** - * - * smtp_perform() - * - * This is the actual DO function for SMTP. Get a file/directory according to - * the options previously setup. - */ - -static -CURLcode smtp_perform(struct connectdata *conn, - bool *connected, /* connect status after PASV / PORT */ - bool *dophase_done) -{ - /* this is SMTP 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 *smtp = conn->data->state.proto.smtp; - smtp->transfer = FTPTRANSFER_INFO; - } - - *dophase_done = FALSE; /* not done yet */ - - /* start the first command in the DO phase */ - result = smtp_mail(conn); - if(result) - return result; - - /* run the state-machine */ - if(conn->data->state.used_interface == Curl_if_multi) - result = smtp_multi_statemach(conn, dophase_done); - else { - result = smtp_easy_statemach(conn); - *dophase_done = TRUE; /* with the easy interface we are done here */ - } - *connected = conn->bits.tcpconnect; - - if(*dophase_done) - DEBUGF(infof(conn->data, "DO phase is complete\n")); - - return result; -} - -/*********************************************************************** - * - * smtp_do() - * - * This function is registered as 'curl_do' function. It decodes the path - * parts etc as a wrapper to the actual DO function (smtp_perform). - * - * The input argument is already checked for validity. - */ -static CURLcode smtp_do(struct connectdata *conn, bool *done) -{ - CURLcode retcode = CURLE_OK; - - *done = FALSE; /* default to false */ - - /* - Since connections can be re-used between SessionHandles, this might be a - connection already existing but on a fresh SessionHandle struct so we must - make sure we have a good 'struct SMTP' to play with. For new connections, - the struct SMTP is allocated and setup in the smtp_connect() function. - */ - Curl_reset_reqproto(conn); - retcode = smtp_init(conn); - if(retcode) - return retcode; - - retcode = smtp_regular_transfer(conn, done); - - return retcode; -} - -/*********************************************************************** - * - * smtp_quit() - * - * This should be called before calling sclose(). We should then wait for the - * response from the server before returning. The calling code should then try - * to close the connection. - * - */ -static CURLcode smtp_quit(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "QUIT"); - if(result) - return result; - state(conn, SMTP_QUIT); - - result = smtp_easy_statemach(conn); - - return result; -} - -/*********************************************************************** - * - * smtp_disconnect() - * - * Disconnect from an SMTP server. Cleanup protocol-specific per-connection - * resources. BLOCKING. - */ -static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection) -{ - struct smtp_conn *smtpc= &conn->proto.smtpc; - - /* We cannot send quit unconditionally. If this connection is stale or - bad in any way, sending quit and waiting around here will make the - disconnect wait in vain and cause more problems than we need to. - */ - - /* The SMTP session may or may not have been allocated/setup at this - point! */ - if(!dead_connection && smtpc->pp.conn) - (void)smtp_quit(conn); /* ignore errors on the LOGOUT */ - - Curl_pp_disconnect(&smtpc->pp); - - /* This won't already be freed in some error cases */ - Curl_safefree(smtpc->domain); - smtpc->domain = NULL; - - return CURLE_OK; -} - -/* call this when the DO phase has completed */ -static CURLcode smtp_dophase_done(struct connectdata *conn, - bool connected) -{ - struct FTP *smtp = conn->data->state.proto.smtp; - struct smtp_conn *smtpc= &conn->proto.smtpc; - (void)connected; - - if(smtp->transfer != FTPTRANSFER_BODY) - /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - - free(smtpc->domain); - smtpc->domain = NULL; - - return CURLE_OK; -} - -/* called from multi.c while DOing */ -static CURLcode smtp_doing(struct connectdata *conn, - bool *dophase_done) -{ - CURLcode result; - result = smtp_multi_statemach(conn, dophase_done); - - if(*dophase_done) { - result = smtp_dophase_done(conn, FALSE /* not connected */); - - DEBUGF(infof(conn->data, "DO phase is complete\n")); - } - return result; -} - -/*********************************************************************** - * - * smtp_regular_transfer() - * - * The input argument is already checked for validity. - * - * Performs all commands done before a regular transfer between a local and a - * remote host. - */ -static -CURLcode smtp_regular_transfer(struct connectdata *conn, - bool *dophase_done) -{ - CURLcode result=CURLE_OK; - bool connected=FALSE; - struct SessionHandle *data = conn->data; - data->req.size = -1; /* make sure this is unknown at this point */ - - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - Curl_pgrsSetUploadSize(data, 0); - Curl_pgrsSetDownloadSize(data, 0); - - result = smtp_perform(conn, - &connected, /* have we connected after PASV/PORT */ - dophase_done); /* all commands in the DO-phase done? */ - - if(CURLE_OK == result) { - - if(!*dophase_done) - /* the DO phase has not completed yet */ - return CURLE_OK; - - result = smtp_dophase_done(conn, connected); - if(result) - return result; - } - - return result; -} - -static CURLcode smtp_setup_connection(struct connectdata * conn) -{ - struct SessionHandle *data = conn->data; - - if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { - /* Unless we have asked to tunnel smtp operations through the proxy, we - switch and use HTTP operations only */ -#ifndef CURL_DISABLE_HTTP - if(conn->handler == &Curl_handler_smtp) - conn->handler = &Curl_handler_smtp_proxy; - else { -#ifdef USE_SSL - conn->handler = &Curl_handler_smtps_proxy; -#else - failf(data, "SMTPS not supported!"); - return CURLE_UNSUPPORTED_PROTOCOL; -#endif - } - /* - * We explicitly mark this connection as persistent here as we're doing - * SMTP over HTTP and thus we accidentally avoid setting this value - * otherwise. - */ - conn->bits.close = FALSE; -#else - failf(data, "SMTP over http proxy requires HTTP support built-in!"); - return CURLE_UNSUPPORTED_PROTOCOL; -#endif - } - - data->state.path++; /* don't include the initial slash */ - - return CURLE_OK; -} - -CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread) -{ - /* When sending SMTP payload, we must detect CRLF.CRLF sequences in - * the data and make sure it is sent as CRLF..CRLF instead, as - * otherwise it will wrongly be detected as end of data by the server. - */ - ssize_t i; - ssize_t si; - struct smtp_conn *smtpc = &conn->proto.smtpc; - struct SessionHandle *data = conn->data; - - if(data->state.scratch == NULL) - data->state.scratch = malloc(2*BUFSIZE); - if(data->state.scratch == NULL) { - failf (data, "Failed to alloc scratch buffer!"); - return CURLE_OUT_OF_MEMORY; - } - /* This loop can be improved by some kind of Boyer-Moore style of - approach but that is saved for later... */ - for(i = 0, si = 0; i < nread; i++, si++) { - ssize_t left = nread - i; - - if(left>= (ssize_t)(SMTP_EOB_LEN-smtpc->eob)) { - if(!memcmp(SMTP_EOB+smtpc->eob, &data->req.upload_fromhere[i], - SMTP_EOB_LEN-smtpc->eob)) { - /* It matched, copy the replacement data to the target buffer - instead. Note that the replacement does not contain the - trailing CRLF but we instead continue to match on that one - to deal with repeated sequences. Like CRLF.CRLF.CRLF etc - */ - memcpy(&data->state.scratch[si], SMTP_EOB_REPL, - SMTP_EOB_REPL_LEN); - si+=SMTP_EOB_REPL_LEN-1; /* minus one since the for() increments - it */ - i+=SMTP_EOB_LEN-smtpc->eob-1-2; - smtpc->eob = 0; /* start over */ - continue; - } - } - else if(!memcmp(SMTP_EOB+smtpc->eob, &data->req.upload_fromhere[i], - left)) { - /* the last piece of the data matches the EOB so we can't send that - until we know the rest of it */ - smtpc->eob += left; - break; - } - - data->state.scratch[si] = data->req.upload_fromhere[i]; - } /* for() */ - - if(si != nread) { - /* only use the new buffer if we replaced something */ - nread = si; - - /* upload from the new (replaced) buffer instead */ - data->req.upload_fromhere = data->state.scratch; - - /* set the new amount too */ - data->req.upload_present = nread; - } - return CURLE_OK; -} - -#endif /* CURL_DISABLE_SMTP */ diff --git a/third_party/curl/lib/smtp.h b/third_party/curl/lib/smtp.h deleted file mode 100644 index 0f527142c..000000000 --- a/third_party/curl/lib/smtp.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef __SMTP_H -#define __SMTP_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2009 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#include "pingpong.h" - -/**************************************************************************** - * SMTP unique setup - ***************************************************************************/ -typedef enum { - SMTP_STOP, /* do nothing state, stops the state machine */ - SMTP_SERVERGREET, /* waiting for the initial greeting immediately after - a connect */ - SMTP_EHLO, - SMTP_HELO, - SMTP_STARTTLS, - SMTP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS (multi mode only) */ - SMTP_AUTHPLAIN, - SMTP_AUTHLOGIN, - SMTP_AUTHPASSWD, - SMTP_AUTHCRAM, - SMTP_AUTH, - SMTP_MAIL, /* MAIL FROM */ - SMTP_RCPT, /* RCPT TO */ - SMTP_DATA, - SMTP_POSTDATA, - SMTP_QUIT, - SMTP_LAST /* never used */ -} smtpstate; - -/* smtp_conn is used for struct connection-oriented data in the connectdata - struct */ -struct smtp_conn { - struct pingpong pp; - char *domain; /* what to send in the EHLO */ - size_t eob; /* number of bytes of the EOB (End Of Body) that has been - received thus far */ - unsigned int authmechs; /* Accepted authentication methods. */ - smtpstate state; /* always use smtp.c:state() to change state! */ - struct curl_slist *rcpt; - bool ssldone; /* is connect() over SSL done? only relevant in multi mode */ -}; - -/* Authentication mechanism flags. */ -#define SMTP_AUTH_LOGIN 0x0001 -#define SMTP_AUTH_PLAIN 0x0002 -#define SMTP_AUTH_CRAM_MD5 0x0004 -#define SMTP_AUTH_DIGEST_MD5 0x0008 -#define SMTP_AUTH_GSSAPI 0x0010 -#define SMTP_AUTH_EXTERNAL 0x0020 - -extern const struct Curl_handler Curl_handler_smtp; -extern const struct Curl_handler Curl_handler_smtps; - -/* this is the 5-bytes End-Of-Body marker for SMTP */ -#define SMTP_EOB "\x0d\x0a\x2e\x0d\x0a" -#define SMTP_EOB_LEN 5 - -/* if found in data, replace it with this string instead */ -#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e" -#define SMTP_EOB_REPL_LEN 4 - -CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread); - -#endif /* __SMTP_H */ diff --git a/third_party/curl/lib/sockaddr.h b/third_party/curl/lib/sockaddr.h deleted file mode 100644 index c69411b52..000000000 --- a/third_party/curl/lib/sockaddr.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __SOCKADDR_H -#define __SOCKADDR_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_STRUCT_SOCKADDR_STORAGE -struct Curl_sockaddr_storage { - struct sockaddr_storage buffer; -}; -#else -struct Curl_sockaddr_storage { - char buffer[256]; /* this should be big enough to fit a lot */ -}; -#endif - -#endif /* __SOCKADDR_H */ diff --git a/third_party/curl/lib/socks.c b/third_party/curl/lib/socks.c deleted file mode 100644 index c03cd2be3..000000000 --- a/third_party/curl/lib/socks.c +++ /dev/null @@ -1,732 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#if !defined(CURL_DISABLE_PROXY) || defined(USE_WINDOWS_SSPI) -#include - -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif - -#include "urldata.h" -#include "sendf.h" -#include "strequal.h" -#include "select.h" -#include "connect.h" -#include "timeval.h" -#include "socks.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -/* - * Helper read-from-socket functions. Does the same as Curl_read() but it - * blocks until all bytes amount of buffersize will be read. No more, no less. - * - * This is STUPID BLOCKING behaviour which we frown upon, but right now this - * is what we have... - */ -int Curl_blockread_all(struct connectdata *conn, /* connection data */ - curl_socket_t sockfd, /* read from this socket */ - char *buf, /* store read data here */ - ssize_t buffersize, /* max amount to read */ - ssize_t *n, /* amount bytes read */ - long conn_timeout) /* timeout for data wait - relative to - conn->created */ -{ - ssize_t nread; - ssize_t allread = 0; - int result; - struct timeval tvnow; - long conntime; - *n = 0; - for(;;) { - tvnow = Curl_tvnow(); - /* calculating how long connection is establishing */ - conntime = Curl_tvdiff(tvnow, conn->created); - if(conntime > conn_timeout) { - /* we already got the timeout */ - result = CURLE_OPERATION_TIMEDOUT; - break; - } - if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD, - (int)(conn_timeout - conntime)) <= 0) { - result = ~CURLE_OK; - break; - } - result = Curl_read_plain(sockfd, buf, buffersize, &nread); - if(CURLE_AGAIN == result) - continue; - else if(result) - break; - - if(buffersize == nread) { - allread += nread; - *n = allread; - result = CURLE_OK; - break; - } - if(!nread) { - result = ~CURLE_OK; - break; - } - - buffersize -= nread; - buf += nread; - allread += nread; - } - return result; -} - -/* -* This function logs in to a SOCKS4 proxy and sends the specifics to the final -* destination server. -* -* Reference : -* http://socks.permeo.com/protocol/socks4.protocol -* -* Note : -* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)" -* Nonsupport "Identification Protocol (RFC1413)" -*/ -CURLcode Curl_SOCKS4(const char *proxy_name, - const char *hostname, - int remote_port, - int sockindex, - struct connectdata *conn, - bool protocol4a) -{ -#define SOCKS4REQLEN 262 - unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user - id */ - int result; - CURLcode code; - curl_socket_t sock = conn->sock[sockindex]; - long timeout; - struct SessionHandle *data = conn->data; - - /* get timeout */ - timeout = Curl_timeleft(data, NULL, TRUE); - - if(timeout < 0) { - /* time-out, bail out, go home */ - failf(data, "Connection time-out"); - return CURLE_OPERATION_TIMEDOUT; - } - - curlx_nonblock(sock, FALSE); - - /* - * Compose socks4 request - * - * Request format - * - * +----+----+----+----+----+----+----+----+----+----+....+----+ - * | VN | CD | DSTPORT | DSTIP | USERID |NULL| - * +----+----+----+----+----+----+----+----+----+----+....+----+ - * # of bytes: 1 1 2 4 variable 1 - */ - - socksreq[0] = 4; /* version (SOCKS4) */ - socksreq[1] = 1; /* connect */ - *((unsigned short*)&socksreq[2]) = htons((unsigned short)remote_port); - - /* DNS resolve only for SOCKS4, not SOCKS4a */ - if (!protocol4a) { - struct Curl_dns_entry *dns; - Curl_addrinfo *hp=NULL; - int rc; - - rc = Curl_resolv(conn, hostname, remote_port, &dns); - - if(rc == CURLRESOLV_ERROR) - return CURLE_COULDNT_RESOLVE_PROXY; - - if(rc == CURLRESOLV_PENDING) - /* ignores the return code, but 'dns' remains NULL on failure */ - (void)Curl_wait_for_resolv(conn, &dns); - - /* - * We cannot use 'hostent' as a struct that Curl_resolv() returns. It - * returns a Curl_addrinfo pointer that may not always look the same. - */ - if(dns) - hp=dns->addr; - if(hp) { - char buf[64]; - unsigned short ip[4]; - Curl_printable_address(hp, buf, sizeof(buf)); - - if(4 == sscanf( buf, "%hu.%hu.%hu.%hu", - &ip[0], &ip[1], &ip[2], &ip[3])) { - /* Set DSTIP */ - socksreq[4] = (unsigned char)ip[0]; - socksreq[5] = (unsigned char)ip[1]; - socksreq[6] = (unsigned char)ip[2]; - socksreq[7] = (unsigned char)ip[3]; - } - else - hp = NULL; /* fail! */ - - Curl_resolv_unlock(data, dns); /* not used anymore from now on */ - - } - if(!hp) { - failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.", - hostname); - return CURLE_COULDNT_RESOLVE_HOST; - } - } - - /* - * This is currently not supporting "Identification Protocol (RFC1413)". - */ - socksreq[8] = 0; /* ensure empty userid is NUL-terminated */ - if(proxy_name) - strlcat((char*)socksreq + 8, proxy_name, sizeof(socksreq) - 8); - - /* - * Make connection - */ - { - ssize_t actualread; - ssize_t written; - ssize_t hostnamelen = 0; - int packetsize = 9 + - (int)strlen((char*)socksreq + 8); /* size including NUL */ - - /* If SOCKS4a, set special invalid IP address 0.0.0.x */ - if (protocol4a) { - socksreq[4] = 0; - socksreq[5] = 0; - socksreq[6] = 0; - socksreq[7] = 1; - /* If still enough room in buffer, also append hostname */ - hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */ - if (packetsize + hostnamelen <= SOCKS4REQLEN) - strcpy((char*)socksreq + packetsize, hostname); - else - hostnamelen = 0; /* Flag: hostname did not fit in buffer */ - } - - /* Send request */ - code = Curl_write_plain(conn, sock, (char *)socksreq, - packetsize + hostnamelen, - &written); - if((code != CURLE_OK) || (written != packetsize + hostnamelen)) { - failf(data, "Failed to send SOCKS4 connect request."); - return CURLE_COULDNT_CONNECT; - } - if (protocol4a && hostnamelen == 0) { - /* SOCKS4a with very long hostname - send that name separately */ - hostnamelen = (ssize_t)strlen(hostname) + 1; - code = Curl_write_plain(conn, sock, (char *)hostname, hostnamelen, - &written); - if((code != CURLE_OK) || (written != hostnamelen)) { - failf(data, "Failed to send SOCKS4 connect request."); - return CURLE_COULDNT_CONNECT; - } - } - - packetsize = 8; /* receive data size */ - - /* Receive response */ - result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize, - &actualread, timeout); - if((result != CURLE_OK) || (actualread != packetsize)) { - failf(data, "Failed to receive SOCKS4 connect request ack."); - return CURLE_COULDNT_CONNECT; - } - - /* - * Response format - * - * +----+----+----+----+----+----+----+----+ - * | VN | CD | DSTPORT | DSTIP | - * +----+----+----+----+----+----+----+----+ - * # of bytes: 1 1 2 4 - * - * VN is the version of the reply code and should be 0. CD is the result - * code with one of the following values: - * - * 90: request granted - * 91: request rejected or failed - * 92: request rejected because SOCKS server cannot connect to - * identd on the client - * 93: request rejected because the client program and identd - * report different user-ids - */ - - /* wrong version ? */ - if(socksreq[0] != 0) { - failf(data, - "SOCKS4 reply has wrong version, version should be 4."); - return CURLE_COULDNT_CONNECT; - } - - /* Result */ - switch(socksreq[1]) - { - case 90: - if (protocol4a) - infof(data, "SOCKS4a request granted.\n"); - else - infof(data, "SOCKS4 request granted.\n"); - break; - case 91: - failf(data, - "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" - ", request rejected or failed.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], - (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])), - socksreq[1]); - return CURLE_COULDNT_CONNECT; - case 92: - failf(data, - "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" - ", request rejected because SOCKS server cannot connect to " - "identd on the client.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], - (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])), - socksreq[1]); - return CURLE_COULDNT_CONNECT; - case 93: - failf(data, - "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" - ", request rejected because the client program and identd " - "report different user-ids.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], - (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])), - socksreq[1]); - return CURLE_COULDNT_CONNECT; - default: - failf(data, - "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)" - ", Unknown.", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], - (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])), - socksreq[1]); - return CURLE_COULDNT_CONNECT; - } - } - - curlx_nonblock(sock, TRUE); - - return CURLE_OK; /* Proxy was successful! */ -} - -/* - * This function logs in to a SOCKS5 proxy and sends the specifics to the final - * destination server. - */ -CURLcode Curl_SOCKS5(const char *proxy_name, - const char *proxy_password, - const char *hostname, - int remote_port, - int sockindex, - struct connectdata *conn) -{ - /* - According to the RFC1928, section "6. Replies". This is what a SOCK5 - replies: - - +----+-----+-------+------+----------+----------+ - |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | - +----+-----+-------+------+----------+----------+ - | 1 | 1 | X'00' | 1 | Variable | 2 | - +----+-----+-------+------+----------+----------+ - - Where: - - o VER protocol version: X'05' - o REP Reply field: - o X'00' succeeded - */ - - unsigned char socksreq[600]; /* room for large user/pw (255 max each) */ - ssize_t actualread; - ssize_t written; - int result; - CURLcode code; - curl_socket_t sock = conn->sock[sockindex]; - struct SessionHandle *data = conn->data; - long timeout; - bool socks5_resolve_local = (bool)(data->set.proxytype == CURLPROXY_SOCKS5); - const size_t hostname_len = strlen(hostname); - ssize_t packetsize = 0; - - /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ - if(!socks5_resolve_local && hostname_len > 255) - { - infof(conn->data,"SOCKS5: server resolving disabled for hostnames of " - "length > 255 [actual len=%zu]\n", hostname_len); - socks5_resolve_local = TRUE; - } - - /* get timeout */ - timeout = Curl_timeleft(data, NULL, TRUE); - - if(timeout < 0) { - /* time-out, bail out, go home */ - failf(data, "Connection time-out"); - return CURLE_OPERATION_TIMEDOUT; - } - - curlx_nonblock(sock, TRUE); - - /* wait until socket gets connected */ - result = Curl_socket_ready(CURL_SOCKET_BAD, sock, (int)timeout); - - if(-1 == result) { - failf(conn->data, "SOCKS5: no connection here"); - return CURLE_COULDNT_CONNECT; - } - else if(0 == result) { - failf(conn->data, "SOCKS5: connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - if(result & CURL_CSELECT_ERR) { - failf(conn->data, "SOCKS5: error occurred during connection"); - return CURLE_COULDNT_CONNECT; - } - - socksreq[0] = 5; /* version */ -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - socksreq[1] = (char)(proxy_name ? 3 : 2); /* number of methods (below) */ - socksreq[2] = 0; /* no authentication */ - socksreq[3] = 1; /* gssapi */ - socksreq[4] = 2; /* username/password */ -#else - socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */ - socksreq[2] = 0; /* no authentication */ - socksreq[3] = 2; /* username/password */ -#endif - - curlx_nonblock(sock, FALSE); - - code = Curl_write_plain(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]), - &written); - if((code != CURLE_OK) || (written != (2 + (int)socksreq[1]))) { - failf(data, "Unable to send initial SOCKS5 request."); - return CURLE_COULDNT_CONNECT; - } - - curlx_nonblock(sock, TRUE); - - result = Curl_socket_ready(sock, CURL_SOCKET_BAD, (int)timeout); - - if(-1 == result) { - failf(conn->data, "SOCKS5 nothing to read"); - return CURLE_COULDNT_CONNECT; - } - else if(0 == result) { - failf(conn->data, "SOCKS5 read timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - if(result & CURL_CSELECT_ERR) { - failf(conn->data, "SOCKS5 read error occurred"); - return CURLE_RECV_ERROR; - } - - curlx_nonblock(sock, FALSE); - - result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread, - timeout); - if((result != CURLE_OK) || (actualread != 2)) { - failf(data, "Unable to receive initial SOCKS5 response."); - return CURLE_COULDNT_CONNECT; - } - - if(socksreq[0] != 5) { - failf(data, "Received invalid version in initial SOCKS5 response."); - return CURLE_COULDNT_CONNECT; - } - if(socksreq[1] == 0) { - /* Nothing to do, no authentication needed */ - ; - } -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - else if(socksreq[1] == 1) { - code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn); - if(code != CURLE_OK) { - failf(data, "Unable to negotiate SOCKS5 gssapi context."); - return CURLE_COULDNT_CONNECT; - } - } -#endif - else if(socksreq[1] == 2) { - /* Needs user name and password */ - size_t userlen, pwlen; - int len; - if(proxy_name && proxy_password) { - userlen = strlen(proxy_name); - pwlen = strlen(proxy_password); - } - else { - userlen = 0; - pwlen = 0; - } - - /* username/password request looks like - * +----+------+----------+------+----------+ - * |VER | ULEN | UNAME | PLEN | PASSWD | - * +----+------+----------+------+----------+ - * | 1 | 1 | 1 to 255 | 1 | 1 to 255 | - * +----+------+----------+------+----------+ - */ - len = 0; - socksreq[len++] = 1; /* username/pw subnegotiation version */ - socksreq[len++] = (unsigned char) userlen; - if(proxy_name && userlen) - memcpy(socksreq + len, proxy_name, userlen); - len += (int)userlen; - socksreq[len++] = (unsigned char) pwlen; - if(proxy_password && pwlen) - memcpy(socksreq + len, proxy_password, pwlen); - len += (int)pwlen; - - code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written); - if((code != CURLE_OK) || (len != written)) { - failf(data, "Failed to send SOCKS5 sub-negotiation request."); - return CURLE_COULDNT_CONNECT; - } - - result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread, - timeout); - if((result != CURLE_OK) || (actualread != 2)) { - failf(data, "Unable to receive SOCKS5 sub-negotiation response."); - return CURLE_COULDNT_CONNECT; - } - - /* ignore the first (VER) byte */ - if(socksreq[1] != 0) { /* status */ - failf(data, "User was rejected by the SOCKS5 server (%d %d).", - socksreq[0], socksreq[1]); - return CURLE_COULDNT_CONNECT; - } - - /* Everything is good so far, user was authenticated! */ - } - else { - /* error */ -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - if(socksreq[1] == 255) { -#else - if(socksreq[1] == 1) { - failf(data, - "SOCKS5 GSSAPI per-message authentication is not supported."); - return CURLE_COULDNT_CONNECT; - } - else if(socksreq[1] == 255) { -#endif - if(!proxy_name || !*proxy_name) { - failf(data, - "No authentication method was acceptable. (It is quite likely" - " that the SOCKS5 server wanted a username/password, since none" - " was supplied to the server on this connection.)"); - } - else { - failf(data, "No authentication method was acceptable."); - } - return CURLE_COULDNT_CONNECT; - } - else { - failf(data, - "Undocumented SOCKS5 mode attempted to be used by server."); - return CURLE_COULDNT_CONNECT; - } - } - - /* Authentication is complete, now specify destination to the proxy */ - socksreq[0] = 5; /* version (SOCKS5) */ - socksreq[1] = 1; /* connect */ - socksreq[2] = 0; /* must be zero */ - - if(!socks5_resolve_local) { - packetsize = (ssize_t)(5 + hostname_len + 2); - - socksreq[3] = 3; /* ATYP: domain name = 3 */ - socksreq[4] = (char) hostname_len; /* address length */ - memcpy(&socksreq[5], hostname, hostname_len); /* address bytes w/o NULL */ - - *((unsigned short*)&socksreq[hostname_len+5]) = - htons((unsigned short)remote_port); - } - else { - struct Curl_dns_entry *dns; - Curl_addrinfo *hp=NULL; - int rc = Curl_resolv(conn, hostname, remote_port, &dns); - - packetsize = 10; - - socksreq[3] = 1; /* IPv4 = 1 */ - - if(rc == CURLRESOLV_ERROR) - return CURLE_COULDNT_RESOLVE_HOST; - - if(rc == CURLRESOLV_PENDING) { - /* this requires that we're in "wait for resolve" state */ - code = Curl_wait_for_resolv(conn, &dns); - if(code != CURLE_OK) - return code; - } - - /* - * We cannot use 'hostent' as a struct that Curl_resolv() returns. It - * returns a Curl_addrinfo pointer that may not always look the same. - */ - if(dns) - hp=dns->addr; - if(hp) { - char buf[64]; - unsigned short ip[4]; - Curl_printable_address(hp, buf, sizeof(buf)); - - if(4 == sscanf( buf, "%hu.%hu.%hu.%hu", - &ip[0], &ip[1], &ip[2], &ip[3])) { - socksreq[4] = (unsigned char)ip[0]; - socksreq[5] = (unsigned char)ip[1]; - socksreq[6] = (unsigned char)ip[2]; - socksreq[7] = (unsigned char)ip[3]; - } - else - hp = NULL; /* fail! */ - - Curl_resolv_unlock(data, dns); /* not used anymore from now on */ - } - if(!hp) { - failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", - hostname); - return CURLE_COULDNT_RESOLVE_HOST; - } - - *((unsigned short*)&socksreq[8]) = htons((unsigned short)remote_port); - } - -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - if(conn->socks5_gssapi_enctype) { - failf(data, "SOCKS5 gssapi protection not yet implemented."); - } else -#endif - code = Curl_write_plain(conn, sock, (char *)socksreq, packetsize, &written); - if((code != CURLE_OK) || (written != packetsize)) { - failf(data, "Failed to send SOCKS5 connect request."); - return CURLE_COULDNT_CONNECT; - } - - packetsize = 10; /* minimum packet size is 10 */ - -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - if(conn->socks5_gssapi_enctype) { - failf(data, "SOCKS5 gssapi protection not yet implemented."); - } else -#endif - result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize, - &actualread, timeout); - if((result != CURLE_OK) || (actualread != packetsize)) { - failf(data, "Failed to receive SOCKS5 connect request ack."); - return CURLE_COULDNT_CONNECT; - } - - if(socksreq[0] != 5) { /* version */ - failf(data, - "SOCKS5 reply has wrong version, version should be 5."); - return CURLE_COULDNT_CONNECT; - } - if(socksreq[1] != 0) { /* Anything besides 0 is an error */ - failf(data, - "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)", - (unsigned char)socksreq[4], (unsigned char)socksreq[5], - (unsigned char)socksreq[6], (unsigned char)socksreq[7], - (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])), - socksreq[1]); - return CURLE_COULDNT_CONNECT; - } - - /* Fix: in general, returned BND.ADDR is variable length parameter by RFC - 1928, so the reply packet should be read until the end to avoid errors at - subsequent protocol level. - - +----+-----+-------+------+----------+----------+ - |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | - +----+-----+-------+------+----------+----------+ - | 1 | 1 | X'00' | 1 | Variable | 2 | - +----+-----+-------+------+----------+----------+ - - ATYP: - o IP v4 address: X'01', BND.ADDR = 4 byte - o domain name: X'03', BND.ADDR = [ 1 byte length, string ] - o IP v6 address: X'04', BND.ADDR = 16 byte - */ - - /* Calculate real packet size */ - if(socksreq[3] == 3) { - /* domain name */ - int addrlen = (int) socksreq[4]; - packetsize = 5 + addrlen + 2; - } - else if(socksreq[3] == 4) { - /* IPv6 */ - packetsize = 4 + 16 + 2; - } - - /* At this point we already read first 10 bytes */ -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - if(!conn->socks5_gssapi_enctype) { - /* decrypt_gssapi_blockread already read the whole packet */ -#endif - if(packetsize > 10) { - packetsize -= 10; - result = Curl_blockread_all(conn, sock, (char *)&socksreq[10], - packetsize, &actualread, timeout); - if((result != CURLE_OK) || (actualread != packetsize)) { - failf(data, "Failed to receive SOCKS5 connect request ack."); - return CURLE_COULDNT_CONNECT; - } - } -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - } -#endif - - curlx_nonblock(sock, TRUE); - return CURLE_OK; /* Proxy was successful! */ -} - -#endif /* CURL_DISABLE_PROXY */ diff --git a/third_party/curl/lib/socks.h b/third_party/curl/lib/socks.h deleted file mode 100644 index 42b8080b0..000000000 --- a/third_party/curl/lib/socks.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef __CURL_SOCKS_H -#define __CURL_SOCKS_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef CURL_DISABLE_PROXY -#define Curl_SOCKS4(a,b,c,d,e,f) CURLE_NOT_BUILT_IN -#define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN -#else -/* - * Helper read-from-socket functions. Does the same as Curl_read() but it - * blocks until all bytes amount of buffersize will be read. No more, no less. - * - * This is STUPID BLOCKING behaviour which we frown upon, but right now this - * is what we have... - */ -int Curl_blockread_all(struct connectdata *conn, - curl_socket_t sockfd, - char *buf, - ssize_t buffersize, - ssize_t *n, - long conn_timeout); - -/* - * This function logs in to a SOCKS4(a) proxy and sends the specifics to the - * final destination server. - */ -CURLcode Curl_SOCKS4(const char *proxy_name, - const char *hostname, - int remote_port, - int sockindex, - struct connectdata *conn, - bool protocol4a); - -/* - * This function logs in to a SOCKS5 proxy and sends the specifics to the - * final destination server. - */ -CURLcode Curl_SOCKS5(const char *proxy_name, - const char *proxy_password, - const char *hostname, - int remote_port, - int sockindex, - struct connectdata *conn); - -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) -/* - * This function handles the sockss5 gssapie negotiation and initialisation - */ -CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, - struct connectdata *conn); -#endif - -#endif /* CURL_DISABLE_PROXY */ - -#endif /* __CURL_SOCKS_H */ diff --git a/third_party/curl/lib/socks_gssapi.c b/third_party/curl/lib/socks_gssapi.c deleted file mode 100644 index b509c7132..000000000 --- a/third_party/curl/lib/socks_gssapi.c +++ /dev/null @@ -1,546 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2009, 2011, Markus Moeller, - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef CURL_DISABLE_PROXY - -#ifdef HAVE_GSSAPI -#ifdef HAVE_OLD_GSSMIT -#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name -#endif -#ifndef gss_nt_service_name -#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE -#endif -#include - -#ifdef HAVE_STDLIB_H -#include -#endif - -#include "urldata.h" -#include "sendf.h" -#include "connect.h" -#include "timeval.h" -#include "socks.h" - -static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* - * Helper gssapi error functions. - */ -static int check_gss_err(struct SessionHandle *data, - OM_uint32 major_status, - OM_uint32 minor_status, - const char* function) -{ - if(GSS_ERROR(major_status)) { - OM_uint32 maj_stat,min_stat; - OM_uint32 msg_ctx = 0; - gss_buffer_desc status_string; - char buf[1024]; - size_t len; - - len = 0; - msg_ctx = 0; - while(!msg_ctx) { - /* convert major status code (GSS-API error) to text */ - maj_stat = gss_display_status(&min_stat, major_status, - GSS_C_GSS_CODE, - GSS_C_NULL_OID, - &msg_ctx, &status_string); - if(maj_stat == GSS_S_COMPLETE) { - if(sizeof(buf) > len + status_string.length + 1) { - strcpy(buf+len, (char*) status_string.value); - len += status_string.length; - } - gss_release_buffer(&min_stat, &status_string); - break; - } - gss_release_buffer(&min_stat, &status_string); - } - if(sizeof(buf) > len + 3) { - strcpy(buf+len, ".\n"); - len += 2; - } - msg_ctx = 0; - while(!msg_ctx) { - /* convert minor status code (underlying routine error) to text */ - maj_stat = gss_display_status(&min_stat, minor_status, - GSS_C_MECH_CODE, - GSS_C_NULL_OID, - &msg_ctx, &status_string); - if(maj_stat == GSS_S_COMPLETE) { - if(sizeof(buf) > len + status_string.length) - strcpy(buf+len, (char*) status_string.value); - gss_release_buffer(&min_stat, &status_string); - break; - } - gss_release_buffer(&min_stat, &status_string); - } - failf(data, "GSSAPI error: %s failed:\n%s\n", function, buf); - return(1); - } - - return(0); -} - -CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, - struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - curl_socket_t sock = conn->sock[sockindex]; - CURLcode code; - ssize_t actualread; - ssize_t written; - int result; - long timeout; - OM_uint32 gss_major_status, gss_minor_status, gss_status; - OM_uint32 gss_ret_flags; - int gss_conf_state, gss_enc; - gss_buffer_desc service = GSS_C_EMPTY_BUFFER; - gss_buffer_desc gss_send_token = GSS_C_EMPTY_BUFFER; - gss_buffer_desc gss_recv_token = GSS_C_EMPTY_BUFFER; - gss_buffer_desc gss_w_token = GSS_C_EMPTY_BUFFER; - gss_buffer_desc* gss_token = GSS_C_NO_BUFFER; - gss_name_t server = GSS_C_NO_NAME; - gss_name_t gss_client_name = GSS_C_NO_NAME; - unsigned short us_length; - char *user=NULL; - unsigned char socksreq[4]; /* room for gssapi exchange header only */ - char *serviceptr = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE]; - - /* get timeout */ - timeout = Curl_timeleft(data, NULL, TRUE); - - /* GSSAPI request looks like - * +----+------+-----+----------------+ - * |VER | MTYP | LEN | TOKEN | - * +----+------+----------------------+ - * | 1 | 1 | 2 | up to 2^16 - 1 | - * +----+------+-----+----------------+ - */ - - /* prepare service name */ - if (strchr(serviceptr,'/')) { - service.value = malloc(strlen(serviceptr)); - if(!service.value) - return CURLE_OUT_OF_MEMORY; - service.length = strlen(serviceptr); - memcpy(service.value, serviceptr, service.length); - - gss_major_status = gss_import_name(&gss_minor_status, &service, - (gss_OID) GSS_C_NULL_OID, &server); - } - else { - service.value = malloc(strlen(serviceptr) +strlen(conn->proxy.name)+2); - if(!service.value) - return CURLE_OUT_OF_MEMORY; - service.length = strlen(serviceptr) +strlen(conn->proxy.name)+1; - snprintf(service.value, service.length+1, "%s@%s", - serviceptr, conn->proxy.name); - - gss_major_status = gss_import_name(&gss_minor_status, &service, - gss_nt_service_name, &server); - } - - gss_release_buffer(&gss_status, &service); /* clear allocated memory */ - - if(check_gss_err(data,gss_major_status, - gss_minor_status,"gss_import_name()")) { - failf(data, "Failed to create service name."); - gss_release_name(&gss_status, &server); - return CURLE_COULDNT_CONNECT; - } - - /* As long as we need to keep sending some context info, and there's no */ - /* errors, keep sending it... */ - for(;;) { - gss_major_status = gss_init_sec_context(&gss_minor_status, - GSS_C_NO_CREDENTIAL, - &gss_context, server, - GSS_C_NULL_OID, - GSS_C_MUTUAL_FLAG | - GSS_C_REPLAY_FLAG, - 0, - NULL, - gss_token, - NULL, - &gss_send_token, - &gss_ret_flags, - NULL); - - if(gss_token != GSS_C_NO_BUFFER) - gss_release_buffer(&gss_status, &gss_recv_token); - if(check_gss_err(data,gss_major_status, - gss_minor_status,"gss_init_sec_context")) { - gss_release_name(&gss_status, &server); - gss_release_buffer(&gss_status, &gss_recv_token); - gss_release_buffer(&gss_status, &gss_send_token); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - failf(data, "Failed to initial GSSAPI token."); - return CURLE_COULDNT_CONNECT; - } - - if(gss_send_token.length != 0) { - socksreq[0] = 1; /* gssapi subnegotiation version */ - socksreq[1] = 1; /* authentication message type */ - us_length = htons((short)gss_send_token.length); - memcpy(socksreq+2,&us_length,sizeof(short)); - - code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); - if((code != CURLE_OK) || (4 != written)) { - failf(data, "Failed to send GSSAPI authentication request."); - gss_release_name(&gss_status, &server); - gss_release_buffer(&gss_status, &gss_recv_token); - gss_release_buffer(&gss_status, &gss_send_token); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - code = Curl_write_plain(conn, sock, (char *)gss_send_token.value, - gss_send_token.length, &written); - - if((code != CURLE_OK) || ((ssize_t)gss_send_token.length != written)) { - failf(data, "Failed to send GSSAPI authentication token."); - gss_release_name(&gss_status, &server); - gss_release_buffer(&gss_status, &gss_recv_token); - gss_release_buffer(&gss_status, &gss_send_token); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - } - - gss_release_buffer(&gss_status, &gss_send_token); - gss_release_buffer(&gss_status, &gss_recv_token); - if(gss_major_status != GSS_S_CONTINUE_NEEDED) break; - - /* analyse response */ - - /* GSSAPI response looks like - * +----+------+-----+----------------+ - * |VER | MTYP | LEN | TOKEN | - * +----+------+----------------------+ - * | 1 | 1 | 2 | up to 2^16 - 1 | - * +----+------+-----+----------------+ - */ - - result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, - &actualread, timeout); - if(result != CURLE_OK || actualread != 4) { - failf(data, "Failed to receive GSSAPI authentication response."); - gss_release_name(&gss_status, &server); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - /* ignore the first (VER) byte */ - if(socksreq[1] == 255) { /* status / message type */ - failf(data, "User was rejected by the SOCKS5 server (%d %d).", - socksreq[0], socksreq[1]); - gss_release_name(&gss_status, &server); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - if(socksreq[1] != 1) { /* status / messgae type */ - failf(data, "Invalid GSSAPI authentication response type (%d %d).", - socksreq[0], socksreq[1]); - gss_release_name(&gss_status, &server); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - memcpy(&us_length, socksreq+2, sizeof(short)); - us_length = ntohs(us_length); - - gss_recv_token.length=us_length; - gss_recv_token.value=malloc(us_length); - if(!gss_recv_token.value) { - failf(data, - "Could not allocate memory for GSSAPI authentication " - "response token."); - gss_release_name(&gss_status, &server); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_OUT_OF_MEMORY; - } - - result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, - gss_recv_token.length, - &actualread, timeout); - - if(result != CURLE_OK || actualread != us_length) { - failf(data, "Failed to receive GSSAPI authentication token."); - gss_release_name(&gss_status, &server); - gss_release_buffer(&gss_status, &gss_recv_token); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - gss_token = &gss_recv_token; - } - - gss_release_name(&gss_status, &server); - - /* Everything is good so far, user was authenticated! */ - gss_major_status = gss_inquire_context (&gss_minor_status, gss_context, - &gss_client_name, NULL, NULL, NULL, - NULL, NULL, NULL); - if(check_gss_err(data,gss_major_status, - gss_minor_status,"gss_inquire_context")) { - gss_delete_sec_context(&gss_status, &gss_context, NULL); - gss_release_name(&gss_status, &gss_client_name); - failf(data, "Failed to determine user name."); - return CURLE_COULDNT_CONNECT; - } - gss_major_status = gss_display_name(&gss_minor_status, gss_client_name, - &gss_send_token, NULL); - if(check_gss_err(data,gss_major_status, - gss_minor_status,"gss_display_name")) { - gss_delete_sec_context(&gss_status, &gss_context, NULL); - gss_release_name(&gss_status, &gss_client_name); - gss_release_buffer(&gss_status, &gss_send_token); - failf(data, "Failed to determine user name."); - return CURLE_COULDNT_CONNECT; - } - user=malloc(gss_send_token.length+1); - if(!user) { - gss_delete_sec_context(&gss_status, &gss_context, NULL); - gss_release_name(&gss_status, &gss_client_name); - gss_release_buffer(&gss_status, &gss_send_token); - return CURLE_OUT_OF_MEMORY; - } - - memcpy(user, gss_send_token.value, gss_send_token.length); - user[gss_send_token.length] = '\0'; - gss_release_name(&gss_status, &gss_client_name); - gss_release_buffer(&gss_status, &gss_send_token); - infof(data, "SOCKS5 server authencticated user %s with gssapi.\n",user); - free(user); - user=NULL; - - /* Do encryption */ - socksreq[0] = 1; /* gssapi subnegotiation version */ - socksreq[1] = 2; /* encryption message type */ - - gss_enc = 0; /* no data protection */ - /* do confidentiality protection if supported */ - if(gss_ret_flags & GSS_C_CONF_FLAG) - gss_enc = 2; - /* else do integrity protection */ - else if(gss_ret_flags & GSS_C_INTEG_FLAG) - gss_enc = 1; - - infof(data, "SOCKS5 server supports gssapi %s data protection.\n", - (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality")); - /* force for the moment to no data protection */ - gss_enc = 0; - /* - * Sending the encryption type in clear seems wrong. It should be - * protected with gss_seal()/gss_wrap(). See RFC1961 extract below - * The NEC reference implementations on which this is based is - * therefore at fault - * - * +------+------+------+.......................+ - * + ver | mtyp | len | token | - * +------+------+------+.......................+ - * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets | - * +------+------+------+.......................+ - * - * Where: - * - * - "ver" is the protocol version number, here 1 to represent the - * first version of the SOCKS/GSS-API protocol - * - * - "mtyp" is the message type, here 2 to represent a protection - * -level negotiation message - * - * - "len" is the length of the "token" field in octets - * - * - "token" is the GSS-API encapsulated protection level - * - * The token is produced by encapsulating an octet containing the - * required protection level using gss_seal()/gss_wrap() with conf_req - * set to FALSE. The token is verified using gss_unseal()/ - * gss_unwrap(). - * - */ - if(data->set.socks5_gssapi_nec) { - us_length = htons((short)1); - memcpy(socksreq+2,&us_length,sizeof(short)); - } - else { - gss_send_token.length = 1; - gss_send_token.value = malloc(1); - if(!gss_send_token.value) { - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_OUT_OF_MEMORY; - } - memcpy(gss_send_token.value, &gss_enc, 1); - - gss_major_status = gss_wrap(&gss_minor_status, gss_context, 0, - GSS_C_QOP_DEFAULT, &gss_send_token, - &gss_conf_state, &gss_w_token); - - if(check_gss_err(data,gss_major_status,gss_minor_status,"gss_wrap")) { - gss_release_buffer(&gss_status, &gss_send_token); - gss_release_buffer(&gss_status, &gss_w_token); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - failf(data, "Failed to wrap GSSAPI encryption value into token."); - return CURLE_COULDNT_CONNECT; - } - gss_release_buffer(&gss_status, &gss_send_token); - - us_length = htons((short)gss_w_token.length); - memcpy(socksreq+2,&us_length,sizeof(short)); - } - - code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); - if((code != CURLE_OK) || (4 != written)) { - failf(data, "Failed to send GSSAPI encryption request."); - gss_release_buffer(&gss_status, &gss_w_token); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - if(data->set.socks5_gssapi_nec) { - memcpy(socksreq, &gss_enc, 1); - code = Curl_write_plain(conn, sock, socksreq, 1, &written); - if((code != CURLE_OK) || ( 1 != written)) { - failf(data, "Failed to send GSSAPI encryption type."); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - } else { - code = Curl_write_plain(conn, sock, (char *)gss_w_token.value, - gss_w_token.length, &written); - if((code != CURLE_OK) || ((ssize_t)gss_w_token.length != written)) { - failf(data, "Failed to send GSSAPI encryption type."); - gss_release_buffer(&gss_status, &gss_w_token); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - gss_release_buffer(&gss_status, &gss_w_token); - } - - result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, - &actualread, timeout); - if(result != CURLE_OK || actualread != 4) { - failf(data, "Failed to receive GSSAPI encryption response."); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - /* ignore the first (VER) byte */ - if(socksreq[1] == 255) { /* status / message type */ - failf(data, "User was rejected by the SOCKS5 server (%d %d).", - socksreq[0], socksreq[1]); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - if(socksreq[1] != 2) { /* status / messgae type */ - failf(data, "Invalid GSSAPI encryption response type (%d %d).", - socksreq[0], socksreq[1]); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - memcpy(&us_length, socksreq+2, sizeof(short)); - us_length = ntohs(us_length); - - gss_recv_token.length= us_length; - gss_recv_token.value=malloc(gss_recv_token.length); - if(!gss_recv_token.value) { - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_OUT_OF_MEMORY; - } - result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value, - gss_recv_token.length, - &actualread, timeout); - - if(result != CURLE_OK || actualread != us_length) { - failf(data, "Failed to receive GSSAPI encryptrion type."); - gss_release_buffer(&gss_status, &gss_recv_token); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - if(!data->set.socks5_gssapi_nec) { - gss_major_status = gss_unwrap(&gss_minor_status, gss_context, - &gss_recv_token, &gss_w_token, - 0, GSS_C_QOP_DEFAULT); - - if(check_gss_err(data,gss_major_status,gss_minor_status,"gss_unwrap")) { - gss_release_buffer(&gss_status, &gss_recv_token); - gss_release_buffer(&gss_status, &gss_w_token); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - failf(data, "Failed to unwrap GSSAPI encryption value into token."); - return CURLE_COULDNT_CONNECT; - } - gss_release_buffer(&gss_status, &gss_recv_token); - - if(gss_w_token.length != 1) { - failf(data, "Invalid GSSAPI encryption response length (%d).", - gss_w_token.length); - gss_release_buffer(&gss_status, &gss_w_token); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - memcpy(socksreq,gss_w_token.value,gss_w_token.length); - gss_release_buffer(&gss_status, &gss_w_token); - } - else { - if(gss_recv_token.length != 1) { - failf(data, "Invalid GSSAPI encryption response length (%d).", - gss_recv_token.length); - gss_release_buffer(&gss_status, &gss_recv_token); - gss_delete_sec_context(&gss_status, &gss_context, NULL); - return CURLE_COULDNT_CONNECT; - } - - memcpy(socksreq,gss_recv_token.value,gss_recv_token.length); - gss_release_buffer(&gss_status, &gss_recv_token); - } - - infof(data, "SOCKS5 access with%s protection granted.\n", - (socksreq[0]==0)?"out gssapi data": - ((socksreq[0]==1)?" gssapi integrity":" gssapi confidentiality")); - - conn->socks5_gssapi_enctype = socksreq[0]; - if(socksreq[0] == 0) - gss_delete_sec_context(&gss_status, &gss_context, NULL); - - return CURLE_OK; -} -#endif - -#endif /* CURL_DISABLE_PROXY */ diff --git a/third_party/curl/lib/socks_sspi.c b/third_party/curl/lib/socks_sspi.c deleted file mode 100644 index aaaed5e95..000000000 --- a/third_party/curl/lib/socks_sspi.c +++ /dev/null @@ -1,696 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2009, 2011, Markus Moeller, - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef USE_WINDOWS_SSPI - -#include - -#ifdef HAVE_STDLIB_H -#include -#endif - -#include "urldata.h" -#include "sendf.h" -#include "connect.h" -#include "timeval.h" -#include "socks.h" -#include "curl_sspi.h" - -#define _MPRINTF_REPLACE /* use the internal *printf() functions */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* - * Definitions required from ntsecapi.h are directly provided below this point - * to avoid including ntsecapi.h due to a conflict with OpenSSL's safestack.h - */ -#define KERB_WRAP_NO_ENCRYPT 0x80000001 - -/* - * Helper sspi error functions. - */ -static int check_sspi_err(struct SessionHandle *data, - SECURITY_STATUS major_status, - SECURITY_STATUS minor_status, - const char* function) -{ - const char *txt; - (void)minor_status; - - if(major_status != SEC_E_OK && - major_status != SEC_I_COMPLETE_AND_CONTINUE && - major_status != SEC_I_COMPLETE_NEEDED && - major_status != SEC_I_CONTINUE_NEEDED) { - failf(data, "SSPI error: %s failed: %d\n", function, major_status); - switch (major_status) { - case SEC_I_COMPLETE_AND_CONTINUE: - txt="SEC_I_COMPLETE_AND_CONTINUE"; - break; - case SEC_I_COMPLETE_NEEDED: - txt="SEC_I_COMPLETE_NEEDED"; - break; - case SEC_I_CONTINUE_NEEDED: - txt="SEC_I_CONTINUE_NEEDED"; - break; - case SEC_I_CONTEXT_EXPIRED: - txt="SEC_I_CONTEXT_EXPIRED"; - break; - case SEC_I_INCOMPLETE_CREDENTIALS: - txt="SEC_I_INCOMPLETE_CREDENTIALS"; - break; - case SEC_I_RENEGOTIATE: - txt="SEC_I_RENEGOTIATE"; - break; - case SEC_E_BUFFER_TOO_SMALL: - txt="SEC_E_BUFFER_TOO_SMALL"; - break; - case SEC_E_CONTEXT_EXPIRED: - txt="SEC_E_CONTEXT_EXPIRED"; - break; - case SEC_E_CRYPTO_SYSTEM_INVALID: - txt="SEC_E_CRYPTO_SYSTEM_INVALID"; - break; - case SEC_E_INCOMPLETE_MESSAGE: - txt="SEC_E_INCOMPLETE_MESSAGE"; - break; - case SEC_E_INSUFFICIENT_MEMORY: - txt="SEC_E_INSUFFICIENT_MEMORY"; - break; - case SEC_E_INTERNAL_ERROR: - txt="SEC_E_INTERNAL_ERROR"; - break; - case SEC_E_INVALID_HANDLE: - txt="SEC_E_INVALID_HANDLE"; - break; - case SEC_E_INVALID_TOKEN: - txt="SEC_E_INVALID_TOKEN"; - break; - case SEC_E_LOGON_DENIED: - txt="SEC_E_LOGON_DENIED"; - break; - case SEC_E_MESSAGE_ALTERED: - txt="SEC_E_MESSAGE_ALTERED"; - break; - case SEC_E_NO_AUTHENTICATING_AUTHORITY: - txt="SEC_E_NO_AUTHENTICATING_AUTHORITY"; - break; - case SEC_E_NO_CREDENTIALS: - txt="SEC_E_NO_CREDENTIALS"; - break; - case SEC_E_NOT_OWNER: - txt="SEC_E_NOT_OWNER"; - break; - case SEC_E_OUT_OF_SEQUENCE: - txt="SEC_E_OUT_OF_SEQUENCE"; - break; - case SEC_E_QOP_NOT_SUPPORTED: - txt="SEC_E_QOP_NOT_SUPPORTED"; - break; - case SEC_E_SECPKG_NOT_FOUND: - txt="SEC_E_SECPKG_NOT_FOUND"; - break; - case SEC_E_TARGET_UNKNOWN: - txt="SEC_E_TARGET_UNKNOWN"; - break; - case SEC_E_UNKNOWN_CREDENTIALS: - txt="SEC_E_UNKNOWN_CREDENTIALS"; - break; - case SEC_E_UNSUPPORTED_FUNCTION: - txt="SEC_E_UNSUPPORTED_FUNCTION"; - break; - case SEC_E_WRONG_PRINCIPAL: - txt="SEC_E_WRONG_PRINCIPAL"; - break; - default: - txt="Unknown error"; - - } - failf(data, "SSPI error: %s failed: %s\n", function, txt); - return 1; - } - return 0; -} - -/* This is the SSPI-using version of this function */ -CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, - struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - curl_socket_t sock = conn->sock[sockindex]; - CURLcode code; - ssize_t actualread; - ssize_t written; - int result; - long timeout; - /* Needs GSSAPI authentication */ - SECURITY_STATUS sspi_major_status, sspi_minor_status=0; - unsigned long sspi_ret_flags=0; - int gss_enc; - SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3]; - SecBufferDesc input_desc, output_desc, wrap_desc; - SecPkgContext_Sizes sspi_sizes; - CredHandle cred_handle; - CtxtHandle sspi_context; - PCtxtHandle context_handle = NULL; - SecPkgCredentials_Names names; - TimeStamp expiry; - char *service_name=NULL; - unsigned short us_length; - ULONG qop; - unsigned char socksreq[4]; /* room for gssapi exchange header only */ - char *service = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE]; - - /* get timeout */ - timeout = Curl_timeleft(data, NULL, TRUE); - - /* GSSAPI request looks like - * +----+------+-----+----------------+ - * |VER | MTYP | LEN | TOKEN | - * +----+------+----------------------+ - * | 1 | 1 | 2 | up to 2^16 - 1 | - * +----+------+-----+----------------+ - */ - - /* prepare service name */ - if (strchr(service, '/')) { - service_name = malloc(strlen(service)); - if(!service_name) - return CURLE_OUT_OF_MEMORY; - memcpy(service_name, service, strlen(service)); - } - else { - service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2); - if(!service_name) - return CURLE_OUT_OF_MEMORY; - snprintf(service_name,strlen(service) +strlen(conn->proxy.name)+2,"%s/%s", - service,conn->proxy.name); - } - - input_desc.cBuffers = 1; - input_desc.pBuffers = &sspi_recv_token; - input_desc.ulVersion = SECBUFFER_VERSION; - - sspi_recv_token.BufferType = SECBUFFER_TOKEN; - sspi_recv_token.cbBuffer = 0; - sspi_recv_token.pvBuffer = NULL; - - output_desc.cBuffers = 1; - output_desc.pBuffers = &sspi_send_token; - output_desc.ulVersion = SECBUFFER_VERSION; - - sspi_send_token.BufferType = SECBUFFER_TOKEN; - sspi_send_token.cbBuffer = 0; - sspi_send_token.pvBuffer = NULL; - - wrap_desc.cBuffers = 3; - wrap_desc.pBuffers = sspi_w_token; - wrap_desc.ulVersion = SECBUFFER_VERSION; - - cred_handle.dwLower = 0; - cred_handle.dwUpper = 0; - - sspi_major_status = s_pSecFn->AcquireCredentialsHandleA( NULL, - (char *)"Kerberos", - SECPKG_CRED_OUTBOUND, - NULL, - NULL, - NULL, - NULL, - &cred_handle, - &expiry); - - if(check_sspi_err(data, sspi_major_status,sspi_minor_status, - "AcquireCredentialsHandleA") ) { - failf(data, "Failed to acquire credentials."); - free(service_name); - service_name=NULL; - s_pSecFn->FreeCredentialsHandle(&cred_handle); - return CURLE_COULDNT_CONNECT; - } - - /* As long as we need to keep sending some context info, and there's no */ - /* errors, keep sending it... */ - for(;;) { - - sspi_major_status = s_pSecFn->InitializeSecurityContextA( - &cred_handle, - context_handle, - service_name, - ISC_REQ_MUTUAL_AUTH | - ISC_REQ_ALLOCATE_MEMORY | - ISC_REQ_CONFIDENTIALITY | - ISC_REQ_REPLAY_DETECT, - 0, - SECURITY_NATIVE_DREP, - &input_desc, - 0, - &sspi_context, - &output_desc, - &sspi_ret_flags, - &expiry); - - if(sspi_recv_token.pvBuffer) { - s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); - sspi_recv_token.pvBuffer = NULL; - sspi_recv_token.cbBuffer = 0; - } - - if(check_sspi_err(data,sspi_major_status,sspi_minor_status, - "InitializeSecurityContextA") ){ - free(service_name); - service_name=NULL; - s_pSecFn->FreeCredentialsHandle(&cred_handle); - s_pSecFn->DeleteSecurityContext(&sspi_context); - s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); - failf(data, "Failed to initialise security context."); - return CURLE_COULDNT_CONNECT; - } - - if(sspi_send_token.cbBuffer != 0) { - socksreq[0] = 1; /* gssapi subnegotiation version */ - socksreq[1] = 1; /* authentication message type */ - us_length = htons((short)sspi_send_token.cbBuffer); - memcpy(socksreq+2, &us_length, sizeof(short)); - - code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); - if((code != CURLE_OK) || (4 != written)) { - failf(data, "Failed to send SSPI authentication request."); - free(service_name); - service_name=NULL; - s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); - s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); - s_pSecFn->FreeCredentialsHandle(&cred_handle); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, - sspi_send_token.cbBuffer, &written); - if((code != CURLE_OK) || (sspi_send_token.cbBuffer != (size_t)written)) { - failf(data, "Failed to send SSPI authentication token."); - free(service_name); - service_name=NULL; - s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); - s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); - s_pSecFn->FreeCredentialsHandle(&cred_handle); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - } - - s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); - sspi_send_token.pvBuffer = NULL; - sspi_send_token.cbBuffer = 0; - s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); - sspi_recv_token.pvBuffer = NULL; - sspi_recv_token.cbBuffer = 0; - if(sspi_major_status != SEC_I_CONTINUE_NEEDED) break; - - /* analyse response */ - - /* GSSAPI response looks like - * +----+------+-----+----------------+ - * |VER | MTYP | LEN | TOKEN | - * +----+------+----------------------+ - * | 1 | 1 | 2 | up to 2^16 - 1 | - * +----+------+-----+----------------+ - */ - - result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, - &actualread, timeout); - if(result != CURLE_OK || actualread != 4) { - failf(data, "Failed to receive SSPI authentication response."); - free(service_name); - service_name=NULL; - s_pSecFn->FreeCredentialsHandle(&cred_handle); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - /* ignore the first (VER) byte */ - if(socksreq[1] == 255) { /* status / message type */ - failf(data, "User was rejected by the SOCKS5 server (%d %d).", - socksreq[0], socksreq[1]); - free(service_name); - service_name=NULL; - s_pSecFn->FreeCredentialsHandle(&cred_handle); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - if(socksreq[1] != 1) { /* status / messgae type */ - failf(data, "Invalid SSPI authentication response type (%d %d).", - socksreq[0], socksreq[1]); - free(service_name); - service_name=NULL; - s_pSecFn->FreeCredentialsHandle(&cred_handle); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - memcpy(&us_length, socksreq+2, sizeof(short)); - us_length = ntohs(us_length); - - sspi_recv_token.cbBuffer = us_length; - sspi_recv_token.pvBuffer = malloc(us_length); - - if(!sspi_recv_token.pvBuffer) { - free(service_name); - service_name=NULL; - s_pSecFn->FreeCredentialsHandle(&cred_handle); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_OUT_OF_MEMORY; - } - result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer, - sspi_recv_token.cbBuffer, - &actualread, timeout); - - if(result != CURLE_OK || actualread != us_length) { - failf(data, "Failed to receive SSPI authentication token."); - free(service_name); - service_name=NULL; - s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); - s_pSecFn->FreeCredentialsHandle(&cred_handle); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - context_handle = &sspi_context; - } - - free(service_name); - service_name=NULL; - - /* Everything is good so far, user was authenticated! */ - sspi_major_status = s_pSecFn->QueryCredentialsAttributes( &cred_handle, - SECPKG_CRED_ATTR_NAMES, - &names); - s_pSecFn->FreeCredentialsHandle(&cred_handle); - if(check_sspi_err(data,sspi_major_status,sspi_minor_status, - "QueryCredentialAttributes") ){ - s_pSecFn->DeleteSecurityContext(&sspi_context); - s_pSecFn->FreeContextBuffer(names.sUserName); - failf(data, "Failed to determine user name."); - return CURLE_COULDNT_CONNECT; - } - infof(data, "SOCKS5 server authencticated user %s with gssapi.\n", - names.sUserName); - s_pSecFn->FreeContextBuffer(names.sUserName); - - /* Do encryption */ - socksreq[0] = 1; /* gssapi subnegotiation version */ - socksreq[1] = 2; /* encryption message type */ - - gss_enc = 0; /* no data protection */ - /* do confidentiality protection if supported */ - if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY) - gss_enc = 2; - /* else do integrity protection */ - else if(sspi_ret_flags & ISC_REQ_INTEGRITY) - gss_enc = 1; - - infof(data, "SOCKS5 server supports gssapi %s data protection.\n", - (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality") ); - /* force to no data protection, avoid encryption/decryption for now */ - gss_enc = 0; - /* - * Sending the encryption type in clear seems wrong. It should be - * protected with gss_seal()/gss_wrap(). See RFC1961 extract below - * The NEC reference implementations on which this is based is - * therefore at fault - * - * +------+------+------+.......................+ - * + ver | mtyp | len | token | - * +------+------+------+.......................+ - * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets | - * +------+------+------+.......................+ - * - * Where: - * - * - "ver" is the protocol version number, here 1 to represent the - * first version of the SOCKS/GSS-API protocol - * - * - "mtyp" is the message type, here 2 to represent a protection - * -level negotiation message - * - * - "len" is the length of the "token" field in octets - * - * - "token" is the GSS-API encapsulated protection level - * - * The token is produced by encapsulating an octet containing the - * required protection level using gss_seal()/gss_wrap() with conf_req - * set to FALSE. The token is verified using gss_unseal()/ - * gss_unwrap(). - * - */ - - if(data->set.socks5_gssapi_nec) { - us_length = htons((short)1); - memcpy(socksreq+2, &us_length, sizeof(short)); - } - else { - sspi_major_status = s_pSecFn->QueryContextAttributesA( &sspi_context, - SECPKG_ATTR_SIZES, - &sspi_sizes); - if(check_sspi_err(data,sspi_major_status,sspi_minor_status, - "QueryContextAttributesA")) { - s_pSecFn->DeleteSecurityContext(&sspi_context); - failf(data, "Failed to query security context attributes."); - return CURLE_COULDNT_CONNECT; - } - - sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer; - sspi_w_token[0].BufferType = SECBUFFER_TOKEN; - sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer); - - if(!sspi_w_token[0].pvBuffer) { - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_OUT_OF_MEMORY; - } - - sspi_w_token[1].cbBuffer = 1; - sspi_w_token[1].pvBuffer = malloc(1); - if(!sspi_w_token[1].pvBuffer){ - s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_OUT_OF_MEMORY; - } - - memcpy(sspi_w_token[1].pvBuffer,&gss_enc,1); - sspi_w_token[2].BufferType = SECBUFFER_PADDING; - sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize; - sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize); - if(!sspi_w_token[2].pvBuffer) { - s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_OUT_OF_MEMORY; - } - sspi_major_status = s_pSecFn->EncryptMessage( &sspi_context, - KERB_WRAP_NO_ENCRYPT, - &wrap_desc, - 0); - if(check_sspi_err(data,sspi_major_status,sspi_minor_status, - "EncryptMessage") ) { - s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); - s_pSecFn->DeleteSecurityContext(&sspi_context); - failf(data, "Failed to query security context attributes."); - return CURLE_COULDNT_CONNECT; - } - sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer - + sspi_w_token[1].cbBuffer - + sspi_w_token[2].cbBuffer; - sspi_send_token.pvBuffer = malloc(sspi_send_token.cbBuffer); - if(!sspi_send_token.pvBuffer) { - s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_OUT_OF_MEMORY; - } - - memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer, - sspi_w_token[0].cbBuffer); - memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer, - sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer); - memcpy((PUCHAR) sspi_send_token.pvBuffer - +sspi_w_token[0].cbBuffer - +sspi_w_token[1].cbBuffer, - sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer); - - s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); - sspi_w_token[0].pvBuffer = NULL; - sspi_w_token[0].cbBuffer = 0; - s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); - sspi_w_token[1].pvBuffer = NULL; - sspi_w_token[1].cbBuffer = 0; - s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer); - sspi_w_token[2].pvBuffer = NULL; - sspi_w_token[2].cbBuffer = 0; - - us_length = htons((short)sspi_send_token.cbBuffer); - memcpy(socksreq+2,&us_length,sizeof(short)); - } - - code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written); - if((code != CURLE_OK) || (4 != written)) { - failf(data, "Failed to send SSPI encryption request."); - s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - if(data->set.socks5_gssapi_nec) { - memcpy(socksreq,&gss_enc,1); - code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written); - if((code != CURLE_OK) || (1 != written)) { - failf(data, "Failed to send SSPI encryption type."); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - } else { - code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer, - sspi_send_token.cbBuffer, &written); - if((code != CURLE_OK) || (sspi_send_token.cbBuffer != (size_t)written)) { - failf(data, "Failed to send SSPI encryption type."); - s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); - } - - result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, - &actualread, timeout); - if(result != CURLE_OK || actualread != 4) { - failf(data, "Failed to receive SSPI encryption response."); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - /* ignore the first (VER) byte */ - if(socksreq[1] == 255) { /* status / message type */ - failf(data, "User was rejected by the SOCKS5 server (%d %d).", - socksreq[0], socksreq[1]); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - if(socksreq[1] != 2) { /* status / message type */ - failf(data, "Invalid SSPI encryption response type (%d %d).", - socksreq[0], socksreq[1]); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - memcpy(&us_length, socksreq+2, sizeof(short)); - us_length = ntohs(us_length); - - sspi_w_token[0].cbBuffer = us_length; - sspi_w_token[0].pvBuffer = malloc(us_length); - if(!sspi_w_token[0].pvBuffer) { - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_OUT_OF_MEMORY; - } - - result=Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer, - sspi_w_token[0].cbBuffer, - &actualread, timeout); - - if(result != CURLE_OK || actualread != us_length) { - failf(data, "Failed to receive SSPI encryption type."); - s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - - if(!data->set.socks5_gssapi_nec) { - wrap_desc.cBuffers = 2; - sspi_w_token[0].BufferType = SECBUFFER_STREAM; - sspi_w_token[1].BufferType = SECBUFFER_DATA; - sspi_w_token[1].cbBuffer = 0; - sspi_w_token[1].pvBuffer = NULL; - - sspi_major_status = s_pSecFn->DecryptMessage( &sspi_context, - &wrap_desc, - 0, - &qop); - - if(check_sspi_err(data,sspi_major_status,sspi_minor_status, - "DecryptMessage")) { - s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); - s_pSecFn->DeleteSecurityContext(&sspi_context); - failf(data, "Failed to query security context attributes."); - return CURLE_COULDNT_CONNECT; - } - - if(sspi_w_token[1].cbBuffer != 1) { - failf(data, "Invalid SSPI encryption response length (%d).", - sspi_w_token[1].cbBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - - memcpy(socksreq,sspi_w_token[1].pvBuffer,sspi_w_token[1].cbBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer); - } else { - if(sspi_w_token[0].cbBuffer != 1) { - failf(data, "Invalid SSPI encryption response length (%d).", - sspi_w_token[0].cbBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); - s_pSecFn->DeleteSecurityContext(&sspi_context); - return CURLE_COULDNT_CONNECT; - } - memcpy(socksreq,sspi_w_token[0].pvBuffer,sspi_w_token[0].cbBuffer); - s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer); - } - - infof(data, "SOCKS5 access with%s protection granted.\n", - (socksreq[0]==0)?"out gssapi data": - ((socksreq[0]==1)?" gssapi integrity":" gssapi confidentiality")); - - /* For later use if encryption is required - conn->socks5_gssapi_enctype = socksreq[0]; - if (socksreq[0] != 0) - conn->socks5_sspi_context = sspi_context; - else { - s_pSecFn->DeleteSecurityContext(&sspi_context); - conn->socks5_sspi_context = sspi_context; - } - */ - return CURLE_OK; -} -#endif diff --git a/third_party/curl/lib/speedcheck.c b/third_party/curl/lib/speedcheck.c deleted file mode 100644 index a43acb3f0..000000000 --- a/third_party/curl/lib/speedcheck.c +++ /dev/null @@ -1,74 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include - -#include -#include "urldata.h" -#include "sendf.h" -#include "multiif.h" -#include "speedcheck.h" - -void Curl_speedinit(struct SessionHandle *data) -{ - memset(&data->state.keeps_speed, 0, sizeof(struct timeval)); -} - -CURLcode Curl_speedcheck(struct SessionHandle *data, - struct timeval now) -{ - if((data->progress.current_speed >= 0) && - data->set.low_speed_time && - (Curl_tvlong(data->state.keeps_speed) != 0) && - (data->progress.current_speed < data->set.low_speed_limit)) { - long howlong = Curl_tvdiff(now, data->state.keeps_speed); - - /* We are now below the "low speed limit". If we are below it - for "low speed time" seconds we consider that enough reason - to abort the download. */ - - if( (howlong/1000) > data->set.low_speed_time) { - /* we have been this slow for long enough, now die */ - failf(data, - "Operation too slow. " - "Less than %ld bytes/sec transferred the last %ld seconds", - data->set.low_speed_limit, - data->set.low_speed_time); - return CURLE_OPERATION_TIMEDOUT; - } - Curl_expire(data, howlong); - } - else { - /* we keep up the required speed all right */ - data->state.keeps_speed = now; - - if(data->set.low_speed_limit) - /* if there is a low speed limit enabled, we set the expire timer to - make this connection's speed get checked again no later than when - this time is up */ - Curl_expire(data, data->set.low_speed_time*1000); - } - return CURLE_OK; -} diff --git a/third_party/curl/lib/speedcheck.h b/third_party/curl/lib/speedcheck.h deleted file mode 100644 index fc40e7d0c..000000000 --- a/third_party/curl/lib/speedcheck.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef HEADER_CURL_SPEEDCHECK_H -#define HEADER_CURL_SPEEDCHECK_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include "timeval.h" - -void Curl_speedinit(struct SessionHandle *data); -CURLcode Curl_speedcheck(struct SessionHandle *data, - struct timeval now); - -#endif /* HEADER_CURL_SPEEDCHECK_H */ diff --git a/third_party/curl/lib/splay.c b/third_party/curl/lib/splay.c deleted file mode 100644 index dcc42cf26..000000000 --- a/third_party/curl/lib/splay.c +++ /dev/null @@ -1,438 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1997 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include "splay.h" - -/* - * This macro compares two node keys i and j and returns: - * - * negative value: when i is smaller than j - * zero : when i is equal to j - * positive when : when i is larger than j - */ -#define compare(i,j) Curl_splaycomparekeys((i),(j)) - -/* - * Splay using the key i (which may or may not be in the tree.) The starting - * root is t. - */ -struct Curl_tree *Curl_splay(struct timeval i, - struct Curl_tree *t) -{ - struct Curl_tree N, *l, *r, *y; - long comp; - - if(t == NULL) - return t; - N.smaller = N.larger = NULL; - l = r = &N; - - for (;;) { - comp = compare(i, t->key); - if(comp < 0) { - if(t->smaller == NULL) - break; - if(compare(i, t->smaller->key) < 0) { - y = t->smaller; /* rotate smaller */ - t->smaller = y->larger; - y->larger = t; - t = y; - if(t->smaller == NULL) - break; - } - r->smaller = t; /* link smaller */ - r = t; - t = t->smaller; - } - else if(comp > 0) { - if(t->larger == NULL) - break; - if(compare(i, t->larger->key) > 0) { - y = t->larger; /* rotate larger */ - t->larger = y->smaller; - y->smaller = t; - t = y; - if(t->larger == NULL) - break; - } - l->larger = t; /* link larger */ - l = t; - t = t->larger; - } - else - break; - } - - l->larger = t->smaller; /* assemble */ - r->smaller = t->larger; - t->smaller = N.larger; - t->larger = N.smaller; - - return t; -} - -/* Insert key i into the tree t. Return a pointer to the resulting tree or - NULL if something went wrong. */ -struct Curl_tree *Curl_splayinsert(struct timeval i, - struct Curl_tree *t, - struct Curl_tree *node) -{ - static struct timeval KEY_NOTUSED = {-1,-1}; /* key that will *NEVER* appear */ - - if(node == NULL) - return t; - - if(t != NULL) { - t = Curl_splay(i,t); - if(compare(i, t->key)==0) { - /* There already exists a node in the tree with the very same key. Build - a linked list of nodes. We make the new 'node' struct the new master - node and make the previous node the first one in the 'same' list. */ - - node->same = t; - node->key = i; - node->smaller = t->smaller; - node->larger = t->larger; - - t->smaller = node; /* in the sub node for this same key, we use the - smaller pointer to point back to the master - node */ - - t->key = KEY_NOTUSED; /* and we set the key in the sub node to NOTUSED - to quickly identify this node as a subnode */ - - return node; /* new root node */ - } - } - - if(t == NULL) { - node->smaller = node->larger = NULL; - } - else if(compare(i, t->key) < 0) { - node->smaller = t->smaller; - node->larger = t; - t->smaller = NULL; - - } - else { - node->larger = t->larger; - node->smaller = t; - t->larger = NULL; - } - node->key = i; - - node->same = NULL; /* no identical node (yet) */ - return node; -} - -#if 0 -/* Deletes 'i' from the tree if it's there (with an exact match). Returns a - pointer to the resulting tree. - - Function not used in libcurl. -*/ -struct Curl_tree *Curl_splayremove(struct timeval i, - struct Curl_tree *t, - struct Curl_tree **removed) -{ - struct Curl_tree *x; - - *removed = NULL; /* default to no removed */ - - if(t==NULL) - return NULL; - - t = Curl_splay(i,t); - if(compare(i, t->key) == 0) { /* found it */ - - /* FIRST! Check if there is a list with identical sizes */ - if((x = t->same) != NULL) { - /* there is, pick one from the list */ - - /* 'x' is the new root node */ - - x->key = t->key; - x->larger = t->larger; - x->smaller = t->smaller; - - *removed = t; - return x; /* new root */ - } - - if(t->smaller == NULL) { - x = t->larger; - } - else { - x = Curl_splay(i, t->smaller); - x->larger = t->larger; - } - *removed = t; - - return x; - } - else - return t; /* It wasn't there */ -} -#endif - -/* Finds and deletes the best-fit node from the tree. Return a pointer to the - resulting tree. best-fit means the node with the given or lower key */ -struct Curl_tree *Curl_splaygetbest(struct timeval i, - struct Curl_tree *t, - struct Curl_tree **removed) -{ - struct Curl_tree *x; - - if(!t) { - *removed = NULL; /* none removed since there was no root */ - return NULL; - } - - t = Curl_splay(i,t); - if(compare(i, t->key) < 0) { - /* too big node, try the smaller chain */ - if(t->smaller) - t=Curl_splay(t->smaller->key, t); - else { - /* fail */ - *removed = NULL; - return t; - } - } - - if(compare(i, t->key) >= 0) { /* found it */ - /* FIRST! Check if there is a list with identical keys */ - x = t->same; - if(x) { - /* there is, pick one from the list */ - - /* 'x' is the new root node */ - - x->key = t->key; - x->larger = t->larger; - x->smaller = t->smaller; - - *removed = t; - return x; /* new root */ - } - - if(t->smaller == NULL) { - x = t->larger; - } - else { - x = Curl_splay(i, t->smaller); - x->larger = t->larger; - } - *removed = t; - - return x; - } - else { - *removed = NULL; /* no match */ - return t; /* It wasn't there */ - } -} - - -/* Deletes the very node we point out from the tree if it's there. Stores a - pointer to the new resulting tree in 'newroot'. - - Returns zero on success and non-zero on errors! TODO: document error codes. - When returning error, it does not touch the 'newroot' pointer. - - NOTE: when the last node of the tree is removed, there's no tree left so - 'newroot' will be made to point to NULL. -*/ -int Curl_splayremovebyaddr(struct Curl_tree *t, - struct Curl_tree *removenode, - struct Curl_tree **newroot) -{ - static struct timeval KEY_NOTUSED = {-1,-1}; /* key that will *NEVER* appear */ - struct Curl_tree *x; - - if(!t || !removenode) - return 1; - - if(compare(KEY_NOTUSED, removenode->key) == 0) { - /* Key set to NOTUSED means it is a subnode within a 'same' linked list - and thus we can unlink it easily. The 'smaller' link of a subnode - links to the parent node. */ - if(removenode->smaller == NULL) - return 3; - - removenode->smaller->same = removenode->same; - if(removenode->same) - removenode->same->smaller = removenode->smaller; - - /* Ensures that double-remove gets caught. */ - removenode->smaller = NULL; - - /* voila, we're done! */ - *newroot = t; /* return the same root */ - return 0; - } - - t = Curl_splay(removenode->key, t); - - /* First make sure that we got the same root node as the one we want - to remove, as otherwise we might be trying to remove a node that - isn't actually in the tree. - - We cannot just compare the keys here as a double remove in quick - succession of a node with key != KEY_NOTUSED && same != NULL - could return the same key but a different node. */ - if(t != removenode) - return 2; - - /* Check if there is a list with identical sizes, as then we're trying to - remove the root node of a list of nodes with identical keys. */ - x = t->same; - if(x) { - /* 'x' is the new root node, we just make it use the root node's - smaller/larger links */ - - x->key = t->key; - x->larger = t->larger; - x->smaller = t->smaller; - } - else { - /* Remove the root node */ - if(t->smaller == NULL) - x = t->larger; - else { - x = Curl_splay(removenode->key, t->smaller); - x->larger = t->larger; - } - } - - *newroot = x; /* store new root pointer */ - - return 0; -} - -#ifdef DEBUGBUILD - -void Curl_splayprint(struct Curl_tree * t, int d, char output) -{ - struct Curl_tree *node; - int i; - int count; - if(t == NULL) - return; - - Curl_splayprint(t->larger, d+1, output); - for (i=0; ikey.tv_usec, i); -#else - fprintf(stderr, "%ld.%ld[%d]", (long)t->key.tv_sec, (long)t->key.tv_usec, i); -#endif - } - - for(count=0, node = t->same; node; node = node->same, count++) - ; - - if(output) { - if(count) - fprintf(stderr, " [%d more]\n", count); - else - fprintf(stderr, "\n"); - } - - Curl_splayprint(t->smaller, d+1, output); -} -#endif - -#ifdef TEST_SPLAY - -/*#define TEST2 */ -#define MAX 50 -#define TEST2 - -/* A sample use of these functions. Start with the empty tree, insert some - stuff into it, and then delete it */ -int main(int argc, argv_item_t argv[]) -{ - struct Curl_tree *root, *t; - void *ptrs[MAX]; - int adds=0; - int rc; - - static const long sizes[]={ - 50, 60, 50, 100, 60, 200, 120, 300, 400, 200, 256, 122, 60, 120, 200, 300, - 220, 80, 90, 50, 100, 60, 200, 120, 300, 400, 200, 256, 122, 60, 120, 200, - 300, 220, 80, 90, 50, 100, 60, 200, 120, 300, 400, 200, 256, 122, 60, 120, - 200, 300, 220, 80, 90}; - int i; - root = NULL; /* the empty tree */ - - for (i = 0; i < MAX; i++) { - struct timeval key; - ptrs[i] = t = malloc(sizeof(struct Curl_tree)); - if(!t) { - puts("out of memory!"); - return 0; - } - - key.tv_sec = 0; -#ifdef TEST2 - key.tv_usec = sizes[i]; -#elif defined(TEST1) - key.tv_usec = (541*i)%1023; -#elif defined(TEST3) - key.tv_usec = 100; -#endif - - t->payload = (void *)key.tv_usec; /* for simplicity */ - root = Curl_splayinsert(key, root, t); - } - -#if 0 - puts("Result:"); - Curl_splayprint(root, 0, 1); -#endif - -#if 1 - for (i = 0; i < MAX; i++) { - int rem = (i+7)%MAX; - struct Curl_tree *r; - printf("Tree look:\n"); - Curl_splayprint(root, 0, 1); - printf("remove pointer %d, payload %ld\n", rem, - (long)((struct Curl_tree *)ptrs[rem])->payload); - rc = Curl_splayremovebyaddr(root, (struct Curl_tree *)ptrs[rem], &root); - if(rc) - /* failed! */ - printf("remove %d failed!\n", rem); - } -#endif - - return 0; -} - -#endif /* TEST_SPLAY */ diff --git a/third_party/curl/lib/splay.h b/third_party/curl/lib/splay.h deleted file mode 100644 index 832e4e2bb..000000000 --- a/third_party/curl/lib/splay.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef __SPLAY_H -#define __SPLAY_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1997 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -struct Curl_tree { - struct Curl_tree *smaller; /* smaller node */ - struct Curl_tree *larger; /* larger node */ - struct Curl_tree *same; /* points to a node with identical key */ - struct timeval key; /* this node's "sort" key */ - void *payload; /* data the splay code doesn't care about */ -}; - -struct Curl_tree *Curl_splay(struct timeval i, - struct Curl_tree *t); - -struct Curl_tree *Curl_splayinsert(struct timeval key, - struct Curl_tree *t, - struct Curl_tree *newnode); - -#if 0 -struct Curl_tree *Curl_splayremove(struct timeval key, - struct Curl_tree *t, - struct Curl_tree **removed); -#endif - -struct Curl_tree *Curl_splaygetbest(struct timeval key, - struct Curl_tree *t, - struct Curl_tree **removed); - -int Curl_splayremovebyaddr(struct Curl_tree *t, - struct Curl_tree *removenode, - struct Curl_tree **newroot); - -#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec) < (j.tv_sec)) ? -1 : \ - ( ((i.tv_sec) > (j.tv_sec)) ? 1 : \ - ( ((i.tv_usec) < (j.tv_usec)) ? -1 : \ - ( ((i.tv_usec) > (j.tv_usec)) ? 1 : 0 )))) - -#ifdef DEBUGBUILD -void Curl_splayprint(struct Curl_tree * t, int d, char output); -#else -#define Curl_splayprint(x,y,z) -#endif - -#endif diff --git a/third_party/curl/lib/ssh.c b/third_party/curl/lib/ssh.c deleted file mode 100644 index cc2e1d919..000000000 --- a/third_party/curl/lib/ssh.c +++ /dev/null @@ -1,3157 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* #define CURL_LIBSSH2_DEBUG */ - -#include "setup.h" - -#ifdef USE_LIBSSH2 -#include -#include -#include -#include -#include -#ifdef HAVE_LIMITS_H -# include -#endif - -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#endif - -#ifdef HAVE_TIME_H -#include -#endif - -#ifndef WIN32 -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_UTSNAME_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef __VMS -#include -#include -#endif -#endif /* !WIN32 */ - -#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) -#undef in_addr_t -#define in_addr_t unsigned long -#endif - -#include -#include "urldata.h" -#include "sendf.h" -#include "hostip.h" -#include "progress.h" -#include "transfer.h" -#include "escape.h" -#include "http.h" /* for HTTP proxy tunnel stuff */ -#include "ssh.h" -#include "url.h" -#include "speedcheck.h" -#include "getinfo.h" - -#include "strequal.h" -#include "sslgen.h" -#include "connect.h" -#include "strerror.h" -#include "inet_ntop.h" -#include "parsedate.h" /* for the week day and month names */ -#include "sockaddr.h" /* required for Curl_sockaddr_storage */ -#include "strtoofft.h" -#include "multiif.h" -#include "select.h" -#include "warnless.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -#ifndef PATH_MAX -#define PATH_MAX 1024 /* just an extra precaution since there are systems that - have their definition hidden well */ -#endif - -/* Local functions: */ -static const char *sftp_libssh2_strerror(unsigned long err); -static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc); -static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc); -static LIBSSH2_FREE_FUNC(my_libssh2_free); - -static CURLcode get_pathname(const char **cpp, char **path); - -static CURLcode ssh_connect(struct connectdata *conn, bool *done); -static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done); -static CURLcode ssh_do(struct connectdata *conn, bool *done); - -static CURLcode ssh_getworkingpath(struct connectdata *conn, - char *homedir, /* when SFTP is used */ - char **path); - -static CURLcode scp_done(struct connectdata *conn, - CURLcode, bool premature); -static CURLcode scp_doing(struct connectdata *conn, - bool *dophase_done); -static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection); - -static CURLcode sftp_done(struct connectdata *conn, - CURLcode, bool premature); -static CURLcode sftp_doing(struct connectdata *conn, - bool *dophase_done); -static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection); -static -CURLcode sftp_perform(struct connectdata *conn, - bool *connected, - bool *dophase_done); - -static int ssh_getsock(struct connectdata *conn, - curl_socket_t *sock, /* points to numsocks number - of sockets */ - int numsocks); - -static int ssh_perform_getsock(const struct connectdata *conn, - curl_socket_t *sock, /* points to numsocks - number of sockets */ - int numsocks); - -/* - * SCP protocol handler. - */ - -const struct Curl_handler Curl_handler_scp = { - "SCP", /* scheme */ - ZERO_NULL, /* setup_connection */ - ssh_do, /* do_it */ - scp_done, /* done */ - ZERO_NULL, /* do_more */ - ssh_connect, /* connect_it */ - ssh_multi_statemach, /* connecting */ - scp_doing, /* doing */ - ssh_getsock, /* proto_getsock */ - ssh_getsock, /* doing_getsock */ - ssh_perform_getsock, /* perform_getsock */ - scp_disconnect, /* disconnect */ - PORT_SSH, /* defport */ - CURLPROTO_SCP, /* protocol */ - PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION /* flags */ -}; - - -/* - * SFTP protocol handler. - */ - -const struct Curl_handler Curl_handler_sftp = { - "SFTP", /* scheme */ - ZERO_NULL, /* setup_connection */ - ssh_do, /* do_it */ - sftp_done, /* done */ - ZERO_NULL, /* do_more */ - ssh_connect, /* connect_it */ - ssh_multi_statemach, /* connecting */ - sftp_doing, /* doing */ - ssh_getsock, /* proto_getsock */ - ssh_getsock, /* doing_getsock */ - ssh_perform_getsock, /* perform_getsock */ - sftp_disconnect, /* disconnect */ - PORT_SSH, /* defport */ - CURLPROTO_SFTP, /* protocol */ - PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION /* flags */ -}; - - -static void -kbd_callback(const char *name, int name_len, const char *instruction, - int instruction_len, int num_prompts, - const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, - LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, - void **abstract) -{ - struct connectdata *conn = (struct connectdata *)*abstract; - -#ifdef CURL_LIBSSH2_DEBUG - fprintf(stderr, "name=%s\n", name); - fprintf(stderr, "name_len=%d\n", name_len); - fprintf(stderr, "instruction=%s\n", instruction); - fprintf(stderr, "instruction_len=%d\n", instruction_len); - fprintf(stderr, "num_prompts=%d\n", num_prompts); -#else - (void)name; - (void)name_len; - (void)instruction; - (void)instruction_len; -#endif /* CURL_LIBSSH2_DEBUG */ - if(num_prompts == 1) { - responses[0].text = strdup(conn->passwd); - responses[0].length = (unsigned int)strlen(conn->passwd); - } - (void)prompts; - (void)abstract; -} /* kbd_callback */ - -static CURLcode sftp_libssh2_error_to_CURLE(int err) -{ - switch (err) { - case LIBSSH2_FX_OK: - return CURLE_OK; - - case LIBSSH2_FX_NO_SUCH_FILE: - case LIBSSH2_FX_NO_SUCH_PATH: - return CURLE_REMOTE_FILE_NOT_FOUND; - - case LIBSSH2_FX_PERMISSION_DENIED: - case LIBSSH2_FX_WRITE_PROTECT: - case LIBSSH2_FX_LOCK_CONFlICT: - return CURLE_REMOTE_ACCESS_DENIED; - - case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: - case LIBSSH2_FX_QUOTA_EXCEEDED: - return CURLE_REMOTE_DISK_FULL; - - case LIBSSH2_FX_FILE_ALREADY_EXISTS: - return CURLE_REMOTE_FILE_EXISTS; - - case LIBSSH2_FX_DIR_NOT_EMPTY: - return CURLE_QUOTE_ERROR; - - default: - break; - } - - return CURLE_SSH; -} - -static CURLcode libssh2_session_error_to_CURLE(int err) -{ - switch (err) { - /* Ordered by order of appearance in libssh2.h */ - case LIBSSH2_ERROR_NONE: - return CURLE_OK; - - case LIBSSH2_ERROR_SOCKET_NONE: - return CURLE_COULDNT_CONNECT; - - case LIBSSH2_ERROR_ALLOC: - return CURLE_OUT_OF_MEMORY; - - case LIBSSH2_ERROR_SOCKET_SEND: - return CURLE_SEND_ERROR; - - case LIBSSH2_ERROR_HOSTKEY_INIT: - case LIBSSH2_ERROR_HOSTKEY_SIGN: - case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED: - case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED: - return CURLE_PEER_FAILED_VERIFICATION; - - case LIBSSH2_ERROR_PASSWORD_EXPIRED: - return CURLE_LOGIN_DENIED; - - case LIBSSH2_ERROR_SOCKET_TIMEOUT: - case LIBSSH2_ERROR_TIMEOUT: - return CURLE_OPERATION_TIMEDOUT; - - case LIBSSH2_ERROR_EAGAIN: - return CURLE_AGAIN; - } - - /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode - error code, and possibly add a few new SSH-related one. We must however - not return or even depend on libssh2 errors in the public libcurl API */ - - return CURLE_SSH; -} - -static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc) -{ - (void)abstract; /* arg not used */ - return malloc(count); -} - -static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc) -{ - (void)abstract; /* arg not used */ - return realloc(ptr, count); -} - -static LIBSSH2_FREE_FUNC(my_libssh2_free) -{ - (void)abstract; /* arg not used */ - free(ptr); -} - -/* - * SSH State machine related code - */ -/* This is the ONLY way to change SSH state! */ -static void state(struct connectdata *conn, sshstate nowstate) -{ -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - /* for debug purposes */ - static const char * const names[] = { - "SSH_STOP", - "SSH_S_STARTUP", - "SSH_HOSTKEY", - "SSH_AUTHLIST", - "SSH_AUTH_PKEY_INIT", - "SSH_AUTH_PKEY", - "SSH_AUTH_PASS_INIT", - "SSH_AUTH_PASS", - "SSH_AUTH_HOST_INIT", - "SSH_AUTH_HOST", - "SSH_AUTH_KEY_INIT", - "SSH_AUTH_KEY", - "SSH_AUTH_DONE", - "SSH_SFTP_INIT", - "SSH_SFTP_REALPATH", - "SSH_SFTP_QUOTE_INIT", - "SSH_SFTP_POSTQUOTE_INIT", - "SSH_SFTP_QUOTE", - "SSH_SFTP_NEXT_QUOTE", - "SSH_SFTP_QUOTE_STAT", - "SSH_SFTP_QUOTE_SETSTAT", - "SSH_SFTP_QUOTE_SYMLINK", - "SSH_SFTP_QUOTE_MKDIR", - "SSH_SFTP_QUOTE_RENAME", - "SSH_SFTP_QUOTE_RMDIR", - "SSH_SFTP_QUOTE_UNLINK", - "SSH_SFTP_TRANS_INIT", - "SSH_SFTP_UPLOAD_INIT", - "SSH_SFTP_CREATE_DIRS_INIT", - "SSH_SFTP_CREATE_DIRS", - "SSH_SFTP_CREATE_DIRS_MKDIR", - "SSH_SFTP_READDIR_INIT", - "SSH_SFTP_READDIR", - "SSH_SFTP_READDIR_LINK", - "SSH_SFTP_READDIR_BOTTOM", - "SSH_SFTP_READDIR_DONE", - "SSH_SFTP_DOWNLOAD_INIT", - "SSH_SFTP_DOWNLOAD_STAT", - "SSH_SFTP_CLOSE", - "SSH_SFTP_SHUTDOWN", - "SSH_SCP_TRANS_INIT", - "SSH_SCP_UPLOAD_INIT", - "SSH_SCP_DOWNLOAD_INIT", - "SSH_SCP_DONE", - "SSH_SCP_SEND_EOF", - "SSH_SCP_WAIT_EOF", - "SSH_SCP_WAIT_CLOSE", - "SSH_SCP_CHANNEL_FREE", - "SSH_SESSION_DISCONNECT", - "SSH_SESSION_FREE", - "QUIT" - }; -#endif - struct ssh_conn *sshc = &conn->proto.sshc; - -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - if(sshc->state != nowstate) { - infof(conn->data, "SFTP %p state change from %s to %s\n", - sshc, names[sshc->state], names[nowstate]); - } -#endif - - sshc->state = nowstate; -} - -/* figure out the path to work with in this particular request */ -static CURLcode ssh_getworkingpath(struct connectdata *conn, - char *homedir, /* when SFTP is used */ - char **path) /* returns the allocated - real path to work with */ -{ - struct SessionHandle *data = conn->data; - char *real_path = NULL; - char *working_path; - int working_path_len; - - working_path = curl_easy_unescape(data, data->state.path, 0, - &working_path_len); - if(!working_path) - return CURLE_OUT_OF_MEMORY; - - /* Check for /~/ , indicating relative to the user's home directory */ - if(conn->handler->protocol & CURLPROTO_SCP) { - real_path = malloc(working_path_len+1); - if(real_path == NULL) { - free(working_path); - return CURLE_OUT_OF_MEMORY; - } - if((working_path_len > 1) && (working_path[1] == '~')) - /* It is referenced to the home directory, so strip the leading '/' */ - memcpy(real_path, working_path+1, 1 + working_path_len-1); - else - memcpy(real_path, working_path, 1 + working_path_len); - } - else if(conn->handler->protocol & CURLPROTO_SFTP) { - if((working_path_len > 1) && (working_path[1] == '~')) { - size_t homelen = strlen(homedir); - real_path = malloc(homelen + working_path_len + 1); - if(real_path == NULL) { - free(working_path); - return CURLE_OUT_OF_MEMORY; - } - /* It is referenced to the home directory, so strip the - leading '/' */ - memcpy(real_path, homedir, homelen); - real_path[homelen] = '/'; - real_path[homelen+1] = '\0'; - if(working_path_len > 3) { - memcpy(real_path+homelen+1, working_path + 3, - 1 + working_path_len -3); - } - } - else { - real_path = malloc(working_path_len+1); - if(real_path == NULL) { - free(working_path); - return CURLE_OUT_OF_MEMORY; - } - memcpy(real_path, working_path, 1+working_path_len); - } - } - - free(working_path); - - /* store the pointer for the caller to receive */ - *path = real_path; - - return CURLE_OK; -} - -#ifdef HAVE_LIBSSH2_KNOWNHOST_API -static int sshkeycallback(CURL *easy, - const struct curl_khkey *knownkey, /* known */ - const struct curl_khkey *foundkey, /* found */ - enum curl_khmatch match, - void *clientp) -{ - (void)easy; - (void)knownkey; - (void)foundkey; - (void)clientp; - - /* we only allow perfect matches, and we reject everything else */ - return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE; -} -#endif - -/* - * Earlier libssh2 versions didn't have the ability to seek to 64bit positions - * with 32bit size_t. - */ -#ifdef HAVE_LIBSSH2_SFTP_SEEK64 -#define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y) -#else -#define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y) -#endif - -/* - * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit - * architectures so we check of the necessary function is present. - */ -#ifndef HAVE_LIBSSH2_SCP_SEND64 -#define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0) -#else -#define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \ - (libssh2_uint64_t)d, 0, 0) -#endif - -/* - * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64. - */ -#ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE -#define libssh2_session_startup(x,y) libssh2_session_handshake(x,y) -#endif - -/* - * ssh_statemach_act() runs the SSH state machine as far as it can without - * blocking and without reaching the end. The data the pointer 'block' points - * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN - * meaning it wants to be called again when the socket is ready - */ - -static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - struct SSHPROTO *sftp_scp = data->state.proto.ssh; - struct ssh_conn *sshc = &conn->proto.sshc; - curl_socket_t sock = conn->sock[FIRSTSOCKET]; -#ifdef CURL_LIBSSH2_DEBUG - const char *fingerprint; -#endif /* CURL_LIBSSH2_DEBUG */ - const char *host_public_key_md5; - int rc = LIBSSH2_ERROR_NONE, i; - int err; - int seekerr = CURL_SEEKFUNC_OK; - *block = 0; /* we're not blocking by default */ - - do { - - switch(sshc->state) { - case SSH_S_STARTUP: - sshc->secondCreateDirs = 0; - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_OK; - - rc = libssh2_session_startup(sshc->ssh_session, sock); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc) { - failf(data, "Failure establishing ssh session"); - state(conn, SSH_SESSION_FREE); - sshc->actualcode = CURLE_FAILED_INIT; - break; - } - - /* Set libssh2 to non-blocking, since everything internally is - non-blocking */ - libssh2_session_set_blocking(sshc->ssh_session, 0); - - state(conn, SSH_HOSTKEY); - - /* fall-through */ - case SSH_HOSTKEY: - -#ifdef CURL_LIBSSH2_DEBUG - /* - * Before we authenticate we should check the hostkey's fingerprint - * against our known hosts. How that is handled (reading from file, - * whatever) is up to us. As for know not much is implemented, besides - * showing how to get the fingerprint. - */ - fingerprint = libssh2_hostkey_hash(sshc->ssh_session, - LIBSSH2_HOSTKEY_HASH_MD5); - - /* The fingerprint points to static storage (!), don't free() it. */ - infof(data, "Fingerprint: "); - for (rc = 0; rc < 16; rc++) { - infof(data, "%02X ", (unsigned char) fingerprint[rc]); - } - infof(data, "\n"); -#endif /* CURL_LIBSSH2_DEBUG */ - - /* Before we authenticate we check the hostkey's MD5 fingerprint - * against a known fingerprint, if available. This implementation pulls - * it from the curl option. - */ - if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] && - strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) == 32) { - char buf[33]; - host_public_key_md5 = libssh2_hostkey_hash(sshc->ssh_session, - LIBSSH2_HOSTKEY_HASH_MD5); - for (i = 0; i < 16; i++) - snprintf(&buf[i*2], 3, "%02x", - (unsigned char) host_public_key_md5[i]); - if(!strequal(buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5])) { - failf(data, - "Denied establishing ssh session: mismatch md5 fingerprint. " - "Remote %s is not equal to %s", - buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]); - state(conn, SSH_SESSION_FREE); - sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; - break; - } - } - -#ifdef HAVE_LIBSSH2_KNOWNHOST_API - if(data->set.str[STRING_SSH_KNOWNHOSTS]) { - /* we're asked to verify the host against a file */ - int keytype; - size_t keylen; - const char *remotekey = libssh2_session_hostkey(sshc->ssh_session, - &keylen, &keytype); - int keycheck; - int keybit; - - if(remotekey) { - /* - * A subject to figure out is what host name we need to pass in here. - * What host name does OpenSSH store in its file if an IDN name is - * used? - */ - struct libssh2_knownhost *host; - enum curl_khmatch keymatch; - curl_sshkeycallback func = - data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback; - struct curl_khkey knownkey; - struct curl_khkey *knownkeyp = NULL; - struct curl_khkey foundkey; - - keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? - LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS; - - keycheck = libssh2_knownhost_check(sshc->kh, - conn->host.name, - remotekey, keylen, - LIBSSH2_KNOWNHOST_TYPE_PLAIN| - LIBSSH2_KNOWNHOST_KEYENC_RAW| - keybit, - &host); - - infof(data, "SSH host check: %d, key: %s\n", keycheck, - (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)? - host->key:""); - - /* setup 'knownkey' */ - if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) { - knownkey.key = host->key; - knownkey.len = 0; - knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? - CURLKHTYPE_RSA : CURLKHTYPE_DSS; - knownkeyp = &knownkey; - } - - /* setup 'foundkey' */ - foundkey.key = remotekey; - foundkey.len = keylen; - foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)? - CURLKHTYPE_RSA : CURLKHTYPE_DSS; - - /* - * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the - * curl_khmatch enum are ever modified, we need to introduce a - * translation table here! - */ - keymatch = (enum curl_khmatch)keycheck; - - /* Ask the callback how to behave */ - rc = func(data, knownkeyp, /* from the knownhosts file */ - &foundkey, /* from the remote host */ - keymatch, data->set.ssh_keyfunc_userp); - } - else - /* no remotekey means failure! */ - rc = CURLKHSTAT_REJECT; - - switch(rc) { - default: /* unknown return codes will equal reject */ - case CURLKHSTAT_REJECT: - state(conn, SSH_SESSION_FREE); - case CURLKHSTAT_DEFER: - /* DEFER means bail out but keep the SSH_HOSTKEY state */ - result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; - break; - case CURLKHSTAT_FINE: - case CURLKHSTAT_FINE_ADD_TO_FILE: - /* proceed */ - if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) { - /* the found host+key didn't match but has been told to be fine - anyway so we add it in memory */ - int addrc = libssh2_knownhost_add(sshc->kh, - conn->host.name, NULL, - remotekey, keylen, - LIBSSH2_KNOWNHOST_TYPE_PLAIN| - LIBSSH2_KNOWNHOST_KEYENC_RAW| - keybit, NULL); - if(addrc) - infof(data, "Warning adding the known host %s failed!\n", - conn->host.name); - else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) { - /* now we write the entire in-memory list of known hosts to the - known_hosts file */ - int wrc = - libssh2_knownhost_writefile(sshc->kh, - data->set.str[STRING_SSH_KNOWNHOSTS], - LIBSSH2_KNOWNHOST_FILE_OPENSSH); - if(wrc) { - infof(data, "Warning, writing %s failed!\n", - data->set.str[STRING_SSH_KNOWNHOSTS]); - } - } - } - break; - } - } -#endif /* HAVE_LIBSSH2_KNOWNHOST_API */ - - state(conn, SSH_AUTHLIST); - break; - - case SSH_AUTHLIST: - /* - * Figure out authentication methods - * NB: As soon as we have provided a username to an openssh server we - * must never change it later. Thus, always specify the correct username - * here, even though the libssh2 docs kind of indicate that it should be - * possible to get a 'generic' list (not user-specific) of authentication - * methods, presumably with a blank username. That won't work in my - * experience. - * So always specify it here. - */ - sshc->authlist = libssh2_userauth_list(sshc->ssh_session, - conn->user, - (unsigned int)strlen(conn->user)); - - if(!sshc->authlist) { - if((err = libssh2_session_last_errno(sshc->ssh_session)) == - LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; - break; - } - else { - state(conn, SSH_SESSION_FREE); - sshc->actualcode = libssh2_session_error_to_CURLE(err); - break; - } - } - infof(data, "SSH authentication methods available: %s\n", - sshc->authlist); - - state(conn, SSH_AUTH_PKEY_INIT); - break; - - case SSH_AUTH_PKEY_INIT: - /* - * Check the supported auth types in the order I feel is most secure - * with the requested type of authentication - */ - sshc->authed = FALSE; - - if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) && - (strstr(sshc->authlist, "publickey") != NULL)) { - char *home; - - sshc->rsa_pub = sshc->rsa = NULL; - - /* To ponder about: should really the lib be messing about with the - HOME environment variable etc? */ - home = curl_getenv("HOME"); - - if(data->set.str[STRING_SSH_PUBLIC_KEY]) - sshc->rsa_pub = aprintf("%s", data->set.str[STRING_SSH_PUBLIC_KEY]); - else if(home) - sshc->rsa_pub = aprintf("%s/.ssh/id_dsa.pub", home); - else - /* as a final resort, try current dir! */ - sshc->rsa_pub = strdup("id_dsa.pub"); - - if(sshc->rsa_pub == NULL) { - Curl_safefree(home); - home = NULL; - state(conn, SSH_SESSION_FREE); - sshc->actualcode = CURLE_OUT_OF_MEMORY; - break; - } - - if(data->set.str[STRING_SSH_PRIVATE_KEY]) - sshc->rsa = aprintf("%s", data->set.str[STRING_SSH_PRIVATE_KEY]); - else if(home) - sshc->rsa = aprintf("%s/.ssh/id_dsa", home); - else - /* as a final resort, try current dir! */ - sshc->rsa = strdup("id_dsa"); - - if(sshc->rsa == NULL) { - Curl_safefree(home); - home = NULL; - Curl_safefree(sshc->rsa_pub); - sshc->rsa_pub = NULL; - state(conn, SSH_SESSION_FREE); - sshc->actualcode = CURLE_OUT_OF_MEMORY; - break; - } - - sshc->passphrase = data->set.str[STRING_KEY_PASSWD]; - if(!sshc->passphrase) - sshc->passphrase = ""; - - Curl_safefree(home); - home = NULL; - - infof(data, "Using ssh public key file %s\n", sshc->rsa_pub); - infof(data, "Using ssh private key file %s\n", sshc->rsa); - - state(conn, SSH_AUTH_PKEY); - } - else { - state(conn, SSH_AUTH_PASS_INIT); - } - break; - - case SSH_AUTH_PKEY: - /* The function below checks if the files exists, no need to stat() here. - */ - rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session, - conn->user, - (unsigned int) - strlen(conn->user), - sshc->rsa_pub, - sshc->rsa, sshc->passphrase); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - - Curl_safefree(sshc->rsa_pub); - sshc->rsa_pub = NULL; - Curl_safefree(sshc->rsa); - sshc->rsa = NULL; - - if(rc == 0) { - sshc->authed = TRUE; - infof(data, "Initialized SSH public key authentication\n"); - state(conn, SSH_AUTH_DONE); - } - else { - char *err_msg; - (void)libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0); - infof(data, "SSH public key authentication failed: %s\n", err_msg); - state(conn, SSH_AUTH_PASS_INIT); - } - break; - - case SSH_AUTH_PASS_INIT: - if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) && - (strstr(sshc->authlist, "password") != NULL)) { - state(conn, SSH_AUTH_PASS); - } - else { - state(conn, SSH_AUTH_HOST_INIT); - } - break; - - case SSH_AUTH_PASS: - rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user, - (unsigned int)strlen(conn->user), - conn->passwd, - (unsigned int)strlen(conn->passwd), - NULL); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc == 0) { - sshc->authed = TRUE; - infof(data, "Initialized password authentication\n"); - state(conn, SSH_AUTH_DONE); - } - else { - state(conn, SSH_AUTH_HOST_INIT); - } - break; - - case SSH_AUTH_HOST_INIT: - if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) && - (strstr(sshc->authlist, "hostbased") != NULL)) { - state(conn, SSH_AUTH_HOST); - } - else { - state(conn, SSH_AUTH_KEY_INIT); - } - break; - - case SSH_AUTH_HOST: - state(conn, SSH_AUTH_KEY_INIT); - break; - - case SSH_AUTH_KEY_INIT: - if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) - && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) { - state(conn, SSH_AUTH_KEY); - } - else { - state(conn, SSH_AUTH_DONE); - } - break; - - case SSH_AUTH_KEY: - /* Authentication failed. Continue with keyboard-interactive now. */ - rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session, - conn->user, - (unsigned int) - strlen(conn->user), - &kbd_callback); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc == 0) { - sshc->authed = TRUE; - infof(data, "Initialized keyboard interactive authentication\n"); - } - state(conn, SSH_AUTH_DONE); - break; - - case SSH_AUTH_DONE: - if(!sshc->authed) { - failf(data, "Authentication failure"); - state(conn, SSH_SESSION_FREE); - sshc->actualcode = CURLE_LOGIN_DENIED; - break; - } - - /* - * At this point we have an authenticated ssh session. - */ - infof(data, "Authentication complete\n"); - - Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */ - - conn->sockfd = sock; - conn->writesockfd = CURL_SOCKET_BAD; - - if(conn->handler->protocol == CURLPROTO_SFTP) { - state(conn, SSH_SFTP_INIT); - break; - } - infof(data, "SSH CONNECT phase done\n"); - state(conn, SSH_STOP); - break; - - case SSH_SFTP_INIT: - /* - * Start the libssh2 sftp session - */ - sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session); - if(!sshc->sftp_session) { - if(libssh2_session_last_errno(sshc->ssh_session) == - LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; - break; - } - else { - char *err_msg; - - (void)libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0); - failf(data, "Failure initializing sftp session: %s", err_msg); - state(conn, SSH_SESSION_FREE); - sshc->actualcode = CURLE_FAILED_INIT; - break; - } - } - state(conn, SSH_SFTP_REALPATH); - break; - - case SSH_SFTP_REALPATH: - { - char tempHome[PATH_MAX]; - - /* - * Get the "home" directory - */ - rc = libssh2_sftp_realpath(sshc->sftp_session, ".", - tempHome, PATH_MAX-1); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc > 0) { - /* It seems that this string is not always NULL terminated */ - tempHome[rc] = '\0'; - sshc->homedir = strdup(tempHome); - if(!sshc->homedir) { - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = CURLE_OUT_OF_MEMORY; - break; - } - conn->data->state.most_recent_ftp_entrypath = sshc->homedir; - } - else { - /* Return the error type */ - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - result = sftp_libssh2_error_to_CURLE(err); - sshc->actualcode = result?result:CURLE_SSH; - DEBUGF(infof(data, "error = %d makes libcurl = %d\n", - err, (int)result)); - state(conn, SSH_STOP); - break; - } - } - /* This is the last step in the SFTP connect phase. Do note that while - we get the homedir here, we get the "workingpath" in the DO action - since the homedir will remain the same between request but the - working path will not. */ - DEBUGF(infof(data, "SSH CONNECT phase done\n")); - state(conn, SSH_STOP); - break; - - case SSH_SFTP_QUOTE_INIT: - - result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path); - if(result) { - sshc->actualcode = result; - state(conn, SSH_STOP); - break; - } - - if(data->set.quote) { - infof(data, "Sending quote commands\n"); - sshc->quote_item = data->set.quote; - state(conn, SSH_SFTP_QUOTE); - } - else { - state(conn, SSH_SFTP_TRANS_INIT); - } - break; - - case SSH_SFTP_POSTQUOTE_INIT: - if(data->set.postquote) { - infof(data, "Sending quote commands\n"); - sshc->quote_item = data->set.postquote; - state(conn, SSH_SFTP_QUOTE); - } - else { - state(conn, SSH_STOP); - } - break; - - case SSH_SFTP_QUOTE: - /* Send any quote commands */ - { - const char *cp; - - /* - * Support some of the "FTP" commands - */ - if(curl_strequal("pwd", sshc->quote_item->data)) { - /* output debug output if that is requested */ - char *tmp = aprintf("257 \"%s\" is current directory.\n", - sftp_scp->path); - if(!tmp) { - result = CURLE_OUT_OF_MEMORY; - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - break; - } - if(data->set.verbose) { - Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn); - Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn); - } - /* this sends an FTP-like "header" to the header callback so that the - current directory can be read very similar to how it is read when - using ordinary FTP. */ - result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp)); - free(tmp); - state(conn, SSH_SFTP_NEXT_QUOTE); - break; - } - else if(sshc->quote_item->data) { - /* - * the arguments following the command must be separated from the - * command with a space so we can check for it unconditionally - */ - cp = strchr(sshc->quote_item->data, ' '); - if(cp == NULL) { - failf(data, "Syntax error in SFTP command. Supply parameter(s)!"); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - - /* - * also, every command takes at least one argument so we get that - * first argument right now - */ - result = get_pathname(&cp, &sshc->quote_path1); - if(result) { - if(result == CURLE_OUT_OF_MEMORY) - failf(data, "Out of memory"); - else - failf(data, "Syntax error: Bad first parameter"); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - break; - } - - /* - * SFTP is a binary protocol, so we don't send text commands to - * the server. Instead, we scan for commands for commands used by - * OpenSSH's sftp program and call the appropriate libssh2 - * functions. - */ - if(curl_strnequal(sshc->quote_item->data, "chgrp ", 6) || - curl_strnequal(sshc->quote_item->data, "chmod ", 6) || - curl_strnequal(sshc->quote_item->data, "chown ", 6) ) { - /* attribute change */ - - /* sshc->quote_path1 contains the mode to set */ - /* get the destination */ - result = get_pathname(&cp, &sshc->quote_path2); - if(result) { - if(result == CURLE_OUT_OF_MEMORY) - failf(data, "Out of memory"); - else - failf(data, "Syntax error in chgrp/chmod/chown: " - "Bad second parameter"); - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - break; - } - memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); - state(conn, SSH_SFTP_QUOTE_STAT); - break; - } - else if(curl_strnequal(sshc->quote_item->data, "ln ", 3) || - curl_strnequal(sshc->quote_item->data, "symlink ", 8)) { - /* symbolic linking */ - /* sshc->quote_path1 is the source */ - /* get the destination */ - result = get_pathname(&cp, &sshc->quote_path2); - if(result) { - if(result == CURLE_OUT_OF_MEMORY) - failf(data, "Out of memory"); - else - failf(data, - "Syntax error in ln/symlink: Bad second parameter"); - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - break; - } - state(conn, SSH_SFTP_QUOTE_SYMLINK); - break; - } - else if(curl_strnequal(sshc->quote_item->data, "mkdir ", 6)) { - /* create dir */ - state(conn, SSH_SFTP_QUOTE_MKDIR); - break; - } - else if(curl_strnequal(sshc->quote_item->data, "rename ", 7)) { - /* rename file */ - /* first param is the source path */ - /* second param is the dest. path */ - result = get_pathname(&cp, &sshc->quote_path2); - if(result) { - if(result == CURLE_OUT_OF_MEMORY) - failf(data, "Out of memory"); - else - failf(data, "Syntax error in rename: Bad second parameter"); - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - break; - } - state(conn, SSH_SFTP_QUOTE_RENAME); - break; - } - else if(curl_strnequal(sshc->quote_item->data, "rmdir ", 6)) { - /* delete dir */ - state(conn, SSH_SFTP_QUOTE_RMDIR); - break; - } - else if(curl_strnequal(sshc->quote_item->data, "rm ", 3)) { - state(conn, SSH_SFTP_QUOTE_UNLINK); - break; - } - - failf(data, "Unknown SFTP command"); - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - Curl_safefree(sshc->quote_path2); - sshc->quote_path2 = NULL; - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - } - if(!sshc->quote_item) { - state(conn, SSH_SFTP_TRANS_INIT); - } - break; - - case SSH_SFTP_NEXT_QUOTE: - if(sshc->quote_path1) { - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - } - if(sshc->quote_path2) { - Curl_safefree(sshc->quote_path2); - sshc->quote_path2 = NULL; - } - - sshc->quote_item = sshc->quote_item->next; - - if(sshc->quote_item) { - state(conn, SSH_SFTP_QUOTE); - } - else { - if(sshc->nextstate != SSH_NO_STATE) { - state(conn, sshc->nextstate); - sshc->nextstate = SSH_NO_STATE; - } - else { - state(conn, SSH_SFTP_TRANS_INIT); - } - } - break; - - case SSH_SFTP_QUOTE_STAT: - if(!curl_strnequal(sshc->quote_item->data, "chmod", 5)) { - /* Since chown and chgrp only set owner OR group but libssh2 wants to - * set them both at once, we need to obtain the current ownership - * first. This takes an extra protocol round trip. - */ - rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, - (unsigned int)strlen(sshc->quote_path2), - LIBSSH2_SFTP_STAT, - &sshc->quote_attrs); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc != 0) { /* get those attributes */ - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - Curl_safefree(sshc->quote_path2); - sshc->quote_path2 = NULL; - failf(data, "Attempt to get SFTP stats failed: %s", - sftp_libssh2_strerror(err)); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - } - - /* Now set the new attributes... */ - if(curl_strnequal(sshc->quote_item->data, "chgrp", 5)) { - sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10); - sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; - if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0])) { - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - Curl_safefree(sshc->quote_path2); - sshc->quote_path2 = NULL; - failf(data, "Syntax error: chgrp gid not a number"); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - } - else if(curl_strnequal(sshc->quote_item->data, "chmod", 5)) { - sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8); - sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS; - /* permissions are octal */ - if(sshc->quote_attrs.permissions == 0 && - !ISDIGIT(sshc->quote_path1[0])) { - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - Curl_safefree(sshc->quote_path2); - sshc->quote_path2 = NULL; - failf(data, "Syntax error: chmod permissions not a number"); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - } - else if(curl_strnequal(sshc->quote_item->data, "chown", 5)) { - sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10); - sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID; - if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0])) { - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - Curl_safefree(sshc->quote_path2); - sshc->quote_path2 = NULL; - failf(data, "Syntax error: chown uid not a number"); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - } - - /* Now send the completed structure... */ - state(conn, SSH_SFTP_QUOTE_SETSTAT); - break; - - case SSH_SFTP_QUOTE_SETSTAT: - rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, - (unsigned int)strlen(sshc->quote_path2), - LIBSSH2_SFTP_SETSTAT, - &sshc->quote_attrs); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc != 0) { - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - Curl_safefree(sshc->quote_path2); - sshc->quote_path2 = NULL; - failf(data, "Attempt to set SFTP stats failed: %s", - sftp_libssh2_strerror(err)); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - state(conn, SSH_SFTP_NEXT_QUOTE); - break; - - case SSH_SFTP_QUOTE_SYMLINK: - rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1, - (unsigned int)strlen(sshc->quote_path1), - sshc->quote_path2, - (unsigned int)strlen(sshc->quote_path2), - LIBSSH2_SFTP_SYMLINK); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc != 0) { - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - Curl_safefree(sshc->quote_path2); - sshc->quote_path2 = NULL; - failf(data, "symlink command failed: %s", - sftp_libssh2_strerror(err)); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - state(conn, SSH_SFTP_NEXT_QUOTE); - break; - - case SSH_SFTP_QUOTE_MKDIR: - rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1, - (unsigned int)strlen(sshc->quote_path1), - 0755); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc != 0) { - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err)); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - state(conn, SSH_SFTP_NEXT_QUOTE); - break; - - case SSH_SFTP_QUOTE_RENAME: - rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1, - (unsigned int)strlen(sshc->quote_path1), - sshc->quote_path2, - (unsigned int)strlen(sshc->quote_path2), - LIBSSH2_SFTP_RENAME_OVERWRITE | - LIBSSH2_SFTP_RENAME_ATOMIC | - LIBSSH2_SFTP_RENAME_NATIVE); - - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc != 0) { - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - Curl_safefree(sshc->quote_path2); - sshc->quote_path2 = NULL; - failf(data, "rename command failed: %s", sftp_libssh2_strerror(err)); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - state(conn, SSH_SFTP_NEXT_QUOTE); - break; - - case SSH_SFTP_QUOTE_RMDIR: - rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1, - (unsigned int)strlen(sshc->quote_path1)); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc != 0) { - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err)); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - state(conn, SSH_SFTP_NEXT_QUOTE); - break; - - case SSH_SFTP_QUOTE_UNLINK: - rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1, - (unsigned int)strlen(sshc->quote_path1)); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc != 0) { - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - Curl_safefree(sshc->quote_path1); - sshc->quote_path1 = NULL; - failf(data, "rm command failed: %s", sftp_libssh2_strerror(err)); - state(conn, SSH_SFTP_CLOSE); - sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - break; - } - state(conn, SSH_SFTP_NEXT_QUOTE); - break; - - case SSH_SFTP_TRANS_INIT: - if(data->set.upload) - state(conn, SSH_SFTP_UPLOAD_INIT); - else { - if(data->set.opt_no_body) - state(conn, SSH_STOP); - else if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/') - state(conn, SSH_SFTP_READDIR_INIT); - else - state(conn, SSH_SFTP_DOWNLOAD_INIT); - } - break; - - case SSH_SFTP_UPLOAD_INIT: - { - unsigned long flags; - /* - * NOTE!!! libssh2 requires that the destination path is a full path - * that includes the destination file and name OR ends in a "/" - * If this is not done the destination file will be named the - * same name as the last directory in the path. - */ - - if(data->state.resume_from != 0) { - LIBSSH2_SFTP_ATTRIBUTES attrs; - if(data->state.resume_from < 0) { - rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, - (unsigned int)strlen(sftp_scp->path), - LIBSSH2_SFTP_STAT, &attrs); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc) { - data->state.resume_from = 0; - } - else { - curl_off_t size = attrs.filesize; - if(size < 0) { - failf(data, "Bad file size (%" FORMAT_OFF_T ")", size); - return CURLE_BAD_DOWNLOAD_RESUME; - } - data->state.resume_from = attrs.filesize; - } - } - } - - if(data->set.ftp_append) - /* Try to open for append, but create if nonexisting */ - flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND; - else if (data->state.resume_from > 0) - /* If we have restart position then open for append */ - flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND; - else - /* Clear file before writing (normal behaviour) */ - flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC; - - sshc->sftp_handle = - libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, - (unsigned int)strlen(sftp_scp->path), - flags, data->set.new_file_perms, - LIBSSH2_SFTP_OPENFILE); - - if(!sshc->sftp_handle) { - rc = libssh2_session_last_errno(sshc->ssh_session); - - if(LIBSSH2_ERROR_EAGAIN == rc) - break; - else { - if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc) - /* only when there was an SFTP protocol error can we extract - the sftp error! */ - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - else - err = -1; /* not an sftp error at all */ - - if(sshc->secondCreateDirs) { - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = err>= LIBSSH2_FX_OK? - sftp_libssh2_error_to_CURLE(err):CURLE_SSH; - failf(data, "Creating the dir/file failed: %s", - sftp_libssh2_strerror(err)); - break; - } - else if(((err == LIBSSH2_FX_NO_SUCH_FILE) || - (err == LIBSSH2_FX_FAILURE) || - (err == LIBSSH2_FX_NO_SUCH_PATH)) && - (data->set.ftp_create_missing_dirs && - (strlen(sftp_scp->path) > 1))) { - /* try to create the path remotely */ - sshc->secondCreateDirs = 1; - state(conn, SSH_SFTP_CREATE_DIRS_INIT); - break; - } - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = err>= LIBSSH2_FX_OK? - sftp_libssh2_error_to_CURLE(err):CURLE_SSH; - if(!sshc->actualcode) { - /* Sometimes, for some reason libssh2_sftp_last_error() returns - zero even though libssh2_sftp_open() failed previously! We need - to work around that! */ - sshc->actualcode = CURLE_SSH; - err=-1; - } - failf(data, "Upload failed: %s (%d/%d)", - err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error", - err, rc); - break; - } - } - - /* If we have restart point then we need to seek to the correct - position. */ - if(data->state.resume_from > 0) { - /* Let's read off the proper amount of bytes from the input. */ - if(conn->seek_func) { - seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, - SEEK_SET); - } - - if(seekerr != CURL_SEEKFUNC_OK){ - - if(seekerr != CURL_SEEKFUNC_CANTSEEK) { - failf(data, "Could not seek stream"); - return CURLE_FTP_COULDNT_USE_REST; - } - /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ - else { - curl_off_t passed=0; - do { - size_t readthisamountnow = - (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? - BUFSIZE : curlx_sotouz(data->state.resume_from - passed); - - size_t actuallyread = - conn->fread_func(data->state.buffer, 1, readthisamountnow, - conn->fread_in); - - passed += actuallyread; - if((actuallyread == 0) || (actuallyread > readthisamountnow)) { - /* this checks for greater-than only to make sure that the - CURL_READFUNC_ABORT return code still aborts */ - failf(data, "Failed to read data"); - return CURLE_FTP_COULDNT_USE_REST; - } - } while(passed < data->state.resume_from); - } - } - - /* now, decrease the size of the read */ - if(data->set.infilesize > 0) { - data->set.infilesize -= data->state.resume_from; - data->req.size = data->set.infilesize; - Curl_pgrsSetUploadSize(data, data->set.infilesize); - } - - SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); - } - if(data->set.infilesize > 0) { - data->req.size = data->set.infilesize; - Curl_pgrsSetUploadSize(data, data->set.infilesize); - } - /* upload data */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); - - /* not set by Curl_setup_transfer to preserve keepon bits */ - conn->sockfd = conn->writesockfd; - - if(result) { - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = result; - } - else { - /* store this original bitmask setup to use later on if we can't - figure out a "real" bitmask */ - sshc->orig_waitfor = data->req.keepon; - - /* we want to use the _sending_ function even when the socket turns - out readable as the underlying libssh2 sftp send function will deal - with both accordingly */ - conn->cselect_bits = CURL_CSELECT_OUT; - - /* since we don't really wait for anything at this point, we want the - state machine to move on as soon as possible so we set a very short - timeout here */ - Curl_expire(data, 1); - - state(conn, SSH_STOP); - } - break; - } - - case SSH_SFTP_CREATE_DIRS_INIT: - if(strlen(sftp_scp->path) > 1) { - sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */ - state(conn, SSH_SFTP_CREATE_DIRS); - } - else { - state(conn, SSH_SFTP_UPLOAD_INIT); - } - break; - - case SSH_SFTP_CREATE_DIRS: - if((sshc->slash_pos = strchr(sshc->slash_pos, '/')) != NULL) { - *sshc->slash_pos = 0; - - infof(data, "Creating directory '%s'\n", sftp_scp->path); - state(conn, SSH_SFTP_CREATE_DIRS_MKDIR); - break; - } - else { - state(conn, SSH_SFTP_UPLOAD_INIT); - } - break; - - case SSH_SFTP_CREATE_DIRS_MKDIR: - /* 'mode' - parameter is preliminary - default to 0644 */ - rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path, - (unsigned int)strlen(sftp_scp->path), - data->set.new_directory_perms); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - *sshc->slash_pos = '/'; - ++sshc->slash_pos; - if(rc == -1) { - unsigned int sftp_err = 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 - */ - sftp_err = (unsigned int)(libssh2_sftp_last_error(sshc->sftp_session)); - if((sftp_err != LIBSSH2_FX_FILE_ALREADY_EXISTS) && - (sftp_err != LIBSSH2_FX_FAILURE) && - (sftp_err != LIBSSH2_FX_PERMISSION_DENIED)) { - result = sftp_libssh2_error_to_CURLE(sftp_err); - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = result?result:CURLE_SSH; - break; - } - } - state(conn, SSH_SFTP_CREATE_DIRS); - break; - - case SSH_SFTP_READDIR_INIT: - /* - * This is a directory that we are trying to get, so produce a directory - * listing - */ - sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session, - sftp_scp->path, - (unsigned int) - strlen(sftp_scp->path), - 0, 0, LIBSSH2_SFTP_OPENDIR); - if(!sshc->sftp_handle) { - if(libssh2_session_last_errno(sshc->ssh_session) == - LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; - break; - } - else { - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - failf(data, "Could not open directory for reading: %s", - sftp_libssh2_strerror(err)); - state(conn, SSH_SFTP_CLOSE); - result = sftp_libssh2_error_to_CURLE(err); - sshc->actualcode = result?result:CURLE_SSH; - break; - } - } - if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) { - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = CURLE_OUT_OF_MEMORY; - break; - } - if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) { - Curl_safefree(sshc->readdir_filename); - sshc->readdir_filename = NULL; - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = CURLE_OUT_OF_MEMORY; - break; - } - state(conn, SSH_SFTP_READDIR); - break; - - case SSH_SFTP_READDIR: - sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle, - sshc->readdir_filename, - PATH_MAX, - sshc->readdir_longentry, - PATH_MAX, - &sshc->readdir_attrs); - if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; - break; - } - if(sshc->readdir_len > 0) { - sshc->readdir_filename[sshc->readdir_len] = '\0'; - - if(data->set.ftp_list_only) { - char *tmpLine; - - tmpLine = aprintf("%s\n", sshc->readdir_filename); - if(tmpLine == NULL) { - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = CURLE_OUT_OF_MEMORY; - break; - } - result = Curl_client_write(conn, CLIENTWRITE_BODY, - tmpLine, sshc->readdir_len+1); - Curl_safefree(tmpLine); - - if(result) { - state(conn, SSH_STOP); - break; - } - /* since this counts what we send to the client, we include the - newline in this counter */ - data->req.bytecount += sshc->readdir_len+1; - - /* output debug output if that is requested */ - if(data->set.verbose) { - Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename, - sshc->readdir_len, conn); - } - } - else { - sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry); - sshc->readdir_totalLen = 80 + sshc->readdir_currLen; - sshc->readdir_line = calloc(sshc->readdir_totalLen, 1); - if(!sshc->readdir_line) { - Curl_safefree(sshc->readdir_filename); - sshc->readdir_filename = NULL; - Curl_safefree(sshc->readdir_longentry); - sshc->readdir_longentry = NULL; - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = CURLE_OUT_OF_MEMORY; - break; - } - - memcpy(sshc->readdir_line, sshc->readdir_longentry, - sshc->readdir_currLen); - if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) && - ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) == - LIBSSH2_SFTP_S_IFLNK)) { - sshc->readdir_linkPath = malloc(PATH_MAX + 1); - if(sshc->readdir_linkPath == NULL) { - Curl_safefree(sshc->readdir_filename); - sshc->readdir_filename = NULL; - Curl_safefree(sshc->readdir_longentry); - sshc->readdir_longentry = NULL; - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = CURLE_OUT_OF_MEMORY; - break; - } - - snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path, - sshc->readdir_filename); - state(conn, SSH_SFTP_READDIR_LINK); - break; - } - state(conn, SSH_SFTP_READDIR_BOTTOM); - break; - } - } - else if(sshc->readdir_len == 0) { - Curl_safefree(sshc->readdir_filename); - sshc->readdir_filename = NULL; - Curl_safefree(sshc->readdir_longentry); - sshc->readdir_longentry = NULL; - state(conn, SSH_SFTP_READDIR_DONE); - break; - } - else if(sshc->readdir_len <= 0) { - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - result = sftp_libssh2_error_to_CURLE(err); - sshc->actualcode = result?result:CURLE_SSH; - failf(data, "Could not open remote file for reading: %s :: %d", - sftp_libssh2_strerror(err), - libssh2_session_last_errno(sshc->ssh_session)); - Curl_safefree(sshc->readdir_filename); - sshc->readdir_filename = NULL; - Curl_safefree(sshc->readdir_longentry); - sshc->readdir_longentry = NULL; - state(conn, SSH_SFTP_CLOSE); - break; - } - break; - - case SSH_SFTP_READDIR_LINK: - sshc->readdir_len = - libssh2_sftp_symlink_ex(sshc->sftp_session, - sshc->readdir_linkPath, - (unsigned int) strlen(sshc->readdir_linkPath), - sshc->readdir_filename, - PATH_MAX, LIBSSH2_SFTP_READLINK); - if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; - break; - } - Curl_safefree(sshc->readdir_linkPath); - sshc->readdir_linkPath = NULL; - sshc->readdir_line = realloc(sshc->readdir_line, - sshc->readdir_totalLen + 4 + - sshc->readdir_len); - if(!sshc->readdir_line) { - Curl_safefree(sshc->readdir_filename); - sshc->readdir_filename = NULL; - Curl_safefree(sshc->readdir_longentry); - sshc->readdir_longentry = NULL; - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = CURLE_OUT_OF_MEMORY; - break; - } - - sshc->readdir_currLen += snprintf(sshc->readdir_line + - sshc->readdir_currLen, - sshc->readdir_totalLen - - sshc->readdir_currLen, - " -> %s", - sshc->readdir_filename); - - state(conn, SSH_SFTP_READDIR_BOTTOM); - break; - - case SSH_SFTP_READDIR_BOTTOM: - sshc->readdir_currLen += snprintf(sshc->readdir_line + - sshc->readdir_currLen, - sshc->readdir_totalLen - - sshc->readdir_currLen, "\n"); - result = Curl_client_write(conn, CLIENTWRITE_BODY, - sshc->readdir_line, - sshc->readdir_currLen); - - if(result == CURLE_OK) { - - /* output debug output if that is requested */ - if(data->set.verbose) { - Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line, - sshc->readdir_currLen, conn); - } - data->req.bytecount += sshc->readdir_currLen; - } - Curl_safefree(sshc->readdir_line); - sshc->readdir_line = NULL; - if(result) { - state(conn, SSH_STOP); - } - else - state(conn, SSH_SFTP_READDIR); - break; - - case SSH_SFTP_READDIR_DONE: - if(libssh2_sftp_closedir(sshc->sftp_handle) == - LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; - break; - } - sshc->sftp_handle = NULL; - Curl_safefree(sshc->readdir_filename); - sshc->readdir_filename = NULL; - Curl_safefree(sshc->readdir_longentry); - sshc->readdir_longentry = 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 - */ - sshc->sftp_handle = - libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path, - (unsigned int)strlen(sftp_scp->path), - LIBSSH2_FXF_READ, data->set.new_file_perms, - LIBSSH2_SFTP_OPENFILE); - if(!sshc->sftp_handle) { - if(libssh2_session_last_errno(sshc->ssh_session) == - LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; - break; - } - else { - err = (int)(libssh2_sftp_last_error(sshc->sftp_session)); - failf(data, "Could not open remote file for reading: %s", - sftp_libssh2_strerror(err)); - state(conn, SSH_SFTP_CLOSE); - result = sftp_libssh2_error_to_CURLE(err); - sshc->actualcode = result?result:CURLE_SSH; - break; - } - } - state(conn, SSH_SFTP_DOWNLOAD_STAT); - break; - - case SSH_SFTP_DOWNLOAD_STAT: - { - LIBSSH2_SFTP_ATTRIBUTES attrs; - - rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path, - (unsigned int)strlen(sftp_scp->path), - LIBSSH2_SFTP_STAT, &attrs); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc) { - /* - * libssh2_sftp_open() didn't return an error, so maybe the server - * just doesn't support stat() - */ - data->req.size = -1; - data->req.maxdownload = -1; - } - else { - curl_off_t size = attrs.filesize; - - if(size < 0) { - failf(data, "Bad file size (%" FORMAT_OFF_T ")", size); - return CURLE_BAD_DOWNLOAD_RESUME; - } - if(conn->data->state.use_range) { - curl_off_t from, to; - char *ptr; - char *ptr2; - - from=curlx_strtoofft(conn->data->state.range, &ptr, 0); - while(*ptr && (ISSPACE(*ptr) || (*ptr=='-'))) - ptr++; - to=curlx_strtoofft(ptr, &ptr2, 0); - if((ptr == ptr2) /* no "to" value given */ - || (to >= size)) { - to = size - 1; - } - if(from < 0) { - /* from is relative to end of file */ - from += size; - } - if(from >= size) { - failf(data, "Offset (%" - FORMAT_OFF_T ") was beyond file size (%" FORMAT_OFF_T ")", - from, attrs.filesize); - return CURLE_BAD_DOWNLOAD_RESUME; - } - if(from > to) { - from = to; - size = 0; - } - else { - size = to - from + 1; - } - - SFTP_SEEK(conn->proto.sshc.sftp_handle, from); - } - data->req.size = size; - data->req.maxdownload = size; - Curl_pgrsSetDownloadSize(data, size); - } - - /* We can resume if we can seek to the resume position */ - if(data->state.resume_from) { - if(data->state.resume_from < 0) { - /* We're supposed to download the last abs(from) bytes */ - if((curl_off_t)attrs.filesize < -data->state.resume_from) { - failf(data, "Offset (%" - FORMAT_OFF_T ") was beyond file size (%" FORMAT_OFF_T ")", - data->state.resume_from, attrs.filesize); - return CURLE_BAD_DOWNLOAD_RESUME; - } - /* download from where? */ - data->state.resume_from += attrs.filesize; - } - else { - if((curl_off_t)attrs.filesize < data->state.resume_from) { - failf(data, "Offset (%" FORMAT_OFF_T - ") was beyond file size (%" FORMAT_OFF_T ")", - data->state.resume_from, attrs.filesize); - return CURLE_BAD_DOWNLOAD_RESUME; - } - } - /* Does a completed file need to be seeked and started or closed ? */ - /* Now store the number of bytes we are expected to download */ - data->req.size = attrs.filesize - data->state.resume_from; - data->req.maxdownload = attrs.filesize - data->state.resume_from; - Curl_pgrsSetDownloadSize(data, - attrs.filesize - data->state.resume_from); - SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); - } - } - /* Setup the actual download */ - if(data->req.size == 0) { - /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - infof(data, "File already completely downloaded\n"); - state(conn, SSH_STOP); - break; - } - else { - Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size, - FALSE, NULL, -1, NULL); - - /* not set by Curl_setup_transfer to preserve keepon bits */ - conn->writesockfd = conn->sockfd; - - /* we want to use the _receiving_ function even when the socket turns - out writableable as the underlying libssh2 recv function will deal - with both accordingly */ - conn->cselect_bits = CURL_CSELECT_IN; - } - if(result) { - state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = result; - } - else { - state(conn, SSH_STOP); - } - break; - - case SSH_SFTP_CLOSE: - if(sshc->sftp_handle) { - rc = libssh2_sftp_close(sshc->sftp_handle); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc < 0) { - infof(data, "Failed to close libssh2 file\n"); - } - sshc->sftp_handle = NULL; - } - if(sftp_scp) { - Curl_safefree(sftp_scp->path); - sftp_scp->path = NULL; - } - - 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) { - state(conn, sshc->nextstate); - sshc->nextstate = SSH_SFTP_CLOSE; - } - else { - state(conn, SSH_STOP); - result = sshc->actualcode; - } - break; - - case SSH_SFTP_SHUTDOWN: - /* during times we get here due to a broken transfer and then the - sftp_handle might not have been taken down so make sure that is done - before we proceed */ - - if(sshc->sftp_handle) { - rc = libssh2_sftp_close(sshc->sftp_handle); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc < 0) { - infof(data, "Failed to close libssh2 file\n"); - } - sshc->sftp_handle = NULL; - } - if(sshc->sftp_session) { - rc = libssh2_sftp_shutdown(sshc->sftp_session); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc < 0) { - infof(data, "Failed to stop libssh2 sftp subsystem\n"); - } - sshc->sftp_session = NULL; - } - - Curl_safefree(sshc->homedir); - sshc->homedir = NULL; - conn->data->state.most_recent_ftp_entrypath = NULL; - - state(conn, SSH_SESSION_DISCONNECT); - break; - - case SSH_SCP_TRANS_INIT: - result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path); - if(result) { - sshc->actualcode = result; - state(conn, SSH_STOP); - break; - } - - if(data->set.upload) { - if(data->set.infilesize < 0) { - failf(data, "SCP requires a known file size for upload"); - sshc->actualcode = CURLE_UPLOAD_FAILED; - state(conn, SSH_SCP_CHANNEL_FREE); - break; - } - state(conn, SSH_SCP_UPLOAD_INIT); - } - else { - state(conn, SSH_SCP_DOWNLOAD_INIT); - } - break; - - case SSH_SCP_UPLOAD_INIT: - /* - * libssh2 requires that the destination path is a full path that - * includes the destination file and name OR ends in a "/" . If this is - * not done the destination file will be named the same name as the last - * directory in the path. - */ - sshc->ssh_channel = - SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms, - data->set.infilesize); - if(!sshc->ssh_channel) { - if(libssh2_session_last_errno(sshc->ssh_session) == - LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; - break; - } - else { - int ssh_err; - char *err_msg; - - ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0)); - failf(conn->data, "%s", err_msg); - state(conn, SSH_SCP_CHANNEL_FREE); - sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); - break; - } - } - - /* upload data */ - Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL, - FIRSTSOCKET, NULL); - - /* not set by Curl_setup_transfer to preserve keepon bits */ - conn->sockfd = conn->writesockfd; - - if(result) { - state(conn, SSH_SCP_CHANNEL_FREE); - sshc->actualcode = result; - } - else { - /* we want to use the _sending_ function even when the socket turns - out readable as the underlying libssh2 scp send function will deal - with both accordingly */ - conn->cselect_bits = CURL_CSELECT_OUT; - - state(conn, SSH_STOP); - } - break; - - case SSH_SCP_DOWNLOAD_INIT: - { - /* - * We must check the remote file; if it is a directory no values will - * be set in sb - */ - struct stat sb; - curl_off_t bytecount; - - /* clear the struct scp recv will fill in */ - memset(&sb, 0, sizeof(struct stat)); - - /* get a fresh new channel from the ssh layer */ - sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session, - sftp_scp->path, &sb); - if(!sshc->ssh_channel) { - if(libssh2_session_last_errno(sshc->ssh_session) == - LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; - break; - } - else { - int ssh_err; - char *err_msg; - - ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0)); - failf(conn->data, "%s", err_msg); - state(conn, SSH_SCP_CHANNEL_FREE); - sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); - break; - } - } - - /* download data */ - bytecount = (curl_off_t)sb.st_size; - data->req.maxdownload = (curl_off_t)sb.st_size; - Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL); - - /* not set by Curl_setup_transfer to preserve keepon bits */ - conn->writesockfd = conn->sockfd; - - /* we want to use the _receiving_ function even when the socket turns - out writableable as the underlying libssh2 recv function will deal - with both accordingly */ - conn->cselect_bits = CURL_CSELECT_IN; - - if(result) { - state(conn, SSH_SCP_CHANNEL_FREE); - sshc->actualcode = result; - } - else - state(conn, SSH_STOP); - } - break; - - case SSH_SCP_DONE: - if(data->set.upload) - state(conn, SSH_SCP_SEND_EOF); - else - state(conn, SSH_SCP_CHANNEL_FREE); - break; - - case SSH_SCP_SEND_EOF: - if(sshc->ssh_channel) { - rc = libssh2_channel_send_eof(sshc->ssh_channel); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc) { - infof(data, "Failed to send libssh2 channel EOF\n"); - } - } - state(conn, SSH_SCP_WAIT_EOF); - break; - - case SSH_SCP_WAIT_EOF: - if(sshc->ssh_channel) { - rc = libssh2_channel_wait_eof(sshc->ssh_channel); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc) { - infof(data, "Failed to get channel EOF: %d\n", rc); - } - } - state(conn, SSH_SCP_WAIT_CLOSE); - break; - - case SSH_SCP_WAIT_CLOSE: - if(sshc->ssh_channel) { - rc = libssh2_channel_wait_closed(sshc->ssh_channel); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc) { - infof(data, "Channel failed to close: %d\n", rc); - } - } - state(conn, SSH_SCP_CHANNEL_FREE); - break; - - case SSH_SCP_CHANNEL_FREE: - if(sshc->ssh_channel) { - rc = libssh2_channel_free(sshc->ssh_channel); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc < 0) { - infof(data, "Failed to free libssh2 scp subsystem\n"); - } - sshc->ssh_channel = NULL; - } - DEBUGF(infof(data, "SCP DONE phase complete\n")); -#if 0 /* PREV */ - state(conn, SSH_SESSION_DISCONNECT); -#endif - state(conn, SSH_STOP); - result = sshc->actualcode; - break; - - case SSH_SESSION_DISCONNECT: - /* during weird times when we've been prematurely aborted, the channel - is still alive when we reach this state and we MUST kill the channel - properly first */ - if(sshc->ssh_channel) { - rc = libssh2_channel_free(sshc->ssh_channel); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc < 0) { - infof(data, "Failed to free libssh2 scp subsystem\n"); - } - sshc->ssh_channel = NULL; - } - - if(sshc->ssh_session) { - rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown"); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc < 0) { - infof(data, "Failed to disconnect libssh2 session\n"); - } - } - - Curl_safefree(sshc->homedir); - sshc->homedir = NULL; - conn->data->state.most_recent_ftp_entrypath = NULL; - - state(conn, SSH_SESSION_FREE); - break; - - case SSH_SESSION_FREE: -#ifdef HAVE_LIBSSH2_KNOWNHOST_API - if(sshc->kh) { - libssh2_knownhost_free(sshc->kh); - sshc->kh = NULL; - } -#endif - - if(sshc->ssh_session) { - rc = libssh2_session_free(sshc->ssh_session); - if(rc == LIBSSH2_ERROR_EAGAIN) { - break; - } - else if(rc < 0) { - infof(data, "Failed to free libssh2 session\n"); - } - sshc->ssh_session = NULL; - } - conn->bits.close = TRUE; - sshc->nextstate = SSH_NO_STATE; - state(conn, SSH_STOP); - result = sshc->actualcode; - break; - - case SSH_QUIT: - /* fallthrough, just stop! */ - default: - /* internal error */ - sshc->nextstate = SSH_NO_STATE; - state(conn, SSH_STOP); - break; - } - - } while(!rc && (sshc->state != SSH_STOP)); - - if(rc == LIBSSH2_ERROR_EAGAIN) { - /* we would block, we need to wait for the socket to be ready (in the - right direction too)! */ - *block = TRUE; - } - - return result; -} - -/* called by the multi interface to figure out what socket(s) to wait for and - for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ -static int ssh_perform_getsock(const struct connectdata *conn, - curl_socket_t *sock, /* points to numsocks - number of sockets */ - int numsocks) -{ -#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION - int bitmap = GETSOCK_BLANK; - (void)numsocks; - - sock[0] = conn->sock[FIRSTSOCKET]; - - if(conn->waitfor & KEEP_RECV) - bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); - - if(conn->waitfor & KEEP_SEND) - bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); - - return bitmap; -#else - /* if we don't know the direction we can use the generic *_getsock() - function even for the protocol_connect and doing states */ - return Curl_single_getsock(conn, sock, numsocks); -#endif -} - -/* Generic function called by the multi interface to figure out what socket(s) - to wait for and for what actions during the DOING and PROTOCONNECT states*/ -static int ssh_getsock(struct connectdata *conn, - curl_socket_t *sock, /* points to numsocks number - of sockets */ - int numsocks) -{ -#ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION - (void)conn; - (void)sock; - (void)numsocks; - /* if we don't know any direction we can just play along as we used to and - not provide any sensible info */ - return GETSOCK_BLANK; -#else - /* if we know the direction we can use the generic *_getsock() function even - for the protocol_connect and doing states */ - return ssh_perform_getsock(conn, sock, numsocks); -#endif -} - -#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION -/* - * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this - * function is used to figure out in what direction and stores this info so - * that the multi interface can take advantage of it. Make sure to call this - * function in all cases so that when it _doesn't_ return EAGAIN we can - * restore the default wait bits. - */ -static void ssh_block2waitfor(struct connectdata *conn, bool block) -{ - struct ssh_conn *sshc = &conn->proto.sshc; - int dir; - if(!block) - conn->waitfor = 0; - else if((dir = libssh2_session_block_directions(sshc->ssh_session))) { - /* translate the libssh2 define bits into our own bit defines */ - conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | - ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0); - } - else - /* It didn't block or libssh2 didn't reveal in which direction, put back - the original set */ - conn->waitfor = sshc->orig_waitfor; -} -#else - /* no libssh2 directional support so we simply don't know */ -#define ssh_block2waitfor(x,y) -#endif - -/* called repeatedly until done from multi.c */ -static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done) -{ - struct ssh_conn *sshc = &conn->proto.sshc; - CURLcode result = CURLE_OK; - bool block; /* we store the status and use that to provide a ssh_getsock() - implementation */ - - result = ssh_statemach_act(conn, &block); - *done = (bool)(sshc->state == SSH_STOP); - ssh_block2waitfor(conn, block); - - return result; -} - -static CURLcode ssh_easy_statemach(struct connectdata *conn, - bool duringconnect) -{ - struct ssh_conn *sshc = &conn->proto.sshc; - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - - while((sshc->state != SSH_STOP) && !result) { - bool block; - long left; - - result = ssh_statemach_act(conn, &block); - if(result) - break; - - if(Curl_pgrsUpdate(conn)) - return CURLE_ABORTED_BY_CALLBACK; - else { - struct timeval now = Curl_tvnow(); - result = Curl_speedcheck(data, now); - if(result) - break; - } - - left = Curl_timeleft(data, NULL, duringconnect); - if(left < 0) { - failf(data, "Operation timed out\n"); - return CURLE_OPERATION_TIMEDOUT; - } - -#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION - if((CURLE_OK == result) && block) { - int dir = libssh2_session_block_directions(sshc->ssh_session); - curl_socket_t sock = conn->sock[FIRSTSOCKET]; - curl_socket_t fd_read = CURL_SOCKET_BAD; - curl_socket_t fd_write = CURL_SOCKET_BAD; - if (LIBSSH2_SESSION_BLOCK_INBOUND & dir) { - fd_read = sock; - } - if (LIBSSH2_SESSION_BLOCK_OUTBOUND & dir) { - fd_write = sock; - } - /* wait for the socket to become ready */ - Curl_socket_ready(fd_read, fd_write, - (int)(left>1000?1000:left)); /* ignore result */ - } -#endif - - } - - return result; -} - -/* - * SSH setup and connection - */ -static CURLcode ssh_init(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - struct SSHPROTO *ssh; - struct ssh_conn *sshc = &conn->proto.sshc; - - sshc->actualcode = CURLE_OK; /* reset error code */ - sshc->secondCreateDirs =0; /* reset the create dir attempt state - variable */ - - if(data->state.proto.ssh) - return CURLE_OK; - - ssh = calloc(1, sizeof(struct SSHPROTO)); - if(!ssh) - return CURLE_OUT_OF_MEMORY; - - data->state.proto.ssh = ssh; - - return CURLE_OK; -} - -static Curl_recv scp_recv, sftp_recv; -static Curl_send scp_send, sftp_send; - -/* - * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to - * do protocol-specific actions at connect-time. - */ -static CURLcode ssh_connect(struct connectdata *conn, bool *done) -{ -#ifdef CURL_LIBSSH2_DEBUG - curl_socket_t sock; -#endif - struct ssh_conn *ssh; - CURLcode result; - struct SessionHandle *data = conn->data; - - /* 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. */ - conn->bits.close = FALSE; - - /* If there already is a protocol-specific struct allocated for this - sessionhandle, deal with it */ - Curl_reset_reqproto(conn); - - result = ssh_init(conn); - if(result) - return result; - - if(conn->handler->protocol & CURLPROTO_SCP) { - conn->recv[FIRSTSOCKET] = scp_recv; - conn->send[FIRSTSOCKET] = scp_send; - } else { - conn->recv[FIRSTSOCKET] = sftp_recv; - conn->send[FIRSTSOCKET] = sftp_send; - } - ssh = &conn->proto.sshc; - -#ifdef CURL_LIBSSH2_DEBUG - if(conn->user) { - infof(data, "User: %s\n", conn->user); - } - if(conn->passwd) { - infof(data, "Password: %s\n", conn->passwd); - } - sock = conn->sock[FIRSTSOCKET]; -#endif /* CURL_LIBSSH2_DEBUG */ - - ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc, - my_libssh2_free, - my_libssh2_realloc, conn); - if(ssh->ssh_session == NULL) { - failf(data, "Failure initialising ssh session"); - return CURLE_FAILED_INIT; - } - -#ifdef HAVE_LIBSSH2_KNOWNHOST_API - if(data->set.str[STRING_SSH_KNOWNHOSTS]) { - int rc; - ssh->kh = libssh2_knownhost_init(ssh->ssh_session); - if(!ssh->kh) { - /* eeek. TODO: free the ssh_session! */ - return CURLE_FAILED_INIT; - } - - /* read all known hosts from there */ - rc = libssh2_knownhost_readfile(ssh->kh, - data->set.str[STRING_SSH_KNOWNHOSTS], - LIBSSH2_KNOWNHOST_FILE_OPENSSH); - if(rc < 0) - infof(data, "Failed to read known hosts from %s\n", - data->set.str[STRING_SSH_KNOWNHOSTS]); - } -#endif /* HAVE_LIBSSH2_KNOWNHOST_API */ - -#ifdef CURL_LIBSSH2_DEBUG - libssh2_trace(ssh->ssh_session, ~0); - infof(data, "SSH socket: %d\n", (int)sock); -#endif /* CURL_LIBSSH2_DEBUG */ - - state(conn, SSH_S_STARTUP); - - if(data->state.used_interface == Curl_if_multi) - result = ssh_multi_statemach(conn, done); - else { - result = ssh_easy_statemach(conn, TRUE); - if(!result) - *done = TRUE; - } - - return result; -} - -/* - *********************************************************************** - * - * scp_perform() - * - * This is the actual DO function for SCP. Get a file according to - * the options previously setup. - */ - -static -CURLcode scp_perform(struct connectdata *conn, - bool *connected, - bool *dophase_done) -{ - CURLcode result = CURLE_OK; - - DEBUGF(infof(conn->data, "DO phase starts\n")); - - *dophase_done = FALSE; /* not done yet */ - - /* start the first command in the DO phase */ - state(conn, SSH_SCP_TRANS_INIT); - - /* run the state-machine */ - if(conn->data->state.used_interface == Curl_if_multi) { - result = ssh_multi_statemach(conn, dophase_done); - } - else { - result = ssh_easy_statemach(conn, FALSE); - *dophase_done = TRUE; /* with the easy interface we are done here */ - } - *connected = conn->bits.tcpconnect; - - if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); - } - - return result; -} - -/* called from multi.c while DOing */ -static CURLcode scp_doing(struct connectdata *conn, - bool *dophase_done) -{ - CURLcode result; - result = ssh_multi_statemach(conn, dophase_done); - - if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); - } - return result; -} - -/* - * The DO function is generic for both protocols. There was previously two - * separate ones but this way means less duplicated code. - */ - -static CURLcode ssh_do(struct connectdata *conn, bool *done) -{ - CURLcode res; - bool connected = 0; - struct SessionHandle *data = conn->data; - - *done = FALSE; /* default to false */ - - /* - Since connections can be re-used between SessionHandles, this might be a - connection already existing but on a fresh SessionHandle struct so we must - make sure we have a good 'struct SSHPROTO' to play with. For new - connections, the struct SSHPROTO is allocated and setup in the - ssh_connect() function. - */ - Curl_reset_reqproto(conn); - res = ssh_init(conn); - if(res) - return res; - - data->req.size = -1; /* make sure this is unknown at this point */ - - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - Curl_pgrsSetUploadSize(data, 0); - Curl_pgrsSetDownloadSize(data, 0); - - if(conn->handler->protocol & CURLPROTO_SCP) - res = scp_perform(conn, &connected, done); - else - res = sftp_perform(conn, &connected, done); - - return res; -} - -/* BLOCKING, but the function is using the state machine so the only reason - this is still blocking is that the multi interface code has no support for - disconnecting operations that takes a while */ -static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection) -{ - CURLcode result = CURLE_OK; - struct ssh_conn *ssh = &conn->proto.sshc; - (void) dead_connection; - - Curl_safefree(conn->data->state.proto.ssh); - conn->data->state.proto.ssh = NULL; - - if(ssh->ssh_session) { - /* only if there's a session still around to use! */ - - state(conn, SSH_SESSION_DISCONNECT); - - result = ssh_easy_statemach(conn, FALSE); - } - - return result; -} - -/* generic done function for both SCP and SFTP called from their specific - done functions */ -static CURLcode ssh_done(struct connectdata *conn, CURLcode status) -{ - CURLcode result = CURLE_OK; - struct SSHPROTO *sftp_scp = conn->data->state.proto.ssh; - - if(status == CURLE_OK) { - /* run the state-machine - - TODO: when the multi interface is used, this _really_ should be using - the ssh_multi_statemach function but we have no general support for - non-blocking DONE operations, not in the multi state machine and with - Curl_done() invokes on several places in the code! - */ - result = ssh_easy_statemach(conn, FALSE); - } - else - result = status; - - if(sftp_scp) { - Curl_safefree(sftp_scp->path); - sftp_scp->path = NULL; - } - Curl_pgrsDone(conn); - - conn->data->req.keepon = 0; /* clear all bits */ - return result; -} - - -static CURLcode scp_done(struct connectdata *conn, CURLcode status, - bool premature) -{ - (void)premature; /* not used */ - - if(status == CURLE_OK) - state(conn, SSH_SCP_DONE); - - return ssh_done(conn, status); - -} - -/* return number of received (decrypted) bytes */ -static ssize_t scp_send(struct connectdata *conn, int sockindex, - const void *mem, size_t len, CURLcode *err) -{ - ssize_t nwrite; - (void)sockindex; /* we only support SCP on the fixed known primary socket */ - - /* libssh2_channel_write() returns int! */ - nwrite = (ssize_t) - libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len); - - ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); - - if(nwrite == LIBSSH2_ERROR_EAGAIN) { - *err = CURLE_AGAIN; - nwrite = 0; - } - - return nwrite; -} - -/* - * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return - * a regular CURLcode value. - */ -static ssize_t scp_recv(struct connectdata *conn, int sockindex, - char *mem, size_t len, CURLcode *err) -{ - ssize_t nread; - (void)sockindex; /* we only support SCP on the fixed known primary socket */ - - /* libssh2_channel_read() returns int */ - nread = (ssize_t) - libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len); - - ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); - if (nread == LIBSSH2_ERROR_EAGAIN) { - *err = CURLE_AGAIN; - nread = -1; - } - - return nread; -} - -/* - * =============== SFTP =============== - */ - -/* - *********************************************************************** - * - * sftp_perform() - * - * This is the actual DO function for SFTP. Get a file/directory according to - * the options previously setup. - */ - -static -CURLcode sftp_perform(struct connectdata *conn, - bool *connected, - bool *dophase_done) -{ - CURLcode result = CURLE_OK; - - DEBUGF(infof(conn->data, "DO phase starts\n")); - - *dophase_done = FALSE; /* not done yet */ - - /* start the first command in the DO phase */ - state(conn, SSH_SFTP_QUOTE_INIT); - - /* run the state-machine */ - if(conn->data->state.used_interface == Curl_if_multi) { - result = ssh_multi_statemach(conn, dophase_done); - } - else { - result = ssh_easy_statemach(conn, FALSE); - *dophase_done = TRUE; /* with the easy interface we are done here */ - } - *connected = conn->bits.tcpconnect; - - if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); - } - - return result; -} - -/* called from multi.c while DOing */ -static CURLcode sftp_doing(struct connectdata *conn, - bool *dophase_done) -{ - CURLcode result; - result = ssh_multi_statemach(conn, dophase_done); - - if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); - } - return result; -} - -/* BLOCKING, but the function is using the state machine so the only reason - this is still blocking is that the multi interface code has no support for - disconnecting operations that takes a while */ -static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection) -{ - CURLcode result = CURLE_OK; - (void) dead_connection; - - DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n")); - - Curl_safefree(conn->data->state.proto.ssh); - conn->data->state.proto.ssh = NULL; - - if(conn->proto.sshc.ssh_session) { - /* only if there's a session still around to use! */ - state(conn, SSH_SFTP_SHUTDOWN); - result = ssh_easy_statemach(conn, FALSE); - } - - DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n")); - - return result; - -} - -static CURLcode sftp_done(struct connectdata *conn, CURLcode status, - bool premature) -{ - struct ssh_conn *sshc = &conn->proto.sshc; - - if(status == CURLE_OK) { - /* Post quote commands are executed after the SFTP_CLOSE state to avoid - errors that could happen due to open file handles during POSTQUOTE - operation */ - if(!status && !premature && conn->data->set.postquote) { - sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; - state(conn, SSH_SFTP_CLOSE); - } - else - state(conn, SSH_SFTP_CLOSE); - } - return ssh_done(conn, status); -} - -/* return number of sent bytes */ -static ssize_t sftp_send(struct connectdata *conn, int sockindex, - const void *mem, size_t len, CURLcode *err) -{ - ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14 - but is changed to ssize_t in 0.15. These days we don't - support libssh2 0.15*/ - (void)sockindex; - - nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len); - - ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); - - if(nwrite == LIBSSH2_ERROR_EAGAIN) { - *err = CURLE_AGAIN; - nwrite = 0; - } - - return nwrite; -} - -/* - * Return number of received (decrypted) bytes - */ -static ssize_t sftp_recv(struct connectdata *conn, int sockindex, - char *mem, size_t len, CURLcode *err) -{ - ssize_t nread; - (void)sockindex; - - nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len); - - ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); - - if(nread == LIBSSH2_ERROR_EAGAIN) { - *err = CURLE_AGAIN; - nread = -1; - } - return nread; -} - -/* The get_pathname() function is being borrowed from OpenSSH sftp.c - version 4.6p1. */ -/* - * Copyright (c) 2001-2004 Damien Miller - * - * 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); - *path = NULL; - return CURLE_QUOTE_ERROR; -} - - -static const char *sftp_libssh2_strerror(unsigned long err) -{ - switch (err) { - case LIBSSH2_FX_NO_SUCH_FILE: - return "No such file or directory"; - - case LIBSSH2_FX_PERMISSION_DENIED: - return "Permission denied"; - - case LIBSSH2_FX_FAILURE: - return "Operation failed"; - - case LIBSSH2_FX_BAD_MESSAGE: - return "Bad message from SFTP server"; - - case LIBSSH2_FX_NO_CONNECTION: - return "Not connected to SFTP server"; - - case LIBSSH2_FX_CONNECTION_LOST: - return "Connection to SFTP server lost"; - - case LIBSSH2_FX_OP_UNSUPPORTED: - return "Operation not supported by SFTP server"; - - case LIBSSH2_FX_INVALID_HANDLE: - return "Invalid handle"; - - case LIBSSH2_FX_NO_SUCH_PATH: - return "No such file or directory"; - - case LIBSSH2_FX_FILE_ALREADY_EXISTS: - return "File already exists"; - - case LIBSSH2_FX_WRITE_PROTECT: - return "File is write protected"; - - case LIBSSH2_FX_NO_MEDIA: - return "No media"; - - case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: - return "Disk full"; - - case LIBSSH2_FX_QUOTA_EXCEEDED: - return "User quota exceeded"; - - case LIBSSH2_FX_UNKNOWN_PRINCIPLE: - return "Unknown principle"; - - case LIBSSH2_FX_LOCK_CONFlICT: - return "File lock conflict"; - - case LIBSSH2_FX_DIR_NOT_EMPTY: - return "Directory not empty"; - - case LIBSSH2_FX_NOT_A_DIRECTORY: - return "Not a directory"; - - case LIBSSH2_FX_INVALID_FILENAME: - return "Invalid filename"; - - case LIBSSH2_FX_LINK_LOOP: - return "Link points to itself"; - } - return "Unknown error in libssh2"; -} - -#endif /* USE_LIBSSH2 */ diff --git a/third_party/curl/lib/ssh.h b/third_party/curl/lib/ssh.h deleted file mode 100644 index 406220cc4..000000000 --- a/third_party/curl/lib/ssh.h +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef HEADER_CURL_SSH_H -#define HEADER_CURL_SSH_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_LIBSSH2_H -#include -#include -#endif /* HAVE_LIBSSH2_H */ - -/**************************************************************************** - * SSH unique setup - ***************************************************************************/ -typedef enum { - SSH_NO_STATE = -1, /* Used for "nextState" so say there is none */ - SSH_STOP = 0, /* do nothing state, stops the state machine */ - - SSH_S_STARTUP, /* Session startup, First state in SSH-CONNECT */ - SSH_HOSTKEY, /* verify hostkey */ - SSH_AUTHLIST, - SSH_AUTH_PKEY_INIT, - SSH_AUTH_PKEY, - SSH_AUTH_PASS_INIT, - SSH_AUTH_PASS, - SSH_AUTH_HOST_INIT, - SSH_AUTH_HOST, - SSH_AUTH_KEY_INIT, - SSH_AUTH_KEY, - SSH_AUTH_DONE, - SSH_SFTP_INIT, - SSH_SFTP_REALPATH, /* Last state in SSH-CONNECT */ - - SSH_SFTP_QUOTE_INIT, /* First state in SFTP-DO */ - SSH_SFTP_POSTQUOTE_INIT, /* (Possibly) First state in SFTP-DONE */ - SSH_SFTP_QUOTE, - SSH_SFTP_NEXT_QUOTE, - SSH_SFTP_QUOTE_STAT, - SSH_SFTP_QUOTE_SETSTAT, - SSH_SFTP_QUOTE_SYMLINK, - SSH_SFTP_QUOTE_MKDIR, - SSH_SFTP_QUOTE_RENAME, - SSH_SFTP_QUOTE_RMDIR, - SSH_SFTP_QUOTE_UNLINK, - SSH_SFTP_TRANS_INIT, - SSH_SFTP_UPLOAD_INIT, - SSH_SFTP_CREATE_DIRS_INIT, - SSH_SFTP_CREATE_DIRS, - SSH_SFTP_CREATE_DIRS_MKDIR, - SSH_SFTP_READDIR_INIT, - SSH_SFTP_READDIR, - SSH_SFTP_READDIR_LINK, - SSH_SFTP_READDIR_BOTTOM, - SSH_SFTP_READDIR_DONE, - SSH_SFTP_DOWNLOAD_INIT, - SSH_SFTP_DOWNLOAD_STAT, /* Last state in SFTP-DO */ - SSH_SFTP_CLOSE, /* Last state in SFTP-DONE */ - SSH_SFTP_SHUTDOWN, /* First state in SFTP-DISCONNECT */ - SSH_SCP_TRANS_INIT, /* First state in SCP-DO */ - SSH_SCP_UPLOAD_INIT, - SSH_SCP_DOWNLOAD_INIT, - SSH_SCP_DONE, - SSH_SCP_SEND_EOF, - SSH_SCP_WAIT_EOF, - SSH_SCP_WAIT_CLOSE, - SSH_SCP_CHANNEL_FREE, /* Last state in SCP-DONE */ - SSH_SESSION_DISCONNECT, /* First state in SCP-DISCONNECT */ - SSH_SESSION_FREE, /* Last state in SCP/SFTP-DISCONNECT */ - SSH_QUIT, - SSH_LAST /* never used */ -} sshstate; - -/* this struct is used in the HandleData struct which is part of the - SessionHandle, which means this is used on a per-easy handle basis. - Everything that is strictly related to a connection is banned from this - struct. */ -struct SSHPROTO { - char *path; /* the path we operate on */ -}; - -/* ssh_conn is used for struct connection-oriented data in the connectdata - struct */ -struct ssh_conn { - const char *authlist; /* List of auth. methods, managed by libssh2 */ -#ifdef USE_LIBSSH2 - const char *passphrase; /* pass-phrase to use */ - char *rsa_pub; /* path name */ - char *rsa; /* path name */ - bool authed; /* the connection has been authenticated fine */ - sshstate state; /* always use ssh.c:state() to change state! */ - sshstate nextstate; /* the state to goto after stopping */ - CURLcode actualcode; /* the actual error code */ - struct curl_slist *quote_item; /* for the quote option */ - char *quote_path1; /* two generic pointers for the QUOTE stuff */ - char *quote_path2; - LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */ - char *homedir; /* when doing SFTP we figure out home dir in the - connect phase */ - - /* Here's a set of struct members used by the SFTP_READDIR state */ - LIBSSH2_SFTP_ATTRIBUTES readdir_attrs; - char *readdir_filename; - char *readdir_longentry; - int readdir_len, readdir_totalLen, readdir_currLen; - char *readdir_line; - char *readdir_linkPath; - /* end of READDIR stuff */ - - int secondCreateDirs; /* counter use by the code to see if the - second attempt has been made to change - to/create a directory */ - char *slash_pos; /* used by the SFTP_CREATE_DIRS state */ - LIBSSH2_SESSION *ssh_session; /* Secure Shell session */ - LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */ - LIBSSH2_SFTP *sftp_session; /* SFTP handle */ - LIBSSH2_SFTP_HANDLE *sftp_handle; - int orig_waitfor; /* default READ/WRITE bits wait for */ - - /* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h - header */ -#ifdef HAVE_LIBSSH2_KNOWNHOST_API - LIBSSH2_KNOWNHOSTS *kh; -#endif -#endif /* USE_LIBSSH2 */ -}; - -#ifdef USE_LIBSSH2 - -#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x001000) -# error "SCP/SFTP protocols require libssh2 0.16 or later" -#endif - -#if defined(LIBSSH2_VERSION_NUM) && (LIBSSH2_VERSION_NUM >= 0x010000) -# define HAVE_LIBSSH2_SFTP_SEEK64 1 -#else -# undef HAVE_LIBSSH2_SFTP_SEEK64 -#endif - -#if defined(LIBSSH2_VERSION_NUM) && (LIBSSH2_VERSION_NUM >= 0x010206) -# define HAVE_LIBSSH2_SCP_SEND64 1 -#else -# undef HAVE_LIBSSH2_SCP_SEND64 -#endif - - -extern const struct Curl_handler Curl_handler_scp; -extern const struct Curl_handler Curl_handler_sftp; - -#endif /* USE_LIBSSH2 */ - -#endif /* HEADER_CURL_SSH_H */ diff --git a/third_party/curl/lib/sslgen.c b/third_party/curl/lib/sslgen.c deleted file mode 100644 index a1b65ae74..000000000 --- a/third_party/curl/lib/sslgen.c +++ /dev/null @@ -1,481 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* This file is for implementing all "generic" SSL functions that all libcurl - internals should use. It is then responsible for calling the proper - "backend" function. - - SSL-functions in libcurl should call functions in this source file, and not - to any specific SSL-layer. - - Curl_ssl_ - prefix for generic ones - Curl_ossl_ - prefix for OpenSSL ones - Curl_gtls_ - prefix for GnuTLS ones - Curl_nss_ - prefix for NSS ones - Curl_polarssl_ - prefix for PolarSSL ones - Curl_cyassl_ - prefix for CyaSSL ones - - Note that this source code uses curlssl_* functions, and they are all - defines/macros #defined by the lib-specific header files. - - "SSL/TLS Strong Encryption: An Introduction" - http://httpd.apache.org/docs-2.0/ssl/ssl_intro.html -*/ - -#include "setup.h" - -#include -#include -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#include "urldata.h" -#define SSLGEN_C -#include "sslgen.h" /* generic SSL protos etc */ -#include "ssluse.h" /* OpenSSL versions */ -#include "gtls.h" /* GnuTLS versions */ -#include "nssg.h" /* NSS versions */ -#include "qssl.h" /* QSOSSL versions */ -#include "polarssl.h" /* PolarSSL versions */ -#include "axtls.h" /* axTLS versions */ -#include "cyassl.h" /* CyaSSL versions */ -#include "sendf.h" -#include "rawstr.h" -#include "url.h" -#include "curl_memory.h" -#include "progress.h" -/* The last #include file should be: */ -#include "memdebug.h" - -static bool safe_strequal(char* str1, char* str2) -{ - if(str1 && str2) - /* both pointers point to something then compare them */ - return (bool)(0 != Curl_raw_equal(str1, str2)); - else - /* if both pointers are NULL then treat them as equal */ - return (bool)(!str1 && !str2); -} - -bool -Curl_ssl_config_matches(struct ssl_config_data* data, - struct ssl_config_data* needle) -{ - if((data->version == needle->version) && - (data->verifypeer == needle->verifypeer) && - (data->verifyhost == needle->verifyhost) && - safe_strequal(data->CApath, needle->CApath) && - safe_strequal(data->CAfile, needle->CAfile) && - safe_strequal(data->random_file, needle->random_file) && - safe_strequal(data->egdsocket, needle->egdsocket) && - safe_strequal(data->cipher_list, needle->cipher_list)) - return TRUE; - - return FALSE; -} - -bool -Curl_clone_ssl_config(struct ssl_config_data *source, - struct ssl_config_data *dest) -{ - dest->sessionid = source->sessionid; - dest->verifyhost = source->verifyhost; - dest->verifypeer = source->verifypeer; - dest->version = source->version; - - if(source->CAfile) { - dest->CAfile = strdup(source->CAfile); - if(!dest->CAfile) - return FALSE; - } - else - dest->CAfile = NULL; - - if(source->CApath) { - dest->CApath = strdup(source->CApath); - if(!dest->CApath) - return FALSE; - } - else - dest->CApath = NULL; - - if(source->cipher_list) { - dest->cipher_list = strdup(source->cipher_list); - if(!dest->cipher_list) - return FALSE; - } - else - dest->cipher_list = NULL; - - if(source->egdsocket) { - dest->egdsocket = strdup(source->egdsocket); - if(!dest->egdsocket) - return FALSE; - } - else - dest->egdsocket = NULL; - - if(source->random_file) { - dest->random_file = strdup(source->random_file); - if(!dest->random_file) - return FALSE; - } - else - dest->random_file = NULL; - - return TRUE; -} - -void Curl_free_ssl_config(struct ssl_config_data* sslc) -{ - Curl_safefree(sslc->CAfile); - Curl_safefree(sslc->CApath); - Curl_safefree(sslc->cipher_list); - Curl_safefree(sslc->egdsocket); - Curl_safefree(sslc->random_file); -} - -#ifdef USE_SSL - -/* "global" init done? */ -static bool init_ssl=FALSE; - -/** - * Global SSL init - * - * @retval 0 error initializing SSL - * @retval 1 SSL initialized successfully - */ -int Curl_ssl_init(void) -{ - /* make sure this is only done once */ - if(init_ssl) - return 1; - init_ssl = TRUE; /* never again */ - - return curlssl_init(); -} - - -/* Global cleanup */ -void Curl_ssl_cleanup(void) -{ - if(init_ssl) { - /* only cleanup if we did a previous init */ - curlssl_cleanup(); - init_ssl = FALSE; - } -} - -CURLcode -Curl_ssl_connect(struct connectdata *conn, int sockindex) -{ - CURLcode res; - /* mark this is being ssl-enabled from here on. */ - conn->ssl[sockindex].use = TRUE; - conn->ssl[sockindex].state = ssl_connection_negotiating; - - res = curlssl_connect(conn, sockindex); - - if(!res) - Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ - - return res; -} - -CURLcode -Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, - bool *done) -{ -#ifdef curlssl_connect_nonblocking - CURLcode res; - /* mark this is being ssl requested from here on. */ - conn->ssl[sockindex].use = TRUE; - res = curlssl_connect_nonblocking(conn, sockindex, done); - if(!res && *done == TRUE) - Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ - return res; -#else - *done = TRUE; /* fallback to BLOCKING */ - conn->ssl[sockindex].use = TRUE; - return curlssl_connect(conn, sockindex); -#endif /* non-blocking connect support */ -} - -/* - * Check if there's a session ID for the given connection in the cache, and if - * there's one suitable, it is provided. Returns TRUE when no entry matched. - */ -int Curl_ssl_getsessionid(struct connectdata *conn, - void **ssl_sessionid, - size_t *idsize) /* set 0 if unknown */ -{ - struct curl_ssl_session *check; - struct SessionHandle *data = conn->data; - long i; - - if(!conn->ssl_config.sessionid) - /* session ID re-use is disabled */ - return TRUE; - - for(i=0; i< data->set.ssl.numsessions; i++) { - check = &data->state.session[i]; - if(!check->sessionid) - /* not session ID means blank entry */ - continue; - if(Curl_raw_equal(conn->host.name, check->name) && - (conn->remote_port == check->remote_port) && - Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) { - /* yes, we have a session ID! */ - data->state.sessionage++; /* increase general age */ - check->age = data->state.sessionage; /* set this as used in this age */ - *ssl_sessionid = check->sessionid; - if(idsize) - *idsize = check->idsize; - return FALSE; - } - } - *ssl_sessionid = NULL; - return TRUE; -} - -/* - * Kill a single session ID entry in the cache. - */ -static int kill_session(struct curl_ssl_session *session) -{ - if(session->sessionid) { - /* defensive check */ - - /* free the ID the SSL-layer specific way */ - curlssl_session_free(session->sessionid); - - session->sessionid=NULL; - session->age = 0; /* fresh */ - - Curl_free_ssl_config(&session->ssl_config); - - Curl_safefree(session->name); - session->name = NULL; /* no name */ - - return 0; /* ok */ - } - else - return 1; -} - -/* - * Delete the given session ID from the cache. - */ -void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) -{ - int i; - for(i=0; i< conn->data->set.ssl.numsessions; i++) { - struct curl_ssl_session *check = &conn->data->state.session[i]; - - if (check->sessionid == ssl_sessionid) { - kill_session(check); - break; - } - } -} - -/* - * Store session id in the session cache. The ID passed on to this function - * must already have been extracted and allocated the proper way for the SSL - * layer. Curl_XXXX_session_free() will be called to free/kill the session ID - * later on. - */ -CURLcode Curl_ssl_addsessionid(struct connectdata *conn, - void *ssl_sessionid, - size_t idsize) -{ - long i; - struct SessionHandle *data=conn->data; /* the mother of all structs */ - struct curl_ssl_session *store = &data->state.session[0]; - long oldest_age=data->state.session[0].age; /* zero if unused */ - char *clone_host; - - /* Even though session ID re-use might be disabled, that only disables USING - IT. We still store it here in case the re-using is again enabled for an - upcoming transfer */ - - clone_host = strdup(conn->host.name); - if(!clone_host) - return CURLE_OUT_OF_MEMORY; /* bail out */ - - /* Now we should add the session ID and the host name to the cache, (remove - the oldest if necessary) */ - - /* find an empty slot for us, or find the oldest */ - for(i=1; (iset.ssl.numsessions) && - data->state.session[i].sessionid; i++) { - if(data->state.session[i].age < oldest_age) { - oldest_age = data->state.session[i].age; - store = &data->state.session[i]; - } - } - if(i == data->set.ssl.numsessions) - /* cache is full, we must "kill" the oldest entry! */ - kill_session(store); - else - store = &data->state.session[i]; /* use this slot */ - - /* now init the session struct wisely */ - store->sessionid = ssl_sessionid; - store->idsize = idsize; - store->age = data->state.sessionage; /* set current age */ - if (store->name) - /* free it if there's one already present */ - free(store->name); - store->name = clone_host; /* clone host name */ - store->remote_port = conn->remote_port; /* port number */ - - if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) { - store->sessionid = NULL; /* let caller free sessionid */ - free(clone_host); - return CURLE_OUT_OF_MEMORY; - } - - return CURLE_OK; -} - - -void Curl_ssl_close_all(struct SessionHandle *data) -{ - long i; - /* kill the session ID cache */ - if(data->state.session) { - for(i=0; i< data->set.ssl.numsessions; i++) - /* the single-killer function handles empty table slots */ - kill_session(&data->state.session[i]); - - /* free the cache data */ - free(data->state.session); - data->state.session = NULL; - } - - curlssl_close_all(data); -} - -void Curl_ssl_close(struct connectdata *conn, int sockindex) -{ - DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); - curlssl_close(conn, sockindex); -} - -CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) -{ - if(curlssl_shutdown(conn, sockindex)) - return CURLE_SSL_SHUTDOWN_FAILED; - - conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ - conn->ssl[sockindex].state = ssl_connection_none; - - conn->recv[sockindex] = Curl_recv_plain; - conn->send[sockindex] = Curl_send_plain; - - return CURLE_OK; -} - -/* Selects an SSL crypto engine - */ -CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine) -{ - return curlssl_set_engine(data, engine); -} - -/* Selects the default SSL crypto engine - */ -CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data) -{ - return curlssl_set_engine_default(data); -} - -/* Return list of OpenSSL crypto engine names. */ -struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data) -{ - return curlssl_engines_list(data); -} - -/* - * This sets up a session ID cache to the specified size. Make sure this code - * is agnostic to what underlying SSL technology we use. - */ -CURLcode Curl_ssl_initsessions(struct SessionHandle *data, long amount) -{ - struct curl_ssl_session *session; - - if(data->state.session) - /* this is just a precaution to prevent multiple inits */ - return CURLE_OK; - - session = calloc(amount, sizeof(struct curl_ssl_session)); - if(!session) - return CURLE_OUT_OF_MEMORY; - - /* store the info in the SSL section */ - data->set.ssl.numsessions = amount; - data->state.session = session; - data->state.sessionage = 1; /* this is brand new */ - return CURLE_OK; -} - -size_t Curl_ssl_version(char *buffer, size_t size) -{ - return curlssl_version(buffer, size); -} - -/* - * This function tries to determine connection status. - * - * Return codes: - * 1 means the connection is still in place - * 0 means the connection has been closed - * -1 means the connection status is unknown - */ -int Curl_ssl_check_cxn(struct connectdata *conn) -{ - return curlssl_check_cxn(conn); -} - -bool Curl_ssl_data_pending(const struct connectdata *conn, - int connindex) -{ - return curlssl_data_pending(conn, connindex); -} - -void Curl_ssl_free_certinfo(struct SessionHandle *data) -{ - int i; - struct curl_certinfo *ci = &data->info.certs; - if(ci->num_of_certs) { - /* free all individual lists used */ - for(i=0; inum_of_certs; i++) - curl_slist_free_all(ci->certinfo[i]); - free(ci->certinfo); /* free the actual array too */ - ci->num_of_certs = 0; - } -} -#endif /* USE_SSL */ diff --git a/third_party/curl/lib/sslgen.h b/third_party/curl/lib/sslgen.h deleted file mode 100644 index b0a0fab12..000000000 --- a/third_party/curl/lib/sslgen.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef __SSLGEN_H -#define __SSLGEN_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -bool Curl_ssl_config_matches(struct ssl_config_data* data, - struct ssl_config_data* needle); -bool Curl_clone_ssl_config(struct ssl_config_data* source, - struct ssl_config_data* dest); -void Curl_free_ssl_config(struct ssl_config_data* sslc); - -#ifdef USE_SSL -int Curl_ssl_init(void); -void Curl_ssl_cleanup(void); -CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex); -CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn, - int sockindex, - bool *done); -/* tell the SSL stuff to close down all open information regarding - connections (and thus session ID caching etc) */ -void Curl_ssl_close_all(struct SessionHandle *data); -void Curl_ssl_close(struct connectdata *conn, int sockindex); -CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex); -CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine); -/* Sets engine as default for all SSL operations */ -CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data); -struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data); - -/* init the SSL session ID cache */ -CURLcode Curl_ssl_initsessions(struct SessionHandle *, long); -size_t Curl_ssl_version(char *buffer, size_t size); -bool Curl_ssl_data_pending(const struct connectdata *conn, - int connindex); -int Curl_ssl_check_cxn(struct connectdata *conn); -void Curl_ssl_free_certinfo(struct SessionHandle *data); - -/* Functions to be used by SSL library adaptation functions */ - -/* extract a session ID */ -int Curl_ssl_getsessionid(struct connectdata *conn, - void **ssl_sessionid, - size_t *idsize) /* set 0 if unknown */; -/* add a new session ID */ -CURLcode Curl_ssl_addsessionid(struct connectdata *conn, - void *ssl_sessionid, - size_t idsize); -/* delete a session from the cache */ -void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); - -#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ - -#else -/* When SSL support is not present, just define away these function calls */ -#define Curl_ssl_init() 1 -#define Curl_ssl_cleanup() do { } while (0) -#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN -#define Curl_ssl_close_all(x) -#define Curl_ssl_close(x,y) -#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN -#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN -#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN -#define Curl_ssl_engines_list(x) NULL -#define Curl_ssl_send(a,b,c,d,e) -1 -#define Curl_ssl_recv(a,b,c,d,e) -1 -#define Curl_ssl_initsessions(x,y) CURLE_OK -#define Curl_ssl_version(x,y) 0 -#define Curl_ssl_data_pending(x,y) 0 -#define Curl_ssl_check_cxn(x) 0 -#define Curl_ssl_free_certinfo(x) -#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN -#endif - -#endif /* USE_SSL */ diff --git a/third_party/curl/lib/ssluse.c b/third_party/curl/lib/ssluse.c deleted file mode 100644 index 1b53f2589..000000000 --- a/third_party/curl/lib/ssluse.c +++ /dev/null @@ -1,2719 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * Source file for all OpenSSL-specific code for the TLS/SSL layer. No code - * but sslgen.c should ever call or use these functions. - */ - -/* - * The original SSLeay-using code for curl was written by Linas Vepstas and - * Sampo Kellomaki 1998. - */ - -#include "setup.h" - -#include -#include -#include -#ifdef HAVE_LIMITS_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif - -#include "urldata.h" -#include "sendf.h" -#include "formdata.h" /* for the boundary function */ -#include "url.h" /* for the ssl config check function */ -#include "inet_pton.h" -#include "ssluse.h" -#include "connect.h" -#include "strequal.h" -#include "select.h" -#include "sslgen.h" -#include "rawstr.h" - -#define _MPRINTF_REPLACE /* use the internal *printf() functions */ -#include - -#ifdef USE_SSLEAY - -#ifdef USE_OPENSSL -#include -#include -#include -#include -#include -#else -#include -#include -#endif - -#include "curl_memory.h" -#include "non-ascii.h" /* for Curl_convert_from_utf8 prototype */ - -/* The last #include file should be: */ -#include "memdebug.h" - -#if OPENSSL_VERSION_NUMBER >= 0x0090581fL -#define HAVE_SSL_GET1_SESSION 1 -#else -#undef HAVE_SSL_GET1_SESSION -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x00904100L -#define HAVE_USERDATA_IN_PWD_CALLBACK 1 -#else -#undef HAVE_USERDATA_IN_PWD_CALLBACK -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x00907001L -/* ENGINE_load_private_key() takes four arguments */ -#define HAVE_ENGINE_LOAD_FOUR_ARGS -#include -#else -/* ENGINE_load_private_key() takes three arguments */ -#undef HAVE_ENGINE_LOAD_FOUR_ARGS -#endif - -#if (OPENSSL_VERSION_NUMBER >= 0x00903001L) && defined(HAVE_OPENSSL_PKCS12_H) -/* OpenSSL has PKCS 12 support */ -#define HAVE_PKCS12_SUPPORT -#else -/* OpenSSL/SSLEay does not have PKCS12 support */ -#undef HAVE_PKCS12_SUPPORT -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x00906001L -#define HAVE_ERR_ERROR_STRING_N 1 -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x00909000L -#define SSL_METHOD_QUAL const -#else -#define SSL_METHOD_QUAL -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x00907000L -/* 0.9.6 didn't have X509_STORE_set_flags() */ -#define HAVE_X509_STORE_SET_FLAGS 1 -#else -#define X509_STORE_set_flags(x,y) -#endif - -/* - * Number of bytes to read from the random number seed file. This must be - * a finite value (because some entropy "files" like /dev/urandom have - * an infinite length), but must be large enough to provide enough - * entopy to properly seed OpenSSL's PRNG. - */ -#define RAND_LOAD_LENGTH 1024 - -#ifndef HAVE_USERDATA_IN_PWD_CALLBACK -static char global_passwd[64]; -#endif - -static int passwd_callback(char *buf, int num, int verify -#ifdef HAVE_USERDATA_IN_PWD_CALLBACK - /* This was introduced in 0.9.4, we can set this - using SSL_CTX_set_default_passwd_cb_userdata() - */ - , void *global_passwd -#endif - ) -{ - if(verify) - fprintf(stderr, "%s\n", buf); - else { - if(num > (int)strlen((char *)global_passwd)) { - strcpy(buf, global_passwd); - return (int)strlen(buf); - } - } - return 0; -} - -/* - * rand_enough() is a function that returns TRUE if we have seeded the random - * engine properly. We use some preprocessor magic to provide a seed_enough() - * macro to use, just to prevent a compiler warning on this function if we - * pass in an argument that is never used. - */ - -#ifdef HAVE_RAND_STATUS -#define seed_enough(x) rand_enough() -static bool rand_enough(void) -{ - return (bool)(0 != RAND_status()); -} -#else -#define seed_enough(x) rand_enough(x) -static bool rand_enough(int nread) -{ - /* this is a very silly decision to make */ - return (bool)(nread > 500); -} -#endif - -static int ossl_seed(struct SessionHandle *data) -{ - char *buf = data->state.buffer; /* point to the big buffer */ - int nread=0; - - /* Q: should we add support for a random file name as a libcurl option? - A: Yes, it is here */ - -#ifndef RANDOM_FILE - /* if RANDOM_FILE isn't defined, we only perform this if an option tells - us to! */ - if(data->set.ssl.random_file) -#define RANDOM_FILE "" /* doesn't matter won't be used */ -#endif - { - /* let the option override the define */ - nread += RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]? - data->set.str[STRING_SSL_RANDOM_FILE]: - RANDOM_FILE), - RAND_LOAD_LENGTH); - if(seed_enough(nread)) - return nread; - } - -#if defined(HAVE_RAND_EGD) - /* only available in OpenSSL 0.9.5 and later */ - /* EGD_SOCKET is set at configure time or not at all */ -#ifndef EGD_SOCKET - /* If we don't have the define set, we only do this if the egd-option - is set */ - if(data->set.str[STRING_SSL_EGDSOCKET]) -#define EGD_SOCKET "" /* doesn't matter won't be used */ -#endif - { - /* If there's an option and a define, the option overrides the - define */ - int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]? - data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET); - if(-1 != ret) { - nread += ret; - if(seed_enough(nread)) - return nread; - } - } -#endif - - /* If we get here, it means we need to seed the PRNG using a "silly" - approach! */ -#ifdef HAVE_RAND_SCREEN - /* if RAND_screen() is present, this is windows and thus we assume that the - randomness is already taken care of */ - nread = 100; /* just a value */ -#else - { - int len; - char *area; - - /* Changed call to RAND_seed to use the underlying RAND_add implementation - * directly. Do this in a loop, with the amount of additional entropy - * being dependent upon the algorithm used by Curl_FormBoundary(): N bytes - * of a 7-bit ascii set. -- Richard Gorton, March 11 2003. - */ - - do { - area = Curl_FormBoundary(); - if(!area) - return 3; /* out of memory */ - - len = (int)strlen(area); - RAND_add(area, len, (len >> 1)); - - free(area); /* now remove the random junk */ - } while(!RAND_status()); - } -#endif - - /* generates a default path for the random seed file */ - buf[0]=0; /* blank it first */ - RAND_file_name(buf, BUFSIZE); - if(buf[0]) { - /* we got a file name to try */ - nread += RAND_load_file(buf, RAND_LOAD_LENGTH); - if(seed_enough(nread)) - return nread; - } - - infof(data, "libcurl is now using a weak random seed!\n"); - return nread; -} - -int Curl_ossl_seed(struct SessionHandle *data) -{ - /* we have the "SSL is seeded" boolean static to prevent multiple - time-consuming seedings in vain */ - static bool ssl_seeded = FALSE; - - if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || - data->set.str[STRING_SSL_EGDSOCKET]) { - ossl_seed(data); - ssl_seeded = TRUE; - } - return 0; -} - - -#ifndef SSL_FILETYPE_ENGINE -#define SSL_FILETYPE_ENGINE 42 -#endif -#ifndef SSL_FILETYPE_PKCS12 -#define SSL_FILETYPE_PKCS12 43 -#endif -static int do_file_type(const char *type) -{ - if(!type || !type[0]) - return SSL_FILETYPE_PEM; - if(Curl_raw_equal(type, "PEM")) - return SSL_FILETYPE_PEM; - if(Curl_raw_equal(type, "DER")) - return SSL_FILETYPE_ASN1; - if(Curl_raw_equal(type, "ENG")) - return SSL_FILETYPE_ENGINE; - if(Curl_raw_equal(type, "P12")) - return SSL_FILETYPE_PKCS12; - return -1; -} - -static -int cert_stuff(struct connectdata *conn, - SSL_CTX* ctx, - char *cert_file, - const char *cert_type, - char *key_file, - const char *key_type) -{ - struct SessionHandle *data = conn->data; - - int file_type = do_file_type(cert_type); - - if(cert_file != NULL || file_type == SSL_FILETYPE_ENGINE) { - SSL *ssl; - X509 *x509; - int cert_done = 0; - - if(data->set.str[STRING_KEY_PASSWD]) { -#ifndef HAVE_USERDATA_IN_PWD_CALLBACK - /* - * If password has been given, we store that in the global - * area (*shudder*) for a while: - */ - size_t len = strlen(data->set.str[STRING_KEY_PASSWD]); - if(len < sizeof(global_passwd)) - memcpy(global_passwd, data->set.str[STRING_KEY_PASSWD], len+1); -#else - /* - * We set the password in the callback userdata - */ - SSL_CTX_set_default_passwd_cb_userdata(ctx, - data->set.str[STRING_KEY_PASSWD]); -#endif - /* Set passwd callback: */ - SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); - } - - -#define SSL_CLIENT_CERT_ERR \ - "unable to use client certificate (no key found or wrong pass phrase?)" - - switch(file_type) { - case SSL_FILETYPE_PEM: - /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ - if(SSL_CTX_use_certificate_chain_file(ctx, - cert_file) != 1) { - failf(data, SSL_CLIENT_CERT_ERR); - return 0; - } - break; - - case SSL_FILETYPE_ASN1: - /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but - we use the case above for PEM so this can only be performed with - ASN1 files. */ - if(SSL_CTX_use_certificate_file(ctx, - cert_file, - file_type) != 1) { - failf(data, SSL_CLIENT_CERT_ERR); - return 0; - } - break; - case SSL_FILETYPE_ENGINE: -#if defined(HAVE_OPENSSL_ENGINE_H) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME) - { - if(data->state.engine) { - const char *cmd_name = "LOAD_CERT_CTRL"; - struct { - const char *cert_id; - X509 *cert; - } params; - - params.cert_id = cert_file; - params.cert = NULL; - - /* Does the engine supports LOAD_CERT_CTRL ? */ - if (!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME, - 0, (void *)cmd_name, NULL)) { - failf(data, "ssl engine does not support loading certificates"); - return 0; - } - - /* Load the certificate from the engine */ - if (!ENGINE_ctrl_cmd(data->state.engine, cmd_name, - 0, ¶ms, NULL, 1)) { - failf(data, "ssl engine cannot load client cert with id" - " '%s' [%s]", cert_file, - ERR_error_string(ERR_get_error(), NULL)); - return 0; - } - - if (!params.cert) { - failf(data, "ssl engine didn't initialized the certificate " - "properly."); - return 0; - } - - if(SSL_CTX_use_certificate(ctx, params.cert) != 1) { - failf(data, "unable to set client certificate"); - X509_free(params.cert); - return 0; - } - X509_free(params.cert); /* we don't need the handle any more... */ - } - else { - failf(data, "crypto engine not set, can't load certificate"); - return 0; - } - } - break; -#else - failf(data, "file type ENG for certificate not implemented"); - return 0; -#endif - - case SSL_FILETYPE_PKCS12: - { -#ifdef HAVE_PKCS12_SUPPORT - FILE *f; - PKCS12 *p12; - EVP_PKEY *pri; - STACK_OF(X509) *ca = NULL; - int i; - - f = fopen(cert_file,"rb"); - if(!f) { - failf(data, "could not open PKCS12 file '%s'", cert_file); - return 0; - } - p12 = d2i_PKCS12_fp(f, NULL); - fclose(f); - - if(!p12) { - failf(data, "error reading PKCS12 file '%s'", cert_file ); - return 0; - } - - PKCS12_PBE_add(); - - if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509, - &ca)) { - failf(data, - "could not parse PKCS12 file, check password, OpenSSL error %s", - ERR_error_string(ERR_get_error(), NULL) ); - PKCS12_free(p12); - return 0; - } - - PKCS12_free(p12); - - if(SSL_CTX_use_certificate(ctx, x509) != 1) { - failf(data, SSL_CLIENT_CERT_ERR); - EVP_PKEY_free(pri); - X509_free(x509); - return 0; - } - - if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) { - failf(data, "unable to use private key from PKCS12 file '%s'", - cert_file); - EVP_PKEY_free(pri); - X509_free(x509); - return 0; - } - - if (!SSL_CTX_check_private_key (ctx)) { - failf(data, "private key from PKCS12 file '%s' " - "does not match certificate in same file", cert_file); - EVP_PKEY_free(pri); - X509_free(x509); - return 0; - } - /* Set Certificate Verification chain */ - if (ca && sk_X509_num(ca)) { - for (i = 0; i < sk_X509_num(ca); i++) { - if (!SSL_CTX_add_extra_chain_cert(ctx,sk_X509_value(ca, i))) { - failf(data, "cannot add certificate to certificate chain"); - EVP_PKEY_free(pri); - X509_free(x509); - return 0; - } - if (!SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i))) { - failf(data, "cannot add certificate to client CA list"); - EVP_PKEY_free(pri); - X509_free(x509); - return 0; - } - } - } - - EVP_PKEY_free(pri); - X509_free(x509); - cert_done = 1; - break; -#else - failf(data, "file type P12 for certificate not supported"); - return 0; -#endif - } - default: - failf(data, "not supported file type '%s' for certificate", cert_type); - return 0; - } - - file_type = do_file_type(key_type); - - switch(file_type) { - case SSL_FILETYPE_PEM: - if(cert_done) - break; - if(key_file == NULL) - /* cert & key can only be in PEM case in the same file */ - key_file=cert_file; - case SSL_FILETYPE_ASN1: - if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { - failf(data, "unable to set private key file: '%s' type %s", - key_file, key_type?key_type:"PEM"); - return 0; - } - break; - case SSL_FILETYPE_ENGINE: -#ifdef HAVE_OPENSSL_ENGINE_H - { /* XXXX still needs some work */ - EVP_PKEY *priv_key = NULL; - if(data->state.engine) { -#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS - UI_METHOD *ui_method = UI_OpenSSL(); -#endif - /* the typecast below was added to please mingw32 */ - priv_key = (EVP_PKEY *) - ENGINE_load_private_key(data->state.engine,key_file, -#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS - ui_method, -#endif - data->set.str[STRING_KEY_PASSWD]); - if(!priv_key) { - failf(data, "failed to load private key from crypto engine"); - return 0; - } - if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) { - failf(data, "unable to set private key"); - EVP_PKEY_free(priv_key); - return 0; - } - EVP_PKEY_free(priv_key); /* we don't need the handle any more... */ - } - else { - failf(data, "crypto engine not set, can't load private key"); - return 0; - } - } - break; -#else - failf(data, "file type ENG for private key not supported"); - return 0; -#endif - case SSL_FILETYPE_PKCS12: - if(!cert_done) { - failf(data, "file type P12 for private key not supported"); - return 0; - } - break; - default: - failf(data, "not supported file type for private key"); - return 0; - } - - ssl=SSL_new(ctx); - if(NULL == ssl) { - failf(data,"unable to create an SSL structure"); - return 0; - } - - x509=SSL_get_certificate(ssl); - - /* This version was provided by Evan Jordan and is supposed to not - leak memory as the previous version: */ - if(x509 != NULL) { - EVP_PKEY *pktmp = X509_get_pubkey(x509); - EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(ssl)); - EVP_PKEY_free(pktmp); - } - - SSL_free(ssl); - - /* If we are using DSA, we can copy the parameters from - * the private key */ - - - /* Now we know that a key and cert have been set against - * the SSL context */ - if(!SSL_CTX_check_private_key(ctx)) { - failf(data, "Private key does not match the certificate public key"); - return 0; - } -#ifndef HAVE_USERDATA_IN_PWD_CALLBACK - /* erase it now */ - memset(global_passwd, 0, sizeof(global_passwd)); -#endif - } - return 1; -} - -/* returns non-zero on failure */ -static int x509_name_oneline(X509_NAME *a, char *buf, size_t size) -{ -#if 0 - return X509_NAME_oneline(a, buf, size); -#else - BIO *bio_out = BIO_new(BIO_s_mem()); - BUF_MEM *biomem; - int rc; - - if(!bio_out) - return 1; /* alloc failed! */ - - rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC); - BIO_get_mem_ptr(bio_out, &biomem); - - if((size_t)biomem->length < size) - size = biomem->length; - else - size--; /* don't overwrite the buffer end */ - - memcpy(buf, biomem->data, size); - buf[size]=0; - - BIO_free(bio_out); - - return !rc; -#endif -} - -static -int cert_verify_callback(int ok, X509_STORE_CTX *ctx) -{ - X509 *err_cert; - char buf[256]; - - err_cert=X509_STORE_CTX_get_current_cert(ctx); - (void)x509_name_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); - return ok; -} - -/* Return error string for last OpenSSL error - */ -static char *SSL_strerror(unsigned long error, char *buf, size_t size) -{ -#ifdef HAVE_ERR_ERROR_STRING_N - /* OpenSSL 0.9.6 and later has a function named - ERRO_error_string_n() that takes the size of the buffer as a - third argument */ - ERR_error_string_n(error, buf, size); -#else - (void) size; - ERR_error_string(error, buf); -#endif - return buf; -} - -#endif /* USE_SSLEAY */ - -#ifdef USE_SSLEAY -/** - * Global SSL init - * - * @retval 0 error initializing SSL - * @retval 1 SSL initialized successfully - */ -int Curl_ossl_init(void) -{ -#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES - ENGINE_load_builtin_engines(); -#endif - - /* Lets get nice error messages */ - SSL_load_error_strings(); - - /* Init the global ciphers and digests */ - if(!SSLeay_add_ssl_algorithms()) - return 0; - - OpenSSL_add_all_algorithms(); - - return 1; -} - -#endif /* USE_SSLEAY */ - -#ifdef USE_SSLEAY - -/* Global cleanup */ -void Curl_ossl_cleanup(void) -{ - /* Free the SSL error strings */ - ERR_free_strings(); - - /* EVP_cleanup() removes all ciphers and digests from the table. */ - EVP_cleanup(); - -#ifdef HAVE_ENGINE_CLEANUP - ENGINE_cleanup(); -#endif - -#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA - /* this function was not present in 0.9.6b, but was added sometimes - later */ - CRYPTO_cleanup_all_ex_data(); -#endif -} - -/* - * This function uses SSL_peek to determine connection status. - * - * Return codes: - * 1 means the connection is still in place - * 0 means the connection has been closed - * -1 means the connection status is unknown - */ -int Curl_ossl_check_cxn(struct connectdata *conn) -{ - int rc; - char buf; - - rc = SSL_peek(conn->ssl[FIRSTSOCKET].handle, (void*)&buf, 1); - if(rc > 0) - return 1; /* connection still in place */ - - if(rc == 0) - return 0; /* connection has been closed */ - - return -1; /* connection status unknown */ -} - -/* Selects an OpenSSL crypto engine - */ -CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine) -{ -#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H) - ENGINE *e; - -#if OPENSSL_VERSION_NUMBER >= 0x00909000L - e = ENGINE_by_id(engine); -#else - /* avoid memory leak */ - for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { - const char *e_id = ENGINE_get_id(e); - if(!strcmp(engine, e_id)) - break; - } -#endif - - if(!e) { - failf(data, "SSL Engine '%s' not found", engine); - return CURLE_SSL_ENGINE_NOTFOUND; - } - - if(data->state.engine) { - ENGINE_finish(data->state.engine); - ENGINE_free(data->state.engine); - data->state.engine = NULL; - } - if(!ENGINE_init(e)) { - char buf[256]; - - ENGINE_free(e); - failf(data, "Failed to initialise SSL Engine '%s':\n%s", - engine, SSL_strerror(ERR_get_error(), buf, sizeof(buf))); - return CURLE_SSL_ENGINE_INITFAILED; - } - data->state.engine = e; - return CURLE_OK; -#else - (void)engine; - failf(data, "SSL Engine not supported"); - return CURLE_SSL_ENGINE_NOTFOUND; -#endif -} - -/* Sets engine as default for all SSL operations - */ -CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data) -{ -#ifdef HAVE_OPENSSL_ENGINE_H - if(data->state.engine) { - if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) { - infof(data,"set default crypto engine '%s'\n", ENGINE_get_id(data->state.engine)); - } - else { - failf(data, "set default crypto engine '%s' failed", ENGINE_get_id(data->state.engine)); - return CURLE_SSL_ENGINE_SETFAILED; - } - } -#else - (void) data; -#endif - return CURLE_OK; -} - -/* Return list of OpenSSL crypto engine names. - */ -struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data) -{ - struct curl_slist *list = NULL; -#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H) - struct curl_slist *beg = NULL; - ENGINE *e; - - for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { - list = curl_slist_append(list, ENGINE_get_id(e)); - if(list == NULL) { - curl_slist_free_all(beg); - return NULL; - } - else if(beg == NULL) { - beg = list; - } - } -#endif - (void) data; - return list; -} - - -/* - * This function is called when an SSL connection is closed. - */ -void Curl_ossl_close(struct connectdata *conn, int sockindex) -{ - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - if(connssl->handle) { - (void)SSL_shutdown(connssl->handle); - SSL_set_connect_state(connssl->handle); - - SSL_free (connssl->handle); - connssl->handle = NULL; - } - if(connssl->ctx) { - SSL_CTX_free (connssl->ctx); - connssl->ctx = NULL; - } -} - -/* - * This function is called to shut down the SSL layer but keep the - * socket open (CCC - Clear Command Channel) - */ -int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) -{ - int retval = 0; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - struct SessionHandle *data = conn->data; - char buf[120]; /* We will use this for the OpenSSL error buffer, so it has - to be at least 120 bytes long. */ - unsigned long sslerror; - ssize_t nread; - int buffsize; - int err; - int done = 0; - - /* This has only been tested on the proftpd server, and the mod_tls code - sends a close notify alert without waiting for a close notify alert in - response. Thus we wait for a close notify alert from the server, but - we do not send one. Let's hope other servers do the same... */ - - if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) - (void)SSL_shutdown(connssl->handle); - - if(connssl->handle) { - buffsize = (int)sizeof(buf); - while(!done) { - int what = Curl_socket_ready(conn->sock[sockindex], - CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); - if(what > 0) { - ERR_clear_error(); - - /* Something to read, let's do it and hope that it is the close - notify alert from the server */ - nread = (ssize_t)SSL_read(conn->ssl[sockindex].handle, buf, - buffsize); - err = SSL_get_error(conn->ssl[sockindex].handle, (int)nread); - - switch(err) { - case SSL_ERROR_NONE: /* this is not an error */ - case SSL_ERROR_ZERO_RETURN: /* no more data */ - /* This is the expected response. There was no data but only - the close notify alert */ - done = 1; - break; - case SSL_ERROR_WANT_READ: - /* there's data pending, re-invoke SSL_read() */ - infof(data, "SSL_ERROR_WANT_READ\n"); - break; - case SSL_ERROR_WANT_WRITE: - /* SSL wants a write. Really odd. Let's bail out. */ - infof(data, "SSL_ERROR_WANT_WRITE\n"); - done = 1; - break; - default: - /* openssl/ssl.h says "look at error stack/return value/errno" */ - sslerror = ERR_get_error(); - failf(conn->data, "SSL read: %s, errno %d", - ERR_error_string(sslerror, buf), - SOCKERRNO); - done = 1; - break; - } - } - else if(0 == what) { - /* timeout */ - failf(data, "SSL shutdown timeout"); - done = 1; - } - else { - /* anything that gets here is fatally bad */ - failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); - retval = -1; - done = 1; - } - } /* while()-loop for the select() */ - - if(data->set.verbose) { -#ifdef HAVE_SSL_GET_SHUTDOWN - switch(SSL_get_shutdown(connssl->handle)) { - case SSL_SENT_SHUTDOWN: - infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n"); - break; - case SSL_RECEIVED_SHUTDOWN: - infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n"); - break; - case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN: - infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|" - "SSL_RECEIVED__SHUTDOWN\n"); - break; - } -#endif - } - - SSL_free (connssl->handle); - connssl->handle = NULL; - } - return retval; -} - -void Curl_ossl_session_free(void *ptr) -{ - /* free the ID */ - SSL_SESSION_free(ptr); -} - -/* - * This function is called when the 'data' struct is going away. Close - * down everything and free all resources! - */ -int Curl_ossl_close_all(struct SessionHandle *data) -{ - /* - ERR_remove_state() frees the error queue associated with - thread pid. If pid == 0, the current thread will have its - error queue removed. - - Since error queue data structures are allocated - automatically for new threads, they must be freed when - threads are terminated in oder to avoid memory leaks. - */ - ERR_remove_state(0); - -#ifdef HAVE_OPENSSL_ENGINE_H - if(data->state.engine) { - ENGINE_finish(data->state.engine); - ENGINE_free(data->state.engine); - data->state.engine = NULL; - } -#else - (void)data; -#endif - return 0; -} - -static int asn1_output(const ASN1_UTCTIME *tm, - char *buf, - size_t sizeofbuf) -{ - const char *asn1_string; - int gmt=FALSE; - int i; - int year=0,month=0,day=0,hour=0,minute=0,second=0; - - i=tm->length; - asn1_string=(const char *)tm->data; - - if(i < 10) - return 1; - if(asn1_string[i-1] == 'Z') - gmt=TRUE; - for (i=0; i<10; i++) - if((asn1_string[i] > '9') || (asn1_string[i] < '0')) - return 2; - - year= (asn1_string[0]-'0')*10+(asn1_string[1]-'0'); - if(year < 50) - year+=100; - - month= (asn1_string[2]-'0')*10+(asn1_string[3]-'0'); - if((month > 12) || (month < 1)) - return 3; - - day= (asn1_string[4]-'0')*10+(asn1_string[5]-'0'); - hour= (asn1_string[6]-'0')*10+(asn1_string[7]-'0'); - minute= (asn1_string[8]-'0')*10+(asn1_string[9]-'0'); - - if((asn1_string[10] >= '0') && (asn1_string[10] <= '9') && - (asn1_string[11] >= '0') && (asn1_string[11] <= '9')) - second= (asn1_string[10]-'0')*10+(asn1_string[11]-'0'); - - snprintf(buf, sizeofbuf, - "%04d-%02d-%02d %02d:%02d:%02d %s", - year+1900, month, day, hour, minute, second, (gmt?"GMT":"")); - - return 0; -} - -/* ====================================================== */ - -/* - * Match a hostname against a wildcard pattern. - * E.g. - * "foo.host.com" matches "*.host.com". - * - * We are a bit more liberal than RFC2818 describes in that we - * accept multiple "*" in pattern (similar to what some other browsers do). - * E.g. - * "abc.def.domain.com" should strickly not match "*.domain.com", but we - * don't consider "." to be important in CERT checking. - */ -#define HOST_NOMATCH 0 -#define HOST_MATCH 1 - -static int hostmatch(const char *hostname, const char *pattern) -{ - for(;;) { - char c = *pattern++; - - if(c == '\0') - return (*hostname ? HOST_NOMATCH : HOST_MATCH); - - if(c == '*') { - c = *pattern; - if(c == '\0') /* "*\0" matches anything remaining */ - return HOST_MATCH; - - while(*hostname) { - /* The only recursive function in libcurl! */ - if(hostmatch(hostname++,pattern) == HOST_MATCH) - return HOST_MATCH; - } - break; - } - - if(Curl_raw_toupper(c) != Curl_raw_toupper(*hostname++)) - break; - } - return HOST_NOMATCH; -} - -static int -cert_hostcheck(const char *match_pattern, const char *hostname) -{ - if(!match_pattern || !*match_pattern || - !hostname || !*hostname) /* sanity check */ - return 0; - - if(Curl_raw_equal(hostname, match_pattern)) /* trivial case */ - return 1; - - if(hostmatch(hostname,match_pattern) == HOST_MATCH) - return 1; - return 0; -} - -/* Quote from RFC2818 section 3.1 "Server Identity" - - If a subjectAltName extension of type dNSName is present, that MUST - be used as the identity. Otherwise, the (most specific) Common Name - field in the Subject field of the certificate MUST be used. Although - the use of the Common Name is existing practice, it is deprecated and - Certification Authorities are encouraged to use the dNSName instead. - - Matching is performed using the matching rules specified by - [RFC2459]. If more than one identity of a given type is present in - the certificate (e.g., more than one dNSName name, a match in any one - of the set is considered acceptable.) Names may contain the wildcard - character * which is considered to match any single domain name - component or component fragment. E.g., *.a.com matches foo.a.com but - not bar.foo.a.com. f*.com matches foo.com but not bar.com. - - In some cases, the URI is specified as an IP address rather than a - hostname. In this case, the iPAddress subjectAltName must be present - in the certificate and must exactly match the IP in the URI. - -*/ -static CURLcode verifyhost(struct connectdata *conn, - X509 *server_cert) -{ - int matched = -1; /* -1 is no alternative match yet, 1 means match and 0 - means mismatch */ - int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */ - size_t addrlen = 0; - struct SessionHandle *data = conn->data; - STACK_OF(GENERAL_NAME) *altnames; -#ifdef ENABLE_IPV6 - struct in6_addr addr; -#else - struct in_addr addr; -#endif - CURLcode res = CURLE_OK; - -#ifdef ENABLE_IPV6 - if(conn->bits.ipv6_ip && - Curl_inet_pton(AF_INET6, conn->host.name, &addr)) { - target = GEN_IPADD; - addrlen = sizeof(struct in6_addr); - } - else -#endif - if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) { - target = GEN_IPADD; - addrlen = sizeof(struct in_addr); - } - - /* get a "list" of alternative names */ - altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL); - - if(altnames) { - int numalts; - int i; - - /* get amount of alternatives, RFC2459 claims there MUST be at least - one, but we don't depend on it... */ - numalts = sk_GENERAL_NAME_num(altnames); - - /* loop through all alternatives while none has matched */ - for (i=0; (itype == target) { - /* get data and length */ - const char *altptr = (char *)ASN1_STRING_data(check->d.ia5); - size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5); - - switch(target) { - case GEN_DNS: /* name/pattern comparison */ - /* The OpenSSL man page explicitly says: "In general it cannot be - assumed that the data returned by ASN1_STRING_data() is null - terminated or does not contain embedded nulls." But also that - "The actual format of the data will depend on the actual string - type itself: for example for and IA5String the data will be ASCII" - - Gisle researched the OpenSSL sources: - "I checked the 0.9.6 and 0.9.8 sources before my patch and - it always 0-terminates an IA5String." - */ - if((altlen == strlen(altptr)) && - /* if this isn't true, there was an embedded zero in the name - string and we cannot match it. */ - cert_hostcheck(altptr, conn->host.name)) - matched = 1; - else - matched = 0; - break; - - case GEN_IPADD: /* IP address comparison */ - /* compare alternative IP address if the data chunk is the same size - our server IP address is */ - if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) - matched = 1; - else - matched = 0; - break; - } - } - } - GENERAL_NAMES_free(altnames); - } - - if(matched == 1) - /* an alternative name matched the server hostname */ - infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname); - else if(matched == 0) { - /* an alternative name field existed, but didn't match and then - we MUST fail */ - infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname); - res = CURLE_PEER_FAILED_VERIFICATION; - } - else { - /* we have to look to the last occurrence of a commonName in the - distinguished one to get the most significant one. */ - int j,i=-1 ; - -/* The following is done because of a bug in 0.9.6b */ - - unsigned char *nulstr = (unsigned char *)""; - unsigned char *peer_CN = nulstr; - - X509_NAME *name = X509_get_subject_name(server_cert) ; - if(name) - while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i))>=0) - i=j; - - /* we have the name entry and we will now convert this to a string - that we can use for comparison. Doing this we support BMPstring, - UTF8 etc. */ - - if(i>=0) { - ASN1_STRING *tmp = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i)); - - /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input - is already UTF-8 encoded. We check for this case and copy the raw - string manually to avoid the problem. This code can be made - conditional in the future when OpenSSL has been fixed. Work-around - brought by Alexis S. L. Carvalho. */ - if(tmp) { - if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) { - j = ASN1_STRING_length(tmp); - if(j >= 0) { - peer_CN = OPENSSL_malloc(j+1); - if(peer_CN) { - memcpy(peer_CN, ASN1_STRING_data(tmp), j); - peer_CN[j] = '\0'; - } - } - } - else /* not a UTF8 name */ - j = ASN1_STRING_to_UTF8(&peer_CN, tmp); - - if(peer_CN && ((int)strlen((char *)peer_CN) != j)) { - /* there was a terminating zero before the end of string, this - cannot match and we return failure! */ - failf(data, "SSL: illegal cert name field"); - res = CURLE_PEER_FAILED_VERIFICATION; - } - } - } - - if(peer_CN == nulstr) - peer_CN = NULL; - else { - /* convert peer_CN from UTF8 */ - size_t rc = Curl_convert_from_utf8(data, peer_CN, strlen(peer_CN)); - /* Curl_convert_from_utf8 calls failf if unsuccessful */ - if(rc) { - OPENSSL_free(peer_CN); - return rc; - } - } - - if(res) - /* error already detected, pass through */ - ; - else if(!peer_CN) { - failf(data, - "SSL: unable to obtain common name from peer certificate"); - res = CURLE_PEER_FAILED_VERIFICATION; - } - else if(!cert_hostcheck((const char *)peer_CN, conn->host.name)) { - if(data->set.ssl.verifyhost > 1) { - failf(data, "SSL: certificate subject name '%s' does not match " - "target host name '%s'", peer_CN, conn->host.dispname); - res = CURLE_PEER_FAILED_VERIFICATION; - } - else - infof(data, "\t common name: %s (does not match '%s')\n", - peer_CN, conn->host.dispname); - } - else { - infof(data, "\t common name: %s (matched)\n", peer_CN); - } - if(peer_CN) - OPENSSL_free(peer_CN); - } - return res; -} -#endif /* USE_SSLEAY */ - -/* The SSL_CTRL_SET_MSG_CALLBACK doesn't exist in ancient OpenSSL versions - and thus this cannot be done there. */ -#ifdef SSL_CTRL_SET_MSG_CALLBACK - -static const char *ssl_msg_type(int ssl_ver, int msg) -{ - if(ssl_ver == SSL2_VERSION_MAJOR) { - switch (msg) { - case SSL2_MT_ERROR: - return "Error"; - case SSL2_MT_CLIENT_HELLO: - return "Client hello"; - case SSL2_MT_CLIENT_MASTER_KEY: - return "Client key"; - case SSL2_MT_CLIENT_FINISHED: - return "Client finished"; - case SSL2_MT_SERVER_HELLO: - return "Server hello"; - case SSL2_MT_SERVER_VERIFY: - return "Server verify"; - case SSL2_MT_SERVER_FINISHED: - return "Server finished"; - case SSL2_MT_REQUEST_CERTIFICATE: - return "Request CERT"; - case SSL2_MT_CLIENT_CERTIFICATE: - return "Client CERT"; - } - } - else if(ssl_ver == SSL3_VERSION_MAJOR) { - switch (msg) { - case SSL3_MT_HELLO_REQUEST: - return "Hello request"; - case SSL3_MT_CLIENT_HELLO: - return "Client hello"; - case SSL3_MT_SERVER_HELLO: - return "Server hello"; - case SSL3_MT_CERTIFICATE: - return "CERT"; - case SSL3_MT_SERVER_KEY_EXCHANGE: - return "Server key exchange"; - case SSL3_MT_CLIENT_KEY_EXCHANGE: - return "Client key exchange"; - case SSL3_MT_CERTIFICATE_REQUEST: - return "Request CERT"; - case SSL3_MT_SERVER_DONE: - return "Server finished"; - case SSL3_MT_CERTIFICATE_VERIFY: - return "CERT verify"; - case SSL3_MT_FINISHED: - return "Finished"; - } - } - return "Unknown"; -} - -static const char *tls_rt_type(int type) -{ - return ( - type == SSL3_RT_CHANGE_CIPHER_SPEC ? "TLS change cipher, " : - type == SSL3_RT_ALERT ? "TLS alert, " : - type == SSL3_RT_HANDSHAKE ? "TLS handshake, " : - type == SSL3_RT_APPLICATION_DATA ? "TLS app data, " : - "TLS Unknown, "); -} - - -/* - * Our callback from the SSL/TLS layers. - */ -static void ssl_tls_trace(int direction, int ssl_ver, int content_type, - const void *buf, size_t len, const SSL *ssl, - struct connectdata *conn) -{ - struct SessionHandle *data; - const char *msg_name, *tls_rt_name; - char ssl_buf[1024]; - int ver, msg_type, txt_len; - - if(!conn || !conn->data || !conn->data->set.fdebug || - (direction != 0 && direction != 1)) - return; - - data = conn->data; - ssl_ver >>= 8; - ver = (ssl_ver == SSL2_VERSION_MAJOR ? '2' : - ssl_ver == SSL3_VERSION_MAJOR ? '3' : '?'); - - /* SSLv2 doesn't seem to have TLS record-type headers, so OpenSSL - * always pass-up content-type as 0. But the interesting message-type - * is at 'buf[0]'. - */ - if(ssl_ver == SSL3_VERSION_MAJOR && content_type != 0) - tls_rt_name = tls_rt_type(content_type); - else - tls_rt_name = ""; - - msg_type = *(char*)buf; - msg_name = ssl_msg_type(ssl_ver, msg_type); - - txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "SSLv%c, %s%s (%d):\n", - ver, tls_rt_name, msg_name, msg_type); - Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL); - - Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT : - CURLINFO_SSL_DATA_IN, (char *)buf, len, NULL); - (void) ssl; -} -#endif - -#ifdef USE_SSLEAY -/* ====================================================== */ - -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME -# define use_sni(x) sni = (x) -#else -# define use_sni(x) do { } while (0) -#endif - -static CURLcode -ossl_connect_step1(struct connectdata *conn, - int sockindex) -{ - CURLcode retcode = CURLE_OK; - - struct SessionHandle *data = conn->data; - SSL_METHOD_QUAL SSL_METHOD *req_method=NULL; - void *ssl_sessionid=NULL; - X509_LOOKUP *lookup=NULL; - curl_socket_t sockfd = conn->sock[sockindex]; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - bool sni; -#ifdef ENABLE_IPV6 - struct in6_addr addr; -#else - struct in_addr addr; -#endif -#endif - - DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); - - /* Make funny stuff to get random input */ - Curl_ossl_seed(data); - - /* check to see if we've been told to use an explicit SSL/TLS version */ - - switch(data->set.ssl.version) { - default: - case CURL_SSLVERSION_DEFAULT: -#ifdef USE_TLS_SRP - if (data->set.ssl.authtype == CURL_TLSAUTH_SRP) { - infof(data, "Set version TLSv1 for SRP authorisation\n"); - req_method = TLSv1_client_method() ; - } else -#endif - /* we try to figure out version */ - req_method = SSLv23_client_method(); - use_sni(TRUE); - break; - case CURL_SSLVERSION_TLSv1: - req_method = TLSv1_client_method(); - use_sni(TRUE); - break; - case CURL_SSLVERSION_SSLv2: -#ifdef OPENSSL_NO_SSL2 - failf(data, "OpenSSL was built without SSLv2 support"); - return CURLE_NOT_BUILT_IN; -#else -#ifdef USE_TLS_SRP - if (data->set.ssl.authtype == CURL_TLSAUTH_SRP) - return CURLE_SSL_CONNECT_ERROR; -#endif - req_method = SSLv2_client_method(); - use_sni(FALSE); - break; -#endif - case CURL_SSLVERSION_SSLv3: -#ifdef USE_TLS_SRP - if (data->set.ssl.authtype == CURL_TLSAUTH_SRP) - return CURLE_SSL_CONNECT_ERROR; -#endif - req_method = SSLv3_client_method(); - use_sni(FALSE); - break; - } - - if(connssl->ctx) - SSL_CTX_free(connssl->ctx); - connssl->ctx = SSL_CTX_new(req_method); - - if(!connssl->ctx) { - failf(data, "SSL: couldn't create a context: %s", - ERR_error_string(ERR_peek_error(), NULL)); - return CURLE_OUT_OF_MEMORY; - } - -#ifdef SSL_CTRL_SET_MSG_CALLBACK - if(data->set.fdebug && data->set.verbose) { - /* the SSL trace callback is only used for verbose logging so we only - inform about failures of setting it */ - if(!SSL_CTX_callback_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK, - (void (*)(void))ssl_tls_trace)) { - infof(data, "SSL: couldn't set callback!\n"); - } - else if(!SSL_CTX_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, - conn)) { - infof(data, "SSL: couldn't set callback argument!\n"); - } - } -#endif - - /* OpenSSL contains code to work-around lots of bugs and flaws in various - SSL-implementations. SSL_CTX_set_options() is used to enabled those - work-arounds. The man page for this option states that SSL_OP_ALL enables - all the work-arounds and that "It is usually safe to use SSL_OP_ALL to - enable the bug workaround options if compatibility with somewhat broken - implementations is desired." - - The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to - disable "rfc4507bis session ticket support". rfc4507bis was later turned - into the proper RFC5077 it seems: http://tools.ietf.org/html/rfc5077 - - The enabled extension concerns the session management. I wonder how often - libcurl stops a connection and then resumes a TLS session. also, sending - the session data is some overhead. .I suggest that you just use your - proposed patch (which explicitly disables TICKET). - - If someone writes an application with libcurl and openssl who wants to - enable the feature, one can do this in the SSL callback. - - */ -#ifdef SSL_OP_NO_TICKET - /* expect older openssl releases to not have this define so only use it if - present */ -#define CURL_CTX_OPTIONS SSL_OP_ALL|SSL_OP_NO_TICKET -#else -#define CURL_CTX_OPTIONS SSL_OP_ALL -#endif - - SSL_CTX_set_options(connssl->ctx, CURL_CTX_OPTIONS); - - /* disable SSLv2 in the default case (i.e. allow SSLv3 and TLSv1) */ - if(data->set.ssl.version == CURL_SSLVERSION_DEFAULT) - SSL_CTX_set_options(connssl->ctx, SSL_OP_NO_SSLv2); - -#if 0 - /* - * Not sure it's needed to tell SSL_connect() that socket is - * non-blocking. It doesn't seem to care, but just return with - * SSL_ERROR_WANT_x. - */ - if(data->state.used_interface == Curl_if_multi) - SSL_CTX_ctrl(connssl->ctx, BIO_C_SET_NBIO, 1, NULL); -#endif - - if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) { - if(!cert_stuff(conn, - connssl->ctx, - data->set.str[STRING_CERT], - data->set.str[STRING_CERT_TYPE], - data->set.str[STRING_KEY], - data->set.str[STRING_KEY_TYPE])) { - /* failf() is already done in cert_stuff() */ - return CURLE_SSL_CERTPROBLEM; - } - } - - if(data->set.str[STRING_SSL_CIPHER_LIST]) { - if(!SSL_CTX_set_cipher_list(connssl->ctx, - data->set.str[STRING_SSL_CIPHER_LIST])) { - failf(data, "failed setting cipher list"); - return CURLE_SSL_CIPHER; - } - } - -#ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { - infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); - - if (!SSL_CTX_set_srp_username(connssl->ctx, data->set.ssl.username)) { - failf(data, "Unable to set SRP user name"); - return CURLE_BAD_FUNCTION_ARGUMENT; - } - if (!SSL_CTX_set_srp_password(connssl->ctx,data->set.ssl.password)) { - failf(data, "failed setting SRP password"); - return CURLE_BAD_FUNCTION_ARGUMENT; - } - if(!data->set.str[STRING_SSL_CIPHER_LIST]) { - infof(data, "Setting cipher list SRP\n"); - - if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) { - failf(data, "failed setting SRP cipher list"); - return CURLE_SSL_CIPHER; - } - } - } -#endif - if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) { - /* tell SSL where to find CA certificates that are used to verify - the servers certificate. */ - if(!SSL_CTX_load_verify_locations(connssl->ctx, - data->set.str[STRING_SSL_CAFILE], - data->set.str[STRING_SSL_CAPATH])) { - if(data->set.ssl.verifypeer) { - /* Fail if we insist on successfully verifying the server. */ - failf(data,"error setting certificate verify locations:\n" - " CAfile: %s\n CApath: %s\n", - data->set.str[STRING_SSL_CAFILE]? - data->set.str[STRING_SSL_CAFILE]: "none", - data->set.str[STRING_SSL_CAPATH]? - data->set.str[STRING_SSL_CAPATH] : "none"); - return CURLE_SSL_CACERT_BADFILE; - } - else { - /* Just continue with a warning if no strict certificate verification - is required. */ - infof(data, "error setting certificate verify locations," - " continuing anyway:\n"); - } - } - else { - /* Everything is fine. */ - infof(data, "successfully set certificate verify locations:\n"); - } - infof(data, - " CAfile: %s\n" - " CApath: %s\n", - data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]: - "none", - data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]: - "none"); - } - - if (data->set.str[STRING_SSL_CRLFILE]) { - /* tell SSL where to find CRL file that is used to check certificate - * revocation */ - lookup=X509_STORE_add_lookup(connssl->ctx->cert_store,X509_LOOKUP_file()); - if ( !lookup || - (!X509_load_crl_file(lookup,data->set.str[STRING_SSL_CRLFILE], - X509_FILETYPE_PEM)) ) { - failf(data,"error loading CRL file: %s\n", - data->set.str[STRING_SSL_CRLFILE]); - return CURLE_SSL_CRL_BADFILE; - } - else { - /* Everything is fine. */ - infof(data, "successfully load CRL file:\n"); - X509_STORE_set_flags(connssl->ctx->cert_store, - X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); - } - infof(data, - " CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ? - data->set.str[STRING_SSL_CRLFILE]: "none"); - } - - /* SSL always tries to verify the peer, this only says whether it should - * fail to connect if the verification fails, or if it should continue - * anyway. In the latter case the result of the verification is checked with - * SSL_get_verify_result() below. */ - SSL_CTX_set_verify(connssl->ctx, - data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE, - cert_verify_callback); - - /* give application a chance to interfere with SSL set up. */ - if(data->set.ssl.fsslctx) { - retcode = (*data->set.ssl.fsslctx)(data, connssl->ctx, - data->set.ssl.fsslctxp); - if(retcode) { - failf(data,"error signaled by ssl ctx callback"); - return retcode; - } - } - - /* Lets make an SSL structure */ - if(connssl->handle) - SSL_free(connssl->handle); - connssl->handle = SSL_new(connssl->ctx); - if(!connssl->handle) { - failf(data, "SSL: couldn't create a context (handle)!"); - return CURLE_OUT_OF_MEMORY; - } - SSL_set_connect_state(connssl->handle); - - connssl->server_cert = 0x0; - -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - if ((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && -#ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && -#endif - sni && - !SSL_set_tlsext_host_name(connssl->handle, conn->host.name)) - infof(data, "WARNING: failed to configure server name indication (SNI) " - "TLS extension\n"); -#endif - - /* Check if there's a cached ID we can/should use here! */ - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) { - /* we got a session id, use it! */ - if(!SSL_set_session(connssl->handle, ssl_sessionid)) { - failf(data, "SSL: SSL_set_session failed: %s", - ERR_error_string(ERR_get_error(),NULL)); - return CURLE_SSL_CONNECT_ERROR; - } - /* Informational message */ - infof (data, "SSL re-using session ID\n"); - } - - /* pass the raw socket into the SSL layers */ - if(!SSL_set_fd(connssl->handle, (int)sockfd)) { - failf(data, "SSL: SSL_set_fd failed: %s", - ERR_error_string(ERR_get_error(),NULL)); - return CURLE_SSL_CONNECT_ERROR; - } - - connssl->connecting_state = ssl_connect_2; - return CURLE_OK; -} - -static CURLcode -ossl_connect_step2(struct connectdata *conn, int sockindex) -{ - struct SessionHandle *data = conn->data; - int err; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - DEBUGASSERT(ssl_connect_2 == connssl->connecting_state - || ssl_connect_2_reading == connssl->connecting_state - || ssl_connect_2_writing == connssl->connecting_state); - - ERR_clear_error(); - - err = SSL_connect(connssl->handle); - - /* 1 is fine - 0 is "not successful but was shut down controlled" - <0 is "handshake was not successful, because a fatal error occurred" */ - if(1 != err) { - int detail = SSL_get_error(connssl->handle, err); - - if(SSL_ERROR_WANT_READ == detail) { - connssl->connecting_state = ssl_connect_2_reading; - return CURLE_OK; - } - else if(SSL_ERROR_WANT_WRITE == detail) { - connssl->connecting_state = ssl_connect_2_writing; - return CURLE_OK; - } - else { - /* untreated error */ - unsigned long errdetail; - char error_buffer[256]; /* OpenSSL documents that this must be at least - 256 bytes long. */ - CURLcode rc; - const char *cert_problem = NULL; - - connssl->connecting_state = ssl_connect_2; /* the connection failed, - we're not waiting for - anything else. */ - - errdetail = ERR_get_error(); /* Gets the earliest error code from the - thread's error queue and removes the - entry. */ - - switch(errdetail) { - case 0x1407E086: - /* 1407E086: - SSL routines: - SSL2_SET_CERTIFICATE: - certificate verify failed */ - /* fall-through */ - case 0x14090086: - /* 14090086: - SSL routines: - SSL3_GET_SERVER_CERTIFICATE: - certificate verify failed */ - cert_problem = "SSL certificate problem, verify that the CA cert is" - " OK. Details:\n"; - rc = CURLE_SSL_CACERT; - break; - default: - rc = CURLE_SSL_CONNECT_ERROR; - break; - } - - /* detail is already set to the SSL error above */ - - /* If we e.g. use SSLv2 request-method and the server doesn't like us - * (RST connection etc.), OpenSSL gives no explanation whatsoever and - * the SO_ERROR is also lost. - */ - if(CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) { - failf(data, "Unknown SSL protocol error in connection to %s:%ld ", - conn->host.name, conn->port); - return rc; - } - /* Could be a CERT problem */ - - SSL_strerror(errdetail, error_buffer, sizeof(error_buffer)); - failf(data, "%s%s", cert_problem ? cert_problem : "", error_buffer); - return rc; - } - } - else { - /* we have been connected fine, we're not waiting for anything else. */ - connssl->connecting_state = ssl_connect_3; - - /* Informational message */ - infof (data, "SSL connection using %s\n", - SSL_get_cipher(connssl->handle)); - - return CURLE_OK; - } -} - -static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len) -{ - int i, ilen; - - if((ilen = (int)len) < 0) - return 1; /* buffer too big */ - - i = i2t_ASN1_OBJECT(buf, ilen, a); - - if(i >= ilen) - return 1; /* buffer too small */ - - return 0; -} - -static CURLcode push_certinfo_len(struct SessionHandle *data, - int certnum, - const char *label, - const char *value, - size_t valuelen) -{ - struct curl_certinfo *ci = &data->info.certs; - char *output; - struct curl_slist *nl; - CURLcode res = CURLE_OK; - size_t labellen = strlen(label); - size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */ - - output = malloc(outlen); - if(!output) - return CURLE_OUT_OF_MEMORY; - - /* sprintf the label and colon */ - snprintf(output, outlen, "%s:", label); - - /* memcpy the value (it might not be zero terminated) */ - memcpy(&output[labellen+1], value, valuelen); - - /* zero terminate the output */ - output[labellen + 1 + valuelen] = 0; - - /* TODO: we should rather introduce an internal API that can do the - equivalent of curl_slist_append but doesn't strdup() the given data as - like in this place the extra malloc/free is totally pointless */ - nl = curl_slist_append(ci->certinfo[certnum], output); - if(!nl) { - curl_slist_free_all(ci->certinfo[certnum]); - res = CURLE_OUT_OF_MEMORY; - } - else - ci->certinfo[certnum] = nl; - - free(output); - - return res; -} - -/* this is a convenience function for push_certinfo_len that takes a zero - terminated value */ -static CURLcode push_certinfo(struct SessionHandle *data, - int certnum, - const char *label, - const char *value) -{ - size_t valuelen = strlen(value); - - return push_certinfo_len(data, certnum, label, value, valuelen); -} - -static void pubkey_show(struct SessionHandle *data, - int num, - const char *type, - const char *name, - unsigned char *raw, - int len) -{ - size_t left; - int i; - char namebuf[32]; - char *buffer; - - left = len*3 + 1; - buffer = malloc(left); - if(buffer) { - char *ptr=buffer; - snprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name); - for(i=0; i< len; i++) { - snprintf(ptr, left, "%02x:", raw[i]); - ptr += 3; - left -= 3; - } - infof(data, " %s: %s\n", namebuf, buffer); - push_certinfo(data, num, namebuf, buffer); - free(buffer); - } -} - -#define print_pubkey_BN(_type, _name, _num) \ -do { \ - if (pubkey->pkey._type->_name != NULL) { \ - int len = BN_num_bytes(pubkey->pkey._type->_name); \ - if(len < CERTBUFFERSIZE) { \ - BN_bn2bin(pubkey->pkey._type->_name, (unsigned char*)bufp); \ - bufp[len] = 0; \ - pubkey_show(data, _num, #_type, #_name, (unsigned char*)bufp, len); \ - } \ - } \ -} while (0) - -static int X509V3_ext(struct SessionHandle *data, - int certnum, - STACK_OF(X509_EXTENSION) *exts) -{ - int i; - size_t j; - - if(sk_X509_EXTENSION_num(exts) <= 0) - /* no extensions, bail out */ - return 1; - - for (i=0; ivalue); - - BIO_get_mem_ptr(bio_out, &biomem); - - /* biomem->length bytes at biomem->data, this little loop here is only - done for the infof() call, we send the "raw" data to the certinfo - function */ - for(j=0; j<(size_t)biomem->length; j++) { - const char *sep=""; - if(biomem->data[j] == '\n') { - sep=", "; - j++; /* skip the newline */ - }; - while((biomem->data[j] == ' ') && (j<(size_t)biomem->length)) - j++; - if(j<(size_t)biomem->length) - ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep, biomem->data[j]); - } - infof(data, " %s\n", buf); - - push_certinfo(data, certnum, namebuf, buf); - - BIO_free(bio_out); - - } - return 0; /* all is fine */ -} - - -static void X509_signature(struct SessionHandle *data, - int numcert, - ASN1_STRING *sig) -{ - char buf[1024]; - char *ptr = buf; - int i; - for (i=0; ilength; i++) - ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%02x:", sig->data[i]); - - infof(data, " Signature: %s\n", buf); - push_certinfo(data, numcert, "Signature", buf); -} - -static void dumpcert(struct SessionHandle *data, X509 *x, int numcert) -{ - BIO *bio_out = BIO_new(BIO_s_mem()); - BUF_MEM *biomem; - - /* this outputs the cert in this 64 column wide style with newlines and - -----BEGIN CERTIFICATE----- texts and more */ - PEM_write_bio_X509(bio_out, x); - - BIO_get_mem_ptr(bio_out, &biomem); - - infof(data, "%s\n", biomem->data); - - push_certinfo_len(data, numcert, "Cert", biomem->data, biomem->length); - - BIO_free(bio_out); - -} - - -static int init_certinfo(struct SessionHandle *data, - int num) -{ - struct curl_certinfo *ci = &data->info.certs; - struct curl_slist **table; - - Curl_ssl_free_certinfo(data); - - ci->num_of_certs = num; - table = calloc((size_t)num, sizeof(struct curl_slist *)); - if(!table) - return 1; - - ci->certinfo = table; - return 0; -} - -/* - * This size was previously 512 which has been reported "too small" without - * any specifics, so it was enlarged to allow more data to get shown uncut. - * The "perfect" size is yet to figure out. - */ -#define CERTBUFFERSIZE 8192 - -static CURLcode get_cert_chain(struct connectdata *conn, - struct ssl_connect_data *connssl) - -{ - STACK_OF(X509) *sk; - int i; - char *bufp; - struct SessionHandle *data = conn->data; - int numcerts; - - bufp = malloc(CERTBUFFERSIZE); - if(!bufp) - return CURLE_OUT_OF_MEMORY; - - sk = SSL_get_peer_cert_chain(connssl->handle); - if(!sk) { - free(bufp); - return CURLE_OUT_OF_MEMORY; - } - - numcerts = sk_X509_num(sk); - if(init_certinfo(data, numcerts)) { - free(bufp); - return CURLE_OUT_OF_MEMORY; - } - - infof(data, "--- Certificate chain\n"); - for (i=0; ilength <= 4) { - value = ASN1_INTEGER_get(num); - infof(data," Serial Number: %ld (0x%lx)\n", value, value); - snprintf(bufp, CERTBUFFERSIZE, "%lx", value); - } - else { - int left = CERTBUFFERSIZE; - - ptr = bufp; - *ptr++ = 0; - if(num->type == V_ASN1_NEG_INTEGER) - *ptr++='-'; - - for (j=0; (jlength) && (left>=4); j++) { - /* TODO: length restrictions */ - snprintf(ptr, 3, "%02x%c",num->data[j], - ((j+1 == num->length)?'\n':':')); - ptr += 3; - left-=4; - } - if(num->length) - infof(data," Serial Number: %s\n", bufp); - else - bufp[0]=0; - } - if(bufp[0]) - push_certinfo(data, i, "Serial Number", bufp); /* hex */ - - cinf = x->cert_info; - - j = asn1_object_dump(cinf->signature->algorithm, bufp, CERTBUFFERSIZE); - if(!j) { - infof(data, " Signature Algorithm: %s\n", bufp); - push_certinfo(data, i, "Signature Algorithm", bufp); - } - - certdate = X509_get_notBefore(x); - asn1_output(certdate, bufp, CERTBUFFERSIZE); - infof(data, " Start date: %s\n", bufp); - push_certinfo(data, i, "Start date", bufp); - - certdate = X509_get_notAfter(x); - asn1_output(certdate, bufp, CERTBUFFERSIZE); - infof(data, " Expire date: %s\n", bufp); - push_certinfo(data, i, "Expire date", bufp); - - j = asn1_object_dump(cinf->key->algor->algorithm, bufp, CERTBUFFERSIZE); - if(!j) { - infof(data, " Public Key Algorithm: %s\n", bufp); - push_certinfo(data, i, "Public Key Algorithm", bufp); - } - - pubkey = X509_get_pubkey(x); - if(!pubkey) - infof(data, " Unable to load public key\n"); - else { - switch(pubkey->type) { - case EVP_PKEY_RSA: - infof(data, " RSA Public Key (%d bits)\n", - BN_num_bits(pubkey->pkey.rsa->n)); - snprintf(bufp, CERTBUFFERSIZE, "%d", BN_num_bits(pubkey->pkey.rsa->n)); - push_certinfo(data, i, "RSA Public Key", bufp); - - print_pubkey_BN(rsa, n, i); - print_pubkey_BN(rsa, e, i); - print_pubkey_BN(rsa, d, i); - print_pubkey_BN(rsa, p, i); - print_pubkey_BN(rsa, q, i); - print_pubkey_BN(rsa, dmp1, i); - print_pubkey_BN(rsa, dmq1, i); - print_pubkey_BN(rsa, iqmp, i); - break; - case EVP_PKEY_DSA: - print_pubkey_BN(dsa, p, i); - print_pubkey_BN(dsa, q, i); - print_pubkey_BN(dsa, g, i); - print_pubkey_BN(dsa, priv_key, i); - print_pubkey_BN(dsa, pub_key, i); - break; - case EVP_PKEY_DH: - print_pubkey_BN(dh, p, i); - print_pubkey_BN(dh, g, i); - print_pubkey_BN(dh, priv_key, i); - print_pubkey_BN(dh, pub_key, i); - break; -#if 0 - case EVP_PKEY_EC: /* symbol not present in OpenSSL 0.9.6 */ - /* left TODO */ - break; -#endif - } - EVP_PKEY_free(pubkey); - } - - X509V3_ext(data, i, cinf->extensions); - - X509_signature(data, i, x->signature); - - dumpcert(data, x, i); - } - - free(bufp); - - return CURLE_OK; -} - -/* - * Get the server cert, verify it and show it etc, only call failf() if the - * 'strict' argument is TRUE as otherwise all this is for informational - * purposes only! - * - * We check certificates to authenticate the server; otherwise we risk - * man-in-the-middle attack. - */ -static CURLcode servercert(struct connectdata *conn, - struct ssl_connect_data *connssl, - bool strict) -{ - CURLcode retcode = CURLE_OK; - int rc; - long lerr; - ASN1_TIME *certdate; - struct SessionHandle *data = conn->data; - X509 *issuer; - FILE *fp; - char buffer[256]; - - if(data->set.ssl.certinfo) - /* we've been asked to gather certificate info! */ - (void)get_cert_chain(conn, connssl); - - data->set.ssl.certverifyresult = !X509_V_OK; - - connssl->server_cert = SSL_get_peer_certificate(connssl->handle); - if(!connssl->server_cert) { - if(strict) - failf(data, "SSL: couldn't get peer certificate!"); - return CURLE_PEER_FAILED_VERIFICATION; - } - infof (data, "Server certificate:\n"); - - rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert), - buffer, sizeof(buffer)); - if(rc) { - if(strict) - failf(data, "SSL: couldn't get X509-subject!"); - X509_free(connssl->server_cert); - connssl->server_cert = NULL; - return CURLE_SSL_CONNECT_ERROR; - } - infof(data, "\t subject: %s\n", buffer); - - certdate = X509_get_notBefore(connssl->server_cert); - asn1_output(certdate, buffer, sizeof(buffer)); - infof(data, "\t start date: %s\n", buffer); - - certdate = X509_get_notAfter(connssl->server_cert); - asn1_output(certdate, buffer, sizeof(buffer)); - infof(data, "\t expire date: %s\n", buffer); - - if(data->set.ssl.verifyhost) { - retcode = verifyhost(conn, connssl->server_cert); - if(retcode) { - X509_free(connssl->server_cert); - connssl->server_cert = NULL; - return retcode; - } - } - - rc = x509_name_oneline(X509_get_issuer_name(connssl->server_cert), - buffer, sizeof(buffer)); - if(rc) { - if(strict) - failf(data, "SSL: couldn't get X509-issuer name!"); - retcode = CURLE_SSL_CONNECT_ERROR; - } - else { - infof(data, "\t issuer: %s\n", buffer); - - /* We could do all sorts of certificate verification stuff here before - deallocating the certificate. */ - - /* e.g. match issuer name with provided issuer certificate */ - if (data->set.str[STRING_SSL_ISSUERCERT]) { - if (! (fp=fopen(data->set.str[STRING_SSL_ISSUERCERT],"r"))) { - if (strict) - failf(data, "SSL: Unable to open issuer cert (%s)\n", - data->set.str[STRING_SSL_ISSUERCERT]); - X509_free(connssl->server_cert); - connssl->server_cert = NULL; - return CURLE_SSL_ISSUER_ERROR; - } - issuer = PEM_read_X509(fp,NULL,ZERO_NULL,NULL); - if (!issuer) { - if (strict) - failf(data, "SSL: Unable to read issuer cert (%s)\n", - data->set.str[STRING_SSL_ISSUERCERT]); - X509_free(connssl->server_cert); - X509_free(issuer); - fclose(fp); - return CURLE_SSL_ISSUER_ERROR; - } - fclose(fp); - if (X509_check_issued(issuer,connssl->server_cert) != X509_V_OK) { - if (strict) - failf(data, "SSL: Certificate issuer check failed (%s)\n", - data->set.str[STRING_SSL_ISSUERCERT]); - X509_free(connssl->server_cert); - X509_free(issuer); - connssl->server_cert = NULL; - return CURLE_SSL_ISSUER_ERROR; - } - infof(data, "\t SSL certificate issuer check ok (%s)\n", - data->set.str[STRING_SSL_ISSUERCERT]); - X509_free(issuer); - } - - lerr = data->set.ssl.certverifyresult= - SSL_get_verify_result(connssl->handle); - if(data->set.ssl.certverifyresult != X509_V_OK) { - if(data->set.ssl.verifypeer) { - /* We probably never reach this, because SSL_connect() will fail - and we return earlier if verifypeer is set? */ - if(strict) - failf(data, "SSL certificate verify result: %s (%ld)", - X509_verify_cert_error_string(lerr), lerr); - retcode = CURLE_PEER_FAILED_VERIFICATION; - } - else - infof(data, "\t SSL certificate verify result: %s (%ld)," - " continuing anyway.\n", - X509_verify_cert_error_string(lerr), lerr); - } - else - infof(data, "\t SSL certificate verify ok.\n"); - } - - X509_free(connssl->server_cert); - connssl->server_cert = NULL; - connssl->connecting_state = ssl_connect_done; - - return retcode; -} - - -static CURLcode -ossl_connect_step3(struct connectdata *conn, - int sockindex) -{ - CURLcode retcode = CURLE_OK; - void *old_ssl_sessionid=NULL; - struct SessionHandle *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - int incache; - SSL_SESSION *our_ssl_sessionid; - - DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - -#ifdef HAVE_SSL_GET1_SESSION - our_ssl_sessionid = SSL_get1_session(connssl->handle); - - /* SSL_get1_session() will increment the reference - count and the session will stay in memory until explicitly freed with - SSL_SESSION_free(3), regardless of its state. - This function was introduced in openssl 0.9.5a. */ -#else - our_ssl_sessionid = SSL_get_session(connssl->handle); - - /* if SSL_get1_session() is unavailable, use SSL_get_session(). - This is an inferior option because the session can be flushed - at any time by openssl. It is included only so curl compiles - under versions of openssl < 0.9.5a. - - WARNING: How curl behaves if it's session is flushed is - untested. - */ -#endif - - incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); - if (incache) { - if (old_ssl_sessionid != our_ssl_sessionid) { - infof(data, "old SSL session ID is stale, removing\n"); - Curl_ssl_delsessionid(conn, old_ssl_sessionid); - incache = FALSE; - } - } - if (!incache) { - retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, - 0 /* unknown size */); - if(retcode) { - failf(data, "failed to store ssl session"); - return retcode; - } - } -#ifdef HAVE_SSL_GET1_SESSION - else { - /* Session was incache, so refcount already incremented earlier. - * Avoid further increments with each SSL_get1_session() call. - * This does not free the session as refcount remains > 0 - */ - SSL_SESSION_free(our_ssl_sessionid); - } -#endif - - /* - * We check certificates to authenticate the server; otherwise we risk - * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to - * verify the peer ignore faults and failures from the server cert - * operations. - */ - - if(!data->set.ssl.verifypeer) - (void)servercert(conn, connssl, FALSE); - else - retcode = servercert(conn, connssl, TRUE); - - if(CURLE_OK == retcode) - connssl->connecting_state = ssl_connect_done; - return retcode; -} - -static Curl_recv ossl_recv; -static Curl_send ossl_send; - -static CURLcode -ossl_connect_common(struct connectdata *conn, - int sockindex, - bool nonblocking, - bool *done) -{ - CURLcode retcode; - struct SessionHandle *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - curl_socket_t sockfd = conn->sock[sockindex]; - long timeout_ms; - int what; - - /* check if the connection has already been established */ - if(ssl_connection_complete == connssl->state) { - *done = TRUE; - return CURLE_OK; - } - - if(ssl_connect_1==connssl->connecting_state) { - /* Find out how much more time we're allowed */ - timeout_ms = Curl_timeleft(data, NULL, TRUE); - - if(timeout_ms < 0) { - /* no need to continue if time already is up */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - retcode = ossl_connect_step1(conn, sockindex); - if(retcode) - return retcode; - } - - while(ssl_connect_2 == connssl->connecting_state || - ssl_connect_2_reading == connssl->connecting_state || - ssl_connect_2_writing == connssl->connecting_state) { - - /* check allowed time left */ - timeout_ms = Curl_timeleft(data, NULL, TRUE); - - if(timeout_ms < 0) { - /* no need to continue if time already is up */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - - /* if ssl is expecting something, check if it's available. */ - if(connssl->connecting_state == ssl_connect_2_reading - || connssl->connecting_state == ssl_connect_2_writing) { - - curl_socket_t writefd = ssl_connect_2_writing== - connssl->connecting_state?sockfd:CURL_SOCKET_BAD; - curl_socket_t readfd = ssl_connect_2_reading== - connssl->connecting_state?sockfd:CURL_SOCKET_BAD; - - what = Curl_socket_ready(readfd, writefd, - nonblocking?0:(int)timeout_ms); - if(what < 0) { - /* fatal error */ - failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); - return CURLE_SSL_CONNECT_ERROR; - } - else if(0 == what) { - if(nonblocking) { - *done = FALSE; - return CURLE_OK; - } - else { - /* timeout */ - failf(data, "SSL connection timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - } - /* socket is readable or writable */ - } - - /* Run transaction, and return to the caller if it failed or if this - * connection is done nonblocking and this loop would execute again. This - * permits the owner of a multi handle to abort a connection attempt - * before step2 has completed while ensuring that a client using select() - * or epoll() will always have a valid fdset to wait on. - */ - retcode = ossl_connect_step2(conn, sockindex); - if(retcode || (nonblocking && - (ssl_connect_2 == connssl->connecting_state || - ssl_connect_2_reading == connssl->connecting_state || - ssl_connect_2_writing == connssl->connecting_state))) - return retcode; - - } /* repeat step2 until all transactions are done. */ - - - if(ssl_connect_3==connssl->connecting_state) { - retcode = ossl_connect_step3(conn, sockindex); - if(retcode) - return retcode; - } - - if(ssl_connect_done==connssl->connecting_state) { - connssl->state = ssl_connection_complete; - conn->recv[sockindex] = ossl_recv; - conn->send[sockindex] = ossl_send; - *done = TRUE; - } - else - *done = FALSE; - - /* Reset our connect state machine */ - connssl->connecting_state = ssl_connect_1; - - return CURLE_OK; -} - -CURLcode -Curl_ossl_connect_nonblocking(struct connectdata *conn, - int sockindex, - bool *done) -{ - return ossl_connect_common(conn, sockindex, TRUE, done); -} - -CURLcode -Curl_ossl_connect(struct connectdata *conn, - int sockindex) -{ - CURLcode retcode; - bool done = FALSE; - - retcode = ossl_connect_common(conn, sockindex, FALSE, &done); - if(retcode) - return retcode; - - DEBUGASSERT(done); - - return CURLE_OK; -} - -bool Curl_ossl_data_pending(const struct connectdata *conn, - int connindex) -{ - if(conn->ssl[connindex].handle) - /* SSL is in use */ - return (bool)(0 != SSL_pending(conn->ssl[connindex].handle)); - else - return FALSE; -} - -static ssize_t ossl_send(struct connectdata *conn, - int sockindex, - const void *mem, - size_t len, - CURLcode *curlcode) -{ - /* SSL_write() is said to return 'int' while write() and send() returns - 'size_t' */ - int err; - char error_buffer[120]; /* OpenSSL documents that this must be at least 120 - bytes long. */ - unsigned long sslerror; - int memlen; - int rc; - - ERR_clear_error(); - - memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; - rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen); - - if(rc < 0) { - err = SSL_get_error(conn->ssl[sockindex].handle, rc); - - switch(err) { - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - /* The operation did not complete; the same TLS/SSL I/O function - should be called again later. This is basically an EWOULDBLOCK - equivalent. */ - *curlcode = CURLE_AGAIN; - return -1; - case SSL_ERROR_SYSCALL: - failf(conn->data, "SSL_write() returned SYSCALL, errno = %d", - SOCKERRNO); - *curlcode = CURLE_SEND_ERROR; - return -1; - case SSL_ERROR_SSL: - /* A failure in the SSL library occurred, usually a protocol error. - The OpenSSL error queue contains more information on the error. */ - sslerror = ERR_get_error(); - failf(conn->data, "SSL_write() error: %s", - ERR_error_string(sslerror, error_buffer)); - *curlcode = CURLE_SEND_ERROR; - return -1; - } - /* a true error */ - failf(conn->data, "SSL_write() return error %d", err); - *curlcode = CURLE_SEND_ERROR; - return -1; - } - return (ssize_t)rc; /* number of bytes */ -} - -static ssize_t ossl_recv(struct connectdata *conn, /* connection data */ - int num, /* socketindex */ - char *buf, /* store read data here */ - size_t buffersize, /* max amount to read */ - CURLcode *curlcode) -{ - char error_buffer[120]; /* OpenSSL documents that this must be at - least 120 bytes long. */ - unsigned long sslerror; - ssize_t nread; - int buffsize; - - ERR_clear_error(); - - buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; - nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize); - if(nread < 0) { - /* failed SSL_read */ - int err = SSL_get_error(conn->ssl[num].handle, (int)nread); - - switch(err) { - case SSL_ERROR_NONE: /* this is not an error */ - case SSL_ERROR_ZERO_RETURN: /* no more data */ - break; - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - /* there's data pending, re-invoke SSL_read() */ - *curlcode = CURLE_AGAIN; - return -1; - default: - /* openssl/ssl.h says "look at error stack/return value/errno" */ - sslerror = ERR_get_error(); - failf(conn->data, "SSL read: %s, errno %d", - ERR_error_string(sslerror, error_buffer), - SOCKERRNO); - *curlcode = CURLE_RECV_ERROR; - return -1; - } - } - return nread; -} - -size_t Curl_ossl_version(char *buffer, size_t size) -{ -#ifdef YASSL_VERSION - /* yassl provides an OpenSSL API compatibility layer so it looks identical - to OpenSSL in all other aspects */ - return snprintf(buffer, size, "yassl/%s", YASSL_VERSION); -#else /* YASSL_VERSION */ - -#if(SSLEAY_VERSION_NUMBER >= 0x905000) - { - char sub[2]; - unsigned long ssleay_value; - sub[1]='\0'; - ssleay_value=SSLeay(); - if(ssleay_value < 0x906000) { - ssleay_value=SSLEAY_VERSION_NUMBER; - sub[0]='\0'; - } - else { - if(ssleay_value&0xff0) { - sub[0]=(char)(((ssleay_value>>4)&0xff) + 'a' -1); - } - else - sub[0]='\0'; - } - - return snprintf(buffer, size, "OpenSSL/%lx.%lx.%lx%s", - (ssleay_value>>28)&0xf, - (ssleay_value>>20)&0xff, - (ssleay_value>>12)&0xff, - sub); - } - -#else /* SSLEAY_VERSION_NUMBER is less than 0.9.5 */ - -#if(SSLEAY_VERSION_NUMBER >= 0x900000) - return snprintf(buffer, size, "OpenSSL/%lx.%lx.%lx", - (SSLEAY_VERSION_NUMBER>>28)&0xff, - (SSLEAY_VERSION_NUMBER>>20)&0xff, - (SSLEAY_VERSION_NUMBER>>12)&0xf); - -#else /* (SSLEAY_VERSION_NUMBER >= 0x900000) */ - { - char sub[2]; - sub[1]='\0'; - if(SSLEAY_VERSION_NUMBER&0x0f) { - sub[0]=(SSLEAY_VERSION_NUMBER&0x0f) + 'a' -1; - } - else - sub[0]='\0'; - - return snprintf(buffer, size, "SSL/%x.%x.%x%s", - (SSLEAY_VERSION_NUMBER>>12)&0xff, - (SSLEAY_VERSION_NUMBER>>8)&0xf, - (SSLEAY_VERSION_NUMBER>>4)&0xf, sub); - } -#endif /* (SSLEAY_VERSION_NUMBER >= 0x900000) */ -#endif /* SSLEAY_VERSION_NUMBER is less than 0.9.5 */ - -#endif /* YASSL_VERSION */ -} -#endif /* USE_SSLEAY */ diff --git a/third_party/curl/lib/ssluse.h b/third_party/curl/lib/ssluse.h deleted file mode 100644 index 2ac0ad2ec..000000000 --- a/third_party/curl/lib/ssluse.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef __SSLUSE_H -#define __SSLUSE_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#ifdef USE_SSLEAY -/* - * This header should only be needed to get included by sslgen.c and ssluse.c - */ - -#include "urldata.h" -CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex); -CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn, - int sockindex, - bool *done); - -/* close a SSL connection */ -void Curl_ossl_close(struct connectdata *conn, int sockindex); - -/* tell OpenSSL to close down all open information regarding connections (and - thus session ID caching etc) */ -int Curl_ossl_close_all(struct SessionHandle *data); - -/* Sets an OpenSSL engine */ -CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine); - -/* function provided for the generic SSL-layer, called when a session id - should be freed */ -void Curl_ossl_session_free(void *ptr); - -/* Sets engine as default for all SSL operations */ -CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data); - -/* Build list of OpenSSL engines */ -struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data); - -int Curl_ossl_init(void); -void Curl_ossl_cleanup(void); - -size_t Curl_ossl_version(char *buffer, size_t size); -int Curl_ossl_check_cxn(struct connectdata *cxn); -int Curl_ossl_seed(struct SessionHandle *data); - -int Curl_ossl_shutdown(struct connectdata *conn, int sockindex); -bool Curl_ossl_data_pending(const struct connectdata *conn, - int connindex); - -/* API setup for OpenSSL */ -#define curlssl_init Curl_ossl_init -#define curlssl_cleanup Curl_ossl_cleanup -#define curlssl_connect Curl_ossl_connect -#define curlssl_connect_nonblocking Curl_ossl_connect_nonblocking -#define curlssl_session_free(x) Curl_ossl_session_free(x) -#define curlssl_close_all Curl_ossl_close_all -#define curlssl_close Curl_ossl_close -#define curlssl_shutdown(x,y) Curl_ossl_shutdown(x,y) -#define curlssl_set_engine(x,y) Curl_ossl_set_engine(x,y) -#define curlssl_set_engine_default(x) Curl_ossl_set_engine_default(x) -#define curlssl_engines_list(x) Curl_ossl_engines_list(x) -#define curlssl_version Curl_ossl_version -#define curlssl_check_cxn Curl_ossl_check_cxn -#define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y) - -#endif /* USE_SSLEAY */ -#endif /* __SSLUSE_H */ diff --git a/third_party/curl/lib/strdup.c b/third_party/curl/lib/strdup.c deleted file mode 100644 index a3107cff7..000000000 --- a/third_party/curl/lib/strdup.c +++ /dev/null @@ -1,49 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" -#include "strdup.h" - -#ifndef HAVE_STRDUP -char *curlx_strdup(const char *str) -{ - size_t len; - char *newstr; - - if(!str) - return (char *)NULL; - - len = strlen(str); - - if(len >= ((size_t)-1) / sizeof(char)) - return (char *)NULL; - - newstr = malloc((len+1)*sizeof(char)); - if(!newstr) - return (char *)NULL; - - memcpy(newstr,str,(len+1)*sizeof(char)); - - return newstr; - -} -#endif diff --git a/third_party/curl/lib/strdup.h b/third_party/curl/lib/strdup.h deleted file mode 100644 index 4edbcd7d4..000000000 --- a/third_party/curl/lib/strdup.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef HEADER_CURL_STRDUP_H -#define HEADER_CURL_STRDUP_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef HAVE_STRDUP -extern char *curlx_strdup(const char *str); -#endif - -#endif /* HEADER_CURL_STRDUP_H */ diff --git a/third_party/curl/lib/strequal.c b/third_party/curl/lib/strequal.c deleted file mode 100644 index f6bf5f3b9..000000000 --- a/third_party/curl/lib/strequal.c +++ /dev/null @@ -1,121 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include - -#ifdef HAVE_STRINGS_H -#include -#endif - -#include "strequal.h" - -int curl_strequal(const char *first, const char *second) -{ -#if defined(HAVE_STRCASECMP) - return !(strcasecmp)(first, second); -#elif defined(HAVE_STRCMPI) - return !(strcmpi)(first, second); -#elif defined(HAVE_STRICMP) - return !(stricmp)(first, second); -#else - while(*first && *second) { - if(toupper(*first) != toupper(*second)) { - break; - } - first++; - second++; - } - return toupper(*first) == toupper(*second); -#endif -} - -int curl_strnequal(const char *first, const char *second, size_t max) -{ -#if defined(HAVE_STRNCASECMP) - return !strncasecmp(first, second, max); -#elif defined(HAVE_STRNCMPI) - return !strncmpi(first, second, max); -#elif defined(HAVE_STRNICMP) - return !strnicmp(first, second, max); -#else - while(*first && *second && max) { - if(toupper(*first) != toupper(*second)) { - break; - } - max--; - first++; - second++; - } - if(0 == max) - return 1; /* they are equal this far */ - - return toupper(*first) == toupper(*second); -#endif -} - -#ifndef HAVE_STRLCAT -/* - * The strlcat() function appends the NUL-terminated string src to the end - * of dst. It will append at most size - strlen(dst) - 1 bytes, NUL-termi- - * nating the result. - * - * The strlcpy() and strlcat() functions return the total length of the - * string they tried to create. For strlcpy() that means the length of src. - * For strlcat() that means the initial length of dst plus the length of - * src. While this may seem somewhat confusing it was done to make trunca- - * tion detection simple. - * - * - */ -size_t Curl_strlcat(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - union { - ssize_t sig; - size_t uns; - } dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while(n-- != 0 && *d != '\0') - d++; - dlen.sig = d - dst; - n = siz - dlen.uns; - - if(n == 0) - return(dlen.uns + strlen(s)); - while(*s != '\0') { - if(n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen.uns + (s - src)); /* count does not include NUL */ -} -#endif diff --git a/third_party/curl/lib/strequal.h b/third_party/curl/lib/strequal.h deleted file mode 100644 index 0c6d0b73f..000000000 --- a/third_party/curl/lib/strequal.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __STREQUAL_H -#define __STREQUAL_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 - -#define strequal(a,b) curl_strequal(a,b) -#define strnequal(a,b,c) curl_strnequal(a,b,c) - -#ifndef HAVE_STRLCAT -#define strlcat(x,y,z) Curl_strlcat(x,y,z) -size_t strlcat(char *dst, const char *src, size_t siz); -#endif - -#endif diff --git a/third_party/curl/lib/strerror.c b/third_party/curl/lib/strerror.c deleted file mode 100644 index 82851a05c..000000000 --- a/third_party/curl/lib/strerror.c +++ /dev/null @@ -1,778 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2004 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifdef HAVE_STRERROR_R -# if (!defined(HAVE_POSIX_STRERROR_R) && \ - !defined(HAVE_GLIBC_STRERROR_R) && \ - !defined(HAVE_VXWORKS_STRERROR_R)) || \ - (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ - (defined(HAVE_GLIBC_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ - (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)) -# error "strerror_r MUST be either POSIX-style, glibc-style or vxworks-style" -# endif -#endif - -#include -#include -#include -#include - -#ifdef USE_LIBIDN -#include -#endif - -#include "strerror.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - - -const char * -curl_easy_strerror(CURLcode error) -{ -#ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (error) { - case CURLE_OK: - return "No error"; - - case CURLE_UNSUPPORTED_PROTOCOL: - return "Unsupported protocol"; - - case CURLE_FAILED_INIT: - return "Failed initialization"; - - case CURLE_URL_MALFORMAT: - return "URL using bad/illegal format or missing URL"; - - case CURLE_NOT_BUILT_IN: - return "A requested feature, protocol or option was not found built-in in" - " this libcurl due to a build-time decision."; - - case CURLE_COULDNT_RESOLVE_PROXY: - return "Couldn't resolve proxy name"; - - case CURLE_COULDNT_RESOLVE_HOST: - return "Couldn't resolve host name"; - - case CURLE_COULDNT_CONNECT: - return "Couldn't connect to server"; - - case CURLE_FTP_WEIRD_SERVER_REPLY: - return "FTP: weird server reply"; - - case CURLE_REMOTE_ACCESS_DENIED: - return "Access denied to remote resource"; - - case CURLE_FTP_PRET_FAILED: - return "FTP: The server did not accept the PRET command."; - - case CURLE_FTP_WEIRD_PASS_REPLY: - return "FTP: unknown PASS reply"; - - case CURLE_FTP_WEIRD_PASV_REPLY: - return "FTP: unknown PASV reply"; - - case CURLE_FTP_WEIRD_227_FORMAT: - return "FTP: unknown 227 response format"; - - case CURLE_FTP_CANT_GET_HOST: - return "FTP: can't figure out the host in the PASV response"; - - case CURLE_FTP_COULDNT_SET_TYPE: - return "FTP: couldn't set file type"; - - case CURLE_PARTIAL_FILE: - return "Transferred a partial file"; - - case CURLE_FTP_COULDNT_RETR_FILE: - return "FTP: couldn't retrieve (RETR failed) the specified file"; - - case CURLE_QUOTE_ERROR: - return "Quote command returned error"; - - case CURLE_HTTP_RETURNED_ERROR: - return "HTTP response code said error"; - - case CURLE_WRITE_ERROR: - return "Failed writing received data to disk/application"; - - case CURLE_UPLOAD_FAILED: - return "Upload failed (at start/before it took off)"; - - case CURLE_READ_ERROR: - return "Failed to open/read local data from file/application"; - - case CURLE_OUT_OF_MEMORY: - return "Out of memory"; - - case CURLE_OPERATION_TIMEDOUT: - return "Timeout was reached"; - - case CURLE_FTP_PORT_FAILED: - return "FTP: command PORT failed"; - - case CURLE_FTP_COULDNT_USE_REST: - return "FTP: command REST failed"; - - case CURLE_RANGE_ERROR: - return "Requested range was not delivered by the server"; - - case CURLE_HTTP_POST_ERROR: - return "Internal problem setting up the POST"; - - case CURLE_SSL_CONNECT_ERROR: - return "SSL connect error"; - - case CURLE_BAD_DOWNLOAD_RESUME: - return "Couldn't resume download"; - - case CURLE_FILE_COULDNT_READ_FILE: - return "Couldn't read a file:// file"; - - case CURLE_LDAP_CANNOT_BIND: - return "LDAP: cannot bind"; - - case CURLE_LDAP_SEARCH_FAILED: - return "LDAP: search failed"; - - case CURLE_FUNCTION_NOT_FOUND: - return "A required function in the library was not found"; - - case CURLE_ABORTED_BY_CALLBACK: - return "Operation was aborted by an application callback"; - - case CURLE_BAD_FUNCTION_ARGUMENT: - return "A libcurl function was given a bad argument"; - - case CURLE_INTERFACE_FAILED: - return "Failed binding local connection end"; - - case CURLE_TOO_MANY_REDIRECTS : - return "Number of redirects hit maximum amount"; - - case CURLE_UNKNOWN_OPTION: - return "An unknown option was passed in to libcurl"; - - case CURLE_TELNET_OPTION_SYNTAX : - return "Malformed telnet option"; - - case CURLE_PEER_FAILED_VERIFICATION: - return "SSL peer certificate or SSH remote key was not OK"; - - case CURLE_GOT_NOTHING: - return "Server returned nothing (no headers, no data)"; - - case CURLE_SSL_ENGINE_NOTFOUND: - return "SSL crypto engine not found"; - - case CURLE_SSL_ENGINE_SETFAILED: - return "Can not set SSL crypto engine as default"; - - case CURLE_SSL_ENGINE_INITFAILED: - return "Failed to initialise SSL crypto engine"; - - case CURLE_SEND_ERROR: - return "Failed sending data to the peer"; - - case CURLE_RECV_ERROR: - return "Failure when receiving data from the peer"; - - case CURLE_SSL_CERTPROBLEM: - return "Problem with the local SSL certificate"; - - case CURLE_SSL_CIPHER: - return "Couldn't use specified SSL cipher"; - - case CURLE_SSL_CACERT: - return "Peer certificate cannot be authenticated with known CA certificates"; - - case CURLE_SSL_CACERT_BADFILE: - return "Problem with the SSL CA cert (path? access rights?)"; - - case CURLE_BAD_CONTENT_ENCODING: - return "Unrecognized or bad HTTP Content or Transfer-Encoding"; - - case CURLE_LDAP_INVALID_URL: - return "Invalid LDAP URL"; - - case CURLE_FILESIZE_EXCEEDED: - return "Maximum file size exceeded"; - - case CURLE_USE_SSL_FAILED: - return "Requested SSL level failed"; - - case CURLE_SSL_SHUTDOWN_FAILED: - return "Failed to shut down the SSL connection"; - - case CURLE_SSL_CRL_BADFILE: - return "Failed to load CRL file (path? access rights?, format?)"; - - case CURLE_SSL_ISSUER_ERROR: - return "Issuer check against peer certificate failed"; - - case CURLE_SEND_FAIL_REWIND: - return "Send failed since rewinding of the data stream failed"; - - case CURLE_LOGIN_DENIED: - return "Login denied"; - - case CURLE_TFTP_NOTFOUND: - return "TFTP: File Not Found"; - - case CURLE_TFTP_PERM: - return "TFTP: Access Violation"; - - case CURLE_REMOTE_DISK_FULL: - return "Disk full or allocation exceeded"; - - case CURLE_TFTP_ILLEGAL: - return "TFTP: Illegal operation"; - - case CURLE_TFTP_UNKNOWNID: - return "TFTP: Unknown transfer ID"; - - case CURLE_REMOTE_FILE_EXISTS: - return "Remote file already exists"; - - case CURLE_TFTP_NOSUCHUSER: - return "TFTP: No such user"; - - case CURLE_CONV_FAILED: - return "Conversion failed"; - - case CURLE_CONV_REQD: - return "Caller must register CURLOPT_CONV_ callback options"; - - case CURLE_REMOTE_FILE_NOT_FOUND: - return "Remote file not found"; - - case CURLE_SSH: - return "Error in the SSH layer"; - - case CURLE_AGAIN: - return "Socket not ready for send/recv"; - - case CURLE_RTSP_CSEQ_ERROR: - return "RTSP CSeq mismatch or invalid CSeq"; - - case CURLE_RTSP_SESSION_ERROR: - return "RTSP session error"; - - case CURLE_FTP_BAD_FILE_LIST: - return "Unable to parse FTP file list"; - - case CURLE_CHUNK_FAILED: - return "Chunk callback failed"; - - /* error codes not used by current libcurl */ - case CURLE_OBSOLETE10: - case CURLE_OBSOLETE12: - case CURLE_OBSOLETE16: - case CURLE_OBSOLETE20: - case CURLE_OBSOLETE24: - case CURLE_OBSOLETE29: - case CURLE_OBSOLETE32: - case CURLE_OBSOLETE40: - case CURLE_OBSOLETE44: - case CURLE_OBSOLETE46: - case CURLE_OBSOLETE50: - case CURLE_OBSOLETE57: - case CURL_LAST: - break; - } - /* - * By using a switch, gcc -Wall will complain about enum values - * which do not appear, helping keep this function up-to-date. - * By using gcc -Wall -Werror, you can't forget. - * - * A table would not have the same benefit. Most compilers will - * generate code very similar to a table in any case, so there - * is little performance gain from a table. And something is broken - * for the user's application, anyways, so does it matter how fast - * it _doesn't_ work? - * - * The line number for the error will be near this comment, which - * is why it is here, and not at the start of the switch. - */ - return "Unknown error"; -#else - if(error == CURLE_OK) - return "No error"; - else - return "Error"; -#endif -} - -const char * -curl_multi_strerror(CURLMcode error) -{ -#ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (error) { - case CURLM_CALL_MULTI_PERFORM: - return "Please call curl_multi_perform() soon"; - - case CURLM_OK: - return "No error"; - - case CURLM_BAD_HANDLE: - return "Invalid multi handle"; - - case CURLM_BAD_EASY_HANDLE: - return "Invalid easy handle"; - - case CURLM_OUT_OF_MEMORY: - return "Out of memory"; - - case CURLM_INTERNAL_ERROR: - return "Internal error"; - - case CURLM_BAD_SOCKET: - return "Invalid socket argument"; - - case CURLM_UNKNOWN_OPTION: - return "Unknown option"; - - case CURLM_LAST: - break; - } - - return "Unknown error"; -#else - if(error == CURLM_OK) - return "No error"; - else - return "Error"; -#endif -} - -const char * -curl_share_strerror(CURLSHcode error) -{ -#ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (error) { - case CURLSHE_OK: - return "No error"; - - case CURLSHE_BAD_OPTION: - return "Unknown share option"; - - case CURLSHE_IN_USE: - return "Share currently in use"; - - case CURLSHE_INVALID: - return "Invalid share handle"; - - case CURLSHE_NOMEM: - return "Out of memory"; - - case CURLSHE_LAST: - break; - } - - return "CURLSHcode unknown"; -#else - if(error == CURLSHE_OK) - return "No error"; - else - return "Error"; -#endif -} - -#ifdef USE_WINSOCK - -/* This function handles most / all (?) Winsock errors cURL is able to produce. - */ -static const char * -get_winsock_error (int err, char *buf, size_t len) -{ - const char *p; - -#ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (err) { - case WSAEINTR: - p = "Call interrupted"; - break; - case WSAEBADF: - p = "Bad file"; - break; - case WSAEACCES: - p = "Bad access"; - break; - case WSAEFAULT: - p = "Bad argument"; - break; - case WSAEINVAL: - p = "Invalid arguments"; - break; - case WSAEMFILE: - p = "Out of file descriptors"; - break; - case WSAEWOULDBLOCK: - p = "Call would block"; - break; - case WSAEINPROGRESS: - case WSAEALREADY: - p = "Blocking call in progress"; - break; - case WSAENOTSOCK: - p = "Descriptor is not a socket"; - break; - case WSAEDESTADDRREQ: - p = "Need destination address"; - break; - case WSAEMSGSIZE: - p = "Bad message size"; - break; - case WSAEPROTOTYPE: - p = "Bad protocol"; - break; - case WSAENOPROTOOPT: - p = "Protocol option is unsupported"; - break; - case WSAEPROTONOSUPPORT: - p = "Protocol is unsupported"; - break; - case WSAESOCKTNOSUPPORT: - p = "Socket is unsupported"; - break; - case WSAEOPNOTSUPP: - p = "Operation not supported"; - break; - case WSAEAFNOSUPPORT: - p = "Address family not supported"; - break; - case WSAEPFNOSUPPORT: - p = "Protocol family not supported"; - break; - case WSAEADDRINUSE: - p = "Address already in use"; - break; - case WSAEADDRNOTAVAIL: - p = "Address not available"; - break; - case WSAENETDOWN: - p = "Network down"; - break; - case WSAENETUNREACH: - p = "Network unreachable"; - break; - case WSAENETRESET: - p = "Network has been reset"; - break; - case WSAECONNABORTED: - p = "Connection was aborted"; - break; - case WSAECONNRESET: - p = "Connection was reset"; - break; - case WSAENOBUFS: - p = "No buffer space"; - break; - case WSAEISCONN: - p = "Socket is already connected"; - break; - case WSAENOTCONN: - p = "Socket is not connected"; - break; - case WSAESHUTDOWN: - p = "Socket has been shut down"; - break; - case WSAETOOMANYREFS: - p = "Too many references"; - break; - case WSAETIMEDOUT: - p = "Timed out"; - break; - case WSAECONNREFUSED: - p = "Connection refused"; - break; - case WSAELOOP: - p = "Loop??"; - break; - case WSAENAMETOOLONG: - p = "Name too long"; - break; - case WSAEHOSTDOWN: - p = "Host down"; - break; - case WSAEHOSTUNREACH: - p = "Host unreachable"; - break; - case WSAENOTEMPTY: - p = "Not empty"; - break; - case WSAEPROCLIM: - p = "Process limit reached"; - break; - case WSAEUSERS: - p = "Too many users"; - break; - case WSAEDQUOT: - p = "Bad quota"; - break; - case WSAESTALE: - p = "Something is stale"; - break; - case WSAEREMOTE: - p = "Remote error"; - break; -#ifdef WSAEDISCON /* missing in SalfordC! */ - case WSAEDISCON: - p = "Disconnected"; - break; -#endif - /* Extended Winsock errors */ - case WSASYSNOTREADY: - p = "Winsock library is not ready"; - break; - case WSANOTINITIALISED: - p = "Winsock library not initialised"; - break; - case WSAVERNOTSUPPORTED: - p = "Winsock version not supported"; - break; - - /* getXbyY() errors (already handled in herrmsg): - * Authoritative Answer: Host not found */ - case WSAHOST_NOT_FOUND: - p = "Host not found"; - break; - - /* Non-Authoritative: Host not found, or SERVERFAIL */ - case WSATRY_AGAIN: - p = "Host not found, try again"; - break; - - /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ - case WSANO_RECOVERY: - p = "Unrecoverable error in call to nameserver"; - break; - - /* Valid name, no data record of requested type */ - case WSANO_DATA: - p = "No data record of requested type"; - break; - - default: - return NULL; - } -#else - if(err == CURLE_OK) - return NULL; - else - p = "error"; -#endif - strncpy (buf, p, len); - buf [len-1] = '\0'; - return buf; -} -#endif /* USE_WINSOCK */ - -/* - * Our thread-safe and smart strerror() replacement. - * - * The 'err' argument passed in to this function MUST be a true errno number - * as reported on this system. We do no range checking on the number before - * we pass it to the "number-to-message" conversion function and there might - * be systems that don't do proper range checking in there themselves. - * - * We don't do range checking (on systems other than Windows) since there is - * no good reliable and portable way to do it. - */ -const char *Curl_strerror(struct connectdata *conn, int err) -{ - char *buf, *p; - size_t max; - int old_errno = ERRNO; - - DEBUGASSERT(conn); - DEBUGASSERT(err >= 0); - - buf = conn->syserr_buf; - max = sizeof(conn->syserr_buf)-1; - *buf = '\0'; - -#ifdef USE_WINSOCK - -#ifdef _WIN32_WCE - { - wchar_t wbuf[256]; - wbuf[0] = L'\0'; - - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, - LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL); - wcstombs(buf,wbuf,max); - } -#else - /* 'sys_nerr' is the maximum errno number, it is not widely portable */ - if(err >= 0 && err < sys_nerr) - strncpy(buf, strerror(err), max); - else { - if(!get_winsock_error(err, buf, max) && - !FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, - LANG_NEUTRAL, buf, (DWORD)max, NULL)) - snprintf(buf, max, "Unknown error %d (%#x)", err, err); - } -#endif - -#else /* not USE_WINSOCK coming up */ - -#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R) - /* - * The POSIX-style strerror_r() may set errno to ERANGE if insufficient - * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated - * message string, or EINVAL if 'errnum' is not a valid error number. - */ - if(0 != strerror_r(err, buf, max)) { - if('\0' == buf[0]) - snprintf(buf, max, "Unknown error %d", err); - } -#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R) - /* - * The glibc-style strerror_r() only *might* use the buffer we pass to - * the function, but it always returns the error message as a pointer, - * so we must copy that string unconditionally (if non-NULL). - */ - { - char buffer[256]; - char *msg = strerror_r(err, buffer, sizeof(buffer)); - if(msg) - strncpy(buf, msg, max); - else - snprintf(buf, max, "Unknown error %d", err); - } -#elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R) - /* - * The vxworks-style strerror_r() does use the buffer we pass to the function. - * The buffer size should be at least MAXERRSTR_SIZE (150) defined in rtsold.h - */ - { - char buffer[256]; - if(OK == strerror_r(err, buffer)) - strncpy(buf, buffer, max); - else - snprintf(buf, max, "Unknown error %d", err); - } -#else - { - char *msg = strerror(err); - if(msg) - strncpy(buf, msg, max); - else - snprintf(buf, max, "Unknown error %d", err); - } -#endif - -#endif /* end of ! USE_WINSOCK */ - - buf[max] = '\0'; /* make sure the string is zero terminated */ - - /* strip trailing '\r\n' or '\n'. */ - if((p = strrchr(buf,'\n')) != NULL && (p - buf) >= 2) - *p = '\0'; - if((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1) - *p = '\0'; - - if(old_errno != ERRNO) - SET_ERRNO(old_errno); - - return buf; -} - -#ifdef USE_LIBIDN -/* - * Return error-string for libidn status as returned from idna_to_ascii_lz(). - */ -const char *Curl_idn_strerror (struct connectdata *conn, int err) -{ -#ifdef HAVE_IDNA_STRERROR - (void)conn; - return idna_strerror((Idna_rc) err); -#else - const char *str; - char *buf; - size_t max; - - DEBUGASSERT(conn); - - buf = conn->syserr_buf; - max = sizeof(conn->syserr_buf)-1; - *buf = '\0'; - -#ifndef CURL_DISABLE_VERBOSE_STRINGS - switch ((Idna_rc)err) { - case IDNA_SUCCESS: - str = "No error"; - break; - case IDNA_STRINGPREP_ERROR: - str = "Error in string preparation"; - break; - case IDNA_PUNYCODE_ERROR: - str = "Error in Punycode operation"; - break; - case IDNA_CONTAINS_NON_LDH: - str = "Illegal ASCII characters"; - break; - case IDNA_CONTAINS_MINUS: - str = "Contains minus"; - break; - case IDNA_INVALID_LENGTH: - str = "Invalid output length"; - break; - case IDNA_NO_ACE_PREFIX: - str = "No ACE prefix (\"xn--\")"; - break; - case IDNA_ROUNDTRIP_VERIFY_ERROR: - str = "Round trip verify error"; - break; - case IDNA_CONTAINS_ACE_PREFIX: - str = "Already have ACE prefix (\"xn--\")"; - break; - case IDNA_ICONV_ERROR: - str = "Locale conversion failed"; - break; - case IDNA_MALLOC_ERROR: - str = "Allocation failed"; - break; - case IDNA_DLOPEN_ERROR: - str = "dlopen() error"; - break; - default: - snprintf(buf, max, "error %d", err); - str = NULL; - break; - } -#else - if((Idna_rc)err == IDNA_SUCCESS) - str = "No error"; - else - str = "Error"; -#endif - if(str) - strncpy(buf, str, max); - buf[max] = '\0'; - return (buf); -#endif -} -#endif /* USE_LIBIDN */ diff --git a/third_party/curl/lib/strerror.h b/third_party/curl/lib/strerror.h deleted file mode 100644 index 7f2342aea..000000000 --- a/third_party/curl/lib/strerror.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __CURL_STRERROR_H -#define __CURL_STRERROR_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#include "urldata.h" - -const char *Curl_strerror (struct connectdata *conn, int err); - -#ifdef USE_LIBIDN -const char *Curl_idn_strerror (struct connectdata *conn, int err); -#endif - -#endif diff --git a/third_party/curl/lib/strtok.c b/third_party/curl/lib/strtok.c deleted file mode 100644 index 91c254156..000000000 --- a/third_party/curl/lib/strtok.c +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef HAVE_STRTOK_R -#include -#include - -#include "strtok.h" - -char * -Curl_strtok_r(char *ptr, const char *sep, char **end) -{ - if(!ptr) - /* we got NULL input so then we get our last position instead */ - ptr = *end; - - /* pass all letters that are including in the separator string */ - while(*ptr && strchr(sep, *ptr)) - ++ptr; - - if(*ptr) { - /* so this is where the next piece of string starts */ - char *start = ptr; - - /* set the end pointer to the first byte after the start */ - *end = start + 1; - - /* scan through the string to find where it ends, it ends on a - null byte or a character that exists in the separator string */ - while(**end && !strchr(sep, **end)) - ++*end; - - if(**end) { - /* the end is not a null byte */ - **end = '\0'; /* zero terminate it! */ - ++*end; /* advance the last pointer to beyond the null byte */ - } - - return start; /* return the position where the string starts */ - } - - /* we ended up on a null byte, there are no more strings to find! */ - return NULL; -} - -#endif /* this was only compiled if strtok_r wasn't present */ diff --git a/third_party/curl/lib/strtok.h b/third_party/curl/lib/strtok.h deleted file mode 100644 index 8baf77948..000000000 --- a/third_party/curl/lib/strtok.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef HEADER_CURL_STRTOK_H -#define HEADER_CURL_STRTOK_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" -#include - -#ifndef HAVE_STRTOK_R -char *Curl_strtok_r(char *s, const char *delim, char **last); -#define strtok_r Curl_strtok_r -#else -#include -#endif - -#endif /* HEADER_CURL_STRTOK_H */ diff --git a/third_party/curl/lib/strtoofft.c b/third_party/curl/lib/strtoofft.c deleted file mode 100644 index 61ff05bed..000000000 --- a/third_party/curl/lib/strtoofft.c +++ /dev/null @@ -1,191 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" -#include "strtoofft.h" - -/* - * NOTE: - * - * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we - * could use in case strtoll() doesn't exist... See - * http://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html - */ - -#ifdef NEED_CURL_STRTOLL -#include -#include -#include - -/* Range tests can be used for alphanum decoding if characters are consecutive, - like in ASCII. Else an array is scanned. Determine this condition now. */ - -#if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25 -#include - -#define NO_RANGE_TEST - -static const char valchars[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -#endif - -static int get_char(char c, int base); - -/** - * Emulated version of the strtoll function. This extracts a long long - * value from the given input string and returns it. - */ -curl_off_t -curlx_strtoll(const char *nptr, char **endptr, int base) -{ - char *end; - int is_negative = 0; - int overflow; - int i; - curl_off_t value = 0; - curl_off_t newval; - - /* Skip leading whitespace. */ - end = (char *)nptr; - while(ISSPACE(end[0])) { - end++; - } - - /* Handle the sign, if any. */ - if(end[0] == '-') { - is_negative = 1; - end++; - } - else if(end[0] == '+') { - end++; - } - else if(end[0] == '\0') { - /* We had nothing but perhaps some whitespace -- there was no number. */ - if(endptr) { - *endptr = end; - } - return 0; - } - - /* Handle special beginnings, if present and allowed. */ - if(end[0] == '0' && end[1] == 'x') { - if(base == 16 || base == 0) { - end += 2; - base = 16; - } - } - else if(end[0] == '0') { - if(base == 8 || base == 0) { - end++; - base = 8; - } - } - - /* Matching strtol, if the base is 0 and it doesn't look like - * the number is octal or hex, we assume it's base 10. - */ - if(base == 0) { - base = 10; - } - - /* Loop handling digits. */ - value = 0; - overflow = 0; - for (i = get_char(end[0], base); - i != -1; - end++, i = get_char(end[0], base)) { - newval = base * value + i; - if(newval < value) { - /* We've overflowed. */ - overflow = 1; - break; - } - else - value = newval; - } - - if(!overflow) { - if(is_negative) { - /* Fix the sign. */ - value *= -1; - } - } - else { - if(is_negative) - value = CURL_OFF_T_MIN; - else - value = CURL_OFF_T_MAX; - - SET_ERRNO(ERANGE); - } - - if(endptr) - *endptr = end; - - return value; -} - -/** - * Returns the value of c in the given base, or -1 if c cannot - * be interpreted properly in that base (i.e., is out of range, - * is a null, etc.). - * - * @param c the character to interpret according to base - * @param base the base in which to interpret c - * - * @return the value of c in base, or -1 if c isn't in range - */ -static int get_char(char c, int base) -{ -#ifndef NO_RANGE_TEST - int value = -1; - if(c <= '9' && c >= '0') { - value = c - '0'; - } - else if(c <= 'Z' && c >= 'A') { - value = c - 'A' + 10; - } - else if(c <= 'z' && c >= 'a') { - value = c - 'a' + 10; - } -#else - const char * cp; - int value; - - cp = memchr(valchars, c, 10 + 26 + 26); - - if(!cp) - return -1; - - value = cp - valchars; - - if(value >= 10 + 26) - value -= 26; /* Lowercase. */ -#endif - - if(value >= base) { - value = -1; - } - - return value; -} -#endif /* Only present if we need strtoll, but don't have it. */ diff --git a/third_party/curl/lib/strtoofft.h b/third_party/curl/lib/strtoofft.h deleted file mode 100644 index 08b0e6d91..000000000 --- a/third_party/curl/lib/strtoofft.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef HEADER_CURL_STRTOOFFT_H -#define HEADER_CURL_STRTOOFFT_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -/* - * Determine which string to integral data type conversion function we use - * to implement string conversion to our curl_off_t integral data type. - * - * Notice that curl_off_t might be 64 or 32 bit wide, and that it might use - * an underlying data type which might be 'long', 'int64_t', 'long long' or - * '__int64' and more remotely other data types. - * - * On systems where the size of curl_off_t is greater than the size of 'long' - * the conversion function to use is strtoll() if it is available, otherwise, - * we emulate its functionality with our own clone. - * - * On systems where the size of curl_off_t is smaller or equal than the size - * of 'long' the conversion function to use is strtol(). - */ - -#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) -# ifdef HAVE_STRTOLL -# define curlx_strtoofft strtoll -# else -# if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64) - _CRTIMP __int64 __cdecl _strtoi64(const char *, char **, int); -# define curlx_strtoofft _strtoi64 -# else - curl_off_t curlx_strtoll(const char *nptr, char **endptr, int base); -# define curlx_strtoofft curlx_strtoll -# define NEED_CURL_STRTOLL 1 -# endif -# endif -#else -# define curlx_strtoofft strtol -#endif - -#if (CURL_SIZEOF_CURL_OFF_T == 4) -# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF) -#else - /* assume CURL_SIZEOF_CURL_OFF_T == 8 */ -# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF) -#endif -#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1)) - -#endif /* HEADER_CURL_STRTOOFFT_H */ diff --git a/third_party/curl/lib/telnet.c b/third_party/curl/lib/telnet.c deleted file mode 100644 index 53f33e9a2..000000000 --- a/third_party/curl/lib/telnet.c +++ /dev/null @@ -1,1559 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef CURL_DISABLE_TELNET -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include - -#if defined(WIN32) -#include -#include -#else -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#endif /* WIN32 */ - -#include "urldata.h" -#include -#include "transfer.h" -#include "sendf.h" -#include "telnet.h" -#include "connect.h" -#include "progress.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#define TELOPTS -#define TELCMDS - -#include "arpa_telnet.h" -#include "curl_memory.h" -#include "select.h" -#include "strequal.h" -#include "rawstr.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -#define SUBBUFSIZE 512 - -#define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer; -#define CURL_SB_TERM(x) { x->subend = x->subpointer; CURL_SB_CLEAR(x); } -#define CURL_SB_ACCUM(x,c) \ - if(x->subpointer < (x->subbuffer+sizeof x->subbuffer)) { \ - *x->subpointer++ = (c); \ - } - -#define CURL_SB_GET(x) ((*x->subpointer++)&0xff) -#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff) -#define CURL_SB_EOF(x) (x->subpointer >= x->subend) -#define CURL_SB_LEN(x) (x->subend - x->subpointer) - -#ifdef CURL_DISABLE_VERBOSE_STRINGS -#define printoption(a,b,c,d) do { } while(0) -#endif - -#ifdef USE_WINSOCK -typedef FARPROC WSOCK2_FUNC; -static CURLcode check_wsock2 ( struct SessionHandle *data ); -#endif - -static -CURLcode telrcv(struct connectdata *, - const unsigned char *inbuf, /* Data received from socket */ - ssize_t count); /* Number of bytes received */ - -#ifndef CURL_DISABLE_VERBOSE_STRINGS -static void printoption(struct SessionHandle *data, - const char *direction, - int cmd, int option); -#endif - -static void negotiate(struct connectdata *); -static void send_negotiation(struct connectdata *, int cmd, int option); -static void set_local_option(struct connectdata *, int cmd, int option); -static void set_remote_option(struct connectdata *, int cmd, int option); - -static void printsub(struct SessionHandle *data, - int direction, unsigned char *pointer, - size_t length); -static void suboption(struct connectdata *); - -static CURLcode telnet_do(struct connectdata *conn, bool *done); -static CURLcode telnet_done(struct connectdata *conn, - CURLcode, bool premature); - -/* For negotiation compliant to RFC 1143 */ -#define CURL_NO 0 -#define CURL_YES 1 -#define CURL_WANTYES 2 -#define CURL_WANTNO 3 - -#define CURL_EMPTY 0 -#define CURL_OPPOSITE 1 - -/* - * Telnet receiver states for fsm - */ -typedef enum -{ - CURL_TS_DATA = 0, - CURL_TS_IAC, - CURL_TS_WILL, - CURL_TS_WONT, - CURL_TS_DO, - CURL_TS_DONT, - CURL_TS_CR, - CURL_TS_SB, /* sub-option collection */ - CURL_TS_SE /* looking for sub-option end */ -} TelnetReceive; - -struct TELNET { - int please_negotiate; - int already_negotiated; - int us[256]; - int usq[256]; - int us_preferred[256]; - int him[256]; - int himq[256]; - int him_preferred[256]; - char subopt_ttype[32]; /* Set with suboption TTYPE */ - char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */ - struct curl_slist *telnet_vars; /* Environment variables */ - - /* suboptions */ - unsigned char subbuffer[SUBBUFSIZE]; - unsigned char *subpointer, *subend; /* buffer for sub-options */ - - TelnetReceive telrcv_state; -}; - - -/* - * TELNET protocol handler. - */ - -const struct Curl_handler Curl_handler_telnet = { - "TELNET", /* scheme */ - ZERO_NULL, /* setup_connection */ - telnet_do, /* do_it */ - telnet_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - PORT_TELNET, /* defport */ - CURLPROTO_TELNET, /* protocol */ - PROTOPT_NONE /* flags */ -}; - - -#ifdef USE_WINSOCK -static CURLcode -check_wsock2 ( struct SessionHandle *data ) -{ - int err; - WORD wVersionRequested; - WSADATA wsaData; - - DEBUGASSERT(data); - - /* telnet requires at least WinSock 2.0 so ask for it. */ - wVersionRequested = MAKEWORD(2, 0); - - err = WSAStartup(wVersionRequested, &wsaData); - - /* We must've called this once already, so this call */ - /* should always succeed. But, just in case... */ - if(err != 0) { - failf(data,"WSAStartup failed (%d)",err); - return CURLE_FAILED_INIT; - } - - /* We have to have a WSACleanup call for every successful */ - /* WSAStartup call. */ - WSACleanup(); - - /* Check that our version is supported */ - if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || - HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) { - /* Our version isn't supported */ - failf(data,"insufficient winsock version to support " - "telnet"); - return CURLE_FAILED_INIT; - } - - /* Our version is supported */ - return CURLE_OK; -} -#endif - -static -CURLcode init_telnet(struct connectdata *conn) -{ - struct TELNET *tn; - - tn = calloc(1, sizeof(struct TELNET)); - if(!tn) - return CURLE_OUT_OF_MEMORY; - - conn->data->state.proto.telnet = (void *)tn; /* make us known */ - - tn->telrcv_state = CURL_TS_DATA; - - /* Init suboptions */ - CURL_SB_CLEAR(tn); - - /* Set the options we want by default */ - tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES; - tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES; - tn->him_preferred[CURL_TELOPT_BINARY] = CURL_YES; - tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES; - - return CURLE_OK; -} - -static void negotiate(struct connectdata *conn) -{ - int i; - struct TELNET *tn = (struct TELNET *) conn->data->state.proto.telnet; - - for(i = 0;i < CURL_NTELOPTS;i++) - { - if(tn->us_preferred[i] == CURL_YES) - set_local_option(conn, i, CURL_YES); - - if(tn->him_preferred[i] == CURL_YES) - set_remote_option(conn, i, CURL_YES); - } -} - -#ifndef CURL_DISABLE_VERBOSE_STRINGS -static void printoption(struct SessionHandle *data, - const char *direction, int cmd, int option) -{ - const char *fmt; - const char *opt; - - if(data->set.verbose) - { - if(cmd == CURL_IAC) - { - if(CURL_TELCMD_OK(option)) - infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option)); - else - infof(data, "%s IAC %d\n", direction, option); - } - else - { - fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" : - (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0; - if(fmt) - { - if(CURL_TELOPT_OK(option)) - opt = CURL_TELOPT(option); - else if(option == CURL_TELOPT_EXOPL) - opt = "EXOPL"; - else - opt = NULL; - - if(opt) - infof(data, "%s %s %s\n", direction, fmt, opt); - else - infof(data, "%s %s %d\n", direction, fmt, option); - } - else - infof(data, "%s %d %d\n", direction, cmd, option); - } - } -} -#endif - -static void send_negotiation(struct connectdata *conn, int cmd, int option) -{ - unsigned char buf[3]; - ssize_t bytes_written; - int err; - struct SessionHandle *data = conn->data; - - buf[0] = CURL_IAC; - buf[1] = (unsigned char)cmd; - buf[2] = (unsigned char)option; - - bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3); - if(bytes_written < 0) { - err = SOCKERRNO; - failf(data,"Sending data failed (%d)",err); - } - - printoption(conn->data, "SENT", cmd, option); -} - -static -void set_remote_option(struct connectdata *conn, int option, int newstate) -{ - struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet; - if(newstate == CURL_YES) - { - switch(tn->him[option]) - { - case CURL_NO: - tn->him[option] = CURL_WANTYES; - send_negotiation(conn, CURL_DO, option); - break; - - case CURL_YES: - /* Already enabled */ - break; - - case CURL_WANTNO: - switch(tn->himq[option]) - { - case CURL_EMPTY: - /* Already negotiating for CURL_YES, queue the request */ - tn->himq[option] = CURL_OPPOSITE; - break; - case CURL_OPPOSITE: - /* Error: already queued an enable request */ - break; - } - break; - - case CURL_WANTYES: - switch(tn->himq[option]) - { - case CURL_EMPTY: - /* Error: already negotiating for enable */ - break; - case CURL_OPPOSITE: - tn->himq[option] = CURL_EMPTY; - break; - } - break; - } - } - else /* NO */ - { - switch(tn->him[option]) - { - case CURL_NO: - /* Already disabled */ - break; - - case CURL_YES: - tn->him[option] = CURL_WANTNO; - send_negotiation(conn, CURL_DONT, option); - break; - - case CURL_WANTNO: - switch(tn->himq[option]) - { - case CURL_EMPTY: - /* Already negotiating for NO */ - break; - case CURL_OPPOSITE: - tn->himq[option] = CURL_EMPTY; - break; - } - break; - - case CURL_WANTYES: - switch(tn->himq[option]) - { - case CURL_EMPTY: - tn->himq[option] = CURL_OPPOSITE; - break; - case CURL_OPPOSITE: - break; - } - break; - } - } -} - -static -void rec_will(struct connectdata *conn, int option) -{ - struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet; - switch(tn->him[option]) - { - case CURL_NO: - if(tn->him_preferred[option] == CURL_YES) - { - tn->him[option] = CURL_YES; - send_negotiation(conn, CURL_DO, option); - } - else - { - send_negotiation(conn, CURL_DONT, option); - } - break; - - case CURL_YES: - /* Already enabled */ - break; - - case CURL_WANTNO: - switch(tn->himq[option]) - { - case CURL_EMPTY: - /* Error: DONT answered by WILL */ - tn->him[option] = CURL_NO; - break; - case CURL_OPPOSITE: - /* Error: DONT answered by WILL */ - tn->him[option] = CURL_YES; - tn->himq[option] = CURL_EMPTY; - break; - } - break; - - case CURL_WANTYES: - switch(tn->himq[option]) - { - case CURL_EMPTY: - tn->him[option] = CURL_YES; - break; - case CURL_OPPOSITE: - tn->him[option] = CURL_WANTNO; - tn->himq[option] = CURL_EMPTY; - send_negotiation(conn, CURL_DONT, option); - break; - } - break; - } -} - -static -void rec_wont(struct connectdata *conn, int option) -{ - struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet; - switch(tn->him[option]) - { - case CURL_NO: - /* Already disabled */ - break; - - case CURL_YES: - tn->him[option] = CURL_NO; - send_negotiation(conn, CURL_DONT, option); - break; - - case CURL_WANTNO: - switch(tn->himq[option]) - { - case CURL_EMPTY: - tn->him[option] = CURL_NO; - break; - - case CURL_OPPOSITE: - tn->him[option] = CURL_WANTYES; - tn->himq[option] = CURL_EMPTY; - send_negotiation(conn, CURL_DO, option); - break; - } - break; - - case CURL_WANTYES: - switch(tn->himq[option]) - { - case CURL_EMPTY: - tn->him[option] = CURL_NO; - break; - case CURL_OPPOSITE: - tn->him[option] = CURL_NO; - tn->himq[option] = CURL_EMPTY; - break; - } - break; - } -} - -static void -set_local_option(struct connectdata *conn, int option, int newstate) -{ - struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet; - if(newstate == CURL_YES) - { - switch(tn->us[option]) - { - case CURL_NO: - tn->us[option] = CURL_WANTYES; - send_negotiation(conn, CURL_WILL, option); - break; - - case CURL_YES: - /* Already enabled */ - break; - - case CURL_WANTNO: - switch(tn->usq[option]) - { - case CURL_EMPTY: - /* Already negotiating for CURL_YES, queue the request */ - tn->usq[option] = CURL_OPPOSITE; - break; - case CURL_OPPOSITE: - /* Error: already queued an enable request */ - break; - } - break; - - case CURL_WANTYES: - switch(tn->usq[option]) - { - case CURL_EMPTY: - /* Error: already negotiating for enable */ - break; - case CURL_OPPOSITE: - tn->usq[option] = CURL_EMPTY; - break; - } - break; - } - } - else /* NO */ - { - switch(tn->us[option]) - { - case CURL_NO: - /* Already disabled */ - break; - - case CURL_YES: - tn->us[option] = CURL_WANTNO; - send_negotiation(conn, CURL_WONT, option); - break; - - case CURL_WANTNO: - switch(tn->usq[option]) - { - case CURL_EMPTY: - /* Already negotiating for NO */ - break; - case CURL_OPPOSITE: - tn->usq[option] = CURL_EMPTY; - break; - } - break; - - case CURL_WANTYES: - switch(tn->usq[option]) - { - case CURL_EMPTY: - tn->usq[option] = CURL_OPPOSITE; - break; - case CURL_OPPOSITE: - break; - } - break; - } - } -} - -static -void rec_do(struct connectdata *conn, int option) -{ - struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet; - switch(tn->us[option]) - { - case CURL_NO: - if(tn->us_preferred[option] == CURL_YES) - { - tn->us[option] = CURL_YES; - send_negotiation(conn, CURL_WILL, option); - } - else - { - send_negotiation(conn, CURL_WONT, option); - } - break; - - case CURL_YES: - /* Already enabled */ - break; - - case CURL_WANTNO: - switch(tn->usq[option]) - { - case CURL_EMPTY: - /* Error: DONT answered by WILL */ - tn->us[option] = CURL_NO; - break; - case CURL_OPPOSITE: - /* Error: DONT answered by WILL */ - tn->us[option] = CURL_YES; - tn->usq[option] = CURL_EMPTY; - break; - } - break; - - case CURL_WANTYES: - switch(tn->usq[option]) - { - case CURL_EMPTY: - tn->us[option] = CURL_YES; - break; - case CURL_OPPOSITE: - tn->us[option] = CURL_WANTNO; - tn->himq[option] = CURL_EMPTY; - send_negotiation(conn, CURL_WONT, option); - break; - } - break; - } -} - -static -void rec_dont(struct connectdata *conn, int option) -{ - struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet; - switch(tn->us[option]) - { - case CURL_NO: - /* Already disabled */ - break; - - case CURL_YES: - tn->us[option] = CURL_NO; - send_negotiation(conn, CURL_WONT, option); - break; - - case CURL_WANTNO: - switch(tn->usq[option]) - { - case CURL_EMPTY: - tn->us[option] = CURL_NO; - break; - - case CURL_OPPOSITE: - tn->us[option] = CURL_WANTYES; - tn->usq[option] = CURL_EMPTY; - send_negotiation(conn, CURL_WILL, option); - break; - } - break; - - case CURL_WANTYES: - switch(tn->usq[option]) - { - case CURL_EMPTY: - tn->us[option] = CURL_NO; - break; - case CURL_OPPOSITE: - tn->us[option] = CURL_NO; - tn->usq[option] = CURL_EMPTY; - break; - } - break; - } -} - - -static void printsub(struct SessionHandle *data, - int direction, /* '<' or '>' */ - unsigned char *pointer, /* where suboption data is */ - size_t length) /* length of suboption data */ -{ - unsigned int i = 0; - - if(data->set.verbose) - { - if(direction) - { - infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT"); - if(length >= 3) - { - int j; - - i = pointer[length-2]; - j = pointer[length-1]; - - if(i != CURL_IAC || j != CURL_SE) - { - infof(data, "(terminated by "); - if(CURL_TELOPT_OK(i)) - infof(data, "%s ", CURL_TELOPT(i)); - else if(CURL_TELCMD_OK(i)) - infof(data, "%s ", CURL_TELCMD(i)); - else - infof(data, "%u ", i); - if(CURL_TELOPT_OK(j)) - infof(data, "%s", CURL_TELOPT(j)); - else if(CURL_TELCMD_OK(j)) - infof(data, "%s", CURL_TELCMD(j)); - else - infof(data, "%d", j); - infof(data, ", not IAC SE!) "); - } - } - length -= 2; - } - if(length < 1) - { - infof(data, "(Empty suboption?)"); - return; - } - - if(CURL_TELOPT_OK(pointer[0])) { - switch(pointer[0]) { - case CURL_TELOPT_TTYPE: - case CURL_TELOPT_XDISPLOC: - case CURL_TELOPT_NEW_ENVIRON: - infof(data, "%s", CURL_TELOPT(pointer[0])); - break; - default: - infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0])); - break; - } - } - else - infof(data, "%d (unknown)", pointer[i]); - - switch(pointer[1]) { - case CURL_TELQUAL_IS: - infof(data, " IS"); - break; - case CURL_TELQUAL_SEND: - infof(data, " SEND"); - break; - case CURL_TELQUAL_INFO: - infof(data, " INFO/REPLY"); - break; - case CURL_TELQUAL_NAME: - infof(data, " NAME"); - break; - } - - switch(pointer[0]) { - case CURL_TELOPT_TTYPE: - case CURL_TELOPT_XDISPLOC: - pointer[length] = 0; - infof(data, " \"%s\"", &pointer[2]); - break; - case CURL_TELOPT_NEW_ENVIRON: - if(pointer[1] == CURL_TELQUAL_IS) { - infof(data, " "); - for(i = 3;i < length;i++) { - switch(pointer[i]) { - case CURL_NEW_ENV_VAR: - infof(data, ", "); - break; - case CURL_NEW_ENV_VALUE: - infof(data, " = "); - break; - default: - infof(data, "%c", pointer[i]); - break; - } - } - } - break; - default: - for (i = 2; i < length; i++) - infof(data, " %.2x", pointer[i]); - break; - } - - if(direction) - { - infof(data, "\n"); - } - } -} - -static CURLcode check_telnet_options(struct connectdata *conn) -{ - struct curl_slist *head; - char option_keyword[128]; - char option_arg[256]; - char *buf; - struct SessionHandle *data = conn->data; - struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet; - - /* Add the user name as an environment variable if it - was given on the command line */ - if(conn->bits.user_passwd) - { - snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user); - tn->telnet_vars = curl_slist_append(tn->telnet_vars, option_arg); - - tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; - } - - for(head = data->set.telnet_options; head; head=head->next) { - if(sscanf(head->data, "%127[^= ]%*[ =]%255s", - option_keyword, option_arg) == 2) { - - /* Terminal type */ - if(Curl_raw_equal(option_keyword, "TTYPE")) { - strncpy(tn->subopt_ttype, option_arg, 31); - tn->subopt_ttype[31] = 0; /* String termination */ - tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES; - continue; - } - - /* Display variable */ - if(Curl_raw_equal(option_keyword, "XDISPLOC")) { - strncpy(tn->subopt_xdisploc, option_arg, 127); - tn->subopt_xdisploc[127] = 0; /* String termination */ - tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES; - continue; - } - - /* Environment variable */ - if(Curl_raw_equal(option_keyword, "NEW_ENV")) { - buf = strdup(option_arg); - if(!buf) - return CURLE_OUT_OF_MEMORY; - tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf); - tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; - continue; - } - - failf(data, "Unknown telnet option %s", head->data); - return CURLE_UNKNOWN_TELNET_OPTION; - } else { - failf(data, "Syntax error in telnet option: %s", head->data); - return CURLE_TELNET_OPTION_SYNTAX; - } - } - - return CURLE_OK; -} - -/* - * suboption() - * - * Look at the sub-option buffer, and try to be helpful to the other - * side. - */ - -static void suboption(struct connectdata *conn) -{ - struct curl_slist *v; - unsigned char temp[2048]; - ssize_t bytes_written; - size_t len; - size_t tmplen; - int err; - char varname[128]; - char varval[128]; - struct SessionHandle *data = conn->data; - struct TELNET *tn = (struct TELNET *)data->state.proto.telnet; - - printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2); - switch (CURL_SB_GET(tn)) { - case CURL_TELOPT_TTYPE: - len = strlen(tn->subopt_ttype) + 4 + 2; - snprintf((char *)temp, sizeof(temp), - "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE, - CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE); - bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); - if(bytes_written < 0) { - err = SOCKERRNO; - failf(data,"Sending data failed (%d)",err); - } - printsub(data, '>', &temp[2], len-2); - break; - case CURL_TELOPT_XDISPLOC: - len = strlen(tn->subopt_xdisploc) + 4 + 2; - snprintf((char *)temp, sizeof(temp), - "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC, - CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE); - bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); - if(bytes_written < 0) { - err = SOCKERRNO; - failf(data,"Sending data failed (%d)",err); - } - printsub(data, '>', &temp[2], len-2); - break; - case CURL_TELOPT_NEW_ENVIRON: - snprintf((char *)temp, sizeof(temp), - "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON, - CURL_TELQUAL_IS); - len = 4; - - for(v = tn->telnet_vars;v;v = v->next) { - tmplen = (strlen(v->data) + 1); - /* Add the variable only if it fits */ - if(len + tmplen < (int)sizeof(temp)-6) { - sscanf(v->data, "%127[^,],%127s", varname, varval); - snprintf((char *)&temp[len], sizeof(temp) - len, - "%c%s%c%s", CURL_NEW_ENV_VAR, varname, - CURL_NEW_ENV_VALUE, varval); - len += tmplen; - } - } - snprintf((char *)&temp[len], sizeof(temp) - len, - "%c%c", CURL_IAC, CURL_SE); - len += 2; - bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); - if(bytes_written < 0) { - err = SOCKERRNO; - failf(data,"Sending data failed (%d)",err); - } - printsub(data, '>', &temp[2], len-2); - break; - } - return; -} - -static -CURLcode telrcv(struct connectdata *conn, - const unsigned char *inbuf, /* Data received from socket */ - ssize_t count) /* Number of bytes received */ -{ - unsigned char c; - CURLcode result; - int in = 0; - int startwrite=-1; - struct SessionHandle *data = conn->data; - struct TELNET *tn = (struct TELNET *)data->state.proto.telnet; - -#define startskipping() \ - if(startwrite >= 0) { \ - result = Curl_client_write(conn, \ - CLIENTWRITE_BODY, \ - (char *)&inbuf[startwrite], \ - in-startwrite); \ - if(result != CURLE_OK) \ - return result; \ - } \ - startwrite = -1 - -#define writebyte() \ - if(startwrite < 0) \ - startwrite = in - -#define bufferflush() startskipping() - - while(count--) - { - c = inbuf[in]; - - /*infof(data,"In rcv state %d char %d\n", tn->telrcv_state, c);*/ - switch (tn->telrcv_state) - { - case CURL_TS_CR: - tn->telrcv_state = CURL_TS_DATA; - if(c == '\0') - { - startskipping(); - break; /* Ignore \0 after CR */ - } - writebyte(); - break; - - case CURL_TS_DATA: - if(c == CURL_IAC) - { - tn->telrcv_state = CURL_TS_IAC; - startskipping(); - break; - } - else if(c == '\r') - { - tn->telrcv_state = CURL_TS_CR; - } - writebyte(); - break; - - case CURL_TS_IAC: - process_iac: - DEBUGASSERT(startwrite < 0); - switch (c) - { - case CURL_WILL: - tn->telrcv_state = CURL_TS_WILL; - break; - case CURL_WONT: - tn->telrcv_state = CURL_TS_WONT; - break; - case CURL_DO: - tn->telrcv_state = CURL_TS_DO; - break; - case CURL_DONT: - tn->telrcv_state = CURL_TS_DONT; - break; - case CURL_SB: - CURL_SB_CLEAR(tn); - tn->telrcv_state = CURL_TS_SB; - break; - case CURL_IAC: - tn->telrcv_state = CURL_TS_DATA; - writebyte(); - break; - case CURL_DM: - case CURL_NOP: - case CURL_GA: - default: - tn->telrcv_state = CURL_TS_DATA; - printoption(data, "RCVD", CURL_IAC, c); - break; - } - break; - - case CURL_TS_WILL: - printoption(data, "RCVD", CURL_WILL, c); - tn->please_negotiate = 1; - rec_will(conn, c); - tn->telrcv_state = CURL_TS_DATA; - break; - - case CURL_TS_WONT: - printoption(data, "RCVD", CURL_WONT, c); - tn->please_negotiate = 1; - rec_wont(conn, c); - tn->telrcv_state = CURL_TS_DATA; - break; - - case CURL_TS_DO: - printoption(data, "RCVD", CURL_DO, c); - tn->please_negotiate = 1; - rec_do(conn, c); - tn->telrcv_state = CURL_TS_DATA; - break; - - case CURL_TS_DONT: - printoption(data, "RCVD", CURL_DONT, c); - tn->please_negotiate = 1; - rec_dont(conn, c); - tn->telrcv_state = CURL_TS_DATA; - break; - - case CURL_TS_SB: - if(c == CURL_IAC) - { - tn->telrcv_state = CURL_TS_SE; - } - else - { - CURL_SB_ACCUM(tn,c); - } - break; - - case CURL_TS_SE: - if(c != CURL_SE) - { - if(c != CURL_IAC) - { - /* - * This is an error. We only expect to get "IAC IAC" or "IAC SE". - * Several things may have happened. An IAC was not doubled, the - * IAC SE was left off, or another option got inserted into the - * suboption are all possibilities. If we assume that the IAC was - * not doubled, and really the IAC SE was left off, we could get - * into an infinate loop here. So, instead, we terminate the - * suboption, and process the partial suboption if we can. - */ - CURL_SB_ACCUM(tn, CURL_IAC); - CURL_SB_ACCUM(tn, c); - tn->subpointer -= 2; - CURL_SB_TERM(tn); - - printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c); - suboption(conn); /* handle sub-option */ - tn->telrcv_state = CURL_TS_IAC; - goto process_iac; - } - CURL_SB_ACCUM(tn,c); - tn->telrcv_state = CURL_TS_SB; - } - else - { - CURL_SB_ACCUM(tn, CURL_IAC); - CURL_SB_ACCUM(tn, CURL_SE); - tn->subpointer -= 2; - CURL_SB_TERM(tn); - suboption(conn); /* handle sub-option */ - tn->telrcv_state = CURL_TS_DATA; - } - break; - } - ++in; - } - bufferflush(); - return CURLE_OK; -} - -/* Escape and send a telnet data block */ -/* TODO: write large chunks of data instead of one byte at a time */ -static CURLcode send_telnet_data(struct connectdata *conn, - char *buffer, ssize_t nread) -{ - unsigned char outbuf[2]; - ssize_t bytes_written, total_written; - int out_count; - CURLcode rc = CURLE_OK; - - while(rc == CURLE_OK && nread--) { - outbuf[0] = *buffer++; - out_count = 1; - if(outbuf[0] == CURL_IAC) - outbuf[out_count++] = CURL_IAC; - - total_written = 0; - do { - /* Make sure socket is writable to avoid EWOULDBLOCK condition */ - struct pollfd pfd[1]; - pfd[0].fd = conn->sock[FIRSTSOCKET]; - pfd[0].events = POLLOUT; - switch (Curl_poll(pfd, 1, -1)) { - case -1: /* error, abort writing */ - case 0: /* timeout (will never happen) */ - rc = CURLE_SEND_ERROR; - break; - default: /* write! */ - bytes_written = 0; - rc = Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf+total_written, - out_count-total_written, &bytes_written); - total_written += bytes_written; - break; - } - /* handle partial write */ - } while (rc == CURLE_OK && total_written < out_count); - } - return rc; -} - -static CURLcode telnet_done(struct connectdata *conn, - CURLcode status, bool premature) -{ - struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet; - (void)status; /* unused */ - (void)premature; /* not used */ - - curl_slist_free_all(tn->telnet_vars); - - free(conn->data->state.proto.telnet); - conn->data->state.proto.telnet = NULL; - - return CURLE_OK; -} - -static CURLcode telnet_do(struct connectdata *conn, bool *done) -{ - CURLcode code; - struct SessionHandle *data = conn->data; - curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; -#ifdef USE_WINSOCK - HMODULE wsock2; - WSOCK2_FUNC close_event_func; - WSOCK2_FUNC create_event_func; - WSOCK2_FUNC event_select_func; - WSOCK2_FUNC enum_netevents_func; - WSAEVENT event_handle; - WSANETWORKEVENTS events; - HANDLE stdin_handle; - HANDLE objs[2]; - DWORD obj_count; - DWORD wait_timeout; - DWORD waitret; - DWORD readfile_read; - int err; -#else - int interval_ms; - struct pollfd pfd[2]; - int poll_cnt; - curl_off_t total_dl = 0; - curl_off_t total_ul = 0; -#endif - ssize_t nread; - struct timeval now; - bool keepon = TRUE; - char *buf = data->state.buffer; - struct TELNET *tn; - - *done = TRUE; /* unconditionally */ - - code = init_telnet(conn); - if(code) - return code; - - tn = (struct TELNET *)data->state.proto.telnet; - - code = check_telnet_options(conn); - if(code) - return code; - -#ifdef USE_WINSOCK - /* - ** This functionality only works with WinSock >= 2.0. So, - ** make sure have it. - */ - code = check_wsock2(data); - if(code) - return code; - - /* OK, so we have WinSock 2.0. We need to dynamically */ - /* load ws2_32.dll and get the function pointers we need. */ - wsock2 = LoadLibrary("WS2_32.DLL"); - if(wsock2 == NULL) { - failf(data,"failed to load WS2_32.DLL (%d)", ERRNO); - return CURLE_FAILED_INIT; - } - - /* Grab a pointer to WSACreateEvent */ - create_event_func = GetProcAddress(wsock2,"WSACreateEvent"); - if(create_event_func == NULL) { - failf(data,"failed to find WSACreateEvent function (%d)", - ERRNO); - FreeLibrary(wsock2); - return CURLE_FAILED_INIT; - } - - /* And WSACloseEvent */ - close_event_func = GetProcAddress(wsock2,"WSACloseEvent"); - if(close_event_func == NULL) { - failf(data,"failed to find WSACloseEvent function (%d)", - ERRNO); - FreeLibrary(wsock2); - return CURLE_FAILED_INIT; - } - - /* And WSAEventSelect */ - event_select_func = GetProcAddress(wsock2,"WSAEventSelect"); - if(event_select_func == NULL) { - failf(data,"failed to find WSAEventSelect function (%d)", - ERRNO); - FreeLibrary(wsock2); - return CURLE_FAILED_INIT; - } - - /* And WSAEnumNetworkEvents */ - enum_netevents_func = GetProcAddress(wsock2,"WSAEnumNetworkEvents"); - if(enum_netevents_func == NULL) { - failf(data,"failed to find WSAEnumNetworkEvents function (%d)", - ERRNO); - FreeLibrary(wsock2); - return CURLE_FAILED_INIT; - } - - /* We want to wait for both stdin and the socket. Since - ** the select() function in winsock only works on sockets - ** we have to use the WaitForMultipleObjects() call. - */ - - /* First, create a sockets event object */ - event_handle = (WSAEVENT)create_event_func(); - if(event_handle == WSA_INVALID_EVENT) { - failf(data,"WSACreateEvent failed (%d)", SOCKERRNO); - FreeLibrary(wsock2); - return CURLE_FAILED_INIT; - } - - /* The get the Windows file handle for stdin */ - stdin_handle = GetStdHandle(STD_INPUT_HANDLE); - - /* Create the list of objects to wait for */ - objs[0] = event_handle; - objs[1] = stdin_handle; - - /* Tell winsock what events we want to listen to */ - if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) { - close_event_func(event_handle); - FreeLibrary(wsock2); - return CURLE_OK; - } - - /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it, - else use the old WaitForMultipleObjects() way */ - if(GetFileType(stdin_handle) == FILE_TYPE_PIPE) { - /* Don't wait for stdin_handle, just wait for event_handle */ - obj_count = 1; - /* Check stdin_handle per 100 milliseconds */ - wait_timeout = 100; - } else { - obj_count = 2; - wait_timeout = 1000; - } - - /* Keep on listening and act on events */ - while(keepon) { - waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout); - switch(waitret) { - case WAIT_TIMEOUT: - { - for(;;) { - if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) { - keepon = FALSE; - code = CURLE_READ_ERROR; - break; - } - - if(!readfile_read) - break; - - if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), - &readfile_read, NULL)) { - keepon = FALSE; - code = CURLE_READ_ERROR; - break; - } - - code = send_telnet_data(conn, buf, readfile_read); - if(code) { - keepon = FALSE; - break; - } - } - } - break; - - case WAIT_OBJECT_0 + 1: - { - if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), - &readfile_read, NULL)) { - keepon = FALSE; - code = CURLE_READ_ERROR; - break; - } - - code = send_telnet_data(conn, buf, readfile_read); - if(code) { - keepon = FALSE; - break; - } - } - break; - - case WAIT_OBJECT_0: - - if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) { - if((err = SOCKERRNO) != EINPROGRESS) { - infof(data,"WSAEnumNetworkEvents failed (%d)", err); - keepon = FALSE; - code = CURLE_READ_ERROR; - } - break; - } - if(events.lNetworkEvents & FD_READ) { - /* read data from network */ - code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); - /* read would've blocked. Loop again */ - if(code == CURLE_AGAIN) - break; - /* returned not-zero, this an error */ - else if(code) { - keepon = FALSE; - break; - } - /* returned zero but actually received 0 or less here, - the server closed the connection and we bail out */ - else if(nread <= 0) { - keepon = FALSE; - break; - } - - code = telrcv(conn, (unsigned char *)buf, nread); - if(code) { - keepon = FALSE; - break; - } - - /* Negotiate if the peer has started negotiating, - otherwise don't. We don't want to speak telnet with - non-telnet servers, like POP or SMTP. */ - if(tn->please_negotiate && !tn->already_negotiated) { - negotiate(conn); - tn->already_negotiated = 1; - } - } - if(events.lNetworkEvents & FD_CLOSE) { - keepon = FALSE; - } - break; - - } - - if(data->set.timeout) { - now = Curl_tvnow(); - if(Curl_tvdiff(now, conn->created) >= data->set.timeout) { - failf(data, "Time-out"); - code = CURLE_OPERATION_TIMEDOUT; - keepon = FALSE; - } - } - } - - /* We called WSACreateEvent, so call WSACloseEvent */ - if(close_event_func(event_handle) == FALSE) { - infof(data,"WSACloseEvent failed (%d)", SOCKERRNO); - } - - /* "Forget" pointers into the library we're about to free */ - create_event_func = NULL; - close_event_func = NULL; - event_select_func = NULL; - enum_netevents_func = NULL; - - /* We called LoadLibrary, so call FreeLibrary */ - if(!FreeLibrary(wsock2)) - infof(data,"FreeLibrary(wsock2) failed (%d)", ERRNO); -#else - pfd[0].fd = sockfd; - pfd[0].events = POLLIN; - - if (data->set.is_fread_set) { - poll_cnt = 1; - interval_ms = 100; /* poll user-supplied read function */ - } - else { - pfd[1].fd = 0; - pfd[1].events = POLLIN; - poll_cnt = 2; - interval_ms = 1 * 1000; - } - - while(keepon) { - switch (Curl_poll(pfd, poll_cnt, interval_ms)) { - case -1: /* error, stop reading */ - keepon = FALSE; - continue; - case 0: /* timeout */ - pfd[0].revents = 0; - pfd[1].revents = 0; - /* fall through */ - default: /* read! */ - if(pfd[0].revents & POLLIN) { - /* read data from network */ - code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); - /* read would've blocked. Loop again */ - if(code == CURLE_AGAIN) - break; - /* returned not-zero, this an error */ - else if(code) { - keepon = FALSE; - break; - } - /* returned zero but actually received 0 or less here, - the server closed the connection and we bail out */ - else if(nread <= 0) { - keepon = FALSE; - break; - } - - total_dl += nread; - Curl_pgrsSetDownloadCounter(data, total_dl); - code = telrcv(conn, (unsigned char *)buf, nread); - if(code) { - keepon = FALSE; - break; - } - - /* Negotiate if the peer has started negotiating, - otherwise don't. We don't want to speak telnet with - non-telnet servers, like POP or SMTP. */ - if(tn->please_negotiate && !tn->already_negotiated) { - negotiate(conn); - tn->already_negotiated = 1; - } - } - - nread = 0; - if (poll_cnt == 2) { - if(pfd[1].revents & POLLIN) { /* read from stdin */ - nread = read(0, buf, BUFSIZE - 1); - } - } - else { - /* read from user-supplied method */ - nread = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in); - if (nread == CURL_READFUNC_ABORT) { - keepon = FALSE; - break; - } - if (nread == CURL_READFUNC_PAUSE) - break; - } - - if (nread > 0) { - code = send_telnet_data(conn, buf, nread); - if(code) { - keepon = FALSE; - break; - } - total_ul += nread; - Curl_pgrsSetUploadCounter(data, total_ul); - } - else if (nread < 0) - keepon = FALSE; - - break; - } /* poll switch statement */ - - if(data->set.timeout) { - now = Curl_tvnow(); - if(Curl_tvdiff(now, conn->created) >= data->set.timeout) { - failf(data, "Time-out"); - code = CURLE_OPERATION_TIMEDOUT; - keepon = FALSE; - } - } - - if(Curl_pgrsUpdate(conn)) { - code = CURLE_ABORTED_BY_CALLBACK; - break; - } - } -#endif - /* mark this as "no further transfer wanted" */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - - return code; -} -#endif diff --git a/third_party/curl/lib/telnet.h b/third_party/curl/lib/telnet.h deleted file mode 100644 index f00f7fd8f..000000000 --- a/third_party/curl/lib/telnet.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __TELNET_H -#define __TELNET_H - -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#ifndef CURL_DISABLE_TELNET -extern const struct Curl_handler Curl_handler_telnet; -#endif -#endif diff --git a/third_party/curl/lib/tftp.c b/third_party/curl/lib/tftp.c deleted file mode 100644 index a280330f9..000000000 --- a/third_party/curl/lib/tftp.c +++ /dev/null @@ -1,1509 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#ifndef CURL_DISABLE_TFTP -/* -- WIN32 approved -- */ -#include -#include -#include -#include - -#if defined(WIN32) -#include -#include -#else -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#endif /* WIN32 */ - -#include "urldata.h" -#include -#include "transfer.h" -#include "sendf.h" -#include "tftp.h" -#include "progress.h" -#include "connect.h" -#include "strerror.h" -#include "sockaddr.h" /* required for Curl_sockaddr_storage */ -#include "multiif.h" -#include "url.h" -#include "rawstr.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -#include "select.h" - -/* The last #include file should be: */ -#include "memdebug.h" - -/* RFC2348 allows the block size to be negotiated */ -#define TFTP_BLKSIZE_DEFAULT 512 -#define TFTP_BLKSIZE_MIN 8 -#define TFTP_BLKSIZE_MAX 65464 -#define TFTP_OPTION_BLKSIZE "blksize" - -/* from RFC2349: */ -#define TFTP_OPTION_TSIZE "tsize" -#define TFTP_OPTION_INTERVAL "timeout" - -typedef enum { - TFTP_MODE_NETASCII=0, - TFTP_MODE_OCTET -} tftp_mode_t; - -typedef enum { - TFTP_STATE_START=0, - TFTP_STATE_RX, - TFTP_STATE_TX, - TFTP_STATE_FIN -} tftp_state_t; - -typedef enum { - TFTP_EVENT_NONE = -1, - TFTP_EVENT_INIT = 0, - TFTP_EVENT_RRQ = 1, - TFTP_EVENT_WRQ = 2, - TFTP_EVENT_DATA = 3, - TFTP_EVENT_ACK = 4, - TFTP_EVENT_ERROR = 5, - TFTP_EVENT_OACK = 6, - TFTP_EVENT_TIMEOUT -} tftp_event_t; - -typedef enum { - TFTP_ERR_UNDEF=0, - TFTP_ERR_NOTFOUND, - TFTP_ERR_PERM, - TFTP_ERR_DISKFULL, - TFTP_ERR_ILLEGAL, - TFTP_ERR_UNKNOWNID, - TFTP_ERR_EXISTS, - TFTP_ERR_NOSUCHUSER, /* This will never be triggered by this code */ - - /* The remaining error codes are internal to curl */ - TFTP_ERR_NONE = -100, - TFTP_ERR_TIMEOUT, - TFTP_ERR_NORESPONSE -} tftp_error_t; - -typedef struct tftp_packet { - unsigned char *data; -} tftp_packet_t; - -typedef struct tftp_state_data { - tftp_state_t state; - tftp_mode_t mode; - tftp_error_t error; - tftp_event_t event; - struct connectdata *conn; - curl_socket_t sockfd; - int retries; - int retry_time; - int retry_max; - time_t start_time; - time_t max_time; - time_t rx_time; - unsigned short block; - struct Curl_sockaddr_storage local_addr; - struct Curl_sockaddr_storage remote_addr; - curl_socklen_t remote_addrlen; - int rbytes; - int sbytes; - int blksize; - int requested_blksize; - tftp_packet_t rpacket; - tftp_packet_t spacket; -} tftp_state_data_t; - - -/* Forward declarations */ -static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) ; -static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) ; -static CURLcode tftp_connect(struct connectdata *conn, bool *done); -static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection); -static CURLcode tftp_do(struct connectdata *conn, bool *done); -static CURLcode tftp_done(struct connectdata *conn, - CURLcode, bool premature); -static CURLcode tftp_setup_connection(struct connectdata * conn); -static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done); -static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done); -static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks, - int numsocks); -static CURLcode tftp_translate_code(tftp_error_t error); - - -/* - * TFTP protocol handler. - */ - -const struct Curl_handler Curl_handler_tftp = { - "TFTP", /* scheme */ - tftp_setup_connection, /* setup_connection */ - tftp_do, /* do_it */ - tftp_done, /* done */ - ZERO_NULL, /* do_more */ - tftp_connect, /* connect_it */ - tftp_multi_statemach, /* connecting */ - tftp_doing, /* doing */ - tftp_getsock, /* proto_getsock */ - tftp_getsock, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - tftp_disconnect, /* disconnect */ - PORT_TFTP, /* defport */ - CURLPROTO_TFTP, /* protocol */ - PROTOPT_NONE /* flags */ -}; - -/********************************************************** - * - * tftp_set_timeouts - - * - * Set timeouts based on state machine state. - * Use user provided connect timeouts until DATA or ACK - * packet is received, then use user-provided transfer timeouts - * - * - **********************************************************/ -static CURLcode tftp_set_timeouts(tftp_state_data_t *state) -{ - time_t maxtime, timeout; - long timeout_ms; - bool start = (bool)(state->state == TFTP_STATE_START); - - time(&state->start_time); - - /* Compute drop-dead time */ - timeout_ms = Curl_timeleft(state->conn->data, NULL, start); - - if(timeout_ms < 0) { - /* time-out, bail out, go home */ - failf(state->conn->data, "Connection time-out"); - return CURLE_OPERATION_TIMEDOUT; - } - - if(start) { - - maxtime = (time_t)(timeout_ms + 500) / 1000; - state->max_time = state->start_time+maxtime; - - /* Set per-block timeout to total */ - timeout = maxtime ; - - /* Average restart after 5 seconds */ - state->retry_max = (int)timeout/5; - - if(state->retry_max < 1) - /* avoid division by zero below */ - state->retry_max = 1; - - /* Compute the re-start interval to suit the timeout */ - state->retry_time = (int)timeout/state->retry_max; - if(state->retry_time<1) - state->retry_time=1; - - } - else { - if(timeout_ms > 0) - maxtime = (time_t)(timeout_ms + 500) / 1000; - else - maxtime = 3600; - - state->max_time = state->start_time+maxtime; - - /* Set per-block timeout to 10% of total */ - timeout = maxtime/10 ; - - /* Average reposting an ACK after 15 seconds */ - state->retry_max = (int)timeout/15; - } - /* But bound the total number */ - if(state->retry_max<3) - state->retry_max=3; - - if(state->retry_max>50) - state->retry_max=50; - - /* Compute the re-ACK interval to suit the timeout */ - state->retry_time = (int)(timeout/state->retry_max); - if(state->retry_time<1) - state->retry_time=1; - - infof(state->conn->data, - "set timeouts for state %d; Total %ld, retry %d maxtry %d\n", - (int)state->state, (long)(state->max_time-state->start_time), - state->retry_time, state->retry_max); - - /* init RX time */ - time(&state->rx_time); - - return CURLE_OK; -} - -/********************************************************** - * - * tftp_set_send_first - * - * Event handler for the START state - * - **********************************************************/ - -static void setpacketevent(tftp_packet_t *packet, unsigned short num) -{ - packet->data[0] = (unsigned char)(num >> 8); - packet->data[1] = (unsigned char)(num & 0xff); -} - - -static void setpacketblock(tftp_packet_t *packet, unsigned short num) -{ - packet->data[2] = (unsigned char)(num >> 8); - packet->data[3] = (unsigned char)(num & 0xff); -} - -static unsigned short getrpacketevent(const tftp_packet_t *packet) -{ - return (unsigned short)((packet->data[0] << 8) | packet->data[1]); -} - -static unsigned short getrpacketblock(const tftp_packet_t *packet) -{ - return (unsigned short)((packet->data[2] << 8) | packet->data[3]); -} - -static size_t Curl_strnlen(const char *string, size_t maxlen) -{ - const char *end = memchr (string, '\0', maxlen); - return end ? (size_t) (end - string) : maxlen; -} - -static const char *tftp_option_get(const char *buf, size_t len, - const char **option, const char **value) -{ - size_t loc; - - loc = Curl_strnlen( buf, len ); - loc++; /* NULL term */ - - if (loc >= len) - return NULL; - *option = buf; - - loc += Curl_strnlen( buf+loc, len-loc ); - loc++; /* NULL term */ - - if (loc > len) - return NULL; - *value = &buf[strlen(*option) + 1]; - - return &buf[loc]; -} - -static CURLcode tftp_parse_option_ack(tftp_state_data_t *state, - const char *ptr, int len) -{ - const char *tmp = ptr; - struct SessionHandle *data = state->conn->data; - - /* if OACK doesn't contain blksize option, the default (512) must be used */ - state->blksize = TFTP_BLKSIZE_DEFAULT; - - while (tmp < ptr + len) { - const char *option, *value; - - tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value); - if(tmp == NULL) { - failf(data, "Malformed ACK packet, rejecting"); - return CURLE_TFTP_ILLEGAL; - } - - infof(data, "got option=(%s) value=(%s)\n", option, value); - - if(checkprefix(option, TFTP_OPTION_BLKSIZE)) { - long blksize; - - blksize = strtol( value, NULL, 10 ); - - if(!blksize) { - failf(data, "invalid blocksize value in OACK packet"); - return CURLE_TFTP_ILLEGAL; - } - else if(blksize > TFTP_BLKSIZE_MAX) { - failf(data, "%s (%d)", "blksize is larger than max supported", - TFTP_BLKSIZE_MAX); - return CURLE_TFTP_ILLEGAL; - } - else if(blksize < TFTP_BLKSIZE_MIN) { - failf(data, "%s (%d)", "blksize is smaller than min supported", - TFTP_BLKSIZE_MIN); - return CURLE_TFTP_ILLEGAL; - } - else if (blksize > state->requested_blksize) { - /* could realloc pkt buffers here, but the spec doesn't call out - * support for the server requesting a bigger blksize than the client - * requests */ - failf(data, "%s (%ld)", - "server requested blksize larger than allocated", blksize); - return CURLE_TFTP_ILLEGAL; - } - - state->blksize = (int)blksize; - infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK", - state->blksize, "requested", state->requested_blksize); - } - else if(checkprefix(option, TFTP_OPTION_TSIZE)) { - long tsize = 0; - - tsize = strtol( value, NULL, 10 ); - infof(data, "%s (%ld)\n", "tsize parsed from OACK", tsize); - - /* tsize should be ignored on upload: Who cares about the size of the - remote file? */ - if (!data->set.upload) { - if(!tsize) { - failf(data, "invalid tsize -:%s:- value in OACK packet", value); - return CURLE_TFTP_ILLEGAL; - } - Curl_pgrsSetDownloadSize(data, tsize); - } - } - } - - return CURLE_OK; -} - -static size_t tftp_option_add(tftp_state_data_t *state, size_t csize, - char *buf, const char *option) -{ - if( ( strlen(option) + csize + 1 ) > (size_t)state->blksize ) - return 0; - strcpy(buf, option); - return( strlen(option) + 1 ); -} - -static CURLcode tftp_connect_for_tx(tftp_state_data_t *state, - tftp_event_t event) -{ - CURLcode res; -#ifndef CURL_DISABLE_VERBOSE_STRINGS - struct SessionHandle *data = state->conn->data; - - infof(data, "%s\n", "Connected for transmit"); -#endif - state->state = TFTP_STATE_TX; - res = tftp_set_timeouts(state); - if(res != CURLE_OK) - return(res); - return tftp_tx(state, event); -} - -static CURLcode tftp_connect_for_rx(tftp_state_data_t *state, - tftp_event_t event) -{ - CURLcode res; -#ifndef CURL_DISABLE_VERBOSE_STRINGS - struct SessionHandle *data = state->conn->data; - - infof(data, "%s\n", "Connected for receive"); -#endif - state->state = TFTP_STATE_RX; - res = tftp_set_timeouts(state); - if(res != CURLE_OK) - return(res); - return tftp_rx(state, event); -} - -static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) -{ - size_t sbytes; - ssize_t senddata; - const char *mode = "octet"; - char *filename; - char buf[64]; - struct SessionHandle *data = state->conn->data; - CURLcode res = CURLE_OK; - - /* Set ascii mode if -B flag was used */ - if(data->set.prefer_ascii) - mode = "netascii"; - - switch(event) { - - case TFTP_EVENT_INIT: /* Send the first packet out */ - case TFTP_EVENT_TIMEOUT: /* Resend the first packet out */ - /* Increment the retry counter, quit if over the limit */ - state->retries++; - if(state->retries>state->retry_max) { - state->error = TFTP_ERR_NORESPONSE; - state->state = TFTP_STATE_FIN; - return res; - } - - if(data->set.upload) { - /* If we are uploading, send an WRQ */ - setpacketevent(&state->spacket, TFTP_EVENT_WRQ); - state->conn->data->req.upload_fromhere = - (char *)state->spacket.data+4; - if(data->set.infilesize != -1) - Curl_pgrsSetUploadSize(data, data->set.infilesize); - } - else { - /* If we are downloading, send an RRQ */ - setpacketevent(&state->spacket, TFTP_EVENT_RRQ); - } - /* As RFC3617 describes the separator slash is not actually part of the - file name so we skip the always-present first letter of the path - string. */ - filename = curl_easy_unescape(data, &state->conn->data->state.path[1], 0, - NULL); - if(!filename) - return CURLE_OUT_OF_MEMORY; - - snprintf((char *)state->spacket.data+2, - state->blksize, - "%s%c%s%c", filename, '\0', mode, '\0'); - sbytes = 4 + strlen(filename) + strlen(mode); - - /* add tsize option */ - if(data->set.upload && (data->set.infilesize != -1)) - snprintf( buf, sizeof(buf), "%" FORMAT_OFF_T, data->set.infilesize ); - else - strcpy(buf, "0"); /* the destination is large enough */ - - sbytes += tftp_option_add(state, sbytes, - (char *)state->spacket.data+sbytes, - TFTP_OPTION_TSIZE); - sbytes += tftp_option_add(state, sbytes, - (char *)state->spacket.data+sbytes, buf); - /* add blksize option */ - snprintf( buf, sizeof(buf), "%d", state->requested_blksize ); - sbytes += tftp_option_add(state, sbytes, - (char *)state->spacket.data+sbytes, - TFTP_OPTION_BLKSIZE); - sbytes += tftp_option_add(state, sbytes, - (char *)state->spacket.data+sbytes, buf ); - - /* add timeout option */ - snprintf( buf, sizeof(buf), "%d", state->retry_time); - sbytes += tftp_option_add(state, sbytes, - (char *)state->spacket.data+sbytes, - TFTP_OPTION_INTERVAL); - sbytes += tftp_option_add(state, sbytes, - (char *)state->spacket.data+sbytes, buf ); - - /* the typecase for the 3rd argument is mostly for systems that do - not have a size_t argument, like older unixes that want an 'int' */ - senddata = sendto(state->sockfd, (void *)state->spacket.data, - (SEND_TYPE_ARG3)sbytes, 0, - state->conn->ip_addr->ai_addr, - state->conn->ip_addr->ai_addrlen); - if(senddata != (ssize_t)sbytes) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); - } - Curl_safefree(filename); - break; - - case TFTP_EVENT_OACK: - if(data->set.upload) { - res = tftp_connect_for_tx(state, event); - } - else { - res = tftp_connect_for_rx(state, event); - } - break; - - case TFTP_EVENT_ACK: /* Connected for transmit */ - res = tftp_connect_for_tx(state, event); - break; - - case TFTP_EVENT_DATA: /* Connected for receive */ - res = tftp_connect_for_rx(state, event); - break; - - case TFTP_EVENT_ERROR: - state->state = TFTP_STATE_FIN; - break; - - default: - failf(state->conn->data, "tftp_send_first: internal error"); - break; - } - return res; -} - -/* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit - boundary */ -#define NEXT_BLOCKNUM(x) (((x)+1)&0xffff) - -/********************************************************** - * - * tftp_rx - * - * Event handler for the RX state - * - **********************************************************/ -static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) -{ - ssize_t sbytes; - int rblock; - struct SessionHandle *data = state->conn->data; - - switch(event) { - - case TFTP_EVENT_DATA: - /* Is this the block we expect? */ - rblock = getrpacketblock(&state->rpacket); - if(NEXT_BLOCKNUM(state->block) != rblock) { - /* No, log it, up the retry count and fail if over the limit */ - infof(data, - "Received unexpected DATA packet block %d\n", rblock); - state->retries++; - if(state->retries > state->retry_max) { - failf(data, "tftp_rx: giving up waiting for block %d", - NEXT_BLOCKNUM(state->block)); - return CURLE_TFTP_ILLEGAL; - } - break; - } - /* This is the expected block. Reset counters and ACK it. */ - state->block = (unsigned short)rblock; - state->retries = 0; - setpacketevent(&state->spacket, TFTP_EVENT_ACK); - setpacketblock(&state->spacket, state->block); - sbytes = sendto(state->sockfd, (void *)state->spacket.data, - 4, SEND_4TH_ARG, - (struct sockaddr *)&state->remote_addr, - state->remote_addrlen); - if(sbytes < 0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); - return CURLE_SEND_ERROR; - } - - /* Check if completed (That is, a less than full packet is received) */ - if(state->rbytes < (ssize_t)state->blksize+4){ - state->state = TFTP_STATE_FIN; - } - else { - state->state = TFTP_STATE_RX; - } - time(&state->rx_time); - break; - - case TFTP_EVENT_OACK: - /* ACK option acknowledgement so we can move on to data */ - state->block = 0; - state->retries = 0; - setpacketevent(&state->spacket, TFTP_EVENT_ACK); - setpacketblock(&state->spacket, state->block); - sbytes = sendto(state->sockfd, (void *)state->spacket.data, - 4, SEND_4TH_ARG, - (struct sockaddr *)&state->remote_addr, - state->remote_addrlen); - if(sbytes < 0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); - return CURLE_SEND_ERROR; - } - - /* we're ready to RX data */ - state->state = TFTP_STATE_RX; - time(&state->rx_time); - break; - - case TFTP_EVENT_TIMEOUT: - /* Increment the retry count and fail if over the limit */ - state->retries++; - infof(data, - "Timeout waiting for block %d ACK. Retries = %d\n", - NEXT_BLOCKNUM(state->block), state->retries); - if(state->retries > state->retry_max) { - state->error = TFTP_ERR_TIMEOUT; - state->state = TFTP_STATE_FIN; - } - else { - /* Resend the previous ACK */ - sbytes = sendto(state->sockfd, (void *)state->spacket.data, - 4, SEND_4TH_ARG, - (struct sockaddr *)&state->remote_addr, - state->remote_addrlen); - if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); - return CURLE_SEND_ERROR; - } - } - break; - - case TFTP_EVENT_ERROR: - setpacketevent(&state->spacket, TFTP_EVENT_ERROR); - setpacketblock(&state->spacket, state->block); - (void)sendto(state->sockfd, (void *)state->spacket.data, - 4, SEND_4TH_ARG, - (struct sockaddr *)&state->remote_addr, - state->remote_addrlen); - /* don't bother with the return code, but if the socket is still up we - * should be a good TFTP client and let the server know we're done */ - state->state = TFTP_STATE_FIN; - break; - - default: - failf(data, "%s", "tftp_rx: internal error"); - return CURLE_TFTP_ILLEGAL; /* not really the perfect return code for - this */ - } - return CURLE_OK; -} - -/********************************************************** - * - * tftp_tx - * - * Event handler for the TX state - * - **********************************************************/ -static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) -{ - struct SessionHandle *data = state->conn->data; - ssize_t sbytes; - int rblock; - CURLcode res = CURLE_OK; - struct SingleRequest *k = &data->req; - - switch(event) { - - case TFTP_EVENT_ACK: - case TFTP_EVENT_OACK: - if (event == TFTP_EVENT_ACK) { - /* Ack the packet */ - rblock = getrpacketblock(&state->rpacket); - - if(rblock != state->block && - /* There's a bug in tftpd-hpa that causes it to send us an ack for - * 65535 when the block number wraps to 0. So when we're expecting - * 0, also accept 65535. See - * http://syslinux.zytor.com/archives/2010-September/015253.html - * */ - !(state->block == 0 && rblock == 65535)) { - /* This isn't the expected block. Log it and up the retry counter */ - infof(data, "Received ACK for block %d, expecting %d\n", - rblock, state->block); - state->retries++; - /* Bail out if over the maximum */ - if(state->retries>state->retry_max) { - failf(data, "tftp_tx: giving up waiting for block %d ack", - state->block); - res = CURLE_SEND_ERROR; - } - else { - /* Re-send the data packet */ - sbytes = sendto(state->sockfd, (void *)&state->spacket.data, - 4+state->sbytes, SEND_4TH_ARG, - (struct sockaddr *)&state->remote_addr, - state->remote_addrlen); - /* Check all sbytes were sent */ - if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); - res = CURLE_SEND_ERROR; - } - } - return res; - } - /* This is the expected packet. Reset the counters and send the next - block */ - time(&state->rx_time); - state->block++; - } - else - state->block = 1; /* first data block is 1 when using OACK */ - - state->retries = 0; - setpacketevent(&state->spacket, TFTP_EVENT_DATA); - setpacketblock(&state->spacket, state->block); - if(state->block > 1 && state->sbytes < (int)state->blksize) { - state->state = TFTP_STATE_FIN; - return CURLE_OK; - } - res = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes); - if(res) - return res; - sbytes = sendto(state->sockfd, (void *)state->spacket.data, - 4+state->sbytes, SEND_4TH_ARG, - (struct sockaddr *)&state->remote_addr, - state->remote_addrlen); - /* Check all sbytes were sent */ - if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); - return CURLE_SEND_ERROR; - } - /* Update the progress meter */ - k->writebytecount += state->sbytes; - Curl_pgrsSetUploadCounter(data, k->writebytecount); - break; - - case TFTP_EVENT_TIMEOUT: - /* Increment the retry counter and log the timeout */ - state->retries++; - infof(data, "Timeout waiting for block %d ACK. " - " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries); - /* Decide if we've had enough */ - if(state->retries > state->retry_max) { - state->error = TFTP_ERR_TIMEOUT; - state->state = TFTP_STATE_FIN; - } - else { - /* Re-send the data packet */ - sbytes = sendto(state->sockfd, (void *)state->spacket.data, - 4+state->sbytes, SEND_4TH_ARG, - (struct sockaddr *)&state->remote_addr, - state->remote_addrlen); - /* Check all sbytes were sent */ - if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); - return CURLE_SEND_ERROR; - } - /* since this was a re-send, we remain at the still byte position */ - Curl_pgrsSetUploadCounter(data, k->writebytecount); - } - break; - - case TFTP_EVENT_ERROR: - state->state = TFTP_STATE_FIN; - setpacketevent(&state->spacket, TFTP_EVENT_ERROR); - setpacketblock(&state->spacket, state->block); - (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG, - (struct sockaddr *)&state->remote_addr, - state->remote_addrlen); - /* don't bother with the return code, but if the socket is still up we - * should be a good TFTP client and let the server know we're done */ - state->state = TFTP_STATE_FIN; - break; - - default: - failf(data, "tftp_tx: internal error, event: %i", (int)(event)); - break; - } - - return res; -} - -/********************************************************** - * - * tftp_translate_code - * - * Translate internal error codes to CURL error codes - * - **********************************************************/ -static CURLcode tftp_translate_code(tftp_error_t error) -{ - CURLcode code = CURLE_OK; - - if(error != TFTP_ERR_NONE) { - switch(error) { - case TFTP_ERR_NOTFOUND: - code = CURLE_TFTP_NOTFOUND; - break; - case TFTP_ERR_PERM: - code = CURLE_TFTP_PERM; - break; - case TFTP_ERR_DISKFULL: - code = CURLE_REMOTE_DISK_FULL; - break; - case TFTP_ERR_UNDEF: - case TFTP_ERR_ILLEGAL: - code = CURLE_TFTP_ILLEGAL; - break; - case TFTP_ERR_UNKNOWNID: - code = CURLE_TFTP_UNKNOWNID; - break; - case TFTP_ERR_EXISTS: - code = CURLE_REMOTE_FILE_EXISTS; - break; - case TFTP_ERR_NOSUCHUSER: - code = CURLE_TFTP_NOSUCHUSER; - break; - case TFTP_ERR_TIMEOUT: - code = CURLE_OPERATION_TIMEDOUT; - break; - case TFTP_ERR_NORESPONSE: - code = CURLE_COULDNT_CONNECT; - break; - default: - code= CURLE_ABORTED_BY_CALLBACK; - break; - } - } - else { - code = CURLE_OK; - } - - return(code); -} - -/********************************************************** - * - * tftp_state_machine - * - * The tftp state machine event dispatcher - * - **********************************************************/ -static CURLcode tftp_state_machine(tftp_state_data_t *state, - tftp_event_t event) -{ - CURLcode res = CURLE_OK; - struct SessionHandle *data = state->conn->data; - switch(state->state) { - case TFTP_STATE_START: - DEBUGF(infof(data, "TFTP_STATE_START\n")); - res = tftp_send_first(state, event); - break; - case TFTP_STATE_RX: - DEBUGF(infof(data, "TFTP_STATE_RX\n")); - res = tftp_rx(state, event); - break; - case TFTP_STATE_TX: - DEBUGF(infof(data, "TFTP_STATE_TX\n")); - res = tftp_tx(state, event); - break; - case TFTP_STATE_FIN: - infof(data, "%s\n", "TFTP finished"); - break; - default: - DEBUGF(infof(data, "STATE: %d\n", state->state)); - failf(data, "%s", "Internal state machine error"); - res = CURLE_TFTP_ILLEGAL; - break; - } - return res; -} - -/********************************************************** - * - * tftp_disconnect - * - * The disconnect callback - * - **********************************************************/ -static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection) -{ - tftp_state_data_t *state = conn->proto.tftpc; - (void) dead_connection; - - /* done, free dynamically allocated pkt buffers */ - if(state) { - Curl_safefree(state->rpacket.data); - Curl_safefree(state->spacket.data); - free(state); - } - - return CURLE_OK; -} - -/********************************************************** - * - * tftp_connect - * - * The connect callback - * - **********************************************************/ -static CURLcode tftp_connect(struct connectdata *conn, bool *done) -{ - CURLcode code; - tftp_state_data_t *state; - int blksize, rc; - - blksize = TFTP_BLKSIZE_DEFAULT; - - /* If there already is a protocol-specific struct allocated for this - sessionhandle, deal with it */ - Curl_reset_reqproto(conn); - - state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t)); - if(!state) - return CURLE_OUT_OF_MEMORY; - - /* alloc pkt buffers based on specified blksize */ - if(conn->data->set.tftp_blksize) { - blksize = (int)conn->data->set.tftp_blksize; - if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN ) - return CURLE_TFTP_ILLEGAL; - } - - if(!state->rpacket.data) { - state->rpacket.data = calloc(1, blksize + 2 + 2); - - if(!state->rpacket.data) - return CURLE_OUT_OF_MEMORY; - } - - if(!state->spacket.data) { - state->spacket.data = calloc(1, blksize + 2 + 2); - - if(!state->spacket.data) - return CURLE_OUT_OF_MEMORY; - } - - conn->bits.close = TRUE; /* we don't keep TFTP connections up bascially - because there's none or very little gain for UDP - */ - - state->conn = conn; - state->sockfd = state->conn->sock[FIRSTSOCKET]; - state->state = TFTP_STATE_START; - state->error = TFTP_ERR_NONE; - state->blksize = TFTP_BLKSIZE_DEFAULT; - state->requested_blksize = blksize; - - ((struct sockaddr *)&state->local_addr)->sa_family = - (unsigned short)(conn->ip_addr->ai_family); - - tftp_set_timeouts(state); - - if(!conn->bits.bound) { - /* If not already bound, bind to any interface, random UDP port. If it is - * reused or a custom local port was desired, this has already been done! - * - * We once used the size of the local_addr struct as the third argument - * for bind() to better work with IPv6 or whatever size the struct could - * have, but we learned that at least Tru64, AIX and IRIX *requires* the - * size of that argument to match the exact size of a 'sockaddr_in' struct - * when running IPv4-only. - * - * Therefore we use the size from the address we connected to, which we - * assume uses the same IP version and thus hopefully this works for both - * IPv4 and IPv6... - */ - rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, - conn->ip_addr->ai_addrlen); - if(rc) { - failf(conn->data, "bind() failed; %s", - Curl_strerror(conn, SOCKERRNO)); - return CURLE_COULDNT_CONNECT; - } - conn->bits.bound = TRUE; - } - - Curl_pgrsStartNow(conn->data); - - *done = TRUE; - code = CURLE_OK; - return(code); -} - -/********************************************************** - * - * tftp_done - * - * The done callback - * - **********************************************************/ -static CURLcode tftp_done(struct connectdata *conn, CURLcode status, - bool premature) -{ - CURLcode code = CURLE_OK; - tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; - - (void)status; /* unused */ - (void)premature; /* not used */ - - Curl_pgrsDone(conn); - - /* If we have encountered an error */ - code = tftp_translate_code(state->error); - - return code; -} - -/********************************************************** - * - * tftp_getsock - * - * The getsock callback - * - **********************************************************/ -static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks, - int numsocks) -{ - if(!numsocks) - return GETSOCK_BLANK; - - socks[0] = conn->sock[FIRSTSOCKET]; - - return GETSOCK_READSOCK(0); -} - -/********************************************************** - * - * tftp_receive_packet - * - * Called once select fires and data is ready on the socket - * - **********************************************************/ -static CURLcode tftp_receive_packet(struct connectdata *conn) -{ - struct Curl_sockaddr_storage fromaddr; - curl_socklen_t fromlen; - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; - struct SingleRequest *k = &data->req; - - /* Receive the packet */ - fromlen = sizeof(fromaddr); - state->rbytes = (int)recvfrom(state->sockfd, - (void *)state->rpacket.data, - state->blksize+4, - 0, - (struct sockaddr *)&fromaddr, - &fromlen); - if(state->remote_addrlen==0) { - memcpy(&state->remote_addr, &fromaddr, fromlen); - state->remote_addrlen = fromlen; - } - - /* Sanity check packet length */ - if(state->rbytes < 4) { - failf(data, "Received too short packet"); - /* Not a timeout, but how best to handle it? */ - state->event = TFTP_EVENT_TIMEOUT; - } - else { - /* The event is given by the TFTP packet time */ - state->event = (tftp_event_t)getrpacketevent(&state->rpacket); - - switch(state->event) { - case TFTP_EVENT_DATA: - /* Don't pass to the client empty or retransmitted packets */ - if(state->rbytes > 4 && - (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) { - result = Curl_client_write(conn, CLIENTWRITE_BODY, - (char *)state->rpacket.data+4, - state->rbytes-4); - if(result) { - tftp_state_machine(state, TFTP_EVENT_ERROR); - return result; - } - k->bytecount += state->rbytes-4; - Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount); - } - break; - case TFTP_EVENT_ERROR: - state->error = (tftp_error_t)getrpacketblock(&state->rpacket); - infof(data, "%s\n", (const char *)state->rpacket.data+4); - break; - case TFTP_EVENT_ACK: - break; - case TFTP_EVENT_OACK: - result = tftp_parse_option_ack(state, - (const char *)state->rpacket.data+2, - state->rbytes-2); - if(result) - return result; - break; - case TFTP_EVENT_RRQ: - case TFTP_EVENT_WRQ: - default: - failf(data, "%s", "Internal error: Unexpected packet"); - break; - } - - /* Update the progress meter */ - if(Curl_pgrsUpdate(conn)) { - tftp_state_machine(state, TFTP_EVENT_ERROR); - return CURLE_ABORTED_BY_CALLBACK; - } - } - return result; -} - -/********************************************************** - * - * tftp_state_timeout - * - * Check if timeouts have been reached - * - **********************************************************/ -static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event) -{ - time_t current; - tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; - - if (event) - *event = TFTP_EVENT_NONE; - - time(¤t); - if(current > state->max_time) { - DEBUGF(infof(conn->data, "timeout: %ld > %ld\n", - (long)current, (long)state->max_time)); - state->error = TFTP_ERR_TIMEOUT; - state->state = TFTP_STATE_FIN; - return 0; - } - else if (current > state->rx_time+state->retry_time) { - if (event) - *event = TFTP_EVENT_TIMEOUT; - time(&state->rx_time); /* update even though we received nothing */ - } - - /* there's a typecast below here since 'time_t' may in fact be larger than - 'long', but we estimate that a 'long' will still be able to hold number - of seconds even if "only" 32 bit */ - return (long)(state->max_time - current); -} - - -/********************************************************** - * - * tftp_easy_statemach - * - * Handle easy request until completion - * - **********************************************************/ -static CURLcode tftp_easy_statemach(struct connectdata *conn) -{ - int rc; - int check_time = 0; - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; - curl_socket_t fd_read; - long timeout_ms; - struct SingleRequest *k = &data->req; - struct timeval transaction_start = Curl_tvnow(); - - k->start = transaction_start; - k->now = transaction_start; - - /* Run the TFTP State Machine */ - for(; (state->state != TFTP_STATE_FIN) && (result == CURLE_OK); ) { - - timeout_ms = state->retry_time * 1000; - - if (data->set.upload) { - if (data->set.max_send_speed && - (data->progress.ulspeed > data->set.max_send_speed)) { - fd_read = CURL_SOCKET_BAD; - timeout_ms = Curl_sleep_time(data->set.max_send_speed, - data->progress.ulspeed, state->blksize); - } - else { - fd_read = state->sockfd; - } - } - else { - if (data->set.max_recv_speed && - (data->progress.dlspeed > data->set.max_recv_speed)) { - fd_read = CURL_SOCKET_BAD; - timeout_ms = Curl_sleep_time(data->set.max_recv_speed, - data->progress.dlspeed, state->blksize); - } - else { - fd_read = state->sockfd; - } - } - - if(data->set.timeout) { - timeout_ms = data->set.timeout - Curl_tvdiff(k->now, k->start); - if (timeout_ms > state->retry_time * 1000) - timeout_ms = state->retry_time * 1000; - else if(timeout_ms < 0) - timeout_ms = 0; - } - - - /* Wait until ready to read or timeout occurs */ - rc = Curl_socket_ready(fd_read, CURL_SOCKET_BAD, (int)(timeout_ms)); - - k->now = Curl_tvnow(); - - /* Force a progress callback if it's been too long */ - if (Curl_tvdiff(k->now, k->start) >= data->set.timeout) { - if(Curl_pgrsUpdate(conn)) { - tftp_state_machine(state, TFTP_EVENT_ERROR); - return CURLE_ABORTED_BY_CALLBACK; - } - k->start = k->now; - } - - if(rc == -1) { - /* bail out */ - int error = SOCKERRNO; - failf(data, "%s", Curl_strerror(conn, error)); - state->event = TFTP_EVENT_ERROR; - } - else { - - if(rc==0) { - /* A timeout occurred, but our timeout is variable, so maybe - just continue? */ - long rtms = state->retry_time * 1000; - if (Curl_tvdiff(k->now, transaction_start) > rtms) { - state->event = TFTP_EVENT_TIMEOUT; - /* Force a look at transfer timeouts */ - check_time = 1; - } - else { - continue; /* skip state machine */ - } - } - else { - result = tftp_receive_packet(conn); - if (result == CURLE_OK) - transaction_start = Curl_tvnow(); - - if(k->bytecountp) - *k->bytecountp = k->bytecount; /* read count */ - if(k->writebytecountp) - *k->writebytecountp = k->writebytecount; /* write count */ - } - } - - if(check_time) { - tftp_state_timeout(conn, NULL); - check_time = 0; - } - - if(result) - return(result); - - result = tftp_state_machine(state, state->event); - } - - /* Tell curl we're done */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - - return(result); -} - -/********************************************************** - * - * tftp_multi_statemach - * - * Handle single RX socket event and return - * - **********************************************************/ -static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) -{ - int rc; - tftp_event_t event; - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; - long timeout_ms = tftp_state_timeout(conn, &event); - - *done = FALSE; - - if(timeout_ms <= 0) { - failf(data, "TFTP response timeout"); - return CURLE_OPERATION_TIMEDOUT; - } - else if (event != TFTP_EVENT_NONE) { - result = tftp_state_machine(state, event); - if(result != CURLE_OK) - return(result); - *done = (bool)(state->state == TFTP_STATE_FIN); - if(*done) - /* Tell curl we're done */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - } - else { - /* no timeouts to handle, check our socket */ - rc = Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD, 0); - - if(rc == -1) { - /* bail out */ - int error = SOCKERRNO; - failf(data, "%s", Curl_strerror(conn, error)); - state->event = TFTP_EVENT_ERROR; - } - else if(rc != 0) { - result = tftp_receive_packet(conn); - if(result != CURLE_OK) - return(result); - result = tftp_state_machine(state, state->event); - if(result != CURLE_OK) - return(result); - *done = (bool)(state->state == TFTP_STATE_FIN); - if(*done) - /* Tell curl we're done */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - } - /* if rc == 0, then select() timed out */ - } - - return result; -} - -/********************************************************** - * - * tftp_doing - * - * Called from multi.c while DOing - * - **********************************************************/ -static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done) -{ - CURLcode result; - result = tftp_multi_statemach(conn, dophase_done); - - if(*dophase_done) { - DEBUGF(infof(conn->data, "DO phase is complete\n")); - } - return result; -} - -/********************************************************** - * - * tftp_peform - * - * Entry point for transfer from tftp_do, sarts state mach - * - **********************************************************/ -static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done) -{ - CURLcode result = CURLE_OK; - tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; - - *dophase_done = FALSE; - - result = tftp_state_machine(state, TFTP_EVENT_INIT); - - if(state->state == TFTP_STATE_FIN || result != CURLE_OK) - return(result); - - if(conn->data->state.used_interface == Curl_if_multi) - tftp_multi_statemach(conn, dophase_done); - else { - result = tftp_easy_statemach(conn); - *dophase_done = TRUE; /* with the easy interface we are done here */ - } - - if(*dophase_done) - DEBUGF(infof(conn->data, "DO phase is complete\n")); - - return result; -} - - -/********************************************************** - * - * tftp_do - * - * The do callback - * - * This callback initiates the TFTP transfer - * - **********************************************************/ - -static CURLcode tftp_do(struct connectdata *conn, bool *done) -{ - tftp_state_data_t *state; - CURLcode code; - - *done = FALSE; - - /* - Since connections can be re-used between SessionHandles, this might be a - connection already existing but on a fresh SessionHandle struct so we must - make sure we have a good 'struct TFTP' to play with. For new connections, - the struct TFTP is allocated and setup in the tftp_connect() function. - */ - Curl_reset_reqproto(conn); - - if(!conn->proto.tftpc) { - code = tftp_connect(conn, done); - if(code) - return code; - } - state = (tftp_state_data_t *)conn->proto.tftpc; - - code = tftp_perform(conn, done); - - /* If tftp_perform() returned an error, use that for return code. If it - was OK, see if tftp_translate_code() has an error. */ - if (code == CURLE_OK) - /* If we have encountered an internal tftp error, translate it. */ - code = tftp_translate_code(state->error); - - return code; -} - -static CURLcode tftp_setup_connection(struct connectdata * conn) -{ - struct SessionHandle *data = conn->data; - char * type; - char command; - - conn->socktype = SOCK_DGRAM; /* UDP datagram based */ - - /* TFTP URLs support an extension like ";mode=" that - * we'll try to get now! */ - type = strstr(data->state.path, ";mode="); - - if(!type) - type = strstr(conn->host.rawalloc, ";mode="); - - if(type) { - *type = 0; /* it was in the middle of the hostname */ - command = Curl_raw_toupper(type[6]); - - switch (command) { - case 'A': /* ASCII mode */ - case 'N': /* NETASCII mode */ - data->set.prefer_ascii = TRUE; - break; - - case 'O': /* octet mode */ - case 'I': /* binary mode */ - default: - /* switch off ASCII */ - data->set.prefer_ascii = FALSE; - break; - } - } - - return CURLE_OK; -} -#endif diff --git a/third_party/curl/lib/tftp.h b/third_party/curl/lib/tftp.h deleted file mode 100644 index b2d67b26b..000000000 --- a/third_party/curl/lib/tftp.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __TFTP_H -#define __TFTP_H - -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#ifndef CURL_DISABLE_TFTP -extern const struct Curl_handler Curl_handler_tftp; -#endif -#endif diff --git a/third_party/curl/lib/timeval.c b/third_party/curl/lib/timeval.c deleted file mode 100644 index cb39308e0..000000000 --- a/third_party/curl/lib/timeval.c +++ /dev/null @@ -1,131 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -#include "timeval.h" - -#if defined(WIN32) && !defined(MSDOS) - -struct timeval curlx_tvnow(void) -{ - /* - ** GetTickCount() is available on _all_ Windows versions from W95 up - ** to nowadays. Returns milliseconds elapsed since last system boot, - ** increases monotonically and wraps once 49.7 days have elapsed. - */ - struct timeval now; - DWORD milliseconds = GetTickCount(); - now.tv_sec = milliseconds / 1000; - now.tv_usec = (milliseconds % 1000) * 1000; - return now; -} - -#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) - -struct timeval curlx_tvnow(void) -{ - /* - ** clock_gettime() is granted to be increased monotonically when the - ** monotonic clock is queried. Time starting point is unspecified, it - ** could be the system start-up time, the Epoch, or something else, - ** in any case the time starting point does not change once that the - ** system has started up. - */ - struct timeval now; - struct timespec tsnow; - if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) { - now.tv_sec = tsnow.tv_sec; - now.tv_usec = tsnow.tv_nsec / 1000; - } - /* - ** Even when the configure process has truly detected monotonic clock - ** availability, it might happen that it is not actually available at - ** run-time. When this occurs simply fallback to other time source. - */ -#ifdef HAVE_GETTIMEOFDAY - else - (void)gettimeofday(&now, NULL); -#else - else { - now.tv_sec = (long)time(NULL); - now.tv_usec = 0; - } -#endif - return now; -} - -#elif defined(HAVE_GETTIMEOFDAY) - -struct timeval curlx_tvnow(void) -{ - /* - ** gettimeofday() is not granted to be increased monotonically, due to - ** clock drifting and external source time synchronization it can jump - ** forward or backward in time. - */ - struct timeval now; - (void)gettimeofday(&now, NULL); - return now; -} - -#else - -struct timeval curlx_tvnow(void) -{ - /* - ** time() returns the value of time in seconds since the Epoch. - */ - struct timeval now; - now.tv_sec = (long)time(NULL); - now.tv_usec = 0; - return now; -} - -#endif - -/* - * Make sure that the first argument is the more recent time, as otherwise - * we'll get a weird negative time-diff back... - * - * Returns: the time difference in number of milliseconds. - */ -long curlx_tvdiff(struct timeval newer, struct timeval older) -{ - return (newer.tv_sec-older.tv_sec)*1000+ - (newer.tv_usec-older.tv_usec)/1000; -} - -/* - * Same as curlx_tvdiff but with full usec resolution. - * - * Returns: the time difference in seconds with subsecond resolution. - */ -double curlx_tvdiff_secs(struct timeval newer, struct timeval older) -{ - return (double)(newer.tv_sec-older.tv_sec)+ - (double)(newer.tv_usec-older.tv_usec)/1000000.0; -} - -/* return the number of seconds in the given input timeval struct */ -long Curl_tvlong(struct timeval t1) -{ - return t1.tv_sec; -} diff --git a/third_party/curl/lib/timeval.h b/third_party/curl/lib/timeval.h deleted file mode 100644 index bc79a45ad..000000000 --- a/third_party/curl/lib/timeval.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __TIMEVAL_H -#define __TIMEVAL_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* - * CAUTION: this header is designed to work when included by the app-side - * as well as the library. Do not mix with library internals! - */ - -#include "setup.h" - -struct timeval curlx_tvnow(void); - -/* - * Make sure that the first argument (t1) is the more recent time and t2 is - * the older time, as otherwise you get a weird negative time-diff back... - * - * Returns: the time difference in number of milliseconds. - */ -long curlx_tvdiff(struct timeval t1, struct timeval t2); - -/* - * Same as curlx_tvdiff but with full usec resolution. - * - * Returns: the time difference in seconds with subsecond resolution. - */ -double curlx_tvdiff_secs(struct timeval t1, struct timeval t2); - -long Curl_tvlong(struct timeval t1); - -/* These two defines below exist to provide the older API for library - internals only. */ -#define Curl_tvnow() curlx_tvnow() -#define Curl_tvdiff(x,y) curlx_tvdiff(x,y) -#define Curl_tvdiff_secs(x,y) curlx_tvdiff_secs(x,y) - -#endif diff --git a/third_party/curl/lib/transfer.c b/third_party/curl/lib/transfer.c deleted file mode 100644 index a77cf17f0..000000000 --- a/third_party/curl/lib/transfer.c +++ /dev/null @@ -1,2384 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -/* -- WIN32 approved -- */ -#include -#include -#include -#include -#include -#include - -#include "strtoofft.h" -#include "strequal.h" -#include "rawstr.h" - -#ifdef WIN32 -#include -#include -#else -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_SIGNAL_H -#include -#endif - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#ifdef HAVE_SYS_SELECT_H -#include -#endif - -#ifndef HAVE_SOCKET -#error "We can't compile without socket() support!" -#endif - -#endif /* WIN32 */ - -#include "urldata.h" -#include -#include "netrc.h" - -#include "content_encoding.h" -#include "hostip.h" -#include "transfer.h" -#include "sendf.h" -#include "speedcheck.h" -#include "progress.h" -#include "http.h" -#include "url.h" -#include "getinfo.h" -#include "sslgen.h" -#include "http_digest.h" -#include "http_ntlm.h" -#include "http_negotiate.h" -#include "share.h" -#include "curl_memory.h" -#include "select.h" -#include "multiif.h" -#include "rtsp.h" -#include "connect.h" -#include "non-ascii.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -/* The last #include file should be: */ -#include "memdebug.h" - -#define CURL_TIMEOUT_EXPECT_100 1000 /* counting ms here */ - -/* - * This function will call the read callback to fill our buffer with data - * to upload. - */ -CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp) -{ - struct SessionHandle *data = conn->data; - size_t buffersize = (size_t)bytes; - int nread; -#ifdef CURL_DOES_CONVERSIONS - bool sending_http_headers = FALSE; - - if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) && - (data->state.proto.http->sending == HTTPSEND_REQUEST)) { - /* We're sending the HTTP request headers, not the data. - Remember that so we don't re-translate them into garbage. */ - sending_http_headers = TRUE; - } -#endif - - if(data->req.upload_chunky) { - /* if chunked Transfer-Encoding */ - buffersize -= (8 + 2 + 2); /* 32bit hex + CRLF + CRLF */ - data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */ - } - - /* this function returns a size_t, so we typecast to int to prevent warnings - with picky compilers */ - nread = (int)conn->fread_func(data->req.upload_fromhere, 1, - buffersize, conn->fread_in); - - if(nread == CURL_READFUNC_ABORT) { - failf(data, "operation aborted by callback"); - *nreadp = 0; - return CURLE_ABORTED_BY_CALLBACK; - } - else if(nread == CURL_READFUNC_PAUSE) { - struct SingleRequest *k = &data->req; - /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */ - k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */ - if(data->req.upload_chunky) { - /* Back out the preallocation done above */ - data->req.upload_fromhere -= (8 + 2); - } - *nreadp = 0; - return CURLE_OK; /* nothing was read */ - } - else if((size_t)nread > buffersize) { - /* the read function returned a too large value */ - *nreadp = 0; - failf(data, "read function returned funny value"); - return CURLE_READ_ERROR; - } - - if(!data->req.forbidchunk && data->req.upload_chunky) { - /* if chunked Transfer-Encoding - * build chunk: - * - * CRLF - * CRLF - */ - /* On non-ASCII platforms the may or may not be - translated based on set.prefer_ascii while the protocol - portion must always be translated to the network encoding. - To further complicate matters, line end conversion might be - done later on, so we need to prevent CRLFs from becoming - CRCRLFs if that's the case. To do this we use bare LFs - here, knowing they'll become CRLFs later on. - */ - - char hexbuffer[11]; - const char *endofline_native; - const char *endofline_network; - int hexlen; -#ifdef CURL_DO_LINEEND_CONV - if((data->set.crlf) || (data->set.prefer_ascii)) { -#else - if(data->set.crlf) { -#endif /* CURL_DO_LINEEND_CONV */ - /* \n will become \r\n later on */ - endofline_native = "\n"; - endofline_network = "\x0a"; - } - else { - endofline_native = "\r\n"; - endofline_network = "\x0d\x0a"; - } - hexlen = snprintf(hexbuffer, sizeof(hexbuffer), - "%x%s", nread, endofline_native); - - /* move buffer pointer */ - data->req.upload_fromhere -= hexlen; - nread += hexlen; - - /* copy the prefix to the buffer, leaving out the NUL */ - memcpy(data->req.upload_fromhere, hexbuffer, hexlen); - - /* always append ASCII CRLF to the data */ - memcpy(data->req.upload_fromhere + nread, - endofline_network, - strlen(endofline_network)); - -#ifdef CURL_DOES_CONVERSIONS - CURLcode res; - int length; - if(data->set.prefer_ascii) { - /* translate the protocol and data */ - length = nread; - } - else { - /* just translate the protocol portion */ - length = strlen(hexbuffer); - } - res = Curl_convert_to_network(data, data->req.upload_fromhere, length); - /* Curl_convert_to_network calls failf if unsuccessful */ - if(res) - return(res); -#endif /* CURL_DOES_CONVERSIONS */ - - if((nread - hexlen) == 0) - /* mark this as done once this chunk is transferred */ - data->req.upload_done = TRUE; - - nread+=(int)strlen(endofline_native); /* for the added end of line */ - } -#ifdef CURL_DOES_CONVERSIONS - else if((data->set.prefer_ascii) && (!sending_http_headers)) { - CURLcode res; - res = Curl_convert_to_network(data, data->req.upload_fromhere, nread); - /* Curl_convert_to_network calls failf if unsuccessful */ - if(res != CURLE_OK) - return(res); - } -#endif /* CURL_DOES_CONVERSIONS */ - - *nreadp = nread; - - return CURLE_OK; -} - - -/* - * Curl_readrewind() rewinds the read stream. This is typically used for HTTP - * POST/PUT with multi-pass authentication when a sending was denied and a - * resend is necessary. - */ -CURLcode Curl_readrewind(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - - conn->bits.rewindaftersend = FALSE; /* we rewind now */ - - /* explicitly switch off sending data on this connection now since we are - about to restart a new transfer and thus we want to avoid inadvertently - sending more data on the existing connection until the next transfer - starts */ - data->req.keepon &= ~KEEP_SEND; - - /* We have sent away data. If not using CURLOPT_POSTFIELDS or - CURLOPT_HTTPPOST, call app to rewind - */ - if(data->set.postfields || - (data->set.httpreq == HTTPREQ_POST_FORM)) - ; /* do nothing */ - else { - if(data->set.seek_func) { - int err; - - err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET); - if(err) { - failf(data, "seek callback returned error %d", (int)err); - return CURLE_SEND_FAIL_REWIND; - } - } - else if(data->set.ioctl_func) { - curlioerr err; - - err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD, - data->set.ioctl_client); - infof(data, "the ioctl callback returned %d\n", (int)err); - - if(err) { - /* FIXME: convert to a human readable error message */ - failf(data, "ioctl callback returned error %d", (int)err); - return CURLE_SEND_FAIL_REWIND; - } - } - else { - /* If no CURLOPT_READFUNCTION is used, we know that we operate on a - given FILE * stream and we can actually attempt to rewind that - ourself with fseek() */ - if(data->set.fread_func == (curl_read_callback)fread) { - if(-1 != fseek(data->set.in, 0, SEEK_SET)) - /* successful rewind */ - return CURLE_OK; - } - - /* no callback set or failure above, makes us fail at once */ - failf(data, "necessary data rewind wasn't possible"); - return CURLE_SEND_FAIL_REWIND; - } - } - return CURLE_OK; -} - -static int data_pending(const struct connectdata *conn) -{ - /* in the case of libssh2, we can never be really sure that we have emptied - its internal buffers so we MUST always try until we get EAGAIN back */ - return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) || - Curl_ssl_data_pending(conn, FIRSTSOCKET); -} - -static void read_rewind(struct connectdata *conn, - size_t thismuch) -{ - DEBUGASSERT(conn->read_pos >= thismuch); - - conn->read_pos -= thismuch; - conn->bits.stream_was_rewound = TRUE; - -#ifdef DEBUGBUILD - { - char buf[512 + 1]; - size_t show; - - show = CURLMIN(conn->buf_len - conn->read_pos, sizeof(buf)-1); - if(conn->master_buffer) { - memcpy(buf, conn->master_buffer + conn->read_pos, show); - buf[show] = '\0'; - } - else { - buf[0] = '\0'; - } - - DEBUGF(infof(conn->data, - "Buffer after stream rewind (read_pos = %zu): [%s]", - conn->read_pos, buf)); - } -#endif -} - -/* - * Check to see if CURLOPT_TIMECONDITION was met by comparing the time of the - * remote document with the time provided by CURLOPT_TIMEVAL - */ -bool Curl_meets_timecondition(struct SessionHandle *data, time_t timeofdoc) -{ - if((timeofdoc == 0) || (data->set.timevalue == 0)) - return TRUE; - - switch(data->set.timecondition) { - case CURL_TIMECOND_IFMODSINCE: - default: - if(timeofdoc <= data->set.timevalue) { - infof(data, - "The requested document is not new enough\n"); - data->info.timecond = TRUE; - return FALSE; - } - break; - case CURL_TIMECOND_IFUNMODSINCE: - if(timeofdoc >= data->set.timevalue) { - infof(data, - "The requested document is not old enough\n"); - data->info.timecond = TRUE; - return FALSE; - } - break; - } - - return TRUE; -} - -/* - * Go ahead and do a read if we have a readable socket or if - * the stream was rewound (in which case we have data in a - * buffer) - */ -static CURLcode readwrite_data(struct SessionHandle *data, - struct connectdata *conn, - struct SingleRequest *k, - int *didwhat, bool *done) -{ - CURLcode result = CURLE_OK; - ssize_t nread; /* number of bytes read */ - size_t excess = 0; /* excess bytes read */ - bool is_empty_data = FALSE; -#ifndef CURL_DISABLE_RTSP - bool readmore = FALSE; /* used by RTP to signal for more data */ -#endif - - *done = FALSE; - - /* This is where we loop until we have read everything there is to - read or we get a CURLE_AGAIN */ - do { - size_t buffersize = data->set.buffer_size? - data->set.buffer_size : BUFSIZE; - size_t bytestoread = buffersize; - - if(k->size != -1 && !k->header) { - /* make sure we don't read "too much" if we can help it since we - might be pipelining and then someone else might want to read what - follows! */ - curl_off_t totalleft = k->size - k->bytecount; - if(totalleft < (curl_off_t)bytestoread) - bytestoread = (size_t)totalleft; - } - - if(bytestoread) { - /* receive data from the network! */ - result = Curl_read(conn, conn->sockfd, k->buf, bytestoread, &nread); - - /* read would've blocked */ - if(CURLE_AGAIN == result) - break; /* get out of loop */ - - if(result>0) - return result; - } - else { - /* read nothing but since we wanted nothing we consider this an OK - situation to proceed from */ - nread = 0; - } - - if((k->bytecount == 0) && (k->writebytecount == 0)) { - Curl_pgrsTime(data, TIMER_STARTTRANSFER); - if(k->exp100 > EXP100_SEND_DATA) - /* set time stamp to compare with when waiting for the 100 */ - k->start100 = Curl_tvnow(); - } - - *didwhat |= KEEP_RECV; - /* indicates data of zero size, i.e. empty file */ - is_empty_data = (bool)((nread == 0) && (k->bodywrites == 0)); - - /* NUL terminate, allowing string ops to be used */ - if(0 < nread || is_empty_data) { - k->buf[nread] = 0; - } - else if(0 >= nread) { - /* if we receive 0 or less here, the server closed the connection - and we bail out from this! */ - DEBUGF(infof(data, "nread <= 0, server closed connection, bailing\n")); - k->keepon &= ~KEEP_RECV; - break; - } - - /* Default buffer to use when we write the buffer, it may be changed - in the flow below before the actual storing is done. */ - k->str = k->buf; - -#ifndef CURL_DISABLE_RTSP - /* Check for RTP at the beginning of the data */ - if(conn->handler->protocol & CURLPROTO_RTSP) { - result = Curl_rtsp_rtp_readwrite(data, conn, &nread, &readmore); - if(result) - return result; - if(readmore) - break; - } -#endif - -#ifndef CURL_DISABLE_HTTP - /* Since this is a two-state thing, we check if we are parsing - headers at the moment or not. */ - if(k->header) { - /* we are in parse-the-header-mode */ - bool stop_reading = FALSE; - result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading); - if(result) - return result; - -#ifndef CURL_DISABLE_RTSP - /* Check for RTP after the headers if there is no Content */ - if(k->maxdownload <= 0 && nread > 0 && - (conn->handler->protocol & CURLPROTO_RTSP)) { - result = Curl_rtsp_rtp_readwrite(data, conn, &nread, &readmore); - if(result) - return result; - if(readmore) - break; - } -#endif - - if(stop_reading) { - /* We've stopped dealing with input, get out of the do-while loop */ - - if(nread > 0) { - if(conn->data->multi && Curl_multi_canPipeline(conn->data->multi)) { - infof(data, - "Rewinding stream by : %zd" - " bytes on url %s (zero-length body)\n", - nread, data->state.path); - read_rewind(conn, (size_t)nread); - } - else { - infof(data, - "Excess found in a non pipelined read:" - " excess = %zd" - " url = %s (zero-length body)\n", - nread, data->state.path); - } - } - - break; - } - } -#endif /* CURL_DISABLE_HTTP */ - - - /* This is not an 'else if' since it may be a rest from the header - parsing, where the beginning of the buffer is headers and the end - is non-headers. */ - if(k->str && !k->header && (nread > 0 || is_empty_data)) { - - -#ifndef CURL_DISABLE_HTTP - if(0 == k->bodywrites && !is_empty_data) { - /* These checks are only made the first time we are about to - write a piece of the body */ - if(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) { - /* HTTP-only checks */ - - if(data->req.newurl) { - if(conn->bits.close) { - /* Abort after the headers if "follow Location" is set - and we're set to close anyway. */ - k->keepon &= ~KEEP_RECV; - *done = TRUE; - return CURLE_OK; - } - /* We have a new url to load, but since we want to be able - to re-use this connection properly, we read the full - response in "ignore more" */ - k->ignorebody = TRUE; - infof(data, "Ignoring the response-body\n"); - } - if(data->state.resume_from && !k->content_range && - (data->set.httpreq==HTTPREQ_GET) && - !k->ignorebody) { - /* we wanted to resume a download, although the server doesn't - * seem to support this and we did this with a GET (if it - * wasn't a GET we did a POST or PUT resume) */ - failf(data, "HTTP server doesn't seem to support " - "byte ranges. Cannot resume."); - return CURLE_RANGE_ERROR; - } - - if(data->set.timecondition && !data->state.range) { - /* A time condition has been set AND no ranges have been - requested. This seems to be what chapter 13.3.4 of - RFC 2616 defines to be the correct action for a - HTTP/1.1 client */ - - if(!Curl_meets_timecondition(data, k->timeofdoc)) { - *done = TRUE; - return CURLE_OK; - } - } /* we have a time condition */ - - } /* this is HTTP */ - } /* this is the first time we write a body part */ -#endif /* CURL_DISABLE_HTTP */ - k->bodywrites++; - - /* pass data to the debug function before it gets "dechunked" */ - if(data->set.verbose) { - if(k->badheader) { - Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff, - (size_t)k->hbuflen, conn); - if(k->badheader == HEADER_PARTHEADER) - Curl_debug(data, CURLINFO_DATA_IN, - k->str, (size_t)nread, conn); - } - else - Curl_debug(data, CURLINFO_DATA_IN, - k->str, (size_t)nread, conn); - } - -#ifndef CURL_DISABLE_HTTP - if(k->chunk) { - /* - * Here comes a chunked transfer flying and we need to decode this - * properly. While the name says read, this function both reads - * and writes away the data. The returned 'nread' holds the number - * of actual data it wrote to the client. - */ - - CHUNKcode res = - Curl_httpchunk_read(conn, k->str, nread, &nread); - - if(CHUNKE_OK < res) { - if(CHUNKE_WRITE_ERROR == res) { - failf(data, "Failed writing data"); - return CURLE_WRITE_ERROR; - } - failf(data, "Received problem %d in the chunky parser", (int)res); - return CURLE_RECV_ERROR; - } - else if(CHUNKE_STOP == res) { - size_t dataleft; - /* we're done reading chunks! */ - k->keepon &= ~KEEP_RECV; /* read no more */ - - /* There are now possibly N number of bytes at the end of the - str buffer that weren't written to the client. - - We DO care about this data if we are pipelining. - Push it back to be read on the next pass. */ - - dataleft = conn->chunk.dataleft; - if(dataleft != 0) { - infof(conn->data, "Leftovers after chunking: %zu bytes", dataleft); - if(conn->data->multi && Curl_multi_canPipeline(conn->data->multi)) { - /* only attempt the rewind if we truly are pipelining */ - infof(conn->data, "Rewinding %zu bytes\n",dataleft); - read_rewind(conn, dataleft); - } - } - } - /* If it returned OK, we just keep going */ - } -#endif /* CURL_DISABLE_HTTP */ - - /* Account for body content stored in the header buffer */ - if(k->badheader && !k->ignorebody) { - DEBUGF(infof(data, "Increasing bytecount by %zu from hbuflen\n", - k->hbuflen)); - k->bytecount += k->hbuflen; - } - - if((-1 != k->maxdownload) && - (k->bytecount + nread >= k->maxdownload)) { - - excess = (size_t)(k->bytecount + nread - k->maxdownload); - if(excess > 0 && !k->ignorebody) { - if(conn->data->multi && Curl_multi_canPipeline(conn->data->multi)) { - /* The 'excess' amount below can't be more than BUFSIZE which - always will fit in a size_t */ - infof(data, - "Rewinding stream by : %zu" - " bytes on url %s (size = %" FORMAT_OFF_T - ", maxdownload = %" FORMAT_OFF_T - ", bytecount = %" FORMAT_OFF_T ", nread = %zd)\n", - excess, data->state.path, - k->size, k->maxdownload, k->bytecount, nread); - read_rewind(conn, excess); - } - else { - infof(data, - "Excess found in a non pipelined read:" - " excess = %zu" - ", size = %" FORMAT_OFF_T - ", maxdownload = %" FORMAT_OFF_T - ", bytecount = %" FORMAT_OFF_T "\n", - excess, k->size, k->maxdownload, k->bytecount); - } - } - - nread = (ssize_t) (k->maxdownload - k->bytecount); - if(nread < 0 ) /* this should be unusual */ - nread = 0; - - k->keepon &= ~KEEP_RECV; /* we're done reading */ - } - - k->bytecount += nread; - - Curl_pgrsSetDownloadCounter(data, k->bytecount); - - if(!k->chunk && (nread || k->badheader || is_empty_data)) { - /* If this is chunky transfer, it was already written */ - - if(k->badheader && !k->ignorebody) { - /* we parsed a piece of data wrongly assuming it was a header - and now we output it as body instead */ - - /* Don't let excess data pollute body writes */ - if(k->maxdownload == -1 || (curl_off_t)k->hbuflen <= k->maxdownload) - result = Curl_client_write(conn, CLIENTWRITE_BODY, - data->state.headerbuff, - k->hbuflen); - else - result = Curl_client_write(conn, CLIENTWRITE_BODY, - data->state.headerbuff, - (size_t)k->maxdownload); - - if(result) - return result; - } - if(k->badheader < HEADER_ALLBAD) { - /* This switch handles various content encodings. If there's an - error here, be sure to check over the almost identical code - in http_chunks.c. - Make sure that ALL_CONTENT_ENCODINGS contains all the - encodings handled here. */ -#ifdef HAVE_LIBZ - switch (conn->data->set.http_ce_skip ? - IDENTITY : k->auto_decoding) { - case IDENTITY: -#endif - /* This is the default when the server sends no - Content-Encoding header. See Curl_readwrite_init; the - memset() call initializes k->auto_decoding to zero. */ - if(!k->ignorebody) { - -#ifndef CURL_DISABLE_POP3 - if(conn->handler->protocol&CURLPROTO_POP3) - result = Curl_pop3_write(conn, k->str, nread); - else -#endif /* CURL_DISABLE_POP3 */ - - result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str, - nread); - } -#ifdef HAVE_LIBZ - break; - - case DEFLATE: - /* Assume CLIENTWRITE_BODY; headers are not encoded. */ - if(!k->ignorebody) - result = Curl_unencode_deflate_write(conn, k, nread); - break; - - case GZIP: - /* Assume CLIENTWRITE_BODY; headers are not encoded. */ - if(!k->ignorebody) - result = Curl_unencode_gzip_write(conn, k, nread); - break; - - case COMPRESS: - default: - failf (data, "Unrecognized content encoding type. " - "libcurl understands `identity', `deflate' and `gzip' " - "content encodings."); - result = CURLE_BAD_CONTENT_ENCODING; - break; - } -#endif - } - k->badheader = HEADER_NORMAL; /* taken care of now */ - - if(result) - return result; - } - - } /* if(! header and data to read ) */ - -#ifndef CURL_DISABLE_RTSP - if(excess > 0 && !conn->bits.stream_was_rewound && - (conn->handler->protocol & CURLPROTO_RTSP)) { - /* Check for RTP after the content if there is unrewound excess */ - - /* Parse the excess data */ - k->str += nread; - nread = (ssize_t)excess; - - result = Curl_rtsp_rtp_readwrite(data, conn, &nread, &readmore); - if(result) - return result; - - if(readmore) - k->keepon |= KEEP_RECV; /* we're not done reading */ - break; - } -#endif - - if(is_empty_data) { - /* if we received nothing, the server closed the connection and we - are done */ - k->keepon &= ~KEEP_RECV; - } - - } while(data_pending(conn)); - - if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) && - conn->bits.close ) { - /* When we've read the entire thing and the close bit is set, the server - may now close the connection. If there's now any kind of sending going - on from our side, we need to stop that immediately. */ - infof(data, "we are done reading and this is set to close, stop send\n"); - k->keepon &= ~KEEP_SEND; /* no writing anymore either */ - } - - return CURLE_OK; -} - -/* - * Send data to upload to the server, when the socket is writable. - */ -static CURLcode readwrite_upload(struct SessionHandle *data, - struct connectdata *conn, - struct SingleRequest *k, - int *didwhat) -{ - ssize_t i, si; - ssize_t bytes_written; - CURLcode result; - ssize_t nread; /* number of bytes read */ - bool sending_http_headers = FALSE; - - if((k->bytecount == 0) && (k->writebytecount == 0)) - Curl_pgrsTime(data, TIMER_STARTTRANSFER); - - *didwhat |= KEEP_SEND; - - /* - * We loop here to do the READ and SEND loop until we run out of - * data to send or until we get EWOULDBLOCK back - */ - do { - - /* only read more data if there's no upload data already - present in the upload buffer */ - if(0 == data->req.upload_present) { - /* init the "upload from here" pointer */ - data->req.upload_fromhere = k->uploadbuf; - - if(!k->upload_done) { - /* HTTP pollution, this should be written nicer to become more - protocol agnostic. */ - int fillcount; - - if((k->exp100 == EXP100_SENDING_REQUEST) && - (data->state.proto.http->sending == HTTPSEND_BODY)) { - /* If this call is to send body data, we must take some action: - We have sent off the full HTTP 1.1 request, and we shall now - go into the Expect: 100 state and await such a header */ - k->exp100 = EXP100_AWAITING_CONTINUE; /* wait for the header */ - k->keepon &= ~KEEP_SEND; /* disable writing */ - k->start100 = Curl_tvnow(); /* timeout count starts now */ - *didwhat &= ~KEEP_SEND; /* we didn't write anything actually */ - - /* set a timeout for the multi interface */ - Curl_expire(data, CURL_TIMEOUT_EXPECT_100); - break; - } - - if(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) { - if(data->state.proto.http->sending == HTTPSEND_REQUEST) - /* We're sending the HTTP request headers, not the data. - Remember that so we don't change the line endings. */ - sending_http_headers = TRUE; - else - sending_http_headers = FALSE; - } - - result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount); - if(result) - return result; - - nread = (ssize_t)fillcount; - } - else - nread = 0; /* we're done uploading/reading */ - - if(!nread && (k->keepon & KEEP_SEND_PAUSE)) { - /* this is a paused transfer */ - break; - } - else if(nread<=0) { - /* done */ - k->keepon &= ~KEEP_SEND; /* we're done writing */ - - if(conn->bits.rewindaftersend) { - result = Curl_readrewind(conn); - if(result) - return result; - } - break; - } - - /* store number of bytes available for upload */ - data->req.upload_present = nread; - -#ifndef CURL_DISABLE_SMTP - if(conn->handler->protocol & CURLPROTO_SMTP) { - result = Curl_smtp_escape_eob(conn, nread); - if(result) - return result; - } - else -#endif /* CURL_DISABLE_SMTP */ - - /* convert LF to CRLF if so asked */ - if((!sending_http_headers) && -#ifdef CURL_DO_LINEEND_CONV - /* always convert if we're FTPing in ASCII mode */ - ((data->set.crlf) || (data->set.prefer_ascii))) { -#else - (data->set.crlf)) { -#endif - if(data->state.scratch == NULL) - data->state.scratch = malloc(2*BUFSIZE); - if(data->state.scratch == NULL) { - failf (data, "Failed to alloc scratch buffer!"); - return CURLE_OUT_OF_MEMORY; - } - /* - * ASCII/EBCDIC Note: This is presumably a text (not binary) - * transfer so the data should already be in ASCII. - * That means the hex values for ASCII CR (0x0d) & LF (0x0a) - * must be used instead of the escape sequences \r & \n. - */ - for(i = 0, si = 0; i < nread; i++, si++) { - if(data->req.upload_fromhere[i] == 0x0a) { - data->state.scratch[si++] = 0x0d; - data->state.scratch[si] = 0x0a; - if(!data->set.crlf) { - /* we're here only because FTP is in ASCII mode... - bump infilesize for the LF we just added */ - data->set.infilesize++; - } - } - else - data->state.scratch[si] = data->req.upload_fromhere[i]; - } - if(si != nread) { - /* only perform the special operation if we really did replace - anything */ - nread = si; - - /* upload from the new (replaced) buffer instead */ - data->req.upload_fromhere = data->state.scratch; - - /* set the new amount too */ - data->req.upload_present = nread; - } - } - } /* if 0 == data->req.upload_present */ - else { - /* We have a partial buffer left from a previous "round". Use - that instead of reading more data */ - } - - /* write to socket (send away data) */ - result = Curl_write(conn, - conn->writesockfd, /* socket to send to */ - data->req.upload_fromhere, /* buffer pointer */ - data->req.upload_present, /* buffer size */ - &bytes_written); /* actually sent */ - - if(result) - return result; - - if(data->set.verbose) - /* show the data before we change the pointer upload_fromhere */ - Curl_debug(data, CURLINFO_DATA_OUT, data->req.upload_fromhere, - (size_t)bytes_written, conn); - - k->writebytecount += bytes_written; - - if(k->writebytecount == data->set.infilesize) { - /* we have sent all data we were supposed to */ - k->upload_done = TRUE; - infof(data, "We are completely uploaded and fine\n"); - } - - if(data->req.upload_present != bytes_written) { - /* we only wrote a part of the buffer (if anything), deal with it! */ - - /* store the amount of bytes left in the buffer to write */ - data->req.upload_present -= bytes_written; - - /* advance the pointer where to find the buffer when the next send - is to happen */ - data->req.upload_fromhere += bytes_written; - } - else { - /* we've uploaded that buffer now */ - data->req.upload_fromhere = k->uploadbuf; - data->req.upload_present = 0; /* no more bytes left */ - - if(k->upload_done) { - /* switch off writing, we're done! */ - k->keepon &= ~KEEP_SEND; /* we're done writing */ - } - } - - Curl_pgrsSetUploadCounter(data, k->writebytecount); - - } while(0); /* just to break out from! */ - - return CURLE_OK; -} - -/* - * Curl_readwrite() is the low-level function to be called when data is to - * be read and written to/from the connection. - */ -CURLcode Curl_readwrite(struct connectdata *conn, - bool *done) -{ - struct SessionHandle *data = conn->data; - struct SingleRequest *k = &data->req; - CURLcode result; - int didwhat=0; - - curl_socket_t fd_read; - curl_socket_t fd_write; - int select_res = conn->cselect_bits; - - conn->cselect_bits = 0; - - /* only use the proper socket if the *_HOLD bit is not set simultaneously as - then we are in rate limiting state in that transfer direction */ - - if((k->keepon & KEEP_RECVBITS) == KEEP_RECV) - fd_read = conn->sockfd; - else - fd_read = CURL_SOCKET_BAD; - - if((k->keepon & KEEP_SENDBITS) == KEEP_SEND) - fd_write = conn->writesockfd; - else - fd_write = CURL_SOCKET_BAD; - - if(!select_res) /* Call for select()/poll() only, if read/write/error - status is not known. */ - select_res = Curl_socket_ready(fd_read, fd_write, 0); - - if(select_res == CURL_CSELECT_ERR) { - failf(data, "select/poll returned error"); - return CURLE_SEND_ERROR; - } - - /* We go ahead and do a read if we have a readable socket or if - the stream was rewound (in which case we have data in a - buffer) */ - if((k->keepon & KEEP_RECV) && - ((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) { - - result = readwrite_data(data, conn, k, &didwhat, done); - if(result || *done) - return result; - } - - /* If we still have writing to do, we check if we have a writable socket. */ - if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) { - /* write */ - - result = readwrite_upload(data, conn, k, &didwhat); - if(result) - return result; - } - - k->now = Curl_tvnow(); - if(didwhat) { - /* Update read/write counters */ - if(k->bytecountp) - *k->bytecountp = k->bytecount; /* read count */ - if(k->writebytecountp) - *k->writebytecountp = k->writebytecount; /* write count */ - } - else { - /* no read no write, this is a timeout? */ - if(k->exp100 == EXP100_AWAITING_CONTINUE) { - /* This should allow some time for the header to arrive, but only a - very short time as otherwise it'll be too much wasted time too - often. */ - - /* Quoting RFC2616, section "8.2.3 Use of the 100 (Continue) Status": - - Therefore, when a client sends this header field to an origin server - (possibly via a proxy) from which it has never seen a 100 (Continue) - status, the client SHOULD NOT wait for an indefinite period before - sending the request body. - - */ - - long ms = Curl_tvdiff(k->now, k->start100); - if(ms > CURL_TIMEOUT_EXPECT_100) { - /* we've waited long enough, continue anyway */ - k->exp100 = EXP100_SEND_DATA; - k->keepon |= KEEP_SEND; - infof(data, "Done waiting for 100-continue\n"); - } - } - } - - if(Curl_pgrsUpdate(conn)) - result = CURLE_ABORTED_BY_CALLBACK; - else - result = Curl_speedcheck(data, k->now); - if(result) - return result; - - if(k->keepon) { - if(0 > Curl_timeleft(data, &k->now, FALSE)) { - if(k->size != -1) { - failf(data, "Operation timed out after %ld milliseconds with %" - FORMAT_OFF_T " out of %" FORMAT_OFF_T " bytes received", - Curl_tvdiff(k->now, data->progress.t_startsingle), k->bytecount, - k->size); - } - else { - failf(data, "Operation timed out after %ld milliseconds with %" - FORMAT_OFF_T " bytes received", - Curl_tvdiff(k->now, data->progress.t_startsingle), k->bytecount); - } - return CURLE_OPERATION_TIMEDOUT; - } - } - else { - /* - * The transfer has been performed. Just make some general checks before - * returning. - */ - - if(!(data->set.opt_no_body) && (k->size != -1) && - (k->bytecount != k->size) && -#ifdef CURL_DO_LINEEND_CONV - /* Most FTP servers don't adjust their file SIZE response for CRLFs, - so we'll check to see if the discrepancy can be explained - by the number of CRLFs we've changed to LFs. - */ - (k->bytecount != (k->size + data->state.crlf_conversions)) && -#endif /* CURL_DO_LINEEND_CONV */ - !data->req.newurl) { - failf(data, "transfer closed with %" FORMAT_OFF_T - " bytes remaining to read", - k->size - k->bytecount); - return CURLE_PARTIAL_FILE; - } - else if(!(data->set.opt_no_body) && - k->chunk && - (conn->chunk.state != CHUNK_STOP)) { - /* - * In chunked mode, return an error if the connection is closed prior to - * the empty (terminiating) chunk is read. - * - * The condition above used to check for - * conn->proto.http->chunk.datasize != 0 which is true after reading - * *any* chunk, not just the empty chunk. - * - */ - failf(data, "transfer closed with outstanding read data remaining"); - return CURLE_PARTIAL_FILE; - } - if(Curl_pgrsUpdate(conn)) - return CURLE_ABORTED_BY_CALLBACK; - } - - /* Now update the "done" boolean we return */ - *done = (bool)(0 == (k->keepon&(KEEP_RECV|KEEP_SEND| - KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))); - - return CURLE_OK; -} - -/* - * Curl_single_getsock() gets called by the multi interface code when the app - * has requested to get the sockets for the current connection. This function - * will then be called once for every connection that the multi interface - * keeps track of. This function will only be called for connections that are - * in the proper state to have this information available. - */ -int Curl_single_getsock(const struct connectdata *conn, - curl_socket_t *sock, /* points to numsocks number - of sockets */ - int numsocks) -{ - const struct SessionHandle *data = conn->data; - int bitmap = GETSOCK_BLANK; - unsigned sockindex = 0; - - if(conn->handler->perform_getsock) - return conn->handler->perform_getsock(conn, sock, numsocks); - - if(numsocks < 2) - /* simple check but we might need two slots */ - return GETSOCK_BLANK; - - /* don't include HOLD and PAUSE connections */ - if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) { - - DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD); - - bitmap |= GETSOCK_READSOCK(sockindex); - sock[sockindex] = conn->sockfd; - } - - /* don't include HOLD and PAUSE connections */ - if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) { - - if((conn->sockfd != conn->writesockfd) || - !(data->req.keepon & KEEP_RECV)) { - /* only if they are not the same socket or we didn't have a readable - one, we increase index */ - if(data->req.keepon & KEEP_RECV) - sockindex++; /* increase index if we need two entries */ - - DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD); - - sock[sockindex] = conn->writesockfd; - } - - bitmap |= GETSOCK_WRITESOCK(sockindex); - } - - return bitmap; -} - -/* - * Determine optimum sleep time based on configured rate, current rate, - * and packet size. - * Returns value in mili-seconds. - * - * The basic idea is to adjust the desired rate up/down in this method - * based on whether we are running too slow or too fast. Then, calculate - * how many miliseconds to wait for the next packet to achieve this new - * rate. - */ -long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps, - int pkt_size) -{ - curl_off_t min_sleep = 0; - curl_off_t rv = 0; - - if (rate_bps == 0) - return 0; - - /* If running faster than about .1% of the desired speed, slow - * us down a bit. Use shift instead of division as the 0.1% - * cutoff is arbitrary anyway. - */ - if (cur_rate_bps > (rate_bps + (rate_bps >> 10))) { - /* running too fast, decrease target rate by 1/64th of rate */ - rate_bps -= rate_bps >> 6; - min_sleep = 1; - } - else if (cur_rate_bps < (rate_bps - (rate_bps >> 10))) { - /* running too slow, increase target rate by 1/64th of rate */ - rate_bps += rate_bps >> 6; - } - - /* Determine number of miliseconds to wait until we do - * the next packet at the adjusted rate. We should wait - * longer when using larger packets, for instance. - */ - rv = ((curl_off_t)((pkt_size * 8) * 1000) / rate_bps); - - /* Catch rounding errors and always slow down at least 1ms if - * we are running too fast. - */ - if (rv < min_sleep) - rv = min_sleep; - - /* Bound value to fit in 'long' on 32-bit platform. That's - * plenty long enough anyway! - */ - if(rv > 0x7fffffff) - rv = 0x7fffffff; - - return (long)rv; -} - - -/* - * Transfer() - * - * This function is what performs the actual transfer. It is capable of doing - * both ways simultaneously. The transfer must already have been setup by a - * call to Curl_setup_transfer(). - * - * Note that headers are created in a preallocated buffer of a default size. - * That buffer can be enlarged on demand, but it is never shrunken again. - * - */ - -static CURLcode -Transfer(struct connectdata *conn) -{ - CURLcode result; - struct SessionHandle *data = conn->data; - struct SingleRequest *k = &data->req; - bool done=FALSE; - bool first=TRUE; - int timeout_ms; - int buffersize; - int totmp; - - if((conn->sockfd == CURL_SOCKET_BAD) && - (conn->writesockfd == CURL_SOCKET_BAD)) - /* nothing to read, nothing to write, we're already OK! */ - return CURLE_OK; - - /* we want header and/or body, if neither then don't do this! */ - if(!k->getheader && data->set.opt_no_body) - return CURLE_OK; - - while(!done) { - curl_socket_t fd_read = conn->sockfd; - curl_socket_t fd_write = conn->writesockfd; - int keepon = k->keepon; - timeout_ms = 1000; - - if(conn->waitfor) { - /* if waitfor is set, get the RECV and SEND bits from that but keep the - other bits */ - keepon &= ~ (KEEP_RECV|KEEP_SEND); - keepon |= conn->waitfor & (KEEP_RECV|KEEP_SEND); - } - - /* limit-rate logic: if speed exceeds threshold, then do not include fd in - select set. The current speed is recalculated in each Curl_readwrite() - call */ - if((keepon & KEEP_SEND) && - (!data->set.max_send_speed || - (data->progress.ulspeed < data->set.max_send_speed) )) { - k->keepon &= ~KEEP_SEND_HOLD; - } - else { - if (data->set.upload && data->set.max_send_speed && - (data->progress.ulspeed > data->set.max_send_speed) ) { - /* calculate upload rate-limitation timeout. */ - buffersize = (int)(data->set.buffer_size ? - data->set.buffer_size : BUFSIZE); - totmp = (int)Curl_sleep_time(data->set.max_send_speed, - data->progress.ulspeed, buffersize); - if (totmp < timeout_ms) - timeout_ms = totmp; - } - fd_write = CURL_SOCKET_BAD; - if(keepon & KEEP_SEND) - k->keepon |= KEEP_SEND_HOLD; /* hold it */ - } - - if((keepon & KEEP_RECV) && - (!data->set.max_recv_speed || - (data->progress.dlspeed < data->set.max_recv_speed)) ) { - k->keepon &= ~KEEP_RECV_HOLD; - } - else { - if ((!data->set.upload) && data->set.max_recv_speed && - (data->progress.dlspeed > data->set.max_recv_speed)) { - /* Calculate download rate-limitation timeout. */ - buffersize = (int)(data->set.buffer_size ? - data->set.buffer_size : BUFSIZE); - totmp = (int)Curl_sleep_time(data->set.max_recv_speed, - data->progress.dlspeed, buffersize); - if (totmp < timeout_ms) - timeout_ms = totmp; - } - fd_read = CURL_SOCKET_BAD; - if(keepon & KEEP_RECV) - k->keepon |= KEEP_RECV_HOLD; /* hold it */ - } - - /* pause logic. Don't check descriptors for paused connections */ - if(k->keepon & KEEP_RECV_PAUSE) - fd_read = CURL_SOCKET_BAD; - if(k->keepon & KEEP_SEND_PAUSE) - fd_write = CURL_SOCKET_BAD; - - /* The *_HOLD and *_PAUSE logic is necessary since even though there might - be no traffic during the select interval, we still call - Curl_readwrite() for the timeout case and if we limit transfer speed we - must make sure that this function doesn't transfer anything while in - HOLD status. - - The no timeout for the first round is for the protocols for which data - has already been slurped off the socket and thus waiting for action - won't work since it'll wait even though there is already data present - to work with. */ - if(first && - ((fd_read != CURL_SOCKET_BAD) || (fd_write != CURL_SOCKET_BAD))) - /* if this is the first lap and one of the file descriptors is fine - to work with, skip the timeout */ - timeout_ms = 0; - else { - totmp = Curl_timeleft(data, &k->now, FALSE); - if(totmp < 0) - return CURLE_OPERATION_TIMEDOUT; - else if(!totmp) - totmp = 1000; - - if (totmp < timeout_ms) - timeout_ms = totmp; - } - - switch (Curl_socket_ready(fd_read, fd_write, timeout_ms)) { - case -1: /* select() error, stop reading */ -#ifdef EINTR - /* The EINTR is not serious, and it seems you might get this more - often when using the lib in a multi-threaded environment! */ - if(SOCKERRNO == EINTR) - continue; -#endif - return CURLE_RECV_ERROR; /* indicate a network problem */ - case 0: /* timeout */ - default: /* readable descriptors */ - - result = Curl_readwrite(conn, &done); - /* "done" signals to us if the transfer(s) are ready */ - break; - } - if(result) - return result; - - first = FALSE; /* not the first lap anymore */ - } - - return CURLE_OK; -} - -static CURLcode loadhostpairs(struct SessionHandle *data) -{ - struct curl_slist *hostp; - char hostname[256]; - char address[256]; - int port; - - for(hostp = data->change.resolve; hostp; hostp = hostp->next ) { - if(!hostp->data) - continue; - if(hostp->data[0] == '-') { - /* TODO: mark an entry for removal */ - } - else if(3 == sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port, - address)) { - struct Curl_dns_entry *dns; - Curl_addrinfo *addr; - - addr = Curl_str2addr(address, port); - if(!addr) { - infof(data, "Resolve %s found illegal!\n", hostp->data); - continue; - } - infof(data, "Added %s:%d:%s to DNS cache\n", - hostname, port, address); - - if(data->share) - Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - - /* put this host in the cache */ - dns = Curl_cache_addr(data, addr, hostname, port); - - if(data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); - - if(!dns) - return CURLE_OUT_OF_MEMORY; - } - } - data->change.resolve = NULL; /* dealt with now */ - - return CURLE_OK; -} - - -/* - * Curl_pretransfer() is called immediately before a transfer starts. - */ -CURLcode Curl_pretransfer(struct SessionHandle *data) -{ - CURLcode res; - if(!data->change.url) { - /* we can't do anything without URL */ - failf(data, "No URL set!"); - return CURLE_URL_MALFORMAT; - } - - /* Init the SSL session ID cache here. We do it here since we want to do it - after the *_setopt() calls (that could change the size of the cache) but - before any transfer takes place. */ - res = Curl_ssl_initsessions(data, data->set.ssl.numsessions); - if(res) - return res; - - data->set.followlocation=0; /* reset the location-follow counter */ - data->state.this_is_a_follow = FALSE; /* reset this */ - data->state.errorbuf = FALSE; /* no error has occurred */ - data->state.httpversion = 0; /* don't assume any particular server version */ - - data->state.ssl_connect_retry = FALSE; - - data->state.authproblem = FALSE; - data->state.authhost.want = data->set.httpauth; - data->state.authproxy.want = data->set.proxyauth; - Curl_safefree(data->info.wouldredirect); - data->info.wouldredirect = NULL; - - /* If there is a list of cookie files to read, do it now! */ - if(data->change.cookielist) - Curl_cookie_loadfiles(data); - - /* If there is a list of host pairs to deal with */ - if(data->change.resolve) - res = loadhostpairs(data); - - if(!res) { - /* Allow data->set.use_port to set which port to use. This needs to be - * disabled for example when we follow Location: headers to URLs using - * different ports! */ - data->state.allow_port = TRUE; - -#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) - /************************************************************* - * Tell signal handler to ignore SIGPIPE - *************************************************************/ - if(!data->set.no_signal) - data->state.prev_signal = signal(SIGPIPE, SIG_IGN); -#endif - - Curl_initinfo(data); /* reset session-specific information "variables" */ - Curl_pgrsStartNow(data); - - if(data->set.timeout) - Curl_expire(data, data->set.timeout); - - if(data->set.connecttimeout) - Curl_expire(data, data->set.connecttimeout); - } - - return res; -} - -/* - * Curl_posttransfer() is called immediately after a transfer ends - */ -CURLcode Curl_posttransfer(struct SessionHandle *data) -{ -#if defined(HAVE_SIGNAL) && defined(SIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) - /* restore the signal handler for SIGPIPE before we get back */ - if(!data->set.no_signal) - signal(SIGPIPE, data->state.prev_signal); -#else - (void)data; /* unused parameter */ -#endif - - return CURLE_OK; -} - -#ifndef CURL_DISABLE_HTTP -/* - * strlen_url() returns the length of the given URL if the spaces within the - * URL were properly URL encoded. - */ -static size_t strlen_url(const char *url) -{ - const char *ptr; - size_t newlen=0; - bool left=TRUE; /* left side of the ? */ - - for(ptr=url; *ptr; ptr++) { - switch(*ptr) { - case '?': - left=FALSE; - /* fall through */ - default: - newlen++; - break; - case ' ': - if(left) - newlen+=3; - else - newlen++; - break; - } - } - return newlen; -} - -/* strcpy_url() copies a url to a output buffer and URL-encodes the spaces in - * the source URL accordingly. - */ -static void strcpy_url(char *output, const char *url) -{ - /* we must add this with whitespace-replacing */ - bool left=TRUE; - const char *iptr; - char *optr = output; - for(iptr = url; /* read from here */ - *iptr; /* until zero byte */ - iptr++) { - switch(*iptr) { - case '?': - left=FALSE; - /* fall through */ - default: - *optr++=*iptr; - break; - case ' ': - if(left) { - *optr++='%'; /* add a '%' */ - *optr++='2'; /* add a '2' */ - *optr++='0'; /* add a '0' */ - } - else - *optr++='+'; /* add a '+' here */ - break; - } - } - *optr=0; /* zero terminate output buffer */ - -} - -/* - * Returns true if the given URL is absolute (as opposed to relative) - */ -static bool is_absolute_url(const char *url) -{ - char prot[16]; /* URL protocol string storage */ - char letter; /* used for a silly sscanf */ - - return (bool)(2 == sscanf(url, "%15[^?&/:]://%c", prot, &letter)); -} - -/* - * Concatenate a relative URL to a base URL making it absolute. - * URL-encodes any spaces. - * The returned pointer must be freed by the caller unless NULL - * (returns NULL on out of memory). - */ -static char *concat_url(const char *base, const char *relurl) -{ - /*** - TRY to append this new path to the old URL - to the right of the host part. Oh crap, this is doomed to cause - problems in the future... - */ - char *newest; - char *protsep; - char *pathsep; - size_t newlen; - - const char *useurl = relurl; - size_t urllen; - - /* we must make our own copy of the URL to play with, as it may - point to read-only data */ - char *url_clone=strdup(base); - - if(!url_clone) - return NULL; /* skip out of this NOW */ - - /* protsep points to the start of the host name */ - protsep=strstr(url_clone, "//"); - if(!protsep) - protsep=url_clone; - else - protsep+=2; /* pass the slashes */ - - if('/' != relurl[0]) { - int level=0; - - /* First we need to find out if there's a ?-letter in the URL, - and cut it and the right-side of that off */ - pathsep = strchr(protsep, '?'); - if(pathsep) - *pathsep=0; - - /* we have a relative path to append to the last slash if there's one - available, or if the new URL is just a query string (starts with a - '?') we append the new one at the end of the entire currently worked - out URL */ - if(useurl[0] != '?') { - pathsep = strrchr(protsep, '/'); - if(pathsep) - *pathsep=0; - } - - /* Check if there's any slash after the host name, and if so, remember - that position instead */ - pathsep = strchr(protsep, '/'); - if(pathsep) - protsep = pathsep+1; - else - protsep = NULL; - - /* now deal with one "./" or any amount of "../" in the newurl - and act accordingly */ - - if((useurl[0] == '.') && (useurl[1] == '/')) - useurl+=2; /* just skip the "./" */ - - while((useurl[0] == '.') && - (useurl[1] == '.') && - (useurl[2] == '/')) { - level++; - useurl+=3; /* pass the "../" */ - } - - if(protsep) { - while(level--) { - /* cut off one more level from the right of the original URL */ - pathsep = strrchr(protsep, '/'); - if(pathsep) - *pathsep=0; - else { - *protsep=0; - break; - } - } - } - } - else { - /* We got a new absolute path for this server, cut off from the - first slash */ - pathsep = strchr(protsep, '/'); - if(pathsep) { - /* When people use badly formatted URLs, such as - "http://www.url.com?dir=/home/daniel" we must not use the first - slash, if there's a ?-letter before it! */ - char *sep = strchr(protsep, '?'); - if(sep && (sep < pathsep)) - pathsep = sep; - *pathsep=0; - } - else { - /* There was no slash. Now, since we might be operating on a badly - formatted URL, such as "http://www.url.com?id=2380" which doesn't - use a slash separator as it is supposed to, we need to check for a - ?-letter as well! */ - pathsep = strchr(protsep, '?'); - if(pathsep) - *pathsep=0; - } - } - - /* If the new part contains a space, this is a mighty stupid redirect - but we still make an effort to do "right". To the left of a '?' - letter we replace each space with %20 while it is replaced with '+' - on the right side of the '?' letter. - */ - newlen = strlen_url(useurl); - - urllen = strlen(url_clone); - - newest = malloc( urllen + 1 + /* possible slash */ - newlen + 1 /* zero byte */); - - if(!newest) { - free(url_clone); /* don't leak this */ - return NULL; - } - - /* copy over the root url part */ - memcpy(newest, url_clone, urllen); - - /* check if we need to append a slash */ - if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0])) - ; - else - newest[urllen++]='/'; - - /* then append the new piece on the right side */ - strcpy_url(&newest[urllen], useurl); - - free(url_clone); - - return newest; -} -#endif /* CURL_DISABLE_HTTP */ - -/* - * Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string - * as given by the remote server and set up the new URL to request. - */ -CURLcode Curl_follow(struct SessionHandle *data, - char *newurl, /* this 'newurl' is the Location: string, - and it must be malloc()ed before passed - here */ - followtype type) /* see transfer.h */ -{ -#ifdef CURL_DISABLE_HTTP - (void)data; - (void)newurl; - (void)type; - /* Location: following will not happen when HTTP is disabled */ - return CURLE_TOO_MANY_REDIRECTS; -#else - - /* Location: redirect */ - bool disallowport = FALSE; - - if(type == FOLLOW_REDIR) { - if((data->set.maxredirs != -1) && - (data->set.followlocation >= data->set.maxredirs)) { - failf(data,"Maximum (%ld) redirects followed", data->set.maxredirs); - return CURLE_TOO_MANY_REDIRECTS; - } - - /* mark the next request as a followed location: */ - data->state.this_is_a_follow = TRUE; - - data->set.followlocation++; /* count location-followers */ - - if(data->set.http_auto_referer) { - /* We are asked to automatically set the previous URL as the referer - when we get the next URL. We pick the ->url field, which may or may - not be 100% correct */ - - if(data->change.referer_alloc) - /* If we already have an allocated referer, free this first */ - free(data->change.referer); - - data->change.referer = strdup(data->change.url); - if (!data->change.referer) { - data->change.referer_alloc = FALSE; - return CURLE_OUT_OF_MEMORY; - } - data->change.referer_alloc = TRUE; /* yes, free this later */ - } - } - - if(!is_absolute_url(newurl)) { - /*** - *DANG* this is an RFC 2068 violation. The URL is supposed - to be absolute and this doesn't seem to be that! - */ - char *absolute = concat_url(data->change.url, newurl); - if (!absolute) - return CURLE_OUT_OF_MEMORY; - free(newurl); - newurl = absolute; - } - else { - /* This is an absolute URL, don't allow the custom port number */ - disallowport = TRUE; - - if(strchr(newurl, ' ')) { - /* This new URL contains at least one space, this is a mighty stupid - redirect but we still make an effort to do "right". */ - char *newest; - size_t newlen = strlen_url(newurl); - - newest = malloc(newlen+1); /* get memory for this */ - if (!newest) - return CURLE_OUT_OF_MEMORY; - strcpy_url(newest, newurl); /* create a space-free URL */ - - free(newurl); /* that was no good */ - newurl = newest; /* use this instead now */ - } - - } - - if(type == FOLLOW_FAKE) { - /* we're only figuring out the new url if we would've followed locations - but now we're done so we can get out! */ - data->info.wouldredirect = newurl; - return CURLE_OK; - } - - if(disallowport) - data->state.allow_port = FALSE; - - if(data->change.url_alloc) - free(data->change.url); - else - data->change.url_alloc = TRUE; /* the URL is allocated */ - - data->change.url = newurl; - newurl = NULL; /* don't free! */ - - infof(data, "Issue another request to this URL: '%s'\n", data->change.url); - - /* - * We get here when the HTTP code is 300-399 (and 401). We need to perform - * differently based on exactly what return code there was. - * - * News from 7.10.6: we can also get here on a 401 or 407, in case we act on - * a HTTP (proxy-) authentication scheme other than Basic. - */ - switch(data->info.httpcode) { - /* 401 - Act on a WWW-Authenticate, we keep on moving and do the - Authorization: XXXX header in the HTTP request code snippet */ - /* 407 - Act on a Proxy-Authenticate, we keep on moving and do the - Proxy-Authorization: XXXX header in the HTTP request code snippet */ - /* 300 - Multiple Choices */ - /* 306 - Not used */ - /* 307 - Temporary Redirect */ - default: /* for all above (and the unknown ones) */ - /* Some codes are explicitly mentioned since I've checked RFC2616 and they - * seem to be OK to POST to. - */ - break; - case 301: /* Moved Permanently */ - /* (quote from RFC2616, section 10.3.2): - * - * Note: When automatically redirecting a POST request after receiving a - * 301 status code, some existing HTTP/1.0 user agents will erroneously - * change it into a GET request. - * - * ---- - * - * Warning: Because most of importants user agents do this obvious RFC2616 - * violation, many webservers expect this misbehavior. So these servers - * often answers to a POST request with an error page. To be sure that - * libcurl gets the page that most user agents would get, libcurl has to - * force GET. - * - * This behaviour can be overridden with CURLOPT_POSTREDIR. - */ - if( (data->set.httpreq == HTTPREQ_POST - || data->set.httpreq == HTTPREQ_POST_FORM) - && !data->set.post301) { - infof(data, - "Violate RFC 2616/10.3.2 and switch from POST to GET\n"); - data->set.httpreq = HTTPREQ_GET; - } - break; - case 302: /* Found */ - /* (From 10.3.3) - - Note: RFC 1945 and RFC 2068 specify that the client is not allowed - to change the method on the redirected request. However, most - existing user agent implementations treat 302 as if it were a 303 - response, performing a GET on the Location field-value regardless - of the original request method. The status codes 303 and 307 have - been added for servers that wish to make unambiguously clear which - kind of reaction is expected of the client. - - (From 10.3.4) - - Note: Many pre-HTTP/1.1 user agents do not understand the 303 - status. When interoperability with such clients is a concern, the - 302 status code may be used instead, since most user agents react - to a 302 response as described here for 303. - - This behaviour can be overriden with CURLOPT_POSTREDIR - */ - if( (data->set.httpreq == HTTPREQ_POST - || data->set.httpreq == HTTPREQ_POST_FORM) - && !data->set.post302) { - infof(data, - "Violate RFC 2616/10.3.3 and switch from POST to GET\n"); - data->set.httpreq = HTTPREQ_GET; - } - break; - - case 303: /* See Other */ - /* Disable both types of POSTs, since doing a second POST when - * following isn't what anyone would want! */ - if(data->set.httpreq != HTTPREQ_GET) { - data->set.httpreq = HTTPREQ_GET; /* enforce GET request */ - infof(data, "Disables POST, goes with %s\n", - data->set.opt_no_body?"HEAD":"GET"); - } - break; - case 304: /* Not Modified */ - /* 304 means we did a conditional request and it was "Not modified". - * We shouldn't get any Location: header in this response! - */ - break; - case 305: /* Use Proxy */ - /* (quote from RFC2616, section 10.3.6): - * "The requested resource MUST be accessed through the proxy given - * by the Location field. The Location field gives the URI of the - * proxy. The recipient is expected to repeat this single request - * via the proxy. 305 responses MUST only be generated by origin - * servers." - */ - break; - } - Curl_pgrsTime(data, TIMER_REDIRECT); - Curl_pgrsResetTimes(data); - - return CURLE_OK; -#endif /* CURL_DISABLE_HTTP */ -} - -static CURLcode -connect_host(struct SessionHandle *data, - struct connectdata **conn) -{ - CURLcode res = CURLE_OK; - - bool async; - bool protocol_done=TRUE; /* will be TRUE always since this is only used - within the easy interface */ - Curl_pgrsTime(data, TIMER_STARTSINGLE); - res = Curl_connect(data, conn, &async, &protocol_done); - - if((CURLE_OK == res) && async) { - /* Now, if async is TRUE here, we need to wait for the name - to resolve */ - res = Curl_wait_for_resolv(*conn, NULL); - if(CURLE_OK == res) - /* Resolved, continue with the connection */ - res = Curl_async_resolved(*conn, &protocol_done); - else - /* if we can't resolve, we kill this "connection" now */ - (void)Curl_disconnect(*conn, /* dead_connection */ FALSE); - } - - return res; -} - -CURLcode -Curl_reconnect_request(struct connectdata **connp) -{ - CURLcode result = CURLE_OK; - struct connectdata *conn = *connp; - struct SessionHandle *data = conn->data; - - /* This was a re-use of a connection and we got a write error in the - * DO-phase. Then we DISCONNECT this connection and have another attempt to - * CONNECT and then DO again! The retry cannot possibly find another - * connection to re-use, since we only keep one possible connection for - * each. */ - - infof(data, "Re-used connection seems dead, get a new one\n"); - - conn->bits.close = TRUE; /* enforce close of this connection */ - result = Curl_done(&conn, result, FALSE); /* we are so done with this */ - - /* conn may no longer be a good pointer */ - - /* - * According to bug report #1330310. We need to check for CURLE_SEND_ERROR - * here as well. I figure this could happen when the request failed on a FTP - * connection and thus Curl_done() itself tried to use the connection - * (again). Slight Lack of feedback in the report, but I don't think this - * extra check can do much harm. - */ - if((CURLE_OK == result) || (CURLE_SEND_ERROR == result)) { - bool async; - bool protocol_done = TRUE; - - /* Now, redo the connect and get a new connection */ - result = Curl_connect(data, connp, &async, &protocol_done); - if(CURLE_OK == result) { - /* We have connected or sent away a name resolve query fine */ - - conn = *connp; /* setup conn to again point to something nice */ - if(async) { - /* Now, if async is TRUE here, we need to wait for the name - to resolve */ - result = Curl_wait_for_resolv(conn, NULL); - if(result) - return result; - - /* Resolved, continue with the connection */ - result = Curl_async_resolved(conn, &protocol_done); - if(result) - return result; - } - } - } - - return result; -} - -/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted. - - NOTE: that the *url is malloc()ed. */ -CURLcode Curl_retry_request(struct connectdata *conn, - char **url) -{ - struct SessionHandle *data = conn->data; - - *url = NULL; - - /* if we're talking upload, we can't do the checks below, unless the protocol - is HTTP as when uploading over HTTP we will still get a response */ - if(data->set.upload && - !(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP))) - return CURLE_OK; - - if(/* workaround for broken TLS servers */ data->state.ssl_connect_retry || - ((data->req.bytecount + - data->req.headerbytecount == 0) && - conn->bits.reuse && - !data->set.opt_no_body && - data->set.rtspreq != RTSPREQ_RECEIVE)) { - /* We got no data, we attempted to re-use a connection and yet we want a - "body". This might happen if the connection was left alive when we were - done using it before, but that was closed when we wanted to read from - it again. Bad luck. Retry the same request on a fresh connect! */ - infof(conn->data, "Connection died, retrying a fresh connect\n"); - *url = strdup(conn->data->change.url); - if(!*url) - return CURLE_OUT_OF_MEMORY; - - conn->bits.close = TRUE; /* close this connection */ - conn->bits.retry = TRUE; /* mark this as a connection we're about - to retry. Marking it this way should - prevent i.e HTTP transfers to return - error just because nothing has been - transferred! */ - - if(data->state.proto.http->writebytecount) - Curl_readrewind(conn); - } - return CURLE_OK; -} - -static CURLcode Curl_do_perform(struct SessionHandle *data) -{ - CURLcode res; - CURLcode res2; - struct connectdata *conn=NULL; - char *newurl = NULL; /* possibly a new URL to follow to! */ - followtype follow = FOLLOW_NONE; - - data->state.used_interface = Curl_if_easy; - - res = Curl_pretransfer(data); - if(res) - return res; - - /* - * It is important that there is NO 'return' from this function at any other - * place than falling down to the end of the function! This is because we - * have cleanup stuff that must be done before we get back, and that is only - * performed after this do-while loop. - */ - - for(;;) { - res = connect_host(data, &conn); /* primary connection */ - - if(res == CURLE_OK) { - bool do_done; - if(data->set.connect_only) { - /* keep connection open for application to use the socket */ - conn->bits.close = FALSE; - res = Curl_done(&conn, CURLE_OK, FALSE); - break; - } - res = Curl_do(&conn, &do_done); - - if(res == CURLE_OK) { - if(conn->data->set.wildcardmatch) { - if(conn->data->wildcard.state == CURLWC_DONE || - conn->data->wildcard.state == CURLWC_SKIP) { - /* keep connection open for application to use the socket */ - conn->bits.close = FALSE; - res = Curl_done(&conn, CURLE_OK, FALSE); - break; - } - } - res = Transfer(conn); /* now fetch that URL please */ - if((res == CURLE_OK) || (res == CURLE_RECV_ERROR)) { - bool retry = FALSE; - CURLcode rc = Curl_retry_request(conn, &newurl); - if(rc) - res = rc; - else - retry = (newurl?TRUE:FALSE); - - if(retry) { - /* we know (newurl != NULL) at this point */ - res = CURLE_OK; - follow = FOLLOW_RETRY; - } - else if (res == CURLE_OK) { - /* - * We must duplicate the new URL here as the connection data may - * be free()ed in the Curl_done() function. We prefer the newurl - * one since that's used for redirects or just further requests - * for retries or multi-stage HTTP auth methods etc. - */ - if(data->req.newurl) { - follow = FOLLOW_REDIR; - newurl = strdup(data->req.newurl); - if (!newurl) - res = CURLE_OUT_OF_MEMORY; - } - else if(data->req.location) { - follow = FOLLOW_FAKE; - newurl = strdup(data->req.location); - if (!newurl) - res = CURLE_OUT_OF_MEMORY; - } - } - - /* in the above cases where 'newurl' gets assigned, we have a fresh - * allocated memory pointed to */ - } - if(res != CURLE_OK) { - /* The transfer phase returned error, we mark the connection to get - * closed to prevent being re-used. This is because we can't - * possibly know if the connection is in a good shape or not now. */ - conn->bits.close = TRUE; - - if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) { - /* if we failed anywhere, we must clean up the secondary socket if - it was used */ - sclose(conn->sock[SECONDARYSOCKET]); - conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; - } - } - - /* Always run Curl_done(), even if some of the previous calls - failed, but return the previous (original) error code */ - res2 = Curl_done(&conn, res, FALSE); - - if(CURLE_OK == res) - res = res2; - } - else if(conn) - /* Curl_do() failed, clean up left-overs in the done-call, but note - that at some cases the conn pointer is NULL when Curl_do() failed - and the connection cache is very small so only call Curl_done() if - conn is still "alive". */ - /* ignore return code since we already have an error to return */ - (void)Curl_done(&conn, res, FALSE); - - /* - * Important: 'conn' cannot be used here, since it may have been closed - * in 'Curl_done' or other functions. - */ - - if((res == CURLE_OK) && follow) { - res = Curl_follow(data, newurl, follow); - if(CURLE_OK == res) { - /* if things went fine, Curl_follow() freed or otherwise took - responsibility for the newurl pointer */ - newurl = NULL; - if(follow >= FOLLOW_RETRY) { - follow = FOLLOW_NONE; - continue; - } - /* else we break out of the loop below */ - } - } - } - break; /* it only reaches here when this shouldn't loop */ - - } /* loop if Location: */ - - if(newurl) - free(newurl); - - if(res && !data->state.errorbuf) { - /* - * As an extra precaution: if no error string has been set and there was - * an error, use the strerror() string or if things are so bad that not - * even that is good, set a bad string that mentions the error code. - */ - const char *str = curl_easy_strerror(res); - if(!str) - failf(data, "unspecified error %d", (int)res); - else - failf(data, "%s", str); - } - - /* run post-transfer unconditionally, but don't clobber the return code if - we already have an error code recorder */ - res2 = Curl_posttransfer(data); - if(!res && res2) - res = res2; - - return res; -} - -/* - * Curl_perform() is the internal high-level function that gets called by the - * external curl_easy_perform() function. It inits, performs and cleans up a - * single file transfer. - */ -CURLcode Curl_perform(struct SessionHandle *data) -{ - CURLcode res; - if(!data->set.wildcardmatch) - return Curl_do_perform(data); - - /* init main wildcard structures */ - res = Curl_wildcard_init(&data->wildcard); - if(res) - return res; - - res = Curl_do_perform(data); - if(res) { - Curl_wildcard_dtor(&data->wildcard); - return res; - } - - /* wildcard loop */ - while(!res && data->wildcard.state != CURLWC_DONE) - res = Curl_do_perform(data); - - Curl_wildcard_dtor(&data->wildcard); - - /* wildcard download finished or failed */ - data->wildcard.state = CURLWC_INIT; - return res; -} - -/* - * Curl_setup_transfer() is called to setup some basic properties for the - * upcoming transfer. - */ -void -Curl_setup_transfer( - struct connectdata *conn, /* connection data */ - int sockindex, /* socket index to read from or -1 */ - curl_off_t size, /* -1 if unknown at this point */ - bool getheader, /* TRUE if header parsing is wanted */ - curl_off_t *bytecountp, /* return number of bytes read or NULL */ - int writesockindex, /* socket index to write to, it may very well be - the same we read from. -1 disables */ - curl_off_t *writecountp /* return number of bytes written or NULL */ - ) -{ - struct SessionHandle *data; - struct SingleRequest *k; - - DEBUGASSERT(conn != NULL); - - data = conn->data; - k = &data->req; - - DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); - - /* now copy all input parameters */ - conn->sockfd = sockindex == -1 ? - CURL_SOCKET_BAD : conn->sock[sockindex]; - conn->writesockfd = writesockindex == -1 ? - CURL_SOCKET_BAD:conn->sock[writesockindex]; - k->getheader = getheader; - - k->size = size; - k->bytecountp = bytecountp; - k->writebytecountp = writecountp; - - /* The code sequence below is placed in this function just because all - necessary input is not always known in do_complete() as this function may - be called after that */ - - if(!k->getheader) { - k->header = FALSE; - if(size > 0) - Curl_pgrsSetDownloadSize(data, size); - } - /* we want header and/or body, if neither then don't do this! */ - if(k->getheader || !data->set.opt_no_body) { - - if(conn->sockfd != CURL_SOCKET_BAD) - k->keepon |= KEEP_RECV; - - if(conn->writesockfd != CURL_SOCKET_BAD) { - /* HTTP 1.1 magic: - - Even if we require a 100-return code before uploading data, we might - need to write data before that since the REQUEST may not have been - finished sent off just yet. - - Thus, we must check if the request has been sent before we set the - state info where we wait for the 100-return code - */ - if((data->state.expect100header) && - (data->state.proto.http->sending == HTTPSEND_BODY)) { - /* wait with write until we either got 100-continue or a timeout */ - k->exp100 = EXP100_AWAITING_CONTINUE; - k->start100 = k->start; - - /* set a timeout for the multi interface */ - Curl_expire(data, CURL_TIMEOUT_EXPECT_100); - } - else { - if(data->state.expect100header) - /* when we've sent off the rest of the headers, we must await a - 100-continue but first finish sending the request */ - k->exp100 = EXP100_SENDING_REQUEST; - - /* enable the write bit when we're not waiting for continue */ - k->keepon |= KEEP_SEND; - } - } /* if(conn->writesockfd != CURL_SOCKET_BAD) */ - } /* if(k->getheader || !data->set.opt_no_body) */ - -} diff --git a/third_party/curl/lib/transfer.h b/third_party/curl/lib/transfer.h deleted file mode 100644 index f60937cbf..000000000 --- a/third_party/curl/lib/transfer.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef __TRANSFER_H -#define __TRANSFER_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -CURLcode Curl_perform(struct SessionHandle *data); -CURLcode Curl_pretransfer(struct SessionHandle *data); -CURLcode Curl_second_connect(struct connectdata *conn); -CURLcode Curl_posttransfer(struct SessionHandle *data); - -typedef enum { - FOLLOW_NONE, /* not used within the function, just a placeholder to - allow initing to this */ - FOLLOW_FAKE, /* only records stuff, not actually following */ - FOLLOW_RETRY, /* set if this is a request retry as opposed to a real - redirect following */ - FOLLOW_REDIR, /* a full true redirect */ - FOLLOW_LAST /* never used */ -} followtype; - -CURLcode Curl_follow(struct SessionHandle *data, char *newurl, followtype type); - - -CURLcode Curl_readwrite(struct connectdata *conn, bool *done); -int Curl_single_getsock(const struct connectdata *conn, - curl_socket_t *socks, - int numsocks); -CURLcode Curl_readrewind(struct connectdata *conn); -CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp); -CURLcode Curl_reconnect_request(struct connectdata **connp); -CURLcode Curl_retry_request(struct connectdata *conn, char **url); -bool Curl_meets_timecondition(struct SessionHandle *data, time_t timeofdoc); - -/* This sets up a forthcoming transfer */ -void -Curl_setup_transfer (struct connectdata *data, - int sockindex, /* socket index to read from or -1 */ - curl_off_t size, /* -1 if unknown at this point */ - bool getheader, /* TRUE if header parsing is wanted */ - curl_off_t *bytecountp, /* return number of bytes read */ - int writesockindex, /* socket index to write to, it may - very well be the same we read from. - -1 disables */ - curl_off_t *writecountp /* return number of bytes written */ -); - -long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps, - int pkt_size); - -#endif diff --git a/third_party/curl/lib/url.c b/third_party/curl/lib/url.c deleted file mode 100644 index 3bc8db06d..000000000 --- a/third_party/curl/lib/url.c +++ /dev/null @@ -1,5394 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* -- WIN32 approved -- */ - -#include "setup.h" - -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#include -#else -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif - -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#ifdef __VMS -#include -#include -#endif - -#ifndef HAVE_SOCKET -#error "We can't compile without socket() support!" -#endif - -#endif /* WIN32 */ - -#ifdef HAVE_LIMITS_H -#include -#endif - -#ifdef USE_LIBIDN -#include -#include -#include -#ifdef HAVE_IDN_FREE_H -#include -#else -/* prototype from idn-free.h, not provided by libidn 0.4.5's make install! */ -void idn_free (void *ptr); -#endif -#ifndef HAVE_IDN_FREE -/* if idn_free() was not found in this version of libidn use free() instead */ -#define idn_free(x) (free)(x) -#endif -#elif defined(USE_WIN32_IDN) -/* prototype for curl_win32_idn_to_ascii() */ -int curl_win32_idn_to_ascii(const char *in, char **out); -#endif /* USE_LIBIDN */ - -#include "urldata.h" -#include "netrc.h" - -#include "formdata.h" -#include "sslgen.h" -#include "hostip.h" -#include "transfer.h" -#include "sendf.h" -#include "progress.h" -#include "cookie.h" -#include "strequal.h" -#include "strerror.h" -#include "escape.h" -#include "strtok.h" -#include "share.h" -#include "content_encoding.h" -#include "http_digest.h" -#include "http_negotiate.h" -#include "select.h" -#include "multiif.h" -#include "easyif.h" -#include "speedcheck.h" -#include "rawstr.h" -#include "warnless.h" -#include "non-ascii.h" - -/* And now for the protocols */ -#include "ftp.h" -#include "dict.h" -#include "telnet.h" -#include "tftp.h" -#include "http.h" -#include "file.h" -#include "curl_ldap.h" -#include "ssh.h" -#include "imap.h" -#include "url.h" -#include "connect.h" -#include "inet_ntop.h" -#include "http_ntlm.h" -#include "socks.h" -#include "rtsp.h" -#include "curl_rtmp.h" -#include "gopher.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -/* Local static prototypes */ -static long ConnectionKillOne(struct SessionHandle *data); -static void conn_free(struct connectdata *conn); -static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke); - -/* - * Protocol table. - */ - -static const struct Curl_handler * const protocols[] = { - -#ifndef CURL_DISABLE_HTTP - &Curl_handler_http, -#endif - -#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) - &Curl_handler_https, -#endif - -#ifndef CURL_DISABLE_FTP - &Curl_handler_ftp, -#endif - -#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) - &Curl_handler_ftps, -#endif - -#ifndef CURL_DISABLE_TELNET - &Curl_handler_telnet, -#endif - -#ifndef CURL_DISABLE_DICT - &Curl_handler_dict, -#endif - -#ifndef CURL_DISABLE_LDAP - &Curl_handler_ldap, -#if !defined(CURL_DISABLE_LDAPS) && \ - ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ - (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) - &Curl_handler_ldaps, -#endif -#endif - -#ifndef CURL_DISABLE_FILE - &Curl_handler_file, -#endif - -#ifndef CURL_DISABLE_TFTP - &Curl_handler_tftp, -#endif - -#ifdef USE_LIBSSH2 - &Curl_handler_scp, - &Curl_handler_sftp, -#endif - -#ifndef CURL_DISABLE_IMAP - &Curl_handler_imap, -#ifdef USE_SSL - &Curl_handler_imaps, -#endif -#endif - -#ifndef CURL_DISABLE_POP3 - &Curl_handler_pop3, -#ifdef USE_SSL - &Curl_handler_pop3s, -#endif -#endif - -#ifndef CURL_DISABLE_SMTP - &Curl_handler_smtp, -#ifdef USE_SSL - &Curl_handler_smtps, -#endif -#endif - -#ifndef CURL_DISABLE_RTSP - &Curl_handler_rtsp, -#endif - -#ifndef CURL_DISABLE_GOPHER - &Curl_handler_gopher, -#endif - -#ifdef USE_LIBRTMP - &Curl_handler_rtmp, - &Curl_handler_rtmpt, - &Curl_handler_rtmpe, - &Curl_handler_rtmpte, - &Curl_handler_rtmps, - &Curl_handler_rtmpts, -#endif - - (struct Curl_handler *) NULL -}; - -/* - * Dummy handler for undefined protocol schemes. - */ - -static const struct Curl_handler Curl_handler_dummy = { - "", /* scheme */ - ZERO_NULL, /* setup_connection */ - ZERO_NULL, /* do_it */ - ZERO_NULL, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_getsock */ - ZERO_NULL, /* doing_getsock */ - ZERO_NULL, /* perform_getsock */ - ZERO_NULL, /* disconnect */ - 0, /* defport */ - 0, /* protocol */ - PROTOPT_NONE /* flags */ -}; - -void Curl_safefree(void *ptr) -{ - if(ptr) - free(ptr); -} - -static void close_connections(struct SessionHandle *data) -{ - /* Loop through all open connections and kill them one by one */ - long i; - do { - i = ConnectionKillOne(data); - } while(i != -1L); -} - -void Curl_freeset(struct SessionHandle * data) -{ - /* Free all dynamic strings stored in the data->set substructure. */ - enum dupstring i; - for(i=(enum dupstring)0; i < STRING_LAST; i++) - Curl_safefree(data->set.str[i]); -} - -static CURLcode setstropt(char **charp, char * s) -{ - /* Release the previous storage at `charp' and replace by a dynamic storage - copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */ - - if(*charp) { - free(*charp); - *charp = (char *) NULL; - } - - if(s) { - s = strdup(s); - - if(!s) - return CURLE_OUT_OF_MEMORY; - - *charp = s; - } - - return CURLE_OK; -} - -static CURLcode setstropt_userpwd(char *option, char **user_storage, - char **pwd_storage) -{ - char* separator; - CURLcode result = CURLE_OK; - - if(!option) { - /* we treat a NULL passed in as a hint to clear existing info */ - Curl_safefree(*user_storage); - *user_storage = (char *) NULL; - Curl_safefree(*pwd_storage); - *pwd_storage = (char *) NULL; - return CURLE_OK; - } - - separator = strchr(option, ':'); - if (separator != NULL) { - - /* store username part of option */ - char * p; - size_t username_len = (size_t)(separator-option); - p = malloc(username_len+1); - if(!p) - result = CURLE_OUT_OF_MEMORY; - else { - memcpy(p, option, username_len); - p[username_len] = '\0'; - Curl_safefree(*user_storage); - *user_storage = p; - } - - /* store password part of option */ - if (result == CURLE_OK) { - result = setstropt(pwd_storage, separator+1); - } - } - else { - result = setstropt(user_storage, option); - } - return result; -} - -CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src) -{ - CURLcode r = CURLE_OK; - enum dupstring i; - - /* Copy src->set into dst->set first, then deal with the strings - afterwards */ - dst->set = src->set; - - /* clear all string pointers first */ - memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); - - /* duplicate all strings */ - for(i=(enum dupstring)0; i< STRING_LAST; i++) { - r = setstropt(&dst->set.str[i], src->set.str[i]); - if(r != CURLE_OK) - break; - } - - /* If a failure occurred, freeing has to be performed externally. */ - return r; -} - -/* - * This is the internal function curl_easy_cleanup() calls. This should - * cleanup and free all resources associated with this sessionhandle. - * - * NOTE: if we ever add something that attempts to write to a socket or - * similar here, we must ignore SIGPIPE first. It is currently only done - * when curl_easy_perform() is invoked. - */ - -CURLcode Curl_close(struct SessionHandle *data) -{ - struct Curl_multi *m = data->multi; - -#ifdef DEBUGBUILD - /* only for debugging, scan through all connections and see if there's a - pipe reference still identifying this handle */ - - if(data->state.connc && data->state.connc->type == CONNCACHE_MULTI) { - struct conncache *c = data->state.connc; - long i; - struct curl_llist *pipeline; - struct curl_llist_element *curr; - struct connectdata *connptr; - - for(i=0; i< c->num; i++) { - connptr = c->connects[i]; - if(!connptr) - continue; - - pipeline = connptr->send_pipe; - if(pipeline) { - for (curr = pipeline->head; curr; curr=curr->next) { - if(data == (struct SessionHandle *) curr->ptr) { - fprintf(stderr, - "problem we %p are still in send pipe for %p done %d\n", - data, connptr, (int)connptr->bits.done); - } - } - } - pipeline = connptr->recv_pipe; - if(pipeline) { - for (curr = pipeline->head; curr; curr=curr->next) { - if(data == (struct SessionHandle *) curr->ptr) { - fprintf(stderr, - "problem we %p are still in recv pipe for %p done %d\n", - data, connptr, (int)connptr->bits.done); - } - } - } - pipeline = connptr->done_pipe; - if(pipeline) { - for (curr = pipeline->head; curr; curr=curr->next) { - if(data == (struct SessionHandle *) curr->ptr) { - fprintf(stderr, - "problem we %p are still in done pipe for %p done %d\n", - data, connptr, (int)connptr->bits.done); - } - } - } - pipeline = connptr->pend_pipe; - if(pipeline) { - for (curr = pipeline->head; curr; curr=curr->next) { - if(data == (struct SessionHandle *) curr->ptr) { - fprintf(stderr, - "problem we %p are still in pend pipe for %p done %d\n", - data, connptr, (int)connptr->bits.done); - } - } - } - } - } -#endif - - Curl_expire(data, 0); /* shut off timers */ - - if(m) - /* This handle is still part of a multi handle, take care of this first - and detach this handle from there. */ - curl_multi_remove_handle(data->multi, data); - - /* Destroy the timeout list that is held in the easy handle. It is - /normally/ done by curl_multi_remove_handle() but this is "just in - case" */ - if(data->state.timeoutlist) { - Curl_llist_destroy(data->state.timeoutlist, NULL); - data->state.timeoutlist = NULL; - } - - data->magic = 0; /* force a clear AFTER the possibly enforced removal from - the multi handle, since that function uses the magic - field! */ - - if(data->state.connc) { - - if(data->state.connc->type == CONNCACHE_PRIVATE) { - /* close all connections still alive that are in the private connection - cache, as we no longer have the pointer left to the shared one. */ - close_connections(data); - - /* free the connection cache if allocated privately */ - Curl_rm_connc(data->state.connc); - } - } - - if(data->state.shared_conn) { - /* marked to be used by a pending connection so we can't kill this handle - just yet */ - data->state.closed = TRUE; - return CURLE_OK; - } - - if(data->dns.hostcachetype == HCACHE_PRIVATE) { - Curl_hash_destroy(data->dns.hostcache); - data->dns.hostcachetype = HCACHE_NONE; - data->dns.hostcache = NULL; - } - - if(data->state.rangestringalloc) - free(data->state.range); - - /* Free the pathbuffer */ - Curl_safefree(data->state.pathbuffer); - Curl_safefree(data->state.proto.generic); - - /* Close down all open SSL info and sessions */ - Curl_ssl_close_all(data); - Curl_safefree(data->state.first_host); - Curl_safefree(data->state.scratch); - Curl_ssl_free_certinfo(data); - - if(data->change.referer_alloc) - free(data->change.referer); - - if(data->change.url_alloc) - free(data->change.url); - - Curl_safefree(data->state.headerbuff); - - Curl_flush_cookies(data, 1); - - Curl_digest_cleanup(data); - - Curl_safefree(data->info.contenttype); - Curl_safefree(data->info.wouldredirect); - - /* this destroys the channel and we cannot use it anymore after this */ - ares_destroy(data->state.areschannel); - - Curl_convert_close(data); - - /* No longer a dirty share, if it exists */ - if(data->share) { - Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); - data->share->dirty--; - Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); - } - - Curl_freeset(data); - free(data); - return CURLE_OK; -} - -/* create a connection cache of a private or multi type */ -struct conncache *Curl_mk_connc(int type, - long amount) /* set -1 to use default */ -{ - /* It is subject for debate how many default connections to have for a multi - connection cache... */ - - struct conncache *c; - long default_amount; - long max_amount = (long)(((size_t)INT_MAX) / sizeof(struct connectdata *)); - - if(type == CONNCACHE_PRIVATE) { - default_amount = (amount < 1L) ? 5L : amount; - } - else { - default_amount = (amount < 1L) ? 10L : amount; - } - - if(default_amount > max_amount) - default_amount = max_amount; - - c = calloc(1, sizeof(struct conncache)); - if(!c) - return NULL; - - c->connects = calloc((size_t)default_amount, sizeof(struct connectdata *)); - if(!c->connects) { - free(c); - return NULL; - } - - c->num = default_amount; - - return c; -} - -/* Change number of entries of a connection cache */ -CURLcode Curl_ch_connc(struct SessionHandle *data, - struct conncache *c, - long newamount) -{ - long i; - struct connectdata **newptr; - long max_amount = (long)(((size_t)INT_MAX) / sizeof(struct connectdata *)); - - if(newamount < 1) - newamount = 1; /* we better have at least one entry */ - - if(!c) { - /* we get a NULL pointer passed in as connection cache, which means that - there is no cache created for this SessionHandle just yet, we create a - brand new with the requested size. - */ - data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, newamount); - if(!data->state.connc) - return CURLE_OUT_OF_MEMORY; - return CURLE_OK; - } - - if(newamount < c->num) { - /* Since this number is *decreased* from the existing number, we must - close the possibly open connections that live on the indexes that - are being removed! - - NOTE: for conncache_multi cases we must make sure that we only - close handles not in use. - */ - for(i=newamount; i< c->num; i++) - Curl_disconnect(c->connects[i], /* dead_connection */ FALSE); - - /* If the most recent connection is no longer valid, mark it - invalid. */ - if(data->state.lastconnect <= newamount) - data->state.lastconnect = -1; - } - if(newamount > 0) { - if(newamount > max_amount) - newamount = max_amount; - newptr = realloc(c->connects, sizeof(struct connectdata *) * newamount); - if(!newptr) - /* we closed a few connections in vain, but so what? */ - return CURLE_OUT_OF_MEMORY; - - /* nullify the newly added pointers */ - for(i=c->num; iconnects = newptr; - c->num = newamount; - } - /* we no longer support less than 1 as size for the connection cache, and - I'm not sure it ever worked to set it to zero */ - return CURLE_OK; -} - -/* Free a connection cache. This is called from Curl_close() and - curl_multi_cleanup(). */ -void Curl_rm_connc(struct conncache *c) -{ - if(c->connects) { - long i; - for(i = 0; i < c->num; ++i) - conn_free(c->connects[i]); - - free(c->connects); - } - - free(c); -} - -/* - * Initialize the UserDefined fields within a SessionHandle. - * This may be safely called on a new or existing SessionHandle. - */ -CURLcode Curl_init_userdefined(struct UserDefined *set) -{ - CURLcode res = CURLE_OK; - - set->out = stdout; /* default output to stdout */ - set->in = stdin; /* default input from stdin */ - set->err = stderr; /* default stderr to stderr */ - - /* use fwrite as default function to store output */ - set->fwrite_func = (curl_write_callback)fwrite; - - /* use fread as default function to read input */ - set->fread_func = (curl_read_callback)fread; - set->is_fread_set = 0; - set->is_fwrite_set = 0; - - set->seek_func = ZERO_NULL; - set->seek_client = ZERO_NULL; - - /* conversion callbacks for non-ASCII hosts */ - set->convfromnetwork = ZERO_NULL; - set->convtonetwork = ZERO_NULL; - set->convfromutf8 = ZERO_NULL; - - set->infilesize = -1; /* we don't know any size */ - set->postfieldsize = -1; /* unknown size */ - set->maxredirs = -1; /* allow any amount by default */ - - set->httpreq = HTTPREQ_GET; /* Default HTTP request */ - set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */ - set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */ - set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */ - set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */ - set->ftp_filemethod = FTPFILE_MULTICWD; - - set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ - - /* Set the default size of the SSL session ID cache */ - set->ssl.numsessions = 5; - - set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */ - set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */ - set->httpauth = CURLAUTH_BASIC; /* defaults to basic */ - set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */ - - /* make libcurl quiet by default: */ - set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */ - - /* - * libcurl 7.10 introduced SSL verification *by default*! This needs to be - * switched off unless wanted. - */ - set->ssl.verifypeer = TRUE; - set->ssl.verifyhost = 2; -#ifdef USE_TLS_SRP - set->ssl.authtype = CURL_TLSAUTH_NONE; -#endif - set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth - type */ - set->ssl.sessionid = TRUE; /* session ID caching enabled by default */ - - set->new_file_perms = 0644; /* Default permissions */ - set->new_directory_perms = 0755; /* Default permissions */ - - /* for the *protocols fields we don't use the CURLPROTO_ALL convenience - define since we internally only use the lower 16 bits for the passed - in bitmask to not conflict with the private bits */ - set->allowed_protocols = CURLPROTO_ALL; - set->redir_protocols = - CURLPROTO_ALL & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */ - -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - /* - * disallow unprotected protection negotiation NEC reference implementation - * seem not to follow rfc1961 section 4.3/4.4 - */ - set->socks5_gssapi_nec = FALSE; - /* set default gssapi service name */ - res = setstropt(&set->str[STRING_SOCKS5_GSSAPI_SERVICE], - (char *) CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE); - if (res != CURLE_OK) - return res; -#endif - - /* This is our preferred CA cert bundle/path since install time */ -#if defined(CURL_CA_BUNDLE) - res = setstropt(&set->str[STRING_SSL_CAFILE], (char *) CURL_CA_BUNDLE); -#elif defined(CURL_CA_PATH) - res = setstropt(&set->str[STRING_SSL_CAPATH], (char *) CURL_CA_PATH); -#endif - - set->wildcardmatch = FALSE; - set->chunk_bgn = ZERO_NULL; - set->chunk_end = ZERO_NULL; - - return res; -} - -/** - * Curl_open() - * - * @param curl is a pointer to a sessionhandle pointer that gets set by this - * function. - * @return CURLcode - */ - -CURLcode Curl_open(struct SessionHandle **curl) -{ - CURLcode res = CURLE_OK; - struct SessionHandle *data; -#ifdef USE_ARES - int status; -#endif - - /* Very simple start-up: alloc the struct, init it with zeroes and return */ - data = calloc(1, sizeof(struct SessionHandle)); - if(!data) { - /* this is a very serious error */ - DEBUGF(fprintf(stderr, "Error: calloc of SessionHandle failed\n")); - return CURLE_OUT_OF_MEMORY; - } - - data->magic = CURLEASY_MAGIC_NUMBER; - -#ifdef USE_ARES - if((status = ares_init(&data->state.areschannel)) != ARES_SUCCESS) { - DEBUGF(fprintf(stderr, "Error: ares_init failed\n")); - free(data); - if(status == ARES_ENOMEM) - return CURLE_OUT_OF_MEMORY; - else - return CURLE_FAILED_INIT; - } - /* make sure that all other returns from this function should destroy the - ares channel before returning error! */ -#endif - - /* We do some initial setup here, all those fields that can't be just 0 */ - - data->state.headerbuff = malloc(HEADERSIZE); - if(!data->state.headerbuff) { - DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n")); - res = CURLE_OUT_OF_MEMORY; - } - else { - Curl_easy_initHandleData(data); - res = Curl_init_userdefined(&data->set); - - data->state.headersize=HEADERSIZE; - - Curl_convert_init(data); - - /* most recent connection is not yet defined */ - data->state.lastconnect = -1; - - data->progress.flags |= PGRS_HIDE; - data->state.current_speed = -1; /* init to negative == impossible */ - - data->wildcard.state = CURLWC_INIT; - data->wildcard.filelist = NULL; - data->set.fnmatch = ZERO_NULL; - /* This no longer creates a connection cache here. It is instead made on - the first call to curl_easy_perform() or when the handle is added to a - multi stack. */ - } - - if(res) { - ares_destroy(data->state.areschannel); - if(data->state.headerbuff) - free(data->state.headerbuff); - Curl_freeset(data); - free(data); - data = NULL; - } - else - *curl = data; - - return res; -} - -CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, - va_list param) -{ - char *argptr; - CURLcode result = CURLE_OK; -#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 */ - long use_cache = va_arg(param, long); - data->set.global_dns_cache = (bool)(0 != use_cache); - } - break; - case CURLOPT_SSL_CIPHER_LIST: - /* set a list of cipher we want to use in the SSL connection */ - result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST], - va_arg(param, char *)); - break; - - case CURLOPT_RANDOM_FILE: - /* - * This is the path name to a file that contains random data to seed - * the random SSL stuff with. The file is only used for reading. - */ - result = setstropt(&data->set.str[STRING_SSL_RANDOM_FILE], - va_arg(param, char *)); - break; - case CURLOPT_EGDSOCKET: - /* - * The Entropy Gathering Daemon socket pathname - */ - result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET], - va_arg(param, char *)); - break; - case CURLOPT_MAXCONNECTS: - /* - * Set the absolute number of maximum simultaneous alive connection that - * libcurl is allowed to have. - */ - result = Curl_ch_connc(data, data->state.connc, 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 = (bool)(0 != va_arg(param, long)); - 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 = (bool)(0 != va_arg(param, long)); - 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 = (bool)(0 != va_arg(param, long)); - break; - case CURLOPT_HEADER: - /* - * Set to include the header in the general data output stream. - */ - data->set.include_header = (bool)(0 != va_arg(param, long)); - break; - case CURLOPT_NOPROGRESS: - /* - * Shut off the internal supported progress meter - */ - data->set.hide_progress = (bool)(0 != va_arg(param, long)); - 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 = (bool)(0 != va_arg(param, long)); - break; - case CURLOPT_FAILONERROR: - /* - * Don't output the >=300 error code HTML-page, but instead only - * return error. - */ - data->set.http_fail_on_error = (bool)(0 != va_arg(param, long)); - 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 = (bool)(0 != va_arg(param, long)); - if(data->set.upload) { - /* If this is HTTP, PUT is what's needed to "upload" */ - data->set.httpreq = HTTPREQ_PUT; - data->set.opt_no_body = FALSE; /* this is implied */ - } - else - /* In HTTP, the opposite of upload is GET (unless NOBODY is true as - then this can be changed to HEAD later on) */ - data->set.httpreq = HTTPREQ_GET; - break; - case CURLOPT_FILETIME: - /* - * Try to get the file time of the remote document. The time will - * later (possibly) become available using curl_easy_getinfo(). - */ - data->set.get_filetime = (bool)(0 != va_arg(param, long)); - break; - case CURLOPT_FTP_CREATE_MISSING_DIRS: - /* - * An FTP option that modifies an upload to create missing directories on - * the server. - */ - switch(va_arg(param, long)) { - case 0: - data->set.ftp_create_missing_dirs = 0; - break; - case 1: - data->set.ftp_create_missing_dirs = 1; - break; - case 2: - data->set.ftp_create_missing_dirs = 2; - break; - default: - /* reserve other values for future use */ - result = CURLE_UNKNOWN_OPTION; - break; - } - break; - case CURLOPT_SERVER_RESPONSE_TIMEOUT: - /* - * Option that specifies how quickly an server response must be obtained - * before it is considered failure. For pingpong protocols. - */ - data->set.server_response_timeout = va_arg( param , long ) * 1000; - break; - case CURLOPT_TFTP_BLKSIZE: - /* - * TFTP option that specifies the block size to use for data transmission - */ - data->set.tftp_blksize = va_arg(param, long); - break; - case CURLOPT_DIRLISTONLY: - /* - * An option that changes the command to one that asks for a list - * only, no file info details. - */ - data->set.ftp_list_only = (bool)(0 != va_arg(param, long)); - break; - case CURLOPT_APPEND: - /* - * We want to upload and append to an existing file. - */ - data->set.ftp_append = (bool)(0 != va_arg(param, long)); - 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 = (bool)(0 != va_arg(param, long)); - break; - case CURLOPT_TIMECONDITION: - /* - * Set HTTP time condition. This must be one of the defines in the - * curl/curl.h header file. - */ - data->set.timecondition = (curl_TimeCond)va_arg(param, long); - break; - case CURLOPT_TIMEVALUE: - /* - * This is the value to compare with the remote document with the - * method set with CURLOPT_TIMECONDITION - */ - data->set.timevalue = (time_t)va_arg(param, long); - break; - case CURLOPT_SSLVERSION: - /* - * Set explicit SSL version to try to connect with, as some SSL - * implementations are lame. - */ - data->set.ssl.version = va_arg(param, long); - break; - -#ifndef CURL_DISABLE_HTTP - case CURLOPT_AUTOREFERER: - /* - * Switch on automatic referer that gets set if curl follows locations. - */ - data->set.http_auto_referer = (bool)(0 != va_arg(param, long)); - break; - - case CURLOPT_ACCEPT_ENCODING: - /* - * String to use at the value of Accept-Encoding header. - * - * If the encoding is set to "" we use an Accept-Encoding header that - * encompasses all the encodings we support. - * If the encoding is set to NULL we don't send an Accept-Encoding header - * and ignore an received Content-Encoding header. - * - */ - argptr = va_arg(param, char *); - result = setstropt(&data->set.str[STRING_ENCODING], - (argptr && !*argptr)? - (char *) ALL_CONTENT_ENCODINGS: argptr); - break; - - case CURLOPT_TRANSFER_ENCODING: - data->set.http_transfer_encoding = (bool)(0 != va_arg(param, long)); - break; - - case CURLOPT_FOLLOWLOCATION: - /* - * Follow Location: header hints on a HTTP-server. - */ - data->set.http_follow_location = (bool)(0 != va_arg(param, long)); - break; - - case CURLOPT_UNRESTRICTED_AUTH: - /* - * Send authentication (user+password) when following locations, even when - * hostname changed. - */ - data->set.http_disable_hostname_check_before_authentication = - (bool)(0 != va_arg(param, long)); - 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_ALL - POST is kept as POST after 301 and 302 - * other - POST is kept as POST after 301 and 302 - */ - long postRedir = va_arg(param, long); - data->set.post301 = (bool)((postRedir & CURL_REDIR_POST_301)?TRUE:FALSE); - data->set.post302 = (bool)((postRedir & CURL_REDIR_POST_302)?TRUE:FALSE); - } - break; - - case CURLOPT_POST: - /* Does this option serve a purpose anymore? Yes it does, when - CURLOPT_POSTFIELDS isn't used and the POST data is read off the - callback! */ - if(va_arg(param, long)) { - data->set.httpreq = HTTPREQ_POST; - data->set.opt_no_body = FALSE; /* this is implied */ - } - else - data->set.httpreq = HTTPREQ_GET; - break; - - case CURLOPT_COPYPOSTFIELDS: - /* - * A string with POST data. Makes curl HTTP POST. Even if it is NULL. - * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to - * CURLOPT_COPYPOSTFIELDS and not altered later. - */ - argptr = va_arg(param, char *); - - if(!argptr || data->set.postfieldsize == -1) - result = setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr); - else { - /* - * Check that requested length does not overflow the size_t type. - */ - - if((data->set.postfieldsize < 0) || - ((sizeof(curl_off_t) != sizeof(size_t)) && - (data->set.postfieldsize > (curl_off_t)((size_t)-1)))) - result = CURLE_OUT_OF_MEMORY; - else { - char * p; - - (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); - - /* Allocate even when size == 0. This satisfies the need of possible - later address compare to detect the COPYPOSTFIELDS mode, and - to mark that postfields is used rather than read function or - form data. - */ - p = malloc((size_t)(data->set.postfieldsize? - data->set.postfieldsize:1)); - - if(!p) - result = CURLE_OUT_OF_MEMORY; - else { - if(data->set.postfieldsize) - memcpy(p, argptr, (size_t)data->set.postfieldsize); - - data->set.str[STRING_COPYPOSTFIELDS] = p; - } - } - } - - data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS]; - data->set.httpreq = HTTPREQ_POST; - break; - - case CURLOPT_POSTFIELDS: - /* - * Like above, but use static data instead of copying it. - */ - data->set.postfields = va_arg(param, void *); - /* Release old copied data. */ - (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); - data->set.httpreq = HTTPREQ_POST; - break; - - case CURLOPT_POSTFIELDSIZE: - /* - * The size of the POSTFIELD data to prevent libcurl to do strlen() to - * figure it out. Enables binary posts. - */ - bigsize = va_arg(param, long); - - if(data->set.postfieldsize < bigsize && - data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { - /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ - (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); - data->set.postfields = NULL; - } - - data->set.postfieldsize = bigsize; - break; - - case CURLOPT_POSTFIELDSIZE_LARGE: - /* - * The size of the POSTFIELD data to prevent libcurl to do strlen() to - * figure it out. Enables binary posts. - */ - bigsize = va_arg(param, curl_off_t); - - if(data->set.postfieldsize < bigsize && - data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { - /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ - (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); - data->set.postfields = NULL; - } - - data->set.postfieldsize = bigsize; - break; - - case CURLOPT_HTTPPOST: - /* - * Set to make us do HTTP POST - */ - data->set.httppost = va_arg(param, struct curl_httppost *); - data->set.httpreq = HTTPREQ_POST_FORM; - data->set.opt_no_body = FALSE; /* this is implied */ - break; - - case CURLOPT_REFERER: - /* - * String to set in the HTTP Referer: field. - */ - if(data->change.referer_alloc) { - free(data->change.referer); - data->change.referer_alloc = FALSE; - } - result = setstropt(&data->set.str[STRING_SET_REFERER], - va_arg(param, char *)); - data->change.referer = data->set.str[STRING_SET_REFERER]; - break; - - case CURLOPT_USERAGENT: - /* - * String to use in the HTTP User-Agent field - */ - result = setstropt(&data->set.str[STRING_USERAGENT], - va_arg(param, char *)); - break; - - case CURLOPT_HTTPHEADER: - /* - * Set a list with HTTP headers to use (or replace internals with) - */ - data->set.headers = va_arg(param, struct curl_slist *); - break; - - case CURLOPT_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) - return CURLE_OUT_OF_MEMORY; - - data->change.cookielist = cl; /* store the list for later use */ - } - break; - - case CURLOPT_COOKIEJAR: - /* - * Set cookie file name to dump all cookies to when we're done. - */ - result = setstropt(&data->set.str[STRING_COOKIEJAR], - va_arg(param, char *)); - - /* - * Activate the cookie parser. This may or may not already - * have been made. - */ - data->cookies = Curl_cookie_init(data, NULL, data->cookies, - data->set.cookiesession); - break; - - case CURLOPT_COOKIESESSION: - /* - * Set this option to TRUE to start a new "cookie session". It will - * prevent the forthcoming read-cookies-from-file actions to accept - * cookies that are marked as being session cookies, as they belong to a - * previous session. - * - * In the original Netscape cookie spec, "session cookies" are cookies - * with no expire date set. RFC2109 describes the same action if no - * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds - * a 'Discard' action that can enforce the discard even for cookies that - * have a Max-Age. - * - * We run mostly with the original cookie spec, as hardly anyone implements - * anything else. - */ - data->set.cookiesession = (bool)(0 != va_arg(param, long)); - break; - - case CURLOPT_COOKIELIST: - argptr = va_arg(param, char *); - - if(argptr == NULL) - break; - - if(Curl_raw_equal(argptr, "ALL")) { - /* clear all cookies */ - Curl_cookie_clearall(data->cookies); - break; - } - else if(Curl_raw_equal(argptr, "SESS")) { - /* clear session cookies */ - Curl_cookie_clearsess(data->cookies); - break; - } - else if(Curl_raw_equal(argptr, "FLUSH")) { - /* flush cookies to file */ - Curl_flush_cookies(data, 0); - break; - } - - if(!data->cookies) - /* if cookie engine was not running, activate it */ - data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE); - - argptr = strdup(argptr); - if(!argptr) { - result = CURLE_OUT_OF_MEMORY; - break; - } - - 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); - - 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. - */ - data->set.httpversion = va_arg(param, long); - break; - - case CURLOPT_HTTPAUTH: - /* - * Set HTTP Authentication type BITMASK. - */ - { - long auth = va_arg(param, long); - - /* 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 = (bool)((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 without SSL */ -#endif -#ifndef USE_HTTP_NEGOTIATE - auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI or WINDOWS_SSPI */ -#endif - if(!auth) - return CURLE_NOT_BUILT_IN; /* no supported types left! */ - - data->set.httpauth = auth; - } - break; - -#endif /* CURL_DISABLE_HTTP */ - - case CURLOPT_CUSTOMREQUEST: - /* - * Set a custom string to use as request - */ - result = setstropt(&data->set.str[STRING_CUSTOMREQUEST], - va_arg(param, char *)); - - /* we don't set - data->set.httpreq = HTTPREQ_CUSTOM; - here, we continue as if we were using the already set type - and this just changes the actual request keyword */ - break; - -#ifndef CURL_DISABLE_PROXY - case CURLOPT_HTTPPROXYTUNNEL: - /* - * Tunnel operations through the proxy instead of normal proxy use - */ - data->set.tunnel_thru_httpproxy = (bool)(0 != va_arg(param, long)); - 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. - */ - { - long auth = va_arg(param, long); - - /* 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 = (bool)((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 without SSL */ -#endif -#ifndef USE_HTTP_NEGOTIATE - auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI or WINDOWS_SSPI */ -#endif - if(!auth) - return CURLE_NOT_BUILT_IN; /* no supported types left! */ - - data->set.proxyauth = auth; - } - break; - - case CURLOPT_PROXY: - /* - * Set proxy server:port to use as HTTP proxy. - * - * If the proxy is set to "" we explicitly say that we don't want to use a - * proxy (even though there might be environment variables saying so). - * - * Setting it to NULL, means no proxy but allows the environment variables - * to decide for us. - */ - result = setstropt(&data->set.str[STRING_PROXY], - va_arg(param, char *)); - break; - - case CURLOPT_PROXYTYPE: - /* - * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME - */ - data->set.proxytype = (curl_proxytype)va_arg(param, long); - break; - - case CURLOPT_PROXY_TRANSFER_MODE: - /* - * set transfer mode (;type=) when doing FTP via an HTTP proxy - */ - switch (va_arg(param, long)) { - case 0: - data->set.proxy_transfer_mode = FALSE; - break; - case 1: - data->set.proxy_transfer_mode = TRUE; - break; - default: - /* reserve other values for future use */ - result = CURLE_UNKNOWN_OPTION; - break; - } - break; -#endif /* CURL_DISABLE_PROXY */ - -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - case CURLOPT_SOCKS5_GSSAPI_SERVICE: - /* - * Set gssapi service name - */ - result = setstropt(&data->set.str[STRING_SOCKS5_GSSAPI_SERVICE], - va_arg(param, char *)); - break; - - case CURLOPT_SOCKS5_GSSAPI_NEC: - /* - * set flag for nec socks5 support - */ - data->set.socks5_gssapi_nec = (bool)(0 != va_arg(param, long)); - break; -#endif - - case CURLOPT_WRITEHEADER: - /* - * 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_FILE: - /* - * FILE pointer to write to or include in the data write callback - */ - data->set.out = va_arg(param, FILE *); - 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 = (bool)(NULL != data->set.str[STRING_FTPPORT]); - break; - - case CURLOPT_FTP_USE_EPRT: - data->set.ftp_use_eprt = (bool)(0 != va_arg(param, long)); - break; - - case CURLOPT_FTP_USE_EPSV: - data->set.ftp_use_epsv = (bool)(0 != va_arg(param, long)); - break; - - case CURLOPT_FTP_USE_PRET: - data->set.ftp_use_pret = (bool)(0 != va_arg(param, long)); - 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 = (bool)(0 != va_arg(param, long)); - break; - - case CURLOPT_INFILE: - /* - * FILE pointer to read the file to be uploaded from. Or possibly - * used as argument to the read callback. - */ - data->set.in = va_arg(param, FILE *); - break; - case CURLOPT_INFILESIZE: - /* - * If known, this should inform curl about the file size of the - * to-be-uploaded file. - */ - data->set.infilesize = 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.infilesize = 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! */ - free(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_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_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_PROGRESSDATA: - /* - * Custom client data to pass to the progress callback - */ - data->set.progress_client = va_arg(param, void *); - break; - -#ifndef CURL_DISABLE_PROXY - case CURLOPT_PROXYUSERPWD: - /* - * user:password needed to use the proxy - */ - result = setstropt_userpwd(va_arg(param, char *), - &data->set.str[STRING_PROXYUSERNAME], - &data->set.str[STRING_PROXYPASSWORD]); - break; - case CURLOPT_PROXYUSERNAME: - /* - * authentication user name to use in the operation - */ - result = setstropt(&data->set.str[STRING_PROXYUSERNAME], - va_arg(param, char *)); - break; - case CURLOPT_PROXYPASSWORD: - /* - * authentication password to use in the operation - */ - result = setstropt(&data->set.str[STRING_PROXYPASSWORD], - va_arg(param, char *)); - break; - case CURLOPT_NOPROXY: - /* - * proxy exception list - */ - result = setstropt(&data->set.str[STRING_NOPROXY], - va_arg(param, char *)); - break; -#endif - - case CURLOPT_RANGE: - /* - * What range of the file you want to transfer - */ - result = setstropt(&data->set.str[STRING_SET_RANGE], - va_arg(param, char *)); - break; - case CURLOPT_RESUME_FROM: - /* - * Resume transfer at the give file position - */ - data->set.set_resume_from = va_arg(param, long); - break; - case CURLOPT_RESUME_FROM_LARGE: - /* - * Resume transfer at the give file position - */ - data->set.set_resume_from = va_arg(param, curl_off_t); - break; - case CURLOPT_DEBUGFUNCTION: - /* - * stderr write callback. - */ - data->set.fdebug = va_arg(param, curl_debug_callback); - /* - * if the callback provided is NULL, it'll use the default callback - */ - break; - case CURLOPT_DEBUGDATA: - /* - * Set to a void * that should receive all error writes. This - * defaults to CURLOPT_STDERR for normal operations. - */ - data->set.debugdata = va_arg(param, void *); - break; - case CURLOPT_STDERR: - /* - * Set to a FILE * that should receive all error writes. This - * defaults to stderr for normal operations. - */ - data->set.err = va_arg(param, FILE *); - if(!data->set.err) - data->set.err = stderr; - break; - case CURLOPT_HEADERFUNCTION: - /* - * Set header write callback - */ - data->set.fwrite_header = va_arg(param, curl_write_callback); - break; - case CURLOPT_WRITEFUNCTION: - /* - * Set data write callback - */ - data->set.fwrite_func = va_arg(param, curl_write_callback); - if(!data->set.fwrite_func) { - data->set.is_fwrite_set = 0; - /* When set to NULL, reset to our internal default function */ - data->set.fwrite_func = (curl_write_callback)fwrite; - } - else - data->set.is_fwrite_set = 1; - break; - case CURLOPT_READFUNCTION: - /* - * Read data callback - */ - data->set.fread_func = va_arg(param, curl_read_callback); - if(!data->set.fread_func) { - data->set.is_fread_set = 0; - /* When set to NULL, reset to our internal default function */ - data->set.fread_func = (curl_read_callback)fread; - } - else - data->set.is_fread_set = 1; - break; - case CURLOPT_SEEKFUNCTION: - /* - * Seek callback. Might be NULL. - */ - data->set.seek_func = va_arg(param, curl_seek_callback); - break; - case CURLOPT_SEEKDATA: - /* - * Seek control callback. Might be NULL. - */ - data->set.seek_client = va_arg(param, void *); - break; - case CURLOPT_CONV_FROM_NETWORK_FUNCTION: - /* - * "Convert from network encoding" callback - */ - data->set.convfromnetwork = va_arg(param, curl_conv_callback); - break; - case CURLOPT_CONV_TO_NETWORK_FUNCTION: - /* - * "Convert to network encoding" callback - */ - data->set.convtonetwork = va_arg(param, curl_conv_callback); - break; - case CURLOPT_CONV_FROM_UTF8_FUNCTION: - /* - * "Convert from UTF-8 encoding" callback - */ - data->set.convfromutf8 = va_arg(param, curl_conv_callback); - break; - case CURLOPT_IOCTLFUNCTION: - /* - * I/O control callback. Might be NULL. - */ - data->set.ioctl_func = va_arg(param, curl_ioctl_callback); - break; - case CURLOPT_IOCTLDATA: - /* - * I/O control data pointer. Might be NULL. - */ - data->set.ioctl_client = va_arg(param, void *); - break; - case CURLOPT_SSLCERT: - /* - * String that holds file name of the SSL certificate to use - */ - result = setstropt(&data->set.str[STRING_CERT], - va_arg(param, char *)); - break; - case CURLOPT_SSLCERTTYPE: - /* - * String that holds file type of the SSL certificate to use - */ - result = setstropt(&data->set.str[STRING_CERT_TYPE], - va_arg(param, char *)); - break; - case CURLOPT_SSLKEY: - /* - * String that holds file name of the SSL key to use - */ - result = setstropt(&data->set.str[STRING_KEY], - va_arg(param, char *)); - break; - case CURLOPT_SSLKEYTYPE: - /* - * String that holds file type of the SSL key to use - */ - result = setstropt(&data->set.str[STRING_KEY_TYPE], - va_arg(param, char *)); - break; - case CURLOPT_KEYPASSWD: - /* - * String that holds the SSL or SSH private key password. - */ - result = setstropt(&data->set.str[STRING_KEY_PASSWD], - va_arg(param, char *)); - break; - case CURLOPT_SSLENGINE: - /* - * String that holds the SSL crypto engine. - */ - argptr = va_arg(param, char *); - if(argptr && argptr[0]) - result = Curl_ssl_set_engine(data, argptr); - break; - - case CURLOPT_SSLENGINE_DEFAULT: - /* - * flag to set engine as default. - */ - result = Curl_ssl_set_engine_default(data); - break; - case CURLOPT_CRLF: - /* - * Kludgy option to enable CRLF conversions. Subject for removal. - */ - data->set.crlf = (bool)(0 != va_arg(param, long)); - break; - - case CURLOPT_INTERFACE: - /* - * Set what interface or address/hostname to bind the socket to when - * performing an operation and thus what from-IP your connection will use. - */ - result = setstropt(&data->set.str[STRING_DEVICE], - va_arg(param, char *)); - break; - case CURLOPT_LOCALPORT: - /* - * Set what local port to bind the socket to when performing an operation. - */ - data->set.localport = curlx_sltous(va_arg(param, long)); - break; - case CURLOPT_LOCALPORTRANGE: - /* - * Set number of local ports to try, starting with CURLOPT_LOCALPORT. - */ - data->set.localportrange = curlx_sltosi(va_arg(param, long)); - break; - case CURLOPT_KRBLEVEL: - /* - * A string that defines the kerberos security level. - */ - result = setstropt(&data->set.str[STRING_KRB_LEVEL], - va_arg(param, char *)); - data->set.krb = (bool)(NULL != data->set.str[STRING_KRB_LEVEL]); - break; - case CURLOPT_SSL_VERIFYPEER: - /* - * Enable peer SSL verifying. - */ - data->set.ssl.verifypeer = va_arg(param, long); - break; - case CURLOPT_SSL_VERIFYHOST: - /* - * Enable verification of the CN contained in the peer certificate - */ - data->set.ssl.verifyhost = va_arg(param, long); - break; -#ifdef USE_SSLEAY - /* since these two options are only possible to use on an OpenSSL- - powered libcurl we #ifdef them on this condition so that libcurls - built against other SSL libs will return a proper error when trying - to set this option! */ - case CURLOPT_SSL_CTX_FUNCTION: - /* - * Set a SSL_CTX callback - */ - data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback); - break; - case CURLOPT_SSL_CTX_DATA: - /* - * Set a SSL_CTX callback parameter pointer - */ - data->set.ssl.fsslctxp = va_arg(param, void *); - break; - case CURLOPT_CERTINFO: - data->set.ssl.certinfo = (bool)(0 != va_arg(param, long)); - break; -#endif - case CURLOPT_CAINFO: - /* - * Set CA info for SSL connection. Specify file name of the CA certificate - */ - result = setstropt(&data->set.str[STRING_SSL_CAFILE], - va_arg(param, char *)); - break; - case CURLOPT_CAPATH: - /* - * Set CA path info for SSL connection. Specify directory name of the CA - * certificates which have been prepared using openssl c_rehash utility. - */ - /* This does not work on windows. */ - result = setstropt(&data->set.str[STRING_SSL_CAPATH], - va_arg(param, char *)); - break; - case CURLOPT_CRLFILE: - /* - * Set CRL file info for SSL connection. Specify file name of the CRL - * to check certificates revocation - */ - result = setstropt(&data->set.str[STRING_SSL_CRLFILE], - va_arg(param, char *)); - break; - case CURLOPT_ISSUERCERT: - /* - * Set Issuer certificate file - * to check certificates issuer - */ - result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT], - va_arg(param, char *)); - break; - case CURLOPT_TELNETOPTIONS: - /* - * Set a linked list of telnet options - */ - data->set.telnet_options = va_arg(param, struct curl_slist *); - break; - - case CURLOPT_BUFFERSIZE: - /* - * The application kindly asks for a differently sized receive buffer. - * If it seems reasonable, we'll use it. - */ - data->set.buffer_size = va_arg(param, long); - - if((data->set.buffer_size> (BUFSIZE -1 )) || - (data->set.buffer_size < 1)) - data->set.buffer_size = 0; /* huge internal default */ - - break; - - case CURLOPT_NOSIGNAL: - /* - * The application asks not to set any signal() or alarm() handlers, - * even when using a timeout. - */ - data->set.no_signal = (bool)(0 != va_arg(param, long)); - 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(data->share->cookies == data->cookies) - data->cookies = NULL; - - data->share->dirty--; - - Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); - data->share = NULL; - } - - /* use new share if it set */ - data->share = set; - if(data->share) { - - Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); - - data->share->dirty++; - - if(data->share->hostcache) { - /* use shared host cache, first free the private one if any */ - if(data->dns.hostcachetype == HCACHE_PRIVATE) - Curl_hash_destroy(data->dns.hostcache); - - data->dns.hostcache = data->share->hostcache; - data->dns.hostcachetype = HCACHE_SHARED; - } -#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) - if(data->share->cookies) { - /* use shared cookie list, first free own one if any */ - if(data->cookies) - Curl_cookie_cleanup(data->cookies); - /* enable cookies since we now use a share that uses cookies! */ - data->cookies = data->share->cookies; - } -#endif /* CURL_DISABLE_HTTP */ - 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.ftp_ssl = (curl_usessl)va_arg(param, long); - 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 = (bool)(0 != va_arg(param, long)); - 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 = (bool)(0 != va_arg(param, long)); - break; - - case CURLOPT_CONNECT_ONLY: - /* - * No data transfer, set up connection and let application use the socket - */ - data->set.connect_only = (bool)(0 != va_arg(param, long)); - 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_SSL_SESSIONID_CACHE: - data->set.ssl.sessionid = (bool)(0 != va_arg(param, long)); - 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 = (bool)(0 == va_arg(param, long)); - break; - - case CURLOPT_HTTP_CONTENT_DECODING: - /* - * raw data passed to the application when content encoding is used - */ - data->set.http_ce_skip = (bool)(0 == va_arg(param, long)); - break; - - case CURLOPT_NEW_FILE_PERMS: - /* - * Uses these permissions instead of 0644 - */ - data->set.new_file_perms = va_arg(param, long); - break; - - case CURLOPT_NEW_DIRECTORY_PERMS: - /* - * Uses these permissions instead of 0755 - */ - data->set.new_directory_perms = va_arg(param, long); - break; - - case CURLOPT_ADDRESS_SCOPE: - /* - * We always get longs when passed plain numericals, but for this value we - * know that an unsigned int will always hold the value so we blindly - * typecast to this type - */ - data->set.scope = curlx_sltoui(va_arg(param, long)); - break; - - case CURLOPT_PROTOCOLS: - /* set the bitmask for the protocols that are allowed to be used for the - transfer, which thus helps the app which takes URLs from users or other - external inputs and want to restrict what protocol(s) to deal - with. Defaults to CURLPROTO_ALL. */ - data->set.allowed_protocols = va_arg(param, long); - break; - - case CURLOPT_REDIR_PROTOCOLS: - /* set the bitmask for the protocols that libcurl is allowed to follow to, - as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs - to be set in both bitmasks to be allowed to get redirected to. Defaults - to all protocols except FILE and SCP. */ - data->set.redir_protocols = va_arg(param, long); - break; - - case CURLOPT_MAIL_FROM: - result = setstropt(&data->set.str[STRING_MAIL_FROM], - va_arg(param, char *)); - break; - - case CURLOPT_MAIL_RCPT: - /* get a list of mail recipients */ - data->set.mail_rcpt = va_arg(param, struct curl_slist *); - break; - - case CURLOPT_RTSP_REQUEST: - { - /* - * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...) - * Would this be better if the RTSPREQ_* were just moved into here? - */ - long curl_rtspreq = va_arg(param, long); - Curl_RtspReq rtspreq = RTSPREQ_NONE; - switch(curl_rtspreq) { - case CURL_RTSPREQ_OPTIONS: - rtspreq = RTSPREQ_OPTIONS; - break; - - case CURL_RTSPREQ_DESCRIBE: - rtspreq = RTSPREQ_DESCRIBE; - break; - - case CURL_RTSPREQ_ANNOUNCE: - rtspreq = RTSPREQ_ANNOUNCE; - break; - - case CURL_RTSPREQ_SETUP: - rtspreq = RTSPREQ_SETUP; - break; - - case CURL_RTSPREQ_PLAY: - rtspreq = RTSPREQ_PLAY; - break; - - case CURL_RTSPREQ_PAUSE: - rtspreq = RTSPREQ_PAUSE; - break; - - case CURL_RTSPREQ_TEARDOWN: - rtspreq = RTSPREQ_TEARDOWN; - break; - - case CURL_RTSPREQ_GET_PARAMETER: - rtspreq = RTSPREQ_GET_PARAMETER; - break; - - case CURL_RTSPREQ_SET_PARAMETER: - rtspreq = RTSPREQ_SET_PARAMETER; - break; - - case CURL_RTSPREQ_RECORD: - rtspreq = RTSPREQ_RECORD; - break; - - case CURL_RTSPREQ_RECEIVE: - rtspreq = RTSPREQ_RECEIVE; - break; - default: - rtspreq = RTSPREQ_NONE; - } - - data->set.rtspreq = rtspreq; - break; - } - - - case CURLOPT_RTSP_SESSION_ID: - /* - * Set the RTSP Session ID manually. Useful if the application is - * resuming a previously established RTSP session - */ - result = setstropt(&data->set.str[STRING_RTSP_SESSION_ID], - va_arg(param, char *)); - break; - - case CURLOPT_RTSP_STREAM_URI: - /* - * Set the Stream URI for the RTSP request. Unless the request is - * for generic server options, the application will need to set this. - */ - result = setstropt(&data->set.str[STRING_RTSP_STREAM_URI], - va_arg(param, char *)); - break; - - case CURLOPT_RTSP_TRANSPORT: - /* - * The content of the Transport: header for the RTSP request - */ - result = setstropt(&data->set.str[STRING_RTSP_TRANSPORT], - va_arg(param, char *)); - break; - - case CURLOPT_RTSP_CLIENT_CSEQ: - /* - * Set the CSEQ number to issue for the next RTSP request. Useful if the - * application is resuming a previously broken connection. The CSEQ - * will increment from this new number henceforth. - */ - data->state.rtsp_next_client_CSeq = va_arg(param, long); - break; - - case CURLOPT_RTSP_SERVER_CSEQ: - /* Same as the above, but for server-initiated requests */ - data->state.rtsp_next_client_CSeq = va_arg(param, long); - break; - - case CURLOPT_INTERLEAVEDATA: - data->set.rtp_out = va_arg(param, void *); - break; - case CURLOPT_INTERLEAVEFUNCTION: - /* Set the user defined RTP write function */ - data->set.fwrite_rtp = va_arg(param, curl_write_callback); - break; - - case CURLOPT_WILDCARDMATCH: - data->set.wildcardmatch = (bool)(0 != va_arg(param, long)); - break; - case CURLOPT_CHUNK_BGN_FUNCTION: - data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback); - break; - case CURLOPT_CHUNK_END_FUNCTION: - data->set.chunk_end = va_arg(param, curl_chunk_end_callback); - break; - case CURLOPT_FNMATCH_FUNCTION: - data->set.fnmatch = va_arg(param, curl_fnmatch_callback); - break; - case CURLOPT_CHUNK_DATA: - data->wildcard.customptr = va_arg(param, void *); - break; - case CURLOPT_FNMATCH_DATA: - data->set.fnmatch_data = va_arg(param, void *); - break; -#ifdef USE_TLS_SRP - case CURLOPT_TLSAUTH_USERNAME: - result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME], - va_arg(param, char *)); - if (data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) - data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ - break; - case CURLOPT_TLSAUTH_PASSWORD: - result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD], - va_arg(param, char *)); - if (data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) - data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ - break; - case CURLOPT_TLSAUTH_TYPE: - if (strncmp((char *)va_arg(param, char *), "SRP", strlen("SRP")) == 0) - data->set.ssl.authtype = CURL_TLSAUTH_SRP; - else - data->set.ssl.authtype = CURL_TLSAUTH_NONE; - break; -#endif - default: - /* unknown tag and its companion, just ignore: */ - result = CURLE_UNKNOWN_OPTION; - break; - } - - return result; -} - -static void conn_free(struct connectdata *conn) -{ - if(!conn) - return; - - /* close the SSL stuff before we close any sockets since they will/may - write to the sockets */ - Curl_ssl_close(conn, FIRSTSOCKET); - Curl_ssl_close(conn, SECONDARYSOCKET); - - /* close possibly still open sockets */ - if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) - sclose(conn->sock[SECONDARYSOCKET]); - if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET]) - sclose(conn->sock[FIRSTSOCKET]); - - Curl_safefree(conn->user); - Curl_safefree(conn->passwd); - Curl_safefree(conn->proxyuser); - Curl_safefree(conn->proxypasswd); - Curl_safefree(conn->allocptr.proxyuserpwd); - Curl_safefree(conn->allocptr.uagent); - Curl_safefree(conn->allocptr.userpwd); - Curl_safefree(conn->allocptr.accept_encoding); - Curl_safefree(conn->allocptr.te); - Curl_safefree(conn->allocptr.rangeline); - Curl_safefree(conn->allocptr.ref); - Curl_safefree(conn->allocptr.host); - Curl_safefree(conn->allocptr.cookiehost); - Curl_safefree(conn->allocptr.rtsp_transport); - Curl_safefree(conn->trailer); - Curl_safefree(conn->host.rawalloc); /* host name buffer */ - Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */ - Curl_safefree(conn->master_buffer); - - Curl_llist_destroy(conn->send_pipe, NULL); - Curl_llist_destroy(conn->recv_pipe, NULL); - Curl_llist_destroy(conn->pend_pipe, NULL); - Curl_llist_destroy(conn->done_pipe, NULL); - - /* possible left-overs from the async name resolvers */ -#if defined(CURLRES_THREADED) - Curl_destroy_thread_data(&conn->async); -#elif defined(CURLRES_ASYNCH) - Curl_safefree(conn->async.hostname); - Curl_safefree(conn->async.os_specific); -#endif - Curl_safefree(conn->localdev); - Curl_free_ssl_config(&conn->ssl_config); - - free(conn); /* free all the connection oriented data */ -} - -CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection) -{ - struct SessionHandle *data; - if(!conn) - return CURLE_OK; /* this is closed and fine already */ - data = conn->data; - - if(!data) { - DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n")); - return CURLE_OK; - } - - if(conn->dns_entry != NULL) { - Curl_resolv_unlock(data, conn->dns_entry); - conn->dns_entry = NULL; - } - -#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST) - /* scan for DNS cache entries still marked as in use */ - Curl_hash_apply(data->hostcache, - NULL, Curl_scan_cache_used); -#endif - - Curl_hostcache_prune(data); /* kill old DNS cache entries */ - - { - int has_host_ntlm = (conn->ntlm.state != NTLMSTATE_NONE); - int has_proxy_ntlm = (conn->proxyntlm.state != NTLMSTATE_NONE); - - /* Authentication data is a mix of connection-related and sessionhandle- - related stuff. NTLM is connection-related so when we close the shop - we shall forget. */ - - if (has_host_ntlm) { - data->state.authhost.done = FALSE; - data->state.authhost.picked = - data->state.authhost.want; - } - - if (has_proxy_ntlm) { - data->state.authproxy.done = FALSE; - data->state.authproxy.picked = - data->state.authproxy.want; - } - - if (has_host_ntlm || has_proxy_ntlm) { - data->state.authproblem = FALSE; - - Curl_ntlm_cleanup(conn); - } - } - - /* Cleanup possible redirect junk */ - if(data->req.newurl) { - free(data->req.newurl); - data->req.newurl = NULL; - } - - if(conn->handler->disconnect) - /* This is set if protocol-specific cleanups should be made */ - conn->handler->disconnect(conn, dead_connection); - - if(-1 != conn->connectindex) { - /* unlink ourselves! */ - infof(data, "Closing connection #%ld\n", conn->connectindex); - if(data->state.connc) - /* only clear the table entry if we still know in which cache we - used to be in */ - data->state.connc->connects[conn->connectindex] = NULL; - } - -#if defined(USE_LIBIDN) - if(conn->host.encalloc) - idn_free(conn->host.encalloc); /* encoded host name buffer, must be freed - with idn_free() since this was allocated - by libidn */ - if(conn->proxy.encalloc) - idn_free(conn->proxy.encalloc); /* encoded proxy name buffer, must be - freed with idn_free() since this was - allocated by libidn */ -#elif defined(USE_WIN32_IDN) - free(conn->host.encalloc); /* encoded host name buffer, must be freed with - idn_free() since this was allocated by - curl_win32_idn_to_ascii */ - if(conn->proxy.encalloc) - free(conn->proxy.encalloc); /* encoded proxy name buffer, must be freed - with idn_free() since this was allocated by - curl_win32_idn_to_ascii */ -#endif - - Curl_ssl_close(conn, FIRSTSOCKET); - - /* Indicate to all handles on the pipe that we're dead */ - if(Curl_isPipeliningEnabled(data)) { - signalPipeClose(conn->send_pipe, TRUE); - signalPipeClose(conn->recv_pipe, TRUE); - signalPipeClose(conn->pend_pipe, TRUE); - signalPipeClose(conn->done_pipe, FALSE); - } - - conn_free(conn); - data->state.current_conn = NULL; - - return CURLE_OK; -} - -/* - * This function should return TRUE if the socket is to be assumed to - * be dead. Most commonly this happens when the server has closed the - * connection due to inactivity. - */ -static bool SocketIsDead(curl_socket_t sock) -{ - int sval; - bool ret_val = TRUE; - - sval = Curl_socket_ready(sock, CURL_SOCKET_BAD, 0); - if(sval == 0) - /* timeout */ - ret_val = FALSE; - - return ret_val; -} - -static bool IsPipeliningPossible(const struct SessionHandle *handle, - const struct connectdata *conn) -{ - if((conn->handler->protocol & CURLPROTO_HTTP) && - handle->multi && Curl_multi_canPipeline(handle->multi) && - (handle->set.httpreq == HTTPREQ_GET || - handle->set.httpreq == HTTPREQ_HEAD) && - handle->set.httpversion != CURL_HTTP_VERSION_1_0) - return TRUE; - - return FALSE; -} - -bool Curl_isPipeliningEnabled(const struct SessionHandle *handle) -{ - if(handle->multi && Curl_multi_canPipeline(handle->multi)) - return TRUE; - - return FALSE; -} - -CURLcode Curl_addHandleToPipeline(struct SessionHandle *data, - struct curl_llist *pipeline) -{ - if(!Curl_llist_insert_next(pipeline, pipeline->tail, data)) - return CURLE_OUT_OF_MEMORY; - return CURLE_OK; -} - -int Curl_removeHandleFromPipeline(struct SessionHandle *handle, - struct curl_llist *pipeline) -{ - struct curl_llist_element *curr; - - curr = pipeline->head; - while(curr) { - if(curr->ptr == handle) { - Curl_llist_remove(pipeline, curr, NULL); - return 1; /* we removed a handle */ - } - curr = curr->next; - } - - return 0; -} - -#if 0 /* this code is saved here as it is useful for debugging purposes */ -static void Curl_printPipeline(struct curl_llist *pipeline) -{ - struct curl_llist_element *curr; - - curr = pipeline->head; - while(curr) { - struct SessionHandle *data = (struct SessionHandle *) curr->ptr; - infof(data, "Handle in pipeline: %s\n", data->state.path); - curr = curr->next; - } -} -#endif - -static struct SessionHandle* gethandleathead(struct curl_llist *pipeline) -{ - struct curl_llist_element *curr = pipeline->head; - if(curr) { - return (struct SessionHandle *) curr->ptr; - } - - return NULL; -} - -/* remove the specified connection from all (possible) pipelines and related - queues */ -void Curl_getoff_all_pipelines(struct SessionHandle *data, - struct connectdata *conn) -{ - bool recv_head = (bool)(conn->readchannel_inuse && - (gethandleathead(conn->recv_pipe) == data)); - - bool send_head = (bool)(conn->writechannel_inuse && - (gethandleathead(conn->send_pipe) == data)); - - if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head) - conn->readchannel_inuse = FALSE; - if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && send_head) - conn->writechannel_inuse = FALSE; - Curl_removeHandleFromPipeline(data, conn->pend_pipe); - Curl_removeHandleFromPipeline(data, conn->done_pipe); -} - -static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke) -{ - struct curl_llist_element *curr; - - if(!pipeline) - return; - - curr = pipeline->head; - while(curr) { - struct curl_llist_element *next = curr->next; - struct SessionHandle *data = (struct SessionHandle *) curr->ptr; - -#ifdef DEBUGBUILD /* debug-only code */ - if(data->magic != CURLEASY_MAGIC_NUMBER) { - /* MAJOR BADNESS */ - infof(data, "signalPipeClose() found BAAD easy handle\n"); - } -#endif - - if (pipe_broke) - data->state.pipe_broke = TRUE; - Curl_multi_handlePipeBreak(data); - Curl_llist_remove(pipeline, curr, NULL); - curr = next; - } -} - - -/* - * Given one filled in connection struct (named needle), this function should - * detect if there already is one that has all the significant details - * exactly the same and thus should be used instead. - * - * If there is a match, this function returns TRUE - and has marked the - * connection as 'in-use'. It must later be called with ConnectionDone() to - * return back to 'idle' (unused) state. - */ -static bool -ConnectionExists(struct SessionHandle *data, - struct connectdata *needle, - struct connectdata **usethis) -{ - long i; - struct connectdata *check; - bool canPipeline = IsPipeliningPossible(data, needle); - - for(i=0; i< data->state.connc->num; i++) { - bool match = FALSE; - size_t pipeLen = 0; - /* - * Note that if we use a HTTP proxy, we check connections to that - * proxy and not to the actual remote server. - */ - check = data->state.connc->connects[i]; - if(!check) - /* NULL pointer means not filled-in entry */ - continue; - - pipeLen = check->send_pipe->size + check->recv_pipe->size; - - if(check->connectindex == -1) { - check->connectindex = i; /* Set this appropriately since it might have - been set to -1 when the easy was removed - from the multi */ - } - - if(!pipeLen && !check->inuse) { - /* The check for a dead socket makes sense only if there are no - handles in pipeline and the connection isn't already marked in - use */ - bool dead; - if(check->handler->protocol & CURLPROTO_RTSP) - /* RTSP is a special case due to RTP interleaving */ - dead = Curl_rtsp_connisdead(check); - else - dead = SocketIsDead(check->sock[FIRSTSOCKET]); - - if(dead) { - check->data = data; - infof(data, "Connection #%ld seems to be dead!\n", i); - - /* disconnect resources */ - Curl_disconnect(check, /* dead_connection */ TRUE); - data->state.connc->connects[i]=NULL; /* nothing here */ - - continue; - } - } - - if(canPipeline) { - /* Make sure the pipe has only GET requests */ - struct SessionHandle* sh = gethandleathead(check->send_pipe); - struct SessionHandle* rh = gethandleathead(check->recv_pipe); - if(sh) { - if(!IsPipeliningPossible(sh, check)) - continue; - } - else if(rh) { - if(!IsPipeliningPossible(rh, check)) - continue; - } - -#ifdef DEBUGBUILD - if(pipeLen > MAX_PIPELINE_LENGTH) { - infof(data, "BAD! Connection #%ld has too big pipeline!\n", - check->connectindex); - } -#endif - } - else { - if(pipeLen > 0) { - /* can only happen within multi handles, and means that another easy - handle is using this connection */ - continue; - } - -#ifdef CURLRES_ASYNCH - /* ip_addr_str[0] is NUL only if the resolving of the name hasn't - completed yet and until then we don't re-use this connection */ - if(!check->ip_addr_str[0]) { - infof(data, - "Connection #%ld hasn't finished name resolve, can't reuse\n", - check->connectindex); - continue; - } -#endif - - if((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) || check->bits.close) { - /* Don't pick a connection that hasn't connected yet or that is going - to get closed. */ - infof(data, "Connection #%ld isn't open enough, can't reuse\n", - check->connectindex); -#ifdef DEBUGBUILD - if(check->recv_pipe->size > 0) { - infof(data, "BAD! Unconnected #%ld has a non-empty recv pipeline!\n", - check->connectindex); - } -#endif - continue; - } - } - - if((needle->handler->flags&PROTOPT_SSL) != - (check->handler->flags&PROTOPT_SSL)) - /* don't do mixed SSL and non-SSL connections */ - continue; - - if(needle->handler->flags&PROTOPT_SSL) { - if((data->set.ssl.verifypeer != check->verifypeer) || - (data->set.ssl.verifyhost != check->verifyhost)) - continue; - } - - if(needle->bits.proxy != check->bits.proxy) - /* don't do mixed proxy and non-proxy connections */ - continue; - - if(!canPipeline && check->inuse) - /* this request can't be pipelined but the checked connection is already - in use so we skip it */ - continue; - - if(needle->localdev || needle->localport) { - /* If we are bound to a specific local end (IP+port), we must not re-use - a random other one, although if we didn't ask for a particular one we - can reuse one that was bound. - - This comparison is a bit rough and too strict. Since the input - parameters can be specified in numerous ways and still end up the - same it would take a lot of processing to make it really accurate. - Instead, this matching will assume that re-uses of bound connections - will most likely also re-use the exact same binding parameters and - missing out a few edge cases shouldn't hurt anyone very much. - */ - if((check->localport != needle->localport) || - (check->localportrange != needle->localportrange) || - !check->localdev || - strcmp(check->localdev, needle->localdev)) - continue; - } - - if(!needle->bits.httpproxy || needle->handler->flags&PROTOPT_SSL || - (needle->bits.httpproxy && check->bits.httpproxy && - needle->bits.tunnel_proxy && check->bits.tunnel_proxy && - Curl_raw_equal(needle->proxy.name, check->proxy.name) && - (needle->port == check->port))) { - /* The requested connection does not use a HTTP proxy or it uses SSL or - it is a non-SSL protocol tunneled over the same http proxy name and - port number */ - - if(Curl_raw_equal(needle->handler->scheme, check->handler->scheme) && - Curl_raw_equal(needle->host.name, check->host.name) && - (needle->remote_port == check->remote_port) ) { - if(needle->handler->flags & PROTOPT_SSL) { - /* This is SSL, verify that we're using the same - ssl options as well */ - if(!Curl_ssl_config_matches(&needle->ssl_config, - &check->ssl_config)) { - DEBUGF(infof(data, - "Connection #%ld has different SSL parameters, " - "can't reuse\n", - check->connectindex)); - continue; - } - else if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) { - DEBUGF(infof(data, - "Connection #%ld has not started ssl connect, " - "can't reuse\n", - check->connectindex)); - continue; - } - } - if((needle->handler->protocol & CURLPROTO_FTP) || - ((needle->handler->protocol & CURLPROTO_HTTP) && - (data->state.authhost.want==CURLAUTH_NTLM))) { - /* This is FTP or HTTP+NTLM, verify that we're using the same name - and password as well */ - if(!strequal(needle->user, check->user) || - !strequal(needle->passwd, check->passwd)) { - /* one of them was different */ - continue; - } - } - match = TRUE; - } - } - else { /* The requested needle connection is using a proxy, - is the checked one using the same host, port and type? */ - if(check->bits.proxy && - (needle->proxytype == check->proxytype) && - (needle->bits.tunnel_proxy == check->bits.tunnel_proxy) && - Curl_raw_equal(needle->proxy.name, check->proxy.name) && - needle->port == check->port) { - /* This is the same proxy connection, use it! */ - match = TRUE; - } - } - - if(match) { - check->inuse = TRUE; /* mark this as being in use so that no other - handle in a multi stack may nick it */ - - *usethis = check; - return TRUE; /* yes, we found one to use! */ - } - } - - return FALSE; /* no matching connecting exists */ -} - - - -/* - * This function frees/closes a connection in the connection cache. This - * should take the previously set policy into account when deciding which - * of the connections to kill. - */ -static long -ConnectionKillOne(struct SessionHandle *data) -{ - long i; - struct connectdata *conn; - long highscore=-1; - long connindex=-1; - long score; - struct timeval now; - - now = Curl_tvnow(); - - for(i=0; data->state.connc && (i< data->state.connc->num); i++) { - conn = data->state.connc->connects[i]; - - if(!conn || conn->inuse) - continue; - - /* Set higher score for the age passed since the connection was used */ - score = Curl_tvdiff(now, conn->now); - - if(score > highscore) { - highscore = score; - connindex = i; - } - } - if(connindex >= 0) { - /* Set the connection's owner correctly */ - conn = data->state.connc->connects[connindex]; - conn->data = data; - - /* the winner gets the honour of being disconnected */ - (void)Curl_disconnect(conn, /* dead_connection */ FALSE); - - /* clean the array entry */ - data->state.connc->connects[connindex] = NULL; - } - - return connindex; /* return the available index or -1 */ -} - -/* this connection can now be marked 'idle' */ -static void -ConnectionDone(struct connectdata *conn) -{ - conn->inuse = FALSE; -} - -/* - * The given input connection struct pointer is to be stored. If the "cache" - * is already full, we must clean out the most suitable using the previously - * set policy. - * - * The given connection should be unique. That must've been checked prior to - * this call. - */ -static long -ConnectionStore(struct SessionHandle *data, - struct connectdata *conn) -{ - long i; - for(i=0; i< data->state.connc->num; i++) { - if(!data->state.connc->connects[i]) - break; - } - if(i == data->state.connc->num) { - /* there was no room available, kill one */ - i = ConnectionKillOne(data); - if(-1 != i) - infof(data, "Connection (#%ld) was killed to make room (holds %ld)\n", - i, data->state.connc->num); - else - infof(data, "This connection did not fit in the connection cache\n"); - } - - conn->connectindex = i; /* Make the child know where the pointer to this - particular data is stored. But note that this -1 - if this is not within the cache and this is - probably not checked for everywhere (yet). */ - conn->inuse = TRUE; - if(-1 != i) { - /* Only do this if a true index was returned, if -1 was returned there - is no room in the cache for an unknown reason and we cannot store - this there. - - TODO: make sure we really can work with more handles than positions in - the cache, or possibly we should (allow to automatically) resize the - connection cache when we add more easy handles to a multi handle! - */ - data->state.connc->connects[i] = conn; /* fill in this */ - conn->data = data; - } - - return i; -} - -/* after a TCP connection to the proxy has been verified, this function does - the next magic step. - - Note: this function's sub-functions call failf() - -*/ -CURLcode Curl_connected_proxy(struct connectdata *conn) -{ - CURLcode result = CURLE_OK; - struct SessionHandle *data = conn->data; - - switch(data->set.proxytype) { -#ifndef CURL_DISABLE_PROXY - case CURLPROXY_SOCKS5: - case CURLPROXY_SOCKS5_HOSTNAME: - result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, - conn->host.name, conn->remote_port, - FIRSTSOCKET, conn); - break; - case CURLPROXY_SOCKS4: - result = Curl_SOCKS4(conn->proxyuser, conn->host.name, - conn->remote_port, FIRSTSOCKET, conn, FALSE); - break; - case CURLPROXY_SOCKS4A: - result = Curl_SOCKS4(conn->proxyuser, conn->host.name, - conn->remote_port, FIRSTSOCKET, conn, TRUE); - break; -#endif /* CURL_DISABLE_PROXY */ - case CURLPROXY_HTTP: - case CURLPROXY_HTTP_1_0: - /* do nothing here. handled later. */ - break; - default: - break; - } /* switch proxytype */ - - return result; -} - -static CURLcode ConnectPlease(struct SessionHandle *data, - struct connectdata *conn, - bool *connected) -{ - CURLcode result; - Curl_addrinfo *addr; -#ifndef CURL_DISABLE_VERBOSE_STRINGS - char *hostname = conn->bits.proxy?conn->proxy.name:conn->host.name; - - infof(data, "About to connect() to %s%s port %ld (#%ld)\n", - conn->bits.proxy?"proxy ":"", - hostname, conn->port, conn->connectindex); -#else - (void)data; -#endif - - /************************************************************* - * Connect to server/proxy - *************************************************************/ - result= Curl_connecthost(conn, - conn->dns_entry, - &conn->sock[FIRSTSOCKET], - &addr, - connected); - if(CURLE_OK == result) { - /* All is cool, we store the current information */ - conn->ip_addr = addr; - - if(*connected) - result = Curl_connected_proxy(conn); - } - - if(result) - *connected = FALSE; /* mark it as not connected */ - - return result; -} - -/* - * verboseconnect() displays verbose information after a connect - */ -#ifndef CURL_DISABLE_VERBOSE_STRINGS -void Curl_verboseconnect(struct connectdata *conn) -{ - if(conn->data->set.verbose) - infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n", - conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname, - conn->ip_addr_str, conn->port, conn->connectindex); -} -#endif - -int Curl_protocol_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - if(conn->handler->proto_getsock) - return conn->handler->proto_getsock(conn, socks, numsocks); - return GETSOCK_BLANK; -} - -int Curl_doing_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - if(conn && conn->handler->doing_getsock) - return conn->handler->doing_getsock(conn, socks, numsocks); - return GETSOCK_BLANK; -} - -/* - * We are doing protocol-specific connecting and this is being called over and - * over from the multi interface until the connection phase is done on - * protocol layer. - */ - -CURLcode Curl_protocol_connecting(struct connectdata *conn, - bool *done) -{ - CURLcode result=CURLE_OK; - - if(conn && conn->handler->connecting) { - *done = FALSE; - result = conn->handler->connecting(conn, done); - } - else - *done = TRUE; - - return result; -} - -/* - * We are DOING this is being called over and over from the multi interface - * until the DOING phase is done on protocol layer. - */ - -CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done) -{ - CURLcode result=CURLE_OK; - - if(conn && conn->handler->doing) { - *done = FALSE; - result = conn->handler->doing(conn, done); - } - else - *done = TRUE; - - return result; -} - -/* - * We have discovered that the TCP connection has been successful, we can now - * proceed with some action. - * - */ -CURLcode Curl_protocol_connect(struct connectdata *conn, - bool *protocol_done) -{ - CURLcode result=CURLE_OK; - struct SessionHandle *data = conn->data; - - *protocol_done = FALSE; - - if(conn->bits.tcpconnect && conn->bits.protoconnstart) { - /* We already are connected, get back. This may happen when the connect - worked fine in the first call, like when we connect to a local server - or proxy. Note that we don't know if the protocol is actually done. - - Unless this protocol doesn't have any protocol-connect callback, as - then we know we're done. */ - if(!conn->handler->connecting) - *protocol_done = TRUE; - - return CURLE_OK; - } - - if(!conn->bits.tcpconnect) { - - Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ - Curl_verboseconnect(conn); - } - - if(!conn->bits.protoconnstart) { - if(conn->handler->connect_it) { - /* is there a protocol-specific connect() procedure? */ - - /* 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(); - - /* Call the protocol-specific connect function */ - result = conn->handler->connect_it(conn, protocol_done); - } - else - *protocol_done = TRUE; - - /* it has started, possibly even completed but that knowledge isn't stored - in this bit! */ - if(!result) - conn->bits.protoconnstart = TRUE; - } - - return result; /* pass back status */ -} - -/* - * Helpers for IDNA convertions. - */ -static bool is_ASCII_name(const char *hostname) -{ - const unsigned char *ch = (const unsigned char*)hostname; - - while(*ch) { - if(*ch++ & 0x80) - return FALSE; - } - return TRUE; -} - -#ifdef USE_LIBIDN -/* - * Check if characters in hostname is allowed in Top Level Domain. - */ -static bool tld_check_name(struct SessionHandle *data, - const char *ace_hostname) -{ - size_t err_pos; - char *uc_name = NULL; - int rc; -#ifndef CURL_DISABLE_VERBOSE_STRINGS - const char *tld_errmsg = ""; -#else - (void)data; -#endif - - /* Convert (and downcase) ACE-name back into locale's character set */ - rc = idna_to_unicode_lzlz(ace_hostname, &uc_name, 0); - if(rc != IDNA_SUCCESS) - return FALSE; - - rc = tld_check_lz(uc_name, &err_pos, NULL); -#ifndef CURL_DISABLE_VERBOSE_STRINGS -#ifdef HAVE_TLD_STRERROR - if(rc != TLD_SUCCESS) - tld_errmsg = tld_strerror((Tld_rc)rc); -#endif - if(rc == TLD_INVALID) - infof(data, "WARNING: %s; pos %u = `%c'/0x%02X\n", - tld_errmsg, err_pos, uc_name[err_pos], - uc_name[err_pos] & 255); - else if(rc != TLD_SUCCESS) - infof(data, "WARNING: TLD check for %s failed; %s\n", - uc_name, tld_errmsg); -#endif /* CURL_DISABLE_VERBOSE_STRINGS */ - if(uc_name) - idn_free(uc_name); - if(rc != TLD_SUCCESS) - return FALSE; - - return TRUE; -} -#endif - -/* - * Perform any necessary IDN conversion of hostname - */ -static void fix_hostname(struct SessionHandle *data, - struct connectdata *conn, struct hostname *host) -{ -#ifndef USE_LIBIDN - (void)data; - (void)conn; -#elif defined(CURL_DISABLE_VERBOSE_STRINGS) - (void)conn; -#endif - - /* set the name we use to display the host name */ - host->dispname = host->name; - if(!is_ASCII_name(host->name)) { -#ifdef USE_LIBIDN - /************************************************************* - * Check name for non-ASCII and convert hostname to ACE form. - *************************************************************/ - if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) { - char *ace_hostname = NULL; - int rc = idna_to_ascii_lz(host->name, &ace_hostname, 0); - infof (data, "Input domain encoded as `%s'\n", - stringprep_locale_charset ()); - if(rc != IDNA_SUCCESS) - infof(data, "Failed to convert %s to ACE; %s\n", - host->name, Curl_idn_strerror(conn,rc)); - else { - /* tld_check_name() displays a warning if the host name contains - "illegal" characters for this TLD */ - (void)tld_check_name(data, ace_hostname); - - host->encalloc = ace_hostname; - /* change the name pointer to point to the encoded hostname */ - host->name = host->encalloc; - } - } -#elif defined(USE_WIN32_IDN) - /************************************************************* - * Check name for non-ASCII and convert hostname to ACE form. - *************************************************************/ - char *ace_hostname = NULL; - int rc = curl_win32_idn_to_ascii(host->name, &ace_hostname); - if(rc == 0) - infof(data, "Failed to convert %s to ACE;\n", - host->name); - else { - host->encalloc = ace_hostname; - /* change the name pointer to point to the encoded hostname */ - host->name = host->encalloc; - } -#else - infof (data, "IDN support not present, can't parse Unicode (UTF-8) domains"); -#endif - } -} - -static void llist_dtor(void *user, void *element) -{ - (void)user; - (void)element; - /* Do nothing */ -} - -/* - * Allocate and initialize a new connectdata object. - */ -static struct connectdata *allocate_conn(struct SessionHandle *data) -{ - struct connectdata *conn = calloc(1, sizeof(struct connectdata)); - if(!conn) - return NULL; - - conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined - already from start to avoid NULL - situations and checks */ - - /* and we setup a few fields in case we end up actually using this struct */ - - conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ - conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ - conn->connectindex = -1; /* no index */ - conn->port = -1; /* unknown at this point */ - - /* Default protocol-independent behavior doesn't support persistent - connections, so we set this to force-close. Protocols that support - this need to set this to FALSE in their "curl_do" functions. */ - conn->bits.close = TRUE; - - /* Store creation time to help future close decision making */ - conn->created = Curl_tvnow(); - - conn->data = data; /* Setup the association between this connection - and the SessionHandle */ - - conn->proxytype = data->set.proxytype; /* type */ - -#ifdef CURL_DISABLE_PROXY - - conn->bits.proxy = FALSE; - conn->bits.httpproxy = FALSE; - conn->bits.proxy_user_passwd = FALSE; - conn->bits.tunnel_proxy = FALSE; - -#else /* CURL_DISABLE_PROXY */ - - conn->bits.proxy = (bool)(data->set.str[STRING_PROXY] && - *data->set.str[STRING_PROXY]); - conn->bits.httpproxy = (bool)(conn->bits.proxy && - (conn->proxytype == CURLPROXY_HTTP || - conn->proxytype == CURLPROXY_HTTP_1_0)); - conn->bits.proxy_user_passwd = - (bool)(NULL != data->set.str[STRING_PROXYUSERNAME]); - conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy; - -#endif /* CURL_DISABLE_PROXY */ - - conn->bits.user_passwd = (bool)(NULL != data->set.str[STRING_USERNAME]); - conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; - conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; - - conn->verifypeer = data->set.ssl.verifypeer; - conn->verifyhost = data->set.ssl.verifyhost; - - conn->ip_version = data->set.ipver; - - if(data->multi && Curl_multi_canPipeline(data->multi) && - !conn->master_buffer) { - /* Allocate master_buffer to be used for pipelining */ - conn->master_buffer = calloc(BUFSIZE, sizeof (char)); - if(!conn->master_buffer) - goto error; - } - - /* Initialize the pipeline lists */ - conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); - conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); - conn->pend_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); - conn->done_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor); - if(!conn->send_pipe || !conn->recv_pipe || !conn->pend_pipe || - !conn->done_pipe) - goto error; - -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - conn->data_prot = PROT_CLEAR; -#endif - - /* Store the local bind parameters that will be used for this connection */ - if(data->set.str[STRING_DEVICE]) { - conn->localdev = strdup(data->set.str[STRING_DEVICE]); - if(!conn->localdev) - goto error; - } - conn->localportrange = data->set.localportrange; - conn->localport = data->set.localport; - - return conn; - error: - - Curl_llist_destroy(conn->send_pipe, NULL); - Curl_llist_destroy(conn->recv_pipe, NULL); - Curl_llist_destroy(conn->pend_pipe, NULL); - Curl_llist_destroy(conn->done_pipe, NULL); - Curl_safefree(conn->master_buffer); - Curl_safefree(conn->localdev); - Curl_safefree(conn); - return NULL; -} - -static CURLcode findprotocol(struct SessionHandle *data, - struct connectdata *conn, - const char *protostr) -{ - const struct Curl_handler * const *pp; - const struct Curl_handler *p; - - /* Scan protocol handler table and match against 'protostr' to set a few - variables based on the URL. Now that the handler may be changed later - when the protocol specific setup function is called. */ - for (pp = protocols; (p = *pp) != NULL; pp++) { - if(Curl_raw_equal(p->scheme, protostr)) { - /* Protocol found in table. Check if allowed */ - if(!(data->set.allowed_protocols & p->protocol)) - /* nope, get out */ - break; - - /* it is allowed for "normal" request, now do an extra check if this is - the result of a redirect */ - if(data->state.this_is_a_follow && - !(data->set.redir_protocols & p->protocol)) - /* nope, get out */ - break; - - /* Perform setup complement if some. */ - conn->handler = conn->given = p; - - /* 'port' and 'remote_port' are set in setup_connection_internals() */ - return CURLE_OK; - } - } - - - /* The protocol was not found in the table, but we don't have to assign it - to anything since it is already assigned to a dummy-struct in the - create_conn() function when the connectdata struct is allocated. */ - failf(data, "Protocol %s not supported or disabled in " LIBCURL_NAME, - protostr); - - return CURLE_UNSUPPORTED_PROTOCOL; -} - -/* - * Parse URL and fill in the relevant members of the connection struct. - */ -static CURLcode parseurlandfillconn(struct SessionHandle *data, - struct connectdata *conn, - bool *prot_missing) -{ - char *at; - char *fragment; - char *path = data->state.path; - char *query; - int rc; - char protobuf[16]; - const char *protop; - - *prot_missing = FALSE; - - /************************************************************* - * Parse the URL. - * - * We need to parse the url even when using the proxy, because we will need - * the hostname and port in case we are trying to SSL connect through the - * proxy -- and we don't know if we will need to use SSL until we parse the - * url ... - ************************************************************/ - if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]", - protobuf, path)) && - Curl_raw_equal(protobuf, "file")) { - if(path[0] == '/' && path[1] == '/') { - /* Allow omitted hostname (e.g. file:/). This is not strictly - * speaking a valid file: URL by RFC 1738, but treating file:/ as - * file://localhost/ is similar to how other schemes treat missing - * hostnames. See RFC 1808. */ - - /* This cannot be done with strcpy() in a portable manner, since the - memory areas overlap! */ - memmove(path, path + 2, strlen(path + 2)+1); - } - /* - * we deal with file:/// differently since it supports no - * hostname other than "localhost" and "127.0.0.1", which is unique among - * the URL protocols specified in RFC 1738 - */ - if(path[0] != '/') { - /* the URL included a host name, we ignore host names in file:// URLs - as the standards don't define what to do with them */ - char *ptr=strchr(path, '/'); - if(ptr) { - /* there was a slash present - - RFC1738 (section 3.1, page 5) says: - - The rest of the locator consists of data specific to the scheme, - and is known as the "url-path". It supplies the details of how the - specified resource can be accessed. Note that the "/" between the - host (or port) and the url-path is NOT part of the url-path. - - As most agents use file://localhost/foo to get '/foo' although the - slash preceding foo is a separator and not a slash for the path, - a URL as file://localhost//foo must be valid as well, to refer to - the same file with an absolute path. - */ - - if(ptr[1] && ('/' == ptr[1])) - /* if there was two slashes, we skip the first one as that is then - used truly as a separator */ - ptr++; - - /* This cannot be made with strcpy, as the memory chunks overlap! */ - memmove(path, ptr, strlen(ptr)+1); - } - } - - protop = "file"; /* protocol string */ - } - else { - /* clear path */ - path[0]=0; - - if(2 > sscanf(data->change.url, - "%15[^\n:]://%[^\n/?]%[^\n]", - protobuf, - conn->host.name, path)) { - - /* - * The URL was badly formatted, let's try the browser-style _without_ - * protocol specified like 'http://'. - */ - rc = sscanf(data->change.url, "%[^\n/?]%[^\n]", conn->host.name, path); - if(1 > rc) { - /* - * We couldn't even get this format. - * djgpp 2.04 has a sscanf() bug where 'conn->host.name' is - * assigned, but the return value is EOF! - */ -#if defined(__DJGPP__) && (DJGPP_MINOR == 4) - if (!(rc == -1 && *conn->host.name)) -#endif - { - failf(data, " malformed"); - return CURLE_URL_MALFORMAT; - } - } - - /* - * Since there was no protocol part specified, we guess what protocol it - * is based on the first letters of the server name. - */ - - /* Note: if you add a new protocol, please update the list in - * lib/version.c too! */ - - if(checkprefix("FTP.", conn->host.name)) - protop = "ftp"; - else if(checkprefix("DICT.", conn->host.name)) - protop = "DICT"; - else if(checkprefix("LDAP.", conn->host.name)) - protop = "LDAP"; - else if(checkprefix("IMAP.", conn->host.name)) - protop = "IMAP"; - else { - protop = "http"; - } - - *prot_missing = TRUE; /* not given in URL */ - } - else - protop = protobuf; - } - - /* We search for '?' in the host name (but only on the right side of a - * @-letter to allow ?-letters in username and password) to handle things - * like http://example.com?param= (notice the missing '/'). - */ - at = strchr(conn->host.name, '@'); - if(at) - query = strchr(at+1, '?'); - else - query = strchr(conn->host.name, '?'); - - if(query) { - /* We must insert a slash before the '?'-letter in the URL. If the URL had - a slash after the '?', that is where the path currently begins and the - '?string' is still part of the host name. - - We must move the trailing part from the host name and put it first in - the path. And have it all prefixed with a slash. - */ - - size_t hostlen = strlen(query); - size_t pathlen = strlen(path); - - /* move the existing path plus the zero byte forward, to make room for - the host-name part */ - memmove(path+hostlen+1, path, pathlen+1); - - /* now copy the trailing host part in front of the existing path */ - memcpy(path+1, query, hostlen); - - path[0]='/'; /* prepend the missing slash */ - - *query=0; /* now cut off the hostname at the ? */ - } - else if(!path[0]) { - /* if there's no path set, use a single slash */ - strcpy(path, "/"); - } - - /* If the URL is malformatted (missing a '/' after hostname before path) we - * insert a slash here. The only letter except '/' we accept to start a path - * is '?'. - */ - if(path[0] == '?') { - /* We need this function to deal with overlapping memory areas. We know - that the memory area 'path' points to is 'urllen' bytes big and that - is bigger than the path. Use +1 to move the zero byte too. */ - memmove(&path[1], path, strlen(path)+1); - path[0] = '/'; - } - - if (conn->host.name[0] == '[') { - /* This looks like an IPv6 address literal. See if there is an address - scope. */ - char *percent = strstr (conn->host.name, "%25"); - if (percent) { - char *endp; - unsigned long scope = strtoul (percent + 3, &endp, 10); - if (*endp == ']') { - /* The address scope was well formed. Knock it out of the - hostname. */ - memmove(percent, endp, strlen(endp)+1); - if (!data->state.this_is_a_follow) - /* Don't honour a scope given in a Location: header */ - conn->scope = (unsigned int)scope; - } else - infof(data, "Invalid IPv6 address format\n"); - } - } - - if(data->set.scope) - /* Override any scope that was set above. */ - conn->scope = data->set.scope; - - /* Remove the fragment part of the path. Per RFC 2396, this is always the - last part of the URI. We are looking for the first '#' so that we deal - gracefully with non conformant URI such as http://example.com#foo#bar. */ - fragment = strchr(path, '#'); - if(fragment) - *fragment = 0; - - /* - * So if the URL was A://B/C#D, - * protop is A - * conn->host.name is B - * data->state.path is /C - */ - - return findprotocol(data, conn, protop); -} - -/* - * If we're doing a resumed transfer, we need to setup our stuff - * properly. - */ -static CURLcode setup_range(struct SessionHandle *data) -{ - struct UrlState *s = &data->state; - s->resume_from = data->set.set_resume_from; - if(s->resume_from || data->set.str[STRING_SET_RANGE]) { - if(s->rangestringalloc) - free(s->range); - - if(s->resume_from) - s->range = aprintf("%" FORMAT_OFF_TU "-", s->resume_from); - else - s->range = strdup(data->set.str[STRING_SET_RANGE]); - - s->rangestringalloc = (bool)(s->range?TRUE:FALSE); - - if(!s->range) - return CURLE_OUT_OF_MEMORY; - - /* tell ourselves to fetch this range */ - s->use_range = TRUE; /* enable range download */ - } - else - s->use_range = FALSE; /* disable range download */ - - return CURLE_OK; -} - - -/*************************************************************** -* Setup connection internals specific to the requested protocol. -* This MUST get called after proxy magic has been figured out. -***************************************************************/ -static CURLcode setup_connection_internals(struct connectdata *conn) -{ - const struct Curl_handler * p; - CURLcode result; - - conn->socktype = SOCK_STREAM; /* most of them are TCP streams */ - - /* Scan protocol handler table. */ - - /* Perform setup complement if some. */ - p = conn->handler; - - if(p->setup_connection) { - result = (*p->setup_connection)(conn); - - if(result != CURLE_OK) - return result; - - p = conn->handler; /* May have changed. */ - } - - if(conn->port < 0) - /* we check for -1 here since if proxy was detected already, this - was very likely already set to the proxy port */ - conn->port = p->defport; - conn->remote_port = (unsigned short)conn->given->defport; - - return CURLE_OK; -} - -#ifndef CURL_DISABLE_PROXY -/**************************************************************** -* Checks if the host is in the noproxy list. returns true if it matches -* and therefore the proxy should NOT be used. -****************************************************************/ -static bool check_noproxy(const char* name, const char* no_proxy) -{ - /* no_proxy=domain1.dom,host.domain2.dom - * (a comma-separated list of hosts which should - * not be proxied, or an asterisk to override - * all proxy variables) - */ - size_t tok_start; - size_t tok_end; - const char* separator = ", "; - size_t no_proxy_len; - size_t namelen; - char *endptr; - - if(no_proxy && no_proxy[0]) { - if(Curl_raw_equal("*", no_proxy)) { - return TRUE; - } - - /* NO_PROXY was specified and it wasn't just an asterisk */ - - no_proxy_len = strlen(no_proxy); - endptr = strchr(name, ':'); - if(endptr) - namelen = endptr - name; - else - namelen = strlen(name); - - for (tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) { - while (tok_start < no_proxy_len && - strchr(separator, no_proxy[tok_start]) != NULL) { - /* Look for the beginning of the token. */ - ++tok_start; - } - - if(tok_start == no_proxy_len) - break; /* It was all trailing separator chars, no more tokens. */ - - for (tok_end = tok_start; tok_end < no_proxy_len && - strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end) { - /* Look for the end of the token. */ - } - - /* To match previous behaviour, where it was necessary to specify - * ".local.com" to prevent matching "notlocal.com", we will leave - * the '.' off. - */ - if(no_proxy[tok_start] == '.') - ++tok_start; - - if((tok_end - tok_start) <= namelen) { - /* Match the last part of the name to the domain we are checking. */ - const char *checkn = name + namelen - (tok_end - tok_start); - if(Curl_raw_nequal(no_proxy + tok_start, checkn, - tok_end - tok_start)) { - if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') { - /* We either have an exact match, or the previous character is a . - * so it is within the same domain, so no proxy for this host. - */ - return TRUE; - } - } - } /* if((tok_end - tok_start) <= namelen) */ - } /* for (tok_start = 0; tok_start < no_proxy_len; - tok_start = tok_end + 1) */ - } /* NO_PROXY was specified and it wasn't just an asterisk */ - - return FALSE; -} - -/**************************************************************** -* Detect what (if any) proxy to use. Remember that this selects a host -* name and is not limited to HTTP proxies only. -* The returned pointer must be freed by the caller (unless NULL) -****************************************************************/ -static char *detect_proxy(struct connectdata *conn) -{ - char *proxy = NULL; - -#ifndef CURL_DISABLE_HTTP - /* If proxy was not specified, we check for default proxy environment - * variables, to enable i.e Lynx compliance: - * - * http_proxy=http://some.server.dom:port/ - * https_proxy=http://some.server.dom:port/ - * ftp_proxy=http://some.server.dom:port/ - * no_proxy=domain1.dom,host.domain2.dom - * (a comma-separated list of hosts which should - * not be proxied, or an asterisk to override - * all proxy variables) - * all_proxy=http://some.server.dom:port/ - * (seems to exist for the CERN www lib. Probably - * the first to check for.) - * - * For compatibility, the all-uppercase versions of these variables are - * checked if the lowercase versions don't exist. - */ - char *no_proxy=NULL; - char proxy_env[128]; - - no_proxy=curl_getenv("no_proxy"); - if(!no_proxy) - no_proxy=curl_getenv("NO_PROXY"); - - if(!check_noproxy(conn->host.name, no_proxy)) { - /* It was not listed as without proxy */ - const char *protop = conn->handler->scheme; - char *envp = proxy_env; - char *prox; - - /* Now, build _proxy and check for such a one to use */ - while(*protop) - *envp++ = (char)tolower((int)*protop++); - - /* append _proxy */ - strcpy(envp, "_proxy"); - - /* read the protocol proxy: */ - prox=curl_getenv(proxy_env); - - /* - * We don't try the uppercase version of HTTP_PROXY because of - * security reasons: - * - * When curl is used in a webserver application - * environment (cgi or php), this environment variable can - * be controlled by the web server user by setting the - * http header 'Proxy:' to some value. - * - * This can cause 'internal' http/ftp requests to be - * arbitrarily redirected by any external attacker. - */ - if(!prox && !Curl_raw_equal("http_proxy", proxy_env)) { - /* There was no lowercase variable, try the uppercase version: */ - Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env)); - prox=curl_getenv(proxy_env); - } - - if(prox && *prox) { /* don't count "" strings */ - proxy = prox; /* use this */ - } - else { - proxy = curl_getenv("all_proxy"); /* default proxy to use */ - if(!proxy) - proxy=curl_getenv("ALL_PROXY"); - } - } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified - non-proxy */ - if(no_proxy) - free(no_proxy); - -#else /* !CURL_DISABLE_HTTP */ - - (void)conn; -#endif /* CURL_DISABLE_HTTP */ - - return proxy; -} - -/* - * If this is supposed to use a proxy, we need to figure out the proxy - * host name, so that we can re-use an existing connection - * that may exist registered to the same proxy host. - * proxy will be freed before this function returns. - */ -static CURLcode parse_proxy(struct SessionHandle *data, - struct connectdata *conn, char *proxy) -{ - char *prox_portno; - char *endofprot; - - /* We use 'proxyptr' to point to the proxy name from now on... */ - char *proxyptr; - char *portptr; - char *atsign; - - /* We do the proxy host string parsing here. We want the host name and the - * port name. Accept a protocol:// prefix, even though it should just be - * ignored. - */ - - /* Skip the protocol part if present */ - endofprot = strstr(proxy, "://"); - if(endofprot) - proxyptr = endofprot+3; - else - proxyptr = proxy; - - /* Is there a username and password given in this proxy url? */ - atsign = strchr(proxyptr, '@'); - if(atsign) { - char proxyuser[MAX_CURL_USER_LENGTH]; - char proxypasswd[MAX_CURL_PASSWORD_LENGTH]; - proxypasswd[0] = 0; - - if(1 <= sscanf(proxyptr, - "%" MAX_CURL_USER_LENGTH_TXT"[^:@]:" - "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]", - proxyuser, proxypasswd)) { - CURLcode res = CURLE_OK; - - /* found user and password, rip them out. note that we are - unescaping them, as there is otherwise no way to have a - username or password with reserved characters like ':' in - them. */ - Curl_safefree(conn->proxyuser); - conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL); - - if(!conn->proxyuser) - res = CURLE_OUT_OF_MEMORY; - else { - Curl_safefree(conn->proxypasswd); - conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL); - - if(!conn->proxypasswd) - res = CURLE_OUT_OF_MEMORY; - } - - if(CURLE_OK == res) { - conn->bits.proxy_user_passwd = TRUE; /* enable it */ - atsign = strdup(atsign+1); /* the right side of the @-letter */ - - if(atsign) { - free(proxy); /* free the former proxy string */ - proxy = proxyptr = atsign; /* now use this instead */ - } - else - res = CURLE_OUT_OF_MEMORY; - } - - if(res) { - free(proxy); /* free the allocated proxy string */ - return res; - } - } - } - - /* start scanning for port number at this point */ - portptr = proxyptr; - - /* detect and extract RFC2732-style IPv6-addresses */ - if(*proxyptr == '[') { - char *ptr = ++proxyptr; /* advance beyond the initial bracket */ - while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '%') || - (*ptr == '.'))) - ptr++; - if(*ptr == ']') { - /* yeps, it ended nicely with a bracket as well */ - *ptr++ = 0; - } else - infof(data, "Invalid IPv6 address format\n"); - portptr = ptr; - /* Note that if this didn't end with a bracket, we still advanced the - * proxyptr first, but I can't see anything wrong with that as no host - * name nor a numeric can legally start with a bracket. - */ - } - - /* Get port number off proxy.server.com:1080 */ - prox_portno = strchr(portptr, ':'); - if(prox_portno) { - *prox_portno = 0x0; /* cut off number from host name */ - prox_portno ++; - /* now set the local port number */ - conn->port = strtol(prox_portno, NULL, 10); - } - else { - /* without a port number after the host name, some people seem to use - a slash so we strip everything from the first slash */ - atsign = strchr(proxyptr, '/'); - if(atsign) - *atsign = 0x0; /* cut off path part from host name */ - - if(data->set.proxyport) - /* None given in the proxy string, then get the default one if it is - given */ - conn->port = data->set.proxyport; - } - - /* now, clone the cleaned proxy host name */ - conn->proxy.rawalloc = strdup(proxyptr); - conn->proxy.name = conn->proxy.rawalloc; - - free(proxy); - if(!conn->proxy.rawalloc) - return CURLE_OUT_OF_MEMORY; - - return CURLE_OK; -} - -/* - * Extract the user and password from the authentication string - */ -static CURLcode parse_proxy_auth(struct SessionHandle *data, - struct connectdata *conn) -{ - char proxyuser[MAX_CURL_USER_LENGTH]=""; - char proxypasswd[MAX_CURL_PASSWORD_LENGTH]=""; - - if(data->set.str[STRING_PROXYUSERNAME] != NULL) { - strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME], - MAX_CURL_USER_LENGTH); - proxyuser[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/ - } - if(data->set.str[STRING_PROXYPASSWORD] != NULL) { - strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD], - MAX_CURL_PASSWORD_LENGTH); - proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/ - } - - conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL); - if(!conn->proxyuser) - return CURLE_OUT_OF_MEMORY; - - conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL); - if(!conn->proxypasswd) - return CURLE_OUT_OF_MEMORY; - - return CURLE_OK; -} -#endif /* CURL_DISABLE_PROXY */ - -/* - * - * Parse a user name and password in the URL and strip it out of the host name - * - * Inputs: data->set.use_netrc (CURLOPT_NETRC) - * conn->host.name - * - * Outputs: (almost :- all currently undefined) - * conn->bits.user_passwd - non-zero if non-default passwords exist - * user - non-zero length if defined - * passwd - ditto - * conn->host.name - remove user name and password - */ -static CURLcode parse_url_userpass(struct SessionHandle *data, - struct connectdata *conn, - char *user, char *passwd) -{ - /* At this point, we're hoping all the other special cases have - * been taken care of, so conn->host.name is at most - * [user[:password]]@]hostname - * - * We need somewhere to put the embedded details, so do that first. - */ - - char *ptr=strchr(conn->host.name, '@'); - char *userpass = conn->host.name; - - user[0] =0; /* to make everything well-defined */ - passwd[0]=0; - - /* We will now try to extract the - * possible user+password pair in a string like: - * ftp://user:password@ftp.my.site:8021/README */ - if(ptr != NULL) { - /* there's a user+password given here, to the left of the @ */ - - conn->host.name = ++ptr; - - /* So the hostname is sane. Only bother interpreting the - * results if we could care. It could still be wasted - * work because it might be overtaken by the programmatically - * set user/passwd, but doing that first adds more cases here :-( - */ - - conn->bits.userpwd_in_url = TRUE; - if(data->set.use_netrc != CURL_NETRC_REQUIRED) { - /* We could use the one in the URL */ - - conn->bits.user_passwd = TRUE; /* enable user+password */ - - if(*userpass != ':') { - /* the name is given, get user+password */ - sscanf(userpass, "%" MAX_CURL_USER_LENGTH_TXT "[^:@]:" - "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]", - user, passwd); - } - else - /* no name given, get the password only */ - sscanf(userpass, ":%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]", passwd); - - if(user[0]) { - char *newname=curl_easy_unescape(data, user, 0, NULL); - if(!newname) - return CURLE_OUT_OF_MEMORY; - if(strlen(newname) < MAX_CURL_USER_LENGTH) - strcpy(user, newname); - - /* if the new name is longer than accepted, then just use - the unconverted name, it'll be wrong but what the heck */ - free(newname); - } - if(passwd[0]) { - /* we have a password found in the URL, decode it! */ - char *newpasswd=curl_easy_unescape(data, passwd, 0, NULL); - if(!newpasswd) - return CURLE_OUT_OF_MEMORY; - if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH) - strcpy(passwd, newpasswd); - - free(newpasswd); - } - } - } - return CURLE_OK; -} - -/************************************************************* - * Figure out the remote port number and fix it in the URL - * - * No matter if we use a proxy or not, we have to figure out the remote - * port number of various reasons. - * - * To be able to detect port number flawlessly, we must not confuse them - * IPv6-specified addresses in the [0::1] style. (RFC2732) - * - * The conn->host.name is currently [user:passwd@]host[:port] where host - * could be a hostname, IPv4 address or IPv6 address. - * - * The port number embedded in the URL is replaced, if necessary. - *************************************************************/ -static CURLcode parse_remote_port(struct SessionHandle *data, - struct connectdata *conn) -{ - char *portptr; - char endbracket; - - /* Note that at this point, the IPv6 address cannot contain any scope - suffix as that has already been removed in the parseurlandfillconn() - function */ - if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c", - &endbracket)) && - (']' == endbracket)) { - /* this is a RFC2732-style specified IP-address */ - conn->bits.ipv6_ip = TRUE; - - conn->host.name++; /* skip over the starting bracket */ - portptr = strchr(conn->host.name, ']'); - if(portptr) { - *portptr++ = '\0'; /* zero terminate, killing the bracket */ - if(':' != *portptr) - portptr = NULL; /* no port number available */ - } - } - else - portptr = strrchr(conn->host.name, ':'); - - if(data->set.use_port && data->state.allow_port) { - /* if set, we use this and ignore the port possibly given in the URL */ - conn->remote_port = (unsigned short)data->set.use_port; - if(portptr) - *portptr = '\0'; /* cut off the name there anyway - if there was a port - number - since the port number is to be ignored! */ - if(conn->bits.httpproxy) { - /* we need to create new URL with the new port number */ - char *url; - char type[12]=""; - - if(conn->bits.type_set) - snprintf(type, sizeof(type), ";type=%c", - data->set.prefer_ascii?'A': - (data->set.ftp_list_only?'D':'I')); - - /* - * This synthesized URL isn't always right--suffixes like ;type=A are - * stripped off. It would be better to work directly from the original - * URL and simply replace the port part of it. - */ - url = aprintf("%s://%s%s%s:%hu%s%s%s", conn->given->scheme, - conn->bits.ipv6_ip?"[":"", conn->host.name, - conn->bits.ipv6_ip?"]":"", conn->remote_port, - data->state.slash_removed?"/":"", data->state.path, - type); - if(!url) - return CURLE_OUT_OF_MEMORY; - - if(data->change.url_alloc) - free(data->change.url); - - data->change.url = url; - data->change.url_alloc = TRUE; - } - } - else if(portptr) { - /* no CURLOPT_PORT given, extract the one from the URL */ - - char *rest; - unsigned long port; - - port=strtoul(portptr+1, &rest, 10); /* Port number must be decimal */ - - if(rest != (portptr+1) && *rest == '\0') { - /* The colon really did have only digits after it, - * so it is either a port number or a mistake */ - - if(port > 0xffff) { /* Single unix standard says port numbers are - * 16 bits long */ - failf(data, "Port number too large: %lu", port); - return CURLE_URL_MALFORMAT; - } - - *portptr = '\0'; /* cut off the name there */ - conn->remote_port = curlx_ultous(port); - } - else if(!port) - /* Browser behavior adaptation. If there's a colon with no digits after, - just cut off the name there which makes us ignore the colon and just - use the default port. Firefox and Chrome both do that. */ - *portptr = '\0'; - } - return CURLE_OK; -} - -/* - * Override a user name and password from the URL with that in the - * CURLOPT_USERPWD option or a .netrc file, if applicable. - */ -static void override_userpass(struct SessionHandle *data, - struct connectdata *conn, - char *user, char *passwd) -{ - if(data->set.str[STRING_USERNAME] != NULL) { - strncpy(user, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH); - user[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/ - } - if(data->set.str[STRING_PASSWORD] != NULL) { - strncpy(passwd, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH); - passwd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/ - } - - conn->bits.netrc = FALSE; - if(data->set.use_netrc != CURL_NETRC_IGNORED) { - if(Curl_parsenetrc(conn->host.name, - user, passwd, - data->set.str[STRING_NETRC_FILE])) { - infof(data, "Couldn't find host %s in the " - DOT_CHAR "netrc file; using defaults\n", - conn->host.name); - } - else { - /* set bits.netrc TRUE to remember that we got the name from a .netrc - file, so that it is safe to use even if we followed a Location: to a - different host or similar. */ - conn->bits.netrc = TRUE; - - conn->bits.user_passwd = TRUE; /* enable user+password */ - } - } -} - -/* - * Set password so it's available in the connection. - */ -static CURLcode set_userpass(struct connectdata *conn, - const char *user, const char *passwd) -{ - /* If our protocol needs a password and we have none, use the defaults */ - if( (conn->handler->protocol & (CURLPROTO_FTP|CURLPROTO_IMAP)) && - !conn->bits.user_passwd) { - - conn->user = strdup(CURL_DEFAULT_USER); - if(conn->user) - conn->passwd = strdup(CURL_DEFAULT_PASSWORD); - else - conn->passwd = NULL; - /* This is the default password, so DON'T set conn->bits.user_passwd */ - } - else { - /* store user + password, zero-length if not set */ - conn->user = strdup(user); - if(conn->user) - conn->passwd = strdup(passwd); - else - conn->passwd = NULL; - } - if(!conn->user || !conn->passwd) - return CURLE_OUT_OF_MEMORY; - - return CURLE_OK; -} - -/************************************************************* - * Resolve the address of the server or proxy - *************************************************************/ -static CURLcode resolve_server(struct SessionHandle *data, - struct connectdata *conn, - bool *async) -{ - CURLcode result=CURLE_OK; - long timeout_ms = Curl_timeleft(data, NULL, TRUE); - - /************************************************************* - * Resolve the name of the server or proxy - *************************************************************/ - if(conn->bits.reuse) { - /* We're reusing the connection - no need to resolve anything */ - *async = FALSE; - - if(conn->bits.proxy) - fix_hostname(data, conn, &conn->host); - } - else { - /* this is a fresh connect */ - int rc; - struct Curl_dns_entry *hostaddr; - - /* set a pointer to the hostname we display */ - fix_hostname(data, conn, &conn->host); - - if(!conn->proxy.name || !*conn->proxy.name) { - /* If not connecting via a proxy, extract the port from the URL, if it is - * there, thus overriding any defaults that might have been set above. */ - conn->port = conn->remote_port; /* it is the same port */ - - /* Resolve target host right on */ - rc = Curl_resolv_timeout(conn, conn->host.name, (int)conn->port, - &hostaddr, timeout_ms); - if(rc == CURLRESOLV_PENDING) - *async = TRUE; - - else if (rc == CURLRESOLV_TIMEDOUT) - result = CURLE_OPERATION_TIMEDOUT; - - else if(!hostaddr) { - failf(data, "Couldn't resolve host '%s'", conn->host.dispname); - result = CURLE_COULDNT_RESOLVE_HOST; - /* don't return yet, we need to clean up the timeout first */ - } - } - else { - /* This is a proxy that hasn't been resolved yet. */ - - /* IDN-fix the proxy name */ - fix_hostname(data, conn, &conn->proxy); - - /* resolve proxy */ - rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port, - &hostaddr, timeout_ms); - - if(rc == CURLRESOLV_PENDING) - *async = TRUE; - - else if (rc == CURLRESOLV_TIMEDOUT) - result = CURLE_OPERATION_TIMEDOUT; - - else if(!hostaddr) { - failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname); - result = CURLE_COULDNT_RESOLVE_PROXY; - /* don't return yet, we need to clean up the timeout first */ - } - } - DEBUGASSERT(conn->dns_entry == NULL); - conn->dns_entry = hostaddr; - } - - return result; -} - -/* - * Cleanup the connection just allocated before we can move along and use the - * previously existing one. All relevant data is copied over and old_conn is - * ready for freeing once this function returns. - */ -static void reuse_conn(struct connectdata *old_conn, - struct connectdata *conn) -{ - if(old_conn->proxy.rawalloc) - free(old_conn->proxy.rawalloc); - - /* free the SSL config struct from this connection struct as this was - allocated in vain and is targeted for destruction */ - Curl_free_ssl_config(&old_conn->ssl_config); - - conn->data = old_conn->data; - - /* get the user+password information from the old_conn struct since it may - * be new for this request even when we re-use an existing connection */ - conn->bits.user_passwd = old_conn->bits.user_passwd; - if(conn->bits.user_passwd) { - /* use the new user name and password though */ - Curl_safefree(conn->user); - Curl_safefree(conn->passwd); - conn->user = old_conn->user; - conn->passwd = old_conn->passwd; - old_conn->user = NULL; - old_conn->passwd = NULL; - } - - conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd; - if(conn->bits.proxy_user_passwd) { - /* use the new proxy user name and proxy password though */ - Curl_safefree(conn->proxyuser); - Curl_safefree(conn->proxypasswd); - conn->proxyuser = old_conn->proxyuser; - conn->proxypasswd = old_conn->proxypasswd; - old_conn->proxyuser = NULL; - old_conn->proxypasswd = NULL; - } - - /* host can change, when doing keepalive with a proxy ! */ - if(conn->bits.proxy) { - free(conn->host.rawalloc); - conn->host=old_conn->host; - } - else - free(old_conn->host.rawalloc); /* free the newly allocated name buffer */ - - /* persist connection info in session handle */ - Curl_persistconninfo(conn); - - /* re-use init */ - conn->bits.reuse = TRUE; /* yes, we're re-using here */ - - Curl_safefree(old_conn->user); - Curl_safefree(old_conn->passwd); - Curl_safefree(old_conn->proxyuser); - Curl_safefree(old_conn->proxypasswd); - Curl_llist_destroy(old_conn->send_pipe, NULL); - Curl_llist_destroy(old_conn->recv_pipe, NULL); - Curl_llist_destroy(old_conn->pend_pipe, NULL); - Curl_llist_destroy(old_conn->done_pipe, NULL); - Curl_safefree(old_conn->master_buffer); -} - -/** - * create_conn() sets up a new connectdata struct, or re-uses an already - * existing one, and resolves host name. - * - * if this function returns CURLE_OK and *async is set to TRUE, the resolve - * response will be coming asynchronously. If *async is FALSE, the name is - * already resolved. - * - * @param data The sessionhandle pointer - * @param in_connect is set to the next connection data pointer - * @param async is set TRUE when an async DNS resolution is pending - * @see setup_conn() - * - * *NOTE* this function assigns the conn->data pointer! - */ - -static CURLcode create_conn(struct SessionHandle *data, - struct connectdata **in_connect, - bool *async) -{ - CURLcode result=CURLE_OK; - struct connectdata *conn; - struct connectdata *conn_temp = NULL; - size_t urllen; - char user[MAX_CURL_USER_LENGTH]; - char passwd[MAX_CURL_PASSWORD_LENGTH]; - bool reuse; - char *proxy = NULL; - bool prot_missing = FALSE; - - *async = FALSE; - - /************************************************************* - * Check input data - *************************************************************/ - - if(!data->change.url) - return CURLE_URL_MALFORMAT; - - /* First, split up the current URL in parts so that we can use the - parts for checking against the already present connections. In order - to not have to modify everything at once, we allocate a temporary - connection data struct and fill in for comparison purposes. */ - conn = allocate_conn(data); - - if(!conn) - return CURLE_OUT_OF_MEMORY; - - /* We must set the return variable as soon as possible, so that our - parent can cleanup any possible allocs we may have done before - any failure */ - *in_connect = conn; - - /* This initing continues below, see the comment "Continue connectdata - * initialization here" */ - - /*********************************************************** - * We need to allocate memory to store the path in. We get the size of the - * full URL to be sure, and we need to make it at least 256 bytes since - * other parts of the code will rely on this fact - ***********************************************************/ -#define LEAST_PATH_ALLOC 256 - urllen=strlen(data->change.url); - if(urllen < LEAST_PATH_ALLOC) - urllen=LEAST_PATH_ALLOC; - - /* - * We malloc() the buffers below urllen+2 to make room for to possibilities: - * 1 - an extra terminating zero - * 2 - an extra slash (in case a syntax like "www.host.com?moo" is used) - */ - - Curl_safefree(data->state.pathbuffer); - data->state.pathbuffer = malloc(urllen+2); - if(NULL == data->state.pathbuffer) - return CURLE_OUT_OF_MEMORY; /* really bad error */ - data->state.path = data->state.pathbuffer; - - conn->host.rawalloc = malloc(urllen+2); - if(NULL == conn->host.rawalloc) - return CURLE_OUT_OF_MEMORY; - - conn->host.name = conn->host.rawalloc; - conn->host.name[0] = 0; - - result = parseurlandfillconn(data, conn, &prot_missing); - if(result != CURLE_OK) { - return result; - } - - /************************************************************* - * No protocol part in URL was used, add it! - *************************************************************/ - if(prot_missing) { - /* We're guessing prefixes here and if we're told to use a proxy or if - we're gonna follow a Location: later or... then we need the protocol - part added so that we have a valid URL. */ - char *reurl; - - reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url); - - if(!reurl) { - Curl_safefree(proxy); - return CURLE_OUT_OF_MEMORY; - } - - data->change.url = reurl; - data->change.url_alloc = TRUE; /* free this later */ - } - - /************************************************************* - * Parse a user name and password in the URL and strip it out - * of the host name - *************************************************************/ - result = parse_url_userpass(data, conn, user, passwd); - if(result != CURLE_OK) - return result; - -#ifndef CURL_DISABLE_PROXY - /************************************************************* - * Extract the user and password from the authentication string - *************************************************************/ - if(conn->bits.proxy_user_passwd) { - result = parse_proxy_auth(data, conn); - if(result != CURLE_OK) - return result; - } - - /************************************************************* - * Detect what (if any) proxy to use - *************************************************************/ - if(data->set.str[STRING_PROXY]) { - proxy = strdup(data->set.str[STRING_PROXY]); - /* if global proxy is set, this is it */ - if(NULL == proxy) { - failf(data, "memory shortage"); - return CURLE_OUT_OF_MEMORY; - } - } - - if(data->set.str[STRING_NOPROXY] && - check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) { - if(proxy) { - free(proxy); /* proxy is in exception list */ - proxy = NULL; - } - } - else if(!proxy) - proxy = detect_proxy(conn); - - if(proxy && !*proxy) { - free(proxy); /* Don't bother with an empty proxy string */ - proxy = NULL; - } - /* proxy must be freed later unless NULL */ - if(proxy && !(conn->handler->flags & PROTOPT_BANPROXY)) { - if((conn->proxytype == CURLPROXY_HTTP) || - (conn->proxytype == CURLPROXY_HTTP_1_0)) { -#ifdef CURL_DISABLE_HTTP - /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */ - return CURLE_UNSUPPORTED_PROTOCOL; -#else - /* force this connection's protocol to become HTTP */ - conn->handler = &Curl_handler_http; - conn->bits.httpproxy = TRUE; -#endif - } - conn->bits.proxy = TRUE; - } - else { - /* we aren't using the proxy after all... */ - conn->bits.proxy = FALSE; - conn->bits.httpproxy = FALSE; - conn->bits.proxy_user_passwd = FALSE; - conn->bits.tunnel_proxy = FALSE; - } - - /*********************************************************************** - * If this is supposed to use a proxy, we need to figure out the proxy - * host name, so that we can re-use an existing connection - * that may exist registered to the same proxy host. - ***********************************************************************/ - if(proxy) { - result = parse_proxy(data, conn, proxy); - /* parse_proxy has freed the proxy string, so don't try to use it again */ - proxy = NULL; - if(result != CURLE_OK) - return result; - } -#endif /* CURL_DISABLE_PROXY */ - - /************************************************************* - * Setup internals depending on protocol. Needs to be done after - * we figured out what/if proxy to use. - *************************************************************/ - result = setup_connection_internals(conn); - if(result != CURLE_OK) { - Curl_safefree(proxy); - return result; - } - - conn->recv[FIRSTSOCKET] = Curl_recv_plain; - conn->send[FIRSTSOCKET] = Curl_send_plain; - conn->recv[SECONDARYSOCKET] = Curl_recv_plain; - conn->send[SECONDARYSOCKET] = Curl_send_plain; - - /*********************************************************************** - * file: is a special case in that it doesn't need a network connection - ***********************************************************************/ -#ifndef CURL_DISABLE_FILE - if(conn->handler->protocol & CURLPROTO_FILE) { - bool done; - /* this is supposed to be the connect function so we better at least check - that the file is present here! */ - DEBUGASSERT(conn->handler->connect_it); - result = conn->handler->connect_it(conn, &done); - - /* Setup a "faked" transfer that'll do nothing */ - if(CURLE_OK == result) { - conn->data = data; - conn->bits.tcpconnect = TRUE; /* we are "connected */ - - ConnectionStore(data, conn); - - /* - * Setup whatever necessary for a resumed transfer - */ - result = setup_range(data); - if(result) { - DEBUGASSERT(conn->handler->done); - /* we ignore the return code for the protocol-specific DONE */ - (void)conn->handler->done(conn, result, FALSE); - return result; - } - - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */ - -1, NULL); /* no upload */ - } - - return result; - } -#endif - - /************************************************************* - * If the protocol is using SSL and HTTP proxy is used, we set - * the tunnel_proxy bit. - *************************************************************/ - if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy) - conn->bits.tunnel_proxy = TRUE; - - /************************************************************* - * Figure out the remote port number and fix it in the URL - *************************************************************/ - result = parse_remote_port(data, conn); - if(result != CURLE_OK) - return result; - - /************************************************************* - * Check for an overridden user name and password, then set it - * for use - *************************************************************/ - override_userpass(data, conn, user, passwd); - result = set_userpass(conn, user, passwd); - if(result != CURLE_OK) - return result; - - /* Get a cloned copy of the SSL config situation stored in the - connection struct. But to get this going nicely, we must first make - sure that the strings in the master copy are pointing to the correct - strings in the session handle strings array! - - Keep in mind that the pointers in the master copy are pointing to strings - that will be freed as part of the SessionHandle struct, but all cloned - copies will be separately allocated. - */ - data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH]; - data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE]; - data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE]; - data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; - data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; - data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; - data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST]; -#ifdef USE_TLS_SRP - data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME]; - data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD]; -#endif - - if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) - return CURLE_OUT_OF_MEMORY; - - /************************************************************* - * Check the current list of connections to see if we can - * re-use an already existing one or if we have to create a - * new one. - *************************************************************/ - - /* reuse_fresh is TRUE if we are told to use a new connection by force, but - we only acknowledge this option if this is not a re-used connection - already (which happens due to follow-location or during a HTTP - authentication phase). */ - if(data->set.reuse_fresh && !data->state.this_is_a_follow) - reuse = FALSE; - else - reuse = ConnectionExists(data, conn, &conn_temp); - - if(reuse) { - /* - * We already have a connection for this, we got the former connection - * in the conn_temp variable and thus we need to cleanup the one we - * just allocated before we can move along and use the previously - * existing one. - */ - reuse_conn(conn, conn_temp); - free(conn); /* we don't need this anymore */ - conn = conn_temp; - *in_connect = conn; - infof(data, "Re-using existing connection! (#%ld) with host %s\n", - conn->connectindex, - conn->proxy.name?conn->proxy.dispname:conn->host.dispname); - } - else { - /* - * This is a brand new connection, so let's store it in the connection - * cache of ours! - */ - ConnectionStore(data, conn); - } - - /* - * Setup whatever necessary for a resumed transfer - */ - result = setup_range(data); - if(result) - return result; - - /* Continue connectdata initialization here. */ - - /* - * Inherit the proper values from the urldata struct AFTER we have arranged - * the persistent connection stuff - */ - conn->fread_func = data->set.fread_func; - conn->fread_in = data->set.in; - conn->seek_func = data->set.seek_func; - conn->seek_client = data->set.seek_client; - - /************************************************************* - * Resolve the address of the server or proxy - *************************************************************/ - result = resolve_server(data, conn, async); - - return result; -} - -/* setup_conn() is called after the name resolve initiated in - * create_conn() is all done. - * - * setup_conn() also handles reused connections - * - * conn->data MUST already have been setup fine (in create_conn) - */ - -static CURLcode setup_conn(struct connectdata *conn, - bool *protocol_done) -{ - CURLcode result=CURLE_OK; - struct SessionHandle *data = conn->data; - - Curl_pgrsTime(data, TIMER_NAMELOOKUP); - - if(conn->handler->protocol & CURLPROTO_FILE) { - /* There's nothing in this function to setup if we're only doing - a file:// transfer */ - *protocol_done = TRUE; - return result; - } - *protocol_done = FALSE; /* default to not done */ - - /* set proxy_connect_closed to false unconditionally already here since it - is used strictly to provide extra information to a parent function in the - case of proxy CONNECT failures and we must make sure we don't have it - lingering set from a previous invoke */ - conn->bits.proxy_connect_closed = FALSE; - - /* - * Set user-agent. Used for HTTP, but since we can attempt to tunnel - * basically anything through a http proxy we can't limit this based on - * protocol. - */ - if(data->set.str[STRING_USERAGENT]) { - Curl_safefree(conn->allocptr.uagent); - conn->allocptr.uagent = - aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]); - if(!conn->allocptr.uagent) - return CURLE_OUT_OF_MEMORY; - } - - data->req.headerbytecount = 0; - -#ifdef CURL_DO_LINEEND_CONV - data->state.crlf_conversions = 0; /* reset CRLF conversion counter */ -#endif /* CURL_DO_LINEEND_CONV */ - - for(;;) { - /* loop for CURL_SERVER_CLOSED_CONNECTION */ - - if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) { - /* Try to connect only if not already connected */ - bool connected = FALSE; - - result = ConnectPlease(data, conn, &connected); - - if(connected) { - result = Curl_protocol_connect(conn, protocol_done); - if(CURLE_OK == result) - conn->bits.tcpconnect = TRUE; - } - else - conn->bits.tcpconnect = FALSE; - - /* if the connection was closed by the server while exchanging - authentication informations, retry with the new set - authentication information */ - if(conn->bits.proxy_connect_closed) { - /* reset the error buffer */ - if(data->set.errorbuffer) - data->set.errorbuffer[0] = '\0'; - data->state.errorbuf = FALSE; - continue; - } - - if(CURLE_OK != result) - return result; - } - else { - Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */ - Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */ - conn->bits.tcpconnect = TRUE; - *protocol_done = TRUE; - Curl_verboseconnect(conn); - Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]); - } - /* Stop the loop now */ - break; - } - - conn->now = Curl_tvnow(); /* time this *after* the connect is done, we - set this here perhaps a second time */ - -#ifdef __EMX__ - /* - * This check is quite a hack. We're calling _fsetmode to fix the problem - * with fwrite converting newline characters (you get mangled text files, - * and corrupted binary files when you download to stdout and redirect it to - * a file). - */ - - if((data->set.out)->_handle == NULL) { - _fsetmode(stdout, "b"); - } -#endif - - return result; -} - -CURLcode Curl_connect(struct SessionHandle *data, - struct connectdata **in_connect, - bool *asyncp, - bool *protocol_done) -{ - CURLcode code; - - *asyncp = FALSE; /* assume synchronous resolves by default */ - - /* call the stuff that needs to be called */ - code = create_conn(data, in_connect, asyncp); - - if(CURLE_OK == code) { - /* no error */ - if((*in_connect)->send_pipe->size || (*in_connect)->recv_pipe->size) - /* pipelining */ - *protocol_done = TRUE; - else if (!*asyncp) { - /* DNS resolution is done: that's either because this is a reused - connection, in which case DNS was unnecessary, or because DNS - really did finish already (synch resolver/fast async resolve) */ - code = setup_conn(*in_connect, protocol_done); - } - } - - if(code && *in_connect) { - /* We're not allowed to return failure with memory left allocated - in the connectdata struct, free those here */ - Curl_disconnect(*in_connect, FALSE); /* close the connection */ - *in_connect = NULL; /* return a NULL */ - } - - return code; -} - -/* Call this function after Curl_connect() has returned async=TRUE and - then a successful name resolve has been received. - - Note: this function disconnects and frees the conn data in case of - resolve failure */ -CURLcode Curl_async_resolved(struct connectdata *conn, - bool *protocol_done) -{ -#ifdef CURLRES_ASYNCH - CURLcode code; - - if(conn->async.dns) { - conn->dns_entry = conn->async.dns; - conn->async.dns = NULL; - } - - code = setup_conn(conn, protocol_done); - - if(code) - /* We're not allowed to return failure with memory left allocated - in the connectdata struct, free those here */ - Curl_disconnect(conn, FALSE); /* close the connection */ - - return code; -#else - (void)conn; - (void)protocol_done; - return CURLE_OK; -#endif -} - - -CURLcode Curl_done(struct connectdata **connp, - CURLcode status, /* an error if this is called after an - error was detected */ - bool premature) -{ - CURLcode result; - struct connectdata *conn; - struct SessionHandle *data; - - DEBUGASSERT(*connp); - - conn = *connp; - data = conn->data; - - if(conn->bits.done) - /* Stop if Curl_done() has already been called */ - return CURLE_OK; - - Curl_getoff_all_pipelines(data, conn); - - if((conn->send_pipe->size + conn->recv_pipe->size != 0 && - !data->set.reuse_forbid && - !conn->bits.close)) - /* Stop if pipeline is not empty and we do not have to close - connection. */ - return CURLE_OK; - - conn->bits.done = TRUE; /* called just now! */ - - /* Cleanup possible redirect junk */ - if(data->req.newurl) { - free(data->req.newurl); - data->req.newurl = NULL; - } - if(data->req.location) { - free(data->req.location); - data->req.location = NULL; - } - - Curl_async_cancel(conn); - - if(conn->dns_entry) { - Curl_resolv_unlock(data, conn->dns_entry); /* done with this */ - conn->dns_entry = NULL; - } - - /* this calls the protocol-specific function pointer previously set */ - if(conn->handler->done) - result = conn->handler->done(conn, status, premature); - else - result = CURLE_OK; - - Curl_pgrsDone(conn); /* done with the operation */ - - /* if the transfer was completed in a paused state there can be buffered - data left to write and then kill */ - if(data->state.tempwrite) { - free(data->state.tempwrite); - data->state.tempwrite = NULL; - } - - /* if data->set.reuse_forbid is TRUE, it means the libcurl client has - forced us to close this no matter what we think. - - if conn->bits.close is TRUE, it means that the connection should be - closed in spite of all our efforts to be nice, due to protocol - restrictions in our or the server's end - - if premature is TRUE, it means this connection was said to be DONE before - the entire request operation is complete and thus we can't know in what - state it is for re-using, so we're forced to close it. In a perfect world - we can add code that keep track of if we really must close it here or not, - but currently we have no such detail knowledge. - - connectindex == -1 here means that the connection has no spot in the - connection cache and thus we must disconnect it here. - */ - if(data->set.reuse_forbid || conn->bits.close || premature || - (-1 == conn->connectindex)) { - CURLcode res2 = Curl_disconnect(conn, premature); /* close the connection */ - - /* If we had an error already, make sure we return that one. But - if we got a new error, return that. */ - if(!result && res2) - result = res2; - } - else { - ConnectionDone(conn); /* the connection is no longer in use */ - - /* remember the most recently used connection */ - data->state.lastconnect = conn->connectindex; - - infof(data, "Connection #%ld to host %s left intact\n", - conn->connectindex, - conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname); - } - - *connp = NULL; /* to make the caller of this function better detect that - this was either closed or handed over to the connection - cache here, and therefore cannot be used from this point on - */ - - return result; -} - -/* - * do_init() inits the readwrite session. This is inited each time (in the DO - * function before the protocol-specific DO functions are invoked) for a - * transfer, sometimes multiple times on the same SessionHandle. Make sure - * nothing in here depends on stuff that are setup dynamically for the - * transfer. - */ - -static CURLcode do_init(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - struct SingleRequest *k = &data->req; - - conn->bits.done = FALSE; /* Curl_done() is not called yet */ - conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */ - data->state.expect100header = FALSE; - - if(data->set.opt_no_body) - /* in HTTP lingo, no body means using the HEAD request... */ - data->set.httpreq = HTTPREQ_HEAD; - else if(HTTPREQ_HEAD == data->set.httpreq) - /* ... but if unset there really is no perfect method that is the - "opposite" of HEAD but in reality most people probably think GET - then. The important thing is that we can't let it remain HEAD if the - opt_no_body is set FALSE since then we'll behave wrong when getting - HTTP. */ - data->set.httpreq = HTTPREQ_GET; - - /* NB: the content encoding software depends on this initialization */ - Curl_easy_initHandleData(data); - - k->start = Curl_tvnow(); /* start time */ - k->now = k->start; /* current time is now */ - k->header = TRUE; /* assume header */ - - k->bytecount = 0; - - k->buf = data->state.buffer; - k->uploadbuf = data->state.uploadbuffer; - k->hbufp = data->state.headerbuff; - k->ignorebody=FALSE; - - Curl_pgrsTime(data, TIMER_PRETRANSFER); - Curl_speedinit(data); - - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - - return CURLE_OK; -} - -/* - * do_complete is called when the DO actions are complete. - * - * We init chunking and trailer bits to their default values here immediately - * before receiving any header data for the current request in the pipeline. - */ -static void do_complete(struct connectdata *conn) -{ - conn->data->req.chunk=FALSE; - conn->data->req.maxfd = (conn->sockfd>conn->writesockfd? - conn->sockfd:conn->writesockfd)+1; -} - -CURLcode Curl_do(struct connectdata **connp, bool *done) -{ - CURLcode result=CURLE_OK; - struct connectdata *conn = *connp; - struct SessionHandle *data = conn->data; - - /* setup and init stuff before DO starts, in preparing for the transfer */ - do_init(conn); - - if(conn->handler->do_it) { - /* generic protocol-specific function pointer set in curl_connect() */ - result = conn->handler->do_it(conn, done); - - /* This was formerly done in transfer.c, but we better do it here */ - if((CURLE_SEND_ERROR == result) && conn->bits.reuse) { - /* - * If the connection is using an easy handle, call reconnect - * to re-establish the connection. Otherwise, let the multi logic - * figure out how to re-establish the connection. - */ - if(!data->multi) { - result = Curl_reconnect_request(connp); - - if(result == CURLE_OK) { - /* ... finally back to actually retry the DO phase */ - conn = *connp; /* re-assign conn since Curl_reconnect_request - creates a new connection */ - result = conn->handler->do_it(conn, done); - } - } - else - return result; - } - - if((result == CURLE_OK) && *done) - /* do_complete must be called after the protocol-specific DO function */ - do_complete(conn); - } - return result; -} - -CURLcode Curl_do_more(struct connectdata *conn) -{ - CURLcode result=CURLE_OK; - - if(conn->handler->do_more) - result = conn->handler->do_more(conn); - - if(result == CURLE_OK) - /* do_complete must be called after the protocol-specific DO function */ - do_complete(conn); - - return result; -} - -/* Called on connect, and if there's already a protocol-specific struct - allocated for a different connection, this frees it that it can be setup - properly later on. */ -void Curl_reset_reqproto(struct connectdata *conn) -{ - struct SessionHandle *data = conn->data; - if(data->state.proto.generic && data->state.current_conn != conn) { - free(data->state.proto.generic); - data->state.proto.generic = NULL; - } - data->state.current_conn = conn; -} diff --git a/third_party/curl/lib/url.h b/third_party/curl/lib/url.h deleted file mode 100644 index 241dc28c0..000000000 --- a/third_party/curl/lib/url.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef __URL_H -#define __URL_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 /* to make sure we have ap_list */ - -/* - * Prototypes for library-wide functions provided by url.c - */ - -CURLcode Curl_open(struct SessionHandle **curl); -CURLcode Curl_init_userdefined(struct UserDefined *set); -CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, - va_list arg); -CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src); -void Curl_freeset(struct SessionHandle * data); -CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */ -CURLcode Curl_connect(struct SessionHandle *, struct connectdata **, - bool *async, bool *protocol_connect); -CURLcode Curl_async_resolved(struct connectdata *conn, - bool *protocol_connect); -CURLcode Curl_do(struct connectdata **, bool *done); -CURLcode Curl_do_more(struct connectdata *); -CURLcode Curl_done(struct connectdata **, CURLcode, bool premature); -CURLcode Curl_disconnect(struct connectdata *, bool dead_connection); -CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done); -CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done); -CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done); -void Curl_safefree(void *ptr); - -/* create a connection cache */ -struct conncache *Curl_mk_connc(int type, long amount); -/* free a connection cache */ -void Curl_rm_connc(struct conncache *c); -/* Change number of entries of a connection cache */ -CURLcode Curl_ch_connc(struct SessionHandle *data, - struct conncache *c, - long newamount); - -int Curl_protocol_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks); -int Curl_doing_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks); - -bool Curl_isPipeliningEnabled(const struct SessionHandle *handle); -CURLcode Curl_addHandleToPipeline(struct SessionHandle *handle, - struct curl_llist *pipeline); -int Curl_removeHandleFromPipeline(struct SessionHandle *handle, - struct curl_llist *pipeline); -/* remove the specified connection from all (possible) pipelines and related - queues */ -void Curl_getoff_all_pipelines(struct SessionHandle *data, - struct connectdata *conn); - -void Curl_close_connections(struct SessionHandle *data); - -/* Called on connect, and if there's already a protocol-specific struct - allocated for a different connection, this frees it that it can be setup - properly later on. */ -void Curl_reset_reqproto(struct connectdata *conn); - -#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ -#define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi service */ - -CURLcode Curl_connected_proxy(struct connectdata *conn); - -#ifdef CURL_DISABLE_VERBOSE_STRINGS -#define Curl_verboseconnect(x) do { } while (0) -#else -void Curl_verboseconnect(struct connectdata *conn); -#endif - - -#endif diff --git a/third_party/curl/lib/urldata.h b/third_party/curl/lib/urldata.h deleted file mode 100644 index c77cc34da..000000000 --- a/third_party/curl/lib/urldata.h +++ /dev/null @@ -1,1568 +0,0 @@ -#ifndef __URLDATA_H -#define __URLDATA_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -/* This file is for lib internal stuff */ - -#include "setup.h" - -#define PORT_FTP 21 -#define PORT_FTPS 990 -#define PORT_TELNET 23 -#define PORT_HTTP 80 -#define PORT_HTTPS 443 -#define PORT_DICT 2628 -#define PORT_LDAP 389 -#define PORT_LDAPS 636 -#define PORT_TFTP 69 -#define PORT_SSH 22 -#define PORT_IMAP 143 -#define PORT_IMAPS 993 -#define PORT_POP3 110 -#define PORT_POP3S 995 -#define PORT_SMTP 25 -#define PORT_SMTPS 465 /* sometimes called SSMTP */ -#define PORT_RTSP 554 -#define PORT_RTMP 1935 -#define PORT_RTMPT PORT_HTTP -#define PORT_RTMPS PORT_HTTPS -#define PORT_GOPHER 70 - -#define DICT_MATCH "/MATCH:" -#define DICT_MATCH2 "/M:" -#define DICT_MATCH3 "/FIND:" -#define DICT_DEFINE "/DEFINE:" -#define DICT_DEFINE2 "/D:" -#define DICT_DEFINE3 "/LOOKUP:" - -#define CURL_DEFAULT_USER "anonymous" -#define CURL_DEFAULT_PASSWORD "ftp@example.com" - -/* length of longest IPv6 address string including the trailing null */ -#define MAX_IPADR_LEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - -/* Default FTP/IMAP etc response timeout in milliseconds. - Symbian OS panics when given a timeout much greater than 1/2 hour. -*/ -#define RESP_TIMEOUT (1800*1000) - -#include "cookie.h" -#include "formdata.h" - -#ifdef USE_SSLEAY -#ifdef USE_OPENSSL -#include "openssl/rsa.h" -#include "openssl/crypto.h" -#include "openssl/x509.h" -#include "openssl/pem.h" -#include "openssl/ssl.h" -#include "openssl/err.h" -#ifdef HAVE_OPENSSL_ENGINE_H -#include -#endif -#ifdef HAVE_OPENSSL_PKCS12_H -#include -#endif -#else /* SSLeay-style includes */ -#include "rsa.h" -#include "crypto.h" -#include "x509.h" -#include "pem.h" -#include "ssl.h" -#include "err.h" -#ifdef HAVE_OPENSSL_ENGINE_H -#include -#endif -#ifdef HAVE_OPENSSL_PKCS12_H -#include -#endif -#endif /* USE_OPENSSL */ -#ifdef USE_GNUTLS -#error Configuration error; cannot use GnuTLS *and* OpenSSL. -#endif -#endif /* USE_SSLEAY */ - -#ifdef USE_GNUTLS -#include -#endif - -#ifdef USE_POLARSSL -#include -#include -#endif - -#ifdef USE_CYASSL -#include -#endif - -#ifdef USE_NSS -#include -#include -#endif - -#ifdef USE_QSOSSL -#include -#endif - -#ifdef USE_AXTLS -#include -#undef malloc -#undef calloc -#undef realloc -#endif /* USE_AXTLS */ - -#ifdef HAVE_NETINET_IN_H -#include -#endif - -#include "timeval.h" - -#ifdef HAVE_ZLIB_H -#include /* for content-encoding */ -#ifdef __SYMBIAN32__ -/* zlib pollutes the namespace with this definition */ -#undef WIN32 -#endif -#endif - -#ifdef USE_ARES -# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ - (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) -# define CARES_STATICLIB -# endif -# include -#endif - -#include - -#include "http_chunks.h" /* for the structs and enum stuff */ -#include "hostip.h" -#include "hash.h" -#include "splay.h" - -#include "imap.h" -#include "pop3.h" -#include "smtp.h" -#include "ftp.h" -#include "file.h" -#include "ssh.h" -#include "http.h" -#include "rtsp.h" -#include "wildcard.h" - -#ifdef HAVE_GSSAPI -# ifdef HAVE_GSSGNU -# include -# elif defined HAVE_GSSMIT -# include -# include -# else -# include -# endif -#endif - -#ifdef HAVE_LIBSSH2_H -#include -#include -#endif /* HAVE_LIBSSH2_H */ - -/* Download buffer size, keep it fairly big for speed reasons */ -#undef BUFSIZE -#define BUFSIZE CURL_MAX_WRITE_SIZE - -/* Initial size of the buffer to store headers in, it'll be enlarged in case - of need. */ -#define HEADERSIZE 256 - -#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU - -/* Some convenience macros to get the larger/smaller value out of two given. - We prefix with CURL to prevent name collisions. */ -#define CURLMAX(x,y) ((x)>(y)?(x):(y)) -#define CURLMIN(x,y) ((x)<(y)?(x):(y)) - - -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) -/* Types needed for krb4/5-ftp connections */ -struct krb4buffer { - void *data; - size_t size; - size_t index; - int eof_flag; -}; - -enum protection_level { - PROT_NONE, /* first in list */ - PROT_CLEAR, - PROT_SAFE, - PROT_CONFIDENTIAL, - PROT_PRIVATE, - PROT_CMD, - PROT_LAST /* last in list */ -}; -#endif - -/* enum for the nonblocking SSL connection state machine */ -typedef enum { - ssl_connect_1, - ssl_connect_2, - ssl_connect_2_reading, - ssl_connect_2_writing, - ssl_connect_3, - ssl_connect_done -} ssl_connect_state; - -typedef enum { - ssl_connection_none, - ssl_connection_negotiating, - ssl_connection_complete -} ssl_connection_state; - -/* struct for data related to each SSL connection */ -struct ssl_connect_data { - /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm - but at least asked to or meaning to use it. See 'state' for the exact - current state of the connection. */ - bool use; - ssl_connection_state state; -#ifdef USE_SSLEAY - /* these ones requires specific SSL-types */ - SSL_CTX* ctx; - SSL* handle; - X509* server_cert; - ssl_connect_state connecting_state; -#endif /* USE_SSLEAY */ -#ifdef USE_GNUTLS - gnutls_session session; - gnutls_certificate_credentials cred; -#ifdef USE_TLS_SRP - gnutls_srp_client_credentials srp_client_cred; -#endif - ssl_connect_state connecting_state; -#endif /* USE_GNUTLS */ -#ifdef USE_POLARSSL - havege_state hs; - ssl_context ssl; - ssl_session ssn; - int server_fd; - x509_cert cacert; - x509_cert clicert; - x509_crl crl; - rsa_context rsa; -#endif /* USE_POLARSSL */ -#ifdef USE_CYASSL - SSL_CTX* ctx; - SSL* handle; - ssl_connect_state connecting_state; -#endif /* USE_CYASSL */ -#ifdef USE_NSS - PRFileDesc *handle; - char *client_nickname; - struct SessionHandle *data; -#ifdef HAVE_PK11_CREATEGENERICOBJECT - struct curl_llist *obj_list; -#endif -#endif /* USE_NSS */ -#ifdef USE_QSOSSL - SSLHandle *handle; -#endif /* USE_QSOSSL */ -#ifdef USE_AXTLS - SSL_CTX* ssl_ctx; - SSL* ssl; -#endif /* USE_AXTLS */ -}; - -struct ssl_config_data { - long version; /* what version the client wants to use */ - long certverifyresult; /* result from the certificate verification */ - long verifypeer; /* set TRUE if this is desired */ - long verifyhost; /* 0: no verify - 1: check that CN exists - 2: CN must match hostname */ - char *CApath; /* certificate dir (doesn't work on windows) */ - char *CAfile; /* certificate to verify peer against */ - const char *CRLfile; /* CRL to check certificate revocation */ - const char *issuercert;/* optional issuer certificate filename */ - char *random_file; /* path to file containing "random" data */ - char *egdsocket; /* path to file containing the EGD daemon socket */ - char *cipher_list; /* list of ciphers to use */ - long numsessions; /* SSL session id cache size */ - curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ - void *fsslctxp; /* parameter for call back */ - bool sessionid; /* cache session IDs or not */ - bool certinfo; /* gather lots of certificate info */ - -#ifdef USE_TLS_SRP - char *username; /* TLS username (for, e.g., SRP) */ - char *password; /* TLS password (for, e.g., SRP) */ - enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ -#endif -}; - -/* information stored about one single SSL session */ -struct curl_ssl_session { - char *name; /* host name for which this ID was used */ - void *sessionid; /* as returned from the SSL layer */ - size_t idsize; /* if known, otherwise 0 */ - long age; /* just a number, the higher the more recent */ - unsigned short remote_port; /* remote port to connect to */ - struct ssl_config_data ssl_config; /* setup for this session */ -}; - -/* Struct used for Digest challenge-response authentication */ -struct digestdata { - char *nonce; - char *cnonce; - char *realm; - int algo; - bool stale; /* set true for re-negotiation */ - char *opaque; - char *qop; - char *algorithm; - int nc; /* nounce count */ -}; - -typedef enum { - NTLMSTATE_NONE, - NTLMSTATE_TYPE1, - NTLMSTATE_TYPE2, - NTLMSTATE_TYPE3, - NTLMSTATE_LAST -} curlntlm; - -#ifdef USE_WINDOWS_SSPI -#include "curl_sspi.h" -#endif - -#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) -#include -#endif - -/* Struct used for NTLM challenge-response authentication */ -struct ntlmdata { - curlntlm state; -#ifdef USE_WINDOWS_SSPI - CredHandle handle; - CtxtHandle c_handle; - SEC_WINNT_AUTH_IDENTITY identity; - SEC_WINNT_AUTH_IDENTITY *p_identity; - int has_handles; - void *type_2; - int n_type_2; -#else - unsigned int flags; - unsigned char nonce[8]; -#endif -}; - -#ifdef USE_HTTP_NEGOTIATE -struct negotiatedata { - /* when doing Negotiate we first need to receive an auth token and then we - need to send our header */ - enum { GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT } state; - bool gss; /* Whether we're processing GSS-Negotiate or Negotiate */ - const char* protocol; /* "GSS-Negotiate" or "Negotiate" */ -#ifdef HAVE_GSSAPI - OM_uint32 status; - gss_ctx_id_t context; - gss_name_t server_name; - gss_buffer_desc output_token; -#else -#ifdef USE_WINDOWS_SSPI - DWORD status; - CtxtHandle *context; - CredHandle *credentials; - char server_name[1024]; - size_t max_token_length; - BYTE *output_token; - size_t output_token_length; -#endif -#endif -}; -#endif - - -/* - * Boolean values that concerns this connection. - */ -struct ConnectBits { - bool close; /* if set, we close the connection after this request */ - bool reuse; /* if set, this is a re-used connection */ - bool proxy; /* if set, this transfer is done through a proxy - any type */ - bool httpproxy; /* if set, this transfer is done through a http proxy */ - bool user_passwd; /* do we use user+password for this connection? */ - bool proxy_user_passwd; /* user+password for the proxy? */ - bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6 - IP address */ - bool ipv6; /* we communicate with a site using an IPv6 address */ - - bool do_more; /* this is set TRUE if the ->curl_do_more() function is - supposed to be called, after ->curl_do() */ - - bool tcpconnect; /* the TCP layer (or similar) is connected, this is set - the first time on the first connect function call */ - bool protoconnstart;/* the protocol layer has STARTED its operation after - the TCP layer connect */ - - bool retry; /* this connection is about to get closed and then - re-attempted at another connection. */ - bool tunnel_proxy; /* if CONNECT is used to "tunnel" through the proxy. - This is implicit when SSL-protocols are used through - proxies, but can also be enabled explicitly by - apps */ - bool tunnel_connecting; /* TRUE while we're still waiting for a proxy CONNECT - */ - bool authneg; /* TRUE when the auth phase has started, which means - that we are creating a request with an auth header, - but it is not the final request in the auth - negotiation. */ - bool rewindaftersend;/* TRUE when the sending couldn't be stopped even - though it will be discarded. When the whole send - operation is done, we must call the data rewind - callback. */ - bool ftp_use_epsv; /* As set with CURLOPT_FTP_USE_EPSV, but if we find out - EPSV doesn't work we disable it for the forthcoming - requests */ - - bool ftp_use_eprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out - EPRT doesn't work we disable it for the forthcoming - requests */ - bool netrc; /* name+password provided by netrc */ - bool userpwd_in_url; /* name+password found in url */ - - bool done; /* set to FALSE when Curl_do() is called and set to TRUE - when Curl_done() is called, to prevent Curl_done() to - get invoked twice when the multi interface is - used. */ - bool stream_was_rewound; /* Indicates that the stream was rewound after a - request read past the end of its response byte - boundary */ - bool proxy_connect_closed; /* set true if a proxy disconnected the - connection in a CONNECT request with auth, so - that libcurl should reconnect and continue. */ - bool bound; /* set true if bind() has already been done on this socket/ - connection */ - bool type_set; /* type= was used in the URL */ -}; - -struct hostname { - char *rawalloc; /* allocated "raw" version of the name */ - char *encalloc; /* allocated IDN-encoded version of the name */ - char *name; /* name to use internally, might be encoded, might be raw */ - const char *dispname; /* name to display, as 'name' might be encoded */ -}; - -/* - * Flags on the keepon member of the Curl_transfer_keeper - */ - -#define KEEP_NONE 0 -#define KEEP_RECV (1<<0) /* there is or may be data to read */ -#define KEEP_SEND (1<<1) /* there is or may be data to write */ -#define KEEP_RECV_HOLD (1<<2) /* when set, no reading should be done but there - might still be data to read */ -#define KEEP_SEND_HOLD (1<<3) /* when set, no writing should be done but there - might still be data to write */ -#define KEEP_RECV_PAUSE (1<<4) /* reading is paused */ -#define KEEP_SEND_PAUSE (1<<5) /* writing is paused */ - -#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE) -#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE) - - -#ifdef HAVE_LIBZ -typedef enum { - ZLIB_UNINIT, /* uninitialized */ - ZLIB_INIT, /* initialized */ - ZLIB_GZIP_HEADER, /* reading gzip header */ - ZLIB_GZIP_INFLATING, /* inflating gzip stream */ - ZLIB_INIT_GZIP /* initialized in transparent gzip mode */ -} zlibInitState; -#endif - -#ifdef CURLRES_ASYNCH -struct Curl_async { - char *hostname; - int port; - struct Curl_dns_entry *dns; - bool done; /* set TRUE when the lookup is complete */ - int status; /* if done is TRUE, this is the status from the callback */ - void *os_specific; /* 'struct thread_data' for Windows */ - int num_pending; /* number of ares_gethostbyname() requests */ - Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */ -}; -#endif - -#define FIRSTSOCKET 0 -#define SECONDARYSOCKET 1 - -/* These function pointer types are here only to allow easier typecasting - within the source when we need to cast between data pointers (such as NULL) - and function pointers. */ -typedef CURLcode (*Curl_do_more_func)(struct connectdata *); -typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool); - - -enum expect100 { - EXP100_SEND_DATA, /* enough waiting, just send the body now */ - EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */ - EXP100_SENDING_REQUEST, /* still sending the request but will wait for - the 100 header once done with the request */ - EXP100_FAILED /* used on 417 Expectation Failed */ -}; - -/* - * Request specific data in the easy handle (SessionHandle). Previously, - * these members were on the connectdata struct but since a conn struct may - * now be shared between different SessionHandles, we store connection-specific - * data here. This struct only keeps stuff that's interesting for *this* - * request, as it will be cleared between multiple ones - */ -struct SingleRequest { - curl_off_t size; /* -1 if unknown at this point */ - curl_off_t *bytecountp; /* return number of bytes read or NULL */ - - curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch, - -1 means unlimited */ - curl_off_t *writebytecountp; /* return number of bytes written or NULL */ - - curl_off_t bytecount; /* total number of bytes read */ - curl_off_t writebytecount; /* number of bytes written */ - - long headerbytecount; /* only count received headers */ - long deductheadercount; /* this amount of bytes doesn't count when we check - if anything has been transferred at the end of a - connection. We use this counter to make only a - 100 reply (without a following second response - code) result in a CURLE_GOT_NOTHING error code */ - - struct timeval start; /* transfer started at this time */ - struct timeval now; /* current time */ - bool header; /* incoming data has HTTP header */ - enum { - HEADER_NORMAL, /* no bad header at all */ - HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest - is normal data */ - HEADER_ALLBAD /* all was believed to be header */ - } badheader; /* the header was deemed bad and will be - written as body */ - int headerline; /* counts header lines to better track the - first one */ - char *hbufp; /* points at *end* of header line */ - size_t hbuflen; - char *str; /* within buf */ - char *str_start; /* within buf */ - char *end_ptr; /* within buf */ - char *p; /* within headerbuff */ - bool content_range; /* set TRUE if Content-Range: was found */ - curl_off_t offset; /* possible resume offset read from the - Content-Range: header */ - int httpcode; /* error code from the 'HTTP/1.? XXX' or - 'RTSP/1.? XXX' line */ - struct timeval start100; /* time stamp to wait for the 100 code from */ - enum expect100 exp100; /* expect 100 continue state */ - - int auto_decoding; /* What content encoding. sec 3.5, RFC2616. */ - -#define IDENTITY 0 /* No encoding */ -#define DEFLATE 1 /* zlib deflate [RFC 1950 & 1951] */ -#define GZIP 2 /* gzip algorithm [RFC 1952] */ -#define COMPRESS 3 /* Not handled, added for completeness */ - -#ifdef HAVE_LIBZ - zlibInitState zlib_init; /* possible zlib init state; - undefined if Content-Encoding header. */ - z_stream z; /* State structure for zlib. */ -#endif - - time_t timeofdoc; - long bodywrites; - - char *buf; - char *uploadbuf; - curl_socket_t maxfd; - - int keepon; - - bool upload_done; /* set to TRUE when doing chunked transfer-encoding upload - and we're uploading the last chunk */ - - bool ignorebody; /* we read a response-body but we ignore it! */ - bool ignorecl; /* This HTTP response has no body so we ignore the Content- - Length: header */ - - char *location; /* This points to an allocated version of the Location: - header data */ - char *newurl; /* Set to the new URL to use when a redirect or a retry is - wanted */ - - /* 'upload_present' is used to keep a byte counter of how much data there is - still left in the buffer, aimed for upload. */ - ssize_t upload_present; - - /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a - buffer, so the next read should read from where this pointer points to, - and the 'upload_present' contains the number of bytes available at this - position */ - char *upload_fromhere; - - bool chunk; /* if set, this is a chunked transfer-encoding */ - bool upload_chunky; /* set TRUE if we are doing chunked transfer-encoding - on upload */ - bool getheader; /* TRUE if header parsing is wanted */ - - bool forbidchunk; /* used only to explicitly forbid chunk-upload for - specific upload buffers. See readmoredata() in - http.c for details. */ -}; - -/* - * Specific protocol handler. - */ - -struct Curl_handler { - const char * scheme; /* URL scheme name. */ - - /* Complement to setup_connection_internals(). */ - CURLcode (*setup_connection)(struct connectdata *); - - /* These two functions MUST be set to be protocol dependent */ - CURLcode (*do_it)(struct connectdata *, bool *done); - Curl_done_func done; - - /* If the curl_do() function is better made in two halves, this - * curl_do_more() function will be called afterwards, if set. For example - * for doing the FTP stuff after the PASV/PORT command. - */ - Curl_do_more_func do_more; - - /* This function *MAY* be set to a protocol-dependent function that is run - * after the connect() and everything is done, as a step in the connection. - * The 'done' pointer points to a bool that should be set to TRUE if the - * function completes before return. If it doesn't complete, the caller - * should call the curl_connecting() function until it is. - */ - CURLcode (*connect_it)(struct connectdata *, bool *done); - - /* See above. Currently only used for FTP. */ - CURLcode (*connecting)(struct connectdata *, bool *done); - CURLcode (*doing)(struct connectdata *, bool *done); - - /* Called from the multi interface during the PROTOCONNECT phase, and it - should then return a proper fd set */ - int (*proto_getsock)(struct connectdata *conn, - curl_socket_t *socks, - int numsocks); - - /* Called from the multi interface during the DOING phase, and it should - then return a proper fd set */ - int (*doing_getsock)(struct connectdata *conn, - curl_socket_t *socks, - int numsocks); - - /* Called from the multi interface during the DO_DONE, PERFORM and - WAITPERFORM phases, and it should then return a proper fd set. Not setting - this will make libcurl use the generic default one. */ - int (*perform_getsock)(const struct connectdata *conn, - curl_socket_t *socks, - int numsocks); - - /* This function *MAY* be set to a protocol-dependent function that is run - * by the curl_disconnect(), as a step in the disconnection. If the handler - * is called because the connection has been considered dead, dead_connection - * is set to TRUE. - */ - CURLcode (*disconnect)(struct connectdata *, bool dead_connection); - - long defport; /* Default port. */ - unsigned int protocol; /* See CURLPROTO_* */ - unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */ -}; - -#define PROTOPT_NONE 0 /* nothing extra */ -#define PROTOPT_SSL (1<<0) /* uses SSL */ -#define PROTOPT_DUAL (1<<1) /* this protocol uses two connections */ -#define PROTOPT_CLOSEACTION (1<<2) /* need action before socket close */ -/* some protocols will have to call the underlying functions without regard to - what exact state the socket signals. IE even if the socket says "readable", - the send function might need to be called while uploading, or vice versa. -*/ -#define PROTOPT_DIRLOCK (1<<3) -#define PROTOPT_BANPROXY (1<<4) /* not allowed to use proxy */ - - -/* return the count of bytes sent, or -1 on error */ -typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */ - int sockindex, /* socketindex */ - const void *buf, /* data to write */ - size_t len, /* max amount to write */ - CURLcode *err); /* error to return */ - -/* return the count of bytes read, or -1 on error */ -typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ - int sockindex, /* socketindex */ - char *buf, /* store data here */ - size_t len, /* max amount to read */ - CURLcode *err); /* error to return */ - -/* - * The connectdata struct contains all fields and variables that should be - * unique for an entire connection. - */ -struct connectdata { - /* 'data' is the CURRENT SessionHandle using this connection -- take great - caution that this might very well vary between different times this - connection is used! */ - struct SessionHandle *data; - - /* chunk is for HTTP chunked encoding, but is in the general connectdata - struct only because we can do just about any protocol through a HTTP proxy - and a HTTP proxy may in fact respond using chunked encoding */ - struct Curl_chunker chunk; - - bool inuse; /* This is a marker for the connection cache logic. If this is - TRUE this handle is being used by an easy handle and cannot - be used by any other easy handle without careful - consideration (== only for pipelining). */ - - /**** Fields set when inited and not modified again */ - long connectindex; /* what index in the connection cache connects index this - particular struct has */ - - /* 'dns_entry' is the particular host we use. This points to an entry in the - DNS cache and it will not get pruned while locked. It gets unlocked in - Curl_done(). This entry will be NULL if the connection is re-used as then - there is no name resolve done. */ - struct Curl_dns_entry *dns_entry; - - /* 'ip_addr' is the particular IP we connected to. It points to a struct - within the DNS cache, so this pointer is only valid as long as the DNS - cache entry remains locked. It gets unlocked in Curl_done() */ - Curl_addrinfo *ip_addr; - - /* 'ip_addr_str' is the ip_addr data as a human readable string. - It remains available as long as the connection does, which is longer than - the ip_addr itself. */ - char ip_addr_str[MAX_IPADR_LEN]; - - unsigned int scope; /* address scope for IPv6 */ - - int socktype; /* SOCK_STREAM or SOCK_DGRAM */ - - struct hostname host; - struct hostname proxy; - - long port; /* which port to use locally */ - unsigned short remote_port; /* what remote port to connect to, - not the proxy port! */ - - /* 'primary_ip' and 'primary_port' get filled with peer's numerical - ip address and port number whenever an outgoing connection is - *attempted* from the primary socket to a remote address. When more - than one address is tried for a connection these will hold data - for the last attempt. When the connection is actually established - these are updated with data which comes directly from the socket. */ - - char primary_ip[MAX_IPADR_LEN]; - long primary_port; - - /* 'local_ip' and 'local_port' get filled with local's numerical - ip address and port number whenever an outgoing connection is - **established** from the primary socket to a remote address. */ - - char local_ip[MAX_IPADR_LEN]; - long local_port; - - char *user; /* user name string, allocated */ - char *passwd; /* password string, allocated */ - - char *proxyuser; /* proxy user name string, allocated */ - char *proxypasswd; /* proxy password string, allocated */ - curl_proxytype proxytype; /* what kind of proxy that is in use */ - - int httpversion; /* the HTTP version*10 reported by the server */ - int rtspversion; /* the RTSP version*10 reported by the server */ - - struct timeval now; /* "current" time */ - struct timeval created; /* creation time */ - curl_socket_t sock[2]; /* two sockets, the second is used for the data - transfer when doing FTP */ - - Curl_recv *recv[2]; - Curl_send *send[2]; - - struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */ - struct ssl_config_data ssl_config; - - struct ConnectBits bits; /* various state-flags for this connection */ - - /* connecttime: when connect() is called on the current IP address. Used to - be able to track when to move on to try next IP - but only when the multi - interface is used. */ - struct timeval connecttime; - /* The two fields below get set in Curl_connecthost */ - int num_addr; /* number of addresses to try to connect to */ - long timeoutms_per_addr; /* how long time in milliseconds to spend on - trying to connect to each IP address */ - - const struct Curl_handler *handler; /* Connection's protocol handler */ - const struct Curl_handler *given; /* The protocol first given */ - - long ip_version; /* copied from the SessionHandle at creation time */ - - /**** curl_get() phase fields */ - - curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */ - curl_socket_t writesockfd; /* socket to write to, it may very - well be the same we read from. - CURL_SOCKET_BAD disables */ - - /** Dynamicly allocated strings, MUST be freed before this **/ - /** struct is killed. **/ - struct dynamically_allocated_data { - char *proxyuserpwd; - char *uagent; - char *accept_encoding; - char *userpwd; - char *rangeline; - char *ref; - char *host; - char *cookiehost; - char *rtsp_transport; - char *te; /* TE: request header */ - } allocptr; - - int sec_complete; /* if kerberos is enabled for this connection */ -#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) - enum protection_level command_prot; - enum protection_level data_prot; - enum protection_level request_data_prot; - size_t buffer_size; - struct krb4buffer in_buffer; - void *app_data; - const struct Curl_sec_client_mech *mech; - struct sockaddr_in local_addr; -#endif - - /* the two following *_inuse fields are only flags, not counters in any way. - If TRUE it means the channel is in use, and if FALSE it means the channel - is up for grabs by one. */ - - bool readchannel_inuse; /* whether the read channel is in use by an easy - handle */ - bool writechannel_inuse; /* whether the write channel is in use by an easy - handle */ - bool server_supports_pipelining; /* TRUE if server supports pipelining, - set after first response */ - - struct curl_llist *send_pipe; /* List of handles waiting to - send on this pipeline */ - struct curl_llist *recv_pipe; /* List of handles waiting to read - their responses on this pipeline */ - struct curl_llist *pend_pipe; /* List of pending handles on - this pipeline */ - struct curl_llist *done_pipe; /* Handles that are finished, but - still reference this connectdata */ -#define MAX_PIPELINE_LENGTH 5 - - char* master_buffer; /* The master buffer allocated on-demand; - used for pipelining. */ - size_t read_pos; /* Current read position in the master buffer */ - size_t buf_len; /* Length of the buffer?? */ - - - curl_seek_callback seek_func; /* function that seeks the input */ - void *seek_client; /* pointer to pass to the seek() above */ - - /*************** Request - specific items ************/ - - /* previously this was in the urldata struct */ - curl_read_callback fread_func; /* function that reads the input */ - void *fread_in; /* pointer to pass to the fread() above */ - - struct ntlmdata ntlm; /* NTLM differs from other authentication schemes - because it authenticates connections, not - single requests! */ - struct ntlmdata proxyntlm; /* NTLM data for proxy */ - - char syserr_buf [256]; /* buffer for Curl_strerror() */ - -#ifdef CURLRES_ASYNCH - /* data used for the asynch name resolve callback */ - struct Curl_async async; -#endif - - /* These three are used for chunked-encoding trailer support */ - char *trailer; /* allocated buffer to store trailer in */ - int trlMax; /* allocated buffer size */ - int trlPos; /* index of where to store data */ - - union { - struct ftp_conn ftpc; - struct ssh_conn sshc; - struct tftp_state_data *tftpc; - struct imap_conn imapc; - struct pop3_conn pop3c; - struct smtp_conn smtpc; - struct rtsp_conn rtspc; - void *generic; - } proto; - - int cselect_bits; /* bitmask of socket events */ - int waitfor; /* current READ/WRITE bits to wait for */ - -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - int socks5_gssapi_enctype; -#endif - - long verifypeer; - long verifyhost; - - /* When this connection is created, store the conditions for the local end - bind. This is stored before the actual bind and before any connection is - made and will serve the purpose of being used for comparison reasons so - that subsequent bound-requested connections aren't accidentally re-using - wrong connections. */ - char *localdev; - unsigned short localport; - int localportrange; - -}; - -/* The end of connectdata. */ - -/* - * Struct to keep statistical and informational data. - */ -struct PureInfo { - int httpcode; /* Recent HTTP, FTP, or RTSP response code */ - int httpproxycode; /* response code from proxy when received separate */ - int httpversion; /* the http version number X.Y = X*10+Y */ - long filetime; /* If requested, this is might get set. Set to -1 if the time - was unretrievable. We cannot have this of type time_t, - since time_t is unsigned on several platforms such as - OpenVMS. */ - bool timecond; /* set to TRUE if the time condition didn't match, which - thus made the document NOT get fetched */ - long header_size; /* size of read header(s) in bytes */ - long request_size; /* the amount of bytes sent in the request(s) */ - long proxyauthavail; /* what proxy auth types were announced */ - long httpauthavail; /* what host auth types were announced */ - long numconnects; /* how many new connection did libcurl created */ - char *contenttype; /* the content type of the object */ - char *wouldredirect; /* URL this would've been redirected to if asked to */ - - /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip' - and, 'conn_local_port' are copied over from the connectdata struct in - order to allow curl_easy_getinfo() to return this information even when - the session handle is no longer associated with a connection, and also - allow curl_easy_reset() to clear this information from the session handle - without disturbing information which is still alive, and that might be - reused, in the connection cache. */ - - char conn_primary_ip[MAX_IPADR_LEN]; - long conn_primary_port; - - char conn_local_ip[MAX_IPADR_LEN]; - long conn_local_port; - - struct curl_certinfo certs; /* info about the certs, only populated in - OpenSSL builds. Asked for with - CURLOPT_CERTINFO / CURLINFO_CERTINFO */ -}; - - -struct Progress { - long lastshow; /* time() of the last displayed progress meter or NULL to - force redraw at next call */ - curl_off_t size_dl; /* total expected size */ - curl_off_t size_ul; /* total expected size */ - curl_off_t downloaded; /* transferred so far */ - curl_off_t uploaded; /* transferred so far */ - - curl_off_t current_speed; /* uses the currently fastest transfer */ - - bool callback; /* set when progress callback is used */ - int width; /* screen width at download start */ - int flags; /* see progress.h */ - - double timespent; - - curl_off_t dlspeed; - curl_off_t ulspeed; - - double t_nslookup; - double t_connect; - double t_appconnect; - double t_pretransfer; - double t_starttransfer; - double t_redirect; - - struct timeval start; - struct timeval t_startsingle; -#define CURR_TIME (5+1) /* 6 entries for 5 seconds */ - - curl_off_t speeder[ CURR_TIME ]; - struct timeval speeder_time[ CURR_TIME ]; - int speeder_c; -}; - -typedef enum { - HTTPREQ_NONE, /* first in list */ - HTTPREQ_GET, - HTTPREQ_POST, - HTTPREQ_POST_FORM, /* we make a difference internally */ - HTTPREQ_PUT, - HTTPREQ_HEAD, - HTTPREQ_CUSTOM, - HTTPREQ_LAST /* last in list */ -} Curl_HttpReq; - -typedef enum { - RTSPREQ_NONE, /* first in list */ - RTSPREQ_OPTIONS, - RTSPREQ_DESCRIBE, - RTSPREQ_ANNOUNCE, - RTSPREQ_SETUP, - RTSPREQ_PLAY, - RTSPREQ_PAUSE, - RTSPREQ_TEARDOWN, - RTSPREQ_GET_PARAMETER, - RTSPREQ_SET_PARAMETER, - RTSPREQ_RECORD, - RTSPREQ_RECEIVE, - RTSPREQ_LAST /* last in list */ -} Curl_RtspReq; - -/* - * Values that are generated, temporary or calculated internally for a - * "session handle" must be defined within the 'struct UrlState'. This struct - * will be used within the SessionHandle struct. When the 'SessionHandle' - * struct is cloned, this data MUST NOT be copied. - * - * Remember that any "state" information goes globally for the curl handle. - * Session-data MUST be put in the connectdata struct and here. */ -#define MAX_CURL_USER_LENGTH 256 -#define MAX_CURL_PASSWORD_LENGTH 256 -#define MAX_CURL_USER_LENGTH_TXT "255" -#define MAX_CURL_PASSWORD_LENGTH_TXT "255" - -struct auth { - long want; /* Bitmask set to the authentication methods wanted by the app - (with CURLOPT_HTTPAUTH or CURLOPT_PROXYAUTH). */ - long picked; - long avail; /* bitmask for what the server reports to support for this - resource */ - bool done; /* TRUE when the auth phase is done and ready to do the *actual* - request */ - bool multi; /* TRUE if this is not yet authenticated but within the auth - multipass negotiation */ - bool iestyle; /* TRUE if digest should be done IE-style or FALSE if it should - be RFC compliant */ -}; - -struct conncache { - /* 'connects' will be an allocated array with pointers. If the pointer is - set, it holds an allocated connection. */ - struct connectdata **connects; - long num; /* number of entries of the 'connects' array */ - enum { - CONNCACHE_PRIVATE, /* used for an easy handle alone */ - CONNCACHE_MULTI /* shared within a multi handle */ - } type; -}; - - -struct UrlState { - enum { - Curl_if_none, - Curl_if_easy, - Curl_if_multi - } used_interface; - - struct conncache *connc; /* points to the connection cache this handle - uses */ - - /* buffers to store authentication data in, as parsed from input options */ - struct timeval keeps_speed; /* for the progress meter really */ - - long lastconnect; /* index of most recent connect or -1 if undefined */ - - char *headerbuff; /* allocated buffer to store headers in */ - size_t headersize; /* size of the allocation */ - - char buffer[BUFSIZE+1]; /* download buffer */ - char uploadbuffer[BUFSIZE+1]; /* upload buffer */ - curl_off_t current_speed; /* the ProgressShow() funcion sets this, - bytes / second */ - bool this_is_a_follow; /* this is a followed Location: request */ - - char *first_host; /* if set, this should be the host name that we will - sent authorization to, no else. Used to make Location: - following not keep sending user+password... This is - strdup() data. - */ - struct curl_ssl_session *session; /* array of 'numsessions' size */ - long sessionage; /* number of the most recent session */ - char *tempwrite; /* allocated buffer to keep data in when a write - callback returns to make the connection paused */ - size_t tempwritesize; /* size of the 'tempwrite' allocated buffer */ - int tempwritetype; /* type of the 'tempwrite' buffer as a bitmask that is - used with Curl_client_write() */ - char *scratch; /* huge buffer[BUFSIZE*2] when doing upload CRLF replacing */ - bool errorbuf; /* Set to TRUE if the error buffer is already filled in. - This must be set to FALSE every time _easy_perform() is - called. */ - int os_errno; /* filled in with errno whenever an error occurs */ -#ifdef HAVE_SIGNAL - /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */ - void (*prev_signal)(int sig); -#endif - bool allow_port; /* Is set.use_port allowed to take effect or not. This - is always set TRUE when curl_easy_perform() is called. */ - struct digestdata digest; /* state data for host Digest auth */ - struct digestdata proxydigest; /* state data for proxy Digest auth */ - -#ifdef USE_HTTP_NEGOTIATE - struct negotiatedata negotiate; /* state data for host Negotiate auth */ - struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */ -#endif - - struct auth authhost; /* auth details for host */ - struct auth authproxy; /* auth details for proxy */ - - bool authproblem; /* TRUE if there's some problem authenticating */ - -#ifdef USE_ARES - ares_channel areschannel; /* for name resolves */ -#endif - -#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H) - ENGINE *engine; -#endif /* USE_SSLEAY */ - struct timeval expiretime; /* set this with Curl_expire() only */ - struct Curl_tree timenode; /* for the splay stuff */ - struct curl_llist *timeoutlist; /* list of pending timeouts */ - - /* a place to store the most recently set FTP entrypath */ - char *most_recent_ftp_entrypath; - - /* set after initial USER failure, to prevent an authentication loop */ - bool ftp_trying_alternative; - - int httpversion; /* the lowest HTTP version*10 reported by any server - involved in this request */ - bool expect100header; /* TRUE if we added Expect: 100-continue */ - - bool pipe_broke; /* TRUE if the connection we were pipelined on broke - and we need to restart from the beginning */ - -#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \ - !defined(__SYMBIAN32__) -/* do FTP line-end conversions on most platforms */ -#define CURL_DO_LINEEND_CONV - /* for FTP downloads: track CRLF sequences that span blocks */ - bool prev_block_had_trailing_cr; - /* for FTP downloads: how many CRLFs did we converted to LFs? */ - curl_off_t crlf_conversions; -#endif - /* If set to non-NULL, there's a connection in a shared connection cache - that uses this handle so we can't kill this SessionHandle just yet but - must keep it around and add it to the list of handles to kill once all - its connections are gone */ - void *shared_conn; - bool closed; /* set to TRUE when curl_easy_cleanup() has been called on this - handle, but it is kept around as mentioned for - shared_conn */ - char *pathbuffer;/* allocated buffer to store the URL's path part in */ - char *path; /* path to use, points to somewhere within the pathbuffer - area */ - bool slash_removed; /* set TRUE if the 'path' points to a path where the - initial URL slash separator has been taken off */ - bool use_range; - bool rangestringalloc; /* the range string is malloc()'ed */ - - char *range; /* range, if used. See README for detailed specification on - this syntax. */ - curl_off_t resume_from; /* continue [ftp] transfer from here */ - - /* This RTSP state information survives requests and connections */ - long rtsp_next_client_CSeq; /* the session's next client CSeq */ - long rtsp_next_server_CSeq; /* the session's next server CSeq */ - long rtsp_CSeq_recv; /* most recent CSeq received */ - - /* Protocol specific data. - * - ************************************************************************* - * Note that this data will be REMOVED after each request, so anything that - * should be kept/stored on a per-connection basis and thus live for the - * next request on the same connection MUST be put in the connectdata struct! - *************************************************************************/ - union { - struct HTTP *http; - struct HTTP *https; /* alias, just for the sake of being more readable */ - struct RTSP *rtsp; - struct FTP *ftp; - /* void *tftp; not used */ - struct FILEPROTO *file; - void *telnet; /* private for telnet.c-eyes only */ - void *generic; - struct SSHPROTO *ssh; - struct FTP *imap; - struct FTP *pop3; - struct FTP *smtp; - } proto; - /* current user of this SessionHandle instance, or NULL */ - struct connectdata *current_conn; - - /* if true, force SSL connection retry (workaround for certain servers) */ - bool ssl_connect_retry; -}; - - -/* - * This 'DynamicStatic' struct defines dynamic states that actually change - * values in the 'UserDefined' area, which MUST be taken into consideration - * if the UserDefined struct is cloned or similar. You can probably just - * copy these, but each one indicate a special action on other data. - */ - -struct DynamicStatic { - char *url; /* work URL, copied from UserDefined */ - bool url_alloc; /* URL string is malloc()'ed */ - char *referer; /* referer string */ - bool referer_alloc; /* referer sting is malloc()ed */ - struct curl_slist *cookielist; /* list of cookie files set by - curl_easy_setopt(COOKIEFILE) calls */ - struct curl_slist *resolve; /* set to point to the set.resolve list when - this should be dealt with in pretransfer */ -}; - -/* - * This 'UserDefined' struct must only contain data that is set once to go - * for many (perhaps) independent connections. Values that are generated or - * calculated internally for the "session handle" MUST be defined within the - * 'struct UrlState' instead. The only exceptions MUST note the changes in - * the 'DynamicStatic' struct. - * Character pointer fields point to dynamic storage, unless otherwise stated. - */ -struct Curl_one_easy; /* declared and used only in multi.c */ -struct Curl_multi; /* declared and used only in multi.c */ - -enum dupstring { - STRING_CERT, /* client certificate file name */ - STRING_CERT_TYPE, /* format for certificate (default: PEM)*/ - STRING_COOKIE, /* HTTP cookie string to send */ - STRING_COOKIEJAR, /* dump all cookies to this file */ - STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */ - STRING_DEVICE, /* local network interface/address to use */ - STRING_ENCODING, /* Accept-Encoding string */ - STRING_FTP_ACCOUNT, /* ftp account data */ - STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */ - STRING_FTPPORT, /* port to send with the FTP PORT command */ - STRING_KEY, /* private key file name */ - STRING_KEY_PASSWD, /* plain text private key password */ - STRING_KEY_TYPE, /* format for private key (default: PEM) */ - STRING_KRB_LEVEL, /* krb security level */ - STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find - $HOME/.netrc */ - STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ - STRING_PROXY, /* proxy to use */ - STRING_SET_RANGE, /* range, if used */ - STRING_SET_REFERER, /* custom string for the HTTP referer field */ - STRING_SET_URL, /* what original URL to work on */ - STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */ - STRING_SSL_CAFILE, /* certificate file to verify peer against */ - STRING_SSL_CIPHER_LIST, /* list of ciphers to use */ - STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */ - STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */ - STRING_USERAGENT, /* User-Agent string */ - STRING_SSL_CRLFILE, /* crl file to check certificate */ - STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */ - STRING_USERNAME, /* , if used */ - STRING_PASSWORD, /* , if used */ - STRING_PROXYUSERNAME, /* Proxy , if used */ - STRING_PROXYPASSWORD, /* Proxy , if used */ - STRING_NOPROXY, /* List of hosts which should not use the proxy, if - used */ - STRING_RTSP_SESSION_ID, /* Session ID to use */ - STRING_RTSP_STREAM_URI, /* Stream URI for this request */ - STRING_RTSP_TRANSPORT, /* Transport for this session */ -#ifdef USE_LIBSSH2 - STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */ - STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */ - STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */ - STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */ -#endif -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - STRING_SOCKS5_GSSAPI_SERVICE, /* GSSAPI service name */ -#endif - STRING_MAIL_FROM, - -#ifdef USE_TLS_SRP - STRING_TLSAUTH_USERNAME, /* TLS auth */ - STRING_TLSAUTH_PASSWORD, /* TLS auth */ -#endif - - /* -- end of strings -- */ - STRING_LAST /* not used, just an end-of-list marker */ -}; - -struct UserDefined { - FILE *err; /* the stderr user data goes here */ - void *debugdata; /* the data that will be passed to fdebug */ - char *errorbuffer; /* (Static) store failure messages in here */ - long proxyport; /* If non-zero, use this port number by default. If the - proxy string features a ":[port]" that one will override - this. */ - void *out; /* the fetched file goes here */ - void *in; /* the uploaded file is read from here */ - void *writeheader; /* write the header to this if non-NULL */ - void *rtp_out; /* write RTP to this if non-NULL */ - long use_port; /* which port to use (when not using default) */ - long httpauth; /* what kind of HTTP authentication to use (bitmask) */ - long proxyauth; /* what kind of proxy authentication to use (bitmask) */ - long followlocation; /* as in HTTP Location: */ - long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1 - for infinity */ - bool post301; /* Obey RFC 2616/10.3.2 and keep POSTs as POSTs after a - 301 */ - bool post302; /* keep POSTs as POSTs after a 302 */ - bool free_referer; /* set TRUE if 'referer' points to a string we - allocated */ - void *postfields; /* if POST, set the fields' values here */ - curl_seek_callback seek_func; /* function that seeks the input */ - curl_off_t postfieldsize; /* if POST, this might have a size to use instead - of strlen(), and then the data *may* be binary - (contain zero bytes) */ - unsigned short localport; /* local port number to bind to */ - int localportrange; /* number of additional port numbers to test in case the - 'localport' one can't be bind()ed */ - curl_write_callback fwrite_func; /* function that stores the output */ - curl_write_callback fwrite_header; /* function that stores headers */ - curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */ - curl_read_callback fread_func; /* function that reads the input */ - int is_fread_set; /* boolean, has read callback been set to non-NULL? */ - int is_fwrite_set; /* boolean, has write callback been set to non-NULL? */ - curl_progress_callback fprogress; /* function for progress information */ - curl_debug_callback fdebug; /* function that write informational data */ - curl_ioctl_callback ioctl_func; /* function for I/O control */ - curl_sockopt_callback fsockopt; /* function for setting socket options */ - void *sockopt_client; /* pointer to pass to the socket options callback */ - curl_opensocket_callback fopensocket; /* function for checking/translating - the address and opening the socket */ - void* opensocket_client; - - void *seek_client; /* pointer to pass to the seek callback */ - /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */ - /* function to convert from the network encoding: */ - curl_conv_callback convfromnetwork; - /* function to convert to the network encoding: */ - curl_conv_callback convtonetwork; - /* function to convert from UTF-8 encoding: */ - curl_conv_callback convfromutf8; - - void *progress_client; /* pointer to pass to the progress callback */ - void *ioctl_client; /* pointer to pass to the ioctl callback */ - long timeout; /* in milliseconds, 0 means no timeout */ - long connecttimeout; /* in milliseconds, 0 means no timeout */ - long server_response_timeout; /* in milliseconds, 0 means no timeout */ - long tftp_blksize ; /* in bytes, 0 means use default */ - curl_off_t infilesize; /* size of file to upload, -1 means unknown */ - long low_speed_limit; /* bytes/second */ - long low_speed_time; /* number of seconds */ - curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */ - curl_off_t max_recv_speed; /* high speed limit in bytes/second for download */ - curl_off_t set_resume_from; /* continue [ftp] transfer from here */ - struct curl_slist *headers; /* linked list of extra headers */ - struct curl_httppost *httppost; /* linked list of POST data */ - bool cookiesession; /* new cookie session? */ - bool crlf; /* convert crlf on ftp upload(?) */ - struct curl_slist *quote; /* after connection is established */ - struct curl_slist *postquote; /* after the transfer */ - struct curl_slist *prequote; /* before the transfer, after type */ - struct curl_slist *source_quote; /* 3rd party quote */ - struct curl_slist *source_prequote; /* in 3rd party transfer mode - before - the transfer on source host */ - struct curl_slist *source_postquote; /* in 3rd party transfer mode - after - the transfer on source host */ - struct curl_slist *telnet_options; /* linked list of telnet options */ - struct curl_slist *resolve; /* list of names to add/remove from - DNS cache */ - curl_TimeCond timecondition; /* kind of time/date comparison */ - time_t timevalue; /* what time to compare with */ - Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ - long httpversion; /* when non-zero, a specific HTTP version requested to - be used in the library's request(s) */ - struct ssl_config_data ssl; /* user defined SSL stuff */ - curl_proxytype proxytype; /* what kind of proxy that is in use */ - long dns_cache_timeout; /* DNS cache timeout */ - long buffer_size; /* size of receive buffer to use */ - void *private_data; /* application-private data */ - - struct Curl_one_easy *one_easy; /* When adding an easy handle to a multi - handle, an internal 'Curl_one_easy' - struct is created and this is a pointer - to the particular struct associated with - this SessionHandle */ - - struct curl_slist *http200aliases; /* linked list of aliases for http200 */ - - long ipver; /* the CURL_IPRESOLVE_* defines in the public header file - 0 - whatever, 1 - v2, 2 - v6 */ - - curl_off_t max_filesize; /* Maximum file size to download */ - - curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */ - - int ftp_create_missing_dirs; /* 1 - create directories that don't exist - 2 - the same but also allow MKD to fail once - */ - - curl_sshkeycallback ssh_keyfunc; /* key matching callback */ - void *ssh_keyfunc_userp; /* custom pointer to callback */ - -/* Here follows boolean settings that define how to behave during - this session. They are STATIC, set by libcurl users or at least initially - and they don't change during operations. */ - - bool printhost; /* printing host name in debug info */ - bool get_filetime; /* get the time and get of the remote file */ - bool tunnel_thru_httpproxy; /* use CONNECT through a HTTP proxy */ - bool prefer_ascii; /* ASCII rather than binary */ - bool ftp_append; /* append, not overwrite, on upload */ - bool ftp_list_only; /* switch FTP command for listing directories */ - bool ftp_use_port; /* use the FTP PORT command */ - bool hide_progress; /* don't use the progress meter */ - bool http_fail_on_error; /* fail on HTTP error codes >= 300 */ - bool http_follow_location; /* follow HTTP redirects */ - bool http_transfer_encoding; /* request compressed HTTP transfer-encoding */ - bool http_disable_hostname_check_before_authentication; - bool include_header; /* include received protocol headers in data output */ - bool http_set_referer; /* is a custom referer used */ - bool http_auto_referer; /* set "correct" referer when following location: */ - bool opt_no_body; /* as set with CURLOPT_NO_BODY */ - bool set_port; /* custom port number used */ - bool upload; /* upload request */ - enum CURL_NETRC_OPTION - use_netrc; /* defined in include/curl.h */ - bool verbose; /* output verbosity */ - bool krb; /* kerberos connection requested */ - bool reuse_forbid; /* forbidden to be reused, close after use */ - bool reuse_fresh; /* do not re-use an existing connection */ - bool ftp_use_epsv; /* if EPSV is to be attempted or not */ - bool ftp_use_eprt; /* if EPRT is to be attempted or not */ - bool ftp_use_pret; /* if PRET is to be used before PASV or not */ - - curl_usessl ftp_ssl; /* if AUTH TLS is to be attempted etc, for FTP or - IMAP or POP3 or others! */ - curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */ - curl_ftpccc ftp_ccc; /* FTP CCC options */ - bool no_signal; /* do not use any signal/alarm handler */ - bool global_dns_cache; /* subject for future removal */ - bool tcp_nodelay; /* whether to enable TCP_NODELAY or not */ - bool ignorecl; /* ignore content length */ - bool ftp_skip_ip; /* skip the IP address the FTP server passes on to - us */ - bool connect_only; /* make connection, let application use the socket */ - long ssh_auth_types; /* allowed SSH auth types */ - bool http_te_skip; /* pass the raw body data to the user, even when - transfer-encoded (chunked, compressed) */ - bool http_ce_skip; /* pass the raw body data to the user, even when - content-encoded (chunked, compressed) */ - long new_file_perms; /* Permissions to use when creating remote files */ - long new_directory_perms; /* Permissions to use when creating remote dirs */ - bool proxy_transfer_mode; /* set transfer mode (;type=) when doing FTP - via an HTTP proxy */ - char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */ - unsigned int scope; /* address scope for IPv6 */ - long allowed_protocols; - long redir_protocols; -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - long socks5_gssapi_nec; /* flag to support nec socks5 server */ -#endif - struct curl_slist *mail_rcpt; /* linked list of mail recipients */ - /* Common RTSP header options */ - Curl_RtspReq rtspreq; /* RTSP request type */ - long rtspversion; /* like httpversion, for RTSP */ - bool wildcardmatch; /* enable wildcard matching */ - curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer starts */ - curl_chunk_end_callback chunk_end; /* called after part transferring - stopped */ - curl_fnmatch_callback fnmatch; /* callback to decide which file corresponds - to pattern (e.g. if WILDCARDMATCH is on) */ - void *fnmatch_data; -}; - -struct Names { - struct curl_hash *hostcache; - enum { - HCACHE_NONE, /* not pointing to anything */ - HCACHE_PRIVATE, /* points to our own */ - HCACHE_GLOBAL, /* points to the (shrug) global one */ - HCACHE_MULTI, /* points to a shared one in the multi handle */ - HCACHE_SHARED /* points to a shared one in a shared object */ - } hostcachetype; -}; - -/* - * The 'connectdata' struct MUST have all the connection oriented stuff as we - * may have several simultaneous connections and connection structs in memory. - * - * The 'struct UserDefined' must only contain data that is set once to go for - * many (perhaps) independent connections. Values that are generated or - * calculated internally for the "session handle" must be defined within the - * 'struct UrlState' instead. - */ - -struct SessionHandle { - struct Names dns; - struct Curl_multi *multi; /* if non-NULL, points to the multi handle - struct to which this "belongs" */ - struct Curl_one_easy *multi_pos; /* if non-NULL, points to its position - in multi controlling structure to assist - in removal. */ - struct Curl_share *share; /* Share, handles global variable mutexing */ - struct SingleRequest req; /* Request-specific data */ - struct UserDefined set; /* values set by the libcurl user */ - struct DynamicStatic change; /* possibly modified userdefined data */ - struct CookieInfo *cookies; /* the cookies, read from files and servers. - NOTE that the 'cookie' field in the - UserDefined struct defines if the "engine" - is to be used or not. */ - struct Progress progress; /* for all the progress meter data */ - struct UrlState state; /* struct for fields used for state info and - other dynamic purposes */ - struct WildcardData wildcard; /* wildcard download state info */ - struct PureInfo info; /* stats, reports and info data */ -#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) - iconv_t outbound_cd; /* for translating to the network encoding */ - iconv_t inbound_cd; /* for translating from the network encoding */ - iconv_t utf8_cd; /* for translating to UTF8 */ -#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ - unsigned int magic; /* set to a CURLEASY_MAGIC_NUMBER */ -}; - -#define LIBCURL_NAME "libcurl" - -#endif diff --git a/third_party/curl/lib/version.c b/third_party/curl/lib/version.c deleted file mode 100644 index 97dd16395..000000000 --- a/third_party/curl/lib/version.c +++ /dev/null @@ -1,334 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include -#include - -#include -#include "urldata.h" -#include "sslgen.h" - -#define _MPRINTF_REPLACE /* use the internal *printf() functions */ -#include - -#ifdef USE_ARES -#include -#endif - -#ifdef USE_LIBIDN -#include -#endif - -#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) -#include -#endif - -#ifdef USE_LIBRTMP -#include -#endif - -#ifdef USE_LIBSSH2 -#include -#endif - -#ifdef HAVE_LIBSSH2_VERSION -/* get it run-time if possible */ -#define CURL_LIBSSH2_VERSION libssh2_version(0) -#else -/* use build-time if run-time not possible */ -#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION -#endif - -char *curl_version(void) -{ - static char version[200]; - char *ptr=version; - size_t len; - size_t left = sizeof(version); - strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION ); - len = strlen(ptr); - left -= len; - ptr += len; - - if(left > 1) { - len = Curl_ssl_version(ptr + 1, left - 1); - - if(len > 0) { - *ptr = ' '; - left -= ++len; - ptr += len; - } - } - -#ifdef HAVE_LIBZ - len = snprintf(ptr, left, " zlib/%s", zlibVersion()); - left -= len; - ptr += len; -#endif -#ifdef USE_ARES - /* this function is only present in c-ares, not in the original ares */ - len = snprintf(ptr, left, " c-ares/%s", ares_version(NULL)); - left -= len; - ptr += len; -#endif -#ifdef USE_LIBIDN - if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) { - len = snprintf(ptr, left, " libidn/%s", stringprep_check_version(NULL)); - left -= len; - ptr += len; - } -#endif -#ifdef USE_WIN32_IDN - len = snprintf(ptr, left, " IDN-Windows-native"); - left -= len; - ptr += len; -#endif -#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) -#ifdef _LIBICONV_VERSION - len = snprintf(ptr, left, " iconv/%d.%d", - _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255); -#else - /* version unknown */ - len = snprintf(ptr, left, " iconv"); -#endif /* _LIBICONV_VERSION */ - left -= len; - ptr += len; -#endif -#ifdef USE_LIBSSH2 - len = snprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION); - left -= len; - ptr += len; -#endif -#ifdef USE_LIBRTMP - { - char suff[2]; - if (RTMP_LIB_VERSION & 0xff) { - suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1; - suff[1] = '\0'; - } else { - suff[0] = '\0'; - } - len = snprintf(ptr, left, " librtmp/%d.%d%s", - RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff, suff); -/* - If another lib version is added below this one, this code would - also have to do: - - left -= len; - ptr += len; -*/ - } -#endif - - return version; -} - -/* data for curl_version_info - - Keep the list sorted alphabetically. It is also written so that each - protocol line has its own #if line to make things easier on the eye. - */ - -static const char * const protocols[] = { -#ifndef CURL_DISABLE_DICT - "dict", -#endif -#ifndef CURL_DISABLE_FILE - "file", -#endif -#ifndef CURL_DISABLE_FTP - "ftp", -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) - "ftps", -#endif -#ifndef CURL_DISABLE_GOPHER - "gopher", -#endif -#ifndef CURL_DISABLE_HTTP - "http", -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) - "https", -#endif -#ifndef CURL_DISABLE_IMAP - "imap", -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP) - "imaps", -#endif -#ifndef CURL_DISABLE_LDAP - "ldap", -#if !defined(CURL_DISABLE_LDAPS) && \ - ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ - (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) - "ldaps", -#endif -#endif -#ifndef CURL_DISABLE_POP3 - "pop3", -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3) - "pop3s", -#endif -#ifdef USE_LIBRTMP - "rtmp", -#endif -#ifndef CURL_DISABLE_RTSP - "rtsp", -#endif -#ifdef USE_LIBSSH2 - "scp", -#endif -#ifdef USE_LIBSSH2 - "sftp", -#endif -#ifndef CURL_DISABLE_SMTP - "smtp", -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP) - "smtps", -#endif -#ifndef CURL_DISABLE_TELNET - "telnet", -#endif -#ifndef CURL_DISABLE_TFTP - "tftp", -#endif - - NULL -}; - -static curl_version_info_data version_info = { - CURLVERSION_NOW, - LIBCURL_VERSION, - LIBCURL_VERSION_NUM, - OS, /* as found by configure or set by hand at build-time */ - 0 /* features is 0 by default */ -#ifdef ENABLE_IPV6 - | CURL_VERSION_IPV6 -#endif -#ifdef HAVE_KRB4 - | CURL_VERSION_KERBEROS4 -#endif -#ifdef USE_SSL - | CURL_VERSION_SSL -#endif -#ifdef USE_NTLM - | CURL_VERSION_NTLM -#endif -#ifdef USE_WINDOWS_SSPI - | CURL_VERSION_SSPI -#endif -#ifdef HAVE_LIBZ - | CURL_VERSION_LIBZ -#endif -#ifdef USE_HTTP_NEGOTIATE - | CURL_VERSION_GSSNEGOTIATE -#endif -#ifdef DEBUGBUILD - | CURL_VERSION_DEBUG -#endif -#ifdef CURLDEBUG - | CURL_VERSION_CURLDEBUG -#endif -#ifdef CURLRES_ASYNCH - | CURL_VERSION_ASYNCHDNS -#endif -#ifdef HAVE_SPNEGO - | CURL_VERSION_SPNEGO -#endif -#if (CURL_SIZEOF_CURL_OFF_T > 4) && \ - ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) ) - | CURL_VERSION_LARGEFILE -#endif -#if defined(CURL_DOES_CONVERSIONS) - | CURL_VERSION_CONV -#endif -#if defined(USE_TLS_SRP) - | CURL_VERSION_TLSAUTH_SRP -#endif - , - NULL, /* ssl_version */ - 0, /* ssl_version_num, this is kept at zero */ - NULL, /* zlib_version */ - protocols, - NULL, /* c-ares version */ - 0, /* c-ares version numerical */ - NULL, /* libidn version */ - 0, /* iconv version */ - NULL, /* ssh lib version */ -}; - -curl_version_info_data *curl_version_info(CURLversion stamp) -{ -#ifdef USE_LIBSSH2 - static char ssh_buffer[80]; -#endif - -#ifdef USE_SSL - static char ssl_buffer[80]; - Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer)); - version_info.ssl_version = ssl_buffer; -#endif - -#ifdef HAVE_LIBZ - version_info.libz_version = zlibVersion(); - /* libz left NULL if non-existing */ -#endif -#ifdef USE_ARES - { - int aresnum; - version_info.ares = ares_version(&aresnum); - version_info.ares_num = aresnum; - } -#endif -#ifdef USE_LIBIDN - /* This returns a version string if we use the given version or later, - otherwise it returns NULL */ - version_info.libidn = stringprep_check_version(LIBIDN_REQUIRED_VERSION); - if(version_info.libidn) - version_info.features |= CURL_VERSION_IDN; -#elif defined(USE_WIN32_IDN) - version_info.features |= CURL_VERSION_IDN; -#endif - -#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) -#ifdef _LIBICONV_VERSION - version_info.iconv_ver_num = _LIBICONV_VERSION; -#else - /* version unknown */ - version_info.iconv_ver_num = -1; -#endif /* _LIBICONV_VERSION */ -#endif - -#ifdef USE_LIBSSH2 - snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION); - version_info.libssh_version = ssh_buffer; -#endif - - (void)stamp; /* avoid compiler warnings, we don't use this */ - - return &version_info; -} diff --git a/third_party/curl/lib/warnless.c b/third_party/curl/lib/warnless.c deleted file mode 100644 index bc29d28df..000000000 --- a/third_party/curl/lib/warnless.c +++ /dev/null @@ -1,253 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" - -#include "warnless.h" - -#define CURL_MASK_SCHAR 0x7F -#define CURL_MASK_UCHAR 0xFF - -#if (SIZEOF_SHORT == 2) -# define CURL_MASK_SSHORT 0x7FFF -# define CURL_MASK_USHORT 0xFFFF -#elif (SIZEOF_SHORT == 4) -# define CURL_MASK_SSHORT 0x7FFFFFFF -# define CURL_MASK_USHORT 0xFFFFFFFF -#elif (SIZEOF_SHORT == 8) -# define CURL_MASK_SSHORT 0x7FFFFFFFFFFFFFFF -# define CURL_MASK_USHORT 0xFFFFFFFFFFFFFFFF -#else -# error "SIZEOF_SHORT not defined" -#endif - -#if (SIZEOF_INT == 2) -# define CURL_MASK_SINT 0x7FFF -# define CURL_MASK_UINT 0xFFFF -#elif (SIZEOF_INT == 4) -# define CURL_MASK_SINT 0x7FFFFFFF -# define CURL_MASK_UINT 0xFFFFFFFF -#elif (SIZEOF_INT == 8) -# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFF -# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFF -#elif (SIZEOF_INT == 16) -# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -#else -# error "SIZEOF_INT not defined" -#endif - -#if (CURL_SIZEOF_LONG == 2) -# define CURL_MASK_SLONG 0x7FFFL -# define CURL_MASK_ULONG 0xFFFFUL -#elif (CURL_SIZEOF_LONG == 4) -# define CURL_MASK_SLONG 0x7FFFFFFFL -# define CURL_MASK_ULONG 0xFFFFFFFFUL -#elif (CURL_SIZEOF_LONG == 8) -# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFL -# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFUL -#elif (CURL_SIZEOF_LONG == 16) -# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL -# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFUL -#else -# error "CURL_SIZEOF_LONG not defined" -#endif - -#if (CURL_SIZEOF_CURL_OFF_T == 2) -# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFF) -# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFF) -#elif (CURL_SIZEOF_CURL_OFF_T == 4) -# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFF) -# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFF) -#elif (CURL_SIZEOF_CURL_OFF_T == 8) -# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF) -# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFF) -#elif (CURL_SIZEOF_CURL_OFF_T == 16) -# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) -# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) -#else -# error "CURL_SIZEOF_CURL_OFF_T not defined" -#endif - -#if (SIZEOF_SIZE_T == SIZEOF_SHORT) -# define CURL_MASK_SSIZE_T CURL_MASK_SSHORT -# define CURL_MASK_USIZE_T CURL_MASK_USHORT -#elif (SIZEOF_SIZE_T == SIZEOF_INT) -# define CURL_MASK_SSIZE_T CURL_MASK_SINT -# define CURL_MASK_USIZE_T CURL_MASK_UINT -#elif (SIZEOF_SIZE_T == CURL_SIZEOF_LONG) -# define CURL_MASK_SSIZE_T CURL_MASK_SLONG -# define CURL_MASK_USIZE_T CURL_MASK_ULONG -#elif (SIZEOF_SIZE_T == CURL_SIZEOF_CURL_OFF_T) -# define CURL_MASK_SSIZE_T CURL_MASK_SCOFFT -# define CURL_MASK_USIZE_T CURL_MASK_UCOFFT -#else -# error "SIZEOF_SIZE_T not defined" -#endif - -/* -** unsigned long to unsigned short -*/ - -unsigned short curlx_ultous(unsigned long ulnum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - return (unsigned short)(ulnum & (unsigned long) CURL_MASK_USHORT); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - -/* -** unsigned long to unsigned char -*/ - -unsigned char curlx_ultouc(unsigned long ulnum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - return (unsigned char)(ulnum & (unsigned long) CURL_MASK_UCHAR); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - -/* -** unsigned size_t to signed int -*/ - -int curlx_uztosi(size_t uznum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - return (int)(uznum & (size_t) CURL_MASK_SINT); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - -/* -** signed long to signed int -*/ - -int curlx_sltosi(long slnum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - DEBUGASSERT(slnum >= 0); - return (int)(slnum & (long) CURL_MASK_SINT); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - -/* -** signed long to unsigned int -*/ - -unsigned int curlx_sltoui(long slnum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - DEBUGASSERT(slnum >= 0); - return (unsigned int)(slnum & (long) CURL_MASK_UINT); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - -/* -** signed long to unsigned short -*/ - -unsigned short curlx_sltous(long slnum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - DEBUGASSERT(slnum >= 0); - return (unsigned short)(slnum & (long) CURL_MASK_USHORT); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - -/* -** unsigned size_t to signed ssize_t -*/ - -ssize_t curlx_uztosz(size_t uznum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - return (ssize_t)(uznum & (size_t) CURL_MASK_SSIZE_T); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - -/* -** signed curl_off_t to unsigned size_t -*/ - -size_t curlx_sotouz(curl_off_t sonum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - DEBUGASSERT(sonum >= 0); - return (size_t)(sonum & (curl_off_t) CURL_MASK_USIZE_T); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} diff --git a/third_party/curl/lib/warnless.h b/third_party/curl/lib/warnless.h deleted file mode 100644 index 7b9bd3c7f..000000000 --- a/third_party/curl/lib/warnless.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef HEADER_CURL_WARNLESS_H -#define HEADER_CURL_WARNLESS_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ - -unsigned short curlx_ultous(unsigned long ulnum); - -unsigned char curlx_ultouc(unsigned long ulnum); - -int curlx_uztosi(size_t uznum); - -int curlx_sltosi(long slnum); - -unsigned int curlx_sltoui(long slnum); - -unsigned short curlx_sltous(long slnum); - -ssize_t curlx_uztosz(size_t uznum); - -size_t curlx_sotouz(curl_off_t sonum); - -#endif /* HEADER_CURL_WARNLESS_H */ diff --git a/third_party/curl/lib/wildcard.c b/third_party/curl/lib/wildcard.c deleted file mode 100644 index 9fe5d5135..000000000 --- a/third_party/curl/lib/wildcard.c +++ /dev/null @@ -1,76 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 "setup.h" -#include "wildcard.h" -#include "llist.h" -#include "fileinfo.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include - -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - -CURLcode Curl_wildcard_init(struct WildcardData *wc) -{ - DEBUGASSERT(wc->filelist == NULL); - /* now allocate only wc->filelist, everything else - will be allocated if it is needed. */ - wc->filelist = Curl_llist_alloc(Curl_fileinfo_dtor); - if(!wc->filelist) {; - return CURLE_OUT_OF_MEMORY; - } - return CURLE_OK; -} - -void Curl_wildcard_dtor(struct WildcardData *wc) -{ - if(!wc) - return; - - if(wc->tmp_dtor) { - wc->tmp_dtor(wc->tmp); - wc->tmp_dtor = ZERO_NULL; - wc->tmp = NULL; - } - DEBUGASSERT(wc->tmp == NULL); - - if(wc->filelist) { - Curl_llist_destroy(wc->filelist, NULL); - wc->filelist = NULL; - } - - if(wc->path) { - free(wc->path); - wc->path = NULL; - } - - if(wc->pattern) { - free(wc->pattern); - wc->pattern = NULL; - } - - wc->customptr = NULL; - wc->state = CURLWC_INIT; -} diff --git a/third_party/curl/lib/wildcard.h b/third_party/curl/lib/wildcard.h deleted file mode 100644 index 8f732d106..000000000 --- a/third_party/curl/lib/wildcard.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef HEADER_CURL_WILDCARD_H -#define HEADER_CURL_WILDCARD_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 2010, Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under 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 - -/* list of wildcard process states */ -typedef enum { - CURLWC_INIT = 0, - CURLWC_MATCHING, /* library is trying to get list of addresses for - downloading */ - CURLWC_DOWNLOADING, - CURLWC_CLEAN, /* deallocate resources and reset settings */ - CURLWC_SKIP, /* skip over concrete file */ - CURLWC_ERROR, /* error cases */ - CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop in - Curl_perform() will end */ -} curl_wildcard_states; - -typedef void (*curl_wildcard_tmp_dtor)(void *ptr); - -/* struct keeping information about wildcard download process */ -struct WildcardData { - curl_wildcard_states state; - char *path; /* path to the directory, where we trying wildcard-match */ - char *pattern; /* wildcard pattern */ - struct curl_llist *filelist; /* llist with struct Curl_fileinfo */ - void *tmp; /* pointer to protocol specific temporary data */ - curl_wildcard_tmp_dtor tmp_dtor; - void *customptr; /* for CURLOPT_CHUNK_DATA pointer */ -}; - -CURLcode Curl_wildcard_init(struct WildcardData *wc); -void Curl_wildcard_dtor(struct WildcardData *wc); - -struct SessionHandle; - -#endif /* HEADER_CURL_WILDCARD_H */ From bcb05d9b3e914a9ac7ee77a2e74fb55aaa7b3ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Capello?= Date: Wed, 6 Oct 2021 17:49:17 -0300 Subject: [PATCH 22/32] Disable curl executable build --- third_party/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index dad788916..0c0a22bd4 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -45,6 +45,7 @@ endif() if(REQUIRE_CURL AND NOT USE_SHARED_CURL) set(BUILD_RELEASE_DEBUG_DIRS ON BOOL) set(CMAKE_USE_OPENSSL OFF CACHE BOOL "Use OpenSSL code. Experimental") + set(BUILD_CURL_EXE OFF CACHE BOOL "Set to ON to build curl executable.") add_subdirectory(curl) endif() From c117b1b01ffef5d70ad57b69b06d29ff8c745139 Mon Sep 17 00:00:00 2001 From: David Capello Date: Wed, 6 Oct 2021 19:15:42 -0300 Subject: [PATCH 23/32] Simplify Image_set_bytes(): as bytes_size == bytes_needed we don't need to call std::min() --- src/app/script/image_class.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/script/image_class.cpp b/src/app/script/image_class.cpp index cd694194a..857e44e95 100644 --- a/src/app/script/image_class.cpp +++ b/src/app/script/image_class.cpp @@ -498,7 +498,7 @@ int Image_set_bytes(lua_State* L) const char* bytes = lua_tolstring(L, 2, &bytes_size); if (bytes_size == bytes_needed) { - std::memcpy(img->getPixelAddress(0, 0), bytes, std::min(bytes_needed, bytes_size)); + std::memcpy(img->getPixelAddress(0, 0), bytes, bytes_size); } else { lua_pushfstring(L, "Data size does not match: given %d, needed %d.", bytes_size, bytes_needed); From 0ca411690bac831e012cea495a18772ef2c66d21 Mon Sep 17 00:00:00 2001 From: David Capello Date: Wed, 6 Oct 2021 19:17:10 -0300 Subject: [PATCH 24/32] Remove trailing whitespaces --- src/app/script/site_class.cpp | 10 +++++----- src/app/script/websocket_class.cpp | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/app/script/site_class.cpp b/src/app/script/site_class.cpp index bed17f91f..11d7d624e 100644 --- a/src/app/script/site_class.cpp +++ b/src/app/script/site_class.cpp @@ -28,7 +28,7 @@ namespace { class ScriptSiteObserver : public ContextObserver { public: - static ScriptSiteObserver* instance() { + static ScriptSiteObserver* instance() { static ScriptSiteObserver instance; return &instance; } @@ -48,11 +48,11 @@ public: } } - int callbackRef() { - return m_onchangeRef; + int callbackRef() { + return m_onchangeRef; } - void setCallbackRef(int onchangeRef) { + void setCallbackRef(int onchangeRef) { m_onchangeRef = onchangeRef; } @@ -147,7 +147,7 @@ int Site_set_onChange(lua_State* L) obs->setCallbackRef(0); App::instance()->context()->remove_observer(obs); } - + return 0; } diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index e743ffd5e..d57290b98 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -34,7 +34,7 @@ int WebSocket_new(lua_State* L) auto ws = new ix::WebSocket(); push_ptr(L, ws); - + if (lua_istable(L, 1)) { lua_getfield(L, 1, "url"); if (const char* s = lua_tostring(L, -1)) { @@ -164,7 +164,7 @@ int WebSocket_get_url(lua_State* L) return 1; } -const luaL_Reg WebSocket_methods[] = { +const luaL_Reg WebSocket_methods[] = { { "__gc", WebSocket_gc }, { "close", WebSocket_close }, { "connect", WebSocket_connect }, @@ -174,7 +174,7 @@ const luaL_Reg WebSocket_methods[] = { { nullptr, nullptr } }; -const Property WebSocket_properties[] = { +const Property WebSocket_properties[] = { { "url", WebSocket_get_url, nullptr }, { nullptr, nullptr, nullptr } }; @@ -206,4 +206,4 @@ void register_websocket_class(lua_State* L) } } // namespace script -} // namespace app \ No newline at end of file +} // namespace app From 327b38a05dd9a215b02f456f070bddf20a687e28 Mon Sep 17 00:00:00 2001 From: David Capello Date: Wed, 6 Oct 2021 19:29:19 -0300 Subject: [PATCH 25/32] Wrap MESSAGE_TYPE_BINARY with parenthesis (...) --- src/app/script/websocket_class.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index d57290b98..a4b5f8851 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -23,8 +23,9 @@ namespace app { namespace script { namespace { -// additional "enum" value to make message callback simpler -#define MESSAGE_TYPE_BINARY (int)ix::WebSocketMessageType::Fragment + 10 + +// Additional "enum" value to make message callback simpler +#define MESSAGE_TYPE_BINARY ((int)ix::WebSocketMessageType::Fragment + 10) int WebSocket_new(lua_State* L) { From 0249275f8c5229a044233d5b848afb447e3c688a Mon Sep 17 00:00:00 2001 From: David Capello Date: Wed, 6 Oct 2021 19:32:56 -0300 Subject: [PATCH 26/32] [lua] Change MessageType to WebSocketMessageType Just in case to avoid collision or confusion with some kind of future MessageType (e.g. ui::MessageType). There are no plans for this, but we prefer to use WebSocket* prefix. --- src/app/script/websocket_class.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index a4b5f8851..32be7d365 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -194,7 +194,7 @@ void register_websocket_class(lua_State* L) // message type enum lua_newtable(L); lua_pushvalue(L, -1); - lua_setglobal(L, "MessageType"); + lua_setglobal(L, "WebSocketMessageType"); setfield_integer(L, "Text", (int)ix::WebSocketMessageType::Message); setfield_integer(L, "Binary", MESSAGE_TYPE_BINARY); setfield_integer(L, "Open", (int)ix::WebSocketMessageType::Open); From cd342f5630151d9756ee92e8bdbc4ac6741b6529 Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 7 Oct 2021 18:56:39 -0300 Subject: [PATCH 27/32] [lua] Add events handling with Sprite.events & App.events Added a new Events object with :on() and :off() methods to start or stop listening to a specific event respectively. This also allows to add several callbacks for the same event. Replaced the temporal Site.onChange & Sprite.onChange implementations. Related to several issues (enable more possibilities for): #138, #1403, #1949, #2965, #2980 --- laf | 2 +- src/app/CMakeLists.txt | 1 + src/app/active_site_handler.cpp | 11 +- src/app/context.cpp | 29 ++- src/app/context.h | 8 +- src/app/doc.cpp | 8 + src/app/doc_observer.h | 3 +- src/app/doc_undo_observer.h | 11 +- src/app/script/app_object.cpp | 7 + src/app/script/engine.cpp | 2 + src/app/script/engine.h | 4 +- src/app/script/events_class.cpp | 343 ++++++++++++++++++++++++++++++++ src/app/script/site_class.cpp | 69 ------- src/app/script/sprite_class.cpp | 75 +------ src/app/ui_context.cpp | 6 +- src/app/ui_context.h | 4 +- 16 files changed, 412 insertions(+), 171 deletions(-) create mode 100644 src/app/script/events_class.cpp diff --git a/laf b/laf index f58ece824..c9bb18ba9 160000 --- a/laf +++ b/laf @@ -1 +1 @@ -Subproject commit f58ece8248e2ebf6124b28ec49044be913f57292 +Subproject commit c9bb18ba92915f0d9735da25360e4725f767b447 diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 9f2e07549..aa81cb727 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -163,6 +163,7 @@ if(ENABLE_SCRIPTING) script/color_space_class.cpp script/dialog_class.cpp script/engine.cpp + script/events_class.cpp script/frame_class.cpp script/frames_class.cpp script/image_class.cpp diff --git a/src/app/active_site_handler.cpp b/src/app/active_site_handler.cpp index 45320b47e..d29e1841f 100644 --- a/src/app/active_site_handler.cpp +++ b/src/app/active_site_handler.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019-2020 Igara Studio S.A. +// Copyright (C) 2019-2021 Igara Studio S.A. // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -28,10 +28,11 @@ ActiveSiteHandler::~ActiveSiteHandler() void ActiveSiteHandler::addDoc(Doc* doc) { Data data; - if (doc::Layer* layer = doc->sprite()->root()->firstLayer()) - data.layer = layer->id(); - else - data.layer = doc::NullId; + data.layer = doc::NullId; + if (doc->sprite()) { // The sprite can be nullptr in some tests + if (doc::Layer* layer = doc->sprite()->root()->firstLayer()) + data.layer = layer->id(); + } data.frame = 0; m_data.insert(std::make_pair(doc, data)); doc->add_observer(this); diff --git a/src/app/context.cpp b/src/app/context.cpp index 078dd9126..1e5bb74a1 100644 --- a/src/app/context.cpp +++ b/src/app/context.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2020 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -81,7 +81,7 @@ Doc* Context::activeDocument() const void Context::setActiveDocument(Doc* document) { - onSetActiveDocument(document); + onSetActiveDocument(document, true); } void Context::setActiveLayer(doc::Layer* layer) @@ -206,15 +206,19 @@ void Context::onAddDocument(Doc* doc) if (m_activeSiteHandler) m_activeSiteHandler->addDoc(doc); + + notifyActiveSiteChanged(); } void Context::onRemoveDocument(Doc* doc) { - if (doc == m_lastSelectedDoc) - m_lastSelectedDoc = nullptr; - if (m_activeSiteHandler) m_activeSiteHandler->removeDoc(doc); + + if (doc == m_lastSelectedDoc) { + m_lastSelectedDoc = nullptr; + notifyActiveSiteChanged(); + } } void Context::onGetActiveSite(Site* site) const @@ -224,24 +228,33 @@ void Context::onGetActiveSite(Site* site) const activeSiteHandler()->getActiveSiteForDoc(doc, site); } -void Context::onSetActiveDocument(Doc* doc) +void Context::onSetActiveDocument(Doc* doc, bool notify) { m_lastSelectedDoc = doc; + if (notify) + notifyActiveSiteChanged(); } void Context::onSetActiveLayer(doc::Layer* layer) { Doc* newDoc = (layer ? static_cast(layer->sprite()->document()): nullptr); + if (!newDoc) + return; + + activeSiteHandler()->setActiveLayerInDoc(newDoc, layer); + if (newDoc != m_lastSelectedDoc) setActiveDocument(newDoc); - if (newDoc) - activeSiteHandler()->setActiveLayerInDoc(newDoc, layer); + else + notifyActiveSiteChanged(); } void Context::onSetActiveFrame(const doc::frame_t frame) { if (m_lastSelectedDoc) activeSiteHandler()->setActiveFrameInDoc(m_lastSelectedDoc, frame); + + notifyActiveSiteChanged(); } void Context::onSetRange(const DocRange& range) diff --git a/src/app/context.h b/src/app/context.h index e9fe64e48..14cbc6e39 100644 --- a/src/app/context.h +++ b/src/app/context.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2020 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -110,7 +110,7 @@ namespace app { void onRemoveDocument(Doc* doc) override; virtual void onGetActiveSite(Site* site) const; - virtual void onSetActiveDocument(Doc* doc); + virtual void onSetActiveDocument(Doc* doc, bool notify); virtual void onSetActiveLayer(doc::Layer* layer); virtual void onSetActiveFrame(const doc::frame_t frame); virtual void onSetRange(const DocRange& range); @@ -122,10 +122,12 @@ namespace app { private: ActiveSiteHandler* activeSiteHandler() const; + // This must be defined before m_docs because ActiveSiteHandler + // will be an observer of all documents. + mutable std::unique_ptr m_activeSiteHandler; mutable Docs m_docs; ContextFlags m_flags; // Last updated flags. Doc* m_lastSelectedDoc; - mutable std::unique_ptr m_activeSiteHandler; mutable std::unique_ptr m_preferences; DISABLE_COPYING(Context); diff --git a/src/app/doc.cpp b/src/app/doc.cpp index c6168aa35..ee23ff21b 100644 --- a/src/app/doc.cpp +++ b/src/app/doc.cpp @@ -70,6 +70,14 @@ Doc::Doc(Sprite* sprite) Doc::~Doc() { DOC_TRACE("DOC: Deleting", this); + + try { + notify_observers(&DocObserver::onDestroy, this); + } + catch (...) { + LOG(ERROR, "DOC: Exception on DocObserver::onDestroy()\n"); + } + removeFromContext(); } diff --git a/src/app/doc_observer.h b/src/app/doc_observer.h index 7c958c120..052d829fd 100644 --- a/src/app/doc_observer.h +++ b/src/app/doc_observer.h @@ -17,6 +17,7 @@ namespace app { public: virtual ~DocObserver() { } + virtual void onDestroy(Doc* doc) { } virtual void onFileNameChanged(Doc* doc) { } // General update. If an observer receives this event, it's because @@ -80,8 +81,6 @@ namespace app { // Slices virtual void onSliceNameChange(DocEvent& ev) { } - // Called to destroy the observable. (Here you could call "delete this".) - virtual void dispose() { } }; } // namespace app diff --git a/src/app/doc_undo_observer.h b/src/app/doc_undo_observer.h index 9808b55b5..aa7feb836 100644 --- a/src/app/doc_undo_observer.h +++ b/src/app/doc_undo_observer.h @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2021 Igara Studio S.A. // Copyright (C) 2015-2018 David Capello // // This program is distributed under the terms of @@ -19,12 +20,12 @@ namespace app { class DocUndoObserver { public: virtual ~DocUndoObserver() { } - virtual void onAddUndoState(DocUndo* history) = 0; + virtual void onAddUndoState(DocUndo* history) { } virtual void onDeleteUndoState(DocUndo* history, - undo::UndoState* state) = 0; - virtual void onCurrentUndoStateChange(DocUndo* history) = 0; - virtual void onClearRedo(DocUndo* history) = 0; - virtual void onTotalUndoSizeChange(DocUndo* history) = 0; + undo::UndoState* state) { } + virtual void onCurrentUndoStateChange(DocUndo* history) { } + virtual void onClearRedo(DocUndo* history) { } + virtual void onTotalUndoSizeChange(DocUndo* history) { } }; } // namespace app diff --git a/src/app/script/app_object.cpp b/src/app/script/app_object.cpp index 700e452db..e1b5f6651 100644 --- a/src/app/script/app_object.cpp +++ b/src/app/script/app_object.cpp @@ -456,6 +456,12 @@ int App_useTool(lua_State* L) return 0; } +int App_get_events(lua_State* L) +{ + push_app_events(L); + return 1; +} + int App_get_activeSprite(lua_State* L) { app::Context* ctx = App::instance()->context(); @@ -736,6 +742,7 @@ const Property App_properties[] = { { "range", App_get_range, nullptr }, { "isUIAvailable", App_get_isUIAvailable, nullptr }, { "defaultPalette", App_get_defaultPalette, App_set_defaultPalette }, + { "events", App_get_events, nullptr }, { nullptr, nullptr, nullptr } }; diff --git a/src/app/script/engine.cpp b/src/app/script/engine.cpp index cf6c7f7b5..b9034037f 100644 --- a/src/app/script/engine.cpp +++ b/src/app/script/engine.cpp @@ -155,6 +155,7 @@ void register_color_space_class(lua_State* L); #ifdef ENABLE_UI void register_dialog_class(lua_State* L); #endif +void register_events_class(lua_State* L); void register_frame_class(lua_State* L); void register_frames_class(lua_State* L); void register_image_class(lua_State* L); @@ -387,6 +388,7 @@ Engine::Engine() #ifdef ENABLE_UI register_dialog_class(L); #endif + register_events_class(L); register_frame_class(L); register_frames_class(L); register_image_class(L); diff --git a/src/app/script/engine.h b/src/app/script/engine.h index 0c8717643..3c3c0b7f6 100644 --- a/src/app/script/engine.h +++ b/src/app/script/engine.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2020 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -121,6 +121,7 @@ namespace app { EngineDelegate* m_oldDelegate; }; + void push_app_events(lua_State* L); int push_image_iterator_function(lua_State* L, const doc::Image* image, int extraArgIndex); void push_brush(lua_State* L, const doc::BrushRef& brush); void push_cel_image(lua_State* L, doc::Cel* cel); @@ -136,6 +137,7 @@ namespace app { void push_palette(lua_State* L, doc::Palette* palette); void push_plugin(lua_State* L, Extension* ext); void push_sprite_cel(lua_State* L, doc::Cel* cel); + void push_sprite_events(lua_State* L, doc::Sprite* sprite); void push_sprite_frame(lua_State* L, doc::Sprite* sprite, doc::frame_t frame); void push_sprite_frames(lua_State* L, doc::Sprite* sprite); void push_sprite_frames(lua_State* L, doc::Sprite* sprite, const std::vector& frames); diff --git a/src/app/script/events_class.cpp b/src/app/script/events_class.cpp new file mode 100644 index 000000000..1bf254bb2 --- /dev/null +++ b/src/app/script/events_class.cpp @@ -0,0 +1,343 @@ +// Aseprite +// Copyright (C) 2021 Igara Studio S.A. +// +// This program is distributed under the terms of +// the End-User License Agreement for Aseprite. + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "app/app.h" +#include "app/context.h" +#include "app/context_observer.h" +#include "app/doc.h" +#include "app/doc_undo.h" +#include "app/doc_undo_observer.h" +#include "app/script/docobj.h" +#include "app/script/engine.h" +#include "app/script/luacpp.h" +#include "doc/document.h" +#include "doc/sprite.h" + +#include +#include +#include + +namespace app { +namespace script { + +using namespace doc; + +namespace { + +using EventListener = int; + +class AppEvents; +class SpriteEvents; +static std::unique_ptr g_appEvents; +static std::map> g_spriteEvents; + +class Events { +public: + using EventType = int; + + Events() { } + virtual ~Events() { } + Events(const Events&) = delete; + Events& operator=(const Events&) = delete; + + virtual EventType eventType(const char* eventName) const = 0; + + bool hasListener(EventListener callbackRef) const { + for (auto& listeners : m_listeners) { + for (EventListener listener : listeners) { + if (listener == callbackRef) + return true; + } + } + return false; + } + + void add(EventType eventType, EventListener callbackRef) { + if (eventType >= m_listeners.size()) + m_listeners.resize(eventType+1); + + auto& listeners = m_listeners[eventType]; + listeners.push_back(callbackRef); + if (listeners.size() == 1) + onAddFirstListener(eventType); + } + + void remove(EventListener callbackRef) { + for (int i=0; i= m_listeners.size()) + return; + + script::Engine* engine = App::instance()->scriptEngine(); + lua_State* L = engine->luaState(); + + try { + for (EventListener callbackRef : m_listeners[eventType]) { + lua_rawgeti(L, LUA_REGISTRYINDEX, callbackRef); + if (lua_pcall(L, 0, 0, 0)) { + if (const char* s = lua_tostring(L, -1)) + engine->consolePrint(s); + } + } + } + catch (const std::exception& ex) { + engine->consolePrint(ex.what()); + } + } + +private: + virtual void onAddFirstListener(EventType eventType) = 0; + virtual void onRemoveLastListener(EventType eventType) = 0; + + using EventListeners = std::vector; + std::vector m_listeners; +}; + +class AppEvents : public Events + , private ContextObserver { +public: + enum : EventType { Unknown = -1, SiteChange }; + + AppEvents() { + } + + EventType eventType(const char* eventName) const { + if (std::strcmp(eventName, "sitechange") == 0) + return SiteChange; + else + return Unknown; + } + +private: + + void onAddFirstListener(EventType eventType) override { + switch (eventType) { + case SiteChange: { + App::instance()->context()->add_observer(this); + break; + } + } + } + + void onRemoveLastListener(EventType eventType) override { + switch (eventType) { + case SiteChange: { + App::instance()->context()->remove_observer(this); + break; + } + } + } + + // ContextObserver impl + void onActiveSiteChange(const Site& site) override { call(SiteChange); } +}; + +class SpriteEvents : public Events + , public DocUndoObserver + , public DocObserver { +public: + enum : EventType { Unknown = -1, Change }; + + SpriteEvents(const Sprite* sprite) + : m_spriteId(sprite->id()) { + doc()->add_observer(this); + } + + ~SpriteEvents() { + if (m_observingUndo) { + doc()->undoHistory()->remove_observer(this); + m_observingUndo = false; + } + doc()->remove_observer(this); + } + + EventType eventType(const char* eventName) const { + if (std::strcmp(eventName, "change") == 0) + return Change; + else + return Unknown; + } + + // DocObserver impl + void onDestroy(Doc* doc) override { + auto it = g_spriteEvents.find(m_spriteId); + ASSERT(it != g_spriteEvents.end()); + if (it != g_spriteEvents.end()) + g_spriteEvents.erase(it); + } + + // DocUndoObserver impl + void onAddUndoState(DocUndo* history) override { call(Change); } + void onCurrentUndoStateChange(DocUndo* history) override { call(Change); } + +private: + + void onAddFirstListener(EventType eventType) override { + switch (eventType) { + case Change: + ASSERT(!m_observingUndo); + doc()->undoHistory()->add_observer(this); + m_observingUndo = true; + break; + } + } + + void onRemoveLastListener(EventType eventType) override { + switch (eventType) { + case Change: { + if (m_observingUndo) { + doc()->undoHistory()->remove_observer(this); + m_observingUndo = false; + } + break; + } + } + } + + Doc* doc() { + Sprite* sprite = doc::get(m_spriteId); + if (sprite) + return static_cast(sprite->document()); + else + return nullptr; + } + + ObjectId m_spriteId; + bool m_observingUndo = false; +}; + +int Events_on(lua_State* L) +{ + auto evs = get_ptr(L, 1); + const char* eventName = lua_tostring(L, 2); + if (!eventName) + return 0; + + const int type = evs->eventType(eventName); + if (type < 0) + return luaL_error(L, "invalid event name to listen"); + + if (!lua_isfunction(L, 3)) + return luaL_error(L, "second argument must be a function"); + + // Copy the callback function to add it to the global registry + lua_pushvalue(L, 3); + int callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); + evs->add(type, callbackRef); + + // Return the callback ref (this is an EventListener easier to use + // in Events_off()) + lua_pushinteger(L, callbackRef); + return 1; +} + +int Events_off(lua_State* L) +{ + auto evs = get_ptr(L, 1); + int callbackRef = LUA_REFNIL; + + // Remove by listener value + if (lua_isinteger(L, 2)) { + callbackRef = lua_tointeger(L, 2); + } + // Remove by function reference + else if (lua_isfunction(L, 2)) { + lua_pushnil(L); + while (lua_next(L, LUA_REGISTRYINDEX) != 0) { + if (lua_isnumber(L, -2) && + lua_isfunction(L, -1)) { + int i = lua_tointeger(L, -2); + if (// Compare value=function in 2nd argument + lua_compare(L, -1, 2, LUA_OPEQ) && + // Check that this Events contain this reference + evs->hasListener(i)) { + callbackRef = i; + lua_pop(L, 2); // Pop value and key + break; + } + } + lua_pop(L, 1); // Pop the value, leave the key for next lua_next() + } + } + else { + return luaL_error(L, "first argument must be a function or a EventListener"); + } + + if (callbackRef != LUA_REFNIL) { + evs->remove(callbackRef); + luaL_unref(L, LUA_REGISTRYINDEX, callbackRef); + } + return 0; +} + +// We don't need a __gc (to call ~Events()), because Events instances +// will be deleted when the Sprite is deleted or on App Exit +const luaL_Reg Events_methods[] = { + { "on", Events_on }, + { "off", Events_off }, + { nullptr, nullptr } +}; + +} // anonymous namespace + +DEF_MTNAME(Events); + +void register_events_class(lua_State* L) +{ + REG_CLASS(L, Events); +} + +void push_app_events(lua_State* L) +{ + if (!g_appEvents) { + App::instance()->Exit.connect([]{ g_appEvents.reset(); }); + g_appEvents.reset(new AppEvents); + } + push_ptr(L, g_appEvents.get()); +} + +void push_sprite_events(lua_State* L, Sprite* sprite) +{ + ASSERT(sprite); + + SpriteEvents* spriteEvents; + + auto it = g_spriteEvents.find(sprite->id()); + if (it != g_spriteEvents.end()) + spriteEvents = it->second.get(); + else { + spriteEvents = new SpriteEvents(sprite); + g_spriteEvents[sprite->id()].reset(spriteEvents); + } + + push_ptr(L, spriteEvents); +} + +} // namespace script +} // namespace app diff --git a/src/app/script/site_class.cpp b/src/app/script/site_class.cpp index 11d7d624e..466ae8ec6 100644 --- a/src/app/script/site_class.cpp +++ b/src/app/script/site_class.cpp @@ -26,47 +26,6 @@ namespace script { namespace { -class ScriptSiteObserver : public ContextObserver { -public: - static ScriptSiteObserver* instance() { - static ScriptSiteObserver instance; - return &instance; - } - - void onActiveSiteChange(const Site& site) { - if (m_onchangeRef == 0) - return; - - script::Engine* engine = App::instance()->scriptEngine(); - lua_State* L = engine->luaState(); - - lua_rawgeti(L, LUA_REGISTRYINDEX, m_onchangeRef); - if (lua_pcall(L, 0, 0, 0)) { - if (const char* s = lua_tostring(L, -1)) { - Console().printf("Error: %s", s); - } - } - } - - int callbackRef() { - return m_onchangeRef; - } - - void setCallbackRef(int onchangeRef) { - m_onchangeRef = onchangeRef; - } - -private: - ScriptSiteObserver() - : ContextObserver(), - m_onchangeRef(0) - { } - - ~ScriptSiteObserver() { } - - int m_onchangeRef; -}; - int Site_get_sprite(lua_State* L) { auto site = get_obj(L, 1); @@ -124,33 +83,6 @@ int Site_get_image(lua_State* L) return 1; } -int Site_get_onChange(lua_State* L) -{ - lua_rawgeti(L, LUA_REGISTRYINDEX, ScriptSiteObserver::instance()->callbackRef()); - return 1; -} - -int Site_set_onChange(lua_State* L) -{ - auto site = get_obj(L, 1); - auto obs = ScriptSiteObserver::instance(); - - if (lua_isfunction(L, 2)) { - int onchangeRef = luaL_ref(L, LUA_REGISTRYINDEX); - if (!obs->callbackRef()) { - App::instance()->context()->add_observer(obs); - } - obs->setCallbackRef(onchangeRef); - } - else if (obs->callbackRef()) { - luaL_unref(L, LUA_REGISTRYINDEX, obs->callbackRef()); - obs->setCallbackRef(0); - App::instance()->context()->remove_observer(obs); - } - - return 0; -} - const luaL_Reg Site_methods[] = { { nullptr, nullptr } }; @@ -162,7 +94,6 @@ const Property Site_properties[] = { { "frame", Site_get_frame, nullptr }, { "frameNumber", Site_get_frameNumber, nullptr }, { "image", Site_get_image, nullptr }, - { "onChange", Site_get_onChange, Site_set_onChange }, { nullptr, nullptr, nullptr } }; diff --git a/src/app/script/sprite_class.cpp b/src/app/script/sprite_class.cpp index cfcdbdd5f..e2db05306 100644 --- a/src/app/script/sprite_class.cpp +++ b/src/app/script/sprite_class.cpp @@ -59,41 +59,6 @@ namespace app { namespace script { namespace { -// in lua, observers become `Sprite.onChange` -class ScriptDocObserver : public DocUndoObserver { -public: - ScriptDocObserver(int callbackRef) - : DocUndoObserver(), - m_callbackRef(callbackRef) - { } - - void onAddUndoState(DocUndo* history) { callback(); } - void onDeleteUndoState(DocUndo* history, undo::UndoState* state) { } - void onCurrentUndoStateChange(DocUndo* history) { callback(); } - void onClearRedo(DocUndo* history) { } - void onTotalUndoSizeChange(DocUndo* history) { } - - int callbackRef() { return m_callbackRef; } - void setCallbackRef(int callbackRef) { m_callbackRef = callbackRef; } - -private: - void callback() { - script::Engine* engine = App::instance()->scriptEngine(); - lua_State* L = engine->luaState(); - - lua_rawgeti(L, LUA_REGISTRYINDEX, m_callbackRef); - if (lua_pcall(L, 0, 0, 0)) { - if (const char* s = lua_tostring(L, -1)) { - Console().printf("Error: %s", s); - } - } - } - - int m_callbackRef; -}; - -// used to maintain one-to-one relation between sprites and observers -std::map script_observers; int Sprite_new(lua_State* L) { @@ -627,47 +592,13 @@ int Sprite_deleteSlice(lua_State* L) } } -int Sprite_get_onChange(lua_State* L) +int Sprite_get_events(lua_State* L) { auto sprite = get_docobj(L, 1); - ScriptDocObserver* obs = script_observers[sprite->id()]; - - if (obs) { - lua_rawgeti(L, LUA_REGISTRYINDEX, obs->callbackRef()); - } - else { - lua_pushnil(L); - } + push_sprite_events(L, sprite); return 1; } -int Sprite_set_onChange(lua_State* L) -{ - auto sprite = get_docobj(L, 1); - auto doc = static_cast(sprite->document()); - ScriptDocObserver* obs = script_observers[sprite->id()]; - - if (lua_isfunction(L, 2)) { - int callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); - if (obs) { - obs->setCallbackRef(callbackRef); - } - else { - obs = new ScriptDocObserver(callbackRef); - doc->undoHistory()->add_observer(obs); - script_observers[sprite->id()] = obs; - } - } - else if (obs) { - doc->undoHistory()->remove_observer(obs); - script_observers.erase(sprite->id()); - luaL_unref(L, LUA_REGISTRYINDEX, obs->callbackRef()); - delete obs; - } - - return 0; -} - int Sprite_get_filename(lua_State* L) { auto sprite = get_docobj(L, 1); @@ -922,7 +853,7 @@ const Property Sprite_properties[] = { { "bounds", Sprite_get_bounds, nullptr }, { "gridBounds", Sprite_get_gridBounds, Sprite_set_gridBounds }, { "pixelRatio", Sprite_get_pixelRatio, Sprite_set_pixelRatio }, - { "onChange", Sprite_get_onChange, Sprite_set_onChange }, + { "events", Sprite_get_events, nullptr }, { nullptr, nullptr, nullptr } }; diff --git a/src/app/ui_context.cpp b/src/app/ui_context.cpp index e2f1a5438..3270414bc 100644 --- a/src/app/ui_context.cpp +++ b/src/app/ui_context.cpp @@ -134,10 +134,10 @@ void UIContext::setActiveView(DocView* docView) notifyActiveSiteChanged(); } -void UIContext::onSetActiveDocument(Doc* document) +void UIContext::onSetActiveDocument(Doc* document, bool notify) { - bool notify = (lastSelectedDoc() != document); - app::Context::onSetActiveDocument(document); + notify = (notify && lastSelectedDoc() != document); + app::Context::onSetActiveDocument(document, false); DocView* docView = getFirstDocView(document); if (docView) { // The view can be null if we are in --batch mode diff --git a/src/app/ui_context.h b/src/app/ui_context.h index 35472d908..aa4d5eb81 100644 --- a/src/app/ui_context.h +++ b/src/app/ui_context.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019-2020 Igara Studio S.A. +// Copyright (C) 2019-2021 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -53,7 +53,7 @@ namespace app { void onAddDocument(Doc* doc) override; void onRemoveDocument(Doc* doc) override; void onGetActiveSite(Site* site) const override; - void onSetActiveDocument(Doc* doc) override; + void onSetActiveDocument(Doc* doc, bool notify) override; void onSetActiveLayer(doc::Layer* layer) override; void onSetActiveFrame(const doc::frame_t frame) override; void onSetRange(const DocRange& range) override; From 4cd137a6398292ed7b02a4339060eaf72f9c6118 Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 7 Oct 2021 19:10:27 -0300 Subject: [PATCH 28/32] [lua] Add Image.rowStride property now that Image.bytes is available We need to know the specific rowStride to be able to set a proper Image.bytes (bytes size = Image.height * Image.rowStride). --- src/app/script/image_class.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/script/image_class.cpp b/src/app/script/image_class.cpp index 857e44e95..785237852 100644 --- a/src/app/script/image_class.cpp +++ b/src/app/script/image_class.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2020 Igara Studio S.A. +// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2015-2018 David Capello // // This program is distributed under the terms of @@ -484,6 +484,13 @@ int Image_resize(lua_State* L) return 0; } +int Image_get_rowStride(lua_State* L) +{ + const auto obj = get_obj(L, 1); + lua_pushinteger(L, obj->image(L)->getRowStrideSize()); + return 1; +} + int Image_get_bytes(lua_State* L) { const auto img = get_obj(L, 1)->image(L); @@ -562,6 +569,7 @@ const luaL_Reg Image_methods[] = { }; const Property Image_properties[] = { + { "rowStride", Image_get_rowStride, nullptr }, { "bytes", Image_get_bytes, Image_set_bytes }, { "width", Image_get_width, nullptr }, { "height", Image_get_height, nullptr }, From b9241e6d91e53a303690ba657e3236252f5f375f Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 7 Oct 2021 19:34:40 -0300 Subject: [PATCH 29/32] Refactor ask_access() with ResourceType argument --- src/app/script/app_fs_object.cpp | 6 +++--- src/app/script/app_object.cpp | 2 +- src/app/script/engine.h | 7 ------- src/app/script/image_class.cpp | 2 +- src/app/script/palette_class.cpp | 6 +++--- src/app/script/security.cpp | 24 +++++++++++++++--------- src/app/script/security.h | 15 ++++++++++++++- src/app/script/sprite_class.cpp | 4 ++-- 8 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/app/script/app_fs_object.cpp b/src/app/script/app_fs_object.cpp index 1f872377c..0250f4b97 100644 --- a/src/app/script/app_fs_object.cpp +++ b/src/app/script/app_fs_object.cpp @@ -126,7 +126,7 @@ int AppFS_makeDirectory(lua_State* L) return 1; } - if (!ask_access(L, path, FileAccessMode::Write, true)) + if (!ask_access(L, path, FileAccessMode::Full, ResourceType::File)) return luaL_error(L, "the script doesn't have access to create the directory '%s'", path); try { @@ -148,7 +148,7 @@ int AppFS_makeAllDirectories(lua_State* L) return 1; } - if (!ask_access(L, path, FileAccessMode::Write, true)) + if (!ask_access(L, path, FileAccessMode::Write, ResourceType::File)) return luaL_error(L, "the script doesn't have access to create all directories '%s'", path); try { @@ -170,7 +170,7 @@ int AppFS_removeDirectory(lua_State* L) return 1; } - if (!ask_access(L, path, FileAccessMode::Write, true)) + if (!ask_access(L, path, FileAccessMode::Write, ResourceType::File)) return luaL_error(L, "the script doesn't have access to remove the directory '%s'", path); try { diff --git a/src/app/script/app_object.cpp b/src/app/script/app_object.cpp index e1b5f6651..2792cee76 100644 --- a/src/app/script/app_object.cpp +++ b/src/app/script/app_object.cpp @@ -58,7 +58,7 @@ int load_sprite_from_file(lua_State* L, const char* filename, const LoadSpriteFromFileParam param) { std::string absFn = base::get_absolute_path(filename); - if (!ask_access(L, absFn.c_str(), FileAccessMode::Read, true)) + if (!ask_access(L, absFn.c_str(), FileAccessMode::Read, ResourceType::File)) return luaL_error(L, "script doesn't have access to open file %s", absFn.c_str()); diff --git a/src/app/script/engine.h b/src/app/script/engine.h index 3c3c0b7f6..6db3fce94 100644 --- a/src/app/script/engine.h +++ b/src/app/script/engine.h @@ -58,13 +58,6 @@ namespace app { namespace script { - enum class FileAccessMode { - Execute = 1, - Write = 2, - Read = 4, - Full = 7 - }; - class EngineDelegate { public: virtual ~EngineDelegate() { } diff --git a/src/app/script/image_class.cpp b/src/app/script/image_class.cpp index 785237852..cc69bc04b 100644 --- a/src/app/script/image_class.cpp +++ b/src/app/script/image_class.cpp @@ -367,7 +367,7 @@ int Image_saveAs(lua_State* L) return luaL_error(L, "missing filename in Image:saveAs()"); std::string absFn = base::get_absolute_path(fn); - if (!ask_access(L, absFn.c_str(), FileAccessMode::Write, true)) + if (!ask_access(L, absFn.c_str(), FileAccessMode::Write, ResourceType::File)) return luaL_error(L, "script doesn't have access to write file %s", absFn.c_str()); diff --git a/src/app/script/palette_class.cpp b/src/app/script/palette_class.cpp index 05cf8ec8b..d926b2c6f 100644 --- a/src/app/script/palette_class.cpp +++ b/src/app/script/palette_class.cpp @@ -76,7 +76,7 @@ int Palette_new(lua_State* L) std::string absFn = base::get_absolute_path(fromFile); lua_pop(L, 1); - if (!ask_access(L, absFn.c_str(), FileAccessMode::Read, true)) + if (!ask_access(L, absFn.c_str(), FileAccessMode::Read, ResourceType::File)) return luaL_error(L, "script doesn't have access to open file %s", absFn.c_str()); @@ -105,7 +105,7 @@ int Palette_new(lua_State* L) if (!idAndPaths[id].empty()) { std::string absFn = base::get_absolute_path(idAndPaths[id]); - if (!ask_access(L, absFn.c_str(), FileAccessMode::Read, true)) + if (!ask_access(L, absFn.c_str(), FileAccessMode::Read, ResourceType::File)) return luaL_error(L, "script doesn't have access to open file %s", absFn.c_str()); @@ -240,7 +240,7 @@ int Palette_saveAs(lua_State* L) const char* fn = luaL_checkstring(L, 2); if (fn) { std::string absFn = base::get_absolute_path(fn); - if (!ask_access(L, absFn.c_str(), FileAccessMode::Write, true)) + if (!ask_access(L, absFn.c_str(), FileAccessMode::Write, ResourceType::File)) return luaL_error(L, "script doesn't have access to write file %s", absFn.c_str()); save_palette(absFn.c_str(), pal, pal->size()); diff --git a/src/app/script/security.cpp b/src/app/script/security.cpp index d9f077173..ae9170869 100644 --- a/src/app/script/security.cpp +++ b/src/app/script/security.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019 Igara Studio S.A. +// Copyright (C) 2019-2021 Igara Studio S.A. // Copyright (C) 2018 David Capello // // This program is distributed under the terms of @@ -81,7 +81,7 @@ int secure_io_open(lua_State* L) mode = FileAccessMode::Write; } - if (!ask_access(L, absFilename.c_str(), mode, true)) { + if (!ask_access(L, absFilename.c_str(), mode, ResourceType::File)) { return luaL_error(L, "the script doesn't have access to file '%s'", absFilename.c_str()); } @@ -101,7 +101,7 @@ int secure_os_execute(lua_State* L) return 0; const char* cmd = lua_tostring(L, 1); - if (!ask_access(L, cmd, FileAccessMode::Execute, false)) { + if (!ask_access(L, cmd, FileAccessMode::Execute, ResourceType::Command)) { // Stop script return luaL_error(L, "the script doesn't have access to execute the command: '%s'", cmd); @@ -117,7 +117,7 @@ int secure_os_execute(lua_State* L) bool ask_access(lua_State* L, const char* filename, const FileAccessMode mode, - const bool canOpenFile) + const ResourceType resourceType) { #ifdef ENABLE_UI // Ask for permission to open the file @@ -144,10 +144,16 @@ bool ask_access(lua_State* L, app::gen::ScriptAccess dlg; dlg.script()->setText(script); - dlg.fileLabel()->setText( - canOpenFile ? - Strings::script_access_file_label(): - Strings::script_access_command_label()); + + { + std::string label; + switch (resourceType) { + case ResourceType::File: label = Strings::script_access_file_label(); break; + case ResourceType::Command: label = Strings::script_access_command_label(); break; + } + dlg.fileLabel()->setText(label); + } + dlg.file()->setText(filename); dlg.allow()->setText(allowButtonText); dlg.allow()->processMnemonicFromText(); @@ -174,7 +180,7 @@ bool ask_access(lua_State* L, } }); - if (canOpenFile) { + if (resourceType == ResourceType::File) { dlg.file()->Click.connect( [&dlg]{ std::string fn = dlg.file()->text(); diff --git a/src/app/script/security.h b/src/app/script/security.h index 4e7b1741b..9ee283471 100644 --- a/src/app/script/security.h +++ b/src/app/script/security.h @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2021 Igara Studio S.A. // Copyright (C) 2018 David Capello // // This program is distributed under the terms of @@ -17,13 +18,25 @@ namespace app { namespace script { + enum class FileAccessMode { + Execute = 1, + Write = 2, + Read = 4, + Full = 7, + }; + + enum class ResourceType { + File, + Command, + }; + int secure_io_open(lua_State* L); int secure_os_execute(lua_State* L); bool ask_access(lua_State* L, const char* filename, const FileAccessMode mode, - const bool canOpenFile); + const ResourceType resourceType); } // namespace script } // namespace app diff --git a/src/app/script/sprite_class.cpp b/src/app/script/sprite_class.cpp index e2db05306..6b60cbf41 100644 --- a/src/app/script/sprite_class.cpp +++ b/src/app/script/sprite_class.cpp @@ -208,7 +208,7 @@ int Sprite_saveAs_base(lua_State* L, std::string& absFn) appCtx->setActiveDocument(doc); absFn = base::get_absolute_path(fn); - if (!ask_access(L, absFn.c_str(), FileAccessMode::Write, true)) + if (!ask_access(L, absFn.c_str(), FileAccessMode::Write, ResourceType::File)) return luaL_error(L, "script doesn't have access to write file %s", absFn.c_str()); @@ -267,7 +267,7 @@ int Sprite_loadPalette(lua_State* L) const char* fn = luaL_checkstring(L, 2); if (fn && sprite) { std::string absFn = base::get_absolute_path(fn); - if (!ask_access(L, absFn.c_str(), FileAccessMode::Read, true)) + if (!ask_access(L, absFn.c_str(), FileAccessMode::Read, ResourceType::File)) return luaL_error(L, "script doesn't have access to open file %s", absFn.c_str()); From 6e84bb5443da89dc7ccb7c0823b15ef080cd9341 Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 7 Oct 2021 19:37:10 -0300 Subject: [PATCH 30/32] [lua] Ask for permission to open a WebSocket from scripts --- data/strings/en.ini | 2 ++ src/app/script/security.cpp | 3 +++ src/app/script/security.h | 2 ++ src/app/script/websocket_class.cpp | 9 ++++++--- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/data/strings/en.ini b/data/strings/en.ini index fbfa87cda..310bd3397 100644 --- a/data/strings/en.ini +++ b/data/strings/en.ini @@ -1377,11 +1377,13 @@ title = Security script_label = The following script: file_label = wants to access to this file: command_label = wants to execute the following command: +websocket_label = wants to open a WebSocket connection to this URL: dont_show_for_this_access = Don't show this specific alert again for this script dont_show_for_this_script = Give full trust to this script allow_execute_access = &Allow Execute Access allow_write_access = &Allow Write Access allow_read_access = &Allow Read Access +allow_open_conn_access = &Allow to Open Connections give_full_access = Give Script Full &Access stop_script = &Stop Script diff --git a/src/app/script/security.cpp b/src/app/script/security.cpp index ae9170869..477b98860 100644 --- a/src/app/script/security.cpp +++ b/src/app/script/security.cpp @@ -136,6 +136,8 @@ bool ask_access(lua_State* L, return true; std::string allowButtonText = + mode == FileAccessMode::OpenSocket ? + Strings::script_access_allow_open_conn_access(): mode == FileAccessMode::Execute ? Strings::script_access_allow_execute_access(): mode == FileAccessMode::Write ? @@ -150,6 +152,7 @@ bool ask_access(lua_State* L, switch (resourceType) { case ResourceType::File: label = Strings::script_access_file_label(); break; case ResourceType::Command: label = Strings::script_access_command_label(); break; + case ResourceType::WebSocket: label = Strings::script_access_websocket_label(); break; } dlg.fileLabel()->setText(label); } diff --git a/src/app/script/security.h b/src/app/script/security.h index 9ee283471..ffaae2cb0 100644 --- a/src/app/script/security.h +++ b/src/app/script/security.h @@ -23,11 +23,13 @@ namespace script { Write = 2, Read = 4, Full = 7, + OpenSocket = 8, }; enum class ResourceType { File, Command, + WebSocket, }; int secure_io_open(lua_State* L); diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index 32be7d365..9aaab4519 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -1,6 +1,5 @@ // Aseprite -// Copyright (C) 2018-2020 Igara Studio S.A. -// Copyright (C) 2018 David Capello +// Copyright (C) 2021 Igara Studio S.A. // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -13,6 +12,7 @@ #include "app/console.h" #include "app/script/engine.h" #include "app/script/luacpp.h" +#include "app/script/security.h" #include "ui/system.h" #include @@ -39,6 +39,9 @@ int WebSocket_new(lua_State* L) if (lua_istable(L, 1)) { lua_getfield(L, 1, "url"); if (const char* s = lua_tostring(L, -1)) { + if (!ask_access(L, s, FileAccessMode::OpenSocket, ResourceType::WebSocket)) + return luaL_error(L, "the script doesn't have access to create a WebSocket for '%s'", s); + ws->setUrl(s); } lua_pop(L, 1); @@ -180,7 +183,7 @@ const Property WebSocket_properties[] = { { nullptr, nullptr, nullptr } }; -} // namespace { } +} // anonymous namespace using WebSocket = ix::WebSocket; DEF_MTNAME(WebSocket); From 2ddbbf00d610be7a01b4c292a4a3ce306f301e8a Mon Sep 17 00:00:00 2001 From: David Capello Date: Fri, 8 Oct 2021 11:05:16 -0300 Subject: [PATCH 31/32] Fix FileAccessMode::Full security value to include OpenSocket Commented in: https://github.com/aseprite/aseprite/pull/2980#issuecomment-938495522 --- src/app/script/security.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/script/security.h b/src/app/script/security.h index ffaae2cb0..c7f9bf1b0 100644 --- a/src/app/script/security.h +++ b/src/app/script/security.h @@ -22,8 +22,8 @@ namespace script { Execute = 1, Write = 2, Read = 4, - Full = 7, OpenSocket = 8, + Full = Execute | Write | Read | OpenSocket, }; enum class ResourceType { From 318d5ed6a0b4de4bbdf756cbcda9bc3dfb3e4754 Mon Sep 17 00:00:00 2001 From: David Capello Date: Fri, 8 Oct 2021 11:09:47 -0300 Subject: [PATCH 32/32] Avoid removing random values from the Lua registry using Events:off() Fix proposed in: https://github.com/aseprite/aseprite/pull/2980#issuecomment-938495522 --- src/app/script/events_class.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/script/events_class.cpp b/src/app/script/events_class.cpp index 1bf254bb2..f1cd4778c 100644 --- a/src/app/script/events_class.cpp +++ b/src/app/script/events_class.cpp @@ -289,7 +289,10 @@ int Events_off(lua_State* L) return luaL_error(L, "first argument must be a function or a EventListener"); } - if (callbackRef != LUA_REFNIL) { + if (callbackRef != LUA_REFNIL && + // Check that we are removing a listener from this Events and no + // other random value from the Lua registry + evs->hasListener(callbackRef)) { evs->remove(callbackRef); luaL_unref(L, LUA_REGISTRYINDEX, callbackRef); }