<commit_before>/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of signon
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Aurel Popirtac <mailto:ext-Aurel.Popirtac@nokia.com>
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include "credentialsaccessmanager.h"

#include "signond-common.h"

#include <QFile>
#include <QBuffer>

#define RETURN_IF_NOT_INITIALIZED(return_value)                  \
    do {                                                         \
        if (!m_isInitialized) {                                  \
            m_error = NotInitialized;                            \
            TRACE() << "CredentialsAccessManager not initialized."; \
            return return_value;                                \
        }                                                       \
    } while (0)

using namespace SignonDaemonNS;

/* ---------------------- CAMConfiguration ---------------------- */

CAMConfiguration::CAMConfiguration()
        : m_dbName(QLatin1String(signonDefaultDbName)),
          m_useEncryption(signonDefaultUseEncryption),
          m_dbFileSystemPath(
                QLatin1String(signonDefaultStoragePath)
                + QDir::separator()
                + QLatin1String(signonDefaultFileSystemName)),
          m_fileSystemType(QLatin1String(signonDefaultFileSystemType)),
          m_fileSystemSize(signonMinumumDbSize),
          m_encryptionPassphrase(QByteArray())
{}

void CAMConfiguration::serialize(QIODevice *device)
{
    if (device == NULL)
        return;

    if (!device->open(QIODevice::ReadWrite)) {
        return;
    }

    QString buffer;
    QTextStream stream(&buffer);
    stream << "\n\n====== Credentials Access Manager Configuration ======\n\n";
    stream << "File system mount name " << m_dbFileSystemPath << '\n';
    stream << "File system format: " << m_fileSystemType << '\n';
    stream << "File system size:" << m_fileSystemSize << "megabytes\n";

    const char *usingEncryption = m_useEncryption ? "true" : "false";
    stream << "Using encryption: " << usingEncryption << '\n';
    stream << "Credentials database name: " << m_dbName << '\n';
    stream << "======================================================\n\n";
    device->write(buffer.toUtf8());
    device->close();
}

/* ---------------------- CredentialsAccessManager ---------------------- */

CredentialsAccessManager *CredentialsAccessManager::m_pInstance = NULL;

CredentialsAccessManager::CredentialsAccessManager(QObject *parent)
        : QObject(parent),
          m_isInitialized(false),
          m_accessCodeFetched(false),
          m_systemOpened(false),
          m_error(NoError),
          keyManagers(),
          m_pCredentialsDB(NULL),
          m_pCryptoFileSystemManager(NULL),
          m_CAMConfiguration(CAMConfiguration())
{
}

CredentialsAccessManager::~CredentialsAccessManager()
{
    closeCredentialsSystem();

    m_pInstance = NULL;
}

CredentialsAccessManager *CredentialsAccessManager::instance(QObject *parent)
{
    if (!m_pInstance)
        m_pInstance = new CredentialsAccessManager(parent);

    return m_pInstance;
}

void CredentialsAccessManager::finalize()
{
    if (m_systemOpened)
        closeCredentialsSystem();

    if (m_pCryptoFileSystemManager)
        delete m_pCryptoFileSystemManager;

    m_accessCodeFetched = false;
    m_isInitialized = false;
    m_error = NoError;
}

bool CredentialsAccessManager::init(const CAMConfiguration &camConfiguration)
{
    if (m_isInitialized) {
        TRACE() << "CAM already initialized.";
        m_error = AlreadyInitialized;
        return false;
    }

    m_CAMConfiguration = camConfiguration;

    QBuffer config;
    m_CAMConfiguration.serialize(&config);
    TRACE() << "\n\nInitualizing CredentialsAccessManager with configuration: " << config.data();

    if (m_CAMConfiguration.m_useEncryption) {
        //Initialize CryptoManager
        m_pCryptoFileSystemManager = new CryptoManager(this);
        m_pCryptoFileSystemManager->setFileSystemPath(m_CAMConfiguration.m_dbFileSystemPath);
        m_pCryptoFileSystemManager->setFileSystemSize(m_CAMConfiguration.m_fileSystemSize);
        m_pCryptoFileSystemManager->setFileSystemType(m_CAMConfiguration.m_fileSystemType);

        //If passphrase exists (device lock code) open creds system - sync
        if (!m_CAMConfiguration.m_encryptionPassphrase.isEmpty()) {

            m_pCryptoFileSystemManager->setEncryptionKey(
                    m_CAMConfiguration.m_encryptionPassphrase);
            m_accessCodeFetched = true;

            if (!openCredentialsSystemPriv(true)) {
                BLAME() << "Failed to open credentials system. Fallback to alternative methods.";
            }
        }

        // Initialize all key managers
        foreach (SignOn::AbstractKeyManager *keyManager, keyManagers) {
            connect(keyManager,
                    SIGNAL(keyInserted(const SignOn::Key)),
                    SLOT(onKeyInserted(const SignOn::Key)));
            connect(keyManager,
                    SIGNAL(keyDisabled(const SignOn::Key)),
                    SLOT(onKeyDisabled(const SignOn::Key)));
            connect(keyManager,
                    SIGNAL(keyRemoved(const SignOn::Key)),
                    SLOT(onKeyRemoved(const SignOn::Key)));
            connect(keyManager,
                    SIGNAL(keyAuthorized(const SignOn::Key, bool)),
                    SLOT(onKeyAuthorized(const SignOn::Key, bool)));
            keyManager->setup();
        }
    }

    m_isInitialized = true;
    m_error = NoError;

    TRACE() << "CredentialsAccessManager successfully initialized...";
    return true;
}

void CredentialsAccessManager::addKeyManager(
    SignOn::AbstractKeyManager *keyManager)
{
    keyManagers.append(keyManager);
}

bool CredentialsAccessManager::openCredentialsSystemPriv(bool mountFileSystem)
{
    //todo remove this variable after LUKS implementation becomes stable.
    QString dbPath;

    if (m_CAMConfiguration.m_useEncryption) {
        dbPath = m_pCryptoFileSystemManager->fileSystemMountPath()
            + QDir::separator()
            + m_CAMConfiguration.m_dbName;

        if (mountFileSystem) {
            if (!fileSystemDeployed()) {
                if (deployCredentialsSystem()) {
                    if (openDB(dbPath))
                        m_systemOpened = true;
                }
                return m_systemOpened;
            }

            if (fileSystemLoaded()) {
                m_error = CredentialsDbAlreadyDeployed;
                return false;
            }

            if (!m_pCryptoFileSystemManager->mountFileSystem()) {
                m_error = CredentialsDbMountFailed;
                return false;
            }
        }
    } else {
        QFileInfo fInfo(m_CAMConfiguration.m_dbFileSystemPath);
        QDir storageDir = fInfo.dir();
        if (!storageDir.exists()) {
            if (!storageDir.mkpath(storageDir.path()))
                BLAME() << "Could not create storage directory!!!";
        }

        dbPath = storageDir.path()
                 + QDir::separator()
                 + m_CAMConfiguration.m_dbName;
    }

    TRACE() << "Database name: [" << dbPath << "]";

    if (openDB(dbPath)) {
        m_systemOpened = true;
        m_error = NoError;
    }

    return m_systemOpened;
}

bool CredentialsAccessManager::openCredentialsSystem()
{
    RETURN_IF_NOT_INITIALIZED(false);

    if (m_CAMConfiguration.m_useEncryption && !m_accessCodeFetched) {
        m_error = AccessCodeNotReady;
        return false;
    }

    return openCredentialsSystemPriv(true);
}

bool CredentialsAccessManager::closeCredentialsSystem()
{
    RETURN_IF_NOT_INITIALIZED(false);

    closeDB();

    if (m_CAMConfiguration.m_useEncryption) {
        if (!m_pCryptoFileSystemManager->unmountFileSystem()) {
            m_error = CredentialsDbUnmountFailed;
            return false;
        }
    }

    m_error = NoError;
    m_systemOpened = false;
    return true;
}

bool CredentialsAccessManager::deleteCredentialsSystem()
{
    RETURN_IF_NOT_INITIALIZED(false);

    if (m_systemOpened && !closeCredentialsSystem()) {
        /* The close operation failed: we cannot proceed */
        return false;
    }

    m_error = NoError;

    if (m_CAMConfiguration.m_useEncryption) {
        if (!m_pCryptoFileSystemManager->deleteFileSystem())
            m_error = CredentialsDbDeletionFailed;
    } else {
        QFile dbFile(m_CAMConfiguration.m_dbName);
        if (dbFile.exists()) {
            if (!dbFile.remove())
                m_error = CredentialsDbDeletionFailed;
        }
    }

    return m_error == NoError;
}

bool CredentialsAccessManager::setMasterEncryptionKey(const QByteArray &newKey,
                                                      const QByteArray &existingKey)
{
    if (!m_CAMConfiguration.m_useEncryption)
        return false;

    /* Clear this for security reasons - SIM data must not be stored
       using an deprecated master key
    */
    m_CAMConfiguration.m_encryptionPassphrase.clear();

    if (!encryptionKeyCanMountFS(existingKey)) {
        BLAME() << "Existing lock code check failed.";
        return false;
    }

    if (!m_pCryptoFileSystemManager->addEncryptionKey(
            newKey, existingKey)) {
        BLAME() << "Failed to add new device lock code.";
        return false;
    }

    if (!m_pCryptoFileSystemManager->removeEncryptionKey(existingKey, newKey)) {
        BLAME() << "Failed to remove old device lock code.";
        return false;
    }

    return true;
}

bool CredentialsAccessManager::lockSecureStorage(const QByteArray &lockData)
{
    // TODO - implement this, research how to.
    Q_UNUSED(lockData)
    return false;
}

CredentialsDB *CredentialsAccessManager::credentialsDB() const
{
    RETURN_IF_NOT_INITIALIZED(NULL);

    return m_pCredentialsDB;
}

bool CredentialsAccessManager::deployCredentialsSystem()
{
    if (m_CAMConfiguration.m_useEncryption) {
        if (!m_pCryptoFileSystemManager->setupFileSystem()) {
            m_error = CredentialsDbSetupFailed;
            return false;
        }
    }
    return true;
}

bool CredentialsAccessManager::fileSystemLoaded(bool checkForDatabase)
{
    if (!m_pCryptoFileSystemManager->fileSystemMounted())
        return false;

    if (checkForDatabase
        && !m_pCryptoFileSystemManager->fileSystemContainsFile(m_CAMConfiguration.m_dbName))
        return false;

    return true;
}

