// 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 #include #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 string 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. string MakePathComponentOSLegal(const string& component) { CHECK(!component.empty()); string mutable_component = component; // Remove illegal characters. for (string::iterator i = mutable_component.begin(); i != mutable_component.end();) { if ((string::npos != string("<>:\"/\\|*?").find(*i)) || ((static_cast(*i) >= 0) && (static_cast(*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. string::size_type first_dot = mutable_component.find_first_of('.'); if (string::npos == first_dot) first_dot = mutable_component.size(); string sub = mutable_component.substr(0, first_dot); string 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); }