<commit_before>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2016 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU General Public License, version 3.0
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>

#include <QDir>
#include <QtQml>
#include <QFile>
#include <QUuid>
#include <QtDebug>
#include <QDateTime>
#include <QSettings>
#include <QTextStream>
#include <QQmlContext>
#include <QApplication>
#include <QQuickWindow>
#include <QStandardPaths>
#include <QQmlApplicationEngine>
#include <QDesktopWidget>
//-------------------------------------
#include "SpellCheck/spellchecksuggestionmodel.h"
#include "Models/filteredartitemsproxymodel.h"
#include "Suggestion/suggestionqueryengine.h"
#include "MetadataIO/metadataiocoordinator.h"
#include "Conectivity/analyticsuserevent.h"
#include "SpellCheck/spellcheckerservice.h"
#include "Models/recentdirectoriesmodel.h"
#include "MetadataIO/backupsaverservice.h"
#include "Suggestion/keywordssuggestor.h"
#include "Models/combinedartworksmodel.h"
#include "Conectivity/telemetryservice.h"
#include "Helpers/globalimageprovider.h"
#include "Models/uploadinforepository.h"
#include "Helpers/helpersqmlwrapper.h"
#include "Encryption/secretsmanager.h"
#include "Models/artworksrepository.h"
#include "Helpers/settingsprovider.h"
#include "Warnings/warningsservice.h"
#include "UndoRedo/undoredomanager.h"
#include "Helpers/clipboardhelper.h"
#include "Commands/commandmanager.h"
#include "Suggestion/locallibrary.h"
#include "Models/artworkuploader.h"
#include "Warnings/warningsmodel.h"
#include "Plugins/pluginmanager.h"
#include "Helpers/loggingworker.h"
#include "Helpers/updateservice.h"
#include "Models/artitemsmodel.h"
#include "Models/settingsmodel.h"
#include "Helpers/appsettings.h"
#include "Models/ziparchiver.h"
#include "Helpers/constants.h"
#include "Helpers/runguard.h"
#include "Models/logsmodel.h"
#include "Helpers/logger.h"
#include "Common/version.h"
#include "Common/defines.h"

void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
    Q_UNUSED(context);

    QString logLine;
    QString time = QDateTime::currentDateTimeUtc().toString("dd.MM.yyyy hh:mm:ss.zzz");
    switch (type) {
        case QtDebugMsg:
            logLine = QString("%1 - Debug: %2").arg(time).arg(msg);
            break;
        case QtWarningMsg:
            logLine = QString("%1 - Warning: %2").arg(time).arg(msg);
            break;
        case QtCriticalMsg:
            logLine = QString("%1 - Critical: %2").arg(time).arg(msg);
            break;
        case QtFatalMsg:
            logLine = QString("%1 - Fatal: %2").arg(time).arg(msg);
            break;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 1))
        case QtInfoMsg:
            logLine = QString("%1 - Info:  %2").arg(time).arg(msg);
            break;
#endif
    }

    Helpers::Logger &logger = Helpers::Logger::getInstance();
    logger.log(logLine);

    if (type == QtFatalMsg) {
        abort();
    }
}

#define STRINGIZE_(x) #x
#define STRINGIZE(x) STRINGIZE_(x)

void initQSettings() {
    QCoreApplication::setOrganizationName(Constants::ORGANIZATION_NAME);
    QCoreApplication::setOrganizationDomain(Constants::ORGANIZATION_DOMAIN);
    QCoreApplication::setApplicationName(Constants::APPLICATION_NAME);
    QString appVersion(STRINGIZE(BUILDNUMBER));
    QCoreApplication::setApplicationVersion(STRINGIZE(XPIKS_VERSION)" "STRINGIZE(XPIKS_VERSION_SUFFIX)" - " + appVersion.left(10));
}

void ensureUserIdExists(Helpers::AppSettings *settings) {
    QLatin1String userIdKey = QLatin1String(Constants::USER_AGENT_ID);
    if (!settings->contains(userIdKey)) {
        QUuid uuid = QUuid::createUuid();
        settings->setValue(userIdKey, uuid.toString());
    }
}

static const char *setHighDpiEnvironmentVariable()
{
    const char* envVarName = 0;
    static const char ENV_VAR_QT_DEVICE_PIXEL_RATIO[] = "QT_DEVICE_PIXEL_RATIO";

#ifdef Q_OS_WIN
    bool isWindows = true;
#else
    bool isWindows = false;
#endif

#if (QT_VERSION < QT_VERSION_CHECK(5, 6, 0))
    if (isWindows
            && !qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO)) {
        envVarName = ENV_VAR_QT_DEVICE_PIXEL_RATIO;
        qputenv(envVarName, "auto");
    }
#else
    if (isWindows
            && !qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO) // legacy in 5.6, but still functional
            && !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR")
            && !qEnvironmentVariableIsSet("QT_SCALE_FACTOR")
            && !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    }
#endif // < Qt 5.6
    return envVarName;
}

int main(int argc, char *argv[]) {
    Helpers::RunGuard guard("xpiks");
    if (!guard.tryToRun()) {
        std::cerr << "Xpiks is already running";
        return -1;
    }

    const char *highDpiEnvironmentVariable = setHighDpiEnvironmentVariable();

    initQSettings();
    Helpers::AppSettings appSettings;
    ensureUserIdExists(&appSettings);

    Suggestion::LocalLibrary localLibrary;

#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
#else
    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
#endif
    if (!appDataPath.isEmpty()) {
        QDir appDataDir(appDataPath);

        QString time = QDateTime::currentDateTimeUtc().toString("ddMMyyyy-hhmmss-zzz");
        QString logFilename = QString("xpiks-qt-%1.log").arg(time);
        QString logFilePath = appDataDir.filePath(logFilename);
        Helpers::Logger &logger = Helpers::Logger::getInstance();
        logger.setLogFilePath(logFilePath);

        QString libraryFilePath = appDataDir.filePath(Constants::LIBRARY_FILENAME);
        localLibrary.setLibraryPath(libraryFilePath);
    } else {
        std::cerr << "AppDataPath is empty!";
    }

#ifdef WITH_LOGS
    const QString &logFileDir = appDataPath;
    if (!logFileDir.isEmpty()) {
        QDir dir(logFileDir);
        if (!dir.exists()) {
            bool created = QDir().mkpath(logFileDir);
            Q_UNUSED(created);
        }
    }
#endif

    Models::LogsModel logsModel;
    logsModel.startLogging();

    qInstallMessageHandler(myMessageHandler);
    qInfo() << "main #" << "Log started." << "Xpiks" << XPIKS_VERSION_STRING << "-" << STRINGIZE(BUILDNUMBER);

#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
    qInfo() << "main #" << QSysInfo::productType() << QSysInfo::productVersion();
#else
#ifdef Q_OS_WIN
    qInfo() << "main #" << QLatin1String("Windows Qt<5.4");
#elsif Q_OS_DARWIN
    qInfo() << "main #" << QLatin1String("OS X Qt<5.4");
#else
    qInfo() << "main #" << QLatin1String("LINUX Qt<5.4");
#endif
#endif

    QApplication app(argc, argv);

    qDebug() << "main #" << "Working directory of Xpiks is:" << QDir::currentPath();

    if (highDpiEnvironmentVariable) {
        qunsetenv(highDpiEnvironmentVariable);
    }

    localLibrary.loadLibraryAsync();

    QString userId = appSettings.value(QLatin1String(Constants::USER_AGENT_ID)).toString();
    userId.remove(QRegExp("[{}-]."));

    Models::ArtworksRepository artworkRepository;
    Models::ArtItemsModel artItemsModel;
    Models::CombinedArtworksModel combinedArtworksModel;
    Models::UploadInfoRepository uploadInfoRepository;
    Warnings::WarningsService warningsService;
    Models::SettingsModel settingsModel;
    settingsModel.readAllValues();
    Encryption::SecretsManager secretsManager;
    UndoRedo::UndoRedoManager undoRedoManager;
    Models::ZipArchiver zipArchiver;
    Suggestion::KeywordsSuggestor keywordsSuggestor;
    keywordsSuggestor.setLocalLibrary(&localLibrary);
    Models::FilteredArtItemsProxyModel filteredArtItemsModel;
    filteredArtItemsModel.setSourceModel(&artItemsModel);
    Models::RecentDirectoriesModel recentDirectorieModel;
    Models::ArtworkUploader artworkUploader(settingsModel.getMaxParallelUploads(), settingsModel.getUploadTimeout());
    SpellCheck::SpellCheckerService spellCheckerService;
    SpellCheck::SpellCheckSuggestionModel spellCheckSuggestionModel;
    MetadataIO::BackupSaverService metadataSaverService;
    Warnings::WarningsModel warningsModel;
    warningsModel.setSourceModel(&artItemsModel);

    bool updateEnabled=appSettings.value(Constants::UPDATE_SERVICE,true ).toBool();
    Helpers::UpdateService updateService(updateEnabled);

    MetadataIO::MetadataIOCoordinator metadataIOCoordinator;
#ifdef TELEMETRY_ENABLED
    bool telemetryEnabled = appSettings.value(Constants::USER_STATISTICS, true).toBool();
#else
    bool telemetryEnabled = appSettings.value(Constants::USER_STATISTICS, false).toBool();
#endif
    Conectivity::TelemetryService telemetryService(userId, telemetryEnabled);
    Plugins::PluginManager pluginManager;
    Plugins::PluginsWithActionsModel pluginsWithActions;
    pluginsWithActions.setSourceModel(&pluginManager);

    Commands::CommandManager commandManager;
    commandManager.InjectDependency(&artworkRepository);
    commandManager.InjectDependency(&artItemsModel);
    commandManager.InjectDependency(&filteredArtItemsModel);
    commandManager.InjectDependency(&combinedArtworksModel);
    commandManager.InjectDependency(&artworkUploader);
    commandManager.InjectDependency(&uploadInfoRepository);
    commandManager.InjectDependency(&warningsService);
    commandManager.InjectDependency(&secretsManager);
    commandManager.InjectDependency(&undoRedoManager);
    commandManager.InjectDependency(&zipArchiver);
    commandManager.InjectDependency(&keywordsSuggestor);
    commandManager.InjectDependency(&settingsModel);
    commandManager.InjectDependency(&recentDirectorieModel);
    commandManager.InjectDependency(&spellCheckerService);
    commandManager.InjectDependency(&spellCheckSuggestionModel);
    commandManager.InjectDependency(&metadataSaverService);
    commandManager.InjectDependency(&telemetryService);
    commandManager.InjectDependency(&updateService);
    commandManager.InjectDependency(&logsModel);
    commandManager.InjectDependency(&localLibrary);
    commandManager.InjectDependency(&metadataIOCoordinator);
    commandManager.InjectDependency(&pluginManager);

    commandManager.ensureDependenciesInjected();

    // other initializations
    secretsManager.setMasterPasswordHash(appSettings.value(Constants::MASTER_PASSWORD_HASH, "").toString());
    uploadInfoRepository.initFromString(appSettings.value(Constants::UPLOAD_HOSTS, "").toString());
    recentDirectorieModel.deserializeFromSettings(appSettings.value(Constants::RECENT_DIRECTORIES, "").toString());

    Helpers::SettingsProvider::getInstance().setSettingsModelInstance(&settingsModel);

    commandManager.connectEntitiesSignalsSlots();

    qmlRegisterType<Helpers::ClipboardHelper>("xpiks", 1, 0, "ClipboardHelper");

    QQmlApplicationEngine engine;
    Helpers::GlobalImageProvider *globalProvider = new Helpers::GlobalImageProvider(QQmlImageProviderBase::Image);

    Helpers::HelpersQmlWrapper helpersQmlWrapper(&commandManager);

    QQmlContext *rootContext = engine.rootContext();
    rootContext->setContextProperty("artItemsModel", &artItemsModel);
    rootContext->setContextProperty("artworkRepository", &artworkRepository);
    rootContext->setContextProperty("combinedArtworks", &combinedArtworksModel);
    rootContext->setContextProperty("appSettings", &appSettings);
    rootContext->setContextProperty("artworkUploader", &artworkUploader);
    rootContext->setContextProperty("uploadInfos", &uploadInfoRepository);
    rootContext->setContextProperty("logsModel", &logsModel);
    rootContext->setContextProperty("secretsManager", &secretsManager);
    rootContext->setContextProperty("undoRedoManager", &undoRedoManager);
    rootContext->setContextProperty("zipArchiver", &zipArchiver);
    rootContext->setContextProperty("keywordsSuggestor", &keywordsSuggestor);
    rootContext->setContextProperty("settingsModel", &settingsModel);
    rootContext->setContextProperty("filteredArtItemsModel", &filteredArtItemsModel);
    rootContext->setContextProperty("helpersWrapper", &helpersQmlWrapper);
    rootContext->setContextProperty("recentDirectories", &recentDirectorieModel);
    rootContext->setContextProperty("updateService", &updateService);
    rootContext->setContextProperty("spellCheckerService", &spellCheckerService);
    rootContext->setContextProperty("spellCheckSuggestionModel", &spellCheckSuggestionModel);
    rootContext->setContextProperty("metadataIOCoordinator", &metadataIOCoordinator);
    rootContext->setContextProperty("pluginManager", &pluginManager);
    rootContext->setContextProperty("pluginsWithActions", &pluginsWithActions);
    rootContext->setContextProperty("warningsModel", &warningsModel);

    engine.addImageProvider("global", globalProvider);
    qDebug() << "main #" << "About to load main view...";
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    qDebug() << "main #" << "Main view loaded";

    pluginManager.getUIProvider()->setQmlEngine(&engine);
    QQuickWindow *window = qobject_cast<QQuickWindow*>(engine.rootObjects().at(0));
    pluginManager.getUIProvider()->setRoot(window->contentItem());

//#ifdef QT_DEBUG
//    if (argc > 1) {
//        QStringList pathes;
//        for (int i = 1; i < argc; ++i) {
//            pathes.append(QString(argv[i]));
//        }
//        commandManager.addInitialArtworks(pathes);
//    }
//#endif

    return app.exec();
}
<commit_msg>Moved logs to logs dir<commit_after>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2016 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU General Public License, version 3.0
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>

