handle torrents with duplicate filenames

This commit is contained in:
Arvid Norberg 2009-06-26 16:20:57 +00:00
parent 356db54dce
commit 10eb3fa00f
6 changed files with 40 additions and 15 deletions

View File

@ -1,3 +1,4 @@
* handle torrents with duplicate filenames
* piece timeouts are adjusted to download rate limits * piece timeouts are adjusted to download rate limits
* encodes urls in torrent files that needs to be encoded * encodes urls in torrent files that needs to be encoded
* fixed not passing &supportcrypto=1 when encryption is disabled * fixed not passing &supportcrypto=1 when encryption is disabled

View File

@ -50,6 +50,7 @@ namespace libtorrent
char TORRENT_EXPORT to_lower(char c); char TORRENT_EXPORT to_lower(char c);
bool TORRENT_EXPORT string_begins_no_case(char const* s1, char const* s2); bool TORRENT_EXPORT string_begins_no_case(char const* s1, char const* s2);
bool TORRENT_EXPORT string_equal_no_case(char const* s1, char const* s2);
std::string TORRENT_EXPORT unescape_string(std::string const& s, error_code& ec); std::string TORRENT_EXPORT unescape_string(std::string const& s, error_code& ec);
// replaces all disallowed URL characters by their %-encoding // replaces all disallowed URL characters by their %-encoding

View File

@ -111,6 +111,17 @@ namespace libtorrent
return true; return true;
} }
bool string_equal_no_case(char const* s1, char const* s2)
{
while (to_lower(*s1) == to_lower(*s2))
{
if (*s1 == 0) return true;
++s1;
++s2;
}
return false;
}
std::string unescape_string(std::string const& s, error_code& ec) std::string unescape_string(std::string const& s, error_code& ec)
{ {
std::string ret; std::string ret;

View File

@ -278,6 +278,22 @@ namespace libtorrent
file_entry e; file_entry e;
if (!extract_single_file(*list.list_at(i), e, root_dir)) if (!extract_single_file(*list.list_at(i), e, root_dir))
return false; return false;
int cnt = 0;
for (file_storage::iterator k = target.begin()
, end(target.end()); k != end; ++k)
{
if (string_equal_no_case(e.path.string().c_str()
, k->path.string().c_str())) ++cnt;
}
if (cnt)
{
char suffix[15];
snprintf(suffix, sizeof(suffix), ".%d", cnt);
e.path.replace_extension(suffix + e.path.extension());
// TODO: we should really make sure that this new name
// doesn't already exist as well, otherwise we might
// just create another collision
}
target.add_file(e); target.add_file(e);
} }
return true; return true;

View File

@ -746,17 +746,6 @@ namespace
dst.clear(); dst.clear();
while (*src) dst.push_back(to_lower(*src++)); while (*src) dst.push_back(to_lower(*src++));
} }
bool string_equal_nocase(char const* lhs, char const* rhs)
{
while (to_lower(*lhs) == to_lower(*rhs))
{
if (*lhs == 0) return true;
++lhs;
++rhs;
}
return false;
}
} }
struct parse_state struct parse_state
@ -781,10 +770,10 @@ struct parse_state
{ {
std::list<std::string>::reverse_iterator i = tag_stack.rbegin(); std::list<std::string>::reverse_iterator i = tag_stack.rbegin();
if (i == tag_stack.rend()) return false; if (i == tag_stack.rend()) return false;
if (!string_equal_nocase(i->c_str(), str2)) return false; if (!string_equal_no_case(i->c_str(), str2)) return false;
++i; ++i;
if (i == tag_stack.rend()) return false; if (i == tag_stack.rend()) return false;
if (!string_equal_nocase(i->c_str(), str1)) return false; if (!string_equal_no_case(i->c_str(), str1)) return false;
return true; return true;
} }
}; };
@ -814,7 +803,7 @@ void find_control_url(int type, char const* string, parse_state& state)
// std::cout << " " << string << std::endl; // std::cout << " " << string << std::endl;
if (!state.in_service && state.top_tags("service", "servicetype")) if (!state.in_service && state.top_tags("service", "servicetype"))
{ {
if (string_equal_nocase(string, state.service_type)) if (string_equal_no_case(string, state.service_type))
state.in_service = true; state.in_service = true;
} }
else if (state.in_service && state.top_tags("service", "controlurl")) else if (state.in_service && state.top_tags("service", "controlurl"))

View File

@ -423,6 +423,13 @@ int test_main()
TEST_CHECK(to_lower('-') == '-'); TEST_CHECK(to_lower('-') == '-');
TEST_CHECK(to_lower('&') == '&'); TEST_CHECK(to_lower('&') == '&');
// test string_equal_no_case
TEST_CHECK(string_equal_no_case("foobar", "FoobAR"));
TEST_CHECK(string_equal_no_case("foobar", "foobar"));
TEST_CHECK(!string_equal_no_case("foobar", "foobar "));
TEST_CHECK(!string_equal_no_case("foobar", "F00"));
// test string_begins_no_case // test string_begins_no_case
TEST_CHECK(string_begins_no_case("foobar", "FoobAR --")); TEST_CHECK(string_begins_no_case("foobar", "FoobAR --"));