Store copies of command names added to xmlrpc-c.

This commit is contained in:
rakshasa
2025-11-17 10:07:20 +01:00
committed by Jari Sundell
parent b05ecb5c5a
commit b825906034
3 changed files with 57 additions and 25 deletions
+17
View File
@@ -4,10 +4,27 @@
#include "parse_commands.h" #include "parse_commands.h"
#include <cstring>
#include <torrent/exceptions.h> #include <torrent/exceptions.h>
namespace rpc { namespace rpc {
std::vector<std::unique_ptr<const char>> XmlRpc::m_command_names;
const char*
XmlRpc::store_command_name(const char* name) {
if (::strnlen(name, 8192) == 8192)
throw torrent::input_error("XMLRPC command name too long, limit is 8192 characters.");
for (const auto& itr : m_command_names) {
if (::strcmp(itr.get(), name) == 0)
return itr.get();
}
m_command_names.push_back(std::unique_ptr<const char>(::strdup(name)));
return m_command_names.back().get();
}
#ifndef HAVE_XMLRPC_C #ifndef HAVE_XMLRPC_C
#ifndef HAVE_XMLRPC_TINYXML2 #ifndef HAVE_XMLRPC_TINYXML2
+4 -1
View File
@@ -59,6 +59,10 @@ public:
void set_size_limit(uint64_t size); void set_size_limit(uint64_t size);
private: private:
static const char* store_command_name(const char* name);
static std::vector<std::unique_ptr<const char>> m_command_names;
slot_download m_slotFindDownload; slot_download m_slotFindDownload;
slot_file m_slotFindFile; slot_file m_slotFindFile;
slot_tracker m_slotFindTracker; slot_tracker m_slotFindTracker;
@@ -73,7 +77,6 @@ private:
// Only used by tinyxml2 // Only used by tinyxml2
bool m_isValid; bool m_isValid;
uint64_t m_sizeLimit{SCgiTask::max_content_size}; uint64_t m_sizeLimit{SCgiTask::max_content_size};
}; };
} }
+36 -24
View File
@@ -357,10 +357,12 @@ object_to_xmlrpc(xmlrpc_env* env, const torrent::Object& object) {
xmlrpc_value* xmlrpc_value*
xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) { xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) {
CommandMap::iterator itr = commands.find((const char*)voidServerInfo); auto server_info = static_cast<const char*>(voidServerInfo);
CommandMap::iterator itr = commands.find(server_info);
if (itr == commands.end()) { if (itr == commands.end()) {
xmlrpc_env_set_fault(env, XMLRPC_PARSE_ERROR, ("Command \"" + std::string((const char*)voidServerInfo) + "\" does not exist.").c_str()); xmlrpc_env_set_fault(env, XMLRPC_PARSE_ERROR, ("Command \"" + std::string(server_info) + "\" does not exist.").c_str());
return NULL; return NULL;
} }
@@ -393,6 +395,11 @@ xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) {
} }
} }
bool
XmlRpc::is_valid() const {
return m_env != NULL;
}
void void
XmlRpc::initialize() { XmlRpc::initialize() {
#ifndef XMLRPC_HAVE_I8 #ifndef XMLRPC_HAVE_I8
@@ -417,34 +424,42 @@ XmlRpc::cleanup() {
bool bool
XmlRpc::process(const char* inBuffer, uint32_t length, slot_write slotWrite) { XmlRpc::process(const char* inBuffer, uint32_t length, slot_write slotWrite) {
xmlrpc_env localEnv; xmlrpc_env local_env;
xmlrpc_env_init(&localEnv); xmlrpc_env_init(&local_env);
xmlrpc_mem_block* memblock = xmlrpc_registry_process_call(&localEnv, (xmlrpc_registry*)m_registry, NULL, inBuffer, length); xmlrpc_mem_block* memblock = xmlrpc_registry_process_call(&local_env, (xmlrpc_registry*)m_registry, NULL, inBuffer, length);
if (localEnv.fault_occurred && localEnv.fault_code == XMLRPC_INTERNAL_ERROR) if (local_env.fault_occurred && local_env.fault_code == XMLRPC_INTERNAL_ERROR)
throw torrent::internal_error("Internal error in XMLRPC."); throw torrent::internal_error("Internal error in XMLRPC.");
bool result = slotWrite((const char*)xmlrpc_mem_block_contents(memblock), bool result = slotWrite((const char*)xmlrpc_mem_block_contents(memblock),
xmlrpc_mem_block_size(memblock)); xmlrpc_mem_block_size(memblock));
xmlrpc_mem_block_free(memblock); xmlrpc_mem_block_free(memblock);
xmlrpc_env_clean(&localEnv); xmlrpc_env_clean(&local_env);
return result; return result;
} }
void void
XmlRpc::insert_command(const char* name, const char* parm, const char* doc) { XmlRpc::insert_command(const char* name, const char* parm, const char* doc) {
xmlrpc_env localEnv; xmlrpc_env local_env;
xmlrpc_env_init(&localEnv); xmlrpc_env_init(&local_env);
xmlrpc_registry_add_method_w_doc(&localEnv, (xmlrpc_registry*)m_registry, NULL, name, auto stored_name = store_command_name(name);
&xmlrpc_call_command, const_cast<char*>(name), parm, doc);
if (localEnv.fault_occurred) xmlrpc_registry_add_method_w_doc(&local_env,
(xmlrpc_registry*)m_registry,
nullptr,
stored_name,
&xmlrpc_call_command,
(void*)stored_name,
parm,
doc);
if (local_env.fault_occurred)
throw torrent::internal_error("Fault occured while inserting xmlrpc call."); throw torrent::internal_error("Fault occured while inserting xmlrpc call.");
xmlrpc_env_clean(&localEnv); xmlrpc_env_clean(&local_env);
} }
void void
@@ -452,8 +467,8 @@ XmlRpc::set_dialect(int dialect) {
if (!is_valid()) if (!is_valid())
throw torrent::input_error("Cannot select XMLRPC dialect before it is initialized."); throw torrent::input_error("Cannot select XMLRPC dialect before it is initialized.");
xmlrpc_env localEnv; xmlrpc_env local_env;
xmlrpc_env_init(&localEnv); xmlrpc_env_init(&local_env);
switch (dialect) { switch (dialect) {
case dialect_generic: case dialect_generic:
@@ -461,25 +476,25 @@ XmlRpc::set_dialect(int dialect) {
#ifdef XMLRPC_HAVE_I8 #ifdef XMLRPC_HAVE_I8
case dialect_i8: case dialect_i8:
xmlrpc_registry_set_dialect(&localEnv, (xmlrpc_registry*)m_registry, xmlrpc_dialect_i8); xmlrpc_registry_set_dialect(&local_env, (xmlrpc_registry*)m_registry, xmlrpc_dialect_i8);
break; break;
case dialect_apache: case dialect_apache:
xmlrpc_registry_set_dialect(&localEnv, (xmlrpc_registry*)m_registry, xmlrpc_dialect_apache); xmlrpc_registry_set_dialect(&local_env, (xmlrpc_registry*)m_registry, xmlrpc_dialect_apache);
break; break;
#endif #endif
default: default:
xmlrpc_env_clean(&localEnv); xmlrpc_env_clean(&local_env);
throw torrent::input_error("Unsupported XMLRPC dialect selected."); throw torrent::input_error("Unsupported XMLRPC dialect selected.");
} }
if (localEnv.fault_occurred) { if (local_env.fault_occurred) {
xmlrpc_env_clean(&localEnv); xmlrpc_env_clean(&local_env);
throw torrent::input_error("Unsupported XMLRPC dialect selected."); throw torrent::input_error("Unsupported XMLRPC dialect selected.");
} }
xmlrpc_env_clean(&localEnv); xmlrpc_env_clean(&local_env);
m_dialect = dialect; m_dialect = dialect;
} }
@@ -496,9 +511,6 @@ XmlRpc::set_size_limit(uint64_t size) {
xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, size); xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, size);
} }
bool
XmlRpc::is_valid() const { return m_env != NULL; }
} // namespace rpc } // namespace rpc
#endif #endif