#include <QDir>
#include <QtQml>
#include <QFile>
#include <QUuid>
#include <QtDebug>
#include <QDateTime>
#include <QSettings>
#include <QTextStream>
#include <QQmlContext>
#include <QApplication>
#include <QQuickWindow>
#include <QStandardPaths>
#include <QQmlApplicationEngine>
#include <QDesktopWidget>
//-------------------------------------
#include "SpellCheck/spellchecksuggestionmodel.h"
#include "Models/filteredartitemsproxymodel.h"
#include "Suggestion/suggestionqueryengine.h"
#include "MetadataIO/metadataiocoordinator.h"
#include "Conectivity/analyticsuserevent.h"
#include "SpellCheck/spellcheckerservice.h"
#include "Models/recentdirectoriesmodel.h"
#include "MetadataIO/backupsaverservice.h"
#include "Suggestion/keywordssuggestor.h"
#include "Models/combinedartworksmodel.h"
#include "Conectivity/telemetryservice.h"
#include "Helpers/globalimageprovider.h"
#include "Models/uploadinforepository.h"
#include "Helpers/helpersqmlwrapper.h"
#include "Encryption/secretsmanager.h"
#include "Models/artworksrepository.h"
#include "Helpers/settingsprovider.h"
#include "Warnings/warningsservice.h"
#include "UndoRedo/undoredomanager.h"
#include "Helpers/clipboardhelper.h"
#include "Commands/commandmanager.h"
#include "Suggestion/locallibrary.h"
#include "Models/artworkuploader.h"
#include "Warnings/warningsmodel.h"
#include "Plugins/pluginmanager.h"
#include "Helpers/loggingworker.h"
#include "Helpers/updateservice.h"
#include "Models/artitemsmodel.h"
#include "Models/settingsmodel.h"
#include "Helpers/appsettings.h"
#include "Models/ziparchiver.h"
#include "Helpers/constants.h"
#include "Helpers/runguard.h"
#include "Models/logsmodel.h"
#include "Helpers/logger.h"
#include "Common/version.h"
#include "Common/defines.h"

void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
    Q_UNUSED(context);

    QString logLine;
    QString time = QDateTime::currentDateTimeUtc().toString("dd.MM.yyyy hh:mm:ss.zzz");
    switch (type) {
        case QtDebugMsg:
            logLine = QString("%1 - Debug: %2").arg(time).arg(msg);
            break;
        case QtWarningMsg:
            logLine = QString("%1 - Warning: %2").arg(time).arg(msg);
            break;
        case QtCriticalMsg:
            logLine = QString("%1 - Critical: %2").arg(time).arg(msg);
            break;
        case QtFatalMsg:
            logLine = QString("%1 - Fatal: %2").arg(time).arg(msg);
            break;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 1))
        case QtInfoMsg:
            logLine = QString("%1 - Info:  %2").arg(time).arg(msg);
            break;
#endif
    }

    Helpers::Logger &logger = Helpers::Logger::getInstance();
    logger.log(logLine);

    if (type == QtFatalMsg) {
        abort();
    }
}

#define STRINGIZE_(x) #x
#define STRINGIZE(x) STRINGIZE_(x)

void initQSettings() {
    QCoreApplication::setOrganizationName(Constants::ORGANIZATION_NAME);
    QCoreApplication::setOrganizationDomain(Constants::ORGANIZATION_DOMAIN);
    QCoreApplication::setApplicationName(Constants::APPLICATION_NAME);
    QString appVersion(STRINGIZE(BUILDNUMBER));
    QCoreApplication::setApplicationVersion(STRINGIZE(XPIKS_VERSION)" "STRINGIZE(XPIKS_VERSION_SUFFIX)" - " + appVersion.left(10));
}

void ensureUserIdExists(Helpers::AppSettings *settings) {
    QLatin1String userIdKey = QLatin1String(Constants::USER_AGENT_ID);
    if (!settings->contains(userIdKey)) {
        QUuid uuid = QUuid::createUuid();
        settings->setValue(userIdKey, uuid.toString());
    }
}

static const char *setHighDpiEnvironmentVariable()
{
    const char* envVarName = 0;
    static const char ENV_VAR_QT_DEVICE_PIXEL_RATIO[] = "QT_DEVICE_PIXEL_RATIO";

#ifdef Q_OS_WIN
    bool isWindows = true;
#else
    bool isWindows = false;
#endif

#if (QT_VERSION < QT_VERSION_CHECK(5, 6, 0))
    if (isWindows
            && !qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO)) {
        envVarName = ENV_VAR_QT_DEVICE_PIXEL_RATIO;
        qputenv(envVarName, "auto");
    }
#else
    if (isWindows
            && !qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO) // legacy in 5.6, but still functional
            && !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR")
            && !qEnvironmentVariableIsSet("QT_SCALE_FACTOR")
            && !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    }
#endif // < Qt 5.6
    return envVarName;
}