bool CredentialsAccessManager::fileSystemDeployed()
{
    return QFile::exists(m_pCryptoFileSystemManager->fileSystemPath());
}

bool CredentialsAccessManager::openDB(const QString &databaseName)
{
    m_pCredentialsDB = new CredentialsDB(databaseName);

    if (!m_pCredentialsDB->connect()) {
        TRACE() << SqlDatabase::errorInfo(m_pCredentialsDB->error(false));
        m_error = CredentialsDbConnectionError;
        return false;
    }
    TRACE() <<  "Database connection succeeded.";

    if (!m_pCredentialsDB->hasTableStructure()) {
        TRACE() << "Creating SQL table structure...";
        if (!m_pCredentialsDB->createTableStructure()) {
            TRACE() << SqlDatabase::errorInfo(m_pCredentialsDB->error());
            m_error = CredentialsDbSqlError;
            return false;
        }
    } else {
        TRACE() << "SQL table structure already created...";
    }

    TRACE() << m_pCredentialsDB->sqlDBConfiguration();

    return true;
}

bool CredentialsAccessManager::encryptionKeyCanMountFS(const QByteArray &key)
{
    if (!fileSystemDeployed()) {
        TRACE() << "Secure FS not deployed";
        return false;
    }

    if (m_pCryptoFileSystemManager->encryptionKeyInUse(key)) {
        TRACE() << "SIM data already in use.";
        if (m_pCryptoFileSystemManager->fileSystemMounted()) {

            m_pCryptoFileSystemManager->setEncryptionKey(key);

            if (!credentialsSystemOpened()) {
                if (openCredentialsSystemPriv(false)) {
                    TRACE() << "Credentials system opened.";
                } else {
                    BLAME() << "Failed to open credentials system.";
                }
            } else {
                TRACE() << "Credentials system already opened.";
            }
        }
        return true;
    } else {
        return false;
    }
}

void CredentialsAccessManager::closeDB()
{
    if (m_pCredentialsDB) {
        m_pCredentialsDB->disconnect();
        delete m_pCredentialsDB;
        m_pCredentialsDB = NULL;
    }
}

void CredentialsAccessManager::onKeyInserted(const SignOn::Key key)
{
    TRACE() << "Key:" << key.toHex();

    if (key.isEmpty()) return;

    /* The `key in use` check will attempt to mount using the new key if
       the file system is not already mounted
    */
    if (encryptionKeyCanMountFS(key)) {
        TRACE() << "SIM data already in use.";
        authorizedKeys << key;
        return;
    }

    /* We got here because the inserted key is totally new to the CAM.
     * Let's see if any key manager wants to authorize it: we call
     * authorizeKey() on each of them, and continue processing the key when
     * the keyAuthorized() signal comes.
     */
    foreach (SignOn::AbstractKeyManager *keyManager, keyManagers) {
        keyManager->authorizeKey(key);
    }
}

void CredentialsAccessManager::onKeyDisabled(const SignOn::Key key)
{
    TRACE() << "Key:" << key.toHex();

    if (authorizedKeys.removeAll(key) == 0) {
        TRACE() << "Key was already disabled";
        return;
    }

    if (authorizedKeys.isEmpty()) {
        TRACE() << "All keys removed, closing secure storage.";
        if (credentialsSystemOpened())
            if (!closeCredentialsSystem())
                BLAME() << "Error occurred while closing secure storage.";

        TRACE() << "Querying for keys.";
        foreach (SignOn::AbstractKeyManager *keyManager, keyManagers) {
            keyManager->queryKeys();
        }
    }
}

void CredentialsAccessManager::onKeyRemoved(const SignOn::Key key)
{
    TRACE() << "Key:" << key.toHex();

    // Make sure the key is disabled:
    onKeyDisabled(key);

    if (!encryptionKeyCanMountFS(key)) {
        TRACE() << "Key is not known to the CryptoManager.";
        return;
    }

    if (authorizedKeys.isEmpty()) {
        BLAME() << "Cannot remove key: no authorized keys";
        return;
    }

    SignOn::Key authorizedKey = authorizedKeys.first();
    if (!m_pCryptoFileSystemManager->removeEncryptionKey(key, authorizedKey)) {
        BLAME() << "Failed to remove key.";
    } else {
        TRACE() << "Key successfully removed.";
    }
}

void CredentialsAccessManager::onKeyAuthorized(const SignOn::Key key,
                                               bool authorized)
{
    TRACE() << "Key:" << key.toHex() << "Authorized:" << authorized;

    if (!authorized) return;

    if (encryptionKeyCanMountFS(key)) {
        TRACE() << "Encryption key already in use.";
        authorizedKeys << key;
        return;
    }

    if (authorizedKeys.isEmpty()) {
        BLAME() << "No authorized keys: cannot add new key";
        return;
    }

    if (m_pCryptoFileSystemManager->fileSystemMounted()) {
        /* if the secure FS is already mounted, add the new key to it */
        SignOn::Key authorizedKey = authorizedKeys.first();
        if (m_pCryptoFileSystemManager->addEncryptionKey(key, authorizedKey)) {
            TRACE() << "Encryption key successfullyadded into the CryptoManager.";
            m_pCryptoFileSystemManager->setEncryptionKey(key);
            authorizedKeys << key;
        } else {
            BLAME() << "Could not store encryption key.";
        }
    } else if (!fileSystemDeployed()) {
        /* if the secure FS does not exist, create it and use this new key to
         * initialize it */
        m_pCryptoFileSystemManager->setEncryptionKey(key);
        m_accessCodeFetched = true;
        if (openCredentialsSystemPriv(true)) {
            authorizedKeys << key;
        } else {
            BLAME() << "Couldn't create the secure FS";
        }
    } else {
        BLAME() << "Secure FS already created with another set of keys";
    }
}

<commit_msg>Fix CredentialsAccessManager::onKeyAuthorized()<commit_after>/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of signon
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Aurel Popirtac <mailto:ext-Aurel.Popirtac@nokia.com>
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include "credentialsaccessmanager.h"

#include "signond-common.h"

#include <QFile>
#include <QBuffer>

#define RETURN_IF_NOT_INITIALIZED(return_value)                  \
    do {                                                         \
        if (!m_isInitialized) {                                  \
            m_error = NotInitialized;                            \
            TRACE() << "CredentialsAccessManager not initialized."; \
            return return_value;                                \
        }                                                       \
    } while (0)

using namespace SignonDaemonNS;

/* ---------------------- CAMConfiguration ---------------------- */

CAMConfiguration::CAMConfiguration()
        : m_dbName(QLatin1String(signonDefaultDbName)),
          m_useEncryption(signonDefaultUseEncryption),
          m_dbFileSystemPath(
                QLatin1String(signonDefaultStoragePath)
                + QDir::separator()
                + QLatin1String(signonDefaultFileSystemName)),
          m_fileSystemType(QLatin1String(signonDefaultFileSystemType)),
          m_fileSystemSize(signonMinumumDbSize),
          m_encryptionPassphrase(QByteArray())
{}

void CAMConfiguration::serialize(QIODevice *device)
{
    if (device == NULL)
        return;

    if (!device->open(QIODevice::ReadWrite)) {
        return;
    }

    QString buffer;
    QTextStream stream(&buffer);
    stream << "\n\n====== Credentials Access Manager Configuration ======\n\n";
    stream << "File system mount name " << m_dbFileSystemPath << '\n';
    stream << "File system format: " << m_fileSystemType << '\n';
    stream << "File system size:" << m_fileSystemSize << "megabytes\n";

    const char *usingEncryption = m_useEncryption ? "true" : "false";
    stream << "Using encryption: " << usingEncryption << '\n';
    stream << "Credentials database name: " << m_dbName << '\n';
    stream << "======================================================\n\n";
    device->write(buffer.toUtf8());
    device->close();
}

/* ---------------------- CredentialsAccessManager ---------------------- */

CredentialsAccessManager *CredentialsAccessManager::m_pInstance = NULL;

CredentialsAccessManager::CredentialsAccessManager(QObject *parent)
        : QObject(parent),
          m_isInitialized(false),
          m_accessCodeFetched(false),
          m_systemOpened(false),
          m_error(NoError),
          keyManagers(),
          m_pCredentialsDB(NULL),
          m_pCryptoFileSystemManager(NULL),
          m_CAMConfiguration(CAMConfiguration())
{
}

CredentialsAccessManager::~CredentialsAccessManager()
{
    closeCredentialsSystem();

    m_pInstance = NULL;
}

CredentialsAccessManager *CredentialsAccessManager::instance(QObject *parent)
{
    if (!m_pInstance)
        m_pInstance = new CredentialsAccessManager(parent);

    return m_pInstance;
}

void CredentialsAccessManager::finalize()
{
    if (m_systemOpened)
        closeCredentialsSystem();

    if (m_pCryptoFileSystemManager)
        delete m_pCryptoFileSystemManager;

    m_accessCodeFetched = false;
    m_isInitialized = false;
    m_error = NoError;
}

bool CredentialsAccessManager::init(const CAMConfiguration &camConfiguration)
{
    if (m_isInitialized) {
        TRACE() << "CAM already initialized.";
        m_error = AlreadyInitialized;
        return false;
    }

    m_CAMConfiguration = camConfiguration;

    QBuffer config;
    m_CAMConfiguration.serialize(&config);
    TRACE() << "\n\nInitualizing CredentialsAccessManager with configuration: " << config.data();

    if (m_CAMConfiguration.m_useEncryption) {
        //Initialize CryptoManager
        m_pCryptoFileSystemManager = new CryptoManager(this);
        m_pCryptoFileSystemManager->setFileSystemPath(m_CAMConfiguration.m_dbFileSystemPath);
        m_pCryptoFileSystemManager->setFileSystemSize(m_CAMConfiguration.m_fileSystemSize);
        m_pCryptoFileSystemManager->setFileSystemType(m_CAMConfiguration.m_fileSystemType);

        //If passphrase exists (device lock code) open creds system - sync
        if (!m_CAMConfiguration.m_encryptionPassphrase.isEmpty()) {

            m_pCryptoFileSystemManager->setEncryptionKey(
                    m_CAMConfiguration.m_encryptionPassphrase);
            m_accessCodeFetched = true;

            if (!openCredentialsSystemPriv(true)) {
                BLAME() << "Failed to open credentials system. Fallback to alternative methods.";
            }
        }

        // Initialize all key managers
        foreach (SignOn::AbstractKeyManager *keyManager, keyManagers) {
            connect(keyManager,
                    SIGNAL(keyInserted(const SignOn::Key)),
                    SLOT(onKeyInserted(const SignOn::Key)));
            connect(keyManager,
                    SIGNAL(keyDisabled(const SignOn::Key)),
                    SLOT(onKeyDisabled(const SignOn::Key)));
            connect(keyManager,
                    SIGNAL(keyRemoved(const SignOn::Key)),
                    SLOT(onKeyRemoved(const SignOn::Key)));
            connect(keyManager,
                    SIGNAL(keyAuthorized(const SignOn::Key, bool)),
                    SLOT(onKeyAuthorized(const SignOn::Key, bool)));
            keyManager->setup();
        }
    }

    m_isInitialized = true;
    m_error = NoError;

    TRACE() << "CredentialsAccessManager successfully initialized...";
    return true;
}

