/*
 * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
 * Copyright (C) 2008 Collabora, Ltd.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "PluginDatabase.h"

#include "PluginPackage.h"
#include <WebCore/Frame.h>
#include <WebCore/URL.h>
#include <stdlib.h>
#include <wtf/text/CString.h>

#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE)
#include "FileSystem.h"
#endif

namespace WebCore {

typedef HashMap<String, RefPtr<PluginPackage> > PluginPackageByNameMap;

#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE)

static const size_t maximumPersistentPluginMetadataCacheSize = 32768;

static bool gPersistentPluginMetadataCacheIsEnabled;

String& persistentPluginMetadataCachePath()
{
    static NeverDestroyed<String> cachePath;
    return cachePath;
}

#endif

PluginDatabase::PluginDatabase()
#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE)
    : m_persistentMetadataCacheIsLoaded(false)
#endif
{
}

PluginDatabase* PluginDatabase::installedPlugins(bool populate)
{
    static PluginDatabase* plugins = 0;

    if (!plugins) {
        plugins = new PluginDatabase;

        if (populate) {
            plugins->setPluginDirectories(PluginDatabase::defaultPluginDirectories());
            plugins->refresh();
        }
    }

    return plugins;
}

bool PluginDatabase::isMIMETypeRegistered(const String& mimeType)
{
    if (mimeType.isNull())
        return false;
    if (m_registeredMIMETypes.contains(mimeType))
        return true;
    // No plugin was found, try refreshing the database and searching again
    return (refresh() && m_registeredMIMETypes.contains(mimeType));
}

void PluginDatabase::addExtraPluginDirectory(const String& directory)
{
    m_pluginDirectories.append(directory);
    refresh();
}

bool PluginDatabase::refresh()
{
#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE)
    if (!m_persistentMetadataCacheIsLoaded)
        loadPersistentMetadataCache();
#endif
    bool pluginSetChanged = false;

    if (!m_plugins.isEmpty()) {
        PluginSet pluginsToUnload;
        getDeletedPlugins(pluginsToUnload);

        // Unload plugins
        auto end = pluginsToUnload.end();
        for (auto it = pluginsToUnload.begin(); it != end; ++it)
            remove(it->get());

        pluginSetChanged = !pluginsToUnload.isEmpty();
    }

    HashSet<String> paths;
    getPluginPathsInDirectories(paths);

    HashMap<String, time_t> pathsWithTimes;

    // We should only skip unchanged files if we didn't remove any plugins above. If we did remove
    // any plugins, we need to look at every plugin file so that, e.g., if the user has two versions
    // of RealPlayer installed and just removed the newer one, we'll pick up the older one.
    bool shouldSkipUnchangedFiles = !pluginSetChanged;

    auto pathsEnd = paths.end();
    for (auto it = paths.begin(); it != pathsEnd; ++it) {
        time_t lastModified;
        if (!FileSystem::getFileModificationTime(*it, lastModified))
            continue;

        pathsWithTimes.add(*it, lastModified);

        // If the path's timestamp hasn't changed since the last time we ran refresh(), we don't have to do anything.
        if (shouldSkipUnchangedFiles && m_pluginPathsWithTimes.get(*it) == lastModified)
            continue;

        if (RefPtr<PluginPackage> oldPackage = m_pluginsByPath.get(*it)) {
            ASSERT(!shouldSkipUnchangedFiles || oldPackage->lastModified() != lastModified);
            remove(oldPackage.get());
        }

        RefPtr<PluginPackage> package = PluginPackage::createPackage(*it, lastModified);
        if (package && add(package.releaseNonNull()))
            pluginSetChanged = true;
    }

    // Cache all the paths we found with their timestamps for next time.
    pathsWithTimes.swap(m_pluginPathsWithTimes);

    if (!pluginSetChanged)
        return false;

#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE)
    updatePersistentMetadataCache();
#endif

    m_registeredMIMETypes.clear();

    // Register plug-in MIME types
    auto end = m_plugins.end();
    for (auto it = m_plugins.begin(); it != end; ++it) {
        // Get MIME types
        auto map_it = (*it)->mimeToDescriptions().begin();
        auto map_end = (*it)->mimeToDescriptions().end();
        for (; map_it != map_end; ++map_it)
            m_registeredMIMETypes.add(map_it->key);
    }

    return true;
}

Vector<PluginPackage*> PluginDatabase::plugins() const
{
    Vector<PluginPackage*> result;

    auto end = m_plugins.end();
    for (auto it = m_plugins.begin(); it != end; ++it)
        result.append((*it).get());

    return result;
}

int PluginDatabase::preferredPluginCompare(const void* a, const void* b)
{
    PluginPackage* pluginA = *static_cast<PluginPackage* const*>(a);
    PluginPackage* pluginB = *static_cast<PluginPackage* const*>(b);

    return pluginA->compare(*pluginB);
}

PluginPackage* PluginDatabase::pluginForMIMEType(const String& mimeType)
{
    if (mimeType.isEmpty())
        return nullptr;

    PluginPackage* preferredPlugin = m_preferredPlugins.get(mimeType);
    if (preferredPlugin
        && preferredPlugin->isEnabled()
        && preferredPlugin->mimeToDescriptions().contains(mimeType)) {
        return preferredPlugin;
    }

    Vector<PluginPackage*, 2> pluginChoices;

    auto end = m_plugins.end();
    for (auto it = m_plugins.begin(); it != end; ++it) {
        PluginPackage* plugin = (*it).get();

        if (!plugin->isEnabled())
            continue;

        if (plugin->mimeToDescriptions().contains(mimeType)) {
#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE)
            if (!plugin->ensurePluginLoaded())
                continue;
#endif
            pluginChoices.append(plugin);
        }
    }

    if (pluginChoices.isEmpty())
        return 0;

    qsort(pluginChoices.data(), pluginChoices.size(), sizeof(PluginPackage*), PluginDatabase::preferredPluginCompare);

    return pluginChoices[0];
}

String PluginDatabase::MIMETypeForExtension(const String& extension) const
{
    if (extension.isEmpty())
        return String();

    auto end = m_plugins.end();
    String mimeType;
    Vector<PluginPackage*, 2> pluginChoices;
    HashMap<PluginPackage*, String> mimeTypeForPlugin;

    for (auto it = m_plugins.begin(); it != end; ++it) {
        if (!(*it)->isEnabled())
            continue;

        auto mime_end = (*it)->mimeToExtensions().end();

        for (auto mime_it = (*it)->mimeToExtensions().begin(); mime_it != mime_end; ++mime_it) {
            mimeType = mime_it->key;
            PluginPackage* preferredPlugin = m_preferredPlugins.get(mimeType);
            const Vector<String>& extensions = mime_it->value;
            bool foundMapping = false;
            for (unsigned i = 0; i < extensions.size(); i++) {
                if (equalIgnoringASCIICase(extensions[i], extension)) {
                    PluginPackage* plugin = (*it).get();

                    if (preferredPlugin && PluginPackage::equal(*plugin, *preferredPlugin))
                        return mimeType;

#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE)
                    if (!plugin->ensurePluginLoaded())
                        continue;
#endif
                    pluginChoices.append(plugin);
                    mimeTypeForPlugin.add(plugin, mimeType);
                    foundMapping = true;
                    break;
                }
            }
            if (foundMapping)
                break;
        }
    }

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

    qsort(pluginChoices.data(), pluginChoices.size(), sizeof(PluginPackage*), PluginDatabase::preferredPluginCompare);

    return mimeTypeForPlugin.get(pluginChoices[0]);
}

PluginPackage* PluginDatabase::findPlugin(const URL& url, String& mimeType)
{
    if (!mimeType.isEmpty())
        return pluginForMIMEType(mimeType);
    
    String filename = url.lastPathComponent();
    if (filename.endsWith('/'))
        return 0;
    
    int extensionPos = filename.reverseFind('.');
    if (extensionPos == -1)
        return 0;
    
    String mimeTypeForExtension = MIMETypeForExtension(filename.substring(extensionPos + 1));
    PluginPackage* plugin = pluginForMIMEType(mimeTypeForExtension);
    if (!plugin) {
        // FIXME: if no plugin could be found, query Windows for the mime type
        // corresponding to the extension.
        return 0;
    }
    
    mimeType = mimeTypeForExtension;
    return plugin;
}

void PluginDatabase::setPreferredPluginForMIMEType(const String& mimeType, PluginPackage* plugin)
{
    if (!plugin || plugin->mimeToExtensions().contains(mimeType))
        m_preferredPlugins.set(mimeType, plugin);
}

bool PluginDatabase::fileExistsAndIsNotDisabled(const String& filePath) const
{
    // Skip plugin files that are disabled by filename.
    if (m_disabledPluginFiles.contains(FileSystem::pathGetFileName(filePath)))
        return false;

    return FileSystem::fileExists(filePath);
}

void PluginDatabase::getDeletedPlugins(PluginSet& plugins) const
{
    auto end = m_plugins.end();
    for (auto it = m_plugins.begin(); it != end; ++it) {
        if (!fileExistsAndIsNotDisabled((*it)->path()))
            plugins.add(*it);
    }
}

bool PluginDatabase::add(Ref<PluginPackage>&& package)
{
    if (!m_plugins.add(package.copyRef()).isNewEntry)
        return false;

    m_pluginsByPath.add(package->path(), package.copyRef());
    return true;
}

void PluginDatabase::remove(PluginPackage* package)
{
    auto it = package->mimeToExtensions().begin();
    auto end = package->mimeToExtensions().end();
    for ( ; it != end; ++it) {
        auto packageInMap = m_preferredPlugins.find(it->key);
        if (packageInMap != m_preferredPlugins.end() && packageInMap->value == package)
            m_preferredPlugins.remove(packageInMap);
    }

    m_plugins.remove(package);
    m_pluginsByPath.remove(package->path());
}

void PluginDatabase::clear()
{
    m_plugins.clear();
    m_pluginsByPath.clear();
    m_pluginPathsWithTimes.clear();
    m_registeredMIMETypes.clear();
    m_preferredPlugins.clear();
#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE)
    m_persistentMetadataCacheIsLoaded = false;
#endif
}

bool PluginDatabase::removeDisabledPluginFile(const String& fileName)
{
    return m_disabledPluginFiles.remove(fileName);
}

bool PluginDatabase::addDisabledPluginFile(const String& fileName)
{
    return m_disabledPluginFiles.add(fileName).isNewEntry;
}

#if !ENABLE(NETSCAPE_PLUGIN_API)
// For Safari/Win the following three methods are implemented
// in PluginDatabaseWin.cpp, but if we can use WebCore constructs
// for the logic we should perhaps move it here under XP_WIN?

Vector<String> PluginDatabase::defaultPluginDirectories()
{
    Vector<String> paths;

    String userPluginPath = FileSystem::homeDirectoryPath();
    userPluginPath.append(String("\\Application Data\\Mozilla\\plugins"));
    paths.append(userPluginPath);

    return paths;
}

bool PluginDatabase::isPreferredPluginDirectory(const String& path)
{
    String preferredPath = FileSystem::homeDirectoryPath();

    preferredPath.append(String("\\Application Data\\Mozilla\\plugins"));

    // TODO: We should normalize the path before doing a comparison.
    return path == preferredPath;
}

void PluginDatabase::getPluginPathsInDirectories(HashSet<String>& paths) const
{
    // FIXME: This should be a case insensitive set.
    HashSet<String> uniqueFilenames;

    String fileNameFilter("");

    auto dirsEnd = m_pluginDirectories.end();
    for (auto dIt = m_pluginDirectories.begin(); dIt != dirsEnd; ++dIt) {
        Vector<String> pluginPaths = FileSystem::listDirectory(*dIt, fileNameFilter);
        auto pluginsEnd = pluginPaths.end();
        for (auto pIt = pluginPaths.begin(); pIt != pluginsEnd; ++pIt) {
            if (!fileExistsAndIsNotDisabled(*pIt))
                continue;

            paths.add(*pIt);
        }
    }
}

#endif // !ENABLE(NETSCAPE_PLUGIN_API)

#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE)

static void fillBufferWithContentsOfFile(FileSystem::PlatformFileHandle file, Vector<char>& buffer)
{
    size_t bufferSize = 0;
    size_t bufferCapacity = 1024;
    buffer.resize(bufferCapacity);

    do {
        bufferSize += FileSystem::readFromFile(file, buffer.data() + bufferSize, bufferCapacity - bufferSize);
        if (bufferSize == bufferCapacity) {
            if (bufferCapacity < maximumPersistentPluginMetadataCacheSize) {
                bufferCapacity *= 2;
                buffer.resize(bufferCapacity);
            } else {
                buffer.clear();
                return;
            }
        } else
            break;
    } while (true);

    buffer.shrink(bufferSize);
}

static bool readUTF8String(String& resultString, char*& start, const char* end)
{
    if (start >= end)
        return false;

    int len = strlen(start);
    resultString = String::fromUTF8(start, len);
    start += len + 1;

    return true;
}

static bool readTime(time_t& resultTime, char*& start, const char* end)
{
    if (start + sizeof(time_t) >= end)
        return false;

    // The stream is not necessary aligned.
    memcpy(&resultTime, start, sizeof(time_t));
    start += sizeof(time_t);

    return true;
}

static const char schemaVersion = '1';
static const char persistentPluginMetadataCacheFilename[] = "PluginMetadataCache.bin";

void PluginDatabase::loadPersistentMetadataCache()
{
    if (!isPersistentMetadataCacheEnabled() || persistentMetadataCachePath().isEmpty())
        return;

    FileSystem::PlatformFileHandle file;
    String absoluteCachePath = FileSystem::pathByAppendingComponent(persistentMetadataCachePath(), persistentPluginMetadataCacheFilename);
    file = FileSystem::openFile(absoluteCachePath, FileSystem::FileOpenMode::Read);

    if (!FileSystem::isHandleValid(file))
        return;

    // Mark cache as loaded regardless of success or failure. If
    // there's error in the cache, we won't try to load it anymore.
    m_persistentMetadataCacheIsLoaded = true;

    Vector<char> fileContents;
    fillBufferWithContentsOfFile(file, fileContents);
    FileSystem::closeFile(file);

    if (fileContents.size() < 2 || fileContents.first() != schemaVersion || fileContents.last() != '\0') {
        LOG_ERROR("Unable to read plugin metadata cache: corrupt schema");
        FileSystem::deleteFile(absoluteCachePath);
        return;
    }

    char* bufferPos = fileContents.data() + 1;
    char* end = fileContents.data() + fileContents.size();

    PluginSet cachedPlugins;
    HashMap<String, time_t> cachedPluginPathsWithTimes;
    HashMap<String, RefPtr<PluginPackage> > cachedPluginsByPath;

    while (bufferPos < end) {
        String path;
        time_t lastModified;
        String name;
        String desc;
        String mimeDesc;
        if (!(readUTF8String(path, bufferPos, end)
              && readTime(lastModified, bufferPos, end)
              && readUTF8String(name, bufferPos, end)
              && readUTF8String(desc, bufferPos, end)
              && readUTF8String(mimeDesc, bufferPos, end))) {
            LOG_ERROR("Unable to read plugin metadata cache: corrupt data");
            FileSystem::deleteFile(absoluteCachePath);
            return;
        }

        // Skip metadata that points to plugins from directories that
        // are not part of plugin directory list anymore.
        String pluginDirectoryName = FileSystem::directoryName(path);
        if (m_pluginDirectories.find(pluginDirectoryName) == WTF::notFound)
            continue;

        auto package = PluginPackage::createPackageFromCache(path, lastModified, name, desc, mimeDesc);

        if (cachedPlugins.add(package.copyRef()).isNewEntry) {
            cachedPluginPathsWithTimes.add(package->path(), package->lastModified());
            cachedPluginsByPath.add(package->path(), package);
        }
    }

    m_plugins.swap(cachedPlugins);
    m_pluginsByPath.swap(cachedPluginsByPath);
    m_pluginPathsWithTimes.swap(cachedPluginPathsWithTimes);
}

static bool writeUTF8String(FileSystem::PlatformFileHandle file, const String& string)
{
    CString utf8String = string.utf8();
    int length = utf8String.length() + 1;
    return FileSystem::writeToFile(file, utf8String.data(), length) == length;
}

static bool writeTime(FileSystem::PlatformFileHandle file, const time_t& time)
{
    return FileSystem::writeToFile(file, reinterpret_cast<const char*>(&time), sizeof(time_t)) == sizeof(time_t);
}

void PluginDatabase::updatePersistentMetadataCache()
{
    if (!isPersistentMetadataCacheEnabled() || persistentMetadataCachePath().isEmpty())
        return;

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

    if (m_plugins.isEmpty())
        return;

    FileSystem::PlatformFileHandle file;
    file = FileSystem::openFile(absoluteCachePath, FileSystem::FileOpenMode::Write);

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

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

    auto end = m_plugins.end();
    for (auto 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");
            FileSystem::closeFile(file);
            FileSystem::deleteFile(absoluteCachePath);
            return;
        }
    }

    FileSystem::closeFile(file);
}

bool PluginDatabase::isPersistentMetadataCacheEnabled()
{
    return gPersistentPluginMetadataCacheIsEnabled;
}

void PluginDatabase::setPersistentMetadataCacheEnabled(bool isEnabled)
{
    gPersistentPluginMetadataCacheIsEnabled = isEnabled;
}

String PluginDatabase::persistentMetadataCachePath()
{
    return WebCore::persistentPluginMetadataCachePath();
}

void PluginDatabase::setPersistentMetadataCachePath(const String& persistentMetadataCachePath)
{
    WebCore::persistentPluginMetadataCachePath() = persistentMetadataCachePath;
}
#endif
}
