mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-09 23:59:22 +00:00
* Added system.time{,_seconds,_usec} commands.
* Cleaned up XMLRPC handling and added support for empty targets so it will handle print and cat properly. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1039 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
@@ -63,6 +63,8 @@ class timer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static timer current();
|
static timer current();
|
||||||
|
static int64_t current_seconds() { return current().seconds(); }
|
||||||
|
static int64_t current_usec() { return current().usec(); }
|
||||||
static timer from_seconds(uint32_t seconds) { return rak::timer((uint64_t)seconds * 1000000); }
|
static timer from_seconds(uint32_t seconds) { return rak::timer((uint64_t)seconds * 1000000); }
|
||||||
static timer from_milliseconds(uint32_t seconds) { return rak::timer((uint64_t)seconds * 1000); }
|
static timer from_milliseconds(uint32_t seconds) { return rak::timer((uint64_t)seconds * 1000); }
|
||||||
|
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ apply_schedule(const torrent::Object& rawArgs) {
|
|||||||
|
|
||||||
torrent::Object
|
torrent::Object
|
||||||
apply_load(int flags, const torrent::Object& rawArgs) {
|
apply_load(int flags, const torrent::Object& rawArgs) {
|
||||||
const torrent::Object::list_type& args = rawArgs.as_list();
|
const torrent::Object::list_type& args = rawArgs.as_list();
|
||||||
torrent::Object::list_const_iterator argsItr = args.begin();
|
torrent::Object::list_const_iterator argsItr = args.begin();
|
||||||
|
|
||||||
if (argsItr == args.end())
|
if (argsItr == args.end())
|
||||||
|
|||||||
+17
-13
@@ -131,8 +131,12 @@ initialize_command_local() {
|
|||||||
ADD_COMMAND_VOID("system.file_status_cache.size", rak::make_mem_fun((utils::FileStatusCache::base_type*)control->core()->file_status_cache(), &utils::FileStatusCache::size));
|
ADD_COMMAND_VOID("system.file_status_cache.size", rak::make_mem_fun((utils::FileStatusCache::base_type*)control->core()->file_status_cache(), &utils::FileStatusCache::size));
|
||||||
ADD_COMMAND_VOID("system.file_status_cache.prune", rak::make_mem_fun(control->core()->file_status_cache(), &utils::FileStatusCache::prune));
|
ADD_COMMAND_VOID("system.file_status_cache.prune", rak::make_mem_fun(control->core()->file_status_cache(), &utils::FileStatusCache::prune));
|
||||||
|
|
||||||
ADD_COMMAND_VALUE_SET_OCT("system.", "umask", std::ptr_fun(&umask));
|
ADD_COMMAND_VOID("system.time", rak::make_mem_fun(&cachedTime, &rak::timer::seconds));
|
||||||
ADD_COMMAND_STRING_PREFIX("system.", "cwd", std::ptr_fun(system_set_cwd), rak::ptr_fun(&system_get_cwd));
|
ADD_COMMAND_VOID("system.time_seconds", rak::ptr_fun(&rak::timer::current_seconds));
|
||||||
|
ADD_COMMAND_VOID("system.time_usec", rak::ptr_fun(&rak::timer::current_usec));
|
||||||
|
|
||||||
|
ADD_COMMAND_VALUE_SET_OCT("system.", "umask", std::ptr_fun(&umask));
|
||||||
|
ADD_COMMAND_STRING_PREFIX("system.", "cwd", std::ptr_fun(system_set_cwd), rak::ptr_fun(&system_get_cwd));
|
||||||
|
|
||||||
ADD_VARIABLE_STRING("name", "");
|
ADD_VARIABLE_STRING("name", "");
|
||||||
|
|
||||||
@@ -140,19 +144,19 @@ initialize_command_local() {
|
|||||||
ADD_VARIABLE_VALUE("split_file_size", -1);
|
ADD_VARIABLE_VALUE("split_file_size", -1);
|
||||||
ADD_VARIABLE_STRING("split_suffix", ".part");
|
ADD_VARIABLE_STRING("split_suffix", ".part");
|
||||||
|
|
||||||
ADD_COMMAND_VOID("get_memory_usage", rak::make_mem_fun(chunkManager, &CM_t::memory_usage));
|
ADD_COMMAND_VOID("get_memory_usage", rak::make_mem_fun(chunkManager, &CM_t::memory_usage));
|
||||||
ADD_COMMAND_VALUE_TRI("max_memory_usage", rak::make_mem_fun(chunkManager, &CM_t::set_max_memory_usage), rak::make_mem_fun(chunkManager, &CM_t::max_memory_usage));
|
ADD_COMMAND_VALUE_TRI("max_memory_usage", rak::make_mem_fun(chunkManager, &CM_t::set_max_memory_usage), rak::make_mem_fun(chunkManager, &CM_t::max_memory_usage));
|
||||||
ADD_COMMAND_VALUE_TRI("safe_sync", rak::make_mem_fun(chunkManager, &CM_t::set_safe_sync), rak::make_mem_fun(chunkManager, &CM_t::safe_sync));
|
ADD_COMMAND_VALUE_TRI("safe_sync", rak::make_mem_fun(chunkManager, &CM_t::set_safe_sync), rak::make_mem_fun(chunkManager, &CM_t::safe_sync));
|
||||||
ADD_COMMAND_VOID("get_safe_free_diskspace", rak::make_mem_fun(chunkManager, &CM_t::safe_free_diskspace));
|
ADD_COMMAND_VOID("get_safe_free_diskspace", rak::make_mem_fun(chunkManager, &CM_t::safe_free_diskspace));
|
||||||
ADD_COMMAND_VALUE_TRI("timeout_sync", rak::make_mem_fun(chunkManager, &CM_t::set_timeout_sync), rak::make_mem_fun(chunkManager, &CM_t::timeout_sync));
|
ADD_COMMAND_VALUE_TRI("timeout_sync", rak::make_mem_fun(chunkManager, &CM_t::set_timeout_sync), rak::make_mem_fun(chunkManager, &CM_t::timeout_sync));
|
||||||
ADD_COMMAND_VALUE_TRI("timeout_safe_sync", rak::make_mem_fun(chunkManager, &CM_t::set_timeout_safe_sync), rak::make_mem_fun(chunkManager, &CM_t::timeout_safe_sync));
|
ADD_COMMAND_VALUE_TRI("timeout_safe_sync", rak::make_mem_fun(chunkManager, &CM_t::set_timeout_safe_sync), rak::make_mem_fun(chunkManager, &CM_t::timeout_safe_sync));
|
||||||
|
|
||||||
ADD_COMMAND_VALUE_TRI("preload_type", rak::make_mem_fun(chunkManager, &CM_t::set_preload_type), rak::make_mem_fun(chunkManager, &CM_t::preload_type));
|
ADD_COMMAND_VALUE_TRI("preload_type", rak::make_mem_fun(chunkManager, &CM_t::set_preload_type), rak::make_mem_fun(chunkManager, &CM_t::preload_type));
|
||||||
ADD_COMMAND_VALUE_TRI("preload_min_size", rak::make_mem_fun(chunkManager, &CM_t::set_preload_min_size), rak::make_mem_fun(chunkManager, &CM_t::preload_min_size));
|
ADD_COMMAND_VALUE_TRI("preload_min_size", rak::make_mem_fun(chunkManager, &CM_t::set_preload_min_size), rak::make_mem_fun(chunkManager, &CM_t::preload_min_size));
|
||||||
ADD_COMMAND_VALUE_TRI_KB("preload_required_rate", rak::make_mem_fun(chunkManager, &CM_t::set_preload_required_rate), rak::make_mem_fun(chunkManager, &CM_t::preload_required_rate));
|
ADD_COMMAND_VALUE_TRI_KB("preload_required_rate", rak::make_mem_fun(chunkManager, &CM_t::set_preload_required_rate), rak::make_mem_fun(chunkManager, &CM_t::preload_required_rate));
|
||||||
|
|
||||||
ADD_COMMAND_VOID("get_stats_preloaded", rak::make_mem_fun(chunkManager, &CM_t::stats_preloaded));
|
ADD_COMMAND_VOID("get_stats_preloaded", rak::make_mem_fun(chunkManager, &CM_t::stats_preloaded));
|
||||||
ADD_COMMAND_VOID("get_stats_not_preloaded", rak::make_mem_fun(chunkManager, &CM_t::stats_not_preloaded));
|
ADD_COMMAND_VOID("get_stats_not_preloaded", rak::make_mem_fun(chunkManager, &CM_t::stats_not_preloaded));
|
||||||
|
|
||||||
ADD_VARIABLE_STRING("directory", "./");
|
ADD_VARIABLE_STRING("directory", "./");
|
||||||
|
|
||||||
|
|||||||
+15
-18
@@ -145,29 +145,24 @@ apply_cat(rpc::target_type target, const torrent::Object& rawArgs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
torrent::Object
|
torrent::Object
|
||||||
apply_to_date(const torrent::Object& rawArgs) {
|
apply_to_time(int flags, const torrent::Object& rawArgs) {
|
||||||
|
std::tm *u;
|
||||||
time_t t = (uint64_t)rawArgs.as_value();
|
time_t t = (uint64_t)rawArgs.as_value();
|
||||||
std::tm *u = std::gmtime(&t);
|
|
||||||
|
if (flags & 0x1)
|
||||||
|
u = std::localtime(&t);
|
||||||
|
else
|
||||||
|
u = std::gmtime(&t);
|
||||||
|
|
||||||
if (u == NULL)
|
if (u == NULL)
|
||||||
return torrent::Object();
|
return torrent::Object();
|
||||||
|
|
||||||
char buffer[11];
|
char buffer[11];
|
||||||
snprintf(buffer, 11, "%02u/%02u/%04u", u->tm_mday, (u->tm_mon + 1), (1900 + u->tm_year));
|
|
||||||
|
|
||||||
return std::string(buffer);
|
if (flags & 0x2)
|
||||||
}
|
snprintf(buffer, 11, "%02u/%02u/%04u", u->tm_mday, (u->tm_mon + 1), (1900 + u->tm_year));
|
||||||
|
else
|
||||||
torrent::Object
|
snprintf(buffer, 9, "%2d:%02d:%02d", u->tm_hour, u->tm_min, u->tm_sec);
|
||||||
apply_to_time(const torrent::Object& rawArgs) {
|
|
||||||
time_t t = (uint64_t)rawArgs.as_value();
|
|
||||||
std::tm *u = std::gmtime(&t);
|
|
||||||
|
|
||||||
if (u == NULL)
|
|
||||||
return torrent::Object();
|
|
||||||
|
|
||||||
char buffer[9];
|
|
||||||
snprintf(buffer, 9, "%2d:%02d:%02d", u->tm_hour, u->tm_min, u->tm_sec);
|
|
||||||
|
|
||||||
return std::string(buffer);
|
return std::string(buffer);
|
||||||
}
|
}
|
||||||
@@ -311,8 +306,10 @@ initialize_command_ui() {
|
|||||||
// support for seperation of commands and literals.
|
// support for seperation of commands and literals.
|
||||||
ADD_ANY_NONE("branch", rak::bind_ptr_fn(&apply_if, 1));
|
ADD_ANY_NONE("branch", rak::bind_ptr_fn(&apply_if, 1));
|
||||||
|
|
||||||
ADD_COMMAND_VALUE("to_date", rak::ptr_fn(&apply_to_date));
|
ADD_COMMAND_VALUE("to_gm_time", rak::bind_ptr_fn(&apply_to_time, 0));
|
||||||
ADD_COMMAND_VALUE("to_time", rak::ptr_fn(&apply_to_time));
|
ADD_COMMAND_VALUE("to_gm_date", rak::bind_ptr_fn(&apply_to_time, 0x2));
|
||||||
|
ADD_COMMAND_VALUE("to_time", rak::bind_ptr_fn(&apply_to_time, 0x1));
|
||||||
|
ADD_COMMAND_VALUE("to_date", rak::bind_ptr_fn(&apply_to_time, 0x1 | 0x2));
|
||||||
ADD_COMMAND_VALUE("to_elapsed_time", rak::ptr_fn(&apply_to_elapsed_time));
|
ADD_COMMAND_VALUE("to_elapsed_time", rak::ptr_fn(&apply_to_elapsed_time));
|
||||||
ADD_COMMAND_VALUE("to_kb", rak::ptr_fn(&apply_to_kb));
|
ADD_COMMAND_VALUE("to_kb", rak::ptr_fn(&apply_to_kb));
|
||||||
ADD_COMMAND_VALUE("to_mb", rak::ptr_fn(&apply_to_mb));
|
ADD_COMMAND_VALUE("to_mb", rak::ptr_fn(&apply_to_mb));
|
||||||
|
|||||||
+201
-223
@@ -51,8 +51,136 @@ namespace rpc {
|
|||||||
|
|
||||||
#ifdef HAVE_XMLRPC_C
|
#ifdef HAVE_XMLRPC_C
|
||||||
|
|
||||||
|
class xmlrpc_error : public torrent::base_error {
|
||||||
|
public:
|
||||||
|
xmlrpc_error(xmlrpc_env* env) : m_type(env->fault_code), m_msg(env->fault_string) {}
|
||||||
|
xmlrpc_error(int type, char* msg) : m_type(type), m_msg(msg) {}
|
||||||
|
virtual ~xmlrpc_error() throw() {}
|
||||||
|
|
||||||
|
virtual int type() const throw() { return m_type; }
|
||||||
|
virtual const char* what() const throw() { return m_msg; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_type;
|
||||||
|
char* m_msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
torrent::Object xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType = 0, rpc::target_type* target = NULL);
|
||||||
|
|
||||||
|
inline torrent::Object
|
||||||
|
xmlrpc_list_entry_to_object(xmlrpc_env* env, xmlrpc_value* src, int index) {
|
||||||
|
xmlrpc_value* tmp;
|
||||||
|
xmlrpc_array_read_item(env, src, index, &tmp);
|
||||||
|
|
||||||
|
if (env->fault_occurred)
|
||||||
|
throw xmlrpc_error(env);
|
||||||
|
|
||||||
|
torrent::Object obj = xmlrpc_to_object(env, tmp);
|
||||||
|
xmlrpc_DECREF(tmp);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
xmlrpc_list_entry_to_value(xmlrpc_env* env, xmlrpc_value* src, int index) {
|
||||||
|
xmlrpc_value* tmp;
|
||||||
|
xmlrpc_array_read_item(env, src, index, &tmp);
|
||||||
|
|
||||||
|
if (env->fault_occurred)
|
||||||
|
throw xmlrpc_error(env);
|
||||||
|
|
||||||
|
switch (xmlrpc_value_type(tmp)) {
|
||||||
|
case XMLRPC_TYPE_INT:
|
||||||
|
int v;
|
||||||
|
xmlrpc_read_int(env, tmp, &v);
|
||||||
|
xmlrpc_DECREF(tmp);
|
||||||
|
return v;
|
||||||
|
|
||||||
|
#ifdef XMLRPC_HAVE_I8
|
||||||
|
case XMLRPC_TYPE_I8:
|
||||||
|
long long v2;
|
||||||
|
xmlrpc_read_i8(env, tmp, &v2);
|
||||||
|
xmlrpc_DECREF(tmp);
|
||||||
|
return v2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case XMLRPC_TYPE_STRING:
|
||||||
|
{
|
||||||
|
const char* str;
|
||||||
|
xmlrpc_read_string(env, tmp, &str);
|
||||||
|
|
||||||
|
if (env->fault_occurred)
|
||||||
|
throw xmlrpc_error(env);
|
||||||
|
|
||||||
|
const char* end = str;
|
||||||
|
int64_t v3 = ::strtoll(str, (char**)&end, 0);
|
||||||
|
|
||||||
|
::free((void*)str);
|
||||||
|
|
||||||
|
if (*str == '\0' || *end != '\0')
|
||||||
|
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Invalid index.");
|
||||||
|
|
||||||
|
return v3;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
xmlrpc_DECREF(tmp);
|
||||||
|
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Invalid type found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consider making a helper function that creates a target_type from a
|
||||||
|
// torrent::Object, then we can just use xmlrpc_to_object.
|
||||||
|
rpc::target_type
|
||||||
|
xmlrpc_to_target(xmlrpc_env* env, xmlrpc_value* value) {
|
||||||
|
switch (xmlrpc_value_type(value)) {
|
||||||
|
case XMLRPC_TYPE_STRING:
|
||||||
|
const char* str;
|
||||||
|
xmlrpc_read_string(env, value, &str);
|
||||||
|
|
||||||
|
if (env->fault_occurred)
|
||||||
|
throw xmlrpc_error(env);
|
||||||
|
|
||||||
|
if (std::strlen(str) == 40) {
|
||||||
|
core::Download* download = xmlrpc.get_slot_find_download()(str);
|
||||||
|
::free((void*)str);
|
||||||
|
|
||||||
|
if (download == NULL)
|
||||||
|
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Could not find info-hash.");
|
||||||
|
|
||||||
|
return rpc::make_target(download);
|
||||||
|
|
||||||
|
} else if (std::strlen(str) == 0) {
|
||||||
|
::free((void*)str);
|
||||||
|
return rpc::make_target();
|
||||||
|
}
|
||||||
|
|
||||||
|
::free((void*)str);
|
||||||
|
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Unsupported target type found.");
|
||||||
|
|
||||||
|
default:
|
||||||
|
return rpc::make_target();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc::target_type
|
||||||
|
xmlrpc_to_index_type(int index, int callType, core::Download* download) {
|
||||||
|
void* result;
|
||||||
|
|
||||||
|
switch (callType) {
|
||||||
|
case XmlRpc::call_file: result = xmlrpc.get_slot_find_file()(download, index); break;
|
||||||
|
case XmlRpc::call_tracker: result = xmlrpc.get_slot_find_tracker()(download, index); break;
|
||||||
|
default: result = NULL; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == NULL)
|
||||||
|
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Invalid index.");
|
||||||
|
|
||||||
|
return rpc::make_target(callType, result);
|
||||||
|
}
|
||||||
|
|
||||||
torrent::Object
|
torrent::Object
|
||||||
xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value) {
|
xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value, int callType, rpc::target_type* target) {
|
||||||
switch (xmlrpc_value_type(value)) {
|
switch (xmlrpc_value_type(value)) {
|
||||||
case XMLRPC_TYPE_INT:
|
case XMLRPC_TYPE_INT:
|
||||||
int v;
|
int v;
|
||||||
@@ -73,19 +201,28 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value) {
|
|||||||
// case XMLRPC_TYPE_DATETIME:
|
// case XMLRPC_TYPE_DATETIME:
|
||||||
|
|
||||||
case XMLRPC_TYPE_STRING:
|
case XMLRPC_TYPE_STRING:
|
||||||
{
|
|
||||||
const char* valueString;
|
|
||||||
xmlrpc_read_string(env, value, &valueString);
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
if (callType != XmlRpc::call_generic) {
|
||||||
|
// When the call type is not supposed to be void, we'll try to
|
||||||
|
// convert it to a command target. It's not that important that
|
||||||
|
// it is converted to the right type here, as an mismatch will
|
||||||
|
// be caught when executing the command.
|
||||||
|
*target = xmlrpc_to_target(env, value);
|
||||||
return torrent::Object();
|
return torrent::Object();
|
||||||
|
|
||||||
torrent::Object result = torrent::Object(std::string(valueString));
|
} else {
|
||||||
|
const char* valueString;
|
||||||
|
xmlrpc_read_string(env, value, &valueString);
|
||||||
|
|
||||||
// Urgh, seriously?
|
if (env->fault_occurred)
|
||||||
::free((void*)valueString);
|
throw xmlrpc_error(env);
|
||||||
return result;
|
|
||||||
}
|
torrent::Object result = torrent::Object(std::string(valueString));
|
||||||
|
|
||||||
|
// Urgh, seriously?
|
||||||
|
::free((void*)valueString);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
case XMLRPC_TYPE_BASE64:
|
case XMLRPC_TYPE_BASE64:
|
||||||
{
|
{
|
||||||
@@ -95,7 +232,7 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value) {
|
|||||||
xmlrpc_read_base64(env, value, &valueSize, (const unsigned char**)&valueString);
|
xmlrpc_read_base64(env, value, &valueSize, (const unsigned char**)&valueString);
|
||||||
|
|
||||||
if (env->fault_occurred)
|
if (env->fault_occurred)
|
||||||
return torrent::Object();
|
throw xmlrpc_error(env);
|
||||||
|
|
||||||
torrent::Object result = torrent::Object(std::string(valueString, valueSize));
|
torrent::Object result = torrent::Object(std::string(valueString, valueSize));
|
||||||
|
|
||||||
@@ -106,28 +243,56 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value) {
|
|||||||
|
|
||||||
case XMLRPC_TYPE_ARRAY:
|
case XMLRPC_TYPE_ARRAY:
|
||||||
{
|
{
|
||||||
torrent::Object result = torrent::Object::create_list();
|
unsigned int current = 0;
|
||||||
torrent::Object::list_type& listRef = result.as_list();
|
|
||||||
|
|
||||||
unsigned int last = xmlrpc_array_size(env, value);
|
unsigned int last = xmlrpc_array_size(env, value);
|
||||||
|
|
||||||
if (env->fault_occurred)
|
if (env->fault_occurred)
|
||||||
return torrent::Object();
|
throw xmlrpc_error(env);
|
||||||
|
|
||||||
|
if (callType != XmlRpc::call_generic) {
|
||||||
|
if (last < 1)
|
||||||
|
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Too few arguments.");
|
||||||
|
|
||||||
// Move this into a helper function.
|
|
||||||
for (unsigned int i = 0; i != last; i++) {
|
|
||||||
// Need to decref.
|
|
||||||
xmlrpc_value* tmp;
|
xmlrpc_value* tmp;
|
||||||
xmlrpc_array_read_item(env, value, i, &tmp);
|
xmlrpc_array_read_item(env, value, current++, &tmp);
|
||||||
|
|
||||||
if (env->fault_occurred)
|
if (env->fault_occurred)
|
||||||
return torrent::Object();
|
throw xmlrpc_error(env);
|
||||||
|
|
||||||
listRef.push_back(xmlrpc_to_object(env, tmp));
|
*target = xmlrpc_to_target(env, tmp);
|
||||||
xmlrpc_DECREF(tmp);
|
xmlrpc_DECREF(tmp);
|
||||||
|
|
||||||
|
if (env->fault_occurred)
|
||||||
|
throw xmlrpc_error(env);
|
||||||
|
|
||||||
|
if (target->first == XmlRpc::call_download &&
|
||||||
|
(callType == XmlRpc::call_file || callType == XmlRpc::call_tracker)) {
|
||||||
|
// If we have a download target and the call type requires
|
||||||
|
// another contained type, then we try to use the next
|
||||||
|
// parameter as the index to support old-style calls.
|
||||||
|
|
||||||
|
if (current == last)
|
||||||
|
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Too few arguments.");
|
||||||
|
|
||||||
|
*target = xmlrpc_to_index_type(xmlrpc_list_entry_to_value(env, value, current++), callType, (core::Download*)target->second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
if (current + 1 < last) {
|
||||||
|
torrent::Object result = torrent::Object::create_list();
|
||||||
|
torrent::Object::list_type& listRef = result.as_list();
|
||||||
|
|
||||||
|
while (current != last)
|
||||||
|
listRef.push_back(xmlrpc_list_entry_to_object(env, value, current++));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} else if (current + 1 == last) {
|
||||||
|
return xmlrpc_list_entry_to_object(env, value, current);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return torrent::Object();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// case XMLRPC_TYPE_STRUCT:
|
// case XMLRPC_TYPE_STRUCT:
|
||||||
@@ -135,202 +300,10 @@ xmlrpc_to_object(xmlrpc_env* env, xmlrpc_value* value) {
|
|||||||
// case XMLRPC_TYPE_NIL:
|
// case XMLRPC_TYPE_NIL:
|
||||||
// case XMLRPC_TYPE_DEAD:
|
// case XMLRPC_TYPE_DEAD:
|
||||||
default:
|
default:
|
||||||
xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Unsupported type found.");
|
throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Unsupported type found.");
|
||||||
return torrent::Object();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
core::Download*
|
|
||||||
xmlrpc_to_download(xmlrpc_env* env, xmlrpc_value* value) {
|
|
||||||
core::Download* download = NULL;
|
|
||||||
|
|
||||||
switch (xmlrpc_value_type(value)) {
|
|
||||||
case XMLRPC_TYPE_STRING:
|
|
||||||
{
|
|
||||||
const char* str;
|
|
||||||
xmlrpc_read_string(env, value, &str);
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (std::strlen(str) != 40 ||
|
|
||||||
(download = xmlrpc.get_slot_find_download()(str)) == NULL)
|
|
||||||
xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Could not find info-hash.");
|
|
||||||
|
|
||||||
// Urgh, seriously?
|
|
||||||
::free((void*)str);
|
|
||||||
return download;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Unsupported type found.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
|
||||||
xmlrpc_to_index_type(xmlrpc_env* env, xmlrpc_value* value, int callType, core::Download* download) {
|
|
||||||
int index;
|
|
||||||
|
|
||||||
switch (xmlrpc_value_type(value)) {
|
|
||||||
case XMLRPC_TYPE_INT:
|
|
||||||
xmlrpc_read_int(env, value, &index);
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifdef XMLRPC_HAVE_I8
|
|
||||||
case XMLRPC_TYPE_I8:
|
|
||||||
long long v2;
|
|
||||||
xmlrpc_read_i8(env, value, &v2);
|
|
||||||
|
|
||||||
index = v2;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case XMLRPC_TYPE_STRING:
|
|
||||||
{
|
|
||||||
const char* str;
|
|
||||||
xmlrpc_read_string(env, value, &str);
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
const char* end = str;
|
|
||||||
index = ::strtol(str, (char**)&end, 0);
|
|
||||||
|
|
||||||
::free((void*)str);
|
|
||||||
|
|
||||||
if (*str == '\0' || *end != '\0') {
|
|
||||||
xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Invalid index.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Unsupported type found.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
void* result;
|
|
||||||
|
|
||||||
switch (callType) {
|
|
||||||
case XmlRpc::call_file: result = xmlrpc.get_slot_find_file()(download, index); break;
|
|
||||||
case XmlRpc::call_tracker: result = xmlrpc.get_slot_find_tracker()(download, index); break;
|
|
||||||
default: result = NULL; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == NULL)
|
|
||||||
xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Invalid index.");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This should really be cleaned up and support for an array of
|
|
||||||
// downloads should be added.
|
|
||||||
torrent::Object
|
|
||||||
xmlrpc_to_object_target(xmlrpc_env* env, xmlrpc_value* value, int callType, void** target) {
|
|
||||||
switch (xmlrpc_value_type(value)) {
|
|
||||||
case XMLRPC_TYPE_STRING:
|
|
||||||
if (callType != XmlRpc::call_download) {
|
|
||||||
xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Unsupported type found.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*target = xmlrpc_to_download(env, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XMLRPC_TYPE_ARRAY:
|
|
||||||
{
|
|
||||||
unsigned int current = 0;
|
|
||||||
unsigned int last = xmlrpc_array_size(env, value);
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (last < 1) {
|
|
||||||
xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Too few arguments.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
xmlrpc_value* tmp;
|
|
||||||
xmlrpc_array_read_item(env, value, current++, &tmp);
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
|
||||||
break;
|
|
||||||
|
|
||||||
*target = xmlrpc_to_download(env, tmp);
|
|
||||||
xmlrpc_DECREF(tmp);
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callType == XmlRpc::call_file || callType == XmlRpc::call_tracker) {
|
|
||||||
if (current == last) {
|
|
||||||
xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Too few arguments.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
xmlrpc_value* tmp;
|
|
||||||
xmlrpc_array_read_item(env, value, current++, &tmp);
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
|
||||||
break;
|
|
||||||
|
|
||||||
*target = xmlrpc_to_index_type(env, tmp, callType, (core::Download*)*target);
|
|
||||||
xmlrpc_DECREF(tmp);
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
torrent::Object result;
|
|
||||||
|
|
||||||
if (current + 1 < last) {
|
|
||||||
result = torrent::Object::create_list();
|
|
||||||
torrent::Object::list_type& listRef = result.as_list();
|
|
||||||
|
|
||||||
// Move this into a helper function?
|
|
||||||
while (current != last) {
|
|
||||||
xmlrpc_value* tmp;
|
|
||||||
xmlrpc_array_read_item(env, value, current++, &tmp);
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
|
||||||
break;
|
|
||||||
|
|
||||||
listRef.push_back(xmlrpc_to_object(env, tmp));
|
|
||||||
xmlrpc_DECREF(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
} else if (current + 1 == last) {
|
|
||||||
// Need to decref.
|
|
||||||
xmlrpc_value* tmp;
|
|
||||||
xmlrpc_array_read_item(env, value, current, &tmp);
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
|
||||||
break;
|
|
||||||
|
|
||||||
result = xmlrpc_to_object(env, tmp);
|
|
||||||
xmlrpc_DECREF(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
xmlrpc_env_set_fault(env, XMLRPC_TYPE_ERROR, "Unsupported type found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return torrent::Object();
|
|
||||||
}
|
|
||||||
|
|
||||||
xmlrpc_value*
|
xmlrpc_value*
|
||||||
object_to_xmlrpc(xmlrpc_env* env, const torrent::Object& object) {
|
object_to_xmlrpc(xmlrpc_env* env, const torrent::Object& object) {
|
||||||
switch (object.type()) {
|
switch (object.type()) {
|
||||||
@@ -380,15 +353,20 @@ xmlrpc_call_command(xmlrpc_env* env, xmlrpc_value* args, void* voidServerInfo) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int type = itr->second.target();
|
|
||||||
void* target = NULL;
|
|
||||||
torrent::Object object = (type == 0) ? xmlrpc_to_object(env, args) : xmlrpc_to_object_target(env, args, type, &target);
|
|
||||||
|
|
||||||
if (env->fault_occurred)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return object_to_xmlrpc(env, rpc::commands.call_command(itr, object, rpc::make_target(type, target)));
|
torrent::Object object;
|
||||||
|
rpc::target_type target = rpc::make_target();
|
||||||
|
|
||||||
|
xmlrpc_to_object(env, args, itr->second.target(), &target).swap(object);
|
||||||
|
|
||||||
|
if (env->fault_occurred)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return object_to_xmlrpc(env, rpc::commands.call_command(itr, object, target));
|
||||||
|
|
||||||
|
} catch (xmlrpc_error& e) {
|
||||||
|
xmlrpc_env_set_fault(env, e.type(), e.what());
|
||||||
|
return NULL;
|
||||||
|
|
||||||
} catch (torrent::local_error& e) {
|
} catch (torrent::local_error& e) {
|
||||||
xmlrpc_env_set_fault(env, XMLRPC_PARSE_ERROR, e.what());
|
xmlrpc_env_set_fault(env, XMLRPC_PARSE_ERROR, e.what());
|
||||||
|
|||||||
Reference in New Issue
Block a user