void CredentialsAccessManager::addKeyManager(
    SignOn::AbstractKeyManager *keyManager)
{
    keyManagers.append(keyManager);
}

bool CredentialsAccessManager::openCredentialsSystemPriv(bool mountFileSystem)
{
    //todo remove this variable after LUKS implementation becomes stable.
    QString dbPath;

    if (m_CAMConfiguration.m_useEncryption) {
        dbPath = m_pCryptoFileSystemManager->fileSystemMountPath()
            + QDir::separator()
            + m_CAMConfiguration.m_dbName;

        if (mountFileSystem) {
            if (!fileSystemDeployed()) {
                if (deployCredentialsSystem()) {
                    if (openDB(dbPath))
                        m_systemOpened = true;
                }
                return m_systemOpened;
            }

            if (fileSystemLoaded()) {
                m_error = CredentialsDbAlreadyDeployed;
                return false;
            }

            if (!m_pCryptoFileSystemManager->mountFileSystem()) {
                m_error = CredentialsDbMountFailed;
                return false;
            }
        }
    } else {
        QFileInfo fInfo(m_CAMConfiguration.m_dbFileSystemPath);
        QDir storageDir = fInfo.dir();
        if (!storageDir.exists()) {
            if (!storageDir.mkpath(storageDir.path()))
                BLAME() << "Could not create storage directory!!!";
        }

        dbPath = storageDir.path()
                 + QDir::separator()
                 + m_CAMConfiguration.m_dbName;
    }

    TRACE() << "Database name: [" << dbPath << "]";

    if (openDB(dbPath)) {
        m_systemOpened = true;
        m_error = NoError;
    }

    return m_systemOpened;
}

bool CredentialsAccessManager::openCredentialsSystem()
{
    RETURN_IF_NOT_INITIALIZED(false);

    if (m_CAMConfiguration.m_useEncryption && !m_accessCodeFetched) {
        m_error = AccessCodeNotReady;
        return false;
    }

    return openCredentialsSystemPriv(true);
}

bool CredentialsAccessManager::closeCredentialsSystem()
{
    RETURN_IF_NOT_INITIALIZED(false);

    closeDB();

    if (m_CAMConfiguration.m_useEncryption) {
        if (!m_pCryptoFileSystemManager->unmountFileSystem()) {
            m_error = CredentialsDbUnmountFailed;
            return false;
        }
    }

    m_error = NoError;
    m_systemOpened = false;
    return true;
}

bool CredentialsAccessManager::deleteCredentialsSystem()
{
    RETURN_IF_NOT_INITIALIZED(false);

    if (m_systemOpened && !closeCredentialsSystem()) {
        /* The close operation failed: we cannot proceed */
        return false;
    }

    m_error = NoError;

    if (m_CAMConfiguration.m_useEncryption) {
        if (!m_pCryptoFileSystemManager->deleteFileSystem())
            m_error = CredentialsDbDeletionFailed;
    } else {
        QFile dbFile(m_CAMConfiguration.m_dbName);
        if (dbFile.exists()) {
            if (!dbFile.remove())
                m_error = CredentialsDbDeletionFailed;
        }
    }

    return m_error == NoError;
}

bool CredentialsAccessManager::setMasterEncryptionKey(const QByteArray &newKey,
                                                      const QByteArray &existingKey)
{
    if (!m_CAMConfiguration.m_useEncryption)
        return false;

    /* Clear this for security reasons - SIM data must not be stored
       using an deprecated master key
    */
    m_CAMConfiguration.m_encryptionPassphrase.clear();

    if (!encryptionKeyCanMountFS(existingKey)) {
        BLAME() << "Existing lock code check failed.";
        return false;
    }

    if (!m_pCryptoFileSystemManager->addEncryptionKey(
            newKey, existingKey)) {
        BLAME() << "Failed to add new device lock code.";
        return false;
    }

    if (!m_pCryptoFileSystemManager->removeEncryptionKey(existingKey, newKey)) {
        BLAME() << "Failed to remove old device lock code.";
        return false;
    }

    return true;
}

bool CredentialsAccessManager::lockSecureStorage(const QByteArray &lockData)
{
    // TODO - implement this, research how to.
    Q_UNUSED(lockData)
    return false;
}

CredentialsDB *CredentialsAccessManager::credentialsDB() const
{
    RETURN_IF_NOT_INITIALIZED(NULL);

    return m_pCredentialsDB;
}

bool CredentialsAccessManager::deployCredentialsSystem()
{
    if (m_CAMConfiguration.m_useEncryption) {
        if (!m_pCryptoFileSystemManager->setupFileSystem()) {
            m_error = CredentialsDbSetupFailed;
            return false;
        }
    }
    return true;
}

bool CredentialsAccessManager::fileSystemLoaded(bool checkForDatabase)
{
    if (!m_pCryptoFileSystemManager->fileSystemMounted())
        return false;

    if (checkForDatabase
        && !m_pCryptoFileSystemManager->fileSystemContainsFile(m_CAMConfiguration.m_dbName))
        return false;

    return true;
}

bool CredentialsAccessManager::fileSystemDeployed()
{
    return QFile::exists(m_pCryptoFileSystemManager->fileSystemPath());
}

bool CredentialsAccessManager::openDB(const QString &databaseName)
{
    m_pCredentialsDB = new CredentialsDB(databaseName);

    if (!m_pCredentialsDB->connect()) {
        TRACE() << SqlDatabase::errorInfo(m_pCredentialsDB->error(false));
        m_error = CredentialsDbConnectionError;
        return false;
    }
    TRACE() <<  "Database connection succeeded.";

    if (!m_pCredentialsDB->hasTableStructure()) {
        TRACE() << "Creating SQL table structure...";
        if (!m_pCredentialsDB->createTableStructure()) {
            TRACE() << SqlDatabase::errorInfo(m_pCredentialsDB->error());
            m_error = CredentialsDbSqlError;
            return false;
        }
    } else {
        TRACE() << "SQL table structure already created...";
    }

    TRACE() << m_pCredentialsDB->sqlDBConfiguration();

    return true;
}

bool CredentialsAccessManager::encryptionKeyCanMountFS(const QByteArray &key)
{
    if (!fileSystemDeployed()) {
        TRACE() << "Secure FS not deployed";
        return false;
    }

    if (m_pCryptoFileSystemManager->encryptionKeyInUse(key)) {
        TRACE() << "SIM data already in use.";
        if (m_pCryptoFileSystemManager->fileSystemMounted()) {

            m_pCryptoFileSystemManager->setEncryptionKey(key);

            if (!credentialsSystemOpened()) {
                if (openCredentialsSystemPriv(false)) {
                    TRACE() << "Credentials system opened.";
                } else {
                    BLAME() << "Failed to open credentials system.";
                }
            } else {
                TRACE() << "Credentials system already opened.";
            }
        }
        return true;
    } else {
        return false;
    }
}

void CredentialsAccessManager::closeDB()
{
    if (m_pCredentialsDB) {
        m_pCredentialsDB->disconnect();
        delete m_pCredentialsDB;
        m_pCredentialsDB = NULL;
    }
}

void CredentialsAccessManager::onKeyInserted(const SignOn::Key key)
{
    TRACE() << "Key:" << key.toHex();

    if (key.isEmpty()) return;

    /* The `key in use` check will attempt to mount using the new key if
       the file system is not already mounted
    */
    if (encryptionKeyCanMountFS(key)) {
        TRACE() << "SIM data already in use.";
        authorizedKeys << key;
        return;
    }

    /* We got here because the inserted key is totally new to the CAM.
     * Let's see if any key manager wants to authorize it: we call
     * authorizeKey() on each of them, and continue processing the key when
     * the keyAuthorized() signal comes.
     */
    foreach (SignOn::AbstractKeyManager *keyManager, keyManagers) {
        keyManager->authorizeKey(key);
    }
}

void CredentialsAccessManager::onKeyDisabled(const SignOn::Key key)
{
    TRACE() << "Key:" << key.toHex();

    if (authorizedKeys.removeAll(key) == 0) {
        TRACE() << "Key was already disabled";
        return;
    }

    if (authorizedKeys.isEmpty()) {
        TRACE() << "All keys removed, closing secure storage.";
        if (credentialsSystemOpened())
            if (!closeCredentialsSystem())
                BLAME() << "Error occurred while closing secure storage.";

        TRACE() << "Querying for keys.";
        foreach (SignOn::AbstractKeyManager *keyManager, keyManagers) {
            keyManager->queryKeys();
        }
    }
}

void CredentialsAccessManager::onKeyRemoved(const SignOn::Key key)
{
    TRACE() << "Key:" << key.toHex();

    // Make sure the key is disabled:
    onKeyDisabled(key);

    if (!encryptionKeyCanMountFS(key)) {
        TRACE() << "Key is not known to the CryptoManager.";
        return;
    }

    if (authorizedKeys.isEmpty()) {
        BLAME() << "Cannot remove key: no authorized keys";
        return;
    }

    SignOn::Key authorizedKey = authorizedKeys.first();
    if (!m_pCryptoFileSystemManager->removeEncryptionKey(key, authorizedKey)) {
        BLAME() << "Failed to remove key.";
    } else {
        TRACE() << "Key successfully removed.";
    }
}