int main(int argc, char *argv[]) {
    Helpers::RunGuard guard("xpiks");
    if (!guard.tryToRun()) {
        std::cerr << "Xpiks is already running";
        return -1;
    }

    const char *highDpiEnvironmentVariable = setHighDpiEnvironmentVariable();

    initQSettings();
    Helpers::AppSettings appSettings;
    ensureUserIdExists(&appSettings);

    Suggestion::LocalLibrary localLibrary;

#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
#else
    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
#endif
    if (!appDataPath.isEmpty()) {
        QDir appDataDir(appDataPath);

        QString libraryFilePath = appDataDir.filePath(Constants::LIBRARY_FILENAME);
        localLibrary.setLibraryPath(libraryFilePath);
    } else {
        std::cerr << "AppDataPath is empty!";
    }

#ifdef WITH_LOGS
    const QString &logFileDir = QDir::cleanPath(appDataPath + QDir::separator() + "logs");
    if (!logFileDir.isEmpty()) {
        QDir dir(logFileDir);
        if (!dir.exists()) {
            bool created = QDir().mkpath(logFileDir);
            Q_UNUSED(created);
        }

        QString time = QDateTime::currentDateTimeUtc().toString("ddMMyyyy-hhmmss-zzz");
        QString logFilename = QString("xpiks-qt-%1.log").arg(time);

        QString logFilePath = dir.filePath(logFilename);

        Helpers::Logger &logger = Helpers::Logger::getInstance();
        logger.setLogFilePath(logFilePath);
    }

#endif

    Models::LogsModel logsModel;
    logsModel.startLogging();

    qInstallMessageHandler(myMessageHandler);
    qInfo() << "main #" << "Log started." << "Xpiks" << XPIKS_VERSION_STRING << "-" << STRINGIZE(BUILDNUMBER);

#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
    qInfo() << "main #" << QSysInfo::productType() << QSysInfo::productVersion();
#else
#ifdef Q_OS_WIN
    qInfo() << "main #" << QLatin1String("Windows Qt<5.4");
#elsif Q_OS_DARWIN
    qInfo() << "main #" << QLatin1String("OS X Qt<5.4");
#else
    qInfo() << "main #" << QLatin1String("LINUX Qt<5.4");
#endif
#endif

    QApplication app(argc, argv);

    qDebug() << "main #" << "Working directory of Xpiks is:" << QDir::currentPath();

    if (highDpiEnvironmentVariable) {
        qunsetenv(highDpiEnvironmentVariable);
    }

    localLibrary.loadLibraryAsync();

    QString userId = appSettings.value(QLatin1String(Constants::USER_AGENT_ID)).toString();
    userId.remove(QRegExp("[{}-]."));

    Models::ArtworksRepository artworkRepository;
    Models::ArtItemsModel artItemsModel;
    Models::CombinedArtworksModel combinedArtworksModel;
    Models::UploadInfoRepository uploadInfoRepository;
    Warnings::WarningsService warningsService;
    Models::SettingsModel settingsModel;
    settingsModel.readAllValues();
    Encryption::SecretsManager secretsManager;
    UndoRedo::UndoRedoManager undoRedoManager;
    Models::ZipArchiver zipArchiver;
    Suggestion::KeywordsSuggestor keywordsSuggestor;
    keywordsSuggestor.setLocalLibrary(&localLibrary);
    Models::FilteredArtItemsProxyModel filteredArtItemsModel;
    filteredArtItemsModel.setSourceModel(&artItemsModel);
    Models::RecentDirectoriesModel recentDirectorieModel;
    Models::ArtworkUploader artworkUploader(settingsModel.getMaxParallelUploads(), settingsModel.getUploadTimeout());
    SpellCheck::SpellCheckerService spellCheckerService;
    SpellCheck::SpellCheckSuggestionModel spellCheckSuggestionModel;
    MetadataIO::BackupSaverService metadataSaverService;
    Warnings::WarningsModel warningsModel;
    warningsModel.setSourceModel(&artItemsModel);

    bool updateEnabled=appSettings.value(Constants::UPDATE_SERVICE,true ).toBool();
    Helpers::UpdateService updateService(updateEnabled);

    MetadataIO::MetadataIOCoordinator metadataIOCoordinator;
#ifdef TELEMETRY_ENABLED
    bool telemetryEnabled = appSettings.value(Constants::USER_STATISTICS, true).toBool();
#else
    bool telemetryEnabled = appSettings.value(Constants::USER_STATISTICS, false).toBool();
#endif
    Conectivity::TelemetryService telemetryService(userId, telemetryEnabled);
    Plugins::PluginManager pluginManager;
    Plugins::PluginsWithActionsModel pluginsWithActions;
    pluginsWithActions.setSourceModel(&pluginManager);

    Commands::CommandManager commandManager;
    commandManager.InjectDependency(&artworkRepository);
    commandManager.InjectDependency(&artItemsModel);
    commandManager.InjectDependency(&filteredArtItemsModel);
    commandManager.InjectDependency(&combinedArtworksModel);
    commandManager.InjectDependency(&artworkUploader);
    commandManager.InjectDependency(&uploadInfoRepository);
    commandManager.InjectDependency(&warningsService);
    commandManager.InjectDependency(&secretsManager);
    commandManager.InjectDependency(&undoRedoManager);
    commandManager.InjectDependency(&zipArchiver);
    commandManager.InjectDependency(&keywordsSuggestor);
    commandManager.InjectDependency(&settingsModel);
    commandManager.InjectDependency(&recentDirectorieModel);
    commandManager.InjectDependency(&spellCheckerService);
    commandManager.InjectDependency(&spellCheckSuggestionModel);
    commandManager.InjectDependency(&metadataSaverService);
    commandManager.InjectDependency(&telemetryService);
    commandManager.InjectDependency(&updateService);
    commandManager.InjectDependency(&logsModel);
    commandManager.InjectDependency(&localLibrary);
    commandManager.InjectDependency(&metadataIOCoordinator);
    commandManager.InjectDependency(&pluginManager);

    commandManager.ensureDependenciesInjected();

    // other initializations
    secretsManager.setMasterPasswordHash(appSettings.value(Constants::MASTER_PASSWORD_HASH, "").toString());
    uploadInfoRepository.initFromString(appSettings.value(Constants::UPLOAD_HOSTS, "").toString());
    recentDirectorieModel.deserializeFromSettings(appSettings.value(Constants::RECENT_DIRECTORIES, "").toString());

    Helpers::SettingsProvider::getInstance().setSettingsModelInstance(&settingsModel);

    commandManager.connectEntitiesSignalsSlots();

    qmlRegisterType<Helpers::ClipboardHelper>("xpiks", 1, 0, "ClipboardHelper");

    QQmlApplicationEngine engine;
    Helpers::GlobalImageProvider *globalProvider = new Helpers::GlobalImageProvider(QQmlImageProviderBase::Image);

    Helpers::HelpersQmlWrapper helpersQmlWrapper(&commandManager);

    QQmlContext *rootContext = engine.rootContext();
    rootContext->setContextProperty("artItemsModel", &artItemsModel);
    rootContext->setContextProperty("artworkRepository", &artworkRepository);
    rootContext->setContextProperty("combinedArtworks", &combinedArtworksModel);
    rootContext->setContextProperty("appSettings", &appSettings);
    rootContext->setContextProperty("artworkUploader", &artworkUploader);
    rootContext->setContextProperty("uploadInfos", &uploadInfoRepository);
    rootContext->setContextProperty("logsModel", &logsModel);
    rootContext->setContextProperty("secretsManager", &secretsManager);
    rootContext->setContextProperty("undoRedoManager", &undoRedoManager);
    rootContext->setContextProperty("zipArchiver", &zipArchiver);
    rootContext->setContextProperty("keywordsSuggestor", &keywordsSuggestor);
    rootContext->setContextProperty("settingsModel", &settingsModel);
    rootContext->setContextProperty("filteredArtItemsModel", &filteredArtItemsModel);
    rootContext->setContextProperty("helpersWrapper", &helpersQmlWrapper);
    rootContext->setContextProperty("recentDirectories", &recentDirectorieModel);
    rootContext->setContextProperty("updateService", &updateService);
    rootContext->setContextProperty("spellCheckerService", &spellCheckerService);
    rootContext->setContextProperty("spellCheckSuggestionModel", &spellCheckSuggestionModel);
    rootContext->setContextProperty("metadataIOCoordinator", &metadataIOCoordinator);
    rootContext->setContextProperty("pluginManager", &pluginManager);
    rootContext->setContextProperty("pluginsWithActions", &pluginsWithActions);
    rootContext->setContextProperty("warningsModel", &warningsModel);

    engine.addImageProvider("global", globalProvider);
    qDebug() << "main #" << "About to load main view...";
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    qDebug() << "main #" << "Main view loaded";

    pluginManager.getUIProvider()->setQmlEngine(&engine);
    QQuickWindow *window = qobject_cast<QQuickWindow*>(engine.rootObjects().at(0));
    pluginManager.getUIProvider()->setRoot(window->contentItem());

//#ifdef QT_DEBUG
//    if (argc > 1) {
//        QStringList pathes;
//        for (int i = 1; i < argc; ++i) {
//            pathes.append(QString(argv[i]));
//        }
//        commandManager.addInitialArtworks(pathes);
//    }
//#endif

    return app.exec();
}
<|endoftext|>


<commit_before>/* Copyright (c) 2008 - 2021 Advanced Micro Devices, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE. */

#include "top.hpp"
#include "utils/flags.hpp"

#include <unordered_map>
#include <string>
#include <cstdlib>
#include <cstring>

#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#else
#include <unistd.h>
#endif  // !_WIN32

namespace {

const char* removeQuotes(const char* Value) {
  const char *b, *e, *p;
  if (Value == NULL) {
    return Value;
  }

  // skip the leading blank
  for (p = Value; *p == ' '; ++p)
    ;
  if (*p != '"') {
    return Value;
  }
  b = p;
  e = NULL;
  for (++p; *p != '\0'; ++p) {
    if (*p == '"') {
      // e points to the last '"'
      e = p;
    } else if ((e != NULL) && (*p != ' ')) {
      // e isn't last '"' if there is any non-blank following e
      e = NULL;
    }
  }

  if (e == NULL) {
    return Value;
  }
  // Found a valid quoted string "<str>" with b=1st '"' and e=the last '"'
  size_t len = (e - b - 1) > 0 ? (e - b - 1) : 0;
#ifdef _WIN32
  char* p1 = _strdup(b + 1);
  p1[len] = '\0';
  p = p1;
#else
  p = strndup(b + 1, len);
#endif
  return p;
}
}

