diff --git a/src/command_network.cc b/src/command_network.cc index f3756aac..c6188a70 100644 --- a/src/command_network.cc +++ b/src/command_network.cc @@ -243,6 +243,25 @@ apply_scgi(const std::string& arg, int type) { control->scgi()->set_slot_process(rak::mem_fn(control->xmlrpc(), &rpc::XmlRpc::process)); } +void +apply_xmlrpc_dialect(const std::string& arg) { + if (control->xmlrpc() == NULL) + initialize_xmlrpc(); + + int value; + + if (arg == "i8") + value = rpc::XmlRpc::dialect_i8; + else if (arg == "apache") + value = rpc::XmlRpc::dialect_apache; + else if (arg == "generic") + value = rpc::XmlRpc::dialect_generic; + else + value = -1; + + control->xmlrpc()->set_dialect(value); +} + void initialize_command_network() { // core::DownloadList* downloadList = control->core()->download_list(); @@ -299,6 +318,7 @@ initialize_command_network() { ADD_COMMAND_STRING_UN("scgi_port", rak::bind2nd(std::ptr_fun(&apply_scgi), 1)); ADD_COMMAND_STRING_UN("scgi_local", rak::bind2nd(std::ptr_fun(&apply_scgi), 2)); ADD_VARIABLE_BOOL("scgi_dont_route", false); + ADD_COMMAND_STRING_UN("xmlrpc_dialect", std::ptr_fun(&apply_xmlrpc_dialect)); ADD_COMMAND_VALUE_TRI("hash_read_ahead", std::ptr_fun(&apply_hash_read_ahead), rak::ptr_fun(torrent::hash_read_ahead)); ADD_COMMAND_VALUE_TRI("hash_interval", std::ptr_fun(&apply_hash_interval), rak::ptr_fun(torrent::hash_interval)); diff --git a/src/rpc/xmlrpc.cc b/src/rpc/xmlrpc.cc index 0cb970a9..4d36ae6d 100644 --- a/src/rpc/xmlrpc.cc +++ b/src/rpc/xmlrpc.cc @@ -49,10 +49,23 @@ namespace rpc { +// Ugly... +#ifdef XMLRPC_HAVE_I8 +int XmlRpc::m_dialect = dialect_i8; +#else +int XmlRpc::m_dialect = dialect_generic; +#endif + XmlRpc::slot_find_download XmlRpc::m_slotFindDownload; #ifdef HAVE_XMLRPC_C +xmlrpc_value* xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo); +xmlrpc_value* xmlrpc_call_command_d(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo); + +core::Download* xmlrpc_to_download(xmlrpc_env* env, xmlrpc_value* value); +torrent::Object xmlrpc_to_object_d(xmlrpc_env* env, xmlrpc_value* value, core::Download** download); + torrent::Object xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value) { switch (xmlrpc_value_type(value)) { @@ -62,6 +75,14 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value) { return torrent::Object((int64_t)v); +#ifdef XMLRPC_HAVE_I8 + case XMLRPC_TYPE_I8: + long long v2; + xmlrpc_read_i8(env, value, &v2); + + return torrent::Object((int64_t)v2); +#endif + // case XMLRPC_TYPE_BOOL: // case XMLRPC_TYPE_DOUBLE: // case XMLRPC_TYPE_DATETIME: @@ -119,7 +140,7 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value) { } core::Download* -XmlRpc::xmlrpc_to_download(xmlrpc_env* env, xmlrpc_value* value) { +xmlrpc_to_download(xmlrpc_env* env, xmlrpc_value* value) { core::Download* download = NULL; switch (xmlrpc_value_type(value)) { @@ -131,7 +152,7 @@ XmlRpc::xmlrpc_to_download(xmlrpc_env* env, xmlrpc_value* value) { return NULL; if (std::strlen(valueString) != 40 || - (download = m_slotFindDownload(valueString)) == NULL) + (download = XmlRpc::get_slot_find_download()(valueString)) == NULL) xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Could not find info-hash."); // Urgh, seriously? @@ -147,7 +168,7 @@ XmlRpc::xmlrpc_to_download(xmlrpc_env* env, xmlrpc_value* value) { // This should really be cleaned up and support for an array of // downloads should be added. torrent::Object -XmlRpc::xmlrpc_to_object_d(xmlrpc_env* env, xmlrpc_value* value, core::Download** download) { +xmlrpc_to_object_d(xmlrpc_env* env, xmlrpc_value* value, core::Download** download) { switch (xmlrpc_value_type(value)) { case XMLRPC_TYPE_STRING: *download = xmlrpc_to_download(env, value); @@ -223,33 +244,34 @@ XmlRpc::xmlrpc_to_object_d(xmlrpc_env* env, xmlrpc_value* value, core::Download* xmlrpc_value* object_to_xmlrpc(xmlrpc_env* env, const torrent::Object& object) { - xmlrpc_value* result; - xmlrpc_int32 tmpInt; - switch (object.type()) { case torrent::Object::TYPE_VALUE: - tmpInt = object.as_value(); - return xmlrpc_build_value(env, "i", tmpInt); + +#ifdef XMLRPC_HAVE_I8 + if (XmlRpc::dialect() != XmlRpc::dialect_generic) + return xmlrpc_i8_new(env, object.as_value()); +#else + return xmlrpc_int_new(env, object.as_value()); +#endif case torrent::Object::TYPE_STRING: return xmlrpc_string_new(env, object.as_string().c_str()); case torrent::Object::TYPE_LIST: - result = xmlrpc_array_new(env); - + xmlrpc_value* result = xmlrpc_array_new(env); + for (torrent::Object::list_type::const_iterator itr = object.as_list().begin(), last = object.as_list().end(); itr != last; itr++) xmlrpc_array_append_item(env, result, object_to_xmlrpc(env, *itr)); return result; default: - tmpInt = 0; - return xmlrpc_build_value(env, "i", tmpInt); + return xmlrpc_int_new(env, 0); } } xmlrpc_value* -XmlRpc::call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) { +xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) { torrent::Object object = xmlrpc_to_object(env, args); if (env->fault_occurred) @@ -265,7 +287,7 @@ XmlRpc::call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) } xmlrpc_value* -XmlRpc::call_command_d(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) { +xmlrpc_call_command_d(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) { core::Download* download = NULL; torrent::Object object = xmlrpc_to_object_d(env, args, &download); @@ -281,15 +303,23 @@ XmlRpc::call_command_d(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo } } -XmlRpc::XmlRpc() : m_env(new xmlrpc_env) { - xmlrpc_env_init(m_env); - m_registry = xmlrpc_registry_new(m_env); +XmlRpc::XmlRpc() : + m_env(new xmlrpc_env) { + +// #ifdef XMLRPC_HAVE_I8 +// m_dialect(dialect_i8) { +// #else +// m_dialect(dialect_generic) { +// #endif + + xmlrpc_env_init((xmlrpc_env*)m_env); + m_registry = xmlrpc_registry_new((xmlrpc_env*)m_env); } XmlRpc::~XmlRpc() { - xmlrpc_registry_free(m_registry); - xmlrpc_env_clean(m_env); - delete m_env; + xmlrpc_registry_free((xmlrpc_registry*)m_registry); + xmlrpc_env_clean((xmlrpc_env*)m_env); + delete (xmlrpc_env*)m_env; } bool @@ -297,7 +327,7 @@ XmlRpc::process(const char* inBuffer, uint32_t length, slot_write slotWrite) { xmlrpc_env localEnv; xmlrpc_env_init(&localEnv); - xmlrpc_mem_block* memblock = xmlrpc_registry_process_call(&localEnv, m_registry, NULL, inBuffer, length); + xmlrpc_mem_block* memblock = xmlrpc_registry_process_call(&localEnv, (xmlrpc_registry*)m_registry, NULL, inBuffer, length); bool result = slotWrite((const char*)xmlrpc_mem_block_contents(memblock), xmlrpc_mem_block_size(memblock)); @@ -312,8 +342,8 @@ XmlRpc::insert_command(const char* name, const char* parm, const char* doc, bool xmlrpc_env localEnv; xmlrpc_env_init(&localEnv); - xmlrpc_registry_add_method_w_doc(&localEnv, m_registry, NULL, name, - onDownload ? &XmlRpc::call_command_d : &XmlRpc::call_command, + xmlrpc_registry_add_method_w_doc(&localEnv, (xmlrpc_registry*)m_registry, NULL, name, + onDownload ? &xmlrpc_call_command_d : &xmlrpc_call_command, const_cast(name), parm, doc); if (localEnv.fault_occurred) @@ -322,9 +352,40 @@ XmlRpc::insert_command(const char* name, const char* parm, const char* doc, bool xmlrpc_env_clean(&localEnv); } +void +XmlRpc::set_dialect(int dialect) { + xmlrpc_env localEnv; + xmlrpc_env_init(&localEnv); + + switch (dialect) { + case dialect_generic: + break; + +#ifdef XMLRPC_HAVE_I8 + case dialect_i8: + xmlrpc_registry_set_dialect(&localEnv, (xmlrpc_registry*)m_registry, xmlrpc_dialect_i8); + break; + + case dialect_apache: + xmlrpc_registry_set_dialect(&localEnv, (xmlrpc_registry*)m_registry, xmlrpc_dialect_apache); + break; +#endif + + default: + xmlrpc_env_clean(&localEnv); + throw torrent::input_error("Unsupported XMLRPC dialect selected."); + } + + if (localEnv.fault_occurred) + throw torrent::input_error("Unsupported XMLRPC dialect selected."); + + xmlrpc_env_clean(&localEnv); + m_dialect = dialect; +} + #else -XmlRpc::XmlRpc() { throw torrent::resource_error("XMLRPC not supported."); } +XmlRpc::XmlRpc() : m_dialect(dialect_generic) { throw torrent::resource_error("XMLRPC not supported."); } XmlRpc::~XmlRpc() {} void XmlRpc::insert_command(const char* name, const char* parm, const char* doc, bool onDownload) {} diff --git a/src/rpc/xmlrpc.h b/src/rpc/xmlrpc.h index 0f9451a3..2ded36f6 100644 --- a/src/rpc/xmlrpc.h +++ b/src/rpc/xmlrpc.h @@ -39,10 +39,6 @@ #include -typedef struct _xmlrpc_env xmlrpc_env; -typedef struct _xmlrpc_value xmlrpc_value; -typedef struct _xmlrpc_registry xmlrpc_registry; - namespace core { class Download; } @@ -58,6 +54,10 @@ public: typedef rak::function1 slot_find_download; typedef rak::function2 slot_write; + static const int dialect_generic = 0; + static const int dialect_i8 = 1; + static const int dialect_apache = 2; + XmlRpc(); ~XmlRpc(); @@ -65,17 +65,21 @@ public: void insert_command(const char* name, const char* parm, const char* doc, bool onDownload); + static int dialect() { return m_dialect; } + void set_dialect(int dialect); + + static slot_find_download& get_slot_find_download() { return m_slotFindDownload; } static void set_slot_find_download(slot_find_download::base_type* slot) { m_slotFindDownload.set(slot); } - static xmlrpc_value* call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo); - static xmlrpc_value* call_command_d(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo); - private: - static core::Download* xmlrpc_to_download(xmlrpc_env* env, xmlrpc_value* value); - static torrent::Object xmlrpc_to_object_d(xmlrpc_env* env, xmlrpc_value* value, core::Download** download); +// xmlrpc_env* m_env; +// xmlrpc_registry* m_registry; - xmlrpc_env* m_env; - xmlrpc_registry* m_registry; + void* m_env; + void* m_registry; + + // Meh. + static int m_dialect; static slot_find_download m_slotFindDownload; };