void CredentialsAccessManager::onKeyAuthorized(const SignOn::Key key,
                                               bool authorized)
{
    TRACE() << "Key:" << key.toHex() << "Authorized:" << authorized;

    if (!authorized) return;

    if (encryptionKeyCanMountFS(key)) {
        TRACE() << "Encryption key already in use.";
        authorizedKeys << key;
        return;
    }

    if (m_pCryptoFileSystemManager->fileSystemMounted()) {
        /* if the secure FS is already mounted, add the new key to it */
        if (authorizedKeys.isEmpty()) {
            BLAME() << "No authorized keys: cannot add new key";
            return;
        }

        SignOn::Key authorizedKey = authorizedKeys.first();
        if (m_pCryptoFileSystemManager->addEncryptionKey(key, authorizedKey)) {
            TRACE() << "Encryption key successfullyadded into the CryptoManager.";
            m_pCryptoFileSystemManager->setEncryptionKey(key);
            authorizedKeys << key;
        } else {
            BLAME() << "Could not store encryption key.";
        }
    } else if (!fileSystemDeployed()) {
        /* if the secure FS does not exist, create it and use this new key to
         * initialize it */
        m_pCryptoFileSystemManager->setEncryptionKey(key);
        m_accessCodeFetched = true;
        if (openCredentialsSystemPriv(true)) {
            authorizedKeys << key;
        } else {
            BLAME() << "Couldn't create the secure FS";
        }
    } else {
        BLAME() << "Secure FS already created with another set of keys";
    }
}

<|endoftext|>


