예제 #1
0
String IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(const SecurityOriginData& topLevelOrigin, const SecurityOriginData& openingOrigin, const String& rootDirectory)
{
    String mainFrameDirectory = pathByAppendingComponent(rootDirectory, topLevelOrigin.databaseIdentifier());

    // If the opening origin and main frame origins are the same, there is no partitioning.
    if (openingOrigin == topLevelOrigin)
        return mainFrameDirectory;

    return pathByAppendingComponent(mainFrameDirectory, openingOrigin.databaseIdentifier());
}
예제 #2
0
파일: IDBServer.cpp 프로젝트: josecu/webkit
static void removeAllDatabasesForOriginPath(const String& originPath, std::chrono::system_clock::time_point modifiedSince)
{
    Vector<String> databasePaths = listDirectory(originPath, "*");

    for (auto& databasePath : databasePaths) {
        String databaseFile = pathByAppendingComponent(databasePath, "IndexedDB.sqlite3");

        if (!fileExists(databaseFile))
            continue;

        if (modifiedSince > std::chrono::system_clock::time_point::min()) {
            time_t modificationTime;
            if (!getFileModificationTime(databaseFile, modificationTime))
                continue;

            if (std::chrono::system_clock::from_time_t(modificationTime) < modifiedSince)
                continue;
        }

        SQLiteFileSystem::deleteDatabaseFile(databaseFile);
        deleteEmptyDirectory(databasePath);
    }

    deleteEmptyDirectory(originPath);
}
예제 #3
0
std::unique_ptr<IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLite::getOrEstablishMetadata()
{
    ASSERT(!isMainThread());

    String dbFilename = pathByAppendingComponent(m_absoluteDatabaseDirectory, "IndexedDB.sqlite3");
    m_sqliteDB = openSQLiteDatabaseAtPath(dbFilename);
    if (!m_sqliteDB)
        return nullptr;

    RefPtr<UniqueIDBDatabaseBackingStoreSQLite> protector(this);
    m_sqliteDB->setCollationFunction("IDBKEY", [this](int aLength, const void* a, int bLength, const void* b) {
        return collate(aLength, a, bLength, b);
    });

    std::unique_ptr<IDBDatabaseMetadata> metadata = extractExistingMetadata();
    if (!metadata)
        metadata = createAndPopulateInitialMetadata();

    if (!metadata)
        LOG_ERROR("Unable to establish IDB database at path '%s'", dbFilename.utf8().data());

    // The database id is a runtime concept and doesn't need to be stored in the metadata database.
    metadata->id = generateDatabaseId();

    return metadata;
}
예제 #4
0
static PassRefPtr<IDBSQLiteDatabase> openSQLiteDatabase(SecurityOrigin* securityOrigin, const String& pathBase, int64_t maximumSize, const String& fileIdentifier, IDBFactoryBackendImpl* factory)
{
    String path = ":memory:";
    if (!pathBase.isEmpty()) {
        if (!makeAllDirectories(pathBase)) {
            // FIXME: Is there any other thing we could possibly do to recover at this point? If so, do it rather than just erroring out.
            LOG_ERROR("Unabled to create LocalStorage database path %s", pathBase.utf8().data());
            return 0;
        }

        path = pathByAppendingComponent(pathBase, securityOrigin->databaseIdentifier() + ".indexeddb");
    }

    RefPtr<IDBSQLiteDatabase> sqliteDatabase = IDBSQLiteDatabase::create(fileIdentifier, factory);
    if (!sqliteDatabase->db().open(path)) {
        // FIXME: Is there any other thing we could possibly do to recover at this point? If so, do it rather than just erroring out.
        LOG_ERROR("Failed to open database file %s for IndexedDB", path.utf8().data());
        return 0;
    }

    // FIXME: Error checking?
    sqliteDatabase->db().setMaximumSize(maximumSize);
    sqliteDatabase->db().turnOnIncrementalAutoVacuum();

    return sqliteDatabase.release();
}
예제 #5
0
static void removeAllDatabasesForOriginPath(const String& originPath, double startDate, double endDate)
{
    // FIXME: We should also close/invalidate any live handles to the database files we are about to delete.
    // Right now:
    //     - For read-only operations, they will continue functioning as normal on the unlinked file.
    //     - For write operations, they will start producing errors as SQLite notices the missing backing store.
    // This is tracked by https://bugs.webkit.org/show_bug.cgi?id=135347

    Vector<String> databasePaths = listDirectory(originPath, "*");

    for (auto& databasePath : databasePaths) {
        String databaseFile = pathByAppendingComponent(databasePath, "IndexedDB.sqlite3");

        if (!fileExists(databaseFile))
            continue;

        time_t modTime;
        getFileModificationTime(databaseFile, modTime);

        if (modTime < startDate || modTime > endDate)
            continue;

        deleteFile(databaseFile);
        deleteEmptyDirectory(databasePath);
    }

    deleteEmptyDirectory(originPath);
}
예제 #6
0
String SQLiteFileSystem::getFileNameForNewDatabase(const String& dbDir, const String&,
                                                   const String&, SQLiteDatabase* db)
{
    // try to get the next sequence number from the given database
    // if we can't get a number, return an empty string
    SQLiteStatement sequenceStatement(*db, "SELECT seq FROM sqlite_sequence WHERE name='Databases';");
    if (sequenceStatement.prepare() != SQLResultOk)
        return String();
    int result = sequenceStatement.step();
    int64_t seq = 0;
    if (result == SQLResultRow)
        seq = sequenceStatement.getColumnInt64(0);
    else if (result != SQLResultDone)
        return String();
    sequenceStatement.finalize();

    // increment the number until we can use it to form a file name that doesn't exist
    String fileName;
    do {
        ++seq;
        fileName = pathByAppendingComponent(dbDir, String::format("%016"PRIx64".db", seq));
    } while (fileExists(fileName));

    return String::format("%016"PRIx64".db", seq);
}
String WebResourceLoadStatisticsStore::persistentStoragePath(const String& label) const
{
    if (m_storagePath.isEmpty())
        return emptyString();
    
    // TODO Decide what to call this file
    return pathByAppendingComponent(m_storagePath, label + "_resourceLog.plist");
}
// Called on a background thread.
String StorageSyncManager::fullDatabaseFilename(const String& databaseIdentifier)
{
    if (!makeAllDirectories(m_path)) {
        LOG_ERROR("Unabled to create LocalStorage database path %s", m_path.utf8().data());
        return String();
    }

    return pathByAppendingComponent(m_path, databaseIdentifier + ".localstorage");
}
String LocalStorageDatabaseTracker::databasePath(const String& filename) const
{
    if (!makeAllDirectories(m_localStorageDirectory)) {
        LOG_ERROR("Unable to create LocalStorage database path %s", m_localStorageDirectory.utf8().data());
        return String();
    }

    return pathByAppendingComponent(m_localStorageDirectory, filename);
}
예제 #10
0
CookieManager::CookieManager()
    : m_count(0)
{
    m_cookieJarFileName = pathByAppendingComponent(OWB_DATA, "cookieCollection.db");

    // We force the cookie backing store to be open with the cookie jar to avoid
    // calling cookieManager() again and recursively calling this constructor.
    cookieBackingStore().open(cookieJar());
    getBackingStoreCookies();
}
예제 #11
0
CookieManager::CookieManager()
    : m_count(0)
    , m_privateMode(false)
    , m_shouldDumpAllCookies(false)
    , m_cookieJarFileName(pathByAppendingComponent(BlackBerry::Platform::Client::get()->getApplicationDataDirectory().c_str(), "/cookieCollection.db"))
    , m_policy(CookieStorageAcceptPolicyAlways)
    , m_cookieBackingStore(CookieDatabaseBackingStore::create())
    , m_limitTimer(this, &CookieManager::cookieLimitCleanUp)
{
}
예제 #12
0
static String findWebKitProcess(const char* processName)
{
    static const char* execDirectory = g_getenv("WEBKIT_EXEC_PATH");
    if (execDirectory) {
        String processPath = pathByAppendingComponent(filenameToString(execDirectory), processName);
        if (fileExists(processPath))
            return processPath;
    }

    static String executablePath = getExecutablePath();
    if (!executablePath.isNull()) {
        String processPath = pathByAppendingComponent(executablePath, processName);
        if (fileExists(processPath))
            return processPath;
    }

    // FIXME: Define and use LIBEXECDIR.
    return String(processName);
}
예제 #13
0
void DatabaseProcess::deleteIndexedDatabaseEntriesForOrigin(const SecurityOriginData& originData)
{
    if (m_indexedDatabaseDirectory.isEmpty())
        return;

    RefPtr<SecurityOrigin> origin = originData.securityOrigin();
    String databaseIdentifier = origin->databaseIdentifier();
    String originPath = pathByAppendingComponent(m_indexedDatabaseDirectory, databaseIdentifier);

    removeAllDatabasesForOriginPath(originPath, std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max());
}
예제 #14
0
파일: IDBServer.cpp 프로젝트: josecu/webkit
void IDBServer::performCloseAndDeleteDatabasesForOrigins(const Vector<SecurityOriginData>& origins, uint64_t callbackID)
{
    if (!m_databaseDirectoryPath.isEmpty()) {
        for (const auto& origin : origins) {
            String originPath = pathByAppendingComponent(m_databaseDirectoryPath, origin.securityOrigin()->databaseIdentifier());
            removeAllDatabasesForOriginPath(originPath, std::chrono::system_clock::time_point::min());
        }
    }

    postDatabaseTaskReply(createCrossThreadTask(*this, &IDBServer::didPerformCloseAndDeleteDatabases, callbackID));
}
static String findWebKitProcess(const char* processName)
{
#if ENABLE(DEVELOPER_MODE)
static const char* execDirectory = g_getenv("WEBKIT_EXEC_PATH");
if (execDirectory) {
    String processPath = pathByAppendingComponent(filenameToString(execDirectory), processName);
    if (fileExists(processPath))
        return processPath;
}

static String executablePath = getExecutablePath();
if (!executablePath.isNull()) {
    String processPath = pathByAppendingComponent(executablePath, processName);
    if (fileExists(processPath))
        return processPath;
}
#endif

return pathByAppendingComponent(filenameToString(PKGLIBEXECDIR), processName);
}
예제 #16
0
void DatabaseProcess::deleteIndexedDatabaseEntriesForOrigins(const Vector<RefPtr<WebCore::SecurityOrigin>>& securityOrigins)
{
    if (m_indexedDatabaseDirectory.isEmpty())
        return;

    for (const auto& securityOrigin : securityOrigins) {
        String originPath = pathByAppendingComponent(m_indexedDatabaseDirectory, securityOrigin->databaseIdentifier());

        removeAllDatabasesForOriginPath(originPath, std::chrono::system_clock::time_point::min());
    }
}
예제 #17
0
void SQLiteIDBTransaction::moveBlobFilesIfNecessary()
{
    String databaseDirectory = m_backingStore.fullDatabaseDirectory();
    for (auto& entry : m_blobTemporaryAndStoredFilenames) {
        m_backingStore.temporaryFileHandler().prepareForAccessToTemporaryFile(entry.first);

        if (!hardLinkOrCopyFile(entry.first, pathByAppendingComponent(databaseDirectory, entry.second)))
            LOG_ERROR("Failed to link/copy temporary blob file '%s' to location '%s'", entry.first.utf8().data(), pathByAppendingComponent(databaseDirectory, entry.second).utf8().data());

        m_backingStore.temporaryFileHandler().accessToTemporaryFileComplete(entry.first);
    }

    m_blobTemporaryAndStoredFilenames.clear();
}
예제 #18
0
void SQLiteIDBTransaction::deleteBlobFilesIfNecessary()
{
    if (m_blobRemovedFilenames.isEmpty())
        return;

    String databaseDirectory = m_backingStore.fullDatabaseDirectory();
    for (auto& entry : m_blobRemovedFilenames) {
        String fullPath = pathByAppendingComponent(databaseDirectory, entry);
        m_backingStore.temporaryFileHandler().prepareForAccessToTemporaryFile(fullPath);
        m_backingStore.temporaryFileHandler().accessToTemporaryFileComplete(fullPath);
    }

    m_blobRemovedFilenames.clear();
}
예제 #19
0
UniqueIDBDatabase::UniqueIDBDatabase(const UniqueIDBDatabaseIdentifier& identifier)
    : m_identifier(identifier)
    , m_acceptingNewRequests(true)
    , m_didGetMetadataFromBackingStore(false)
{
    m_inMemory = !canShareDatabases(identifier.openingOrigin(), identifier.mainFrameOrigin());
    if (m_inMemory)
        return;

    // Each unique Indexed Database exists in a directory named for the database, which exists in a directory representing its opening origin.
    m_databaseRelativeDirectory = pathByAppendingComponent(databaseFilenameIdentifier(identifier.openingOrigin()), filenameForDatabaseName());

    DatabaseProcess::shared().ensureIndexedDatabaseRelativePathExists(m_databaseRelativeDirectory);
}
static String storageDirectory(DWORD pathIdentifier)
{
    Vector<UChar> buffer(MAX_PATH);
    if (FAILED(SHGetFolderPathW(0, pathIdentifier | CSIDL_FLAG_CREATE, 0, 0, buffer.data())))
        return String();
    buffer.resize(wcslen(buffer.data()));
    String directory = String::adopt(buffer);

    static const String companyNameDirectory = "Apple Computer\\";
    directory = pathByAppendingComponent(directory, companyNameDirectory + bundleName());
    if (!makeAllDirectories(directory))
        return String();

    return directory;
}
예제 #21
0
void ApplicationCacheStorage::openDatabase(bool createIfDoesNotExist)
{
    if (m_database.isOpen())
        return;

    // The cache directory should never be null, but if it for some weird reason is we bail out.
    if (m_cacheDirectory.isNull())
        return;
    
    String applicationCachePath = pathByAppendingComponent(m_cacheDirectory, "ApplicationCache.db");
    if (!createIfDoesNotExist && !fileExists(applicationCachePath))
        return;

    makeAllDirectories(m_cacheDirectory);
    m_database.open(applicationCachePath);
    
    if (!m_database.isOpen())
        return;
    
    verifySchemaVersion();
    
    // Create tables
    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheGroups (id INTEGER PRIMARY KEY AUTOINCREMENT, "
                      "manifestHostHash INTEGER NOT NULL ON CONFLICT FAIL, manifestURL TEXT UNIQUE ON CONFLICT FAIL, newestCache INTEGER)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS Caches (id INTEGER PRIMARY KEY AUTOINCREMENT, cacheGroup INTEGER)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheWhitelistURLs (url TEXT NOT NULL ON CONFLICT FAIL, cache INTEGER NOT NULL ON CONFLICT FAIL)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS FallbackURLs (namespace TEXT NOT NULL ON CONFLICT FAIL, fallbackURL TEXT NOT NULL ON CONFLICT FAIL, "
                      "cache INTEGER NOT NULL ON CONFLICT FAIL)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheEntries (cache INTEGER NOT NULL ON CONFLICT FAIL, type INTEGER, resource INTEGER NOT NULL)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheResources (id INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT NOT NULL ON CONFLICT FAIL, "
                      "statusCode INTEGER NOT NULL, responseURL TEXT NOT NULL, mimeType TEXT, textEncodingName TEXT, headers TEXT, data INTEGER NOT NULL ON CONFLICT FAIL)");
    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheResourceData (id INTEGER PRIMARY KEY AUTOINCREMENT, data BLOB)");

    // When a cache is deleted, all its entries and its whitelist should be deleted.
    executeSQLCommand("CREATE TRIGGER IF NOT EXISTS CacheDeleted AFTER DELETE ON Caches"
                      " FOR EACH ROW BEGIN"
                      "  DELETE FROM CacheEntries WHERE cache = OLD.id;"
                      "  DELETE FROM CacheWhitelistURLs WHERE cache = OLD.id;"
                      "  DELETE FROM FallbackURLs WHERE cache = OLD.id;"
                      " END");
    
    // When a cache resource is deleted, its data blob should also be deleted.
    executeSQLCommand("CREATE TRIGGER IF NOT EXISTS CacheResourceDeleted AFTER DELETE ON CacheResources"
                      " FOR EACH ROW BEGIN"
                      "  DELETE FROM CacheResourceData WHERE id = OLD.data;"
                      " END");
}
예제 #22
0
CString openTemporaryFile(const char*, PlatformFileHandle& handle)
{
    handle = INVALID_HANDLE_VALUE;

    wchar_t tempPath[MAX_PATH];
    int tempPathLength = ::GetTempPath(_countof(tempPath), tempPath);
    if (tempPathLength <= 0 || tempPathLength > _countof(tempPath))
        return CString();

    HCRYPTPROV hCryptProv = 0;
    if (!CryptAcquireContext(&hCryptProv, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
        return CString();

    String proposedPath;
    while (1) {

        wchar_t tempFile[] = L"XXXXXXXX.tmp"; // Use 8.3 style name (more characters aren't helpful due to 8.3 short file names)
        const int randomPartLength = 8;
        if (!CryptGenRandom(hCryptProv, randomPartLength * 2, reinterpret_cast<BYTE*>(tempFile)))
            break;

        // Limit to valid filesystem characters, also excluding others that could be problematic, like punctuation.
        // don't include both upper and lowercase since Windows file systems are typically not case sensitive.
        const char validChars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
        for (int i = 0; i < randomPartLength; ++i)
            tempFile[i] = validChars[tempFile[i] % (sizeof(validChars) - 1)];

        ASSERT(wcslen(tempFile) * 2 == sizeof(tempFile) - 2);

        proposedPath = pathByAppendingComponent(String(tempPath), String(tempFile));

        // use CREATE_NEW to avoid overwriting an existing file with the same name
        handle = CreateFile(proposedPath.charactersWithNullTermination(), GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
        if (!isHandleValid(handle) && GetLastError() == ERROR_ALREADY_EXISTS)
            continue;

        break;
    }

    CryptReleaseContext(hCryptProv, 0);

    if (!isHandleValid(handle))
        return CString();

    return proposedPath.latin1();
}
예제 #23
0
void WebContext::ensureDatabaseProcess()
{
    if (m_databaseProcess)
        return;

    m_databaseProcess = DatabaseProcessProxy::create(this);

    DatabaseProcessCreationParameters parameters;

    // Indexed databases exist in a subdirectory of the "database directory path."
    // Currently, the top level of that directory contains entities related to WebSQL databases.
    // We should fix this, and move WebSQL into a subdirectory (https://bugs.webkit.org/show_bug.cgi?id=124807)
    // In the meantime, an entity name prefixed with three underscores will not conflict with any WebSQL entities.
    parameters.indexedDatabaseDirectory = pathByAppendingComponent(databaseDirectory(), "___IndexedDB");
    SandboxExtension::createHandleForReadWriteDirectory(parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);

    m_databaseProcess->send(Messages::DatabaseProcess::InitializeDatabaseProcess(parameters), 0);
}
예제 #24
0
void PluginDatabase::updatePersistentMetadataCache()
{
    if (!isPersistentMetadataCacheEnabled() || persistentMetadataCachePath().isEmpty())
        return;

    makeAllDirectories(persistentMetadataCachePath());
    String absoluteCachePath = pathByAppendingComponent(persistentMetadataCachePath(), persistentPluginMetadataCacheFilename);
    deleteFile(absoluteCachePath);

    if (m_plugins.isEmpty())
        return;

    PlatformFileHandle file;
    file = openFile(absoluteCachePath, OpenForWrite);

    if (!isHandleValid(file)) {
        LOG_ERROR("Unable to open plugin metadata cache for saving");
        return;
    }

    char localSchemaVersion = schemaVersion;
    if (writeToFile(file, &localSchemaVersion, 1) != 1) {
        LOG_ERROR("Unable to write plugin metadata cache schema");
        closeFile(file);
        deleteFile(absoluteCachePath);
        return;
    }

    PluginSet::const_iterator end = m_plugins.end();
    for (PluginSet::const_iterator it = m_plugins.begin(); it != end; ++it) {
        if (!(writeUTF8String(file, (*it)->path())
              && writeTime(file, (*it)->lastModified())
              && writeUTF8String(file, (*it)->name())
              && writeUTF8String(file, (*it)->description())
              && writeUTF8String(file, (*it)->fullMIMEDescription()))) {
            LOG_ERROR("Unable to write plugin metadata to cache");
            closeFile(file);
            deleteFile(absoluteCachePath);
            return;
        }
    }

    closeFile(file);
}
static String storageDirectory(DWORD pathIdentifier)
{
#if OS(WINCE)
    return String();
#else
    Vector<UChar> buffer(MAX_PATH);
    if (FAILED(SHGetFolderPathW(0, pathIdentifier | CSIDL_FLAG_CREATE, 0, 0, buffer.data())))
        return String();
    buffer.resize(wcslen(buffer.data()));
    String directory = String::adopt(buffer);

    DEFINE_STATIC_LOCAL(String, companyNameDirectory, (ASCIILiteral("Apple Computer\\")));
    directory = pathByAppendingComponent(directory, companyNameDirectory + bundleName());
    if (!makeAllDirectories(directory))
        return String();

    return directory;
#endif
}
예제 #26
0
String LocalStorage::fullDatabaseFilename(SecurityOrigin* origin)
{
    // FIXME: Once we actually track origin/quota entries to see which origins have local storage established,
    // we will return an empty path name if the origin isn't allowed to have LocalStorage.
    // We'll need to wait here until the AreaImport task to complete before making that decision.

    if (m_path.isEmpty())
        return String();

    ASSERT(origin);
    if (!origin)
        return String();

    if (!makeAllDirectories(m_path)) {
        LOG_ERROR("Unabled to create LocalStorage database path %s", m_path.utf8().data());
        return String();
    }

    return pathByAppendingComponent(m_path, origin->databaseIdentifier() + ".localstorage");
}
std::unique_ptr<IDBDatabaseMetadata> UniqueIDBDatabaseBackingStoreSQLite::getOrEstablishMetadata()
{
    ASSERT(!isMainThread());

    String dbFilename = pathByAppendingComponent(m_absoluteDatabaseDirectory, "IndexedDB.sqlite3");
    m_sqliteDB = openSQLiteDatabaseAtPath(dbFilename);
    if (!m_sqliteDB)
        return nullptr;

    std::unique_ptr<IDBDatabaseMetadata> metadata = extractExistingMetadata();
    if (!metadata)
        metadata = createAndPopulateInitialMetadata();

    if (!metadata)
        LOG_ERROR("Unable to establish IDB database at path '%s'", dbFilename.utf8().data());

    // The database id is a runtime concept and doesn't need to be stored in the metadata database.
    metadata->id = generateDatabaseId();

    return metadata;
}
예제 #28
0
static PassOwnPtr<SQLiteDatabase> openSQLiteDatabase(SecurityOrigin* securityOrigin, String name, const String& pathBase, int64_t maximumSize)
{
    String path = ":memory:";
    if (!pathBase.isEmpty()) {
        if (!makeAllDirectories(pathBase)) {
            // FIXME: Is there any other thing we could possibly do to recover at this point? If so, do it rather than just erroring out.
            LOG_ERROR("Unabled to create LocalStorage database path %s", pathBase.utf8().data());
            return 0;
        }

        path = pathByAppendingComponent(pathBase, IDBFactoryBackendImpl::databaseFileName(name, securityOrigin));
    }

    OwnPtr<SQLiteDatabase> sqliteDatabase = adoptPtr(new SQLiteDatabase());
    if (!sqliteDatabase->open(path)) {
        // FIXME: Is there any other thing we could possibly do to recover at this point? If so, do it rather than just erroring out.
        LOG_ERROR("Failed to open database file %s for IndexedDB", path.utf8().data());
        return 0;
    }

    sqliteDatabase->setMaximumSize(maximumSize);
    return sqliteDatabase.release();
}
String openTemporaryFile(const String&, PlatformFileHandle& handle)
{
    handle = INVALID_HANDLE_VALUE;

    wchar_t tempPath[MAX_PATH];
    int tempPathLength = ::GetTempPathW(WTF_ARRAY_LENGTH(tempPath), tempPath);
    if (tempPathLength <= 0 || tempPathLength > WTF_ARRAY_LENGTH(tempPath))
        return String();

    String proposedPath;
    do {
        wchar_t tempFile[] = L"XXXXXXXX.tmp"; // Use 8.3 style name (more characters aren't helpful due to 8.3 short file names)
        const int randomPartLength = 8;
        cryptographicallyRandomValues(tempFile, randomPartLength * sizeof(wchar_t));

        // Limit to valid filesystem characters, also excluding others that could be problematic, like punctuation.
        // don't include both upper and lowercase since Windows file systems are typically not case sensitive.
        const char validChars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
        for (int i = 0; i < randomPartLength; ++i)
            tempFile[i] = validChars[tempFile[i] % (sizeof(validChars) - 1)];

        ASSERT(wcslen(tempFile) == WTF_ARRAY_LENGTH(tempFile) - 1);

        proposedPath = pathByAppendingComponent(tempPath, tempFile);
        if (proposedPath.isEmpty())
            break;

        // use CREATE_NEW to avoid overwriting an existing file with the same name
        handle = ::CreateFileW(proposedPath.charactersWithNullTermination().data(), GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
    } while (!isHandleValid(handle) && GetLastError() == ERROR_ALREADY_EXISTS);

    if (!isHandleValid(handle))
        return String();

    return proposedPath;
}
예제 #30
0
String DatabaseProcess::absoluteIndexedDatabasePathFromDatabaseRelativePath(const String& relativePath)
{
    // FIXME: pathByAppendingComponent() was originally designed to append individual atomic components.
    // We don't have a function designed to append a multi-component subpath, but we should.
    return pathByAppendingComponent(m_indexedDatabaseDirectory, relativePath);
}