diff options
author | munjal@chromium.org <munjal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-04 18:33:53 +0000 |
---|---|---|
committer | munjal@chromium.org <munjal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-04 18:33:53 +0000 |
commit | 055aedeb2134e49c10c3b3a3593cb8df768d737c (patch) | |
tree | 4961da84e3e38e7c6a3edb68bb96e031f8856604 /chrome/browser/sync/util | |
parent | 46e9f9d97ec029189618f8ff2089948b950e67e7 (diff) | |
download | chromium_src-055aedeb2134e49c10c3b3a3593cb8df768d737c.zip chromium_src-055aedeb2134e49c10c3b3a3593cb8df768d737c.tar.gz chromium_src-055aedeb2134e49c10c3b3a3593cb8df768d737c.tar.bz2 |
Clean up the strings for sync code:
- Use FilePath for real file paths.
- Use std::string for PathString on Windows as well
TODO in a separate CL:
- Get rid of PathString typedef completely and directly use std::string everywhere.
- Use wchar_t in syncapi.h/.cc and get rid of sync_char16.
TEST=Existing tests are sufficient since this CL does a lot of code refactoring.
BUG=26342
Review URL: http://codereview.chromium.org/340055
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30970 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sync/util')
22 files changed, 259 insertions, 1059 deletions
diff --git a/chrome/browser/sync/util/character_set_converters.cc b/chrome/browser/sync/util/character_set_converters.cc index a9114cf3..3c66c35 100644 --- a/chrome/browser/sync/util/character_set_converters.cc +++ b/chrome/browser/sync/util/character_set_converters.cc @@ -4,51 +4,44 @@ #include "chrome/browser/sync/util/character_set_converters.h" -#include <string> - -using std::string; - namespace browser_sync { -void PathStringToUTF8(const PathChar* wide, int size, - std::string* output_string) { - CHECK(output_string); - output_string->clear(); - AppendPathStringToUTF8(wide, size, output_string); -} - -bool UTF8ToPathString(const char* utf8, size_t size, - PathString* output_string) { - CHECK(output_string); - output_string->clear(); - return AppendUTF8ToPathString(utf8, size, output_string); -}; - -ToUTF8::ToUTF8(const PathChar* wide, size_t size) { - PathStringToUTF8(wide, size, &result_); -} - -ToUTF8::ToUTF8(const PathString& wide) { - PathStringToUTF8(wide.data(), wide.length(), &result_); -} - -ToUTF8::ToUTF8(const PathChar* wide) { - PathStringToUTF8(wide, PathLen(wide), &result_); -} - -ToPathString::ToPathString(const char* utf8, size_t size) { - good_ = UTF8ToPathString(utf8, size, &result_); - good_checked_ = false; -} - -ToPathString::ToPathString(const std::string& utf8) { - good_ = UTF8ToPathString(utf8.data(), utf8.length(), &result_); - good_checked_ = false; -} - -ToPathString::ToPathString(const char* utf8) { - good_ = UTF8ToPathString(utf8, strlen(utf8), &result_); - good_checked_ = false; +void TrimPathStringToValidCharacter(PathString* string) { + // Constants from http://en.wikipedia.org/wiki/UTF-8 + CHECK(string); + if (string->empty()) + return; + if (0 == (string->at(string->length() - 1) & 0x080)) + return; + size_t partial_enc_bytes = 0; + for (partial_enc_bytes = 0 ; true ; ++partial_enc_bytes) { + if (4 == partial_enc_bytes || partial_enc_bytes == string->length()) { + // original string was broken, garbage in, garbage out. + return; + } + PathChar c = string->at(string->length() - 1 - partial_enc_bytes); + if ((c & 0x0c0) == 0x080) // utf continuation char; + continue; + if ((c & 0x0e0) == 0x0e0) { // 2-byte encoded char. + if (1 == partial_enc_bytes) + return; + else + break; + } + if ((c & 0x0f0) == 0xc0) { // 3-byte encoded char. + if (2 == partial_enc_bytes) + return; + else + break; + } + if ((c & 0x0f8) == 0x0f0) { // 4-byte encoded char. + if (3 == partial_enc_bytes) + return; + else + break; + } + } + string->resize(string->length() - 1 - partial_enc_bytes); } } // namespace browser_sync diff --git a/chrome/browser/sync/util/character_set_converters.h b/chrome/browser/sync/util/character_set_converters.h index 6a833ee..44aa8a7 100644 --- a/chrome/browser/sync/util/character_set_converters.h +++ b/chrome/browser/sync/util/character_set_converters.h @@ -5,240 +5,21 @@ #ifndef CHROME_BROWSER_SYNC_UTIL_CHARACTER_SET_CONVERTERS_H_ #define CHROME_BROWSER_SYNC_UTIL_CHARACTER_SET_CONVERTERS_H_ -// A pair of classes to convert UTF8 <-> UCS2 character strings. -// -// Note that the current implementation is limited to UCS2, whereas the -// interface is agnostic to the wide encoding used. -// -// Also note that UCS2 is different from UTF-16, in that UTF-16 can encode all -// the code points in the Unicode character set by multi-character encodings, -// while UCS2 is limited to encoding < 2^16 code points. -// -// It appears that Windows support UTF-16, which means we have to be careful -// what we feed this class. -// -// Usage: -// string utf8; -// CHECK(browser_sync::Append(wide_string, &utf8)); -// PathString bob; -// CHECK(browser_sync::Append(utf8, &bob)); -// PathString fred = bob; - -#include <string> - -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/string16.h" +#include "base/file_path.h" #include "chrome/browser/sync/util/sync_types.h" // Need to cast literals (Linux, OSX) #define STRING16_UGLY_DOUBLE_DEFINE_HACK(s) \ - reinterpret_cast<const char16*>(L##s) + reinterpret_cast<const char16*>(L##s) #define STRING16(s) STRING16_UGLY_DOUBLE_DEFINE_HACK(s) -using std::string; - namespace browser_sync { -// These 2 classes are deprecated. Instead, prefer the Append() functions. - -// A class to convert wide -> UTF8. -class ToUTF8 { - public: - explicit ToUTF8(const PathChar* wide); - ToUTF8(const PathChar* wide, PathString::size_type size); - explicit ToUTF8(const PathString& wide); - - // cast operators - operator const std::string&() const; - operator const char*() const; - - // accessors - const std::string& get_string() const; - const char* data() const; - std::string::size_type byte_length() const; - - private: - std::string result_; -}; - -// A class to convert UTF8 -> wide. -class ToPathString { - public: - explicit ToPathString(const char*); - ToPathString(const char*, size_t size); - explicit ToPathString(const std::string&); - - // true iff UTF-8 to wide conversion succeeded in constructor. - bool good() { - good_checked_ = true; - return good_; - } - - // It's invalid to invoke the accessors or the cast operators unless the - // string is good and good() has been invoked at least once. - - // Implicit casts to const PathString& and const PathChar* - operator const PathString&() const; - operator const PathChar*() const; - - // Accessors - const PathString& get_string16() const; - const PathChar* data() const; - PathString::size_type length() const; - - private: - PathString result_; - - // Conversion succeeded. - bool good_; - // good() has been invoked at least once. - bool good_checked_; -}; - -// Converts the UCS2 string "wide" to UTF8 encoding and stores the result in -// output_string. -void PathStringToUTF8(const PathChar* wide, int size, - std::string* output_string); - -// Converts UCS2 string wide to UTF8 encoding and appends the result to -// output_string. -void AppendPathStringToUTF8(const PathChar* wide, int size, - std::string* output_string); - -// Converts the UTF8 encoded string "utf8" to UCS16 and stores the result in -// output_string. -// -// Returns true iff conversion was successful, false otherwise. -bool UTF8ToPathString(const char* utf8, size_t size, - PathString* output_string); - -// Converts the UTF8 encoded string "utf8" to UCS2 and appends the result in -// output_string. -// -// Returns true iff conversion was successful, false otherwise. -bool AppendUTF8ToPathString(const char* utf8, size_t size, - PathString* output_string); - -// Converts the UTF8 encoded string "utf8" to UCS2 and appends the result in -// output_string. -// -// @returns true iff conversion was successful, false otherwise. -inline bool AppendUTF8ToPathString(const std::string& utf8, - PathString* output_string) { - return AppendUTF8ToPathString(utf8.data(), utf8.length(), output_string); -} - -// Converts UCS2 string wide to UTF8 encoding and appends the result to -// output_string. -inline void AppendPathStringToUTF8(const PathString& wide, - std::string* output_string) { - return AppendPathStringToUTF8(wide.data(), wide.length(), output_string); -} - -// Versions of UTF8ToPathString/PathStringToUTF8 that return the converted -// string directly. Any errors encountered will CHECK(). These functions are -// intended to be used only for testing. - -inline PathString UTF8ToPathStringQuick(const std::string &utf8) { - PathString wide; - CHECK(UTF8ToPathString(utf8.data(), utf8.size(), &wide)); - return wide; -} - -inline std::string PathStringToUTF8Quick(const PathString& wide) { - std::string utf8; - PathStringToUTF8(wide.data(), wide.size(), &utf8); - return utf8; -} - -inline bool Append(const PathChar* wide, int size, - std::string* output_string) { - AppendPathStringToUTF8(wide, size, output_string); - return true; -} - -inline bool Append(const PathChar* wide, std::string* output_string) { - AppendPathStringToUTF8(wide, PathLen(wide), output_string); - return true; -} - -inline bool Append(const std::string& utf8, PathString* output_string) { - return AppendUTF8ToPathString(utf8.data(), utf8.length(), output_string); -} - -#if !PATHSTRING_IS_STD_STRING -inline bool Append(const char* utf8, size_t size, PathString* output_string) { - return AppendUTF8ToPathString(utf8, size, output_string); -} - -inline bool Append(const char* s, int size, std::string* output_string) { - output_string->append(s, size); - return true; -} - -inline bool Append(const char* utf8, PathString* output_string) { - return AppendUTF8ToPathString(utf8, strlen(utf8), output_string); -} - -inline bool Append(const char* s, std::string* output_string) { - output_string->append(s); - return true; -} - -inline bool Append(const PathString& wide, std::string* output_string) { - return Append(wide.data(), wide.length(), output_string); -} - -inline bool Append(const std::string& s, std::string* output_string) { - return Append(s.data(), s.length(), output_string); -} -#endif - -inline ToUTF8::operator const std::string&() const { - return result_; -} - -inline ToUTF8::operator const char*() const { - return result_.c_str(); -} - -inline const std::string& ToUTF8::get_string() const { - return result_; -} - -inline const char* ToUTF8::data() const { - return result_.data(); -} - -inline std::string::size_type ToUTF8::byte_length() const { - return result_.size(); -} - -inline ToPathString::operator const PathString&() const { - DCHECK(good_ && good_checked_); - return result_; -} - -inline ToPathString::operator const PathChar*() const { - DCHECK(good_ && good_checked_); - return result_.c_str(); -} - -inline const PathString& ToPathString::get_string16() const { - DCHECK(good_ && good_checked_); - return result_; -} - -inline const PathChar* ToPathString::data() const { - DCHECK(good_ && good_checked_); - return result_.data(); -} +// Returns UTF8 string from the given FilePath. +std::string FilePathToUTF8(const FilePath& file_path); -inline PathString::size_type ToPathString::length() const { - DCHECK(good_ && good_checked_); - return result_.length(); -} +// Returns FilePath from the given UTF8 string. +FilePath UTF8ToFilePath(const std::string& utf8); void TrimPathStringToValidCharacter(PathString* string); diff --git a/chrome/browser/sync/util/character_set_converters_posix.cc b/chrome/browser/sync/util/character_set_converters_posix.cc index ba57214..aba56aa 100644 --- a/chrome/browser/sync/util/character_set_converters_posix.cc +++ b/chrome/browser/sync/util/character_set_converters_posix.cc @@ -10,54 +10,14 @@ using std::string; namespace browser_sync { -// Converts input_string to UTF8 and appends the result into output_string. -void AppendPathStringToUTF8(const PathChar *wide, int size, - string* output_string) { - output_string->append(wide, size); +// Returns UTF8 string from the given FilePath. +std::string FilePathToUTF8(const FilePath& file_path) { + return file_path.value(); } -bool AppendUTF8ToPathString(const char* utf8, size_t size, - PathString* output_string) { - output_string->append(utf8, size); - return true; -} - -void TrimPathStringToValidCharacter(PathString* string) { - // Constants from http://en.wikipedia.org/wiki/UTF-8 - CHECK(string); - if (string->empty()) - return; - if (0 == (string->at(string->length() - 1) & 0x080)) - return; - size_t partial_enc_bytes = 0; - for (partial_enc_bytes = 0 ; true ; ++partial_enc_bytes) { - if (4 == partial_enc_bytes || partial_enc_bytes == string->length()) { - // original string was broken, garbage in, garbage out. - return; - } - PathChar c = string->at(string->length() - 1 - partial_enc_bytes); - if ((c & 0x0c0) == 0x080) // utf continuation char; - continue; - if ((c & 0x0e0) == 0x0e0) { // 2-byte encoded char. - if (1 == partial_enc_bytes) - return; - else - break; - } - if ((c & 0x0f0) == 0xc0) { // 3-byte encoded char. - if (2 == partial_enc_bytes) - return; - else - break; - } - if ((c & 0x0f8) == 0x0f0) { // 4-byte encoded char. - if (3 == partial_enc_bytes) - return; - else - break; - } - } - string->resize(string->length() - 1 - partial_enc_bytes); +// Returns FilePath from the given UTF8 string. +FilePath UTF8ToFilePath(const std::string& utf8) { + return FilePath(utf8); } } // namespace browser_sync diff --git a/chrome/browser/sync/util/character_set_converters_unittest.cc b/chrome/browser/sync/util/character_set_converters_unittest.cc index 6274a1d..8e75539 100644 --- a/chrome/browser/sync/util/character_set_converters_unittest.cc +++ b/chrome/browser/sync/util/character_set_converters_unittest.cc @@ -6,155 +6,23 @@ #include <string> -#include "base/basictypes.h" -#include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" -using browser_sync::ToPathString; -using browser_sync::ToUTF8; -using browser_sync::AppendPathStringToUTF8; -using browser_sync::AppendUTF8ToPathString; -using browser_sync::PathStringToUTF8; -using browser_sync::UTF8ToPathString; using std::string; class CharacterSetConverterTest : public testing::Test { }; -TEST_F(CharacterSetConverterTest, ASCIIConversionTest) { - string ascii = "Test String"; - PathString wide = PSTR("Test String"); - ToPathString to_wide(ascii); - ASSERT_TRUE(to_wide.good()); - ToUTF8 to_utf8(wide); - - // Using == as gunit doesn't handle PathString equality tests correctly (it - // tries to print the PathString and fails). - ASSERT_TRUE(PathString(wide) == to_wide.get_string16()); - ASSERT_EQ(string(ascii), to_utf8.get_string()); - ToPathString to_16(ascii); - ASSERT_TRUE(to_16.good()); - ASSERT_TRUE(PathString(wide) == to_16.get_string16()); -#if defined(OS_WIN) - // On Linux, PathString is already UTF8 - ASSERT_EQ(string(ascii), static_cast<string>(ToUTF8(wide))); -#endif - // The next line fails the good_checked_ test. It would be a good death test - // but they don't work on Windows. - // ASSERT_TRUE(wide == ToPathString(utf8).get_string16()); -} - -#if defined(OS_WIN) - // On Linux, PathString is already UTF8 -TEST_F(CharacterSetConverterTest, UnicodeConversionText) { - // Source data obtained by running od -b on files saved in utf-8 and unicode - // from a text editor. - const char* utf8 = "\357\273\277\150\145\154\154\157\040\303\250\303\251" - "\302\251\342\202\254\302\243\302\245\302\256\342\204\242"; -// #ifdef IS_LITTLE_ENDIAN - const PathChar* wide = reinterpret_cast<const PathChar*>("\377\376\150\000" - "\145\000\154\000\154\000\157\000\040\000\350\000\351\000\251\000\254\040" - "\243\000\245\000\256\000\042\041"); -// #else -// // This should work, but on Windows we don't have the endian -// // macros. Since we only do conversion between 16<->8 on Windows, -// // it's safe to assume little endian. -// const PathChar* wide = -// reinterpret_cast<PathChar*>("\376\377\000\150\000\145\000" -// "\154\000\154\000\157\000\040\000\350\000\351\000\251\040\254\000\243" -// "\000\245\000\256\041\042"); -// #endif - - ToPathString to_wide(utf8); - ASSERT_TRUE(to_wide.good()); - ToUTF8 to_utf8(wide); - - // Using == as gunit doesn't handle PathString equality tests correctly (it - // tries to print the PathString and fails). - ASSERT_TRUE(wide == to_wide.get_string16()); - ASSERT_EQ(string(utf8), to_utf8.get_string()); - ToPathString to_16(utf8); - ASSERT_TRUE(to_16.good()); - ASSERT_TRUE(wide == to_16.get_string16()); - ASSERT_EQ(string(utf8), reinterpret_cast<const string&>(ToUTF8(wide))); -} -#endif // defined(OS_WIN) - -TEST_F(CharacterSetConverterTest, AppendUTF8Tests) { - PathString one = PSTR("one"); - PathString two = PSTR("two"); - PathString three = PSTR("three"); - string out; - AppendPathStringToUTF8(one.data(), one.length(), &out); - AppendPathStringToUTF8(two.data(), two.length(), &out); - AppendPathStringToUTF8(three.data(), three.length(), &out); - ASSERT_EQ(out, "onetwothree"); - PathString onetwothree = PSTR("onetwothree"); - PathStringToUTF8(onetwothree.data(), onetwothree.length(), &out); - ASSERT_EQ(out, "onetwothree"); -} - -TEST_F(CharacterSetConverterTest, AppendPathStringTests) { - string one = "one"; - string two = "two"; - string three = "three"; - PathString out; - AppendUTF8ToPathString(one.data(), one.length(), &out); - AppendUTF8ToPathString(two.data(), two.length(), &out); - AppendUTF8ToPathString(three.data(), three.length(), &out); - ASSERT_TRUE(out == PathString(PSTR("onetwothree"))); - string onetwothree = "onetwothree"; - UTF8ToPathString(onetwothree.data(), onetwothree.length(), &out); - ASSERT_TRUE(out == PathString(PSTR("onetwothree"))); -} - -#if defined(OS_WIN) -namespace { -// See http://en.wikipedia.org/wiki/UTF-16 for an explanation of UTF16. -// For a test case we use the UTF-8 and UTF-16 encoding of char 119070 -// (hex 1D11E), which is musical G clef. -const unsigned char utf8_test_string[] = { - 0xEF, 0xBB, 0xBF, // BOM - 0xE6, 0xB0, 0xB4, // water, Chinese (0x6C34) - 0x7A, // lower case z - 0xF0, 0x9D, 0x84, 0x9E, // musical G clef (0x1D11E) - 0x00, -}; -const PathChar utf16_test_string[] = { - 0xFEFF, // BOM - 0x6C34, // water, Chinese - 0x007A, // lower case z - 0xD834, 0xDD1E, // musical G clef (0x1D11E) - 0x0000, -}; -} - -TEST_F(CharacterSetConverterTest, UTF16ToUTF8Test) { - // Avoid truncation warning. - const char* utf8_test_string_pointer = - reinterpret_cast<const char*>(utf8_test_string); - ASSERT_STREQ(utf8_test_string_pointer, ToUTF8(utf16_test_string)); -} - -TEST_F(CharacterSetConverterTest, utf8_test_stringToUTF16Test) { - // Avoid truncation warning. - const char* utf8_test_string_pointer = - reinterpret_cast<const char*>(utf8_test_string); - ToPathString converted_utf8(utf8_test_string_pointer); - ASSERT_TRUE(converted_utf8.good()); - ASSERT_EQ(wcscmp(utf16_test_string, converted_utf8), 0); -} - TEST(NameTruncation, WindowsNameTruncation) { using browser_sync::TrimPathStringToValidCharacter; - PathChar array[] = {'1', '2', 0xD950, 0xDF21, '3', '4', 0}; + PathChar array[] = {'1', '2', '\xc0', '\xe0', '3', '4', '\0'}; PathString message = array; ASSERT_EQ(message.length(), arraysize(array) - 1); - int old_length = message.length(); + string::size_type old_length = message.length(); while (old_length != 0) { TrimPathStringToValidCharacter(&message); if (old_length == 4) - EXPECT_EQ(3, message.length()); + EXPECT_EQ(3u, message.length()); else EXPECT_EQ(old_length, message.length()); message.resize(message.length() - 1); @@ -162,8 +30,3 @@ TEST(NameTruncation, WindowsNameTruncation) { } TrimPathStringToValidCharacter(&message); } -#else - -// TODO(zork): Add unittests here once we're running these tests on linux. - -#endif diff --git a/chrome/browser/sync/util/character_set_converters_win.cc b/chrome/browser/sync/util/character_set_converters_win.cc index ce1b882..1032f41 100644 --- a/chrome/browser/sync/util/character_set_converters_win.cc +++ b/chrome/browser/sync/util/character_set_converters_win.cc @@ -2,61 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/utf_string_conversions.h" #include "chrome/browser/sync/util/character_set_converters.h" -#include <windows.h> - -#include <string> - -using std::string; - namespace browser_sync { -// Converts input_string to UTF8 and appends the result into to output_string. -void AppendPathStringToUTF8(const PathChar* wide, int size, - string* output_string) { - CHECK(output_string); - if (0 == size) - return; - - int needed_space = ::WideCharToMultiByte(CP_UTF8, 0, wide, size, 0, 0, 0, 0); - // TODO(sync): This should flag an error when we move to an api that can let - // utf-16 -> utf-8 fail. - CHECK(0 != needed_space); - string::size_type current_size = output_string->size(); - output_string->resize(current_size + needed_space); - CHECK(0 != ::WideCharToMultiByte(CP_UTF8, 0, wide, size, - &(*output_string)[current_size], needed_space, 0, 0)); -} - -bool AppendUTF8ToPathString(const char* utf8, size_t size, - PathString* output_string) { - CHECK(output_string); - if (0 == size) - return true; - // TODO(sync): Do we want to force precomposed characters here? - int needed_wide_chars = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, - utf8, size, 0, 0); - if (0 == needed_wide_chars) { - DWORD err = ::GetLastError(); - if (MB_ERR_INVALID_CHARS == err) - return false; - CHECK(0 == err); - } - PathString::size_type current_length = output_string->size(); - output_string->resize(current_length + needed_wide_chars); - CHECK(0 != ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, size, - &(*output_string)[current_length], needed_wide_chars)); - return true; +// Returns UTF8 string from the given FilePath. +std::string FilePathToUTF8(const FilePath& file_path) { + return WideToUTF8(file_path.value()); } -void TrimPathStringToValidCharacter(PathString* string) { - CHECK(string); - // Constants from http://en.wikipedia.org/wiki/UTF-16 - if (string->empty()) - return; - if (0x0dc00 == (string->at(string->length() - 1) & 0x0fc00)) - string->resize(string->length() - 1); +// Returns FilePath from the given UTF8 string. +FilePath UTF8ToFilePath(const std::string& utf8) { + return FilePath(UTF8ToWide(utf8)); } } // namespace browser_sync diff --git a/chrome/browser/sync/util/compat_file.h b/chrome/browser/sync/util/compat_file.h deleted file mode 100644 index 011dafe..0000000 --- a/chrome/browser/sync/util/compat_file.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// File compatibility routines. Useful to delete database files with. - -#ifndef CHROME_BROWSER_SYNC_UTIL_COMPAT_FILE_H_ -#define CHROME_BROWSER_SYNC_UTIL_COMPAT_FILE_H_ - -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "build/build_config.h" -#include "chrome/browser/sync/util/sync_types.h" - -extern const PathChar* const kPathSeparator; - -// Path calls for all OSes. -// Returns 0 on success, non-zero on failure. -int PathRemove(const PathString& path); - -#if defined(OS_WIN) -inline int PathRemove(const PathString& path) { - return _wremove(path.c_str()); -} -#elif (defined(OS_MACOSX) || defined(OS_LINUX)) -inline int PathRemove(const PathString& path) { - return unlink(path.c_str()); -} -#endif - -#endif // CHROME_BROWSER_SYNC_UTIL_COMPAT_FILE_H_ diff --git a/chrome/browser/sync/util/compat_file_posix.cc b/chrome/browser/sync/util/compat_file_posix.cc deleted file mode 100644 index f84a379e6..0000000 --- a/chrome/browser/sync/util/compat_file_posix.cc +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "build/build_config.h" - -#if !defined(OS_POSIX) -#error Compile this file on Mac OS X or Linux only. -#endif - -#include "chrome/browser/sync/util/compat_file.h" - -const char* const kPathSeparator = "/"; diff --git a/chrome/browser/sync/util/compat_file_win.cc b/chrome/browser/sync/util/compat_file_win.cc deleted file mode 100644 index 0c34cd8..0000000 --- a/chrome/browser/sync/util/compat_file_win.cc +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/util/compat_file.h" - -#include "build/build_config.h" - -#ifndef OS_WIN -#error Compile this file on Windows only. -#endif - -const wchar_t* const kPathSeparator = L"\\"; - diff --git a/chrome/browser/sync/util/path_helpers.cc b/chrome/browser/sync/util/path_helpers.cc index a132086..e947e21 100644 --- a/chrome/browser/sync/util/path_helpers.cc +++ b/chrome/browser/sync/util/path_helpers.cc @@ -4,151 +4,4 @@ #include "chrome/browser/sync/util/path_helpers.h" -#include <Shlwapi.h> -#include <stdlib.h> - -#include "base/logging.h" -#include "base/port.h" -#include "build/build_config.h" -#include "chrome/browser/sync/syncable/syncable.h" - -#ifndef OS_WIN -#error Compile this file on Windows only. -#endif - -using std::string; - -#if OS_WIN -const char PATH_SEPARATOR = '\\'; -#else -const char PATH_SEPARATOR = '/'; -#endif // OS_WIN - - -static PathString RemoveTrailingSlashes16(PathString str) { - while ((str.length() > 0) && (str.at(str.length() - 1) == kPathSeparator[0])) - str.resize(str.length() - 1); - return str; -} - -static string RemoveTrailingSlashes(string str) { - while ((str.length() > 0) && (str.at(str.length() - 1) == PATH_SEPARATOR)) - str.resize(str.length() - 1); - return str; -} - -PathString LastPathSegment(const PathString& path) { - return RemoveTrailingSlashes16(PathFindFileNameW(path.c_str())); -} - -string LastPathSegment(const string& path) { - return RemoveTrailingSlashes(PathFindFileNameA(path.c_str())); -} - -PathString GetFullPath(const PathString& path) { - PathChar buffer[MAX_PATH]; - PathChar* file_part; - DWORD const size = GetFullPathName(path.c_str(), ARRAYSIZE(buffer), buffer, - &file_part); - return PathString(buffer, size); -} - -PathString AppendSlash(const PathString& path) { - PathString result(path); - if (!result.empty()) { - if (*result.rbegin() == '/') - *result.rbegin() = '\\'; - else if (*result.rbegin() != '\\') - result.push_back('\\'); - } - return result; -} - -PathString ExpandTilde(const PathString& path) { - // Do nothing on windows. - return path; -} - -// Returns a string with length or fewer elements, careful to not truncate a -// string mid-surrogate pair. -PathString TruncatePathString(const PathString& original, int length) { - if (original.size() <= static_cast<size_t>(length)) - return original; - if (length <= 0) - return original; - PathString ret(original.begin(), original.begin() + length); - COMPILE_ASSERT(sizeof(PathChar) == sizeof(uint16), PathStringNotUTF16); - PathChar last_char = *ret.rbegin(); - - // Values taken from - // http://en.wikipedia.org/w/index.php?title=UTF-16/UCS-2&oldid=248072840 - if (last_char >= 0xD800 && last_char <= 0xDBFF) - ret.resize(ret.size() - 1); - return ret; -} - -namespace { -const PathString kWindowsIllegalBaseFilenames[] = { - L"CON", L"PRN", L"AUX", L"NUL", L"COM1", L"COM2", - L"COM3", L"COM4", L"COM5", L"COM6", L"COM7", - L"COM8", L"COM9", L"LPT1", L"LPT2", L"LPT3", - L"LPT4", L"LPT5", L"LPT6", L"LPT7", L"LPT8", - L"LPT9" }; -} - -// See: http://msdn.microsoft.com/library/default.asp?url=/library/ -// en-us/fileio/fs/naming_a_file.asp -// note that * and ? are not listed on the page as illegal characters, -// but they are. -PathString MakePathComponentOSLegal(const PathString& component) { - CHECK(!component.empty()); - PathString mutable_component = component; - - // Remove illegal characters. - for (PathString::iterator i = mutable_component.begin(); - i != mutable_component.end();) { - if ((PathString::npos != PathString(L"<>:\"/\\|*?").find(*i)) || - ((static_cast<unsigned short>(*i) >= 0) && - (static_cast<unsigned short>(*i) <= 31))) { - mutable_component.erase(i); - } else { - ++i; - } - } - - // Remove trailing spaces or periods. - while (mutable_component.size() && - ((mutable_component.at(mutable_component.size() - 1) == L' ') || - (mutable_component.at(mutable_component.size() - 1) == L'.'))) - mutable_component.resize(mutable_component.size() - 1, L' '); - - // Remove a bunch of forbidden names. windows only seems to mind if - // a forbidden name matches our name exactly (e.g. "prn") or if the name is - // the forbidden name, followed by a dot, followed by anything - // (e.g., "prn.anything.foo.bar") - - // From this point out, we break mutable_component into two strings, and use - // them this way: we save anything after and including the first dot (usually - // the extension) and only mess with stuff before the first dot. - PathString::size_type first_dot = mutable_component.find_first_of(L'.'); - if (PathString::npos == first_dot) - first_dot = mutable_component.size(); - PathString sub = mutable_component.substr(0, first_dot); - PathString postsub = mutable_component.substr(first_dot); - CHECK(sub + postsub == mutable_component); - for (int i = 0; i < ARRAYSIZE(kWindowsIllegalBaseFilenames); i++) { - // ComparePathNames(a, b) == 0 -> same - if (syncable::ComparePathNames(kWindowsIllegalBaseFilenames[i], sub) == 0) { - sub.append(L"~1"); - break; - } - } - if ((L"" == sub) && (L"" == postsub)) { - sub = L"~1"; - } - - // Return the new name, only if it differs from the original. - if ((sub + postsub) == component) - return L""; - return (sub + postsub); -} +const char kPathSeparator[] = "/"; diff --git a/chrome/browser/sync/util/path_helpers.h b/chrome/browser/sync/util/path_helpers.h index b370fbd..5ebf465 100644 --- a/chrome/browser/sync/util/path_helpers.h +++ b/chrome/browser/sync/util/path_helpers.h @@ -9,9 +9,11 @@ #include <iterator> #include <string> -#include "chrome/browser/sync/util/compat_file.h" +#include "base/file_path.h" #include "chrome/browser/sync/util/sync_types.h" +extern const char kPathSeparator[]; + template <typename StringType> class PathSegmentIterator : public std::iterator<std::forward_iterator_tag, StringType> { @@ -66,32 +68,6 @@ class PathSegmentIterator : public std::iterator<std::forward_iterator_tag, StringType value_; }; -// NOTE: The functions (Strip)LastPathSegment always return values without a -// trailing slash. -PathString LastPathSegment(const PathString& path); -std::string LastPathSegment(const std::string& path); -PathString AppendSlash(const PathString& path); -PathString GetFullPath(const PathString& path); -PathString ExpandTilde(const PathString& path); - -inline bool HasSuffixPathString(const PathString& str, - const PathString& suffix) { - return str.find(suffix, str.size() - suffix.size()) != PathString::npos; -} - -inline PathString StripSuffixPathString(const PathString& str, - const PathString& suffix) { - PathString ret(str); - if (HasSuffixPathString(str, suffix)) { - ret.resize(str.size() - suffix.size()); - } - return ret; -} - -// Returns a string with length or fewer elements, careful to not truncate a -// string mid-surrogate pair. -PathString TruncatePathString(const PathString& original, int length); - // Makes a path component legal for your OS, but doesn't handle collisions // with other files in the same directory. it can do this by removing // illegal characters and adding ~1 before the first '.' in the filename. diff --git a/chrome/browser/sync/util/path_helpers_linux.cc b/chrome/browser/sync/util/path_helpers_linux.cc index 157fa48..c256d5c 100644 --- a/chrome/browser/sync/util/path_helpers_linux.cc +++ b/chrome/browser/sync/util/path_helpers_linux.cc @@ -8,9 +8,3 @@ #ifndef OS_LINUX #error Compile this file on Linux only. #endif - -PathString GetFullPath(const PathString& path) { - // TODO(sync): Not sure what the base of the relative path should be on - // linux. - return path; -} diff --git a/chrome/browser/sync/util/path_helpers_mac.cc b/chrome/browser/sync/util/path_helpers_mac.cc index 3b1c84a..d4f84c8 100644 --- a/chrome/browser/sync/util/path_helpers_mac.cc +++ b/chrome/browser/sync/util/path_helpers_mac.cc @@ -8,10 +8,3 @@ #ifndef OS_MACOSX #error Compile this file on Mac only. #endif - -PathString GetFullPath(const PathString& path) { - // TODO(sync): Not sure what the base of the relative path should be on - // OS X. - return path; -} - diff --git a/chrome/browser/sync/util/path_helpers_posix.cc b/chrome/browser/sync/util/path_helpers_posix.cc index f613f44..c954271 100644 --- a/chrome/browser/sync/util/path_helpers_posix.cc +++ b/chrome/browser/sync/util/path_helpers_posix.cc @@ -2,95 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <sys/types.h> - -#include <algorithm> -#include <pwd.h> -#include <string.h> - -#include "base/logging.h" -#include "base/port.h" -#include "chrome/browser/sync/util/character_set_converters.h" #include "chrome/browser/sync/util/path_helpers.h" +#include "build/build_config.h" + #if ((!defined(OS_LINUX)) && (!defined(OS_MACOSX))) #error Compile this file on Mac OS X or Linux only. #endif -PathString ExpandTilde(const PathString& path) { - if (path.empty()) - return path; - if ('~' != path[0]) - return path; - PathString ret; - // TODO(sync): Consider using getpwuid_r. - ret.insert(0, getpwuid(getuid())->pw_dir); - ret.append(++path.begin(), path.end()); - return ret; -} - -namespace { -// TODO(sync): We really should use char[]. - std::string cache_dir_; -} - -void set_cache_dir(std::string cache_dir) { - CHECK(cache_dir_.empty()); - cache_dir_ = cache_dir; -} - -std::string get_cache_dir() { - CHECK(!cache_dir_.empty()); - return cache_dir_; -} - -// On Posix, PathStrings are UTF-8, not UTF-16 as they are on Windows. Thus, -// this function is different from the Windows version. -PathString TruncatePathString(const PathString& original, int length) { - if (original.size() <= static_cast<size_t>(length)) - return original; - if (length <= 0) - return original; - PathString ret(original.begin(), original.begin() + length); - COMPILE_ASSERT(sizeof(PathChar) == sizeof(uint8), PathStringNotUTF8); - PathString::reverse_iterator last_char = ret.rbegin(); - - // Values taken from - // http://en.wikipedia.org/w/index.php?title=UTF-8&oldid=252875566 - if (0 == (*last_char & 0x80)) - return ret; - - for (; last_char != ret.rend(); ++last_char) { - if (0 == (*last_char & 0x80)) { - // Got malformed UTF-8; bail. - return ret; - } - if (0 == (*last_char & 0x40)) { - // Got another trailing byte. - continue; - } - break; - } - - if (ret.rend() == last_char) { - // We hit the beginning of the string. bail. - return ret; - } - - int last_codepoint_len = last_char - ret.rbegin() + 1; - - if (((0xC0 == (*last_char & 0xE0)) && (2 == last_codepoint_len)) || - ((0xE0 == (*last_char & 0xF0)) && (3 == last_codepoint_len)) || - ((0xF0 == (*last_char & 0xF8)) && (4 == last_codepoint_len))) { - // Valid utf-8. - return ret; - } - - // Invalid utf-8. chop off last "codepoint" and return. - ret.resize(ret.size() - last_codepoint_len); - return ret; -} - // Convert /s to :s. PathString MakePathComponentOSLegal(const PathString& component) { if (PathString::npos == component.find("/")) @@ -99,25 +18,3 @@ PathString MakePathComponentOSLegal(const PathString& component) { std::replace(new_name.begin(), new_name.end(), '/', ':'); return new_name; } - -string LastPathSegment(const string& path) { - string str(path); - string::size_type final_slash = str.find_last_of('/'); - if (string::npos != final_slash && final_slash == str.length() - 1 - && str.length() > 1) { - str.erase(final_slash); - final_slash = str.find_last_of('/'); - } - if (string::npos == final_slash) - return str; - str.erase(0, final_slash + 1); - return str; -} - -PathString AppendSlash(const PathString& path) { - if ((!path.empty()) && (*path.rbegin() != '/')) { - return path + '/'; - } - return path; -} - diff --git a/chrome/browser/sync/util/path_helpers_unittest.cc b/chrome/browser/sync/util/path_helpers_unittest.cc index 62359e1..e38a5a0 100644 --- a/chrome/browser/sync/util/path_helpers_unittest.cc +++ b/chrome/browser/sync/util/path_helpers_unittest.cc @@ -15,117 +15,66 @@ namespace syncable { class PathHelpersTest : public testing::Test { }; -TEST(PathHelpersTest, TruncatePathStringTest) { - // Simple case. - PathString str = PSTR("12345"); - EXPECT_EQ(PSTR("123"), TruncatePathString(str, 3)); - EXPECT_EQ(str, TruncatePathString(str, str.size())); - - // abcg is "abc" + musical g clef U+1D11E -#if PATHSTRING_IS_STD_STRING - // UTF-8 - PathChar abcg[] = {'a', 'b', 'c', 0xF0, 0x9D, 0x84, 0x9E, '\0'}; -#else // PATHSTRING_IS_STD_STRING - // UTF-16 - PathChar abcg[] = {'a', 'b', 'c', 0xD834, 0xDD1E, '\0'}; -#endif // PATHSTRING_IS_STD_STRING - - EXPECT_EQ(PSTR("abc"), TruncatePathString(abcg, 4)); - - // Further utf-8 tests. -#if PATHSTRING_IS_STD_STRING - // UTF-8 - - EXPECT_EQ(PSTR("abc"), TruncatePathString(abcg, 4)); - EXPECT_EQ(PSTR("abc"), TruncatePathString(abcg, 5)); - EXPECT_EQ(PSTR("abc"), TruncatePathString(abcg, 6)); - EXPECT_EQ(PathString(abcg), TruncatePathString(abcg, 7)); - - PathChar abc2[] = {'a', 'b', 'c', 0xC3, 0xB1, '\0'}; // abc(n w/ tilde) - EXPECT_EQ(PSTR("abc"), TruncatePathString(abc2, 3)); - EXPECT_EQ(PSTR("abc"), TruncatePathString(abc2, 4)); - EXPECT_EQ(PathString(abc2), TruncatePathString(abc2, 5)); - - PathChar abc3[] = {'a', 'b', 'c', 0xE2, 0x82, 0xAC, '\0'}; // abc(euro) - EXPECT_EQ(PSTR("abc"), TruncatePathString(abc3, 3)); - EXPECT_EQ(PSTR("abc"), TruncatePathString(abc3, 4)); - EXPECT_EQ(PSTR("abc"), TruncatePathString(abc3, 5)); - EXPECT_EQ(PathString(abc3), TruncatePathString(abc3, 6)); -#endif -} - -TEST(PathHelpersTest, PathStrutil) { - PathString big = PSTR("abcdef"); - PathString suffix = PSTR("def"); - PathString other = PSTR("x"); - EXPECT_TRUE(HasSuffixPathString(big, suffix)); - EXPECT_FALSE(HasSuffixPathString(suffix, big)); - EXPECT_FALSE(HasSuffixPathString(big, other)); - EXPECT_EQ(PSTR("abc"), StripSuffixPathString(big, suffix)); -} - TEST(PathHelpersTest, SanitizePathComponent) { #if defined(OS_WIN) - EXPECT_EQ(MakePathComponentOSLegal(L"bar"), L""); - EXPECT_EQ(MakePathComponentOSLegal(L"bar <"), L"bar"); - EXPECT_EQ(MakePathComponentOSLegal(L"bar.<"), L"bar"); - EXPECT_EQ(MakePathComponentOSLegal(L"prn"), L"prn~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"pr>n"), L"prn~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"ab:c"), L"abc"); - EXPECT_EQ(MakePathComponentOSLegal(L"a|bc"), L"abc"); - EXPECT_EQ(MakePathComponentOSLegal(L"baz~9"), L""); - EXPECT_EQ(MakePathComponentOSLegal(L"\007"), L"~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"com1.txt.bat"), L"com1~1.txt.bat"); - EXPECT_EQ(MakePathComponentOSLegal(L"foo.com1.bat"), L""); - EXPECT_EQ(MakePathComponentOSLegal(L"\010gg"), L"gg"); - EXPECT_EQ(MakePathComponentOSLegal(L"<"), L"~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"col:on"), L"colon"); - EXPECT_EQ(MakePathComponentOSLegal(L"q\""), L"q"); - EXPECT_EQ(MakePathComponentOSLegal(L"back\\slAsh"), L"backslAsh"); - EXPECT_EQ(MakePathComponentOSLegal(L"sla/sh "), L"slash"); - EXPECT_EQ(MakePathComponentOSLegal(L"s|laSh"), L"slaSh"); - EXPECT_EQ(MakePathComponentOSLegal(L"CON"), L"CON~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"PRN"), L"PRN~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"AUX"), L"AUX~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"NUL"), L"NUL~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"COM1"), L"COM1~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"COM2"), L"COM2~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"COM3"), L"COM3~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"COM4"), L"COM4~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"COM5"), L"COM5~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"COM6"), L"COM6~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"COM7"), L"COM7~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"COM8"), L"COM8~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"COM9"), L"COM9~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"LPT1"), L"LPT1~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"LPT2"), L"LPT2~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"LPT3"), L"LPT3~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"LPT4"), L"LPT4~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"LPT5"), L"LPT5~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"LPT6"), L"LPT6~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"LPT7"), L"LPT7~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"LPT8"), L"LPT8~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"LPT9"), L"LPT9~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"bar~bar"), L""); - EXPECT_EQ(MakePathComponentOSLegal(L"adlr~-3"), L""); - EXPECT_EQ(MakePathComponentOSLegal(L"tilde~"), L""); - EXPECT_EQ(MakePathComponentOSLegal(L"mytext.txt"), L""); - EXPECT_EQ(MakePathComponentOSLegal(L"mytext|.txt"), L"mytext.txt"); - EXPECT_EQ(MakePathComponentOSLegal(L"okay.com1.txt"), L""); - EXPECT_EQ(MakePathComponentOSLegal(L"software-3.tar.gz"), L""); - EXPECT_EQ(MakePathComponentOSLegal(L"<"), L"~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"<.<"), L"~1"); - EXPECT_EQ(MakePathComponentOSLegal(L"<.<txt"), L".txt"); - EXPECT_EQ(MakePathComponentOSLegal(L"txt<.<"), L"txt"); + EXPECT_EQ(MakePathComponentOSLegal("bar"), ""); + EXPECT_EQ(MakePathComponentOSLegal("bar <"), "bar"); + EXPECT_EQ(MakePathComponentOSLegal("bar.<"), "bar"); + EXPECT_EQ(MakePathComponentOSLegal("prn"), "prn~1"); + EXPECT_EQ(MakePathComponentOSLegal("pr>n"), "prn~1"); + EXPECT_EQ(MakePathComponentOSLegal("ab:c"), "abc"); + EXPECT_EQ(MakePathComponentOSLegal("a|bc"), "abc"); + EXPECT_EQ(MakePathComponentOSLegal("baz~9"), ""); + EXPECT_EQ(MakePathComponentOSLegal("\007"), "~1"); + EXPECT_EQ(MakePathComponentOSLegal("com1.txt.bat"), "com1~1.txt.bat"); + EXPECT_EQ(MakePathComponentOSLegal("foo.com1.bat"), ""); + EXPECT_EQ(MakePathComponentOSLegal("\010gg"), "gg"); + EXPECT_EQ(MakePathComponentOSLegal("<"), "~1"); + EXPECT_EQ(MakePathComponentOSLegal("col:on"), "colon"); + EXPECT_EQ(MakePathComponentOSLegal("q\""), "q"); + EXPECT_EQ(MakePathComponentOSLegal("back\\slAsh"), "backslAsh"); + EXPECT_EQ(MakePathComponentOSLegal("sla/sh "), "slash"); + EXPECT_EQ(MakePathComponentOSLegal("s|laSh"), "slaSh"); + EXPECT_EQ(MakePathComponentOSLegal("CON"), "CON~1"); + EXPECT_EQ(MakePathComponentOSLegal("PRN"), "PRN~1"); + EXPECT_EQ(MakePathComponentOSLegal("AUX"), "AUX~1"); + EXPECT_EQ(MakePathComponentOSLegal("NUL"), "NUL~1"); + EXPECT_EQ(MakePathComponentOSLegal("COM1"), "COM1~1"); + EXPECT_EQ(MakePathComponentOSLegal("COM2"), "COM2~1"); + EXPECT_EQ(MakePathComponentOSLegal("COM3"), "COM3~1"); + EXPECT_EQ(MakePathComponentOSLegal("COM4"), "COM4~1"); + EXPECT_EQ(MakePathComponentOSLegal("COM5"), "COM5~1"); + EXPECT_EQ(MakePathComponentOSLegal("COM6"), "COM6~1"); + EXPECT_EQ(MakePathComponentOSLegal("COM7"), "COM7~1"); + EXPECT_EQ(MakePathComponentOSLegal("COM8"), "COM8~1"); + EXPECT_EQ(MakePathComponentOSLegal("COM9"), "COM9~1"); + EXPECT_EQ(MakePathComponentOSLegal("LPT1"), "LPT1~1"); + EXPECT_EQ(MakePathComponentOSLegal("LPT2"), "LPT2~1"); + EXPECT_EQ(MakePathComponentOSLegal("LPT3"), "LPT3~1"); + EXPECT_EQ(MakePathComponentOSLegal("LPT4"), "LPT4~1"); + EXPECT_EQ(MakePathComponentOSLegal("LPT5"), "LPT5~1"); + EXPECT_EQ(MakePathComponentOSLegal("LPT6"), "LPT6~1"); + EXPECT_EQ(MakePathComponentOSLegal("LPT7"), "LPT7~1"); + EXPECT_EQ(MakePathComponentOSLegal("LPT8"), "LPT8~1"); + EXPECT_EQ(MakePathComponentOSLegal("LPT9"), "LPT9~1"); + EXPECT_EQ(MakePathComponentOSLegal("bar~bar"), ""); + EXPECT_EQ(MakePathComponentOSLegal("adlr~-3"), ""); + EXPECT_EQ(MakePathComponentOSLegal("tilde~"), ""); + EXPECT_EQ(MakePathComponentOSLegal("mytext.txt"), ""); + EXPECT_EQ(MakePathComponentOSLegal("mytext|.txt"), "mytext.txt"); + EXPECT_EQ(MakePathComponentOSLegal("okay.com1.txt"), ""); + EXPECT_EQ(MakePathComponentOSLegal("software-3.tar.gz"), ""); + EXPECT_EQ(MakePathComponentOSLegal("<"), "~1"); + EXPECT_EQ(MakePathComponentOSLegal("<.<"), "~1"); + EXPECT_EQ(MakePathComponentOSLegal("<.<txt"), ".txt"); + EXPECT_EQ(MakePathComponentOSLegal("txt<.<"), "txt"); #else // !defined(OS_WIN) - EXPECT_EQ(MakePathComponentOSLegal("bar"), ""); EXPECT_EQ(MakePathComponentOSLegal("b"), ""); EXPECT_EQ(MakePathComponentOSLegal("A"), ""); EXPECT_EQ(MakePathComponentOSLegal("<'|"), ""); EXPECT_EQ(MakePathComponentOSLegal("/"), ":"); EXPECT_EQ(MakePathComponentOSLegal(":"), ""); - #endif // defined(OS_WIN) } diff --git a/chrome/browser/sync/util/path_helpers_win.cc b/chrome/browser/sync/util/path_helpers_win.cc new file mode 100644 index 0000000..8fe60df --- /dev/null +++ b/chrome/browser/sync/util/path_helpers_win.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/sync/util/path_helpers.h" + +#include <Shlwapi.h> +#include <stdlib.h> + +#include "base/logging.h" +#include "base/port.h" +#include "build/build_config.h" +#include "chrome/browser/sync/syncable/syncable.h" + +#ifndef OS_WIN +#error Compile this file on Windows only. +#endif + +using std::string; + +namespace { +const PathString kWindowsIllegalBaseFilenames[] = { + "CON", "PRN", "AUX", "NUL", "COM1", "COM2", + "COM3", "COM4", "COM5", "COM6", "COM7", + "COM8", "COM9", "LPT1", "LPT2", "LPT3", + "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", + "LPT9" }; +} + +// See: http://msdn.microsoft.com/library/default.asp?url=/library/ +// en-us/fileio/fs/naming_a_file.asp +// note that * and ? are not listed on the page as illegal characters, +// but they are. +PathString MakePathComponentOSLegal(const PathString& component) { + CHECK(!component.empty()); + PathString mutable_component = component; + + // Remove illegal characters. + for (PathString::iterator i = mutable_component.begin(); + i != mutable_component.end();) { + if ((PathString::npos != PathString("<>:\"/\\|*?").find(*i)) || + ((static_cast<unsigned short>(*i) >= 0) && + (static_cast<unsigned short>(*i) <= 31))) { + mutable_component.erase(i); + } else { + ++i; + } + } + + // Remove trailing spaces or periods. + while (mutable_component.size() && + ((mutable_component.at(mutable_component.size() - 1) == ' ') || + (mutable_component.at(mutable_component.size() - 1) == '.'))) + mutable_component.resize(mutable_component.size() - 1, ' '); + + // Remove a bunch of forbidden names. windows only seems to mind if + // a forbidden name matches our name exactly (e.g. "prn") or if the name is + // the forbidden name, followed by a dot, followed by anything + // (e.g., "prn.anything.foo.bar") + + // From this point out, we break mutable_component into two strings, and use + // them this way: we save anything after and including the first dot (usually + // the extension) and only mess with stuff before the first dot. + PathString::size_type first_dot = mutable_component.find_first_of('.'); + if (PathString::npos == first_dot) + first_dot = mutable_component.size(); + PathString sub = mutable_component.substr(0, first_dot); + PathString postsub = mutable_component.substr(first_dot); + CHECK(sub + postsub == mutable_component); + for (int i = 0; i < ARRAYSIZE(kWindowsIllegalBaseFilenames); i++) { + // ComparePathNames(a, b) == 0 -> same + if (syncable::ComparePathNames(kWindowsIllegalBaseFilenames[i], sub) == 0) { + sub.append("~1"); + break; + } + } + if (("" == sub) && ("" == postsub)) { + sub = "~1"; + } + + // Return the new name, only if it differs from the original. + if ((sub + postsub) == component) + return ""; + return (sub + postsub); +} diff --git a/chrome/browser/sync/util/query_helpers.cc b/chrome/browser/sync/util/query_helpers.cc index c27a877..46e8ee0 100644 --- a/chrome/browser/sync/util/query_helpers.cc +++ b/chrome/browser/sync/util/query_helpers.cc @@ -13,6 +13,7 @@ #include <vector> #include "chrome/browser/sync/util/sync_types.h" +#include "chrome/common/sqlite_utils.h" using std::numeric_limits; using std::string; @@ -55,26 +56,21 @@ int Exec(sqlite3* dbhandle, const char* query, sqlite3_stmt* statement) { return SQLITE_OK == finalize_result ? result : finalize_result; } -int SqliteOpen(PathString filename, sqlite3** db) { - int result = -#if PATHSTRING_IS_STD_STRING - sqlite3_open -#else - sqlite3_open16 -#endif - (filename.c_str(), db); - LOG_IF(ERROR, SQLITE_OK != result) << "Error opening " << filename << ": " +int SqliteOpen(const FilePath& filename, sqlite3** db) { + int result = OpenSqliteDb(filename, db); + LOG_IF(ERROR, SQLITE_OK != result) << "Error opening " + << filename.value() << ": " << result; #if defined(OS_WIN) if (SQLITE_OK == result) { // Make sure we mark the db file as not indexed so since if any other app // opens it, it can break our db locking. - DWORD attrs = GetFileAttributes(filename.c_str()); + DWORD attrs = GetFileAttributesW(filename.value().c_str()); if (FILE_ATTRIBUTE_NORMAL == attrs) attrs = FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; else attrs = attrs | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; - SetFileAttributes(filename.c_str(), attrs); + SetFileAttributesW(filename.value().c_str(), attrs); } #endif // defined(OS_WIN) // Be patient as we set pragmas. @@ -87,27 +83,6 @@ int SqliteOpen(PathString filename, sqlite3** db) { return SQLITE_OK; } -#if !PATHSTRING_IS_STD_STRING -sqlite3_stmt* BindArg(sqlite3_stmt* statement, const PathString& s, int index) { - if (NULL == statement) - return statement; - CHECK(SQLITE_OK == sqlite3_bind_text16(statement, index, s.data(), - CountBytes(s), SQLITE_TRANSIENT)); - return statement; -} - -sqlite3_stmt* BindArg(sqlite3_stmt* statement, const PathChar* s, int index) { - if (NULL == statement) - return statement; - CHECK(SQLITE_OK == sqlite3_bind_text16(statement, - index, - s, - -1, // -1 means s is zero-terminated - SQLITE_TRANSIENT)); - return statement; -} -#endif // !PATHSTRING_IS_STD_STRING - sqlite3_stmt* BindArg(sqlite3_stmt* statement, const string& s, int index) { if (NULL == statement) return statement; @@ -179,17 +154,15 @@ sqlite3_stmt* BindArg(sqlite3_stmt* statement, SqliteNullType, int index) { return statement; } -#if !PATHSTRING_IS_STD_STRING -void GetColumn(sqlite3_stmt* statement, int index, PathString* value) { +void GetColumn(sqlite3_stmt* statement, int index, string16* value) { if (sqlite3_column_type(statement, index) == SQLITE_NULL) { value->clear(); } else { value->assign( - static_cast<const PathChar*>(sqlite3_column_text16(statement, index)), - sqlite3_column_bytes16(statement, index) / sizeof(PathChar)); + static_cast<const char16*>(sqlite3_column_text16(statement, index)), + sqlite3_column_bytes16(statement, index) / sizeof(char16)); } } -#endif // !PATHSTRING_IS_STD_STRING void GetColumn(sqlite3_stmt* statement, int index, string* value) { if (sqlite3_column_type(statement, index) == SQLITE_NULL) { diff --git a/chrome/browser/sync/util/query_helpers.h b/chrome/browser/sync/util/query_helpers.h index 54cda1f..66b1d81 100644 --- a/chrome/browser/sync/util/query_helpers.h +++ b/chrome/browser/sync/util/query_helpers.h @@ -12,7 +12,9 @@ #include <vector> #include "base/basictypes.h" +#include "base/file_path.h" #include "base/logging.h" +#include "base/string16.h" #include "build/build_config.h" #include "chrome/browser/sync/util/sync_types.h" #include "third_party/sqlite/preprocessed/sqlite3.h" @@ -21,13 +23,9 @@ enum SqliteNullType { SQLITE_NULL_VALUE }; -int SqliteOpen(PathString filename, sqlite3** ppDb); +int SqliteOpen(const FilePath& filename, sqlite3** ppDb); sqlite3_stmt* PrepareQuery(sqlite3* dbhandle, const char* query); -#if !PATHSTRING_IS_STD_STRING -sqlite3_stmt* BindArg(sqlite3_stmt*, const PathString&, int index); -sqlite3_stmt* BindArg(sqlite3_stmt*, const PathChar*, int index); -#endif sqlite3_stmt* BindArg(sqlite3_stmt*, const std::string&, int index); sqlite3_stmt* BindArg(sqlite3_stmt*, const char*, int index); sqlite3_stmt* BindArg(sqlite3_stmt*, int32, int index); @@ -37,9 +35,7 @@ sqlite3_stmt* BindArg(sqlite3_stmt*, bool, int index); sqlite3_stmt* BindArg(sqlite3_stmt*, const std::vector<uint8>&, int index); sqlite3_stmt* BindArg(sqlite3_stmt*, SqliteNullType, int index); -#if !PATHSTRING_IS_STD_STRING -void GetColumn(sqlite3_stmt*, int index, PathString* value); -#endif +void GetColumn(sqlite3_stmt*, int index, string16* value); void GetColumn(sqlite3_stmt*, int index, std::string* value); void GetColumn(sqlite3_stmt*, int index, int32* value); void GetColumn(sqlite3_stmt*, int index, int64* value); diff --git a/chrome/browser/sync/util/query_helpers_unittest.cc b/chrome/browser/sync/util/query_helpers_unittest.cc index 0fb86e2..43c0488 100644 --- a/chrome/browser/sync/util/query_helpers_unittest.cc +++ b/chrome/browser/sync/util/query_helpers_unittest.cc @@ -7,7 +7,9 @@ #include <limits> #include <string> -#include "chrome/browser/sync/util/compat_file.h" +#include "base/file_util.h" +#include "chrome/common/sqlite_utils.h" +#include "chrome/test/file_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" using std::numeric_limits; @@ -25,12 +27,19 @@ TEST(QueryHelpers, APEncode) { } TEST(QueryHelpers, TestExecFailure) { - sqlite3* database; - const PathString test_database(PSTR("queryhelper_test.sqlite3")); - PathRemove(test_database); - ASSERT_EQ(SQLITE_OK, SqliteOpen(test_database, &database)); - EXPECT_EQ(SQLITE_DONE, Exec(database, "CREATE TABLE test_table (idx int)")); - EXPECT_NE(SQLITE_DONE, Exec(database, "ALTER TABLE test_table ADD COLUMN " - "broken int32 default ?", -1)); - PathRemove(test_database); + FilePath test_database; + file_util::GetCurrentDirectory(&test_database); + test_database = test_database.Append( + FILE_PATH_LITERAL("queryhelper_test.sqlite3")); + // Cleanup left-over file, if present. + file_util::Delete(test_database, true); + FileAutoDeleter file_deleter(test_database); + { + sqlite3* database = NULL; + ASSERT_EQ(SQLITE_OK, SqliteOpen(test_database, &database)); + sqlite_utils::scoped_sqlite_db_ptr database_deleter(database); + EXPECT_EQ(SQLITE_DONE, Exec(database, "CREATE TABLE test_table (idx int)")); + EXPECT_NE(SQLITE_DONE, Exec(database, "ALTER TABLE test_table ADD COLUMN " + "broken int32 default ?", -1)); + } } diff --git a/chrome/browser/sync/util/sync_types.h b/chrome/browser/sync/util/sync_types.h index 71b9c42..429033b 100644 --- a/chrome/browser/sync/util/sync_types.h +++ b/chrome/browser/sync/util/sync_types.h @@ -12,34 +12,11 @@ #include "base/string_util.h" #include "build/build_config.h" -// TODO(timsteele): Use base/file_path.h instead of PathString. -#if defined(OS_WIN) -#define PATHSTRING_IS_STD_STRING 0 -typedef std::wstring PathString; - -// This ugly double define hack is needed to allow the following pattern on -// Windows: -// -// #define FOO "Foo" -// #define FOO_PATH_STRING PSTR("Foo") -// -// TODO(sync): find out if we can avoid this. -#define PSTR_UGLY_DOUBLE_DEFINE_HACK(s) L##s -#define PSTR(s) PSTR_UGLY_DOUBLE_DEFINE_HACK(s) -#define PSTR_CHAR wchar_t - -inline size_t PathLen(const wchar_t* s) { - return wcslen(s); -} - -#else // Mac and Linux -#define PATHSTRING_IS_STD_STRING 1 +#define PSTR(s) s #define PSTR_CHAR char typedef std::string PathString; -#define PSTR(s) s -inline size_t PathLen(const char* s) { - return strlen(s); -} + +#if !defined(OS_WIN) // Mac OS X typedef's BOOL to signed char, so we do that on Linux too. typedef signed char BOOL; typedef int32 LONG; diff --git a/chrome/browser/sync/util/user_settings.cc b/chrome/browser/sync/util/user_settings.cc index 1c867a6..bb60af2 100644 --- a/chrome/browser/sync/util/user_settings.cc +++ b/chrome/browser/sync/util/user_settings.cc @@ -84,12 +84,12 @@ void UserSettings::MigrateOldVersionsAsNeeded(sqlite3* const handle, "SELECT share_name, file_name FROM shares")); int query_result = sqlite3_step(share_query.get()); CHECK(SQLITE_ROW == query_result); - PathString share_name, file_name; + FilePath::StringType share_name, file_name; GetColumn(share_query.get(), 0, &share_name); GetColumn(share_query.get(), 1, &file_name); if (!file_util::Move(FilePath(file_name), - FilePath(DirectoryManager::GetSyncDataDatabaseFilename()))) { + DirectoryManager::GetSyncDataDatabaseFilename())) { LOG(WARNING) << "Unable to upgrade UserSettings from v10"; return; } @@ -128,12 +128,12 @@ static void MakeClientIDTable(sqlite3* const dbhandle) { Generate128BitRandomHexString()); } -bool UserSettings::Init(const PathString& settings_path) { - { // Scope the handle +bool UserSettings::Init(const FilePath& settings_path) { + { // Scope the handle. ScopedDBHandle dbhandle(this); if (dbhandle_) sqlite3_close(dbhandle_); - CHECK(SQLITE_OK == SqliteOpen(settings_path.c_str(), &dbhandle_)); + CHECK(SQLITE_OK == SqliteOpen(settings_path, &dbhandle_)); // In the worst case scenario, the user may hibernate his computer during // one of our transactions. sqlite3_busy_timeout(dbhandle_, numeric_limits<int>::max()); @@ -183,9 +183,9 @@ bool UserSettings::Init(const PathString& settings_path) { #if defined(OS_WIN) // Do not index this file. Scanning can occur every time we close the file, // which causes long delays in SQLite's file locking. - const DWORD attrs = GetFileAttributes(settings_path.c_str()); + const DWORD attrs = GetFileAttributes(settings_path.value().c_str()); const BOOL attrs_set = - SetFileAttributes(settings_path.c_str(), + SetFileAttributes(settings_path.value().c_str(), attrs | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); #endif return true; diff --git a/chrome/browser/sync/util/user_settings.h b/chrome/browser/sync/util/user_settings.h index 60ad1a9..8f7197d 100644 --- a/chrome/browser/sync/util/user_settings.h +++ b/chrome/browser/sync/util/user_settings.h @@ -9,6 +9,7 @@ #include <set> #include <string> +#include "base/file_path.h" #include "base/lock.h" #include "build/build_config.h" #include "chrome/browser/sync/util/signin.h" @@ -27,7 +28,7 @@ class UserSettings { UserSettings(); ~UserSettings(); // Returns false (failure) if the db is a newer version. - bool Init(const PathString& settings_path); + bool Init(const FilePath& settings_path); void StoreHashedPassword(const std::string& email, const std::string& password); bool VerifyAgainstStoredHash(const std::string& email, @@ -59,8 +60,6 @@ class UserSettings { void RemoveAllGuestSettings(); - void RemoveShare(const PathString& share_path); - void StoreEmailForSignin(const std::string& signin, const std::string& primary_email); diff --git a/chrome/browser/sync/util/user_settings_unittest.cc b/chrome/browser/sync/util/user_settings_unittest.cc index 02f3fd8..ec7676b 100644 --- a/chrome/browser/sync/util/user_settings_unittest.cc +++ b/chrome/browser/sync/util/user_settings_unittest.cc @@ -12,10 +12,15 @@ #include "chrome/browser/sync/util/query_helpers.h" #include "testing/gtest/include/gtest/gtest.h" +using browser_sync::FilePathToUTF8; using browser_sync::UserSettings; -static const PathChar* kV10UserSettingsDB = PSTR("Version10Settings.sqlite3"); -static const PathChar* kOldStyleSyncDataDB = PSTR("OldStyleSyncData.sqlite3"); +static const FilePath::CharType kV10UserSettingsDB[] = + FILE_PATH_LITERAL("Version10Settings.sqlite3"); +static const FilePath::CharType kOldStyleSyncDataDB[] = + FILE_PATH_LITERAL("OldStyleSyncData.sqlite3"); +static const FilePath::CharType kSyncDataDB[] = + FILE_PATH_LITERAL("SyncData.sqlite3"); class UserSettingsTest : public testing::Test { public: @@ -23,7 +28,7 @@ class UserSettingsTest : public testing::Test { void SetUpVersion10Databases() { CleanUpVersion10Databases(); sqlite3* primer_handle = NULL; - ASSERT_TRUE(SQLITE_OK == SqliteOpen(kV10UserSettingsDB, + ASSERT_TRUE(SQLITE_OK == SqliteOpen(FilePath(kV10UserSettingsDB), &primer_handle)); FilePath old_sync_data(kOldStyleSyncDataDB); @@ -45,16 +50,14 @@ class UserSettingsTest : public testing::Test { " PRIMARY KEY(email, share_name) ON CONFLICT REPLACE)"); // Populate a share. ExecOrDie(primer_handle, "INSERT INTO shares values ( ?, ?, ?)", - "foo@foo.com", "foo@foo.com", - browser_sync::PathStringToUTF8Quick(kOldStyleSyncDataDB)); + "foo@foo.com", "foo@foo.com", FilePathToUTF8(old_sync_data)); sqlite3_close(primer_handle); } void CleanUpVersion10Databases() { ASSERT_TRUE(file_util::DieFileDie(FilePath(kV10UserSettingsDB), false)); ASSERT_TRUE(file_util::DieFileDie(FilePath(kOldStyleSyncDataDB), false)); - ASSERT_TRUE(file_util::DieFileDie(FilePath(PSTR("SyncData.sqlite3")), - false)); + ASSERT_TRUE(file_util::DieFileDie(FilePath(kSyncDataDB), false)); } const std::string& sync_data() const { return sync_data_; } @@ -70,21 +73,22 @@ TEST_F(UserSettingsTest, MigrateFromV10ToV11) { // inside a scoped block so it closes itself and we can poke around to see // what happened later. UserSettings settings; - settings.Init(kV10UserSettingsDB); + settings.Init(FilePath(kV10UserSettingsDB)); } // Now poke around using sqlite to see if UserSettings migrated properly. sqlite3* handle = NULL; - ASSERT_TRUE(SQLITE_OK == SqliteOpen(kV10UserSettingsDB, &handle)); + ASSERT_TRUE(SQLITE_OK == SqliteOpen(FilePath(kV10UserSettingsDB), &handle)); ScopedStatement version_query(PrepareQuery(handle, "SELECT version FROM db_version")); ASSERT_TRUE(SQLITE_ROW == sqlite3_step(version_query.get())); const int version = sqlite3_column_int(version_query.get(), 0); - EXPECT_TRUE(11 == version); + EXPECT_EQ(11, version); EXPECT_FALSE(file_util::PathExists(FilePath(kOldStyleSyncDataDB))); - PathString path(syncable::DirectoryManager::GetSyncDataDatabaseFilename()); + const FilePath& path = + syncable::DirectoryManager::GetSyncDataDatabaseFilename(); std::string contents; ASSERT_TRUE(file_util::ReadFileToString(FilePath(path), &contents)); |