<commit_before>/*
 * This file is part of signon
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include "signonauthsessionadaptor.h"
#include "accesscontrolmanager.h"

namespace SignonDaemonNS {

    SignonAuthSessionAdaptor::SignonAuthSessionAdaptor(SignonAuthSession *parent) : QDBusAbstractAdaptor(parent)
    {
        setAutoRelaySignals(true);
    }

    SignonAuthSessionAdaptor::~SignonAuthSessionAdaptor()
    {
    }

    void SignonAuthSessionAdaptor::errorReply(const QString &name,
                                              const QString &message)
    {
        QDBusMessage errReply =
            static_cast<QDBusContext *>(parent())->message().createErrorReply(name, message);
        SIGNOND_BUS.send(errReply);
    }

    QStringList SignonAuthSessionAdaptor::queryAvailableMechanisms(const QStringList &wantedMechanisms)
    {
        TRACE();

        QDBusContext &dbusContext = *static_cast<QDBusContext *>(parent());
        if (AccessControlManager::pidOfPeer(dbusContext) != parent()->ownerPid()) {
            TRACE() << "queryAvailableMechanisms called from peer that doesn't own the AuthSession object\n";
            QString errMsg;
            QTextStream(&errMsg) << SIGNOND_PERMISSION_DENIED_ERR_STR
                                 << " Authentication session owned by other process.";
            errorReply(SIGNOND_PERMISSION_DENIED_ERR_NAME, errMsg);
            return QStringList();
        }

        return parent()->queryAvailableMechanisms(wantedMechanisms);
    }

    QVariantMap SignonAuthSessionAdaptor::process(const QVariantMap &sessionDataVa, const QString &mechanism)
    {
        TRACE();

        QDBusContext &dbusContext = *static_cast<QDBusContext *>(parent());
        if (AccessControlManager::pidOfPeer(dbusContext) != parent()->ownerPid()) {
            TRACE() << "process called from peer that doesn't own the AuthSession object\n";
            QString errMsg;
            QTextStream(&errMsg) << SIGNOND_PERMISSION_DENIED_ERR_STR
                                 << " Authentication session owned by other process.";
            errorReply(SIGNOND_PERMISSION_DENIED_ERR_NAME, errMsg);
            return QVariantMap();
        }

        return parent()->process(sessionDataVa, mechanism);
    }

    void SignonAuthSessionAdaptor::cancel()
    {
        TRACE();

        QDBusContext &dbusContext = *static_cast<QDBusContext *>(parent());
        if (AccessControlManager::pidOfPeer(dbusContext) != parent()->ownerPid()) {
            TRACE() << "cancel called from peer that doesn't own the AuthSession object\n";
            return;
        }

        parent()->cancel();
    }

    void SignonAuthSessionAdaptor::setId(quint32 id)
    {
        TRACE();

        QDBusContext &dbusContext = *static_cast<QDBusContext *>(parent());
        if (AccessControlManager::pidOfPeer(dbusContext) != parent()->ownerPid()) {
            TRACE() << "setId called from peer that doesn't own the AuthSession object\n";
            return;
        }

        parent()->setId(id);
    }

    void SignonAuthSessionAdaptor::objectUnref()
    {
        TRACE();

        QDBusContext &dbusContext = *static_cast<QDBusContext *>(parent());
        if (AccessControlManager::pidOfPeer(dbusContext) != parent()->ownerPid()) {
            TRACE() << "objectUnref called from peer that doesn't own the AuthSession object\n";
            return;
        }

        parent()->objectUnref();
    }

} //namespace SignonDaemonNS
<commit_msg>AuthSession: restrict setId() usage<commit_after>/*
 * This file is part of signon
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include "signonauthsessionadaptor.h"
#include "accesscontrolmanager.h"

namespace SignonDaemonNS {

    SignonAuthSessionAdaptor::SignonAuthSessionAdaptor(SignonAuthSession *parent) : QDBusAbstractAdaptor(parent)
    {
        setAutoRelaySignals(true);
    }

    SignonAuthSessionAdaptor::~SignonAuthSessionAdaptor()
    {
    }

    void SignonAuthSessionAdaptor::errorReply(const QString &name,
                                              const QString &message)
    {
        QDBusMessage errReply =
            static_cast<QDBusContext *>(parent())->message().createErrorReply(name, message);
        SIGNOND_BUS.send(errReply);
    }

    QStringList SignonAuthSessionAdaptor::queryAvailableMechanisms(const QStringList &wantedMechanisms)
    {
        TRACE();

        QDBusContext &dbusContext = *static_cast<QDBusContext *>(parent());
        if (AccessControlManager::pidOfPeer(dbusContext) != parent()->ownerPid()) {
            TRACE() << "queryAvailableMechanisms called from peer that doesn't own the AuthSession object\n";
            QString errMsg;
            QTextStream(&errMsg) << SIGNOND_PERMISSION_DENIED_ERR_STR
                                 << " Authentication session owned by other process.";
            errorReply(SIGNOND_PERMISSION_DENIED_ERR_NAME, errMsg);
            return QStringList();
        }

        return parent()->queryAvailableMechanisms(wantedMechanisms);
    }

    QVariantMap SignonAuthSessionAdaptor::process(const QVariantMap &sessionDataVa, const QString &mechanism)
    {
        TRACE();

        QDBusContext &dbusContext = *static_cast<QDBusContext *>(parent());
        if (AccessControlManager::pidOfPeer(dbusContext) != parent()->ownerPid()) {
            TRACE() << "process called from peer that doesn't own the AuthSession object\n";
            QString errMsg;
            QTextStream(&errMsg) << SIGNOND_PERMISSION_DENIED_ERR_STR
                                 << " Authentication session owned by other process.";
            errorReply(SIGNOND_PERMISSION_DENIED_ERR_NAME, errMsg);
            return QVariantMap();
        }

        return parent()->process(sessionDataVa, mechanism);
    }

    void SignonAuthSessionAdaptor::cancel()
    {
        TRACE();

        QDBusContext &dbusContext = *static_cast<QDBusContext *>(parent());
        if (AccessControlManager::pidOfPeer(dbusContext) != parent()->ownerPid()) {
            TRACE() << "cancel called from peer that doesn't own the AuthSession object\n";
            return;
        }

        parent()->cancel();
    }

    void SignonAuthSessionAdaptor::setId(quint32 id)
    {
        TRACE();

        QDBusContext &dbusContext = *static_cast<QDBusContext *>(parent());
        if (AccessControlManager::pidOfPeer(dbusContext) != parent()->ownerPid()) {
            TRACE() << "setId called from peer that doesn't own the AuthSession object\n";
            return;
        }
        if (!AccessControlManager::isPeerAllowedToUseIdentity(
                                        dbusContext, id)) {
            TRACE() << "setId called with an identifier the peer is not allowed to use";
            return;
        }

        parent()->setId(id);
    }

    void SignonAuthSessionAdaptor::objectUnref()
    {
        TRACE();

        QDBusContext &dbusContext = *static_cast<QDBusContext *>(parent());
        if (AccessControlManager::pidOfPeer(dbusContext) != parent()->ownerPid()) {
            TRACE() << "objectUnref called from peer that doesn't own the AuthSession object\n";
            return;
        }

        parent()->objectUnref();
    }

} //namespace SignonDaemonNS
<|endoftext|>


<commit_before>#include <FROG/App.hpp>
#include <FROG/GameObject.hpp>
#include <FROG/Collision/BoxCollider.hpp>
#include <FROG/Collision/RoundCollider.hpp>
#include <FROG/Collision/LSAP.hpp>
#include <FROG/Control.hpp>
#include <FROG/Function.hpp>

#include "Demo_Colliders.hpp"

#include <SFML/Window/Keyboard.hpp>
#include <SFML/Graphics/RectangleShape.hpp>

#include <iostream> // TODO remove

#define OBJ_DIM 64

using namespace frog;

MainState::MainState(AppInfo& _appinfo)
  : Scene(_appinfo),
    mode(0),
    collisions(0),
    obj(new GameObject),
    obstacle(new GameObject),
    collider_object(new GameObject)
{
}

MainState::~MainState()
{
}

void MainState::enter()
{
  initObj_circle();
  initCollider();
  initObstacle();

  addObject(collider_object);
  addObject(obj);
  addObject(obstacle);
  m_collisionManager.addObject(obj);
  m_collisionManager.addObject(obstacle);
  changeMap();
}

void MainState::initObj_rectangle()
{
  obj->transform->layer = 2;
  auto ctrl = ControlComponent::create(appInfo.eventList);
  obj->addComponent(ctrl, "CONTROL");
  createMapping();
  std::shared_ptr<sf::RectangleShape> r(new sf::RectangleShape(sf::Vector2f(OBJ_DIM, OBJ_DIM) ) );
  r->setFillColor(sf::Color(255,0,0,100) );
  r->setOutlineThickness(2);
  r->setOutlineColor(sf::Color::Black);
  obj->addComponent( RenderingComponent::create( r ), "RENDERING" );
  obj->getComponent<Transform>("TRANSFORM")->setPosition(100, 70);
  obj->getComponent<Transform>("TRANSFORM")->setOrigin(OBJ_DIM/2, OBJ_DIM/2);

  auto collider = BoxCollider::create(sf::Vector2f(OBJ_DIM, OBJ_DIM) );
  auto collision = [this](Collision c){
    collisions++;
    std::cout << "collisions : " << collisions << std::endl;
  };
  collider->setScript(collision);
  obj->addComponent( collider,
                     "COLLIDER");
}

void MainState::initObj_circle()
{
  obj->transform->layer = 2;
  auto ctrl = ControlComponent::create(appInfo.eventList);
  obj->addComponent(ctrl, "CONTROL");
  createMapping();
  std::shared_ptr<sf::CircleShape> r(new sf::CircleShape(OBJ_DIM) );
  r->setFillColor(sf::Color(255,0,0,100) );
  r->setOutlineThickness(2);
  r->setOutlineColor(sf::Color::Black);
  obj->addComponent( RenderingComponent::create( r ), "RENDERING" );
  obj->getComponent<Transform>("TRANSFORM")->setPosition(100, 70);
  obj->getComponent<Transform>("TRANSFORM")->setOrigin(OBJ_DIM, OBJ_DIM);

  auto collider = RoundCollider::create(OBJ_DIM);
  auto collision = [this](Collision c){
    collisions++;
    std::cout << "collisions : " << collisions << std::endl;
  };
  collider->setScript(collision);
  obj->addComponent( collider,
                     "COLLIDER");
}

void MainState::initCollider()
{
  std::shared_ptr<sf::RectangleShape> r2(new sf::RectangleShape(sf::Vector2f(OBJ_DIM, 10) ) );
  r2->setFillColor(sf::Color::Yellow);
  collider_object->addComponent( RenderingComponent::create( r2 ), "RENDERING" );
  //  collider_object->transform = obj->transform;
}

void MainState::initObstacle()
{
  obstacle->transform->setPosition(20, 40);
  obstacle->addComponent(BoxCollider::create(sf::Vector2f(20,100)),
                         "COLLIDER");
  std::shared_ptr<sf::RectangleShape> r(new sf::RectangleShape(sf::Vector2f(20, 100) ) );
  r->setFillColor(sf::Color::Green);
  obstacle->addComponent(RenderingComponent::create(r), "RENDERING");
}

void MainState::exit()
{
  delete mapping_move;
  delete mapping_resize;
  delete mapping_rotate;
}

void MainState::preupdate()
{
  std::shared_ptr<sf::RectangleShape> rect(new sf::RectangleShape() );
  rect->setFillColor(sf::Color(0,0,255,100) );
  try{
    auto fr = obj->getComponent<BoxCollider>("COLLIDER")->getBoundingBox();
      rect->setSize( sf::Vector2f(fr.width, fr.height) );
      rect->setPosition(fr.left, fr.top );
  }catch(std::logic_error e)
    {
      try{
        auto fr = obj->getComponent<RoundCollider>("COLLIDER")->getBoundingBox();
        rect->setSize( sf::Vector2f(fr.width, fr.height) );
        rect->setPosition(fr.left, fr.top );
      }catch(std::logic_error e)
        {

        }
    }
  // DON'T DO THAT
  m_renderer.removeObject(collider_object);
  collider_object->removeComponent("RENDERING");
  collider_object->addComponent(RenderingComponent::create(rect),
                                "RENDERING");
  m_renderer.addObject(collider_object);
  //
}

void MainState::postupdate()
{
  m_collisionManager.update();
 }

void MainState::createMapping()
{
  mapping_move = new ControlComponent::INPUT_MAP;
  mapping_resize = new ControlComponent::INPUT_MAP;
  mapping_rotate = new ControlComponent::INPUT_MAP;
  auto z_key = KeyboardButton::create(sf::Keyboard::Z);
  auto q_key = KeyboardButton::create(sf::Keyboard::Q);
  auto s_key = KeyboardButton::create(sf::Keyboard::S);
  auto d_key = KeyboardButton::create(sf::Keyboard::D);
  auto a_key = KeyboardButton::create(sf::Keyboard::A);
  auto e_key = KeyboardButton::create(sf::Keyboard::E);
  auto space_key = KeyboardButton::create(sf::Keyboard::Space,
                                          Trigger::PRESSED);
  auto resize_x_plus = Resize::create(obj, 0.009, 0);
  auto resize_x_minus = Resize::create(obj, -0.009, 0);
  auto resize_y_plus = Resize::create(obj, 0, 0.009);
  auto resize_y_minus = Resize::create(obj, 0, -0.009);
  auto move_x_plus = Move::create(obj, 1, 0);
  auto move_x_minus = Move::create(obj, -1, 0);
  auto move_y_plus = Move::create(obj, 0, 1);
  auto move_y_minus = Move::create(obj, 0, -1);
  auto rot_right = Rotate::create(obj, 1);
  auto rot_left = Rotate::create(obj, -1);
  auto changemode = Function::create( [this](){
      mode = (mode == 2) ? 0 : mode+1;
      changeMap();
    });
  mapping_move->emplace(z_key, move_y_minus);
  mapping_move->emplace(q_key, move_x_minus);
  mapping_move->emplace(s_key, move_y_plus);
  mapping_move->emplace(d_key, move_x_plus);
  mapping_resize->emplace(z_key, resize_y_plus);
  mapping_resize->emplace(q_key, resize_x_minus);
  mapping_resize->emplace(s_key, resize_y_minus);
  mapping_resize->emplace(d_key, resize_x_plus);
  mapping_rotate->emplace(e_key, rot_right);
  mapping_rotate->emplace(a_key, rot_left);
  auto ctrl = obj->getComponent<ControlComponent>("CONTROL");
  ctrl->bind(space_key, changemode, 0);
}

void MainState::changeMap()
{
  auto ctrl = obj->getComponent<ControlComponent>("CONTROL");
  std::cout << "change mode to ";
  switch(mode)
    {
    case 1:
      ctrl->changeMap(*mapping_resize, 1);
      std::cout << "RESIZE : Z,Q,S,D";
      break;
    case 2:
      ctrl->changeMap(*mapping_rotate, 1);
      std::cout << "ROTATE : A,E";
      break;
    default:
      ctrl->changeMap(*mapping_move, 1);
      std::cout << "MOVE : Z,Q,S,D";
      break;
    }
  std::cout << std::endl;
}

int main()
{
  frog::App demo("FROG - Colliders demo");
  demo.start( new MainState( demo.appInfo ) );
}
<commit_msg>restored square<commit_after>#include <FROG/App.hpp>
#include <FROG/GameObject.hpp>
#include <FROG/Collision/BoxCollider.hpp>
#include <FROG/Collision/RoundCollider.hpp>
#include <FROG/Collision/LSAP.hpp>
#include <FROG/Control.hpp>
#include <FROG/Function.hpp>

#include "Demo_Colliders.hpp"

#include <SFML/Window/Keyboard.hpp>
#include <SFML/Graphics/RectangleShape.hpp>

#include <iostream> // TODO remove

#define OBJ_DIM 64

using namespace frog;

MainState::MainState(AppInfo& _appinfo)
  : Scene(_appinfo),
    mode(0),
    collisions(0),
    obj(new GameObject),
    obstacle(new GameObject),
    collider_object(new GameObject)
{
}

MainState::~MainState()
{
}

void MainState::enter()
{
  initObj_rectangle();
  initCollider();
  initObstacle();

  addObject(collider_object);
  addObject(obj);
  addObject(obstacle);
  m_collisionManager.addObject(obj);
  m_collisionManager.addObject(obstacle);
  changeMap();
}

void MainState::initObj_rectangle()
{
  obj->transform->layer = 2;
  auto ctrl = ControlComponent::create(appInfo.eventList);
  obj->addComponent(ctrl, "CONTROL");
  createMapping();
  std::shared_ptr<sf::RectangleShape> r(new sf::RectangleShape(sf::Vector2f(OBJ_DIM, OBJ_DIM) ) );
  r->setFillColor(sf::Color(255,0,0,100) );
  r->setOutlineThickness(2);
  r->setOutlineColor(sf::Color::Black);
  obj->addComponent( RenderingComponent::create( r ), "RENDERING" );
  obj->getComponent<Transform>("TRANSFORM")->setPosition(100, 70);
  obj->getComponent<Transform>("TRANSFORM")->setOrigin(OBJ_DIM/2, OBJ_DIM/2);

  auto collider = BoxCollider::create(sf::Vector2f(OBJ_DIM, OBJ_DIM) );
  auto collision = [this](Collision c){
    collisions++;
    std::cout << "collisions : " << collisions << std::endl;
  };
  collider->setScript(collision);
  obj->addComponent( collider,
                     "COLLIDER");
}

void MainState::initObj_circle()
{
  obj->transform->layer = 2;
  auto ctrl = ControlComponent::create(appInfo.eventList);
  obj->addComponent(ctrl, "CONTROL");
  createMapping();
  std::shared_ptr<sf::CircleShape> r(new sf::CircleShape(OBJ_DIM) );
  r->setFillColor(sf::Color(255,0,0,100) );
  r->setOutlineThickness(2);
  r->setOutlineColor(sf::Color::Black);
  obj->addComponent( RenderingComponent::create( r ), "RENDERING" );
  obj->getComponent<Transform>("TRANSFORM")->setPosition(100, 70);
  obj->getComponent<Transform>("TRANSFORM")->setOrigin(OBJ_DIM, OBJ_DIM);

  auto collider = RoundCollider::create(OBJ_DIM);
  auto collision = [this](Collision c){
    collisions++;
    std::cout << "collisions : " << collisions << std::endl;
  };
  collider->setScript(collision);
  obj->addComponent( collider,
                     "COLLIDER");
}

void MainState::initCollider()
{
  std::shared_ptr<sf::RectangleShape> r2(new sf::RectangleShape(sf::Vector2f(OBJ_DIM, 10) ) );
  r2->setFillColor(sf::Color::Yellow);
  collider_object->addComponent( RenderingComponent::create( r2 ), "RENDERING" );
  //  collider_object->transform = obj->transform;
}

void MainState::initObstacle()
{
  obstacle->transform->setPosition(20, 40);
  obstacle->addComponent(BoxCollider::create(sf::Vector2f(20,100)),
                         "COLLIDER");
  std::shared_ptr<sf::RectangleShape> r(new sf::RectangleShape(sf::Vector2f(20, 100) ) );
  r->setFillColor(sf::Color::Green);
  obstacle->addComponent(RenderingComponent::create(r), "RENDERING");
}

void MainState::exit()
{
  delete mapping_move;
  delete mapping_resize;
  delete mapping_rotate;
}

void MainState::preupdate()
{
  std::shared_ptr<sf::RectangleShape> rect(new sf::RectangleShape() );
  rect->setFillColor(sf::Color(0,0,255,100) );
  try{
    auto fr = obj->getComponent<BoxCollider>("COLLIDER")->getBoundingBox();
      rect->setSize( sf::Vector2f(fr.width, fr.height) );
      rect->setPosition(fr.left, fr.top );
  }catch(std::logic_error e)
    {
      try{
        auto fr = obj->getComponent<RoundCollider>("COLLIDER")->getBoundingBox();
        rect->setSize( sf::Vector2f(fr.width, fr.height) );
        rect->setPosition(fr.left, fr.top );
      }catch(std::logic_error e)
        {

        }
    }
  // DON'T DO THAT
  m_renderer.removeObject(collider_object);
  collider_object->removeComponent("RENDERING");
  collider_object->addComponent(RenderingComponent::create(rect),
                                "RENDERING");
  m_renderer.addObject(collider_object);
  //
}

void MainState::postupdate()
{
  m_collisionManager.update();
 }

void MainState::createMapping()
{
  mapping_move = new ControlComponent::INPUT_MAP;
  mapping_resize = new ControlComponent::INPUT_MAP;
  mapping_rotate = new ControlComponent::INPUT_MAP;
  auto z_key = KeyboardButton::create(sf::Keyboard::Z);
  auto q_key = KeyboardButton::create(sf::Keyboard::Q);
  auto s_key = KeyboardButton::create(sf::Keyboard::S);
  auto d_key = KeyboardButton::create(sf::Keyboard::D);
  auto a_key = KeyboardButton::create(sf::Keyboard::A);
  auto e_key = KeyboardButton::create(sf::Keyboard::E);
  auto space_key = KeyboardButton::create(sf::Keyboard::Space,
                                          Trigger::PRESSED);
  auto resize_x_plus = Resize::create(obj, 0.009, 0);
  auto resize_x_minus = Resize::create(obj, -0.009, 0);
  auto resize_y_plus = Resize::create(obj, 0, 0.009);
  auto resize_y_minus = Resize::create(obj, 0, -0.009);
  auto move_x_plus = Move::create(obj, 1, 0);
  auto move_x_minus = Move::create(obj, -1, 0);
  auto move_y_plus = Move::create(obj, 0, 1);
  auto move_y_minus = Move::create(obj, 0, -1);
  auto rot_right = Rotate::create(obj, 1);
  auto rot_left = Rotate::create(obj, -1);
  auto changemode = Function::create( [this](){
      mode = (mode == 2) ? 0 : mode+1;
      changeMap();
    });
  mapping_move->emplace(z_key, move_y_minus);
  mapping_move->emplace(q_key, move_x_minus);
  mapping_move->emplace(s_key, move_y_plus);
  mapping_move->emplace(d_key, move_x_plus);
  mapping_resize->emplace(z_key, resize_y_plus);
  mapping_resize->emplace(q_key, resize_x_minus);
  mapping_resize->emplace(s_key, resize_y_minus);
  mapping_resize->emplace(d_key, resize_x_plus);
  mapping_rotate->emplace(e_key, rot_right);
  mapping_rotate->emplace(a_key, rot_left);
  auto ctrl = obj->getComponent<ControlComponent>("CONTROL");
  ctrl->bind(space_key, changemode, 0);
}

void MainState::changeMap()
{
  auto ctrl = obj->getComponent<ControlComponent>("CONTROL");
  std::cout << "change mode to ";
  switch(mode)
    {
    case 1:
      ctrl->changeMap(*mapping_resize, 1);
      std::cout << "RESIZE : Z,Q,S,D";
      break;
    case 2:
      ctrl->changeMap(*mapping_rotate, 1);
      std::cout << "ROTATE : A,E";
      break;
    default:
      ctrl->changeMap(*mapping_move, 1);
      std::cout << "MOVE : Z,Q,S,D";
      break;
    }
  std::cout << std::endl;
}

int main()
{
  frog::App demo("FROG - Colliders demo");
  demo.start( new MainState( demo.appInfo ) );
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_X86_UTILITY_HH__
#define __ARCH_X86_UTILITY_HH__

#include "arch/x86/types.hh"
#include "base/hashmap.hh"
#include "base/misc.hh"
#include "sim/host.hh"

class ThreadContext;

namespace __hash_namespace {
    template<>
    struct hash<X86ISA::ExtMachInst> {
        size_t operator()(const X86ISA::ExtMachInst &emi) const {
            //Because these are all the same, return 0
            return 0;
        };
    };
}

namespace X86ISA
{
    static inline bool
    inUserMode(ThreadContext *tc)
    {
        return false;
    }

    inline bool isCallerSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCallerSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    // Instruction address compression hooks
    inline Addr realPCToFetchPC(const Addr &addr)
    {
        return addr;
    }

    inline Addr fetchPCToRealPC(const Addr &addr)
    {
        return addr;
    }

    // the size of "fetched" instructions (not necessarily the size
    // of real instructions for PISA)
    inline size_t fetchInstSize()
    {
        return sizeof(MachInst);
    }

    /**
     * Function to insure ISA semantics about 0 registers.
     * @param tc The thread context.
     */
    template <class TC>
    void zeroRegisters(TC *tc);

    inline void initCPU(ThreadContext *tc, int cpuId)
    {
        panic("initCPU not implemented!\n");
    }

    inline void startupCPU(ThreadContext *tc, int cpuId)
    {
        tc->activate(0);
    }
};

