diff --git a/rak/string_manip.h b/rak/string_manip.h index b3f30376..68211f73 100644 --- a/rak/string_manip.h +++ b/rak/string_manip.h @@ -302,6 +302,57 @@ generate_random(size_t length) { return s; } +template +inline bool +is_all_alpha(Iterator first, Iterator last) { + while (first != last) + if (!std::isalpha(*first++, std::locale::classic())) + return false; + + return true; +} + +template +inline bool +is_all_alpha(const Sequence& src) { + return is_all_alpha(src.begin(), src.end()); +} + +template +inline bool +is_all_alnum(Iterator first, Iterator last) { + while (first != last) + if (!std::isalnum(*first++, std::locale::classic())) + return false; + + return true; +} + +template +inline bool +is_all_alnum(const Sequence& src) { + return is_all_alnum(src.begin(), src.end()); +} + +template +inline bool +is_all_name(Iterator first, Iterator last) { + while (first != last) { + if (!std::isalnum(*first, std::locale::classic()) && *first != '_') + return false; + + first++; + } + + return true; +} + +template +inline bool +is_all_name(const Sequence& src) { + return is_all_name(src.begin(), src.end()); +} + } #endif diff --git a/src/command_dynamic.cc b/src/command_dynamic.cc index 5345f013..245b8324 100644 --- a/src/command_dynamic.cc +++ b/src/command_dynamic.cc @@ -180,6 +180,18 @@ system_method_erase(__UNUSED rpc::target_type target, const torrent::Object& raw return torrent::Object(); } +torrent::Object +system_method_get(__UNUSED rpc::target_type target, const torrent::Object& rawArgs) { + rpc::CommandFunction* function; + rpc::CommandMap::iterator itr = rpc::commands.find(rawArgs.as_string().c_str()); + + if (itr == rpc::commands.end() || + (function = dynamic_cast(itr->second.m_variable)) == NULL) + throw torrent::input_error("Command not modifiable or wrong type."); + + return torrent::Object(function->command()); +} + torrent::Object system_method_set(__UNUSED rpc::target_type target, const torrent::Object& rawArgs) { const torrent::Object::list_type& args = rawArgs.as_list(); @@ -190,7 +202,7 @@ system_method_set(__UNUSED rpc::target_type target, const torrent::Object& rawAr rpc::CommandFunction* function; rpc::CommandMap::iterator itr = rpc::commands.find(args.front().as_string().c_str()); - if (!rpc::commands.is_modifiable(itr) || + if (itr == rpc::commands.end() || !rpc::commands.is_modifiable(itr) || (function = dynamic_cast(itr->second.m_variable)) == NULL) throw torrent::input_error("Command not modifiable or wrong type."); @@ -262,6 +274,7 @@ void initialize_command_dynamic() { CMD_N ("system.method.insert", rak::ptr_fn(&system_method_insert)); CMD_N_STRING("system.method.erase", rak::ptr_fn(&system_method_erase)); + CMD_N_STRING("system.method.get", rak::ptr_fn(&system_method_get)); CMD_N ("system.method.set", rak::ptr_fn(&system_method_set)); CMD_N ("system.method.set_key", rak::ptr_fn(&system_method_set_key)); CMD_N ("system.method.has_key", rak::ptr_fn(&system_method_has_key)); diff --git a/src/command_events.cc b/src/command_events.cc index 7fe4c970..164be667 100644 --- a/src/command_events.cc +++ b/src/command_events.cc @@ -119,7 +119,7 @@ apply_on_ratio(const torrent::Object& rawArgs) { std::vector downloads; for (core::View::iterator itr = (*viewItr)->begin_visible(), last = (*viewItr)->end_visible(); itr != last; itr++) { - if (rpc::call_command_value("d.get_ignore_commands", rpc::make_target(*itr)) != 0) + if (!(*itr)->is_seeding() || rpc::call_command_value("d.get_ignore_commands", rpc::make_target(*itr)) != 0) continue; rpc::parse_command_single(rpc::make_target(*itr), "print={Checked ratio of download.}"); diff --git a/src/command_helpers.h b/src/command_helpers.h index 199df106..f1419eee 100644 --- a/src/command_helpers.h +++ b/src/command_helpers.h @@ -208,6 +208,9 @@ add_variable(key, NULL, NULL, &rpc::CommandVariable::get_string, NULL, std::stri #define CMD_N_STRING(key, slot) \ CMD_N_SLOT(key, call_string, slot, "i:", "") +#define CMD_N_LIST(key, slot) \ + CMD_N_SLOT(key, call_list, slot, "i:", "") + #define CMD_D_SLOT(key, function, slot, parm, doc) \ commandDownloadSlotsItr->set_slot(slot); \ rpc::commands.insert_type(key, commandDownloadSlotsItr++, &rpc::CommandSlot::function, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, parm, doc); diff --git a/src/command_local.cc b/src/command_local.cc index 4ea6ba8c..828736e5 100644 --- a/src/command_local.cc +++ b/src/command_local.cc @@ -48,6 +48,7 @@ #include "core/download_list.h" #include "core/download_store.h" #include "core/manager.h" +#include "rak/string_manip.h" #include "rpc/command_slot.h" #include "rpc/command_variable.h" #include "rpc/parse_commands.h" @@ -116,6 +117,42 @@ system_set_cwd(const torrent::Object& rawArgs) { return torrent::Object(); } +inline torrent::Object::list_const_iterator +post_increment(torrent::Object::list_const_iterator& itr, const torrent::Object::list_const_iterator& last) { + if (itr == last) + throw torrent::input_error("Invalid number of arguments."); + + return itr++; +} + +inline const std::string& +check_name(const std::string& str) { + if (!rak::is_all_name(str)) + throw torrent::input_error("Non-alphanumeric characters found."); + + return str; +} + +torrent::Object +group_insert(__UNUSED rpc::target_type target, const torrent::Object& rawArgs) { + torrent::Object::list_const_iterator itr = rawArgs.as_list().begin(); + torrent::Object::list_const_iterator last = rawArgs.as_list().end(); + + const std::string& name = check_name(post_increment(itr, last)->as_string()); + const std::string& view = check_name(post_increment(itr, last)->as_string()); + + rpc::commands.call("system.method.insert", rpc::create_object_list("group." + name + ".view", "string", view)); + + rpc::commands.call("system.method.insert", rpc::create_object_list("group." + name + ".ratio.enable", "simple", "schedule=group." + name + ".ratio,5,60,on_ratio=" + name)); + rpc::commands.call("system.method.insert", rpc::create_object_list("group." + name + ".ratio.disable", "simple", "schedule_remove=group." + name + ".ratio")); + rpc::commands.call("system.method.insert", rpc::create_object_list("group." + name + ".ratio.command", "simple", "d.try_close= ;d.set_ignore_commands=1")); + rpc::commands.call("system.method.insert", rpc::create_object_list("group." + name + ".ratio.min", "value", (int64_t)200)); + rpc::commands.call("system.method.insert", rpc::create_object_list("group." + name + ".ratio.max", "value", (int64_t)300)); + rpc::commands.call("system.method.insert", rpc::create_object_list("group." + name + ".ratio.upload", "value", (int64_t)20 << 20)); + + return name; +} + void initialize_command_local() { torrent::ChunkManager* chunkManager = torrent::chunk_manager(); @@ -178,4 +215,6 @@ initialize_command_local() { CMD_OBJ_P("argument.1", get_generic, rpc::Command::argument(1)); CMD_OBJ_P("argument.2", get_generic, rpc::Command::argument(2)); CMD_OBJ_P("argument.3", get_generic, rpc::Command::argument(3)); + + CMD_N_LIST("group.insert", rak::ptr_fn(&group_insert)); } diff --git a/src/command_ui.cc b/src/command_ui.cc index b649be1e..cf1f232f 100644 --- a/src/command_ui.cc +++ b/src/command_ui.cc @@ -394,6 +394,13 @@ cmd_view_size_not_visible(__UNUSED rpc::target_type target, const torrent::Objec return (*control->view_manager()->find_throw(rawArgs.as_string()))->size_not_visible(); } +torrent::Object +cmd_ui_set_view(__UNUSED rpc::target_type target, const torrent::Object& rawArgs) { + control->ui()->download_list()->set_current_view(rawArgs.as_string()); + + return torrent::Object(); +} + torrent::Object cmd_ui_unfocus_download(core::Download* download, const torrent::Object& rawArgs) { control->ui()->download_list()->unfocus_download(download); @@ -451,7 +458,8 @@ initialize_command_ui() { // Commands that affect the default rtorrent UI. // ADD_ANY_NONE("ui.focus", rak::ptr_fn(&cmd_ui_focus)); - CMD_D_ANY("ui.unfocus_download", rak::ptr_fn(&cmd_ui_unfocus_download)); + CMD_D_ANY("ui.unfocus_download", rak::ptr_fn(&cmd_ui_unfocus_download)); + CMD_N_STRING("ui.current_view.set", rak::ptr_fn(&cmd_ui_set_view)); // Move. diff --git a/src/main.cc b/src/main.cc index 8dbb6972..53566108 100644 --- a/src/main.cc +++ b/src/main.cc @@ -210,14 +210,16 @@ main(int argc, char** argv) { // TODO: Remember to ensure it doesn't get restarted by watch // dir, etc. Set ignore commands, or something. - "system.method.insert = group.seeding.view,string|static|const,seeding\n" + "group.insert = seeding,seeding\n" - "system.method.insert = group.seeding.ratio.enable ,simple,\"schedule=group.seeding.ratio,5,60,on_ratio=seeding\"\n" - "system.method.insert = group.seeding.ratio.disable,simple,\"schedule_remove=group.seeding.ratio\"\n" - "system.method.insert = group.seeding.ratio.command,simple|static,\"d.try_close= ;d.set_ignore_commands=1\"\n" - "system.method.insert = group.seeding.ratio.min,value,200\n" - "system.method.insert = group.seeding.ratio.max,value,300\n" - "system.method.insert = group.seeding.ratio.upload,value,20M\n" +// "system.method.insert = group.seeding.view,string|static|const,seeding\n" + +// "system.method.insert = group.seeding.ratio.enable ,simple,\"schedule=group.seeding.ratio,5,60,on_ratio=seeding\"\n" +// "system.method.insert = group.seeding.ratio.disable,simple,\"schedule_remove=group.seeding.ratio\"\n" +// "system.method.insert = group.seeding.ratio.command,simple|static,\"d.try_close= ;d.set_ignore_commands=1\"\n" +// "system.method.insert = group.seeding.ratio.min,value,200\n" +// "system.method.insert = group.seeding.ratio.max,value,300\n" +// "system.method.insert = group.seeding.ratio.upload,value,20M\n" "set_name = \"$cat=$system.hostname=,:,$system.pid=\"\n" diff --git a/src/rpc/command_map.h b/src/rpc/command_map.h index 28df37f3..b58ea3f2 100644 --- a/src/rpc/command_map.h +++ b/src/rpc/command_map.h @@ -127,6 +127,7 @@ public: void insert(key_type key, const command_map_data_type src); void erase(iterator itr); + const mapped_type call(key_type key, const mapped_type& args = mapped_type()); const mapped_type call(key_type key, target_type target, const mapped_type& args = mapped_type()) { return call_command(key, args, target); } const mapped_type call_catch(key_type key, target_type target, const mapped_type& args = mapped_type(), const char* err = "Command failed: "); @@ -177,6 +178,11 @@ create_object_list(const torrent::Object& o1, const torrent::Object& o2, const t return tmp; } +inline const CommandMap::mapped_type +CommandMap::call(key_type key, const mapped_type& args) { + return call_command(key, args, make_target()); +} + } #endif diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 21a4653b..b7d69834 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -120,6 +120,11 @@ DownloadList::current_view() { return dynamic_cast(m_uiArray[DISPLAY_DOWNLOAD_LIST])->view(); } +void +DownloadList::set_current_view(const std::string& name) { + return dynamic_cast(m_uiArray[DISPLAY_DOWNLOAD_LIST])->receive_change_view(name); +} + // This should also do focus_next() or something. void DownloadList::unfocus_download(core::Download* d) { diff --git a/src/ui/download_list.h b/src/ui/download_list.h index a485fc17..dda1b348 100644 --- a/src/ui/download_list.h +++ b/src/ui/download_list.h @@ -101,6 +101,7 @@ public: void activate_display(Display d); core::View* current_view(); + void set_current_view(const std::string& name); void slot_open_uri(SlotOpenUri s) { m_slotOpenUri = s; }