diff --git a/libtorrent/include/libtorrent/xml_parse.hpp b/libtorrent/include/libtorrent/xml_parse.hpp index c3aeddad7..67ae406f0 100644 --- a/libtorrent/include/libtorrent/xml_parse.hpp +++ b/libtorrent/include/libtorrent/xml_parse.hpp @@ -33,11 +33,25 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef TORRENT_XML_PARSE_HPP #define TORRENT_XML_PARSE_HPP +#include + namespace libtorrent { - const int xml_start_tag = 0; - const int xml_end_tag = 1; - const int xml_string = 2; + enum + { + xml_start_tag, + xml_end_tag, + xml_empty_tag, + xml_declaration_tag, + xml_string, + xml_attribute, + xml_comment, + xml_parse_error + }; + + // callback(int type, char const* name, char const* val) + // str2 is only used for attributes. name is element or attribute + // name and val is attribute value template void xml_parse(char* p, char* end, CallbackType callback) @@ -45,6 +59,8 @@ namespace libtorrent for(;p != end; ++p) { char const* start = p; + char const* val_start = 0; + int token; // look for tag start for(; *p != '<' && p != end; ++p); @@ -55,39 +71,135 @@ namespace libtorrent assert(*p == '<'); *p = 0; } - callback(xml_string, start); + token = xml_string; + callback(token, start, val_start); if (p != end) *p = '<'; } - + if (p == end) break; // skip '<' ++p; - // parse the name of the tag. Ignore attributes - for (start = p; p != end && *p != '>'; ++p) - { - // terminate the string at the first space - // to ignore tag attributes - if (*p == ' ') *p = 0; - } + // parse the name of the tag. + for (start = p; p != end && *p != '>' && !std::isspace(*p); ++p); + + char* tag_name_end = p; + + // skip the attributes for now + for (; p != end && *p != '>'; ++p); // parse error - if (p == end) break; + if (p == end) + { + token = xml_parse_error; + start = "unexpected end of file"; + callback(token, start, val_start); + break; + } assert(*p == '>'); - *p = 0; + // save the character that terminated the tag name + // it could be both '>' and ' '. + char save = *tag_name_end; + *tag_name_end = 0; + char* tag_end = p; if (*start == '/') { ++start; - callback(xml_end_tag, start); + token = xml_end_tag; + callback(token, start, val_start); + } + else if (*(p-1) == '/') + { + *(p-1) = 0; + token = xml_empty_tag; + callback(token, start, val_start); + *(p-1) = '/'; + tag_end = p - 1; + } + else if (*start == '?' && *(p-1) == '?') + { + *(p-1) = 0; + ++start; + token = xml_declaration_tag; + callback(token, start, val_start); + *(p-1) = '?'; + tag_end = p - 1; + } + else if (start + 5 < p && memcmp(start, "!--", 3) == 0 && memcmp(p-2, "--", 2) == 0) + { + start += 3; + *(p-2) = 0; + token = xml_comment; + callback(token, start, val_start); + *(p-2) = '-'; + tag_end = p - 2; } else { - callback(xml_start_tag, start); + token = xml_start_tag; + callback(token, start, val_start); + } + + *tag_name_end = save; + + // parse attributes + for (char* i = tag_name_end; i < tag_end; ++i) + { + // find start of attribute name + for (; i != tag_end && std::isspace(*i); ++i); + if (i == tag_end) break; + start = i; + // find end of attribute name + for (; i != tag_end && *i != '=' && !std::isspace(*i); ++i); + char* name_end = i; + + // look for equality sign + for (; i != tag_end && *i != '='; ++i); + + if (i == tag_end) + { + token = xml_parse_error; + val_start = 0; + start = "garbage inside element brackets"; + callback(token, start, val_start); + break; + } + + ++i; + for (; i != tag_end && std::isspace(*i); ++i); + // check for parse error (values must be quoted) + if (i == tag_end || (*i != '\'' && *i != '\"')) + { + token = xml_parse_error; + val_start = 0; + start = "unquoted attribute value"; + callback(token, start, val_start); + break; + } + char quote = *i; + ++i; + val_start = i; + for (; i != tag_end && *i != quote; ++i); + // parse error (missing end quote) + if (i == tag_end) + { + token = xml_parse_error; + val_start = 0; + start = "missing end quote on attribute"; + callback(token, start, val_start); + break; + } + save = *i; + *i = 0; + *name_end = 0; + token = xml_attribute; + callback(token, start, val_start); + *name_end = '='; + *i = save; } - *p = '>'; } } diff --git a/libtorrent/src/lsd.cpp b/libtorrent/src/lsd.cpp index b73e407bc..76f25548d 100644 --- a/libtorrent/src/lsd.cpp +++ b/libtorrent/src/lsd.cpp @@ -35,7 +35,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/lsd.hpp" #include "libtorrent/io.hpp" #include "libtorrent/http_tracker_connection.hpp" -#include "libtorrent/xml_parse.hpp" #include #include #include diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index 8fae3bcb7..81f48a3ce 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -1901,13 +1901,15 @@ namespace detail int session_impl::upload_rate_limit() const { mutex_t::scoped_lock l(m_mutex); - return m_bandwidth_manager[peer_connection::upload_channel]->throttle(); + int ret = m_bandwidth_manager[peer_connection::upload_channel]->throttle(); + return ret == std::numeric_limits::max() ? -1 : ret; } int session_impl::download_rate_limit() const { mutex_t::scoped_lock l(m_mutex); - return m_bandwidth_manager[peer_connection::download_channel]->throttle(); + int ret = m_bandwidth_manager[peer_connection::download_channel]->throttle(); + return ret == std::numeric_limits::max() ? -1 : ret; } void session_impl::start_lsd() diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index 7f9d0b386..0590d6c67 100755 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -1060,9 +1060,9 @@ namespace libtorrent // TODO: POSIX implementation #if defined(__FreeBSD__) - return true; + return true; #else - return false; + return false; #endif } diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 17dec1044..509753814 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -50,7 +50,6 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include #ifdef _MSC_VER #pragma warning(pop) @@ -1659,30 +1658,26 @@ namespace libtorrent }; #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES + namespace + { + unsigned long swap_bytes(unsigned long a) + { + return (a >> 24) | ((a & 0xff0000) >> 8) | ((a & 0xff00) << 8) | (a << 24); + } + } + void torrent::resolve_peer_country(boost::intrusive_ptr const& p) const { if (m_resolving_country || p->has_country() || p->is_connecting() || p->is_queued() - || p->in_handshake()) return; + || p->in_handshake() + || p->remote().address().is_v6()) return; m_resolving_country = true; - - std::string ip_address = boost::lexical_cast(p->remote().address()); - std::string ip_address_reversed = ""; - - boost::char_separator sep("."); - boost::tokenizer< boost::char_separator > tokens(ip_address, sep); - for (boost::tokenizer< boost::char_separator >::const_iterator it = tokens.begin(); it != tokens.end(); ++it) - { - if(ip_address_reversed != "") - ip_address_reversed = "." + ip_address_reversed; - ip_address_reversed = *it + ip_address_reversed; - } - - tcp::resolver::query q(ip_address_reversed - + ".zz.countries.nerd.dk", "0"); + asio::ip::address_v4 reversed(swap_bytes(p->remote().address().to_v4().to_ulong())); + tcp::resolver::query q(reversed.to_string() + ".zz.countries.nerd.dk", "0"); m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p))); } diff --git a/libtorrent/src/upnp.cpp b/libtorrent/src/upnp.cpp index c60725e9d..42c62166e 100644 --- a/libtorrent/src/upnp.cpp +++ b/libtorrent/src/upnp.cpp @@ -62,9 +62,10 @@ namespace libtorrent { if (a.is_v6()) return false; address_v4 a4 = a.to_v4(); - return ((a4.to_ulong() & 0xff000000) == 0x0a000000 - || (a4.to_ulong() & 0xfff00000) == 0xac100000 - || (a4.to_ulong() & 0xffff0000) == 0xc0a80000); + unsigned long ip = htonl(a4.to_ulong()); + return ((ip & 0xff000000) == 0x0a000000 + || (ip & 0xfff00000) == 0xac100000 + || (ip & 0xffff0000) == 0xc0a80000); } address_v4 guess_local_address(asio::io_service& ios)