#endif // __ARCH_X86_UTILITY_HH__
<commit_msg>Compile fix<commit_after>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.  Redistributions
 * in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.  Neither the name of
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_X86_UTILITY_HH__
#define __ARCH_X86_UTILITY_HH__

#include "arch/x86/types.hh"
#include "base/hashmap.hh"
#include "base/misc.hh"
#include "cpu/thread_context.hh"
#include "sim/host.hh"

class ThreadContext;

namespace __hash_namespace {
    template<>
    struct hash<X86ISA::ExtMachInst> {
        size_t operator()(const X86ISA::ExtMachInst &emi) const {
            //Because these are all the same, return 0
            return 0;
        };
    };
}

namespace X86ISA
{
    static inline bool
    inUserMode(ThreadContext *tc)
    {
        return false;
    }

    inline bool isCallerSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCallerSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    inline bool isCalleeSaveFloatRegister(unsigned int reg) {
        panic("register classification not implemented");
        return false;
    }

    // Instruction address compression hooks
    inline Addr realPCToFetchPC(const Addr &addr)
    {
        return addr;
    }

    inline Addr fetchPCToRealPC(const Addr &addr)
    {
        return addr;
    }

    // the size of "fetched" instructions (not necessarily the size
    // of real instructions for PISA)
    inline size_t fetchInstSize()
    {
        return sizeof(MachInst);
    }

    /**
     * Function to insure ISA semantics about 0 registers.
     * @param tc The thread context.
     */
    template <class TC>
    void zeroRegisters(TC *tc);

    inline void initCPU(ThreadContext *tc, int cpuId)
    {
        panic("initCPU not implemented!\n");
    }

    inline void startupCPU(ThreadContext *tc, int cpuId)
    {
        tc->activate(0);
    }
};

#endif // __ARCH_X86_UTILITY_HH__
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2017 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "../common/tutorial/tutorial.h"
#include "../common/tutorial/tutorial_device.h"
#include "../../include/embree2/rtcore.h"
#include "../../kernels/bvh/bvh.h"
#include "../../kernels/geometry/trianglev.h"

namespace embree
{
  /* Visual Studio 2012 link error workaround */
  PrecomputedBezierBasis bezier_basis0;
  PrecomputedBezierBasis bezier_basis1;

  /* error reporting function */
  void error_handler(void* userPtr, const RTCError code, const char* str)
  {
    if (code == RTC_NO_ERROR)
      return;

    printf("Embree: ");
    switch (code) {
    case RTC_UNKNOWN_ERROR    : printf("RTC_UNKNOWN_ERROR"); break;
    case RTC_INVALID_ARGUMENT : printf("RTC_INVALID_ARGUMENT"); break;
    case RTC_INVALID_OPERATION: printf("RTC_INVALID_OPERATION"); break;
    case RTC_OUT_OF_MEMORY    : printf("RTC_OUT_OF_MEMORY"); break;
    case RTC_UNSUPPORTED_CPU  : printf("RTC_UNSUPPORTED_CPU"); break;
    case RTC_CANCELLED        : printf("RTC_CANCELLED"); break;
    default                   : printf("invalid error code"); break;
    }
    if (str) {
      printf(" (");
      while (*str) putchar(*str++);
      printf(")\n");
    }
    exit(1);
  }