namespace amd {

#ifdef __APPLE__
#include <crt_externs.h>
#endif  // __APPLE__

bool IS_HIP = false;

#if !defined(_WIN32) && defined(WITH_PAL_DEVICE)
bool IS_LEGACY = true;
#else
bool IS_LEGACY = false;
#endif

// static
char* Flag::envstr_;

void Flag::tearDown() {
#ifdef _WIN32
  FreeEnvironmentStringsA(envstr_);
#endif
}

bool Flag::init() {
  typedef std::unordered_map<std::string, const char*> vars_type;
  vars_type vars;

#ifdef _WIN32
  char* str = GetEnvironmentStringsA();
  envstr_ = str;

  for (; *str != '\0'; str += strlen(str) + 1) {
    // For all environment variables:
    std::string var = str;
    size_t pos = var.find('=');
    if ((pos == std::string::npos) || ((pos + 1) >= var.size())) {
      continue;
    }

    std::string name = var.substr(0, pos);
    vars.insert(std::make_pair(name, &str[pos + 1]));
  }
#else  // !_WIN32
#ifdef __APPLE__
  char** environ = *_NSGetEnviron();
  if (environ == NULL) {
    return false;
  }
#endif  // __APPLE__

  for (const char** p = const_cast<const char**>(environ); *p != NULL; ++p) {
    std::string var = *p;
    size_t pos = var.find('=');
    if ((pos == std::string::npos) || ((pos + 1) >= var.size())) {
      continue;
    }

    std::string name = var.substr(0, pos);
    vars.insert(std::make_pair(name, &(*p)[pos + 1]));
  }
#endif  // !_WIN32

  for (size_t i = 0; i < numFlags_; ++i) {
    Flag& flag = flags_[i];

    const auto it = vars.find(flag.name_);
    if (it != vars.cend()) {
      flag.setValue(it->second);
    }
  }
  if (!flagIsDefault(AMD_LOG_LEVEL)) {
    if (!flagIsDefault(AMD_LOG_LEVEL_FILE)) {
      std::string fileName = AMD_LOG_LEVEL_FILE;
      fileName = fileName + "_" + std::to_string(getpid());
      outFile = fopen(fileName.c_str(), "w");
    }
  }

  return true;
}

bool Flag::setValue(const char* value) {
  if (value_ == NULL) {
    return false;  // flag is constant.
  }

  isDefault_ = false;

  switch (type_) {
    case Tbool:
      *(bool*)value_ = (strcmp(value, "true") == 0 || atoi(value) != 0) ? true : false;
      return true;

    case Tint:
    case Tuint:
      *(int*)value_ = atoi(value);
      return true;

    case Tsize_t:
      *(size_t*)value_ = atol(value);
      return true;

    case Tcstring:
      *(const char**)value_ = removeQuotes(value);
      return true;

    default:
      break;
  }
  ShouldNotReachHere();
  return false;
}

#define DEFINE_RELEASE_FLAG_STRUCT(type, name, value, help) {#name, &name, T##type, true},
#define DEFINE_DEBUG_FLAG_STRUCT(type, name, value, help)                                          \
  {#name, RELEASE_ONLY(NULL) DEBUG_ONLY(&name), T##type, true},

Flag Flag::flags_[] = {
    RUNTIME_FLAGS(DEFINE_DEBUG_FLAG_STRUCT, DEFINE_RELEASE_FLAG_STRUCT, DEFINE_DEBUG_FLAG_STRUCT)
        {NULL, NULL, Tinvalid, true}};

#undef DEFINE_DEBUG_FLAG_STRUCT
#undef DEFINE_RELEASE_FLAG_STRUCT

}  // namespace amd

#define DEFINE_RELEASE_FLAG_VALUE(type, name, value, help) type name = value;
#define DEFINE_DEBUG_FLAG_VALUE(type, name, value, help) DEBUG_ONLY(type name = value);

RUNTIME_FLAGS(DEFINE_DEBUG_FLAG_VALUE, DEFINE_RELEASE_FLAG_VALUE, DEFINE_DEBUG_FLAG_VALUE);

#undef DEFINE_DEBUG_FLAG_VALUE
#undef DEFINE_RELEASE_FLAG_VALUE
<commit_msg>SWDEV-363536 - HIP_VISIBLE_DEVICES= should disable the device<commit_after>/* Copyright (c) 2008 - 2021 Advanced Micro Devices, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE. */

#include "top.hpp"
#include "utils/flags.hpp"

#include <unordered_map>
#include <string>
#include <cstdlib>
#include <cstring>

#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#else
#include <unistd.h>
#endif  // !_WIN32

namespace {

const char* removeQuotes(const char* Value) {
  const char *b, *e, *p;
  if (Value == NULL) {
    return Value;
  }

  // skip the leading blank
  for (p = Value; *p == ' '; ++p)
    ;
  if (*p != '"') {
    return Value;
  }
  b = p;
  e = NULL;
  for (++p; *p != '\0'; ++p) {
    if (*p == '"') {
      // e points to the last '"'
      e = p;
    } else if ((e != NULL) && (*p != ' ')) {
      // e isn't last '"' if there is any non-blank following e
      e = NULL;
    }
  }

  if (e == NULL) {
    return Value;
  }
  // Found a valid quoted string "<str>" with b=1st '"' and e=the last '"'
  size_t len = (e - b - 1) > 0 ? (e - b - 1) : 0;
#ifdef _WIN32
  char* p1 = _strdup(b + 1);
  p1[len] = '\0';
  p = p1;
#else
  p = strndup(b + 1, len);
#endif
  return p;
}
}

namespace amd {

#ifdef __APPLE__
#include <crt_externs.h>
#endif  // __APPLE__

bool IS_HIP = false;

#if !defined(_WIN32) && defined(WITH_PAL_DEVICE)
bool IS_LEGACY = true;
#else
bool IS_LEGACY = false;
#endif

// static
char* Flag::envstr_;

void Flag::tearDown() {
#ifdef _WIN32
  FreeEnvironmentStringsA(envstr_);
#endif
}

bool Flag::init() {
  typedef std::unordered_map<std::string, const char*> vars_type;
  vars_type vars;

#ifdef _WIN32
  char* str = GetEnvironmentStringsA();
  envstr_ = str;

  for (; *str != '\0'; str += strlen(str) + 1) {
    // For all environment variables:
    std::string var = str;
    size_t pos = var.find('=');
    if ((pos == std::string::npos) || ((pos + 1) > var.size())) {
      continue;
    }

    std::string name = var.substr(0, pos);
    if ((pos + 1) == var.size()) {
      vars.insert(std::make_pair(name, " "));
    } else {
      vars.insert(std::make_pair(name, &str[pos + 1]));
    }
  }
#else  // !_WIN32
#ifdef __APPLE__
  char** environ = *_NSGetEnviron();
  if (environ == NULL) {
    return false;
  }
#endif  // __APPLE__

  for (const char** p = const_cast<const char**>(environ); *p != NULL; ++p) {
    std::string var = *p;
    size_t pos = var.find('=');
    if ((pos == std::string::npos) || ((pos + 1) > var.size())) {
      continue;
    }

    std::string name = var.substr(0, pos);
    if ((pos + 1) == var.size()) {
      vars.insert(std::make_pair(name, " "));
    } else {
      vars.insert(std::make_pair(name, &(*p)[pos + 1]));
    }
  }
#endif  // !_WIN32

  for (size_t i = 0; i < numFlags_; ++i) {
    Flag& flag = flags_[i];

    const auto it = vars.find(flag.name_);
    if (it != vars.cend()) {
      flag.setValue(it->second);
    }
  }
  if (!flagIsDefault(AMD_LOG_LEVEL)) {
    if (!flagIsDefault(AMD_LOG_LEVEL_FILE)) {
      std::string fileName = AMD_LOG_LEVEL_FILE;
      fileName = fileName + "_" + std::to_string(getpid());
      outFile = fopen(fileName.c_str(), "w");
    }
  }

  return true;
}

bool Flag::setValue(const char* value) {
  if (value_ == NULL) {
    return false;  // flag is constant.
  }

  isDefault_ = false;

  switch (type_) {
    case Tbool:
      *(bool*)value_ = (strcmp(value, "true") == 0 || atoi(value) != 0) ? true : false;
      return true;

    case Tint:
    case Tuint:
      *(int*)value_ = atoi(value);
      return true;

    case Tsize_t:
      *(size_t*)value_ = atol(value);
      return true;

    case Tcstring:
      *(const char**)value_ = removeQuotes(value);
      return true;

    default:
      break;
  }
  ShouldNotReachHere();
  return false;
}

#define DEFINE_RELEASE_FLAG_STRUCT(type, name, value, help) {#name, &name, T##type, true},
#define DEFINE_DEBUG_FLAG_STRUCT(type, name, value, help)                                          \
  {#name, RELEASE_ONLY(NULL) DEBUG_ONLY(&name), T##type, true},

Flag Flag::flags_[] = {
    RUNTIME_FLAGS(DEFINE_DEBUG_FLAG_STRUCT, DEFINE_RELEASE_FLAG_STRUCT, DEFINE_DEBUG_FLAG_STRUCT)
        {NULL, NULL, Tinvalid, true}};

#undef DEFINE_DEBUG_FLAG_STRUCT
#undef DEFINE_RELEASE_FLAG_STRUCT

}  // namespace amd

#define DEFINE_RELEASE_FLAG_VALUE(type, name, value, help) type name = value;
#define DEFINE_DEBUG_FLAG_VALUE(type, name, value, help) DEBUG_ONLY(type name = value);

RUNTIME_FLAGS(DEFINE_DEBUG_FLAG_VALUE, DEFINE_RELEASE_FLAG_VALUE, DEFINE_DEBUG_FLAG_VALUE);

#undef DEFINE_DEBUG_FLAG_VALUE
#undef DEFINE_RELEASE_FLAG_VALUE
<|endoftext|>


<commit_before>/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2016 The PHP Group                                |
  +----------------------------------------------------------------------+
  | http://www.opensource.org/licenses/mit-license.php  MIT License      |
  +----------------------------------------------------------------------+
  | Author: Jani Taskinen <jani.taskinen@iki.fi>                         |
  | Author: Patrick Reilly <preilly@php.net>                             |
  | Author: Stefan Siegl <stesie@php.net>                                |
  +----------------------------------------------------------------------+
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdexcept>
#include <limits>

#include "php_v8js_macros.h"
#include "v8js_object_export.h"
#include "v8js_v8object_class.h"
#include "v8js_v8.h"

extern "C" {
#include "php.h"
#include "ext/date/php_date.h"
#include "ext/standard/php_string.h"
#include "zend_interfaces.h"
#include "zend_closures.h"
}

static int v8js_is_assoc_array(HashTable *myht TSRMLS_DC) /* {{{ */
{
	zend_string *key;
	ulong index, idx = 0;

	ZEND_HASH_FOREACH_KEY(myht, index, key) {
		if(key) {
			// HASH_KEY_IS_STRING
			return 1;
		}

		if(index != idx) {
			return 1;
		}

		idx ++;
	} ZEND_HASH_FOREACH_END();

	return 0;
}
/* }}} */

static v8::Handle<v8::Value> v8js_hash_to_jsarr(zval *value, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{
	HashTable *myht = HASH_OF(value);
	int i = myht ? zend_hash_num_elements(myht) : 0;

	/* Return object if dealing with assoc array */
	if (i > 0 && v8js_is_assoc_array(myht TSRMLS_CC)) {
		return v8js_hash_to_jsobj(value, isolate TSRMLS_CC);
	}

	v8::Local<v8::Array> newarr;

	/* Prevent recursion */
	if (myht && ZEND_HASH_GET_APPLY_COUNT(myht) > 1) {
		return V8JS_NULL;
	}

	newarr = v8::Array::New(isolate, i);

	if (i > 0)
	{
		zval *data;
		ulong index = 0;
		HashTable *tmp_ht;

		ZEND_HASH_FOREACH_VAL(myht, data) {
			tmp_ht = HASH_OF(data);

			if (tmp_ht) {
				ZEND_HASH_INC_APPLY_COUNT(myht);
			}

			newarr->Set(index++, zval_to_v8js(data, isolate TSRMLS_CC));

			if (tmp_ht) {
				ZEND_HASH_DEC_APPLY_COUNT(myht);
			}
		} ZEND_HASH_FOREACH_END();
	}
	return newarr;
}
/* }}} */

v8::Handle<v8::Value> zval_to_v8js(zval *value, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{
	v8::Handle<v8::Value> jsValue;
	zend_long v;
	zend_class_entry *ce;

	switch (Z_TYPE_P(value))
	{
		case IS_INDIRECT:
			jsValue = zval_to_v8js(Z_INDIRECT_P(value), isolate);
			break;

		case IS_REFERENCE:
			jsValue = zval_to_v8js(Z_REFVAL_P(value), isolate);
			break;

		case IS_ARRAY:
			jsValue = v8js_hash_to_jsarr(value, isolate TSRMLS_CC);
			break;

		case IS_OBJECT:
             if (V8JSG(use_date)) {
				 ce = php_date_get_date_ce();
				 if (instanceof_function(Z_OBJCE_P(value), ce TSRMLS_CC)) {
					 zval dtval;
					 zend_call_method_with_0_params(value, NULL, NULL, "getTimestamp", &dtval);
					 jsValue = V8JS_DATE(((double)Z_LVAL(dtval) * 1000.0));
					 zval_dtor(&dtval);
				 } else
					 jsValue = v8js_hash_to_jsobj(value, isolate TSRMLS_CC);
			 } else
				 jsValue = v8js_hash_to_jsobj(value, isolate TSRMLS_CC);
			break;

		case IS_STRING:
			jsValue = V8JS_ZSTR(Z_STR_P(value));
			break;

		case IS_LONG:
		    v = Z_LVAL_P(value);
			/* On Windows there are max and min macros, which would clobber the
			 * method names of std::numeric_limits< > otherwise. */
#undef max
#undef min
			if (v < - std::numeric_limits<int32_t>::min() || v > std::numeric_limits<int32_t>::max()) {
				jsValue = V8JS_FLOAT(static_cast<double>(v));
			} else {
				jsValue = V8JS_INT(static_cast<int32_t>(v));
			}
			break;

		case IS_DOUBLE:
			jsValue = V8JS_FLOAT(Z_DVAL_P(value));
			break;

		case IS_TRUE:
			jsValue = V8JS_TRUE();
			break;

		case IS_FALSE:
			jsValue = V8JS_FALSE();
			break;

		case IS_NULL:
			jsValue = V8JS_NULL;
			break;

		case IS_UNDEF:
		default:
			/* undefined -> return v8::Value left empty */
			jsValue = v8::Undefined(isolate);
			break;
	}

	return jsValue;
}
/* }}} */

int v8js_to_zval(v8::Handle<v8::Value> jsValue, zval *return_value, int flags, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{
	if (jsValue->IsString())
	{
		v8::String::Utf8Value str(jsValue);
		const char *cstr = ToCString(str);
		RETVAL_STRINGL(cstr, jsValue->ToString()->Utf8Length());
	}
	else if (jsValue->IsBoolean())
	{
		RETVAL_BOOL(jsValue->Uint32Value());
	}
	else if (jsValue->IsInt32() || jsValue->IsUint32())
	{
		RETVAL_LONG((long) jsValue->IntegerValue());
	}
	else if (jsValue->IsNumber())
	{
		RETVAL_DOUBLE(jsValue->NumberValue());
	}
	else if (jsValue->IsDate())	/* Return as a PHP DateTime object */
	{
		v8::String::Utf8Value str(jsValue);
		const char *cstr = ToCString(str);

		/* cstr has two timezone specifications:
		 *
		 * example from Linux:
		 * Mon Sep 08 1975 09:00:00 GMT+0000 (UTC)
		 *
		 * example from Windows:
		 * Mon Sep 08 1975 11:00:00 GMT+0200 (W. Europe Daylight Time)
		 *
		 * ... problem is, that PHP can't parse the second timezone
		 * specification as returned by v8 running on Windows.  And as a
		 * matter of that fails due to inconsistent second timezone spec
		 */
		char *date_str = estrdup(cstr);
		char *paren_ptr = strchr(date_str, '(');

		if (paren_ptr != NULL) {
			*paren_ptr = 0;
		}

		zend_class_entry *ce = php_date_get_date_ce();
		php_date_instantiate(ce, return_value TSRMLS_CC);
		if (!php_date_initialize(Z_PHPDATE_P(return_value), date_str, strlen(date_str), NULL, NULL, 0 TSRMLS_CC)) {
			efree(date_str);
			return FAILURE;
		}

		efree(date_str);
	}
	else if (jsValue->IsObject())
	{
		v8::Local<v8::Object> self = jsValue->ToObject();

		// if this is a wrapped PHP object, then just unwrap it.
		if (self->InternalFieldCount() == 2) {
			zend_object *object = reinterpret_cast<zend_object *>(self->GetAlignedPointerFromInternalField(1));
			zval zval_object;
			ZVAL_OBJ(&zval_object, object);
			RETVAL_ZVAL(&zval_object, 1, 0);
			return SUCCESS;
		}

		if ((flags & V8JS_FLAG_FORCE_ARRAY && !jsValue->IsFunction()) || jsValue->IsArray()) {
			array_init(return_value);
			return v8js_get_properties_hash(jsValue, Z_ARRVAL_P(return_value), flags, isolate TSRMLS_CC);
		} else {
			v8js_v8object_create(return_value, jsValue, flags, isolate TSRMLS_CC);
			return SUCCESS;
		}
	}
	else /* types External, RegExp, Undefined and Null are considered NULL */
	{
		RETVAL_NULL();
	}

 	return SUCCESS;
}
/* }}} */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: t
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
<commit_msg>move #undef directives to the top of the file<commit_after>/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2016 The PHP Group                                |
  +----------------------------------------------------------------------+
  | http://www.opensource.org/licenses/mit-license.php  MIT License      |
  +----------------------------------------------------------------------+
  | Author: Jani Taskinen <jani.taskinen@iki.fi>                         |
  | Author: Patrick Reilly <preilly@php.net>                             |
  | Author: Stefan Siegl <stesie@php.net>                                |
  +----------------------------------------------------------------------+
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdexcept>
#include <limits>

#include "php_v8js_macros.h"
#include "v8js_object_export.h"
#include "v8js_v8object_class.h"
#include "v8js_v8.h"

extern "C" {
#include "php.h"
#include "ext/date/php_date.h"
#include "ext/standard/php_string.h"
#include "zend_interfaces.h"
#include "zend_closures.h"
}

/* On Windows there are max and min macros, which would clobber the
 * method names of std::numeric_limits< > otherwise. */
#undef max
#undef min

static int v8js_is_assoc_array(HashTable *myht TSRMLS_DC) /* {{{ */
{
	zend_string *key;
	ulong index, idx = 0;

	ZEND_HASH_FOREACH_KEY(myht, index, key) {
		if(key) {
			// HASH_KEY_IS_STRING
			return 1;
		}

		if(index != idx) {
			return 1;
		}

		idx ++;
	} ZEND_HASH_FOREACH_END();

	return 0;
}
/* }}} */

static v8::Handle<v8::Value> v8js_hash_to_jsarr(zval *value, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{
	HashTable *myht = HASH_OF(value);
	int i = myht ? zend_hash_num_elements(myht) : 0;

	/* Return object if dealing with assoc array */
	if (i > 0 && v8js_is_assoc_array(myht TSRMLS_CC)) {
		return v8js_hash_to_jsobj(value, isolate TSRMLS_CC);
	}

	v8::Local<v8::Array> newarr;

	/* Prevent recursion */
	if (myht && ZEND_HASH_GET_APPLY_COUNT(myht) > 1) {
		return V8JS_NULL;
	}

	newarr = v8::Array::New(isolate, i);

	if (i > 0)
	{
		zval *data;
		ulong index = 0;
		HashTable *tmp_ht;

		ZEND_HASH_FOREACH_VAL(myht, data) {
			tmp_ht = HASH_OF(data);

			if (tmp_ht) {
				ZEND_HASH_INC_APPLY_COUNT(myht);
			}

			newarr->Set(index++, zval_to_v8js(data, isolate TSRMLS_CC));

			if (tmp_ht) {
				ZEND_HASH_DEC_APPLY_COUNT(myht);
			}
		} ZEND_HASH_FOREACH_END();
	}
	return newarr;
}
/* }}} */

v8::Handle<v8::Value> zval_to_v8js(zval *value, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{
	v8::Handle<v8::Value> jsValue;
	zend_long v;
	zend_class_entry *ce;

	switch (Z_TYPE_P(value))
	{
		case IS_INDIRECT:
			jsValue = zval_to_v8js(Z_INDIRECT_P(value), isolate);
			break;

		case IS_REFERENCE:
			jsValue = zval_to_v8js(Z_REFVAL_P(value), isolate);
			break;

		case IS_ARRAY:
			jsValue = v8js_hash_to_jsarr(value, isolate TSRMLS_CC);
			break;

		case IS_OBJECT:
             if (V8JSG(use_date)) {
				 ce = php_date_get_date_ce();
				 if (instanceof_function(Z_OBJCE_P(value), ce TSRMLS_CC)) {
					 zval dtval;
					 zend_call_method_with_0_params(value, NULL, NULL, "getTimestamp", &dtval);
					 jsValue = V8JS_DATE(((double)Z_LVAL(dtval) * 1000.0));
					 zval_dtor(&dtval);
				 } else
					 jsValue = v8js_hash_to_jsobj(value, isolate TSRMLS_CC);
			 } else
				 jsValue = v8js_hash_to_jsobj(value, isolate TSRMLS_CC);
			break;

		case IS_STRING:
			jsValue = V8JS_ZSTR(Z_STR_P(value));
			break;

		case IS_LONG:
		    v = Z_LVAL_P(value);
			if (v < - std::numeric_limits<int32_t>::min() || v > std::numeric_limits<int32_t>::max()) {
				jsValue = V8JS_FLOAT(static_cast<double>(v));
			} else {
				jsValue = V8JS_INT(static_cast<int32_t>(v));
			}
			break;

		case IS_DOUBLE:
			jsValue = V8JS_FLOAT(Z_DVAL_P(value));
			break;

		case IS_TRUE:
			jsValue = V8JS_TRUE();
			break;

		case IS_FALSE:
			jsValue = V8JS_FALSE();
			break;

		case IS_NULL:
			jsValue = V8JS_NULL;
			break;

		case IS_UNDEF:
		default:
			/* undefined -> return v8::Value left empty */
			jsValue = v8::Undefined(isolate);
			break;
	}

	return jsValue;
}
/* }}} */

int v8js_to_zval(v8::Handle<v8::Value> jsValue, zval *return_value, int flags, v8::Isolate *isolate TSRMLS_DC) /* {{{ */
{
	if (jsValue->IsString())
	{
		v8::String::Utf8Value str(jsValue);
		const char *cstr = ToCString(str);
		RETVAL_STRINGL(cstr, jsValue->ToString()->Utf8Length());
	}
	else if (jsValue->IsBoolean())
	{
		RETVAL_BOOL(jsValue->Uint32Value());
	}
	else if (jsValue->IsInt32() || jsValue->IsUint32())
	{
		RETVAL_LONG((long) jsValue->IntegerValue());
	}
	else if (jsValue->IsNumber())
	{
		RETVAL_DOUBLE(jsValue->NumberValue());
	}
	else if (jsValue->IsDate())	/* Return as a PHP DateTime object */
	{
		v8::String::Utf8Value str(jsValue);
		const char *cstr = ToCString(str);

		/* cstr has two timezone specifications:
		 *
		 * example from Linux:
		 * Mon Sep 08 1975 09:00:00 GMT+0000 (UTC)
		 *
		 * example from Windows:
		 * Mon Sep 08 1975 11:00:00 GMT+0200 (W. Europe Daylight Time)
		 *
		 * ... problem is, that PHP can't parse the second timezone
		 * specification as returned by v8 running on Windows.  And as a
		 * matter of that fails due to inconsistent second timezone spec
		 */
		char *date_str = estrdup(cstr);
		char *paren_ptr = strchr(date_str, '(');

		if (paren_ptr != NULL) {
			*paren_ptr = 0;
		}

		zend_class_entry *ce = php_date_get_date_ce();
		php_date_instantiate(ce, return_value TSRMLS_CC);
		if (!php_date_initialize(Z_PHPDATE_P(return_value), date_str, strlen(date_str), NULL, NULL, 0 TSRMLS_CC)) {
			efree(date_str);
			return FAILURE;
		}

		efree(date_str);
	}
	else if (jsValue->IsObject())
	{
		v8::Local<v8::Object> self = jsValue->ToObject();

		// if this is a wrapped PHP object, then just unwrap it.
		if (self->InternalFieldCount() == 2) {
			zend_object *object = reinterpret_cast<zend_object *>(self->GetAlignedPointerFromInternalField(1));
			zval zval_object;
			ZVAL_OBJ(&zval_object, object);
			RETVAL_ZVAL(&zval_object, 1, 0);
			return SUCCESS;
		}

		if ((flags & V8JS_FLAG_FORCE_ARRAY && !jsValue->IsFunction()) || jsValue->IsArray()) {
			array_init(return_value);
			return v8js_get_properties_hash(jsValue, Z_ARRVAL_P(return_value), flags, isolate TSRMLS_CC);
		} else {
			v8js_v8object_create(return_value, jsValue, flags, isolate TSRMLS_CC);
			return SUCCESS;
		}
	}
	else /* types External, RegExp, Undefined and Null are considered NULL */
	{
		RETVAL_NULL();
	}

 	return SUCCESS;
}
/* }}} */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * indent-tabs-mode: t
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
<|endoftext|>


<commit_before>/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2012 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author: Jani Taskinen <jani.taskinen@iki.fi>                         |
  | Author: Patrick Reilly <preilly@php.net>                             |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

extern "C" {
#include "php.h"
}

#include "php_v8js_macros.h"
#include <v8.h>
#include <map>
#include <vector>

/* global.exit - terminate execution */
V8JS_METHOD(exit) /* {{{ */
{
	v8::V8::TerminateExecution();
	return v8::Undefined();
}
/* }}} */

/* global.sleep - sleep for passed seconds */
V8JS_METHOD(sleep) /* {{{ */
{
	php_sleep(args[0]->Int32Value());
	return v8::Undefined();
}
/* }}} */

/* global.print - php print() */
V8JS_METHOD(print) /* {{{ */
{
	int ret = 0;
	TSRMLS_FETCH();

	for (int i = 0; i < args.Length(); i++) {
		v8::String::Utf8Value str(args[i]);
		const char *cstr = ToCString(str);
		ret = PHPWRITE(cstr, strlen(cstr));
	}
	return V8JS_INT(ret);
}
/* }}} */

static void _php_v8js_dumper(v8::Local<v8::Value> var, int level TSRMLS_DC) /* {{{ */
{
	v8::String::Utf8Value str(var->ToDetailString());
	const char *valstr = ToCString(str);
	size_t valstr_len = (valstr) ? strlen(valstr) : 0;

	if (level > 1) {
		php_printf("%*c", (level - 1) * 2, ' ');
	}

	if (var->IsString())
	{
		php_printf("string(%d) \"%s\"\n", valstr_len, valstr);
	}
	else if (var->IsBoolean())
	{
		php_printf("bool(%s)\n", valstr);
	}
	else if (var->IsInt32() || var->IsUint32())
	{
		php_printf("int(%s)\n", valstr);
	}
	else if (var->IsNumber())
	{
		php_printf("float(%s)\n", valstr);
	}
	else if (var->IsDate())
	{
		php_printf("Date(%s)\n", valstr);
	}
#if PHP_V8_API_VERSION >= 2003007
	else if (var->IsRegExp())
	{
		php_printf("RegExp(%s)\n", valstr);
	}
#endif
	else if (var->IsArray())
	{
		v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(var);
		uint32_t length = array->Length();

		php_printf("array(%d) {\n", length);

		for (unsigned i = 0; i < length; i++) {
			php_printf("%*c[%d] =>\n", level * 2, ' ', i);
			_php_v8js_dumper(array->Get(i), level + 1 TSRMLS_CC);
		}

		if (level > 1) {
			php_printf("%*c", (level - 1) * 2, ' ');
		}

		ZEND_PUTS("}\n");
	}
	else if (var->IsObject())
	{
		v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(var);
		V8JS_GET_CLASS_NAME(cname, object);

		if (var->IsFunction())
		{
			v8::String::Utf8Value csource(object->ToString());
			php_printf("object(%s)#%d {\n%*c%s\n", ToCString(cname), object->GetIdentityHash(), level * 2 + 2, ' ', ToCString(csource));
		}
		else
		{
			v8::Local<v8::Array> keys = object->GetPropertyNames();
			uint32_t length = keys->Length();

			php_printf("object(%s)#%d (%d) {\n", ToCString(cname), object->GetIdentityHash(), length);

			for (unsigned i = 0; i < length; i++) {
				v8::Local<v8::String> key = keys->Get(i)->ToString();
				v8::String::Utf8Value kname(key);
				php_printf("%*c[\"%s\"] =>\n", level * 2, ' ', ToCString(kname));
				_php_v8js_dumper(object->Get(key), level + 1 TSRMLS_CC);
			}
		}

		if (level > 1) {
			php_printf("%*c", (level - 1) * 2, ' ');
		}

		ZEND_PUTS("}\n");
	}
	else /* null, undefined, etc. */
	{
		php_printf("<%s>\n", valstr);
	}
}
/* }}} */

/* global.var_dump - Dump JS values */
V8JS_METHOD(var_dump) /* {{{ */
{
	int i;
	TSRMLS_FETCH();

	for (int i = 0; i < args.Length(); i++) {
		_php_v8js_dumper(args[i], 1 TSRMLS_CC);
	}

	return V8JS_NULL;
}
/* }}} */

// TODO: Put this in php_v8js_context
std::map<char *, v8::Handle<v8::Object> > modules_loaded;
std::vector<char *> modules_stack;

V8JS_METHOD(require)
{
	v8::String::Utf8Value module_name_v8(args[0]);

	// Make sure to duplicate the module name string so it doesn't get freed by the V8 garbage collector
	char *module_name = strdup(ToCString(module_name_v8));

	// Check for module cyclic dependencies
	for (std::vector<char *>::iterator it = modules_stack.begin(); it != modules_stack.end(); ++it)
    {
    	if (!strcmp(*it, module_name)) {
    		return v8::ThrowException(v8::String::New("Module cyclic dependency"));
    	}
    }

    // If we have already loaded and cached this module then use it
	if (modules_loaded.count(module_name) > 0) {
		return modules_loaded[module_name];
	}

	// Get the extension context
	v8::Handle<v8::External> data = v8::Handle<v8::External>::Cast(args.Data());
	php_v8js_ctx *c = static_cast<php_v8js_ctx*>(data->Value());

	// Check that we have a module loader
	if (c->module_loader == NULL) {
		return v8::ThrowException(v8::String::New("No module loader"));
	}

	// Callback to PHP to load the module code

	zval module_code;
	zval *module_name_zend;

	MAKE_STD_ZVAL(module_name_zend);
	ZVAL_STRING(module_name_zend, module_name, 1);
	zval* params[] = { module_name_zend };

	if (FAILURE == call_user_function(EG(function_table), NULL, c->module_loader, &module_code, 1, params TSRMLS_CC)) {
		return v8::ThrowException(v8::String::New("Module loader callback failed"));
	}

	// Create a template for the global object and set the built-in global functions
	v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
	global->Set(v8::String::New("print"), v8::FunctionTemplate::New(V8JS_MN(print)), v8::ReadOnly);
	global->Set(v8::String::New("require"), v8::FunctionTemplate::New(V8JS_MN(require), v8::External::New(c)), v8::ReadOnly);

	// Add the exports object in which the module returns its API
	v8::Handle<v8::ObjectTemplate> exports_template = v8::ObjectTemplate::New();
	v8::Handle<v8::Object> exports = exports_template->NewInstance();
	global->Set(v8::String::New("exports"), exports);

	// Each module gets its own context so different modules do not affect each other
	v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);

	// Catch JS exceptions
	v8::TryCatch try_catch;

	// Enter the module context
	v8::Context::Scope scope(context);

	v8::HandleScope handle_scope;

	// Set script identifier
	v8::Local<v8::String> sname = V8JS_SYM("require");

	// TODO: Load module code here
	v8::Local<v8::String> source = v8::String::New(Z_STRVAL(module_code));

	// Create and compile script
	v8::Local<v8::Script> script = v8::Script::New(source, sname);

	// The script will be empty if there are compile errors
	if (script.IsEmpty()) {
		return v8::ThrowException(v8::String::New("Module script compile failed"));
	}

	// Add this module to the stack
	modules_stack.push_back(module_name);

	// Run script
	v8::Local<v8::Value> result = script->Run();

	// Remove this module from the stack
	modules_stack.pop_back();

	// Script possibly terminated, return immediately
	if (!try_catch.CanContinue()) {
		return v8::ThrowException(v8::String::New("Module script compile failed"));
	}

	// Handle runtime JS exceptions
	if (try_catch.HasCaught()) {

		// Rethrow the exception back to JS
		return try_catch.ReThrow();
	}

	// Cache the module so it doesn't need to be compiled and run again
	modules_loaded[module_name] = handle_scope.Close(exports);

	return modules_loaded[module_name];
}

void php_v8js_register_methods(v8::Handle<v8::ObjectTemplate> global, php_v8js_ctx *c) /* {{{ */
{
	global->Set(V8JS_SYM("exit"), v8::FunctionTemplate::New(V8JS_MN(exit)), v8::ReadOnly);
	global->Set(V8JS_SYM("sleep"), v8::FunctionTemplate::New(V8JS_MN(sleep)), v8::ReadOnly);
	global->Set(V8JS_SYM("print"), v8::FunctionTemplate::New(V8JS_MN(print)), v8::ReadOnly);
	global->Set(V8JS_SYM("var_dump"), v8::FunctionTemplate::New(V8JS_MN(var_dump)), v8::ReadOnly);

	global->Set(V8JS_SYM("require"), v8::FunctionTemplate::New(V8JS_MN(require), v8::External::New(c)), v8::ReadOnly);
}
/* }}} */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
<commit_msg>Normalisation of module identifier.<commit_after>/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2012 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author: Jani Taskinen <jani.taskinen@iki.fi>                         |
  | Author: Patrick Reilly <preilly@php.net>                             |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

extern "C" {
#include "php.h"
}

#include "php_v8js_macros.h"
#include <v8.h>
#include <map>
#include <vector>

/* global.exit - terminate execution */
V8JS_METHOD(exit) /* {{{ */
{
	v8::V8::TerminateExecution();
	return v8::Undefined();
}
/* }}} */

/* global.sleep - sleep for passed seconds */
V8JS_METHOD(sleep) /* {{{ */
{
	php_sleep(args[0]->Int32Value());
	return v8::Undefined();
}
/* }}} */

/* global.print - php print() */
V8JS_METHOD(print) /* {{{ */
{
	int ret = 0;
	TSRMLS_FETCH();

	for (int i = 0; i < args.Length(); i++) {
		v8::String::Utf8Value str(args[i]);
		const char *cstr = ToCString(str);
		ret = PHPWRITE(cstr, strlen(cstr));
	}
	return V8JS_INT(ret);
}
/* }}} */

static void _php_v8js_dumper(v8::Local<v8::Value> var, int level TSRMLS_DC) /* {{{ */
{
	v8::String::Utf8Value str(var->ToDetailString());
	const char *valstr = ToCString(str);
	size_t valstr_len = (valstr) ? strlen(valstr) : 0;

	if (level > 1) {
		php_printf("%*c", (level - 1) * 2, ' ');
	}

	if (var->IsString())
	{
		php_printf("string(%d) \"%s\"\n", valstr_len, valstr);
	}
	else if (var->IsBoolean())
	{
		php_printf("bool(%s)\n", valstr);
	}
	else if (var->IsInt32() || var->IsUint32())
	{
		php_printf("int(%s)\n", valstr);
	}
	else if (var->IsNumber())
	{
		php_printf("float(%s)\n", valstr);
	}
	else if (var->IsDate())
	{
		php_printf("Date(%s)\n", valstr);
	}
#if PHP_V8_API_VERSION >= 2003007
	else if (var->IsRegExp())
	{
		php_printf("RegExp(%s)\n", valstr);
	}
#endif
	else if (var->IsArray())
	{
		v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(var);
		uint32_t length = array->Length();

		php_printf("array(%d) {\n", length);

		for (unsigned i = 0; i < length; i++) {
			php_printf("%*c[%d] =>\n", level * 2, ' ', i);
			_php_v8js_dumper(array->Get(i), level + 1 TSRMLS_CC);
		}

		if (level > 1) {
			php_printf("%*c", (level - 1) * 2, ' ');
		}

		ZEND_PUTS("}\n");
	}
	else if (var->IsObject())
	{
		v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(var);
		V8JS_GET_CLASS_NAME(cname, object);

		if (var->IsFunction())
		{
			v8::String::Utf8Value csource(object->ToString());
			php_printf("object(%s)#%d {\n%*c%s\n", ToCString(cname), object->GetIdentityHash(), level * 2 + 2, ' ', ToCString(csource));
		}
		else
		{
			v8::Local<v8::Array> keys = object->GetPropertyNames();
			uint32_t length = keys->Length();

			php_printf("object(%s)#%d (%d) {\n", ToCString(cname), object->GetIdentityHash(), length);

			for (unsigned i = 0; i < length; i++) {
				v8::Local<v8::String> key = keys->Get(i)->ToString();
				v8::String::Utf8Value kname(key);
				php_printf("%*c[\"%s\"] =>\n", level * 2, ' ', ToCString(kname));
				_php_v8js_dumper(object->Get(key), level + 1 TSRMLS_CC);
			}
		}

		if (level > 1) {
			php_printf("%*c", (level - 1) * 2, ' ');
		}

		ZEND_PUTS("}\n");
	}
	else /* null, undefined, etc. */
	{
		php_printf("<%s>\n", valstr);
	}
}
/* }}} */

/* global.var_dump - Dump JS values */
V8JS_METHOD(var_dump) /* {{{ */
{
	int i;
	TSRMLS_FETCH();

	for (int i = 0; i < args.Length(); i++) {
		_php_v8js_dumper(args[i], 1 TSRMLS_CC);
	}

	return V8JS_NULL;
}
/* }}} */

// TODO: Put this in php_v8js_context
std::map<char *, v8::Handle<v8::Object> > modules_loaded;
std::vector<char *> modules_stack;

void split_terms(char *identifier, std::vector<char *> &terms)
{
	char *term = (char *)malloc(PATH_MAX), *ptr = term;

	// Initialise the term string
	*term = 0;

	while (*identifier > 0) {
		if (*identifier == '/') {
			if (strlen(term) > 0) {
				// Terminate term string and add to terms vector
				*ptr++ = 0;
				terms.push_back(strdup(term));

				// Reset term string
				memset(term, 0, strlen(term));
				ptr = term;
			}
		} else {
			*ptr++ = *identifier;
		}

		identifier++;
	}

	if (strlen(term) > 0) {
		// Terminate term string and add to terms vector
		*ptr++ = 0;
		terms.push_back(strdup(term));
	}

	if (term > 0) {
		free(term);
	}
}

void normalize_identifier(char *identifier, char *normalised)
{
	std::vector<char *> terms;
	split_terms(identifier, terms);

	std::vector<char *> normalised_terms;

	for (std::vector<char *>::iterator it = terms.begin(); it != terms.end(); it++) {
		char *term = *it;

		if (!strcmp(term, "..")) {
			normalised_terms.pop_back();
		} else if (strcmp(term, ".")) {
			normalised_terms.push_back(term);
		}
	}

	// Initialise the normalised string
	*normalised = 0;

	for (std::vector<char *>::iterator it = normalised_terms.begin(); it != normalised_terms.end(); it++) {
		char *term = *it;

		if (strlen(normalised) > 0) {
			strcat(normalised, "/");
		}

		strcat(normalised, term);
	}
}

V8JS_METHOD(require)
{
	v8::String::Utf8Value module_name_v8(args[0]);

	// Make sure to duplicate the module name string so it doesn't get freed by the V8 garbage collector
	char *module_name = strdup(ToCString(module_name_v8));
	char *normalised_module_identifier = (char *)malloc(strlen(module_name));

	normalize_identifier(module_name, normalised_module_identifier);

	// Check for module cyclic dependencies
	for (std::vector<char *>::iterator it = modules_stack.begin(); it != modules_stack.end(); ++it)
    {
    	if (!strcmp(*it, normalised_module_identifier)) {
    		return v8::ThrowException(v8::String::New("Module cyclic dependency"));
    	}
    }

    // If we have already loaded and cached this module then use it
	if (modules_loaded.count(normalised_module_identifier) > 0) {
		return modules_loaded[normalised_module_identifier];
	}

	// Get the extension context
	v8::Handle<v8::External> data = v8::Handle<v8::External>::Cast(args.Data());
	php_v8js_ctx *c = static_cast<php_v8js_ctx*>(data->Value());

	// Check that we have a module loader
	if (c->module_loader == NULL) {
		return v8::ThrowException(v8::String::New("No module loader"));
	}

	// Callback to PHP to load the module code

	zval module_code;
	zval *module_name_zend;

	MAKE_STD_ZVAL(module_name_zend);
	ZVAL_STRING(module_name_zend, normalised_module_identifier, 1);
	zval* params[] = { module_name_zend };

	if (FAILURE == call_user_function(EG(function_table), NULL, c->module_loader, &module_code, 1, params TSRMLS_CC)) {
		return v8::ThrowException(v8::String::New("Module loader callback failed"));
	}

	// Convert the return value to string
	if (Z_TYPE(module_code) != IS_STRING) {
    	convert_to_string(&module_code);
	}

	// Check that some code has been returned
	if (!strlen(Z_STRVAL(module_code))) {
		return v8::ThrowException(v8::String::New("Module loader callback did not return code"));
	}

	// Create a template for the global object and set the built-in global functions
	v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
	global->Set(v8::String::New("print"), v8::FunctionTemplate::New(V8JS_MN(print)), v8::ReadOnly);
	global->Set(v8::String::New("require"), v8::FunctionTemplate::New(V8JS_MN(require), v8::External::New(c)), v8::ReadOnly);

	// Add the exports object in which the module returns its API
	v8::Handle<v8::ObjectTemplate> exports_template = v8::ObjectTemplate::New();
	v8::Handle<v8::Object> exports = exports_template->NewInstance();
	global->Set(v8::String::New("exports"), exports);

	// Each module gets its own context so different modules do not affect each other
	v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);

	// Catch JS exceptions
	v8::TryCatch try_catch;

	// Enter the module context
	v8::Context::Scope scope(context);

	v8::HandleScope handle_scope;

	// Set script identifier
	v8::Local<v8::String> sname = V8JS_SYM("require");

	v8::Local<v8::String> source = v8::String::New(Z_STRVAL(module_code));

	// Create and compile script
	v8::Local<v8::Script> script = v8::Script::New(source, sname);

	// The script will be empty if there are compile errors
	if (script.IsEmpty()) {
		return v8::ThrowException(v8::String::New("Module script compile failed"));
	}

	// Add this module to the stack
	modules_stack.push_back(normalised_module_identifier);

	// Run script
	v8::Local<v8::Value> result = script->Run();

	// Remove this module from the stack
	modules_stack.pop_back();

	// Script possibly terminated, return immediately
	if (!try_catch.CanContinue()) {
		return v8::ThrowException(v8::String::New("Module script compile failed"));
	}

	// Handle runtime JS exceptions
	if (try_catch.HasCaught()) {

		// Rethrow the exception back to JS
		return try_catch.ReThrow();
	}

	// Cache the module so it doesn't need to be compiled and run again
	modules_loaded[normalised_module_identifier] = handle_scope.Close(exports);

	return modules_loaded[normalised_module_identifier];
}

void php_v8js_register_methods(v8::Handle<v8::ObjectTemplate> global, php_v8js_ctx *c) /* {{{ */
{
	global->Set(V8JS_SYM("exit"), v8::FunctionTemplate::New(V8JS_MN(exit)), v8::ReadOnly);
	global->Set(V8JS_SYM("sleep"), v8::FunctionTemplate::New(V8JS_MN(sleep)), v8::ReadOnly);
	global->Set(V8JS_SYM("print"), v8::FunctionTemplate::New(V8JS_MN(print)), v8::ReadOnly);
	global->Set(V8JS_SYM("var_dump"), v8::FunctionTemplate::New(V8JS_MN(var_dump)), v8::ReadOnly);

	global->Set(V8JS_SYM("require"), v8::FunctionTemplate::New(V8JS_MN(require), v8::External::New(c)), v8::ReadOnly);
}
/* }}} */

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
<|endoftext|>


<commit_before>#include "ai.h"

AI::AI(int player_id) {
	m_player_id = player_id;

	return;
}

void AI::init() {

	return;
}

bool AI::run() {
	// Spawn something
	spawn();

	// Cycle through units
	for(Unit &u : units) {
		// If they're ours
		if(u.player_id() == PlayerID()) {
			// Move them to the right one
			u.move(u.x() + 1, u.y());
		}
	}
	return true;
}

void AI::end() {
	if(PlayerID() == 1) {
		for(Unit u : units) {
			std::cout << u.DebugString() << std::endl;
		}
	}
	return;
}

void AI::spawn(int x, int y, int type) {
	Unit u = Unit(x, y, type, AI::m_player_id);
	units.push_back(u);

	return;
}

int AI::PlayerID() {
	return m_player_id;
}

int AI::TurnNumber() {
	return BaseAI::m_turn_number;
}<commit_msg>Ampersand.<commit_after>#include "ai.h"

AI::AI(int player_id) {
	m_player_id = player_id;

	return;
}

void AI::init() {

	return;
}

bool AI::run() {
	// Spawn something
	spawn();

	// Cycle through units
	for(Unit &u : units) {
		// If they're ours
		if(u.player_id() == PlayerID()) {
			// Move them to the right one
			u.move(u.x() + 1, u.y());
		}
	}
	return true;
}

void AI::end() {
	if(PlayerID() == 1) {
		for(Unit &u : units) {
			std::cout << u.DebugString() << std::endl;
		}
	}
	return;
}

void AI::spawn(int x, int y, int type) {
	Unit u = Unit(x, y, type, AI::m_player_id);
	units.push_back(u);

	return;
}

int AI::PlayerID() {
	return m_player_id;
}

int AI::TurnNumber() {
	return BaseAI::m_turn_number;
}<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the tools applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "tools.h"

#include <QDir>
#include <QFile>
#include <QByteArray>

// std stuff ------------------------------------
#include <iostream>
#include <windows.h>
#include <conio.h>
#define NUMBER_OF_PARTS 7

std::ostream &operator<<(std::ostream &s, const QString &val); // defined in configureapp.cpp
using namespace std;

void Tools::checkLicense(QMap<QString,QString> &dictionary, QMap<QString,QString> &licenseInfo,
                         const QString &path)
{
    if (dictionary[ "BUILDNOKIA" ] == "yes") {
        dictionary["EDITION"] = "NokiaInternalBuild";
        dictionary["LICENSE_FILE"] = ""; // No License for nokia developers
        dictionary["QT_EDITION"] = "QT_EDITION_OPENSOURCE";
        return; // No license key checking in internal builds
    }

    QString tpLicense = dictionary["QT_SOURCE_TREE"] + "/LICENSE.PREVIEW.OPENSOURCE";
    if (QFile::exists(tpLicense)) {
        dictionary["EDITION"] = "Preview";
        dictionary["LICENSE FILE"] = tpLicense;
        dictionary["QT_EDITION"] = "QT_EDITION_OPENSOURCE";
        return; // No license key checking in Tech Preview
    }
    tpLicense = dictionary["QT_SOURCE_TREE"] + "/LICENSE.PREVIEW.COMMERCIAL";
    if (QFile::exists(tpLicense)) {
        dictionary["EDITION"] = "Preview";
        dictionary["LICENSE FILE"] = tpLicense;
        dictionary["QT_EDITION"] = "QT_EDITION_DESKTOP";
        return; // No license key checking in Tech Preview
    }

    // Read in the license file
    QFile licenseFile(path);
    if( !path.isEmpty() && licenseFile.open( QFile::ReadOnly ) ) {
        cout << "Reading license file in....." << qPrintable(path) << endl;

        QString buffer = licenseFile.readLine(1024);
        while (!buffer.isEmpty()) {
            if( buffer[ 0 ] != '#' ) {
                QStringList components = buffer.split( '=' );
                if ( components.size() >= 2 ) {
                    QStringList::Iterator it = components.begin();
                    QString key = (*it++).trimmed().replace( "\"", QString() ).toUpper();
                    QString value = (*it++).trimmed().replace( "\"", QString() );
                    licenseInfo[ key ] = value;
                }
            }
            // read next line
            buffer = licenseFile.readLine(1024);
        }
        licenseFile.close();
    } else {
        cout << "License file not found in " << QDir::homePath() << endl;
        cout << "Please put the Qt license file, '.qt-license' in your home "
             << "directory and run configure again.";
        dictionary["DONE"] = "error";
        return;
    }

    // Verify license info...
    QString licenseKey = licenseInfo["LICENSEKEYEXT"];
    const char * clicenseKey = licenseKey.toLatin1();
    //We check the licence
#ifndef _WIN32_WCE
        char *buffer = strdup(clicenseKey);
#else
        char *buffer = (char*) malloc(strlen(clicenseKey) + 1);
        strcpy(buffer, clicenseKey);
#endif
    static const char * const SEP = "-";
    char *licenseParts[NUMBER_OF_PARTS];
    int partNumber = 0;
    for (char *part = strtok(buffer, SEP); part != 0; part = strtok(0, SEP))
        licenseParts[partNumber++] = part;
    if (partNumber < (NUMBER_OF_PARTS-1)) {
        dictionary["DONE"] = "error";
        cout << "License file does not contain proper license key." <<partNumber<< endl;
        free(buffer);
        return;
    }

    char products = licenseParts[0][0];
    char platforms = licenseParts[1][0];
    char* licenseSchema = licenseParts[2];
    char licenseFeatures = licenseParts[3][0];

    // Determine edition ---------------------------------------------------------------------------
    QString licenseType;
    if (strcmp(licenseSchema,"F4M") == 0) {
        licenseType = "Commercial";
        if (products == 'F') {
            dictionary["EDITION"] = "Universal";
            dictionary["QT_EDITION"] = "QT_EDITION_UNIVERSAL";
        } else if (products == 'B') {
            dictionary["EDITION"] = "FullFramework";
            dictionary["QT_EDITION"] = "QT_EDITION_DESKTOP";
        } else {
            dictionary["EDITION"] = "GUIFramework";
            dictionary["QT_EDITION"] = "QT_EDITION_DESKTOPLIGHT";
        }

        if (platforms == 'X') {
            dictionary["LICENSE_EXTENSION"] = "-ALLOS";
        } else if (strchr("2346789ABCDEGHJKMPQSTUVWX", platforms)) {
            dictionary["LICENSE_EXTENSION"] = "-EMBEDDED";
        } else if (strchr("4BFPQRTY", platforms)) {
            dictionary["LICENSE_EXTENSION"] = "-DESKTOP";
        }
    } else if (strcmp(licenseSchema,"Z4M") == 0 || strcmp(licenseSchema,"R4M") == 0 || strcmp(licenseSchema,"Q4M") == 0) {
        if (products == 'B') {
            dictionary["EDITION"] = "Evaluation";
            dictionary["QT_EDITION"] = "QT_EDITION_EVALUATION";
            dictionary["LICENSE_EXTENSION"] = "-EVALUATION";
        }
    }

    if (QFile::exists(dictionary["QT_SOURCE_TREE"] + "/.LICENSE")) {
        // Generic, no-suffix license
        dictionary["LICENSE_EXTENSION"] = QString();
    } else if (dictionary["LICENSE_EXTENSION"].isEmpty()) {
        cout << "License file does not contain proper license key." << endl;
        dictionary["DONE"] = "error";
    }
    if (licenseType.isEmpty()
        || dictionary["EDITION"].isEmpty()
        || dictionary["QT_EDITION"].isEmpty()) {
        cout << "License file does not contain proper license key." << endl;
        dictionary["DONE"] = "error";
        return;
    }

    if (dictionary["PLATFORM NAME"].contains("Windows CE")) {
        // verify that we are licensed to use Qt for Windows CE
        if (dictionary["LICENSE_EXTENSION"] != "-EMBEDDED" && dictionary["LICENSE_EXTENSION"] != "-ALLOS") {
            cout << "You are not licensed for the " << dictionary["PLATFORM NAME"] << " platform." << endl << endl;
            cout << "Please contact qt-info@nokia.com to upgrade your license" << endl;
            cout << "to include the " << dictionary["PLATFORM NAME"] << " platform, or install the" << endl;
            cout << "Qt Open Source Edition if you intend to develop free software." << endl;
            dictionary["DONE"] = "error";
            return;
        }
    }

    // copy one of .LICENSE-*(-US) to LICENSE
    QString toLicenseFile   = dictionary["QT_SOURCE_TREE"] + "/LICENSE";
    QString fromLicenseFile = dictionary["QT_SOURCE_TREE"] + "/.LICENSE" + dictionary["LICENSE_EXTENSION"];
    if (licenseFeatures == 'G') //US
        fromLicenseFile += "-US";

    if (licenseFeatures == '5') //Floating
        dictionary["METERED LICENSE"] = "true";

    if (!CopyFile((wchar_t*)QDir::toNativeSeparators(fromLicenseFile).utf16(),
        (wchar_t*)QDir::toNativeSeparators(toLicenseFile).utf16(), FALSE)) {
        cout << "Failed to copy license file (" << fromLicenseFile << ")";
        dictionary["DONE"] = "error";
        return;
    }
    dictionary["LICENSE FILE"] = toLicenseFile;
    free(buffer);
}

<commit_msg>configure.exe: Update to the new licensing structure.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the tools applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "tools.h"

#include <QDir>
#include <QFile>
#include <QByteArray>

// std stuff ------------------------------------
#include <iostream>
#include <windows.h>
#include <conio.h>
#define NUMBER_OF_PARTS 7

std::ostream &operator<<(std::ostream &s, const QString &val); // defined in configureapp.cpp
using namespace std;

void Tools::checkLicense(QMap<QString,QString> &dictionary, QMap<QString,QString> &licenseInfo,
                         const QString &path)
{
    if (dictionary[ "BUILDNOKIA" ] == "yes") {
        dictionary["EDITION"] = "NokiaInternalBuild";
        dictionary["LICENSE_FILE"] = ""; // No License for nokia developers
        dictionary["QT_EDITION"] = "QT_EDITION_OPENSOURCE";
        return; // No license key checking in internal builds
    }

    QString tpLicense = dictionary["QT_SOURCE_TREE"] + "/LICENSE.PREVIEW.OPENSOURCE";
    if (QFile::exists(tpLicense)) {
        dictionary["EDITION"] = "Preview";
        dictionary["LICENSE FILE"] = tpLicense;
        dictionary["QT_EDITION"] = "QT_EDITION_OPENSOURCE";
        return; // No license key checking in Tech Preview
    }
    tpLicense = dictionary["QT_SOURCE_TREE"] + "/LICENSE.PREVIEW.COMMERCIAL";
    if (QFile::exists(tpLicense)) {
        dictionary["EDITION"] = "Preview";
        dictionary["LICENSE FILE"] = tpLicense;
        dictionary["QT_EDITION"] = "QT_EDITION_DESKTOP";
        return; // No license key checking in Tech Preview
    }

    // Read in the license file
    QFile licenseFile(path);
    if( !path.isEmpty() && licenseFile.open( QFile::ReadOnly ) ) {
        cout << "Reading license file in....." << qPrintable(path) << endl;

        QString buffer = licenseFile.readLine(1024);
        while (!buffer.isEmpty()) {
            if( buffer[ 0 ] != '#' ) {
                QStringList components = buffer.split( '=' );
                if ( components.size() >= 2 ) {
                    QStringList::Iterator it = components.begin();
                    QString key = (*it++).trimmed().replace( "\"", QString() ).toUpper();
                    QString value = (*it++).trimmed().replace( "\"", QString() );
                    licenseInfo[ key ] = value;
                }
            }
            // read next line
            buffer = licenseFile.readLine(1024);
        }
        licenseFile.close();
    } else {
        cout << "License file not found in " << QDir::homePath() << endl;
        cout << "Please put the Qt license file, '.qt-license' in your home "
             << "directory and run configure again.";
        dictionary["DONE"] = "error";
        return;
    }

    // Verify license info...
    QString licenseKey = licenseInfo["LICENSEKEYEXT"];
    const char * clicenseKey = licenseKey.toLatin1();
    //We check the licence
#ifndef _WIN32_WCE
        char *buffer = strdup(clicenseKey);
#else
        char *buffer = (char*) malloc(strlen(clicenseKey) + 1);
        strcpy(buffer, clicenseKey);
#endif
    static const char * const SEP = "-";
    char *licenseParts[NUMBER_OF_PARTS];
    int partNumber = 0;
    for (char *part = strtok(buffer, SEP); part != 0; part = strtok(0, SEP))
        licenseParts[partNumber++] = part;
    if (partNumber < (NUMBER_OF_PARTS-1)) {
        dictionary["DONE"] = "error";
        cout << "License file does not contain proper license key." <<partNumber<< endl;
        free(buffer);
        return;
    }

    char products = licenseParts[0][0];
    char* platforms = licenseParts[1];
    char* licenseSchema = licenseParts[2];
    char licenseFeatures = licenseParts[3][0];

    // Determine edition ---------------------------------------------------------------------------
    QString licenseType;
    if (strcmp(licenseSchema,"F4M") == 0) {
        licenseType = "Commercial";
        if (products == 'F') {
            dictionary["EDITION"] = "Universal";
            dictionary["QT_EDITION"] = "QT_EDITION_UNIVERSAL";
        } else if (products == 'B') {
            dictionary["EDITION"] = "FullFramework";
            dictionary["QT_EDITION"] = "QT_EDITION_DESKTOP";
        } else {
            dictionary["EDITION"] = "GUIFramework";
            dictionary["QT_EDITION"] = "QT_EDITION_DESKTOPLIGHT";
        }
    } else if (strcmp(licenseSchema,"Z4M") == 0 || strcmp(licenseSchema,"R4M") == 0 || strcmp(licenseSchema,"Q4M") == 0) {
        if (products == 'B') {
            dictionary["EDITION"] = "Evaluation";
            dictionary["QT_EDITION"] = "QT_EDITION_EVALUATION";
        }
    }

    if (platforms[2] == 'L') {
        static const char src[] = "8NPQRTZ";
        static const char dst[] = "UCWX9M7";
        const char *p = strchr(src, platforms[1]);
        platforms[1] = dst + (p - src);
    }

#define PL(a,b) (int(a)+int(b)*256)
    int platformCode = PL(platforms[0],platforms[1]);
    switch (platformCode) {
    case PL('X','9'):
    case PL('X','C'):
    case PL('X','U'):
    case PL('X','W'):
        dictionary["LICENSE_EXTENSION"] = "-ALLOS";
        break;
    case PL('6', 'M'):
    case PL('8', 'M'):
    case PL('N', '7'):
    case PL('N', '9'):
    case PL('N', 'X'):
    case PL('S', '9'):
    case PL('S', 'C'):
    case PL('S', 'U'):
    case PL('S', 'W'):
        dictionary["LICENSE_EXTENSION"] = "-EMBEDDED";
        if (dictionary["PLATFORM NAME"].contains("Windows CE")
            && platformCode != PL('6', 'M') && platformCode != PL('S', '9')
            && platformCode != PL('S', 'C') && platformCode != PL('S', 'U')
            && platformCode != PL('S', 'W')) {
            dictionary["DONE"] = "error";
        } else if (dictionary["PLATFORM NAME"].contains("Symbian")
                   && platformCode != PL('N', '9') && platformCode != PL('S', '9,')
                   && platformCode != PL('S', 'C') && platformCode != PL('S', 'UCWX9M7')
                   && platformCode != PL('S', 'W')) {
            dictionary["DONE"] = "error";
        }
        break;
    case PL('R', 'M'):
    case PL('F', 'M'):
        dictionary["LICENSE_EXTENSION"] = "-DESKTOP";
        if (!dictionary["PLATFORM NAME"].endsWith("Windows")) {
            dictionary["DONE"] = "error";
        }
        break;
    default:
        dictionary["DONE"] = "error";
        return;
    }
#undef PL

    if (dictionary.value("DONE") == "error") {
        cout << "You are not licensed for the " << dictionary["PLATFORM NAME"] << " platform." << endl << endl;
        cout << "Please contact qt-info@nokia.com to upgrade your license" << endl;
        cout << "to include the " << dictionary["PLATFORM NAME"] << " platform, or install the" << endl;
        cout << "Qt Open Source Edition if you intend to develop free software." << endl;
        return;
    }

    // Override for evaluation licenses
    if (dictionary["Edition"] == "Evaluation")
        dictionary["LICENSE_EXTENSION"] = "-EVALUATION";

    if (QFile::exists(dictionary["QT_SOURCE_TREE"] + "/.LICENSE")) {
        // Generic, no-suffix license
        dictionary["LICENSE_EXTENSION"] = QString();
    } else if (dictionary["LICENSE_EXTENSION"].isEmpty()) {
        cout << "License file does not contain proper license key." << endl;
        dictionary["DONE"] = "error";
    }
    if (licenseType.isEmpty()
        || dictionary["EDITION"].isEmpty()
        || dictionary["QT_EDITION"].isEmpty()) {
        cout << "License file does not contain proper license key." << endl;
        dictionary["DONE"] = "error";
        return;
    }

    // copy one of .LICENSE-*(-US) to LICENSE
    QString toLicenseFile   = dictionary["QT_SOURCE_TREE"] + "/LICENSE";
    QString fromLicenseFile = dictionary["QT_SOURCE_TREE"] + "/.LICENSE" + dictionary["LICENSE_EXTENSION"];
    if (licenseFeatures == 'B' || licenseFeatures == 'G'
        || licenseFeatures == 'L' || licenseFeatures == 'Y')
        fromLicenseFile += "-US";

    if (!CopyFile((wchar_t*)QDir::toNativeSeparators(fromLicenseFile).utf16(),
        (wchar_t*)QDir::toNativeSeparators(toLicenseFile).utf16(), FALSE)) {
        cout << "Failed to copy license file (" << fromLicenseFile << ")";
        dictionary["DONE"] = "error";
        return;
    }
    dictionary["LICENSE FILE"] = toLicenseFile;
    free(buffer);
}

<|endoftext|>