mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-13 13:42:30 +00:00
Merge branch 'master' into xirvik
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Perl script to add rTorrent fast resume data to torrent files.
|
||||
#
|
||||
# Usage:
|
||||
# rtorrent_fast_resume.pl [base-directory] < plain.torrent > with_fast_resume.torrent
|
||||
# -OR-
|
||||
# rtorrent_fast_resume.pl [base-directory] plain.torrent [with_fast_resume.torrent]
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Convert::Bencode_XS qw(bencode bdecode);
|
||||
use File::Spec; # core module
|
||||
use POSIX; # core module
|
||||
|
||||
$/ = undef;
|
||||
$| = 1;
|
||||
|
||||
# Process ARGV
|
||||
my $d = $ARGV[0];
|
||||
if ($d and not -d $d) {
|
||||
if (-f $d and -s $d and not $ARGV[2]) { # missing directory, but has file
|
||||
$ARGV[2] = $ARGV[1];
|
||||
$ARGV[1] = $ARGV[0];
|
||||
$d = '';
|
||||
}
|
||||
else { die "$d is not a directory\n"; }
|
||||
}
|
||||
$d ||= ".";
|
||||
$d .= "/" unless $d =~ m#/$#;
|
||||
|
||||
my ($in, $out, $msg);
|
||||
my ($in_file, $out_file) = ('', '');
|
||||
if ($ARGV[1]) {
|
||||
$in_file = $ARGV[1];
|
||||
open($in, ($ARGV[2] ? '<' : '+<'), $in_file) || die "Cannot open $in_file for input!\n";
|
||||
unless ($ARGV[2]) {
|
||||
$out = $in;
|
||||
$out_file = $in_file;
|
||||
}
|
||||
}
|
||||
else { $in = *STDIN; }
|
||||
if ($ARGV[2]) {
|
||||
$out_file = $ARGV[2];
|
||||
open($out, '>', $out_file) || die "Cannot open $out_file for output!\n";
|
||||
$msg = *STDOUT;
|
||||
}
|
||||
elsif (!$ARGV[1]) { $out = *STDOUT; }
|
||||
$msg //= *STDERR;
|
||||
|
||||
print {$msg} "Total input torrent size: ".sprintf('%.2f', (-s $in_file) / 1024)." KB\n" if $in_file;
|
||||
print {$msg} "Decoding ".($in_file || 'torrent from standard input')."...";
|
||||
my $t = bdecode(scalar <$in>);
|
||||
|
||||
die "No info key.\n" unless ref $t eq "HASH" and exists $t->{info};
|
||||
my $psize = $t->{info}{"piece length"} or die "No piece length key.\n";
|
||||
print {$msg} "done\n\n";
|
||||
|
||||
my @files;
|
||||
my $tsize = 0;
|
||||
if (exists $t->{info}{files}) {
|
||||
print {$msg} "Multi file torrent: $t->{info}{name}\n";
|
||||
for (@{$t->{info}{files}}) {
|
||||
push @files, join "/", $t->{info}{name},@{$_->{path}};
|
||||
$tsize += $_->{length};
|
||||
}
|
||||
}
|
||||
else {
|
||||
print {$msg} "Single file torrent: $t->{info}{name}\n";
|
||||
@files = ($t->{info}{name});
|
||||
$tsize = $t->{info}{length};
|
||||
}
|
||||
my $chunks = int(($tsize + $psize - 1) / $psize);
|
||||
print {$msg} "Total size: ".sprintf('%.2f', $tsize / 1024**2)." MB; $chunks chunks; ", scalar @files, " files.\n\n";
|
||||
|
||||
die "Inconsistent piece information!\n" if $chunks*20 != length $t->{info}{pieces};
|
||||
|
||||
print {$msg} "Adding fast resume information...";
|
||||
# flags => 1+16+
|
||||
|
||||
my $pmod = 0;
|
||||
$t->{libtorrent_resume}{bitfield} = $chunks;
|
||||
foreach my $f (0..$#files) {
|
||||
die "$d$files[$f] not found.\n" unless -e "$d$files[$f]";
|
||||
my $mtime = (stat "$d$files[$f]")[9];
|
||||
|
||||
# Compute number of chunks per file
|
||||
my $fsize = $t->{info}{files}[$f]{length};
|
||||
my $fchunks = ($pmod ? 1 : 0);
|
||||
if ($pmod >= $fsize) { ($fsize, $pmod ) = (0, $pmod-$fsize); }
|
||||
else { ($pmod, $fsize) = (0, $fsize-$pmod); }
|
||||
$fchunks += ceil($fsize / $psize);
|
||||
$pmod ||= $psize - ($fsize % $psize);
|
||||
|
||||
$t->{libtorrent_resume}{files}[$f] = {
|
||||
priority => 0, # Don't download; we already have the file, so don't clobber it!
|
||||
mtime => $mtime,
|
||||
completed => $fchunks,
|
||||
};
|
||||
};
|
||||
$t->{libtorrent_resume}{'uncertain_pieces.timestamp'} = time;
|
||||
|
||||
# Some extra information to re-enforce the fact that this is a finished torrent
|
||||
$d .= $t->{info}{name};
|
||||
$t->{rtorrent} = {
|
||||
state => 1, # started
|
||||
state_changed => time,
|
||||
state_counter => 1,
|
||||
chunks_wanted => 0,
|
||||
chunks_done => $chunks,
|
||||
complete => 1,
|
||||
hashing => 0, # Not hashing
|
||||
directory => File::Spec->file_name_is_absolute($d) ? $d : File::Spec->rel2abs($d),
|
||||
((tied_to_file => File::Spec->file_name_is_absolute($out_file) ? $out_file : File::Spec->rel2abs($out_file)) x!! $out_file),
|
||||
'timestamp.finished' => 0,
|
||||
'timestamp.started' => time,
|
||||
};
|
||||
|
||||
print {$msg} "done\n";
|
||||
|
||||
print {$msg} "Encoding ".($out_file || 'torrent from standard output')."...";
|
||||
seek($out, 0, 0); # just in case files are the same
|
||||
print {$out} bencode($t);
|
||||
|
||||
close($in);
|
||||
close($out);
|
||||
print {$msg} "done\n";
|
||||
exit;
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Perl script to read torrent data
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Convert::Bencode_XS qw(bdecode);
|
||||
use Data::Dumper;
|
||||
|
||||
$/ = undef;
|
||||
$| = 1;
|
||||
|
||||
my $in;
|
||||
my $in_file = $ARGV[0];
|
||||
if ($in_file) { open($in, '<', $in_file) || die "Cannot open $in_file for input!\n"; }
|
||||
else { $in = *STDIN; }
|
||||
|
||||
print "Total input torrent size: ".sprintf('%.2f', (-s $in_file) / 1024)." KB\n" if $in_file;
|
||||
print "Decoding ".($in_file || 'torrent from standard input')."...";
|
||||
my $t = bdecode(scalar <$in>);
|
||||
print "done\n\n";
|
||||
|
||||
print Data::Dumper->new([$t], ['*Torrent'])->Indent(1)->Useqq(1)->Quotekeys(0)->Sortkeys(1)->Dump;
|
||||
@@ -123,7 +123,7 @@ fi
|
||||
# which indicates that we try without any flags at all, and "pthread-config"
|
||||
# which is a program returning the flags for the Pth emulation library.
|
||||
|
||||
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
ax_pthread_flags="none pthreads -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
|
||||
# The ordering *is* (sometimes) important. Some notes on the
|
||||
# individual items follow:
|
||||
@@ -160,7 +160,7 @@ case "${host_cpu}-${host_os}" in
|
||||
;;
|
||||
|
||||
*-darwin*)
|
||||
ax_pthread_flags="-pthread $ax_pthread_flags"
|
||||
ax_pthread_flags="none -pthread $ax_pthread_flags"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
@@ -401,7 +401,7 @@ system_method_set_key(const torrent::Object::list_type& args) {
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
if (itrArgs->is_dict_key())
|
||||
if (itrArgs->is_dict_key() || itrArgs->is_list())
|
||||
control->object_storage()->set_str_multi_key_obj(key.c_str(), cmd_key, *itrArgs);
|
||||
else
|
||||
control->object_storage()->set_str_multi_key(key, cmd_key, system_method_generate_command(itrArgs, args.end()));
|
||||
|
||||
@@ -135,7 +135,7 @@ void initialize_commands();
|
||||
torrent::raw_string::from_c_str(key), tr1::placeholders::_2));
|
||||
|
||||
#define CMD2_FUNC_SINGLE(key, cmds) \
|
||||
CMD2_ANY(key, tr1::bind(&rpc::command_function_call, torrent::raw_string::from_c_str(cmds), \
|
||||
CMD2_ANY(key, tr1::bind(&rpc::command_function_call_object, torrent::Object(torrent::raw_string::from_c_str(cmds)), \
|
||||
tr1::placeholders::_1, tr1::placeholders::_2));
|
||||
|
||||
#define CMD2_REDIRECT(from_key, to_key) \
|
||||
|
||||
@@ -263,10 +263,10 @@ file_print_list(torrent::Object::list_const_iterator first, torrent::Object::lis
|
||||
while (first != last) {
|
||||
switch (first->type()) {
|
||||
case torrent::Object::TYPE_STRING:
|
||||
fprintf(output, " %s" + !(flags & file_print_use_space), first->as_string().c_str());
|
||||
fprintf(output, (const char*)" %s" + !(flags & file_print_use_space), first->as_string().c_str());
|
||||
break;
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
fprintf(output, " %lli" + !(flags & file_print_use_space), first->as_value());
|
||||
fprintf(output, (const char*)" %lli" + !(flags & file_print_use_space), first->as_value());
|
||||
break;
|
||||
case torrent::Object::TYPE_LIST:
|
||||
file_print_list(first->as_list().begin(), first->as_list().end(), output, 0);
|
||||
|
||||
+7
-29
@@ -53,8 +53,7 @@
|
||||
#include "control.h"
|
||||
#include "command_helpers.h"
|
||||
|
||||
typedef void (core::ViewManager::*view_cfilter_slot)(const std::string&, const torrent::Object&);
|
||||
typedef void (core::ViewManager::*view_event_slot)(const std::string&, const std::string&);
|
||||
typedef void (core::ViewManager::*view_event_slot)(const std::string&, const torrent::Object&);
|
||||
|
||||
torrent::Object
|
||||
apply_view_filter_on(const torrent::Object::list_type& args) {
|
||||
@@ -76,33 +75,12 @@ apply_view_filter_on(const torrent::Object::list_type& args) {
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_view_cfilter(view_cfilter_slot viewFilterSlot, const torrent::Object::list_type& args) {
|
||||
if (args.size() != 2)
|
||||
throw torrent::input_error("Too few arguments.");
|
||||
|
||||
const std::string& name = args.front().as_string();
|
||||
|
||||
if (name.empty())
|
||||
throw torrent::input_error("First argument must be a string.");
|
||||
|
||||
(control->view_manager()->*viewFilterSlot)(name, args.back());
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
apply_view_event(view_event_slot viewFilterSlot, const torrent::Object::list_type& args) {
|
||||
if (args.size() != 2)
|
||||
throw torrent::input_error("Too few arguments.");
|
||||
|
||||
const std::string& name = args.front().as_string();
|
||||
|
||||
if (name.empty())
|
||||
throw torrent::input_error("First argument must be a string.");
|
||||
|
||||
(control->view_manager()->*viewFilterSlot)(name, args.back().as_string());
|
||||
throw torrent::input_error("Wrong argument count.");
|
||||
|
||||
(control->view_manager()->*viewFilterSlot)(args.front().as_string(), args.back());
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
@@ -472,7 +450,7 @@ torrent::Object
|
||||
cmd_view_persistent(const torrent::Object::string_type& args) {
|
||||
core::View* view = *control->view_manager()->find_throw(args);
|
||||
|
||||
if (!view->get_filter().is_empty() || !view->get_event_added().empty() || !view->get_event_removed().empty())
|
||||
if (!view->get_filter().is_empty() || !view->event_added().is_empty() || !view->event_removed().is_empty())
|
||||
throw torrent::input_error("Cannot set modified views as persitent.");
|
||||
|
||||
view->set_filter("d.views.has=" + args);
|
||||
@@ -546,12 +524,12 @@ initialize_command_ui() {
|
||||
CMD2_ANY_L ("view.list", tr1::bind(&apply_view_list));
|
||||
CMD2_ANY_LIST("view.set", tr1::bind(&apply_view_set, tr1::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST("view.filter", tr1::bind(&apply_view_cfilter, &core::ViewManager::set_filter, tr1::placeholders::_2));
|
||||
CMD2_ANY_LIST("view.filter", tr1::bind(&apply_view_event, &core::ViewManager::set_filter, tr1::placeholders::_2));
|
||||
CMD2_ANY_LIST("view.filter_on", tr1::bind(&apply_view_filter_on, tr1::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST("view.sort", tr1::bind(&apply_view_sort, tr1::placeholders::_2));
|
||||
CMD2_ANY_LIST("view.sort_new", tr1::bind(&apply_view_cfilter, &core::ViewManager::set_sort_new, tr1::placeholders::_2));
|
||||
CMD2_ANY_LIST("view.sort_current", tr1::bind(&apply_view_cfilter, &core::ViewManager::set_sort_current, tr1::placeholders::_2));
|
||||
CMD2_ANY_LIST("view.sort_new", tr1::bind(&apply_view_event, &core::ViewManager::set_sort_new, tr1::placeholders::_2));
|
||||
CMD2_ANY_LIST("view.sort_current", tr1::bind(&apply_view_event, &core::ViewManager::set_sort_current, tr1::placeholders::_2));
|
||||
|
||||
CMD2_ANY_LIST("view.event_added", tr1::bind(&apply_view_event, &core::ViewManager::set_event_added, tr1::placeholders::_2));
|
||||
CMD2_ANY_LIST("view.event_removed", tr1::bind(&apply_view_event, &core::ViewManager::set_event_removed, tr1::placeholders::_2));
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ Manager::get_throttle(const std::string& name) {
|
||||
void
|
||||
Manager::set_address_throttle(uint32_t begin, uint32_t end, torrent::ThrottlePair throttles) {
|
||||
m_addressThrottles.set_merge(begin, end, throttles);
|
||||
torrent::connection_manager()->set_address_throttle(sigc::mem_fun(control->core(), &core::Manager::get_address_throttle));
|
||||
torrent::connection_manager()->address_throttle() = tr1::bind(&core::Manager::get_address_throttle, control->core(), tr1::placeholders::_1);
|
||||
}
|
||||
|
||||
torrent::ThrottlePair
|
||||
|
||||
+11
-9
@@ -184,7 +184,7 @@ View::erase(Download* download) {
|
||||
|
||||
} else {
|
||||
erase_internal(itr);
|
||||
rpc::parse_command_multiple_d_nothrow(download, m_eventRemoved);
|
||||
rpc::call_object_nothrow(m_event_removed, rpc::make_target(download));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ View::set_visible(Download* download) {
|
||||
base_type::erase(itr);
|
||||
insert_visible(download);
|
||||
|
||||
rpc::parse_command_multiple_d_nothrow(download, m_eventAdded);
|
||||
rpc::call_object_nothrow(m_event_added, rpc::make_target(download));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -218,7 +218,7 @@ View::set_not_visible(Download* download) {
|
||||
base_type::erase(itr);
|
||||
base_type::push_back(download);
|
||||
|
||||
rpc::parse_command_multiple_d_nothrow(download, m_eventRemoved);
|
||||
rpc::call_object_nothrow(m_event_removed, rpc::make_target(download));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -275,11 +275,13 @@ View::filter() {
|
||||
// done by using a base_type* member variable, and making sure we
|
||||
// set the elements to NULL as we trigger commands on them. Or
|
||||
// perhaps always clear them, thus not throwing anything.
|
||||
if (!m_eventRemoved.empty())
|
||||
std::for_each(changed.begin(), splitChanged, rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_d_nothrow), m_eventRemoved));
|
||||
if (!m_event_removed.is_empty())
|
||||
std::for_each(changed.begin(), splitChanged,
|
||||
tr1::bind(&rpc::call_object_d_nothrow, m_event_removed, tr1::placeholders::_1));
|
||||
|
||||
if (!m_eventAdded.empty())
|
||||
std::for_each(splitChanged, changed.end(), rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_d_nothrow), m_eventAdded));
|
||||
if (!m_event_added.is_empty())
|
||||
std::for_each(changed.begin(), splitChanged,
|
||||
tr1::bind(&rpc::call_object_d_nothrow, m_event_added, tr1::placeholders::_1));
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
@@ -297,7 +299,7 @@ View::filter_download(core::Download* download) {
|
||||
erase_internal(itr);
|
||||
insert_visible(download);
|
||||
|
||||
rpc::parse_command_multiple_d_nothrow(download, m_eventAdded);
|
||||
rpc::call_object_nothrow(m_event_added, rpc::make_target(download));
|
||||
|
||||
} else {
|
||||
// This makes sure the download is sorted even if it is
|
||||
@@ -315,7 +317,7 @@ View::filter_download(core::Download* download) {
|
||||
erase_internal(itr);
|
||||
base_type::push_back(download);
|
||||
|
||||
rpc::parse_command_multiple_d_nothrow(download, m_eventRemoved);
|
||||
rpc::call_object_nothrow(m_event_removed, rpc::make_target(download));
|
||||
}
|
||||
|
||||
emit_changed();
|
||||
|
||||
+6
-6
@@ -127,10 +127,10 @@ public:
|
||||
|
||||
void clear_filter_on();
|
||||
|
||||
const std::string& get_event_added() const { return m_eventAdded; }
|
||||
const std::string& get_event_removed() const { return m_eventRemoved; }
|
||||
void set_event_added(const std::string& cmd) { m_eventAdded = cmd; }
|
||||
void set_event_removed(const std::string& cmd) { m_eventRemoved = cmd; }
|
||||
const torrent::Object& event_added() const { return m_event_added; }
|
||||
const torrent::Object& event_removed() const { return m_event_removed; }
|
||||
void set_event_added(const torrent::Object& cmd) { m_event_added = cmd; }
|
||||
void set_event_removed(const torrent::Object& cmd) { m_event_removed = cmd; }
|
||||
|
||||
// The time of the last change to the view, semantics of this is
|
||||
// user-dependent. Used by f.ex. ViewManager to decide if it should
|
||||
@@ -171,8 +171,8 @@ private:
|
||||
|
||||
torrent::Object m_filter;
|
||||
|
||||
std::string m_eventAdded;
|
||||
std::string m_eventRemoved;
|
||||
torrent::Object m_event_added;
|
||||
torrent::Object m_event_removed;
|
||||
|
||||
rak::timer m_lastChanged;
|
||||
|
||||
|
||||
@@ -95,8 +95,8 @@ public:
|
||||
void set_filter(const std::string& name, const torrent::Object& cmd);
|
||||
void set_filter_on(const std::string& name, const filter_args& args);
|
||||
|
||||
void set_event_added(const std::string& name, const std::string& cmd) { (*find_throw(name))->set_event_added(cmd); }
|
||||
void set_event_removed(const std::string& name, const std::string& cmd) { (*find_throw(name))->set_event_removed(cmd); }
|
||||
void set_event_added(const std::string& name, const torrent::Object& cmd) { (*find_throw(name))->set_event_added(cmd); }
|
||||
void set_event_removed(const std::string& name, const torrent::Object& cmd) { (*find_throw(name))->set_event_removed(cmd); }
|
||||
|
||||
private:
|
||||
DownloadList* m_list;
|
||||
|
||||
+9
-19
@@ -266,8 +266,8 @@ main(int argc, char** argv) {
|
||||
|
||||
"method.set_key = event.download.inserted, 1_connect_logs, ((d.initialize_logs))\n"
|
||||
"method.set_key = event.download.inserted, 1_send_scrape, ((d.tracker.send_scrape,30))\n"
|
||||
"method.set_key = event.download.inserted_new, 1_prepare, \"branch=d.state=,view.set_visible=started,view.set_visible=stopped ;d.save_full_session=\"\n"
|
||||
"method.set_key = event.download.inserted_session, 1_prepare, \"branch=d.state=,view.set_visible=started,view.set_visible=stopped\"\n"
|
||||
"method.set_key = event.download.inserted_new, 1_prepare, {(branch,((d.state)),((view.set_visible,started)),((view.set_visible,stopped)) ),(d.save_full_session)}\n"
|
||||
"method.set_key = event.download.inserted_session, 1_prepare, {(branch,((d.state)),((view.set_visible,started)),((view.set_visible,stopped)) )}\n"
|
||||
|
||||
"method.set_key = event.download.inserted, 1_prioritize_toc, \"branch=file.prioritize_toc=,{\\\"f.multicall=(file.prioritize_toc.first),f.prioritize_first.enable=\\\",\\\"f.multicall=(file.prioritize_toc.last),f.prioritize_last.enable=\\\",d.update_priorities=}\"\n"
|
||||
|
||||
@@ -293,7 +293,7 @@ main(int argc, char** argv) {
|
||||
|
||||
"group.insert = seeding,seeding\n"
|
||||
|
||||
"session.name.set = \"$cat=$system.hostname=,:,$system.pid=\"\n"
|
||||
"session.name.set = (cat,(system.hostname),:,(system.pid))\n"
|
||||
|
||||
// Currently not doing any sorting on main.
|
||||
"view.add = main\n"
|
||||
@@ -308,46 +308,36 @@ main(int argc, char** argv) {
|
||||
|
||||
"view.add = started\n"
|
||||
"view.filter = started,((false))\n"
|
||||
"view.event_added = started,\"view.set_not_visible=stopped ;d.state.set=1 ;scheduler.simple.added=\"\n"
|
||||
"view.event_removed = started,\"view.set_visible=stopped ;scheduler.simple.removed=\"\n"
|
||||
"view.event_added = started,{(view.set_not_visible,stopped),(d.state.set,1),(scheduler.simple.added)}\n"
|
||||
"view.event_removed = started,{(view.set_visible,stopped),(scheduler.simple.removed)}\n"
|
||||
|
||||
"view.add = stopped\n"
|
||||
"view.filter = stopped,((false))\n"
|
||||
"view.event_added = stopped,\"d.state.set=0 ;view.set_not_visible=started\"\n"
|
||||
"view.event_removed = stopped,view.set_visible=started\n"
|
||||
"view.event_added = stopped,{(d.state.set,0),(view.set_not_visible,started)}\n"
|
||||
"view.event_removed = stopped,((view.set_visible,started))\n"
|
||||
|
||||
"view.add = complete\n"
|
||||
"view.filter = complete,((d.complete))\n"
|
||||
"view.filter_on = complete,event.download.hash_done,event.download.hash_failed,event.download.hash_final_failed,event.download.finished\n"
|
||||
// "view.sort_new = complete,((less,((d.state_changed))))\n"
|
||||
// "view.sort_current = complete,((less,((d.state_changed))))\n"
|
||||
|
||||
"view.add = incomplete\n"
|
||||
"view.filter = incomplete,((not,((d.complete))))\n"
|
||||
"view.filter_on = incomplete,event.download.hash_done,event.download.hash_failed,"
|
||||
"event.download.hash_final_failed,event.download.finished\n"
|
||||
// "view.sort_new = incomplete,((less,((d.state_changed))))\n"
|
||||
// "view.sort_current = incomplete,((less,((d.state_changed))))\n"
|
||||
|
||||
// The hashing view does not include stopped torrents.
|
||||
"view.add = hashing\n"
|
||||
"view.filter = hashing,((d.hashing))\n"
|
||||
"view.filter_on = hashing,event.download.hash_queued,event.download.hash_removed,"
|
||||
"event.download.hash_done,event.download.hash_failed,event.download.hash_final_failed,event.download.finished\n"
|
||||
// "view.sort_new = hashing,less=d.state_changed=\n"
|
||||
// "view.sort_current = hashing,less=d.state_changed=\n"
|
||||
|
||||
"view.add = seeding\n"
|
||||
"view.filter = seeding,((and,((d.state)),((d.complete))))\n"
|
||||
"view.filter_on = seeding,event.download.resumed,event.download.paused,event.download.finished\n"
|
||||
// "view.sort_new = seeding,((less,((d.state_changed))))\n"
|
||||
// "view.sort_current = seeding,((less,((d.state_changed))))\n"
|
||||
"view.filter_on = seeding,event.download.resumed,event.download.paused,event.download.finished\n"
|
||||
|
||||
"view.add = leeching\n"
|
||||
"view.filter = leeching,((and,((d.state)),((not,((d.complete))))))\n"
|
||||
"view.filter_on = leeching,event.download.resumed,event.download.paused,event.download.finished\n"
|
||||
// "view.sort_new = leeching,((less,((d.state_changed))))\n"
|
||||
// "view.sort_current = leeching,((less,((d.state_changed))))\n"
|
||||
"view.filter_on = leeching,event.download.resumed,event.download.paused,event.download.finished\n"
|
||||
|
||||
"schedule2 = view.main,10,10,((view.sort,main,20))\n"
|
||||
"schedule2 = view.name,10,10,((view.sort,name,20))\n"
|
||||
|
||||
@@ -97,24 +97,7 @@ CommandScheduler::call_item(value_type item) {
|
||||
// removed.
|
||||
|
||||
try {
|
||||
if (item->command().is_string()) {
|
||||
rpc::parse_command_multiple_std(item->command().as_string());
|
||||
|
||||
} else if (item->command().is_dict_key()) {
|
||||
// This can/should be optimized...
|
||||
torrent::Object tmp_command = item->command();
|
||||
|
||||
// Unquote the root function object so 'parse_command_execute'
|
||||
// doesn't end up calling it.
|
||||
//
|
||||
// TODO: Only call this if mask_function is set?
|
||||
uint32_t flags = tmp_command.flags() & torrent::Object::mask_function;
|
||||
tmp_command.unset_flags(torrent::Object::mask_function);
|
||||
tmp_command.set_flags((flags >> 1) & torrent::Object::mask_function);
|
||||
|
||||
rpc::parse_command_execute(rpc::make_target(), &tmp_command);
|
||||
rpc::commands.call_command(tmp_command.as_dict_key().c_str(), tmp_command.as_dict_obj());
|
||||
}
|
||||
rpc::call_object(item->command());
|
||||
|
||||
} catch (torrent::input_error& e) {
|
||||
if (m_slotErrorMessage.is_valid())
|
||||
|
||||
@@ -181,9 +181,8 @@ object_storage::call_function(const torrent::raw_string& key, target_type target
|
||||
|
||||
switch (itr->second.flags & mask_type) {
|
||||
case flag_function_type:
|
||||
return command_function_call_object(itr->second.object, target, object);
|
||||
case flag_multi_type:
|
||||
return command_function_multi_call(itr->second.object.as_map(), target, object);
|
||||
return command_function_call_object(itr->second.object, target, object);
|
||||
default:
|
||||
throw torrent::input_error("Key not found or wrong type.");
|
||||
}
|
||||
@@ -219,7 +218,7 @@ object_storage::erase_multi_key(const torrent::raw_string& key, const std::strin
|
||||
|
||||
void
|
||||
object_storage::set_multi_key_obj(const torrent::raw_string& key, const std::string& cmd_key, const torrent::Object& object) {
|
||||
if (!object.is_string() && !object.is_dict_key())
|
||||
if (!object.is_string() && !object.is_dict_key() && !object.is_list())
|
||||
throw torrent::input_error("Object is wrong type.");
|
||||
|
||||
local_iterator itr = find_local_mutable(key, flag_multi_type);
|
||||
|
||||
+42
-99
@@ -181,11 +181,6 @@ parse_command_multiple(target_type target, const char* first, const char* last)
|
||||
return result.first;
|
||||
}
|
||||
|
||||
parse_command_type
|
||||
parse_command_object(target_type target, const torrent::Object& object) {
|
||||
return parse_command(target, object.as_string().c_str(), object.as_string().c_str() + object.as_string().size());
|
||||
}
|
||||
|
||||
bool
|
||||
parse_command_file(const std::string& path) {
|
||||
std::fstream file(rak::path_expand(path).c_str(), std::ios::in);
|
||||
@@ -239,35 +234,55 @@ parse_command_file(const std::string& path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
torrent::Object
|
||||
call_object(const torrent::Object& command, target_type target) {
|
||||
switch (command.type()) {
|
||||
case torrent::Object::TYPE_RAW_STRING:
|
||||
return parse_command_multiple(target, command.as_raw_string().begin(), command.as_raw_string().end());
|
||||
case torrent::Object::TYPE_STRING:
|
||||
return parse_command_multiple(target, command.as_string().c_str(), command.as_string().c_str() + command.as_string().size());
|
||||
|
||||
// Temp until it can be moved somewhere better...
|
||||
const torrent::Object
|
||||
command_function_call(const torrent::raw_string& cmd, target_type target, const torrent::Object& args) {
|
||||
rpc::command_base::stack_type stack;
|
||||
torrent::Object* last_stack;
|
||||
case torrent::Object::TYPE_LIST:
|
||||
{
|
||||
torrent::Object result;
|
||||
|
||||
if (args.is_list())
|
||||
last_stack = rpc::command_base::push_stack(args.as_list(), &stack);
|
||||
else if (args.type() != torrent::Object::TYPE_NONE)
|
||||
last_stack = rpc::command_base::push_stack(&args, &args + 1, &stack);
|
||||
else
|
||||
last_stack = rpc::command_base::push_stack(NULL, NULL, &stack);
|
||||
for (torrent::Object::list_const_iterator itr = command.as_list().begin(), last = command.as_list().end(); itr != last; itr++)
|
||||
result = call_object(*itr, target);
|
||||
|
||||
try {
|
||||
torrent::Object result = parse_command_multiple(target, cmd.begin(), cmd.end());
|
||||
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
return result;
|
||||
}
|
||||
case torrent::Object::TYPE_MAP:
|
||||
{
|
||||
for (torrent::Object::map_const_iterator itr = command.as_map().begin(), last = command.as_map().end(); itr != last; itr++)
|
||||
call_object(itr->second, target);
|
||||
|
||||
} catch (torrent::bencode_error& e) {
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
throw e;
|
||||
return torrent::Object();
|
||||
}
|
||||
case torrent::Object::TYPE_DICT_KEY:
|
||||
{
|
||||
// This can/should be optimized...
|
||||
torrent::Object tmp_command = command;
|
||||
|
||||
// Unquote the root function object so 'parse_command_execute'
|
||||
// doesn't end up calling it.
|
||||
//
|
||||
// TODO: Only call this if mask_function is set?
|
||||
uint32_t flags = tmp_command.flags() & torrent::Object::mask_function;
|
||||
tmp_command.unset_flags(torrent::Object::mask_function);
|
||||
tmp_command.set_flags((flags >> 1) & torrent::Object::mask_function);
|
||||
|
||||
parse_command_execute(make_target(), &tmp_command);
|
||||
return commands.call_command(tmp_command.as_dict_key().c_str(), tmp_command.as_dict_obj(), target);
|
||||
}
|
||||
default:
|
||||
return torrent::Object();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
const torrent::Object
|
||||
command_function_call_object(const torrent::Object& cmd, target_type target, const torrent::Object& args) {
|
||||
rpc::command_base::stack_type stack;
|
||||
@@ -281,34 +296,7 @@ command_function_call_object(const torrent::Object& cmd, target_type target, con
|
||||
last_stack = rpc::command_base::push_stack(NULL, NULL, &stack);
|
||||
|
||||
try {
|
||||
torrent::Object result;
|
||||
|
||||
if (cmd.is_string()) {
|
||||
result = parse_command_multiple(target, cmd.as_string().c_str(), cmd.as_string().c_str() + cmd.as_string().size());
|
||||
|
||||
} else if (cmd.is_list()){
|
||||
for (torrent::Object::list_const_iterator first = cmd.as_list().begin(), last = cmd.as_list().end(); first != last; first++) {
|
||||
torrent::Object tmp_cmd = *first;
|
||||
|
||||
rpc::parse_command_execute(target, &tmp_cmd);
|
||||
result = rpc::commands.call_command(tmp_cmd.as_dict_key().c_str(), tmp_cmd.as_dict_obj());
|
||||
}
|
||||
|
||||
} else {
|
||||
torrent::Object tmp_command = cmd;
|
||||
|
||||
// Unquote the root function object so 'parse_command_execute'
|
||||
// doesn't end up calling it.
|
||||
//
|
||||
// TODO: Only call this if mask_function is set?
|
||||
uint32_t flags = tmp_command.flags() & torrent::Object::mask_function;
|
||||
tmp_command.unset_flags(torrent::Object::mask_function);
|
||||
tmp_command.set_flags((flags >> 1) & torrent::Object::mask_function);
|
||||
|
||||
rpc::parse_command_execute(target, &tmp_command);
|
||||
rpc::commands.call_command(tmp_command.as_dict_key().c_str(), tmp_command.as_dict_obj(), target);
|
||||
}
|
||||
|
||||
torrent::Object result = call_object(cmd, target);
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
return result;
|
||||
|
||||
@@ -318,49 +306,4 @@ command_function_call_object(const torrent::Object& cmd, target_type target, con
|
||||
}
|
||||
}
|
||||
|
||||
const torrent::Object
|
||||
command_function_multi_call(const torrent::Object::map_type& cmd, target_type target, const torrent::Object& args) {
|
||||
rpc::command_base::stack_type stack;
|
||||
torrent::Object* last_stack;
|
||||
|
||||
if (args.is_list())
|
||||
last_stack = rpc::command_base::push_stack(args.as_list(), &stack);
|
||||
else if (args.type() != torrent::Object::TYPE_NONE)
|
||||
last_stack = rpc::command_base::push_stack(&args, &args + 1, &stack);
|
||||
else
|
||||
last_stack = rpc::command_base::push_stack(NULL, NULL, &stack);
|
||||
|
||||
try {
|
||||
for (torrent::Object::map_const_iterator itr = cmd.begin(), last = cmd.end(); itr != last; itr++) {
|
||||
if (itr->second.is_dict_key()) {
|
||||
// This can/should be optimized...
|
||||
torrent::Object tmp_command = itr->second;
|
||||
|
||||
// Unquote the root function object so 'parse_command_execute'
|
||||
// doesn't end up calling it.
|
||||
//
|
||||
// TODO: Only call this if mask_function is set?
|
||||
uint32_t flags = tmp_command.flags() & torrent::Object::mask_function;
|
||||
tmp_command.unset_flags(torrent::Object::mask_function);
|
||||
tmp_command.set_flags((flags >> 1) & torrent::Object::mask_function);
|
||||
|
||||
rpc::parse_command_execute(target, &tmp_command);
|
||||
rpc::commands.call_command(tmp_command.as_dict_key().c_str(), tmp_command.as_dict_obj(), target);
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string& cmd_str = itr->second.as_string();
|
||||
parse_command_multiple(target, cmd_str.c_str(), cmd_str.c_str() + cmd_str.size());
|
||||
}
|
||||
|
||||
} catch (torrent::bencode_error& e) {
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
throw e;
|
||||
}
|
||||
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -64,9 +64,6 @@ torrent::Object parse_command_multiple(target_type target, const char* fi
|
||||
|
||||
void parse_command_execute(target_type target, torrent::Object* object);
|
||||
|
||||
// Make this take care of lists too.
|
||||
parse_command_type parse_command_object(target_type target, const torrent::Object& object);
|
||||
|
||||
inline torrent::Object parse_command_single(target_type target, const char* first) { return parse_command(target, first, first + std::strlen(first)).first; }
|
||||
inline torrent::Object parse_command_multiple(target_type target, const char* first) { return parse_command_multiple(target, first, first + std::strlen(first)); }
|
||||
|
||||
@@ -124,21 +121,28 @@ call_command_d_range(const char* key, core::Download* download, torrent::Object:
|
||||
return commands.call_command_d(key, download, rawArgs);
|
||||
}
|
||||
|
||||
torrent::Object call_object(const torrent::Object& command, target_type target = make_target());
|
||||
|
||||
inline torrent::Object
|
||||
call_object_nothrow(const torrent::Object& command, target_type target = make_target()) {
|
||||
try { return call_object(command, target); } catch (torrent::input_error& e) { return torrent::Object(); }
|
||||
}
|
||||
|
||||
inline torrent::Object
|
||||
call_object_d_nothrow(const torrent::Object& command, core::Download* download) {
|
||||
try { return call_object(command, make_target(download)); } catch (torrent::input_error& e) { return torrent::Object(); }
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
// Temp until it can be moved somewhere better...
|
||||
const torrent::Object
|
||||
command_function_call(const torrent::raw_string& cmd, target_type target, const torrent::Object& args);
|
||||
const torrent::Object
|
||||
command_function_call_object(const torrent::Object& cmd, target_type target, const torrent::Object& args);
|
||||
const torrent::Object
|
||||
command_function_multi_call(const torrent::Object::map_type& cmd, target_type target, const torrent::Object& args);
|
||||
|
||||
inline const torrent::Object
|
||||
command_function_call_str(const std::string& cmd, target_type target, const torrent::Object& args) {
|
||||
return command_function_call(torrent::raw_string::from_string(cmd), target, args);
|
||||
return command_function_call_object(torrent::Object(cmd), target, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user