  /* adds a cube to the scene */
  unsigned int addCube (RTCScene scene_i, const Vec3fa& pos)
  {
    /* create a triangulated cube with 12 triangles and 8 vertices */
    unsigned int mesh = rtcNewTriangleMesh (scene_i, RTC_GEOMETRY_STATIC, 12, 8);

    /* set vertices */
    Vec3fa* vertices = (Vec3fa*) rtcMapBuffer(scene_i,mesh,RTC_VERTEX_BUFFER);
    vertices[0].x = pos.x + -1; vertices[0].y = pos.y + -1; vertices[0].z = pos.z + -1;
    vertices[1].x = pos.x + -1; vertices[1].y = pos.y + -1; vertices[1].z = pos.z + +1;
    vertices[2].x = pos.x + -1; vertices[2].y = pos.y + +1; vertices[2].z = pos.z + -1;
    vertices[3].x = pos.x + -1; vertices[3].y = pos.y + +1; vertices[3].z = pos.z + +1;
    vertices[4].x = pos.x + +1; vertices[4].y = pos.y + -1; vertices[4].z = pos.z + -1;
    vertices[5].x = pos.x + +1; vertices[5].y = pos.y + -1; vertices[5].z = pos.z + +1;
    vertices[6].x = pos.x + +1; vertices[6].y = pos.y + +1; vertices[6].z = pos.z + -1;
    vertices[7].x = pos.x + +1; vertices[7].y = pos.y + +1; vertices[7].z = pos.z + +1;
    rtcUnmapBuffer(scene_i,mesh,RTC_VERTEX_BUFFER);

    /* set triangles */
    int tri = 0;
    Triangle* triangles = (Triangle*) rtcMapBuffer(scene_i,mesh,RTC_INDEX_BUFFER);

    // left side
    triangles[tri].v0 = 0; triangles[tri].v1 = 2; triangles[tri].v2 = 1; tri++;
    triangles[tri].v0 = 1; triangles[tri].v1 = 2; triangles[tri].v2 = 3; tri++;

    // right side
    triangles[tri].v0 = 4; triangles[tri].v1 = 5; triangles[tri].v2 = 6; tri++;
    triangles[tri].v0 = 5; triangles[tri].v1 = 7; triangles[tri].v2 = 6; tri++;

    // bottom side
    triangles[tri].v0 = 0; triangles[tri].v1 = 1; triangles[tri].v2 = 4; tri++;
    triangles[tri].v0 = 1; triangles[tri].v1 = 5; triangles[tri].v2 = 4; tri++;

    // top side
    triangles[tri].v0 = 2; triangles[tri].v1 = 6; triangles[tri].v2 = 3; tri++;
    triangles[tri].v0 = 3; triangles[tri].v1 = 6; triangles[tri].v2 = 7; tri++;

    // front side
    triangles[tri].v0 = 0; triangles[tri].v1 = 4; triangles[tri].v2 = 2; tri++;
    triangles[tri].v0 = 2; triangles[tri].v1 = 4; triangles[tri].v2 = 6; tri++;

    // back side
    triangles[tri].v0 = 1; triangles[tri].v1 = 3; triangles[tri].v2 = 5; tri++;
    triangles[tri].v0 = 3; triangles[tri].v1 = 7; triangles[tri].v2 = 5; tri++;

    rtcUnmapBuffer(scene_i,mesh,RTC_INDEX_BUFFER);

    return mesh;
  }

  /* adds a ground plane to the scene */
  unsigned int addGroundPlane (RTCScene scene_i)
  {
    /* create a triangulated plane with 2 triangles and 4 vertices */
    unsigned int mesh = rtcNewTriangleMesh (scene_i, RTC_GEOMETRY_STATIC, 2, 4);

    /* set vertices */
    Vec3fa* vertices = (Vec3fa*) rtcMapBuffer(scene_i,mesh,RTC_VERTEX_BUFFER);
    vertices[0].x = -10; vertices[0].y = -2; vertices[0].z = -10;
    vertices[1].x = -10; vertices[1].y = -2; vertices[1].z = +10;
    vertices[2].x = +10; vertices[2].y = -2; vertices[2].z = -10;
    vertices[3].x = +10; vertices[3].y = -2; vertices[3].z = +10;
    rtcUnmapBuffer(scene_i,mesh,RTC_VERTEX_BUFFER);

    /* set triangles */
    Triangle* triangles = (Triangle*) rtcMapBuffer(scene_i,mesh,RTC_INDEX_BUFFER);
    triangles[0].v0 = 0; triangles[0].v1 = 2; triangles[0].v2 = 1;
    triangles[1].v0 = 1; triangles[1].v1 = 2; triangles[1].v2 = 3;
    rtcUnmapBuffer(scene_i,mesh,RTC_INDEX_BUFFER);

    return mesh;
  }

  /* adds a hair to the scene */
  unsigned int addHair(RTCScene scene_i)
  {
    unsigned int geomID = rtcNewHairGeometry (scene_i, RTC_GEOMETRY_STATIC, 1, 4, 1);

    vfloat4* pos = (vfloat4*) rtcMapBuffer(scene_i,geomID,RTC_VERTEX_BUFFER);
    pos[0] = vfloat4(0.0f,0.0f,0.0f,0.1f);
    pos[1] = vfloat4(0.0f,1.0f,0.0f,0.1f);
    pos[2] = vfloat4(0.0f,2.0f,0.0f,0.1f);
    pos[3] = vfloat4(0.0f,3.0f,0.0f,0.1f);
    rtcUnmapBuffer(scene_i,geomID,RTC_VERTEX_BUFFER);

    int* index = (int*) rtcMapBuffer(scene_i,geomID,RTC_INDEX_BUFFER);
    index[0] = 0;
    rtcUnmapBuffer(scene_i,geomID,RTC_INDEX_BUFFER);

    return geomID;
  }

  /* prints the bvh4.triangle4v data structure */
  void print_bvh4_triangle4v(BVH4::NodeRef node, size_t depth)
  {
    if (node.isAlignedNode())
    {
      BVH4::AlignedNode* n = node.alignedNode();

      std::cout << "AlignedNode {" << std::endl;
      for (size_t i=0; i<4; i++)
      {
        for (size_t k=0; k<depth; k++) std::cout << "  ";
        std::cout << "  bounds" << i << " = " << n->bounds(i) << std::endl;
      }

      for (size_t i=0; i<4; i++)
      {
        if (n->child(i) == BVH4::emptyNode)
          continue;

        for (size_t k=0; k<depth; k++) std::cout << "  ";
        std::cout << "  child" << i << " = ";
        print_bvh4_triangle4v(n->child(i),depth+1);
      }
      for (size_t k=0; k<depth; k++) std::cout << "  ";
      std::cout << "}" << std::endl;
    }
    else
    {
      size_t num;
      const Triangle4v* tri = (const Triangle4v*) node.leaf(num);

      std::cout << "Leaf {" << std::endl;
      for (size_t i=0; i<num; i++) {
        for (size_t j=0; j<tri[i].size(); j++) {
          for (size_t k=0; k<depth; k++) std::cout << "  ";
          std::cout << "  Triangle { v0 = (" << tri[i].v0.x[j] << ", " << tri[i].v0.y[j] << ", " << tri[i].v0.z[j] << "),  "
            "v1 = (" << tri[i].v1.x[j] << ", " << tri[i].v1.y[j] << ", " << tri[i].v1.z[j] << "), "
            "v2 = (" << tri[i].v2.x[j] << ", " << tri[i].v2.y[j] << ", " << tri[i].v2.z[j] << "), "
            "geomID = " << tri[i].geomID(j) << ", primID = " << tri[i].primID(j) << " }" << std::endl;
        }
      }
      for (size_t k=0; k<depth; k++) std::cout << "  ";
      std::cout << "}" << std::endl;
    }
  }

  /* prints the triangle BVH of a scene */
  void print_bvh(RTCScene scene)
  {
    BVH4* bvh4 = nullptr;

    /* if the scene contains only triangles, the BVH4 acceleration structure can be obtained this way */
    AccelData* accel = ((Accel*)scene)->intersectors.ptr;
    if (accel->type == AccelData::TY_BVH4)
      bvh4 = (BVH4*)accel;

    /* if there are also other geometry types, one has to iterate over the toplevel AccelN structure */
    else if (accel->type == AccelData::TY_ACCELN)
    {
      AccelN* accelN = (AccelN*)(accel);
      for (size_t i=0; i<accelN->accels.size(); i++) {
        if (accelN->accels[i]->intersectors.ptr->type == AccelData::TY_BVH4) {
          bvh4 = (BVH4*)accelN->accels[i]->intersectors.ptr;
          if (bvh4->primTy.name == "triangle4v") break;
          bvh4 = nullptr;
        }
      }
    }
    if (bvh4 == nullptr)
      throw std::runtime_error("cannot access BVH4 acceleration structure"); // will not happen if you use this Embree version

    /* now lets print the entire hierarchy */
    print_bvh4_triangle4v(bvh4->root,0);
  }

  /* main function in embree namespace */
  int main(int argc, char** argv)
  {
    /* for best performance set FTZ and DAZ flags in MXCSR control and status register */
    _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
    _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);

    /* create new Embree device and force bvh4.triangle4v hierarchy for triangles */
    RTCDevice device = rtcNewDevice("tri_accel=bvh4.triangle4v");
    error_handler(nullptr,rtcDeviceGetError(device));

    /* set error handler */
    rtcDeviceSetErrorFunction2(device,error_handler,nullptr);

    /* create scene */
    RTCScene scene = rtcDeviceNewScene(device,RTC_SCENE_STATIC,RTC_INTERSECT1);
    addCube(scene,Vec3fa(-1,0,0));
    addCube(scene,Vec3fa(1,0,0));
    addCube(scene,Vec3fa(0,0,-1));
    addCube(scene,Vec3fa(0,0,1));
    addHair(scene);
    addGroundPlane(scene);
    rtcCommit (scene);
    /* print triangle BVH */
    print_bvh(scene);

    /* cleanup */
    rtcDeleteScene (scene);
    rtcDeleteDevice(device);
    return 0;
  }
}

int main(int argc, char** argv)
{
  try {
    return embree::main(argc, argv);
  }
  catch (const std::exception& e) {
    std::cout << "Error: " << e.what() << std::endl;
    return 1;
  }
  catch (...) {
    std::cout << "Error: unknown exception caught." << std::endl;
    return 1;
  }
}
<commit_msg>compile fix for V110<commit_after>// ======================================================================== //
// Copyright 2009-2017 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "../common/tutorial/tutorial.h"
#include "../common/tutorial/tutorial_device.h"
#include "../../include/embree2/rtcore.h"
#include "../../kernels/bvh/bvh.h"
#include "../../kernels/geometry/trianglev.h"

namespace embree
{
  /* Visual Studio 2012 link error workaround */
  PrecomputedBezierBasis bezier_basis0;
  PrecomputedBezierBasis bezier_basis1;
  PrecomputedBSplineBasis bspline_basis0;
  PrecomputedBSplineBasis bspline_basis1;

  /* error reporting function */
  void error_handler(void* userPtr, const RTCError code, const char* str)
  {
    if (code == RTC_NO_ERROR)
      return;

    printf("Embree: ");
    switch (code) {
    case RTC_UNKNOWN_ERROR    : printf("RTC_UNKNOWN_ERROR"); break;
    case RTC_INVALID_ARGUMENT : printf("RTC_INVALID_ARGUMENT"); break;
    case RTC_INVALID_OPERATION: printf("RTC_INVALID_OPERATION"); break;
    case RTC_OUT_OF_MEMORY    : printf("RTC_OUT_OF_MEMORY"); break;
    case RTC_UNSUPPORTED_CPU  : printf("RTC_UNSUPPORTED_CPU"); break;
    case RTC_CANCELLED        : printf("RTC_CANCELLED"); break;
    default                   : printf("invalid error code"); break;
    }
    if (str) {
      printf(" (");
      while (*str) putchar(*str++);
      printf(")\n");
    }
    exit(1);
  }

