Home | History | Annotate | Download | only in database
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "webkit/browser/database/database_util.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/strings/utf_string_conversions.h"
      9 #include "webkit/browser/database/database_tracker.h"
     10 #include "webkit/browser/database/vfs_backend.h"
     11 
     12 namespace webkit_database {
     13 
     14 const char DatabaseUtil::kJournalFileSuffix[] = "-journal";
     15 
     16 bool DatabaseUtil::CrackVfsFileName(const base::string16& vfs_file_name,
     17                                     std::string* origin_identifier,
     18                                     base::string16* database_name,
     19                                     base::string16* sqlite_suffix) {
     20   // 'vfs_file_name' is of the form <origin_identifier>/<db_name>#<suffix>.
     21   // <suffix> is optional.
     22   DCHECK(!vfs_file_name.empty());
     23   size_t first_slash_index = vfs_file_name.find('/');
     24   size_t last_pound_index = vfs_file_name.rfind('#');
     25   // '/' and '#' must be present in the string. Also, the string cannot start
     26   // with a '/' (origin_identifier cannot be empty) and '/' must come before '#'
     27   if ((first_slash_index == base::string16::npos) ||
     28       (last_pound_index == base::string16::npos) ||
     29       (first_slash_index == 0) ||
     30       (first_slash_index > last_pound_index)) {
     31     return false;
     32   }
     33 
     34   if (origin_identifier) {
     35     *origin_identifier = UTF16ToASCII(
     36         vfs_file_name.substr(0, first_slash_index));
     37   }
     38   if (database_name) {
     39     *database_name = vfs_file_name.substr(
     40         first_slash_index + 1, last_pound_index - first_slash_index - 1);
     41   }
     42   if (sqlite_suffix) {
     43     *sqlite_suffix = vfs_file_name.substr(
     44         last_pound_index + 1, vfs_file_name.length() - last_pound_index - 1);
     45   }
     46   return true;
     47 }
     48 
     49 base::FilePath DatabaseUtil::GetFullFilePathForVfsFile(
     50     DatabaseTracker* db_tracker, const base::string16& vfs_file_name) {
     51   std::string origin_identifier;
     52   base::string16 database_name;
     53   base::string16 sqlite_suffix;
     54   if (!CrackVfsFileName(vfs_file_name, &origin_identifier,
     55                         &database_name, &sqlite_suffix)) {
     56     return base::FilePath(); // invalid vfs_file_name
     57   }
     58 
     59   base::FilePath full_path = db_tracker->GetFullDBFilePath(
     60       origin_identifier, database_name);
     61   if (!full_path.empty() && !sqlite_suffix.empty()) {
     62     DCHECK(full_path.Extension().empty());
     63     full_path = full_path.InsertBeforeExtensionASCII(
     64         UTF16ToASCII(sqlite_suffix));
     65   }
     66   // Watch out for directory traversal attempts from a compromised renderer.
     67   if (full_path.value().find(FILE_PATH_LITERAL("..")) !=
     68           base::FilePath::StringType::npos)
     69     return base::FilePath();
     70   return full_path;
     71 }
     72 
     73 bool DatabaseUtil::IsValidOriginIdentifier(
     74     const std::string& origin_identifier) {
     75   std::string dotdot = "..";
     76   char forbidden[] = {'\\', '/', '\0'};
     77 
     78   std::string::size_type pos = origin_identifier.find(dotdot);
     79   if (pos == std::string::npos)
     80     pos = origin_identifier.find_first_of(forbidden, 0, arraysize(forbidden));
     81 
     82   return pos == std::string::npos;
     83 }
     84 
     85 }  // namespace webkit_database
     86