canonicalize paths when using UNC paths

This commit is contained in:
Arvid Norberg 2012-04-28 21:13:55 +00:00
parent c80e156120
commit 1c60ae4064
5 changed files with 87 additions and 4 deletions

View File

@ -140,6 +140,9 @@ namespace libtorrent
TORRENT_EXPORT std::string complete(std::string const& f);
TORRENT_EXPORT bool is_complete(std::string const& f);
TORRENT_EXPORT std::string current_working_directory();
#if TORRENT_USE_UNC_PATHS
TORRENT_EXTRA_EXPORT std::string canonicalize_path(std::string const& f);
#endif
class TORRENT_EXPORT directory : public boost::noncopyable
{

View File

@ -167,6 +167,9 @@ namespace libtorrent
file_pool fp;
std::string utf8;
wchar_utf8(p, utf8);
#if TORRENT_USE_UNC_PATHS
p = canonicalize_path(p);
#endif
boost::scoped_ptr<storage_interface> st(
default_storage_constructor(const_cast<file_storage&>(t.files()), 0, utf8, fp
, std::vector<boost::uint8_t>()));
@ -195,6 +198,9 @@ namespace libtorrent
, boost::function<void(int)> f, error_code& ec)
{
file_pool fp;
#if TORRENT_USE_UNC_PATHS
p = canonicalize_path(p);
#endif
boost::scoped_ptr<storage_interface> st(
default_storage_constructor(const_cast<file_storage&>(t.files()), 0, p, fp
, std::vector<boost::uint8_t>()));

View File

@ -536,6 +536,69 @@ namespace libtorrent
#endif
}
#if TORRENT_USE_UNC_PATHS
std::string canonicalize_path(std::string const& f)
{
std::string ret;
ret.resize(f.size());
char* write_cur = &ret[0];
char* last_write_sep = write_cur;
char const* read_cur = f.c_str();
char const* last_read_sep = read_cur;
// the last_*_sep pointers point to one past
// the last path separator encountered and is
// initializes to the first character in the path
while (*read_cur)
{
if (*read_cur != '\\')
{
*write_cur++ = *read_cur++;
continue;
}
int element_len = read_cur - last_read_sep;
if (element_len == 1 && memcmp(last_read_sep, ".", 1) == 0)
{
--write_cur;
++read_cur;
last_read_sep = read_cur;
continue;
}
if (element_len == 2 && memcmp(last_read_sep, "..", 2) == 0)
{
// find the previous path separator
if (last_write_sep > &ret[0])
{
--last_write_sep;
while (last_write_sep > &ret[0]
&& last_write_sep[-1] != '\\')
--last_write_sep;
}
write_cur = last_write_sep;
// find the previous path separator
if (last_write_sep > &ret[0])
{
--last_write_sep;
while (last_write_sep > &ret[0]
&& last_write_sep[-1] != '\\')
--last_write_sep;
}
++read_cur;
last_read_sep = read_cur;
continue;
}
*write_cur++ = *read_cur++;
last_write_sep = write_cur;
last_read_sep = read_cur;
}
// terminate destination string
*write_cur = 0;
ret.resize(write_cur - &ret[0]);
return ret;
}
#endif
size_type file_size(std::string const& f)
{
error_code ec;
@ -811,14 +874,12 @@ namespace libtorrent
FILE_SHARE_READ,
};
std::string p = convert_separators(path);
#if TORRENT_USE_UNC_PATHS
// UNC paths must be absolute
std::string p = convert_separators(path);
// network paths are not supported by UNC paths
// network paths are already UNC paths
if (path.substr(0,2) == "\\\\") p = path;
else p = "\\\\?\\" + (is_complete(p) ? p : combine_path(current_working_directory(), p));
#else
std::string p = convert_separators(path);
#endif
#if TORRENT_USE_WSTRING

View File

@ -433,6 +433,10 @@ namespace libtorrent
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
m_resume_data_loaded = false;
#endif
#if TORRENT_USE_UNC_PATHS
m_save_path = canonicalize_path(m_save_path);
#endif
if (!m_apply_ip_filter) ++m_ses.m_non_filtered_torrents;
if (!p.ti || !p.ti->is_valid())

View File

@ -871,6 +871,15 @@ int test_main()
TEST_EQUAL(combine_path("test1", "test2"), "test1/test2");
#endif
#if TORRENT_USE_UNC_PATHS
TEST_EQUAL(canonicalize_path("c:\\a\\..\\b"), "c:\\b");
TEST_EQUAL(canonicalize_path("a\\..\\b"), "b");
TEST_EQUAL(canonicalize_path("a\\..\\.\\b"), "b");
TEST_EQUAL(canonicalize_path("\\.\\a"), "\\a");
TEST_EQUAL(canonicalize_path("\\\\bla\\.\\a"), "\\\\bla\\a");
TEST_EQUAL(canonicalize_path("c:\\bla\\a"), "c:\\bla\\a");
#endif
TEST_EQUAL(extension("blah"), "");
TEST_EQUAL(extension("blah.exe"), ".exe");
TEST_EQUAL(extension("blah.foo.bar"), ".bar");