  /* adds a cube to the scene */
  unsigned int addCube (RTCScene scene_i, const Vec3fa& pos)
  {
    /* create a triangulated cube with 12 triangles and 8 vertices */
    unsigned int mesh = rtcNewTriangleMesh (scene_i, RTC_GEOMETRY_STATIC, 12, 8);

    /* set vertices */
    Vec3fa* vertices = (Vec3fa*) rtcMapBuffer(scene_i,mesh,RTC_VERTEX_BUFFER);
    vertices[0].x = pos.x + -1; vertices[0].y = pos.y + -1; vertices[0].z = pos.z + -1;
    vertices[1].x = pos.x + -1; vertices[1].y = pos.y + -1; vertices[1].z = pos.z + +1;
    vertices[2].x = pos.x + -1; vertices[2].y = pos.y + +1; vertices[2].z = pos.z + -1;
    vertices[3].x = pos.x + -1; vertices[3].y = pos.y + +1; vertices[3].z = pos.z + +1;
    vertices[4].x = pos.x + +1; vertices[4].y = pos.y + -1; vertices[4].z = pos.z + -1;
    vertices[5].x = pos.x + +1; vertices[5].y = pos.y + -1; vertices[5].z = pos.z + +1;
    vertices[6].x = pos.x + +1; vertices[6].y = pos.y + +1; vertices[6].z = pos.z + -1;
    vertices[7].x = pos.x + +1; vertices[7].y = pos.y + +1; vertices[7].z = pos.z + +1;
    rtcUnmapBuffer(scene_i,mesh,RTC_VERTEX_BUFFER);

    /* set triangles */
    int tri = 0;
    Triangle* triangles = (Triangle*) rtcMapBuffer(scene_i,mesh,RTC_INDEX_BUFFER);

    // left side
    triangles[tri].v0 = 0; triangles[tri].v1 = 2; triangles[tri].v2 = 1; tri++;
    triangles[tri].v0 = 1; triangles[tri].v1 = 2; triangles[tri].v2 = 3; tri++;

    // right side
    triangles[tri].v0 = 4; triangles[tri].v1 = 5; triangles[tri].v2 = 6; tri++;
    triangles[tri].v0 = 5; triangles[tri].v1 = 7; triangles[tri].v2 = 6; tri++;

    // bottom side
    triangles[tri].v0 = 0; triangles[tri].v1 = 1; triangles[tri].v2 = 4; tri++;
    triangles[tri].v0 = 1; triangles[tri].v1 = 5; triangles[tri].v2 = 4; tri++;

    // top side
    triangles[tri].v0 = 2; triangles[tri].v1 = 6; triangles[tri].v2 = 3; tri++;
    triangles[tri].v0 = 3; triangles[tri].v1 = 6; triangles[tri].v2 = 7; tri++;

    // front side
    triangles[tri].v0 = 0; triangles[tri].v1 = 4; triangles[tri].v2 = 2; tri++;
    triangles[tri].v0 = 2; triangles[tri].v1 = 4; triangles[tri].v2 = 6; tri++;

    // back side
    triangles[tri].v0 = 1; triangles[tri].v1 = 3; triangles[tri].v2 = 5; tri++;
    triangles[tri].v0 = 3; triangles[tri].v1 = 7; triangles[tri].v2 = 5; tri++;

    rtcUnmapBuffer(scene_i,mesh,RTC_INDEX_BUFFER);

    return mesh;
  }

  /* adds a ground plane to the scene */
  unsigned int addGroundPlane (RTCScene scene_i)
  {
    /* create a triangulated plane with 2 triangles and 4 vertices */
    unsigned int mesh = rtcNewTriangleMesh (scene_i, RTC_GEOMETRY_STATIC, 2, 4);

    /* set vertices */
    Vec3fa* vertices = (Vec3fa*) rtcMapBuffer(scene_i,mesh,RTC_VERTEX_BUFFER);
    vertices[0].x = -10; vertices[0].y = -2; vertices[0].z = -10;
    vertices[1].x = -10; vertices[1].y = -2; vertices[1].z = +10;
    vertices[2].x = +10; vertices[2].y = -2; vertices[2].z = -10;
    vertices[3].x = +10; vertices[3].y = -2; vertices[3].z = +10;
    rtcUnmapBuffer(scene_i,mesh,RTC_VERTEX_BUFFER);

    /* set triangles */
    Triangle* triangles = (Triangle*) rtcMapBuffer(scene_i,mesh,RTC_INDEX_BUFFER);
    triangles[0].v0 = 0; triangles[0].v1 = 2; triangles[0].v2 = 1;
    triangles[1].v0 = 1; triangles[1].v1 = 2; triangles[1].v2 = 3;
    rtcUnmapBuffer(scene_i,mesh,RTC_INDEX_BUFFER);

    return mesh;
  }

  /* adds a hair to the scene */
  unsigned int addHair(RTCScene scene_i)
  {
    unsigned int geomID = rtcNewHairGeometry (scene_i, RTC_GEOMETRY_STATIC, 1, 4, 1);

    vfloat4* pos = (vfloat4*) rtcMapBuffer(scene_i,geomID,RTC_VERTEX_BUFFER);
    pos[0] = vfloat4(0.0f,0.0f,0.0f,0.1f);
    pos[1] = vfloat4(0.0f,1.0f,0.0f,0.1f);
    pos[2] = vfloat4(0.0f,2.0f,0.0f,0.1f);
    pos[3] = vfloat4(0.0f,3.0f,0.0f,0.1f);
    rtcUnmapBuffer(scene_i,geomID,RTC_VERTEX_BUFFER);

    int* index = (int*) rtcMapBuffer(scene_i,geomID,RTC_INDEX_BUFFER);
    index[0] = 0;
    rtcUnmapBuffer(scene_i,geomID,RTC_INDEX_BUFFER);

    return geomID;
  }

  /* prints the bvh4.triangle4v data structure */
  void print_bvh4_triangle4v(BVH4::NodeRef node, size_t depth)
  {
    if (node.isAlignedNode())
    {
      BVH4::AlignedNode* n = node.alignedNode();

      std::cout << "AlignedNode {" << std::endl;
      for (size_t i=0; i<4; i++)
      {
        for (size_t k=0; k<depth; k++) std::cout << "  ";
        std::cout << "  bounds" << i << " = " << n->bounds(i) << std::endl;
      }

      for (size_t i=0; i<4; i++)
      {
        if (n->child(i) == BVH4::emptyNode)
          continue;

        for (size_t k=0; k<depth; k++) std::cout << "  ";
        std::cout << "  child" << i << " = ";
        print_bvh4_triangle4v(n->child(i),depth+1);
      }
      for (size_t k=0; k<depth; k++) std::cout << "  ";
      std::cout << "}" << std::endl;
    }
    else
    {
      size_t num;
      const Triangle4v* tri = (const Triangle4v*) node.leaf(num);

      std::cout << "Leaf {" << std::endl;
      for (size_t i=0; i<num; i++) {
        for (size_t j=0; j<tri[i].size(); j++) {
          for (size_t k=0; k<depth; k++) std::cout << "  ";
          std::cout << "  Triangle { v0 = (" << tri[i].v0.x[j] << ", " << tri[i].v0.y[j] << ", " << tri[i].v0.z[j] << "),  "
            "v1 = (" << tri[i].v1.x[j] << ", " << tri[i].v1.y[j] << ", " << tri[i].v1.z[j] << "), "
            "v2 = (" << tri[i].v2.x[j] << ", " << tri[i].v2.y[j] << ", " << tri[i].v2.z[j] << "), "
            "geomID = " << tri[i].geomID(j) << ", primID = " << tri[i].primID(j) << " }" << std::endl;
        }
      }
      for (size_t k=0; k<depth; k++) std::cout << "  ";
      std::cout << "}" << std::endl;
    }
  }

  /* prints the triangle BVH of a scene */
  void print_bvh(RTCScene scene)
  {
    BVH4* bvh4 = nullptr;

    /* if the scene contains only triangles, the BVH4 acceleration structure can be obtained this way */
    AccelData* accel = ((Accel*)scene)->intersectors.ptr;
    if (accel->type == AccelData::TY_BVH4)
      bvh4 = (BVH4*)accel;

    /* if there are also other geometry types, one has to iterate over the toplevel AccelN structure */
    else if (accel->type == AccelData::TY_ACCELN)
    {
      AccelN* accelN = (AccelN*)(accel);
      for (size_t i=0; i<accelN->accels.size(); i++) {
        if (accelN->accels[i]->intersectors.ptr->type == AccelData::TY_BVH4) {
          bvh4 = (BVH4*)accelN->accels[i]->intersectors.ptr;
          if (bvh4->primTy.name == "triangle4v") break;
          bvh4 = nullptr;
        }
      }
    }
    if (bvh4 == nullptr)
      throw std::runtime_error("cannot access BVH4 acceleration structure"); // will not happen if you use this Embree version

    /* now lets print the entire hierarchy */
    print_bvh4_triangle4v(bvh4->root,0);
  }

  /* main function in embree namespace */
  int main(int argc, char** argv)
  {
    /* for best performance set FTZ and DAZ flags in MXCSR control and status register */
    _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
    _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);

    /* create new Embree device and force bvh4.triangle4v hierarchy for triangles */
    RTCDevice device = rtcNewDevice("tri_accel=bvh4.triangle4v");
    error_handler(nullptr,rtcDeviceGetError(device));

    /* set error handler */
    rtcDeviceSetErrorFunction2(device,error_handler,nullptr);

    /* create scene */
    RTCScene scene = rtcDeviceNewScene(device,RTC_SCENE_STATIC,RTC_INTERSECT1);
    addCube(scene,Vec3fa(-1,0,0));
    addCube(scene,Vec3fa(1,0,0));
    addCube(scene,Vec3fa(0,0,-1));
    addCube(scene,Vec3fa(0,0,1));
    addHair(scene);
    addGroundPlane(scene);
    rtcCommit (scene);
    /* print triangle BVH */
    print_bvh(scene);

    /* cleanup */
    rtcDeleteScene (scene);
    rtcDeleteDevice(device);
    return 0;
  }
}

int main(int argc, char** argv)
{
  try {
    return embree::main(argc, argv);
  }
  catch (const std::exception& e) {
    std::cout << "Error: " << e.what() << std::endl;
    return 1;
  }
  catch (...) {
    std::cout << "Error: unknown exception caught." << std::endl;
    return 1;
  }
}
<|endoftext|>