/*
 * Copyright (C) 2010 Apple Inc. 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. AND ITS CONTRIBUTORS ``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 ITS 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 "config.h"
#include "PluginInfoStore.h"

#include "NetscapePluginModule.h"
#include <WebCore/FileSystem.h>
#include <WebCore/PathWalker.h>
#include <shlwapi.h>

using namespace WebCore;

namespace WebKit {

static inline Vector<int> parseVersionString(const String& versionString)
{
    Vector<int> version;

    unsigned startPos = 0;
    unsigned endPos;
    
    while (startPos < versionString.length()) {
        for (endPos = startPos; endPos < versionString.length(); ++endPos)
            if (versionString[endPos] == '.' || versionString[endPos] == '_')
                break;

        int versionComponent = versionString.substring(startPos, endPos - startPos).toInt();
        version.append(versionComponent);

        startPos = endPos + 1;
    }

    return version;
}

// This returns whether versionA is higher than versionB
static inline bool compareVersions(const Vector<int>& versionA, const Vector<int>& versionB)
{
    for (unsigned i = 0; i < versionA.size(); i++) {
        if (i >= versionB.size())
            return true;

        if (versionA[i] > versionB[i])
            return true;
        else if (versionA[i] < versionB[i])
            return false;
    }

    // If we come here, the versions are either the same or versionB has an extra component, just return false
    return false;
}

static inline String safariPluginsDirectory()
{
    static String pluginsDirectory;
    static bool cachedPluginDirectory = false;

    if (!cachedPluginDirectory) {
        cachedPluginDirectory = true;

        WCHAR moduleFileNameStr[MAX_PATH];
        int moduleFileNameLen = ::GetModuleFileNameW(0, moduleFileNameStr, WTF_ARRAY_LENGTH(moduleFileNameStr));

        if (!moduleFileNameLen || moduleFileNameLen == WTF_ARRAY_LENGTH(moduleFileNameStr))
            return pluginsDirectory;

        if (!::PathRemoveFileSpecW(moduleFileNameStr))
            return pluginsDirectory;

        pluginsDirectory = String(moduleFileNameStr) + "\\Plugins";
    }

    return pluginsDirectory;
}

static inline void addMozillaPluginDirectories(Vector<String>& directories)
{
    // Enumerate all Mozilla plugin directories in the registry
    HKEY key;
    LONG result = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Mozilla", 0, KEY_READ, &key);
    if (result != ERROR_SUCCESS)
        return;

    WCHAR name[128];
    FILETIME lastModified;

    // Enumerate subkeys
    for (int i = 0;; i++) {
        DWORD nameLen = WTF_ARRAY_LENGTH(name);
        result = ::RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);

        if (result != ERROR_SUCCESS)
            break;

        String extensionsPath = String(name, nameLen) + "\\Extensions";
        HKEY extensionsKey;

        // Try opening the key
        result = ::RegOpenKeyExW(key, extensionsPath.charactersWithNullTermination(), 0, KEY_READ, &extensionsKey);

        if (result == ERROR_SUCCESS) {
            // Now get the plugins directory
            WCHAR pluginsDirectoryStr[MAX_PATH];
            DWORD pluginsDirectorySize = sizeof(pluginsDirectoryStr);
            DWORD type;

            result = ::RegQueryValueExW(extensionsKey, L"Plugins", 0, &type, reinterpret_cast<LPBYTE>(&pluginsDirectoryStr), &pluginsDirectorySize);

            if (result == ERROR_SUCCESS && type == REG_SZ)
                directories.append(String(pluginsDirectoryStr, pluginsDirectorySize / sizeof(WCHAR) - 1));

            ::RegCloseKey(extensionsKey);
        }
    }

    ::RegCloseKey(key);
}

static inline void addWindowsMediaPlayerPluginDirectory(Vector<String>& directories)
{
    // The new WMP Firefox plugin is installed in \PFiles\Plugins if it can't find any Firefox installs
    WCHAR pluginDirectoryStr[MAX_PATH + 1];
    DWORD pluginDirectorySize = ::ExpandEnvironmentStringsW(L"%SYSTEMDRIVE%\\PFiles\\Plugins", pluginDirectoryStr, WTF_ARRAY_LENGTH(pluginDirectoryStr));

    if (pluginDirectorySize > 0 && pluginDirectorySize <= WTF_ARRAY_LENGTH(pluginDirectoryStr))
        directories.append(String(pluginDirectoryStr, pluginDirectorySize - 1));

    DWORD type;
    WCHAR installationDirectoryStr[MAX_PATH];
    DWORD installationDirectorySize = sizeof(installationDirectoryStr);

    HRESULT result = ::SHGetValueW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\MediaPlayer", L"Installation Directory", &type, reinterpret_cast<LPBYTE>(&installationDirectoryStr), &installationDirectorySize);

    if (result == ERROR_SUCCESS && type == REG_SZ)
        directories.append(String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1));
}

static inline void addQuickTimePluginDirectory(Vector<String>& directories)
{
    DWORD type;
    WCHAR installationDirectoryStr[MAX_PATH];
    DWORD installationDirectorySize = sizeof(installationDirectoryStr);

    HRESULT result = ::SHGetValueW(HKEY_LOCAL_MACHINE, L"Software\\Apple Computer, Inc.\\QuickTime", L"InstallDir", &type, reinterpret_cast<LPBYTE>(&installationDirectoryStr), &installationDirectorySize);

    if (result == ERROR_SUCCESS && type == REG_SZ) {
        String pluginDir = String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1) + "\\plugins";
        directories.append(pluginDir);
    }
}

static inline void addAdobeAcrobatPluginDirectory(Vector<String>& directories)
{
    HKEY key;
    HRESULT result = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Adobe\\Acrobat Reader", 0, KEY_READ, &key);
    if (result != ERROR_SUCCESS)
        return;

    WCHAR name[128];
    FILETIME lastModified;

    Vector<int> latestAcrobatVersion;
    String latestAcrobatVersionString;

    // Enumerate subkeys
    for (int i = 0;; i++) {
        DWORD nameLen = WTF_ARRAY_LENGTH(name);
        result = ::RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);

        if (result != ERROR_SUCCESS)
            break;

        Vector<int> acrobatVersion = parseVersionString(String(name, nameLen));
        if (compareVersions(acrobatVersion, latestAcrobatVersion)) {
            latestAcrobatVersion = acrobatVersion;
            latestAcrobatVersionString = String(name, nameLen);
        }
    }

    if (!latestAcrobatVersionString.isNull()) {
        DWORD type;
        WCHAR acrobatInstallPathStr[MAX_PATH];
        DWORD acrobatInstallPathSize = sizeof(acrobatInstallPathStr);

        String acrobatPluginKeyPath = "Software\\Adobe\\Acrobat Reader\\" + latestAcrobatVersionString + "\\InstallPath";
        result = ::SHGetValueW(HKEY_LOCAL_MACHINE, acrobatPluginKeyPath.charactersWithNullTermination(), 0, &type, reinterpret_cast<LPBYTE>(acrobatInstallPathStr), &acrobatInstallPathSize);

        if (result == ERROR_SUCCESS) {
            String acrobatPluginDirectory = String(acrobatInstallPathStr, acrobatInstallPathSize / sizeof(WCHAR) - 1) + "\\browser";
            directories.append(acrobatPluginDirectory);
        }
    }

    ::RegCloseKey(key);
}

static inline void addMacromediaPluginDirectories(Vector<String>& directories)
{
#if !OS(WINCE)
    WCHAR systemDirectoryStr[MAX_PATH];

    if (!::GetSystemDirectoryW(systemDirectoryStr, WTF_ARRAY_LENGTH(systemDirectoryStr)))
        return;

    WCHAR macromediaDirectoryStr[MAX_PATH];

    if (!::PathCombineW(macromediaDirectoryStr, systemDirectoryStr, L"macromed\\Flash"))
        return;

    directories.append(macromediaDirectoryStr);

    if (!::PathCombineW(macromediaDirectoryStr, systemDirectoryStr, L"macromed\\Shockwave 10"))
        return;

    directories.append(macromediaDirectoryStr);
#endif
}

Vector<String> PluginInfoStore::pluginsDirectories()
{
    Vector<String> directories;

    String ourDirectory = safariPluginsDirectory();
    if (!ourDirectory.isNull())
        directories.append(ourDirectory);

    addQuickTimePluginDirectory(directories);
    addAdobeAcrobatPluginDirectory(directories);
    addMozillaPluginDirectories(directories);
    addWindowsMediaPlayerPluginDirectory(directories);
    addMacromediaPluginDirectories(directories);

    return directories;
}

Vector<String> PluginInfoStore::pluginPathsInDirectory(const String& directory)
{
    Vector<String> paths;

    PathWalker walker(directory, "*");
    if (!walker.isValid())
        return paths;

    do {
        if (walker.data().dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            continue;

        String filename = walker.data().cFileName;
        if ((!filename.startsWith("np", false) || !filename.endsWith("dll", false)) && (!equalIgnoringCase(filename, "Plugin.dll") || !directory.endsWith("Shockwave 10", false)))
            continue;

        paths.append(directory + "\\" + filename);
    } while (walker.step());

    return paths;
}

static void addPluginPathsFromRegistry(HKEY rootKey, Vector<String>& paths)
{
    HKEY key;
    if (::RegOpenKeyExW(rootKey, L"Software\\MozillaPlugins", 0, KEY_ENUMERATE_SUB_KEYS, &key) != ERROR_SUCCESS)
        return;

    for (size_t i = 0; ; ++i) {
        // MSDN says that key names have a maximum length of 255 characters.
        wchar_t name[256];
        DWORD nameLen = WTF_ARRAY_LENGTH(name);
        if (::RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, 0) != ERROR_SUCCESS)
            break;

        wchar_t path[MAX_PATH];
        DWORD pathSizeInBytes = sizeof(path);
        DWORD type;
        if (::SHGetValueW(key, name, L"Path", &type, path, &pathSizeInBytes) != ERROR_SUCCESS)
            continue;
        if (type != REG_SZ)
            continue;

        paths.append(path);
    }

    ::RegCloseKey(key);
}

Vector<String> PluginInfoStore::individualPluginPaths()
{
    Vector<String> paths;

    addPluginPathsFromRegistry(HKEY_LOCAL_MACHINE, paths);
    addPluginPathsFromRegistry(HKEY_CURRENT_USER, paths);

    return paths;
}

static uint64_t fileVersion(DWORD leastSignificant, DWORD mostSignificant)
{
    ULARGE_INTEGER version;
    version.LowPart = leastSignificant;
    version.HighPart = mostSignificant;
    return version.QuadPart;
}

bool PluginInfoStore::getPluginInfo(const String& pluginPath, Plugin& plugin)
{
    return NetscapePluginModule::getPluginInfo(pluginPath, plugin);
}

static bool isOldWindowsMediaPlayerPlugin(const PluginInfoStore::Plugin& plugin)
{
    return equalIgnoringCase(plugin.info.file, "npdsplay.dll");
}

static bool isNewWindowsMediaPlayerPlugin(const PluginInfoStore::Plugin& plugin)
{
    return equalIgnoringCase(plugin.info.file, "np-mswmp.dll");
}

bool PluginInfoStore::shouldUsePlugin(const Plugin& plugin)
{
    if (plugin.info.name == "Citrix ICA Client") {
        // The Citrix ICA Client plug-in requires a Mozilla-based browser; see <rdar://6418681>.
        return false;
    }

    if (plugin.info.name == "Silverlight Plug-In") {
        // workaround for <rdar://5557379> Crash in Silverlight when opening microsoft.com.
        // the latest 1.0 version of Silverlight does not reproduce this crash, so allow it
        // and any newer versions
        static const uint64_t minimumRequiredVersion = fileVersion(0x51BE0000, 0x00010000);
        return plugin.fileVersion >= minimumRequiredVersion;
    }

    if (equalIgnoringCase(plugin.info.file, "npmozax.dll")) {
        // Bug 15217: Mozilla ActiveX control complains about missing xpcom_core.dll
        return false;
    }

    if (equalIgnoringCase(plugin.info.file, "npwpf.dll")) {
        // Bug 57119: Microsoft Windows Presentation Foundation (WPF) plug-in complains about missing xpcom.dll
        return false;
    }

    if (plugin.info.name == "Yahoo Application State Plugin") {
        // https://bugs.webkit.org/show_bug.cgi?id=26860
        // Bug in Yahoo Application State plug-in earlier than 1.0.0.6 leads to heap corruption.
        static const uint64_t minimumRequiredVersion = fileVersion(0x00000006, 0x00010000);
        return plugin.fileVersion >= minimumRequiredVersion;
    }

    if (isOldWindowsMediaPlayerPlugin(plugin)) {
        // Don't load the old Windows Media Player plugin if we've already loaded the new Windows
        // Media Player plugin.
        for (size_t i = 0; i < m_plugins.size(); ++i) {
            if (!isNewWindowsMediaPlayerPlugin(m_plugins[i]))
                continue;
            return false;
        }
        return true;
    }

    if (isNewWindowsMediaPlayerPlugin(plugin)) {
        // Unload the old Windows Media Player plugin if we've already loaded it.
        for (size_t i = 0; i < m_plugins.size(); ++i) {
            if (!isOldWindowsMediaPlayerPlugin(m_plugins[i]))
                continue;
            m_plugins.remove(i);
        }
        return true;
    }

    // FIXME: We should prefer a newer version of a plugin to an older version, rather than loading
    // only the first. <http://webkit.org/b/58469>
    String pluginFileName = pathGetFileName(plugin.path);
    for (size_t i = 0; i < m_plugins.size(); ++i) {
        Plugin& loadedPlugin = m_plugins[i];

        // If a plug-in with the same filename already exists, we don't want to load it.
        if (equalIgnoringCase(pluginFileName, pathGetFileName(loadedPlugin.path)))
            return false;
    }

    return true;
}

} // namespace WebKit
