diff --git a/Makefile.am b/Makefile.am
index 7364aa5e..240e0972 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,6 +7,7 @@ EXTRA_DIST= \
rak/algorithm.h \
rak/error_number.h \
rak/functional.h \
+ rak/functional_fun.h \
rak/string_manip.h \
rak/timer.h \
rak/unordered_vector.h \
diff --git a/doc/rtorrent.1.xml b/doc/rtorrent.1.xml
index 198652c5..9d134ed9 100644
--- a/doc/rtorrent.1.xml
+++ b/doc/rtorrent.1.xml
@@ -394,6 +394,15 @@
+
+ http_proxy = url
+
+
+ Use a http proxy. Use an empty string to disable.
+
+
+
+
encoding_list = encoding
@@ -464,22 +473,32 @@
- throttle_interval = ms
+ umask = 0644
- Interval between throttle ticks in milli-seconds, must be
- between 1-5000 and defaults to
- 1000. Shorter intervals will cause less
- bandwidth usage spikes while requiring more CPU resources.
+
+ Set the umask for this process, which is applied to all
+ files created by the program.
+
-
- tracker_dump = yes | no
-
- Dump data received from trackers to the files
- "./tracker_dump.*".
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rak/functional_fun.h b/rak/functional_fun.h
new file mode 100644
index 00000000..7d4dc850
--- /dev/null
+++ b/rak/functional_fun.h
@@ -0,0 +1,149 @@
+// rak - Rakshasa's toolbox
+// Copyright (C) 2005, Jari Sundell
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// In addition, as a special exception, the copyright holders give
+// permission to link the code of portions of this program with the
+// OpenSSL library under certain conditions as described in each
+// individual source file, and distribute linked combinations
+// including the two.
+//
+// You must obey the GNU General Public License in all respects for
+// all of the code used other than OpenSSL. If you modify file(s)
+// with this exception, you may extend this exception to your version
+// of the file(s), but you are not obligated to do so. If you do not
+// wish to do so, delete this exception statement from your version.
+// If you delete this exception statement from all source files in the
+// program, then also delete it here.
+//
+// Contact: Jari Sundell
+//
+// Skomakerveien 33
+// 3185 Skoppum, NORWAY
+
+// This file contains functors that wrap function points and member
+// function pointers.
+//
+// 'fn' functors are polymorphic and derives from 'rak::function' and
+// thus is less strict about types, this adds the cost of calling a
+// virtual function.
+//
+// 'fun' functors are non-polymorphic and thus cheaper, but requires
+// the target object's type in the functor's template arguments.
+//
+// This should be replaced with TR1 stuff when it becomes widely
+// available. At the moment it behaves like std::auto_ptr, so be
+// careful when copying.
+
+#ifndef RAK_FUNCTIONAL_FUN_H
+#define RAK_FUNCTIONAL_FUN_H
+
+namespace rak {
+
+template
+class function_base {
+public:
+ virtual ~function_base() {}
+
+ virtual _Result operator () () = 0;
+};
+
+template
+struct function_ref {
+ explicit function_ref(_Base* b) : m_base(b) {}
+
+ _Base* m_base;
+};
+
+template
+class function {
+public:
+ typedef _Result result_type;
+ typedef function_base<_Result> _Base;
+
+ function() : m_base(0) {}
+ function(function_ref<_Base> f) : m_base(f.m_base) {}
+ explicit function(function_base<_Result>* base) { m_base = base; }
+
+ ~function() { delete m_base; }
+
+ function& operator = (function& f) { m_base = f.release(); return *this; }
+
+ function& operator = (function_ref<_Base> f) {
+ if (m_base != f.m_base) {
+ delete m_base;
+ m_base = f.m_base;
+ }
+
+ return *this;
+ }
+
+ template
+ operator function_ref<_T> () { return function_ref<_T>(this->release()); }
+
+ _Result operator () () { return (*m_base)(); }
+
+private:
+ _Base* release() { _Base* tmp = m_base; m_base = 0; return tmp; }
+
+ _Base* m_base;
+};
+
+template
+class _mem_fn0 : public function_base<_Result> {
+public:
+ typedef _Result (_Object::*_Func)();
+
+ _mem_fn0(_Object* object, _Func func) : m_object(object), m_func(func) {}
+ virtual ~_mem_fn0() {}
+
+ virtual _Result operator () () { return (m_object->*m_func)(); }
+
+private:
+ _Object* m_object;
+ _Func m_func;
+};
+
+template
+class _const_mem_fn0 : public function_base<_Result> {
+public:
+ typedef _Result (_Object::*_Func)() const;
+
+ _const_mem_fn0(const _Object* object, _Func func) : m_object(object), m_func(func) {}
+ virtual ~_const_mem_fn0() {}
+
+ virtual _Result operator () () { return (m_object->*m_func)(); }
+
+private:
+ const _Object* m_object;
+ _Func m_func;
+};
+
+template
+function<_Result>
+mem_fn(_Object* object, _Result (_Object::*func)()) {
+ return function<_Result>(static_cast*>(new _mem_fn0<_Object, _Result>(object, func)));
+}
+
+template
+function<_Result>
+mem_fn(const _Object* object, _Result (_Object::*func)() const) {
+ return function<_Result>(static_cast*>(new _const_mem_fn0<_Object, _Result>(object, func)));
+}
+
+}
+
+#endif
diff --git a/src/control.cc b/src/control.cc
index b5a65b90..e1d28875 100644
--- a/src/control.cc
+++ b/src/control.cc
@@ -60,7 +60,7 @@ Control::Control() :
m_inputStdin->slot_pressed(sigc::mem_fun(m_input, &input::Manager::pressed));
m_taskShutdown.set_iterator(taskScheduler.end());
- m_taskShutdown.set_slot(sigc::mem_fun(*this, &Control::receive_shutdown));
+ m_taskShutdown.set_slot(rak::mem_fn(this, &Control::receive_shutdown));
}
Control::~Control() {
diff --git a/src/core/curl_get.cc b/src/core/curl_get.cc
index 5f6750ea..5b52edab 100644
--- a/src/core/curl_get.cc
+++ b/src/core/curl_get.cc
@@ -132,6 +132,11 @@ CurlGet::set_user_agent(const char* s) {
curl_easy_setopt(m_handle, CURLOPT_USERAGENT, s);
}
+void
+CurlGet::set_http_proxy(const char* s) {
+ curl_easy_setopt(m_handle, CURLOPT_PROXY, s);
+}
+
void
CurlGet::perform(CURLMsg* msg) {
if (msg->msg != CURLMSG_DONE)
diff --git a/src/core/curl_get.h b/src/core/curl_get.h
index fbd42893..17c43ea1 100644
--- a/src/core/curl_get.h
+++ b/src/core/curl_get.h
@@ -67,6 +67,7 @@ class CurlGet : public torrent::Http {
double size_total();
void set_user_agent(const char* s);
+ void set_http_proxy(const char* s);
protected:
CURL* handle() { return m_handle; }
diff --git a/src/core/curl_stack.cc b/src/core/curl_stack.cc
index e52acb36..13a419d2 100644
--- a/src/core/curl_stack.cc
+++ b/src/core/curl_stack.cc
@@ -103,7 +103,11 @@ CurlStack::fdset(fd_set* readfds, fd_set* writefds, fd_set* exceptfds) {
void
CurlStack::add_get(CurlGet* get) {
- get->set_user_agent(m_userAgent.c_str());
+ if (!m_userAgent.empty())
+ get->set_user_agent(m_userAgent.c_str());
+
+ if (!m_httpProxy.empty())
+ get->set_http_proxy(m_httpProxy.c_str());
CURLMcode code;
diff --git a/src/core/curl_stack.h b/src/core/curl_stack.h
index 41be3639..ad5b36d3 100644
--- a/src/core/curl_stack.h
+++ b/src/core/curl_stack.h
@@ -68,6 +68,9 @@ class CurlStack {
const std::string& user_agent() const { return m_userAgent; }
void set_user_agent(const std::string& s) { m_userAgent = s; }
+ const std::string& http_proxy() const { return m_httpProxy; }
+ void set_http_proxy(const std::string& s) { m_httpProxy = s; }
+
static void global_init();
static void global_cleanup();
@@ -85,6 +88,7 @@ class CurlStack {
CurlGetList m_getList;
std::string m_userAgent;
+ std::string m_httpProxy;
};
}
diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc
index 14511bd8..359ece6b 100644
--- a/src/core/download_factory.cc
+++ b/src/core/download_factory.cc
@@ -61,10 +61,10 @@ DownloadFactory::DownloadFactory(const std::string& uri, Manager* m) :
m_start(false) {
m_taskLoad.set_iterator(taskScheduler.end());
- m_taskLoad.set_slot(sigc::mem_fun(*this, &DownloadFactory::receive_load));
+ m_taskLoad.set_slot(rak::mem_fn(this, &DownloadFactory::receive_load));
m_taskCommit.set_iterator(taskScheduler.end());
- m_taskCommit.set_slot(sigc::mem_fun(*this, &DownloadFactory::receive_commit));
+ m_taskCommit.set_slot(rak::mem_fn(this, &DownloadFactory::receive_commit));
}
DownloadFactory::~DownloadFactory() {
diff --git a/src/display/window.cc b/src/display/window.cc
index d8fbd3a2..5107a620 100644
--- a/src/display/window.cc
+++ b/src/display/window.cc
@@ -51,7 +51,7 @@ Window::Window(Canvas* c, bool d, int h) :
m_minHeight(h) {
m_taskUpdate.set_iterator(displayScheduler.end());
- m_taskUpdate.set_slot(sigc::mem_fun(*this, &Window::redraw));
+ m_taskUpdate.set_slot(rak::mem_fn(this, &Window::redraw));
}
Window::~Window() {
diff --git a/src/main.cc b/src/main.cc
index 43672f09..a28fe416 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -136,6 +136,8 @@ initialize_option_handler(Control* c, OptionHandler* optionHandler) {
optionHandler->insert("max_open_files", new OptionHandlerInt(c, &apply_max_open_files));
optionHandler->insert("max_open_sockets", new OptionHandlerInt(c, &apply_max_open_sockets));
+ optionHandler->insert("umask", new OptionHandlerOctal(c, &apply_umask));
+
optionHandler->insert("connection_leech", new OptionHandlerString(c, &apply_connection_leech));
optionHandler->insert("connection_seed", new OptionHandlerString(c, &apply_connection_seed));
@@ -143,6 +145,8 @@ initialize_option_handler(Control* c, OptionHandler* optionHandler) {
optionHandler->insert("encoding_list", new OptionHandlerString(c, &apply_encoding_list));
optionHandler->insert("tracker_dump", new OptionHandlerString(c, &apply_tracker_dump));
optionHandler->insert("use_udp_trackers", new OptionHandlerString(c, &apply_use_udp_trackers));
+
+ optionHandler->insert("http_proxy", new OptionHandlerString(c, &apply_http_proxy));
}
void
diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc
index da533a93..e23abbcd 100644
--- a/src/option_handler_rules.cc
+++ b/src/option_handler_rules.cc
@@ -37,9 +37,11 @@
#include "config.h"
#include
+#include
+#include
+#include
#include
#include
-#include
#include "core/manager.h"
#include "ui/root.h"
@@ -55,7 +57,17 @@ OptionHandlerInt::process(const std::string& key, const std::string& arg) {
int a;
if (std::sscanf(arg.c_str(), "%i", &a) != 1)
- throw torrent::input_error("Invalid argument for \"" + key + "\": \"" + arg + "\"");
+ throw torrent::input_error("Invalid argument for \"" + key + "\": \"" + arg + "\", must be an integer.");
+
+ m_apply(m_control, a);
+}
+
+void
+OptionHandlerOctal::process(const std::string& key, const std::string& arg) {
+ int a;
+
+ if (std::sscanf(arg.c_str(), "%o", &a) != 1)
+ throw torrent::input_error("Invalid argument for \"" + key + "\": \"" + arg + "\", must be an octal.");
m_apply(m_control, a);
}
@@ -110,6 +122,11 @@ apply_global_upload_rate(Control* m, int arg) {
m->ui()->set_up_throttle(arg);
}
+void
+apply_umask(Control* m, int arg) {
+ umask(arg);
+}
+
void
apply_hash_read_ahead(Control* m, int arg) {
torrent::set_hash_read_ahead(arg << 20);
@@ -185,6 +202,11 @@ apply_check_hash(Control* m, const std::string& arg) {
m->core()->set_check_hash(false);
}
+void
+apply_http_proxy(Control* m, const std::string& arg) {
+ m->core()->get_poll_manager()->get_http_stack()->set_http_proxy(arg);
+}
+
void
apply_session_directory(Control* m, const std::string& arg) {
m->core()->get_download_store().use(arg);
diff --git a/src/option_handler_rules.h b/src/option_handler_rules.h
index e8eb9c9f..82b09280 100644
--- a/src/option_handler_rules.h
+++ b/src/option_handler_rules.h
@@ -59,6 +59,8 @@ void apply_connection_seed(Control* m, const std::string& arg);
void apply_global_download_rate(Control* m, int arg);
void apply_global_upload_rate(Control* m, int arg);
+void apply_umask(Control* m, int arg);
+
void apply_hash_read_ahead(Control* m, int arg);
void apply_hash_interval(Control* m, int arg);
void apply_hash_max_tries(Control* m, int arg);
@@ -73,6 +75,8 @@ void apply_tracker_dump(Control* m, const std::string& arg);
void apply_use_udp_trackers(Control* m, const std::string& arg);
void apply_check_hash(Control* m, const std::string& arg);
+void apply_http_proxy(Control* m, const std::string& arg);
+
void apply_session_directory(Control* m, const std::string& arg);
void apply_encoding_list(Control* m, const std::string& arg);
@@ -90,6 +94,20 @@ private:
Apply m_apply;
};
+class OptionHandlerOctal : public OptionHandlerBase {
+public:
+ typedef void (*Apply)(Control*, int);
+
+ OptionHandlerOctal(Control* c, Apply a) :
+ m_control(c), m_apply(a) {}
+
+ virtual void process(const std::string& key, const std::string& arg);
+
+private:
+ Control* m_control;
+ Apply m_apply;
+};
+
class OptionHandlerString : public OptionHandlerBase {
public:
typedef void (*Apply)(Control*, const std::string&);
diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc
index fde6ecce..4fcf5cf6 100644
--- a/src/ui/download_list.cc
+++ b/src/ui/download_list.cc
@@ -86,7 +86,7 @@ DownloadList::DownloadList(Control* c) :
m_windowLog = new WLog(&m_control->core()->get_log_important());
m_taskUpdate.set_iterator(taskScheduler.end());
- m_taskUpdate.set_slot(sigc::mem_fun(*this, &DownloadList::task_update)),
+ m_taskUpdate.set_slot(rak::mem_fn(this, &DownloadList::task_update)),
setup_keys();
setup_input();
diff --git a/src/utils/task_item.h b/src/utils/task_item.h
index a32868a8..1ab69938 100644
--- a/src/utils/task_item.h
+++ b/src/utils/task_item.h
@@ -39,7 +39,7 @@
#include
#include
-#include
+#include
namespace utils {
@@ -47,10 +47,10 @@ namespace utils {
class TaskItem {
public:
- typedef sigc::slot Slot;
+ typedef rak::function Slot;
typedef std::list >::iterator iterator;
- TaskItem(Slot s = Slot()) : m_slot(s) {}
+ TaskItem() {}
Slot& get_slot() { return m_slot; }
void set_slot(Slot s) { m_slot = s; }