<commit_before>// Copyright (c) 2011-2017 The Bitcoin developers
// Copyright (c) 2015-2021 The PIVX developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "qt/rpcexecutor.h"

#include "rpc/client.h"

#include <univalue.h>

QString RPCExecutor::categoryClass(int category)
{
    switch (category) {
    case CMD_REQUEST:
        return "cmd-request";
        break;
    case CMD_REPLY:
        return "cmd-reply";
        break;
    case CMD_ERROR:
        return "cmd-error";
        break;
    default:
        return "misc";
    }
}

void RPCExecutor::request(const QString& command)
{
    try
    {
        std::string result;
        std::string executableCommand = command.toStdString() + "\n";

        // Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply.
        if(executableCommand == "help-console\n")
        {
            Q_EMIT reply(CMD_REPLY, QString(("\n"
                "This console accepts RPC commands using the standard syntax.\n"
                "   example:    getblockhash 0\n\n"

                "This console can also accept RPC commands using parenthesized syntax.\n"
                "   example:    getblockhash(0)\n\n"

                "Commands may be nested when specified with the parenthesized syntax.\n"
                "   example:    getblock(getblockhash(0) true)\n\n"

                "A space or a comma can be used to delimit arguments for either syntax.\n"
                "   example:    getblockhash 0\n"
                "               getblockhash,0\n\n"

                "Named results can be queried with a non-quoted key string in brackets.\n"
                "   example:    getblock(getblockhash(0) true)[tx]\n\n"

                "Results without keys can be queried using an integer in brackets.\n"
                "   example:    getblock(getblockhash(0),true)[tx][0]\n\n")));
            return;
        }
        if(!ExecuteCommandLine(result, executableCommand))
        {
            Q_EMIT reply(CMD_ERROR, QString("Parse error: unbalanced ' or \""));
            return;
        }
        Q_EMIT reply(CMD_REPLY, QString::fromStdString(result));
    }
    catch (UniValue& objError)
    {
        try {
            // Nice formatting for standard-format error
            int code = find_value(objError, "code").get_int();
            std::string message = find_value(objError, "message").get_str();
            Q_EMIT reply(CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");

        } catch (const std::runtime_error&) {
            // raised when converting to invalid type, i.e. missing code or message
            // Show raw JSON object
            Q_EMIT reply(CMD_ERROR, QString::fromStdString(objError.write()));
        }
    } catch (const std::exception& e) {
        Q_EMIT reply(CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

/**
 * Split shell command line into a list of arguments and execute the command(s).
 * Aims to emulate \c bash and friends.
 *
 * - Command nesting is possible with brackets [example: validateaddress(getnewaddress())]
 * - Arguments are delimited with whitespace or comma
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Text can be "double" or 'single' quoted
 * - The backslash \c \ is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
 *   - Within single quotes, no escaping is possible and no special interpretation takes place
 *
 * @param[out]   result      stringified Result from the executed command(chain)
 * @param[in]    strCommand  Command line to split
 */
bool RPCExecutor::ExecuteCommandLine(std::string& strResult, const std::string& strCommand)
{
    std::vector< std::vector<std::string> > stack;
    stack.push_back(std::vector<std::string>());

    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_DOUBLEQUOTED,
        STATE_COMMAND_EXECUTED,
        STATE_COMMAND_EXECUTED_INNER
    } state = STATE_EATING_SPACES;
    std::string curarg;
    UniValue lastResult;

    std::string strCommandTerminated = strCommand;
    if (strCommandTerminated.back() != '\n')
        strCommandTerminated += "\n";
    for(char ch: strCommandTerminated)
    {
        switch(state)
        {
            case STATE_COMMAND_EXECUTED_INNER:
            case STATE_COMMAND_EXECUTED:
            {
                bool breakParsing = true;
                switch(ch)
                {
                    case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break;
                    default:
                        if (state == STATE_COMMAND_EXECUTED_INNER)
                        {
                            if (ch != ']')
                            {
                                // append char to the current argument (which is also used for the query command)
                                curarg += ch;
                                break;
                            }
                            if (curarg.size())
                            {
                                // if we have a value query, query arrays with index and objects with a string key
                                UniValue subelement;
                                if (lastResult.isArray())
                                {
                                    for(char argch: curarg)
                                        if (!std::isdigit(argch))
                                            throw std::runtime_error("Invalid result query");
                                    subelement = lastResult[atoi(curarg.c_str())];
                                }
                                else if (lastResult.isObject())
                                    subelement = find_value(lastResult, curarg);
                                else
                                    throw std::runtime_error("Invalid result query"); //no array or object: abort
                                lastResult = subelement;
                            }

                            state = STATE_COMMAND_EXECUTED;
                            break;
                        }
                        // don't break parsing when the char is required for the next argument
                        breakParsing = false;

                        // pop the stack and return the result to the current command arguments
                        stack.pop_back();

                        // don't stringify the json in case of a string to avoid doublequotes
                        if (lastResult.isStr())
                            curarg = lastResult.get_str();
                        else
                            curarg = lastResult.write(2);

                        // if we have a non empty result, use it as stack argument otherwise as general result
                        if (curarg.size())
                        {
                            if (stack.size())
                                stack.back().push_back(curarg);
                            else
                                strResult = curarg;
                        }
                        curarg.clear();
                        // assume eating space state
                        state = STATE_EATING_SPACES;
                }
                if (breakParsing)
                    break;
            }
            case STATE_ARGUMENT: // In or after argument
            case STATE_EATING_SPACES: // Handle runs of whitespace
                switch(ch)
            {
                case '"': state = STATE_DOUBLEQUOTED; break;
                case '\'': state = STATE_SINGLEQUOTED; break;
                case '\\': state = STATE_ESCAPE_OUTER; break;
                case '(': case ')': case '\n':
                    if (state == STATE_ARGUMENT)
                    {
                        if (ch == '(' && stack.size() && stack.back().size() > 0)
                            stack.push_back(std::vector<std::string>());
                        if (curarg.size())
                        {
                            // don't allow commands after executed commands on baselevel
                            if (!stack.size())
                                throw std::runtime_error("Invalid Syntax");
                            stack.back().push_back(curarg);
                        }
                        curarg.clear();
                        state = STATE_EATING_SPACES;
                    }
                    if ((ch == ')' || ch == '\n') && stack.size() > 0)
                    {
                        std::string strPrint;
                        // Convert argument list to JSON objects in method-dependent way,
                        // and pass it along with the method name to the dispatcher.
                        JSONRPCRequest req;
                        req.params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));
                        req.strMethod = stack.back()[0];
                        lastResult = tableRPC.execute(req);
                        state = STATE_COMMAND_EXECUTED;
                        curarg.clear();
                    }
                    break;
                case ' ': case ',': case '\t':
                    if(state == STATE_ARGUMENT) // Space ends argument
                    {
                        if (curarg.size())
                            stack.back().push_back(curarg);
                        curarg.clear();
                    }
                    state = STATE_EATING_SPACES;
                    break;
                default: curarg += ch; state = STATE_ARGUMENT;
            }
                break;
            case STATE_SINGLEQUOTED: // Single-quoted string
                switch(ch)
            {
                case '\'': state = STATE_ARGUMENT; break;
                default: curarg += ch;
            }
                break;
            case STATE_DOUBLEQUOTED: // Double-quoted string
                switch(ch)
            {
                case '"': state = STATE_ARGUMENT; break;
                case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
                default: curarg += ch;
            }
                break;
            case STATE_ESCAPE_OUTER: // '\' outside quotes
                curarg += ch; state = STATE_ARGUMENT;
                break;
            case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
                if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
                curarg += ch; state = STATE_DOUBLEQUOTED;
                break;
        }
    }
    switch (state) // final state
    {
        case STATE_COMMAND_EXECUTED:
            if (lastResult.isStr())
                strResult = lastResult.get_str();
            else
                strResult = lastResult.write(2);
        case STATE_ARGUMENT:
        case STATE_EATING_SPACES:
            return true;
        default: // ERROR to end in one of the other states
            return false;
    }
}
<commit_msg>[Qt] Use wallet 0 in rpc console if running with multiple wallets<commit_after>// Copyright (c) 2011-2017 The Bitcoin developers
// Copyright (c) 2015-2021 The PIVX developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "qt/rpcexecutor.h"

#include "rpc/client.h"

#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif

#include <QUrlQuery>

#include <univalue.h>

QString RPCExecutor::categoryClass(int category)
{
    switch (category) {
    case CMD_REQUEST:
        return "cmd-request";
        break;
    case CMD_REPLY:
        return "cmd-reply";
        break;
    case CMD_ERROR:
        return "cmd-error";
        break;
    default:
        return "misc";
    }
}

void RPCExecutor::request(const QString& command)
{
    try
    {
        std::string result;
        std::string executableCommand = command.toStdString() + "\n";

        // Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply.
        if(executableCommand == "help-console\n")
        {
            Q_EMIT reply(CMD_REPLY, QString(("\n"
                "This console accepts RPC commands using the standard syntax.\n"
                "   example:    getblockhash 0\n\n"

                "This console can also accept RPC commands using parenthesized syntax.\n"
                "   example:    getblockhash(0)\n\n"

                "Commands may be nested when specified with the parenthesized syntax.\n"
                "   example:    getblock(getblockhash(0) true)\n\n"

                "A space or a comma can be used to delimit arguments for either syntax.\n"
                "   example:    getblockhash 0\n"
                "               getblockhash,0\n\n"

                "Named results can be queried with a non-quoted key string in brackets.\n"
                "   example:    getblock(getblockhash(0) true)[tx]\n\n"

                "Results without keys can be queried using an integer in brackets.\n"
                "   example:    getblock(getblockhash(0),true)[tx][0]\n\n")));
            return;
        }
        if(!ExecuteCommandLine(result, executableCommand))
        {
            Q_EMIT reply(CMD_ERROR, QString("Parse error: unbalanced ' or \""));
            return;
        }
        Q_EMIT reply(CMD_REPLY, QString::fromStdString(result));
    }
    catch (UniValue& objError)
    {
        try {
            // Nice formatting for standard-format error
            int code = find_value(objError, "code").get_int();
            std::string message = find_value(objError, "message").get_str();
            Q_EMIT reply(CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");

        } catch (const std::runtime_error&) {
            // raised when converting to invalid type, i.e. missing code or message
            // Show raw JSON object
            Q_EMIT reply(CMD_ERROR, QString::fromStdString(objError.write()));
        }
    } catch (const std::exception& e) {
        Q_EMIT reply(CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

/**
 * Split shell command line into a list of arguments and execute the command(s).
 * Aims to emulate \c bash and friends.
 *
 * - Command nesting is possible with brackets [example: validateaddress(getnewaddress())]
 * - Arguments are delimited with whitespace or comma
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Text can be "double" or 'single' quoted
 * - The backslash \c \ is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
 *   - Within single quotes, no escaping is possible and no special interpretation takes place
 *
 * @param[out]   result      stringified Result from the executed command(chain)
 * @param[in]    strCommand  Command line to split
 */
bool RPCExecutor::ExecuteCommandLine(std::string& strResult, const std::string& strCommand)
{
    std::vector< std::vector<std::string> > stack;
    stack.push_back(std::vector<std::string>());

    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_DOUBLEQUOTED,
        STATE_COMMAND_EXECUTED,
        STATE_COMMAND_EXECUTED_INNER
    } state = STATE_EATING_SPACES;
    std::string curarg;
    UniValue lastResult;

    std::string strCommandTerminated = strCommand;
    if (strCommandTerminated.back() != '\n')
        strCommandTerminated += "\n";
    for(char ch: strCommandTerminated)
    {
        switch(state)
        {
            case STATE_COMMAND_EXECUTED_INNER:
            case STATE_COMMAND_EXECUTED:
            {
                bool breakParsing = true;
                switch(ch)
                {
                    case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break;
                    default:
                        if (state == STATE_COMMAND_EXECUTED_INNER)
                        {
                            if (ch != ']')
                            {
                                // append char to the current argument (which is also used for the query command)
                                curarg += ch;
                                break;
                            }
                            if (curarg.size())
                            {
                                // if we have a value query, query arrays with index and objects with a string key
                                UniValue subelement;
                                if (lastResult.isArray())
                                {
                                    for(char argch: curarg)
                                        if (!std::isdigit(argch))
                                            throw std::runtime_error("Invalid result query");
                                    subelement = lastResult[atoi(curarg.c_str())];
                                }
                                else if (lastResult.isObject())
                                    subelement = find_value(lastResult, curarg);
                                else
                                    throw std::runtime_error("Invalid result query"); //no array or object: abort
                                lastResult = subelement;
                            }

                            state = STATE_COMMAND_EXECUTED;
                            break;
                        }
                        // don't break parsing when the char is required for the next argument
                        breakParsing = false;

                        // pop the stack and return the result to the current command arguments
                        stack.pop_back();

                        // don't stringify the json in case of a string to avoid doublequotes
                        if (lastResult.isStr())
                            curarg = lastResult.get_str();
                        else
                            curarg = lastResult.write(2);

                        // if we have a non empty result, use it as stack argument otherwise as general result
                        if (curarg.size())
                        {
                            if (stack.size())
                                stack.back().push_back(curarg);
                            else
                                strResult = curarg;
                        }
                        curarg.clear();
                        // assume eating space state
                        state = STATE_EATING_SPACES;
                }
                if (breakParsing)
                    break;
            }
            case STATE_ARGUMENT: // In or after argument
            case STATE_EATING_SPACES: // Handle runs of whitespace
                switch(ch)
            {
                case '"': state = STATE_DOUBLEQUOTED; break;
                case '\'': state = STATE_SINGLEQUOTED; break;
                case '\\': state = STATE_ESCAPE_OUTER; break;
                case '(': case ')': case '\n':
                    if (state == STATE_ARGUMENT)
                    {
                        if (ch == '(' && stack.size() && stack.back().size() > 0)
                            stack.push_back(std::vector<std::string>());
                        if (curarg.size())
                        {
                            // don't allow commands after executed commands on baselevel
                            if (!stack.size())
                                throw std::runtime_error("Invalid Syntax");
                            stack.back().push_back(curarg);
                        }
                        curarg.clear();
                        state = STATE_EATING_SPACES;
                    }
                    if ((ch == ')' || ch == '\n') && stack.size() > 0)
                    {
                        std::string strPrint;
                        // Convert argument list to JSON objects in method-dependent way,
                        // and pass it along with the method name to the dispatcher.
                        JSONRPCRequest req;
                        req.params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));
                        req.strMethod = stack.back()[0];
#ifdef ENABLE_WALLET
                        // TODO: Move this logic to WalletModel
                        if (!vpwallets.empty()) {
                            // in Qt, use always the wallet with index 0 when running with multiple wallets
                            QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(vpwallets[0]->GetName()));
                            req.URI = "/wallet/"+std::string(encodedName.constData(), encodedName.length());
                        }
#endif
                        lastResult = tableRPC.execute(req);
                        state = STATE_COMMAND_EXECUTED;
                        curarg.clear();
                    }
                    break;
                case ' ': case ',': case '\t':
                    if(state == STATE_ARGUMENT) // Space ends argument
                    {
                        if (curarg.size())
                            stack.back().push_back(curarg);
                        curarg.clear();
                    }
                    state = STATE_EATING_SPACES;
                    break;
                default: curarg += ch; state = STATE_ARGUMENT;
            }
                break;
            case STATE_SINGLEQUOTED: // Single-quoted string
                switch(ch)
            {
                case '\'': state = STATE_ARGUMENT; break;
                default: curarg += ch;
            }
                break;
            case STATE_DOUBLEQUOTED: // Double-quoted string
                switch(ch)
            {
                case '"': state = STATE_ARGUMENT; break;
                case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
                default: curarg += ch;
            }
                break;
            case STATE_ESCAPE_OUTER: // '\' outside quotes
                curarg += ch; state = STATE_ARGUMENT;
                break;
            case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
                if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
                curarg += ch; state = STATE_DOUBLEQUOTED;
                break;
        }
    }
    switch (state) // final state
    {
        case STATE_COMMAND_EXECUTED:
            if (lastResult.isStr())
                strResult = lastResult.get_str();
            else
                strResult = lastResult.write(2);
        case STATE_ARGUMENT:
        case STATE_EATING_SPACES:
            return true;
        default: // ERROR to end in one of the other states
            return false;
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "walletframe.h"

#include "bitcoingui.h"
#include "walletview.h"

#include <cstdio>

#include <QHBoxLayout>
#include <QLabel>

WalletFrame::WalletFrame(BitcoinGUI *_gui) :
    QFrame(_gui),
    gui(_gui)
{
    // Leave HBox hook for adding a list view later
    QHBoxLayout *walletFrameLayout = new QHBoxLayout(this);
    setContentsMargins(0,0,0,0);
    walletStack = new QStackedWidget(this);
    walletFrameLayout->setContentsMargins(0,0,0,0);
    walletFrameLayout->addWidget(walletStack);

    QLabel *noWallet = new QLabel(tr("No wallet has been loaded."));
    noWallet->setAlignment(Qt::AlignCenter);
    walletStack->addWidget(noWallet);
}

WalletFrame::~WalletFrame()
{
}

void WalletFrame::setClientModel(ClientModel *clientModel)
{
    this->clientModel = clientModel;
}

bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel)
{
    if (!gui || !clientModel || !walletModel || mapWalletViews.count(name) > 0)
        return false;

    WalletView *walletView = new WalletView(this);
    walletView->setBitcoinGUI(gui);
    walletView->setClientModel(clientModel);
    walletView->setWalletModel(walletModel);
    walletView->showOutOfSyncWarning(bOutOfSync);

     /* TODO we should goto the currently selected page once dynamically adding wallets is supported */
    walletView->setStyleSheet("background-color:white;");
    walletView->gotoOverviewPage();
    walletStack->addWidget(walletView);
    mapWalletViews[name] = walletView;

    // Ensure a walletView is able to show the main window
    connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized()));

    return true;
}

bool WalletFrame::setCurrentWallet(const QString& name)
{
    if (mapWalletViews.count(name) == 0)
        return false;

    WalletView *walletView = mapWalletViews.value(name);
    walletStack->setCurrentWidget(walletView);
    walletView->updateEncryptionStatus();
    return true;
}

bool WalletFrame::removeWallet(const QString &name)
{
    if (mapWalletViews.count(name) == 0)
        return false;

    WalletView *walletView = mapWalletViews.take(name);
    walletStack->removeWidget(walletView);
    return true;
}

void WalletFrame::removeAllWallets()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        walletStack->removeWidget(i.value());
    mapWalletViews.clear();
}

bool WalletFrame::handlePaymentRequest(const SendCoinsRecipient &recipient)
{
    WalletView *walletView = currentWalletView();
    if (!walletView)
        return false;

    return walletView->handlePaymentRequest(recipient);
}

void WalletFrame::showOutOfSyncWarning(bool fShow)
{
    bOutOfSync = fShow;
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->showOutOfSyncWarning(fShow);
}

void WalletFrame::gotoOverviewPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoOverviewPage();
}

void WalletFrame::gotoHistoryPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoHistoryPage();
}

void WalletFrame::gotoReceiveCoinsPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoReceiveCoinsPage();
}

void WalletFrame::gotoSendCoinsPage(QString addr)
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoSendCoinsPage(addr);
}

void WalletFrame::gotoSignMessageTab(QString addr)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->gotoSignMessageTab(addr);
}

void WalletFrame::gotoVerifyMessageTab(QString addr)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->gotoVerifyMessageTab(addr);
}

void WalletFrame::encryptWallet(bool status)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->encryptWallet(status);
}

void WalletFrame::backupWallet()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->backupWallet();
}

void WalletFrame::changePassphrase()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->changePassphrase();
}

void WalletFrame::unlockWallet()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->unlockWallet();
}

void WalletFrame::usedSendingAddresses()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->usedSendingAddresses();
}

void WalletFrame::usedReceivingAddresses()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->usedReceivingAddresses();
}

WalletView *WalletFrame::currentWalletView()
{
    return qobject_cast<WalletView*>(walletStack->currentWidget());
}

<commit_msg>Update walletframe.cpp<commit_after>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "walletframe.h"

#include "bitcoingui.h"
#include "walletview.h"

#include <cstdio>

#include <QHBoxLayout>
#include <QLabel>

WalletFrame::WalletFrame(BitcoinGUI *_gui) :
    QFrame(_gui),
    gui(_gui)
{
    // Leave HBox hook for adding a list view later
    QHBoxLayout *walletFrameLayout = new QHBoxLayout(this);
    setContentsMargins(0,0,0,0);
    walletStack = new QStackedWidget(this);
    walletFrameLayout->setContentsMargins(0,0,0,0);
    walletFrameLayout->addWidget(walletStack);

    QLabel *noWallet = new QLabel(tr("No wallet has been loaded."));
    noWallet->setAlignment(Qt::AlignCenter);
    walletStack->addWidget(noWallet);
}

WalletFrame::~WalletFrame()
{
}

void WalletFrame::setClientModel(ClientModel *clientModel)
{
    this->clientModel = clientModel;
}

bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel)
{
    if (!gui || !clientModel || !walletModel || mapWalletViews.count(name) > 0)
        return false;

    WalletView *walletView = new WalletView(this);
    walletView->setBitcoinGUI(gui);
    walletView->setClientModel(clientModel);
    walletView->setWalletModel(walletModel);
    walletView->showOutOfSyncWarning(bOutOfSync);

     /* TODO we should goto the currently selected page once dynamically adding wallets is supported */
    //walletView->setStyleSheet("background-color:white;");
    walletView->setStyleSheet("background:rgb(246,246,246);");
    walletView->gotoOverviewPage();
    walletStack->addWidget(walletView);
    mapWalletViews[name] = walletView;

    // Ensure a walletView is able to show the main window
    connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized()));

    return true;
}

bool WalletFrame::setCurrentWallet(const QString& name)
{
    if (mapWalletViews.count(name) == 0)
        return false;

    WalletView *walletView = mapWalletViews.value(name);
    walletStack->setCurrentWidget(walletView);
    walletView->updateEncryptionStatus();
    return true;
}

bool WalletFrame::removeWallet(const QString &name)
{
    if (mapWalletViews.count(name) == 0)
        return false;

    WalletView *walletView = mapWalletViews.take(name);
    walletStack->removeWidget(walletView);
    return true;
}

void WalletFrame::removeAllWallets()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        walletStack->removeWidget(i.value());
    mapWalletViews.clear();
}

bool WalletFrame::handlePaymentRequest(const SendCoinsRecipient &recipient)
{
    WalletView *walletView = currentWalletView();
    if (!walletView)
        return false;

    return walletView->handlePaymentRequest(recipient);
}

void WalletFrame::showOutOfSyncWarning(bool fShow)
{
    bOutOfSync = fShow;
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->showOutOfSyncWarning(fShow);
}

void WalletFrame::gotoOverviewPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoOverviewPage();
}

void WalletFrame::gotoHistoryPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoHistoryPage();
}

void WalletFrame::gotoReceiveCoinsPage()
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoReceiveCoinsPage();
}

void WalletFrame::gotoSendCoinsPage(QString addr)
{
    QMap<QString, WalletView*>::const_iterator i;
    for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
        i.value()->gotoSendCoinsPage(addr);
}

void WalletFrame::gotoSignMessageTab(QString addr)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->gotoSignMessageTab(addr);
}

void WalletFrame::gotoVerifyMessageTab(QString addr)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->gotoVerifyMessageTab(addr);
}

void WalletFrame::encryptWallet(bool status)
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->encryptWallet(status);
}

void WalletFrame::backupWallet()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->backupWallet();
}

void WalletFrame::changePassphrase()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->changePassphrase();
}

void WalletFrame::unlockWallet()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->unlockWallet();
}

void WalletFrame::usedSendingAddresses()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->usedSendingAddresses();
}

void WalletFrame::usedReceivingAddresses()
{
    WalletView *walletView = currentWalletView();
    if (walletView)
        walletView->usedReceivingAddresses();
}

WalletView *WalletFrame::currentWalletView()
{
    return qobject_cast<WalletView*>(walletStack->currentWidget());
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/
#ifndef REALM_UTIL_URI_HPP
#define REALM_UTIL_URI_HPP

#include <string>

namespace realm {
namespace util {

/// \brief A decomposed URI reference.
///
/// A Uri object contains a URI reference decomposed into its 5 main component
/// parts (scheme, authority, path, query, and fragment identifier).
///
/// The decomposition process (as carried out by the constructor) performs a
/// maximally lenient parsing of the specified URI reference. It does that
/// according to the following regular expression (taken from
/// http://tools.ietf.org/html/rfc3986#appendix):
///
///     ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
///      1             2             3       4           5
///
///     Group
///     ------------------------
///     1       Scheme part
///     2       Authority part
///     3       Path part
///     4       Query part
///     5       Fragment identifier part
///
/// NOTE: Since this regular expression maches every string, every string is
/// decomposable.
///
/// NOTE: This class does not attempt to perform any level of validation of URI
/// references against the grammer specified in the RFC. Such validation could
/// be added later, for example through a new `Uri::validate()`.
///
/// For example, the decomposition of
/// "http://www.ietf.org/rfc/rfc2396.txt?foo=bar#chp3" is:
///
///

///
///   scheme -> "http:"
///   auth   -> "//www.ietf.org"
///   path   -> "/rfc/rfc2396.txt"
///   query  -> "?foo=bar"
///   frag   -> "#chp3"
///
///

///
/// This class also provides recomposition of a URI references from their
/// component parts, where the parts can be specified individually, or be a
/// result of URI resoultion.
///
/// It is important to understand, however, that certain restrictions need to
/// apply to each component part in order that the URI reference as a whole is
/// self consistent. More concretely, it is necessary to require that the
/// component parts at any time must have values that will be preserved across a
/// recomposition -> decomposition cycle.
///
/// The actual restructions on each component part is specified for the
/// corresponding setter-method (e.g., set_scheme()).
///
/// Note that component parts resulting from decomposition, canonicalize, or
/// from resolution (resolve()) will automatically (by design of the underlying
/// algorithm) adhere to these rules.
///
/// Decomposition, recomposition, conanonicalization, and resolution algorithms
/// are taken from RFC 3986.
///
/// \sa http://tools.ietf.org/html/rfc3986
class Uri {
public:
    Uri();

    /// Decompose the specified URI reference into its five main parts.
    Uri(const std::string&);

    /// Reconstruct a URI reference from its 5 components.
    std::string recompose() const;

/*
    /// Resolve this URI reference against the specified base URI reference
    /// according to the rules described in section 5.2 of RFC 3986.
    ///
    /// Be aware that a fragment identifier on the base URI reference is never
    /// carried over to the result. This is in accordance with the RFC.
    void resolve(const Uri& base, bool strict = true);
*/

    /// Remove empty URI components. Also, for URI references having either a
    /// scheme part or an authority part, replace an absent path with "/".
    void canonicalize();

    /// Get the scheme part of this URI reference including the trailing ":", or
    /// the empty tring if there is no scheme part.
    const std::string& get_scheme() const;

    /// Get the authority part of this URI reference including the leading "//",
    /// or the empty tring if there is no authority part.
    const std::string& get_auth() const;

    /// Same as get_auth() (with no arguments), but parse the authority component
    /// into userinfo, host, and port subcomponents.
    ///
    /// \return True if, and only if the authority component was present (i.e.,
    /// not the empty string). When false is returned, none of the specified
    /// strings will have been modified.
    bool get_auth(std::string& userinfo, std::string& host, std::string& port) const;

    /// Get the path part of this URI reference, or the empty tring if there is
    /// no path part.
    const std::string& get_path() const;

    /// Get the query part of this URI reference including the leading "?", or
    /// the empty tring if there is no query part.
    const std::string& get_query() const;

    /// Get the fragment identifier of this URI reference including the leading
    /// "#", or the empty tring if there is no fragment identifier.
    const std::string& get_frag() const;

    /// The specified string must either be empty or have a final ":". Also, it
    /// must not contain "/", "?", or "#", nor may it contain more than one ":".
    ///
    /// \throw std::invalid_argument If the specified string is not valid
    /// according to the specified rules.
    void set_scheme(const std::string&);

    /// The specified string must either be empty or have "//" as a
    /// prefix. Also, it must not contain "?" or "#", nor may it contain "/"
    /// beyond the first two.
    ///
    /// \throw std::invalid_argument If the specified string is not valid
    /// according to the specified rules.
    void set_auth(const std::string&);

    /// The specified string must not contain "?" or "#".
    ///
    /// \throw std::invalid_argument If the specified string is not valid
    /// according to the specified rules.
    void set_path(const std::string&);

    /// The specified string must either be empty or have a leading "?". Also,
    /// it must not contain "#".
    ///
    /// \throw std::invalid_argument If the specified string is not valid
    /// according to the specified rules.
    void set_query(const std::string&);

/*
    /// Set the query string to the serialized form of the specified set of
    /// query parameters. This is slightly faster than set_query(q.encode())
    /// because it avoids the validity check on the string.
    void set_query(const Params&);
*/

    /// The specified string must either be empty or have a leading "#".
    ///
    /// \throw std::invalid_argument If the specified string is not valid
    /// according to the specified rules.
    void set_frag(const std::string&);

    bool is_absolute() const;

private:
    std::string m_scheme, m_auth, m_path, m_query, m_frag;
};

// Implementation

inline Uri::Uri()
{
}

inline std::string Uri::recompose() const
{
    return m_scheme + m_auth + m_path + m_query + m_frag;
}

inline const std::string& Uri::get_scheme() const
{
    return m_scheme;
}

inline const std::string& Uri::get_auth() const
{
    return m_auth;
}

inline const std::string& Uri::get_path() const
{
    return m_path;
}

inline const std::string& Uri::get_query() const
{
    return m_query;
}

inline const std::string& Uri::get_frag() const
{
    return m_frag;
}

inline bool Uri::is_absolute() const
{
    return !m_scheme.empty();
}

} // namespace util
} // namespace realm

#endif // REALM_UTIL_URI_HPP
<commit_msg>Fix for: Improved documentation of the util::Uri class<commit_after>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/
#ifndef REALM_UTIL_URI_HPP
#define REALM_UTIL_URI_HPP

#include <string>

namespace realm {
namespace util {

/// \brief A decomposed URI reference.
///
/// A Uri object contains a URI reference decomposed into its 5 main component
/// parts (scheme, authority, path, query, and fragment identifier).
///
/// The decomposition process (as carried out by the constructor) performs a
/// maximally lenient parsing of the specified URI reference. It does that
/// according to the following regular expression (taken from
/// http://tools.ietf.org/html/rfc3986#appendix-B):
///
///     ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
///      1             2             3       4           5
///
///     Group
///     ------------------------
///     1       Scheme part
///     2       Authority part
///     3       Path part
///     4       Query part
///     5       Fragment identifier part
///
/// NOTE: Since this regular expression maches every string, every string is
/// decomposable.
///
/// NOTE: This class does not attempt to perform any level of validation of URI
/// references against the grammer specified in the RFC. Such validation could
/// be added later, for example through a new `Uri::validate()`.
///
/// For example, the decomposition of
/// "http://www.ietf.org/rfc/rfc2396.txt?foo=bar#chp3" is:
///
///

///
///   scheme -> "http:"
///   auth   -> "//www.ietf.org"
///   path   -> "/rfc/rfc2396.txt"
///   query  -> "?foo=bar"
///   frag   -> "#chp3"
///
///

///
/// This class also provides recomposition of a URI references from their
/// component parts, where the parts can be specified individually, or be a
/// result of URI resoultion.
///
/// It is important to understand, however, that certain restrictions need to
/// apply to each component part in order that the URI reference as a whole is
/// self consistent. More concretely, it is necessary to require that the
/// component parts at any time must have values that will be preserved across a
/// recomposition -> decomposition cycle.
///
/// The actual restructions on each component part is specified for the
/// corresponding setter-method (e.g., set_scheme()).
///
/// Note that component parts resulting from decomposition, canonicalize, or
/// from resolution (resolve()) will automatically (by design of the underlying
/// algorithm) adhere to these rules.
///
/// Decomposition, recomposition, conanonicalization, and resolution algorithms
/// are taken from RFC 3986.
///
/// \sa http://tools.ietf.org/html/rfc3986
class Uri {
public:
    Uri();

    /// Decompose the specified URI reference into its five main parts.
    Uri(const std::string&);

    /// Reconstruct a URI reference from its 5 components.
    std::string recompose() const;

/*
    /// Resolve this URI reference against the specified base URI reference
    /// according to the rules described in section 5.2 of RFC 3986.
    ///
    /// Be aware that a fragment identifier on the base URI reference is never
    /// carried over to the result. This is in accordance with the RFC.
    void resolve(const Uri& base, bool strict = true);
*/

    /// Remove empty URI components. Also, for URI references having either a
    /// scheme part or an authority part, replace an absent path with "/".
    void canonicalize();

    /// Get the scheme part of this URI reference including the trailing ":", or
    /// the empty tring if there is no scheme part.
    const std::string& get_scheme() const;

    /// Get the authority part of this URI reference including the leading "//",
    /// or the empty tring if there is no authority part.
    const std::string& get_auth() const;

    /// Same as get_auth() (with no arguments), but parse the authority component
    /// into userinfo, host, and port subcomponents.
    ///
    /// \return True if, and only if the authority component was present (i.e.,
    /// not the empty string). When false is returned, none of the specified
    /// strings will have been modified.
    bool get_auth(std::string& userinfo, std::string& host, std::string& port) const;

    /// Get the path part of this URI reference, or the empty tring if there is
    /// no path part.
    const std::string& get_path() const;

    /// Get the query part of this URI reference including the leading "?", or
    /// the empty tring if there is no query part.
    const std::string& get_query() const;

    /// Get the fragment identifier of this URI reference including the leading
    /// "#", or the empty tring if there is no fragment identifier.
    const std::string& get_frag() const;

    /// The specified string must either be empty or have a final ":". Also, it
    /// must not contain "/", "?", or "#", nor may it contain more than one ":".
    ///
    /// \throw std::invalid_argument If the specified string is not valid
    /// according to the specified rules.
    void set_scheme(const std::string&);

    /// The specified string must either be empty or have "//" as a
    /// prefix. Also, it must not contain "?" or "#", nor may it contain "/"
    /// beyond the first two.
    ///
    /// \throw std::invalid_argument If the specified string is not valid
    /// according to the specified rules.
    void set_auth(const std::string&);

    /// The specified string must not contain "?" or "#".
    ///
    /// \throw std::invalid_argument If the specified string is not valid
    /// according to the specified rules.
    void set_path(const std::string&);

    /// The specified string must either be empty or have a leading "?". Also,
    /// it must not contain "#".
    ///
    /// \throw std::invalid_argument If the specified string is not valid
    /// according to the specified rules.
    void set_query(const std::string&);

/*
    /// Set the query string to the serialized form of the specified set of
    /// query parameters. This is slightly faster than set_query(q.encode())
    /// because it avoids the validity check on the string.
    void set_query(const Params&);
*/

    /// The specified string must either be empty or have a leading "#".
    ///
    /// \throw std::invalid_argument If the specified string is not valid
    /// according to the specified rules.
    void set_frag(const std::string&);

    bool is_absolute() const;

private:
    std::string m_scheme, m_auth, m_path, m_query, m_frag;
};

// Implementation

inline Uri::Uri()
{
}

inline std::string Uri::recompose() const
{
    return m_scheme + m_auth + m_path + m_query + m_frag;
}

inline const std::string& Uri::get_scheme() const
{
    return m_scheme;
}

inline const std::string& Uri::get_auth() const
{
    return m_auth;
}

inline const std::string& Uri::get_path() const
{
    return m_path;
}

inline const std::string& Uri::get_query() const
{
    return m_query;
}

inline const std::string& Uri::get_frag() const
{
    return m_frag;
}

inline bool Uri::is_absolute() const
{
    return !m_scheme.empty();
}

} // namespace util
} // namespace realm

#endif // REALM_UTIL_URI_HPP
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE state

#include <boost/test/unit_test.hpp>
#include <sys/uio.h>

#include "peer.h"
#include "state.h"

extern "C" {

	int fake_read(int fd, void *buf, size_t count)
	{
		return 0;
	}

	int fake_send(int fd, void *buf, size_t count, int flags)
	{
		return 0;
	}

	int fake_writev(int fd, const struct iovec *iov, int iovcnt)
	{
		int len = 0;
		int i;
		for (i = 0; i < iovcnt; i++) {
			len += iov[i].iov_len;
		}
		return len;
	}
}

struct F {
	F()
	{
		create_state_hashtable();
		p = alloc_peer(-1);
	}
	~F()
	{
		free_peer(p);
		delete_state_hashtable();
	}

	struct peer *p;
};

static void check_invalid_params(cJSON *error)
{
	cJSON *code = cJSON_GetObjectItem(error, "code");
	BOOST_REQUIRE(code != NULL);
	BOOST_CHECK(code->type == cJSON_Number);
	BOOST_CHECK(code->valueint == -32602);
	cJSON *message = cJSON_GetObjectItem(error, "message");
	BOOST_REQUIRE(message != NULL);
	BOOST_CHECK(message->type == cJSON_String);
	BOOST_CHECK(strcmp(message->valuestring, "Invalid params") == 0);
}

BOOST_FIXTURE_TEST_CASE(add_state, F)
{
	const char *path = "/foo/bar/";
	int state_value = 12345;
	cJSON *value = cJSON_CreateNumber(state_value);

	cJSON *error = add_state_to_peer(p, path, value);
	BOOST_CHECK(error == NULL);

	cJSON_Delete(value);

	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == state_value);
}

BOOST_FIXTURE_TEST_CASE(add_duplicate_state, F)
{
	cJSON *value = cJSON_CreateNumber(1234);

	cJSON *error = add_state_to_peer(p, "/foo/bar/", value);
	BOOST_CHECK(error == NULL);

	error = add_state_to_peer(p, "/foo/bar/", value);
	BOOST_REQUIRE(error != NULL);
	check_invalid_params(error);
	cJSON_Delete(error);
	cJSON_Delete(value);
}

BOOST_FIXTURE_TEST_CASE(delete_single_state, F)
{
	const char path[] = "/foo/bar/";
	cJSON *value = cJSON_CreateNumber(1234);
	cJSON *error = add_state_to_peer(p, path, value);
	BOOST_CHECK(error == NULL);

	cJSON_Delete(value);

	error = remove_state_from_peer(p, path);
	BOOST_CHECK(error == NULL);
}

BOOST_FIXTURE_TEST_CASE(delete_nonexisting_state, F)
{
	const char path[] = "/foo/bar/";
	cJSON *error = remove_state_from_peer(p, path);
	BOOST_CHECK(error != NULL);
	check_invalid_params(error);
	cJSON_Delete(error);
}

BOOST_FIXTURE_TEST_CASE(double_free_state, F)
{
	const char path[] = "/foo/bar/";
	cJSON *value = cJSON_CreateNumber(1234);
	cJSON *error = add_state_to_peer(p, path, value);
	BOOST_CHECK(error == NULL);

	cJSON_Delete(value);

	error = remove_state_from_peer(p, path);
	BOOST_CHECK(error == NULL);

	error = remove_state_from_peer(p, path);
	BOOST_CHECK(error != NULL);
	check_invalid_params(error);
	cJSON_Delete(error);
}

BOOST_FIXTURE_TEST_CASE(change, F)
{
	const char path[] = "/foo/bar/";
	cJSON *value = cJSON_CreateNumber(1234);
	cJSON *error = add_state_to_peer(p, path, value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(value);

	cJSON *new_value = cJSON_CreateNumber(4321);
	error = change_state(p, path, new_value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(new_value);

	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == 4321);
}

BOOST_FIXTURE_TEST_CASE(change_wrong_path, F)
{
	cJSON *value = cJSON_CreateNumber(1234);
	cJSON *error = add_state_to_peer(p, "/foo/bar/", value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(value);

	cJSON *new_value = cJSON_CreateNumber(4321);
	error = change_state(p, "/bar/foo/", new_value);
	BOOST_CHECK(error != NULL);
	cJSON_Delete(new_value);
	check_invalid_params(error);
	cJSON_Delete(error);
}

BOOST_FIXTURE_TEST_CASE(set, F)
{
	const char path[] = "/foo/bar/";
	cJSON *value = cJSON_CreateNumber(1234);
	cJSON *error = add_state_to_peer(p, path, value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(value);

	struct peer *set_peer = alloc_peer(-1);
	cJSON *new_value = cJSON_CreateNumber(4321);
	error = set_state(set_peer, path, new_value);
	BOOST_CHECK(error == (cJSON *)ROUTED_MESSAGE);
	cJSON_Delete(new_value);
	free_peer(set_peer);
/*
	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == 4321);

*/
}
<commit_msg>Change state unit test to correctly call set_state.<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE state

#include <boost/test/unit_test.hpp>
#include <sys/uio.h>

#include "peer.h"
#include "state.h"

extern "C" {

	int fake_read(int fd, void *buf, size_t count)
	{
		return 0;
	}

	int fake_send(int fd, void *buf, size_t count, int flags)
	{
		return 0;
	}

	int fake_writev(int fd, const struct iovec *iov, int iovcnt)
	{
		int len = 0;
		int i;
		for (i = 0; i < iovcnt; i++) {
			len += iov[i].iov_len;
		}
		return len;
	}
}

struct F {
	F()
	{
		create_state_hashtable();
		p = alloc_peer(-1);
	}
	~F()
	{
		free_peer(p);
		delete_state_hashtable();
	}

	struct peer *p;
};

static void check_invalid_params(cJSON *error)
{
	cJSON *code = cJSON_GetObjectItem(error, "code");
	BOOST_REQUIRE(code != NULL);
	BOOST_CHECK(code->type == cJSON_Number);
	BOOST_CHECK(code->valueint == -32602);
	cJSON *message = cJSON_GetObjectItem(error, "message");
	BOOST_REQUIRE(message != NULL);
	BOOST_CHECK(message->type == cJSON_String);
	BOOST_CHECK(strcmp(message->valuestring, "Invalid params") == 0);
}

BOOST_FIXTURE_TEST_CASE(add_state, F)
{
	const char *path = "/foo/bar/";
	int state_value = 12345;
	cJSON *value = cJSON_CreateNumber(state_value);

	cJSON *error = add_state_to_peer(p, path, value);
	BOOST_CHECK(error == NULL);

	cJSON_Delete(value);

	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == state_value);
}

BOOST_FIXTURE_TEST_CASE(add_duplicate_state, F)
{
	cJSON *value = cJSON_CreateNumber(1234);

	cJSON *error = add_state_to_peer(p, "/foo/bar/", value);
	BOOST_CHECK(error == NULL);

	error = add_state_to_peer(p, "/foo/bar/", value);
	BOOST_REQUIRE(error != NULL);
	check_invalid_params(error);
	cJSON_Delete(error);
	cJSON_Delete(value);
}

BOOST_FIXTURE_TEST_CASE(delete_single_state, F)
{
	const char path[] = "/foo/bar/";
	cJSON *value = cJSON_CreateNumber(1234);
	cJSON *error = add_state_to_peer(p, path, value);
	BOOST_CHECK(error == NULL);

	cJSON_Delete(value);

	error = remove_state_from_peer(p, path);
	BOOST_CHECK(error == NULL);
}

BOOST_FIXTURE_TEST_CASE(delete_nonexisting_state, F)
{
	const char path[] = "/foo/bar/";
	cJSON *error = remove_state_from_peer(p, path);
	BOOST_CHECK(error != NULL);
	check_invalid_params(error);
	cJSON_Delete(error);
}

BOOST_FIXTURE_TEST_CASE(double_free_state, F)
{
	const char path[] = "/foo/bar/";
	cJSON *value = cJSON_CreateNumber(1234);
	cJSON *error = add_state_to_peer(p, path, value);
	BOOST_CHECK(error == NULL);

	cJSON_Delete(value);

	error = remove_state_from_peer(p, path);
	BOOST_CHECK(error == NULL);

	error = remove_state_from_peer(p, path);
	BOOST_CHECK(error != NULL);
	check_invalid_params(error);
	cJSON_Delete(error);
}

BOOST_FIXTURE_TEST_CASE(change, F)
{
	const char path[] = "/foo/bar/";
	cJSON *value = cJSON_CreateNumber(1234);
	cJSON *error = add_state_to_peer(p, path, value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(value);

	cJSON *new_value = cJSON_CreateNumber(4321);
	error = change_state(p, path, new_value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(new_value);

	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == 4321);
}

BOOST_FIXTURE_TEST_CASE(change_wrong_path, F)
{
	cJSON *value = cJSON_CreateNumber(1234);
	cJSON *error = add_state_to_peer(p, "/foo/bar/", value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(value);

	cJSON *new_value = cJSON_CreateNumber(4321);
	error = change_state(p, "/bar/foo/", new_value);
	BOOST_CHECK(error != NULL);
	cJSON_Delete(new_value);
	check_invalid_params(error);
	cJSON_Delete(error);
}

BOOST_FIXTURE_TEST_CASE(set, F)
{
	const char path[] = "/foo/bar/";
	cJSON *value = cJSON_CreateNumber(1234);
	cJSON *error = add_state_to_peer(p, path, value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(value);

	struct peer *set_peer = alloc_peer(-1);

	cJSON *set_request = cJSON_CreateObject();
	cJSON_AddStringToObject(set_request, "id", "request1");
	cJSON_AddStringToObject(set_request, "method", "set");

	cJSON *params = cJSON_CreateObject();
	cJSON_AddStringToObject(params, "path", "/foo/bar/");
	cJSON *new_value = cJSON_CreateNumber(4321);
	cJSON_AddItemToObject(params, "value", new_value);
	cJSON_AddItemToObject(set_request, "params", params);

	error = set_state(set_peer, path, new_value, set_request);
	BOOST_CHECK(error == (cJSON *)ROUTED_MESSAGE);
	cJSON_Delete(set_request);
	free_peer(set_peer);
/*
	struct state *s = get_state(path);
	BOOST_CHECK(s->value->valueint == 4321);

*/
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "testing/gtest/include/gtest/gtest.h"
extern "C" {
#include "webrtc/modules/audio_processing/aec/aec_core.h"
}
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/test/testsupport/gtest_disable.h"

namespace webrtc {

TEST(EchoCancellationInternalTest, DISABLED_ON_ANDROID(DelayCorrection)) {
  scoped_ptr<AudioProcessing> ap(AudioProcessing::Create(0));
  EXPECT_TRUE(ap->echo_cancellation()->aec_core() == NULL);

  EXPECT_EQ(ap->kNoError, ap->echo_cancellation()->Enable(true));
  EXPECT_TRUE(ap->echo_cancellation()->is_enabled());

  AecCore* aec_core = ap->echo_cancellation()->aec_core();
  ASSERT_TRUE(aec_core != NULL);
  // Disabled by default.
  EXPECT_EQ(0, WebRtcAec_delay_correction_enabled(aec_core));

  Config config;
  config.Set<DelayCorrection>(new DelayCorrection(true));
  ap->SetExtraOptions(config);
  EXPECT_EQ(1, WebRtcAec_delay_correction_enabled(aec_core));

  // Retains setting after initialization.
  EXPECT_EQ(ap->kNoError, ap->Initialize());
  EXPECT_EQ(1, WebRtcAec_delay_correction_enabled(aec_core));

  config.Set<DelayCorrection>(new DelayCorrection(false));
  ap->SetExtraOptions(config);
  EXPECT_EQ(0, WebRtcAec_delay_correction_enabled(aec_core));

  // Retains setting after initialization.
  EXPECT_EQ(ap->kNoError, ap->Initialize());
  EXPECT_EQ(0, WebRtcAec_delay_correction_enabled(aec_core));
}

}  // namespace webrtc
<commit_msg>Enables DelayCorrection tests<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "testing/gtest/include/gtest/gtest.h"
extern "C" {
#include "webrtc/modules/audio_processing/aec/aec_core.h"
}
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/test/testsupport/gtest_disable.h"

namespace webrtc {

TEST(EchoCancellationInternalTest, DelayCorrection) {
  scoped_ptr<AudioProcessing> ap(AudioProcessing::Create(0));
  EXPECT_TRUE(ap->echo_cancellation()->aec_core() == NULL);

  EXPECT_EQ(ap->kNoError, ap->echo_cancellation()->Enable(true));
  EXPECT_TRUE(ap->echo_cancellation()->is_enabled());

  AecCore* aec_core = ap->echo_cancellation()->aec_core();
  ASSERT_TRUE(aec_core != NULL);
  // Disabled by default.
  EXPECT_EQ(0, WebRtcAec_delay_correction_enabled(aec_core));

  Config config;
  config.Set<DelayCorrection>(new DelayCorrection(true));
  ap->SetExtraOptions(config);
  EXPECT_EQ(1, WebRtcAec_delay_correction_enabled(aec_core));

  // Retains setting after initialization.
  EXPECT_EQ(ap->kNoError, ap->Initialize());
  EXPECT_EQ(1, WebRtcAec_delay_correction_enabled(aec_core));

  config.Set<DelayCorrection>(new DelayCorrection(false));
  ap->SetExtraOptions(config);
  EXPECT_EQ(0, WebRtcAec_delay_correction_enabled(aec_core));

  // Retains setting after initialization.
  EXPECT_EQ(ap->kNoError, ap->Initialize());
  EXPECT_EQ(0, WebRtcAec_delay_correction_enabled(aec_core));
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/// @file
/// @author  Boris Mikic
/// @version 3.3
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php

#if defined(_WINRT) && !defined(_OPENKODE)
#include <gtypes/Vector2.h>
#include <hltypes/hdir.h>
#include <hltypes/hlog.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hmap.h>
#include <hltypes/hplatform.h>
#include <hltypes/hstring.h>

#include "april.h"
#include "Platform.h"
#include "RenderSystem.h"
#include "Window.h"
#include "WinRT.h"
#include "WinRT_Window.h"

using namespace Windows::Foundation::Collections;
using namespace Windows::Graphics::Display;
using namespace Windows::Storage;
using namespace Windows::UI::Popups;
#ifndef WINP8
using namespace Windows::UI::ViewManagement;
#endif

namespace april
{
	extern SystemInfo info;

	SystemInfo getSystemInfo()
	{
		if (info.locale == "")
		{
			info.name = "winrt";
			// number of CPU cores
			SYSTEM_INFO w32info;
			GetNativeSystemInfo(&w32info);
			info.cpuCores = w32info.dwNumberOfProcessors;
			// TODO - though, WinRT does not seem to be able to retrieve this information
			// RAM size
#ifndef _WINP8
			info.ram = 1024;
#else
			info.ram = 512;
#endif
			// display resolution
#ifdef _WINRT_WINDOW
			int width = (int)CoreWindow::GetForCurrentThread()->Bounds.Width;
			int height = (int)CoreWindow::GetForCurrentThread()->Bounds.Height;
#ifndef _WINP8
			if (ApplicationView::Value == ApplicationViewState::Filled)
			{
				width += WINRT_SNAPPED_VIEW_UNUSED;
			}
#endif
			info.displayResolution.set((float)hmax(width, height), (float)hmin(width, height));
#endif
			// display DPI
			info.displayDpi = (int)DisplayProperties::LogicalDpi;
			// other
			info.locale = "";
#ifndef _WINP8
			IIterator<Platform::String^>^ it = Windows::Globalization::ApplicationLanguages::Languages->First();
			if (it->HasCurrent)
			{
				info.locale = _HL_PSTR_TO_HSTR(it->Current).lower();
			}
#else
			unsigned long count = 0;
			unsigned long length = LOCALE_NAME_MAX_LENGTH;
			wchar_t locale[LOCALE_NAME_MAX_LENGTH] = {0};
			if (GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &count, locale, &length) && count > 0 && length > 0)
			{
				info.locale = hstr::from_unicode(locale).lower();
			}
#endif
			if (info.locale == "")
			{
				info.locale = "en"; // default is "en"
			}
			else if (info.locale == "pt_pt" || info.locale == "pt-pt")
			{
				info.locale = "pt-PT";
			}
			else if (info.locale.utf8_size() > 2 && info.locale != "pt-PT")
			{
				info.locale = info.locale.utf8_substr(0, 2);
			}
		}
		return info;
	}

	hstr getPackageName()
	{
		return _HL_PSTR_TO_HSTR(Windows::ApplicationModel::Package::Current->Id->FamilyName);
	}

	hstr getUserDataPath()
	{
#ifndef _WINP8
		return hdir::systemize(_HL_PSTR_TO_HSTR(ApplicationData::Current->RoamingFolder->Path));
#else // because Windows Phone 8 is missing yet another feature
		return hdir::systemize(_HL_PSTR_TO_HSTR(ApplicationData::Current->LocalFolder->Path));
#endif
	}

	static void(*currentCallback)(MessageBoxButton) = NULL;

	void _messageBoxResult(int button)
	{
		switch (button)
		{
		case IDOK:
			if (currentCallback != NULL)
			{
				(*currentCallback)(MESSAGE_BUTTON_OK);
			}
			break;
		case IDYES:
			if (currentCallback != NULL)
			{
				(*currentCallback)(MESSAGE_BUTTON_YES);
			}
			break;
		case IDNO:
			if (currentCallback != NULL)
			{
				(*currentCallback)(MESSAGE_BUTTON_NO);
			}
			break;
		case IDCANCEL:
			if (currentCallback != NULL)
			{
				(*currentCallback)(MESSAGE_BUTTON_CANCEL);
			}
			break;
		default:
			hlog::error(april::logTag, "Unknown message box callback: " + hstr(button));
			break;
		}
	}

	void messageBox_platform(chstr title, chstr text, MessageBoxButton buttonMask, MessageBoxStyle style,
		hmap<MessageBoxButton, hstr> customButtonTitles, void(*callback)(MessageBoxButton))
	{
#ifndef _WINP8
		currentCallback = callback;
		_HL_HSTR_TO_PSTR_DEF(text);
		_HL_HSTR_TO_PSTR_DEF(title);
		MessageDialog^ dialog = ref new MessageDialog(ptext, ptitle);
		UICommandInvokedHandler^ commandHandler = ref new UICommandInvokedHandler(
			[](IUICommand^ command)
		{
			_messageBoxResult((int)command->Id);
		});
		hstr ok;
		hstr yes;
		hstr no;
		hstr cancel;
		_makeButtonLabels(&ok, &yes, &no, &cancel, buttonMask, customButtonTitles);
		_HL_HSTR_TO_PSTR_DEF(ok);
		_HL_HSTR_TO_PSTR_DEF(yes);
		_HL_HSTR_TO_PSTR_DEF(no);
		_HL_HSTR_TO_PSTR_DEF(cancel);

		if ((buttonMask & MESSAGE_BUTTON_OK) && (buttonMask & MESSAGE_BUTTON_CANCEL))
		{
			dialog->Commands->Append(ref new UICommand(pok, commandHandler, IDOK));
			dialog->Commands->Append(ref new UICommand(pcancel, commandHandler, IDCANCEL));
			dialog->DefaultCommandIndex = 0;
			dialog->CancelCommandIndex = 1;
		}
		else if ((buttonMask & MESSAGE_BUTTON_YES) && (buttonMask & MESSAGE_BUTTON_NO) && (buttonMask & MESSAGE_BUTTON_CANCEL))
		{
			dialog->Commands->Append(ref new UICommand(pyes, commandHandler, IDYES));
			dialog->Commands->Append(ref new UICommand(pno, commandHandler, IDNO));
			dialog->Commands->Append(ref new UICommand(pcancel, commandHandler, IDCANCEL));
			dialog->DefaultCommandIndex = 0;
			dialog->CancelCommandIndex = 2;
		}
		else if (buttonMask & MESSAGE_BUTTON_OK)
		{
			dialog->Commands->Append(ref new UICommand(pok, commandHandler, IDOK));
			dialog->DefaultCommandIndex = 0;
			dialog->CancelCommandIndex = 0;
		}
		else if ((buttonMask & MESSAGE_BUTTON_YES) && (buttonMask & MESSAGE_BUTTON_NO))
		{
			dialog->Commands->Append(ref new UICommand(pyes, commandHandler, IDYES));
			dialog->Commands->Append(ref new UICommand(pno, commandHandler, IDNO));
			dialog->DefaultCommandIndex = 0;
			dialog->CancelCommandIndex = 1;
		}
		dialog->ShowAsync();
#else
		// TODOp8 - if Microsoft ever decides to allow usage of basic features on Windows Phone 8, this has to be implemented
		hlog::error(april::logTag, "Windows Phone 8 does not support messageBox()!)");
#endif
	}

}
#endif
<commit_msg>- WinP8 update<commit_after>/// @file
/// @author  Boris Mikic
/// @version 3.3
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php

#if defined(_WINRT) && !defined(_OPENKODE)
#include <gtypes/Vector2.h>
#include <hltypes/hdir.h>
#include <hltypes/hlog.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hmap.h>
#include <hltypes/hplatform.h>
#include <hltypes/hstring.h>

#include "april.h"
#include "Platform.h"
#include "RenderSystem.h"
#include "Window.h"
#include "WinRT.h"
#include "WinRT_Window.h"

using namespace Windows::Foundation::Collections;
using namespace Windows::Graphics::Display;
using namespace Windows::Storage;
using namespace Windows::UI::Popups;
#ifndef WINP8
using namespace Windows::UI::ViewManagement;
#endif

namespace april
{
	extern SystemInfo info;

	SystemInfo getSystemInfo()
	{
		if (info.locale == "")
		{
			info.name = "winrt";
			// number of CPU cores
			SYSTEM_INFO w32info;
			GetNativeSystemInfo(&w32info);
			info.cpuCores = w32info.dwNumberOfProcessors;
			// TODO - though, WinRT does not seem to be able to retrieve this information
			// RAM size
#ifndef _WINP8
			info.ram = 1024;
#else
			info.ram = 512;
#endif
			// display resolution
#ifdef _WINRT_WINDOW
			int width = (int)CoreWindow::GetForCurrentThread()->Bounds.Width;
			int height = (int)CoreWindow::GetForCurrentThread()->Bounds.Height;
#ifndef _WINP8
			if (ApplicationView::Value == ApplicationViewState::Filled)
			{
				width += WINRT_SNAPPED_VIEW_UNUSED;
			}
#endif
			info.displayResolution.set((float)hmax(width, height), (float)hmin(width, height));
#endif
			// display DPI
			info.displayDpi = (int)DisplayProperties::LogicalDpi;
			// other
			info.locale = "";
#ifndef _WINP8
			IIterator<Platform::String^>^ it = Windows::Globalization::ApplicationLanguages::Languages->First();
			if (it->HasCurrent)
			{
				info.locale = _HL_PSTR_TO_HSTR(it->Current).lower();
			}
#else
			unsigned long count = 0;
			unsigned long length = LOCALE_NAME_MAX_LENGTH;
			wchar_t locale[LOCALE_NAME_MAX_LENGTH] = {0};
			if (GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &count, locale, &length) && count > 0 && length > 0)
			{
				info.locale = hstr::from_unicode(locale).lower();
			}
#endif
			if (info.locale == "")
			{
				info.locale = "en"; // default is "en"
			}
			else if (info.locale == "pt_pt" || info.locale == "pt-pt")
			{
				info.locale = "pt-PT";
			}
			else if (info.locale.utf8_size() > 2 && info.locale != "pt-PT")
			{
				info.locale = info.locale.utf8_substr(0, 2);
			}
		}
		return info;
	}

	hstr getPackageName()
	{
#ifndef _WINP8
		return _HL_PSTR_TO_HSTR(Windows::ApplicationModel::Package::Current->Id->FamilyName);
#else
		hlog::warn(april::logTag, "Cannot use getPackageName() on this platform.");
		return "";
#endif
	}

	hstr getUserDataPath()
	{
#ifndef _WINP8
		return hdir::systemize(_HL_PSTR_TO_HSTR(ApplicationData::Current->RoamingFolder->Path));
#else // because Windows Phone 8 is missing yet another feature
		return hdir::systemize(_HL_PSTR_TO_HSTR(ApplicationData::Current->LocalFolder->Path));
#endif
	}

	static void(*currentCallback)(MessageBoxButton) = NULL;

	void _messageBoxResult(int button)
	{
		switch (button)
		{
		case IDOK:
			if (currentCallback != NULL)
			{
				(*currentCallback)(MESSAGE_BUTTON_OK);
			}
			break;
		case IDYES:
			if (currentCallback != NULL)
			{
				(*currentCallback)(MESSAGE_BUTTON_YES);
			}
			break;
		case IDNO:
			if (currentCallback != NULL)
			{
				(*currentCallback)(MESSAGE_BUTTON_NO);
			}
			break;
		case IDCANCEL:
			if (currentCallback != NULL)
			{
				(*currentCallback)(MESSAGE_BUTTON_CANCEL);
			}
			break;
		default:
			hlog::error(april::logTag, "Unknown message box callback: " + hstr(button));
			break;
		}
	}

	void messageBox_platform(chstr title, chstr text, MessageBoxButton buttonMask, MessageBoxStyle style,
		hmap<MessageBoxButton, hstr> customButtonTitles, void(*callback)(MessageBoxButton))
	{
#ifndef _WINP8
		currentCallback = callback;
		_HL_HSTR_TO_PSTR_DEF(text);
		_HL_HSTR_TO_PSTR_DEF(title);
		MessageDialog^ dialog = ref new MessageDialog(ptext, ptitle);
		UICommandInvokedHandler^ commandHandler = ref new UICommandInvokedHandler(
			[](IUICommand^ command)
		{
			_messageBoxResult((int)command->Id);
		});
		hstr ok;
		hstr yes;
		hstr no;
		hstr cancel;
		_makeButtonLabels(&ok, &yes, &no, &cancel, buttonMask, customButtonTitles);
		_HL_HSTR_TO_PSTR_DEF(ok);
		_HL_HSTR_TO_PSTR_DEF(yes);
		_HL_HSTR_TO_PSTR_DEF(no);
		_HL_HSTR_TO_PSTR_DEF(cancel);

		if ((buttonMask & MESSAGE_BUTTON_OK) && (buttonMask & MESSAGE_BUTTON_CANCEL))
		{
			dialog->Commands->Append(ref new UICommand(pok, commandHandler, IDOK));
			dialog->Commands->Append(ref new UICommand(pcancel, commandHandler, IDCANCEL));
			dialog->DefaultCommandIndex = 0;
			dialog->CancelCommandIndex = 1;
		}
		else if ((buttonMask & MESSAGE_BUTTON_YES) && (buttonMask & MESSAGE_BUTTON_NO) && (buttonMask & MESSAGE_BUTTON_CANCEL))
		{
			dialog->Commands->Append(ref new UICommand(pyes, commandHandler, IDYES));
			dialog->Commands->Append(ref new UICommand(pno, commandHandler, IDNO));
			dialog->Commands->Append(ref new UICommand(pcancel, commandHandler, IDCANCEL));
			dialog->DefaultCommandIndex = 0;
			dialog->CancelCommandIndex = 2;
		}
		else if (buttonMask & MESSAGE_BUTTON_OK)
		{
			dialog->Commands->Append(ref new UICommand(pok, commandHandler, IDOK));
			dialog->DefaultCommandIndex = 0;
			dialog->CancelCommandIndex = 0;
		}
		else if ((buttonMask & MESSAGE_BUTTON_YES) && (buttonMask & MESSAGE_BUTTON_NO))
		{
			dialog->Commands->Append(ref new UICommand(pyes, commandHandler, IDYES));
			dialog->Commands->Append(ref new UICommand(pno, commandHandler, IDNO));
			dialog->DefaultCommandIndex = 0;
			dialog->CancelCommandIndex = 1;
		}
		dialog->ShowAsync();
#else
		// TODOp8 - if Microsoft ever decides to allow usage of basic features on Windows Phone 8, this has to be implemented
		hlog::error(april::logTag, "Windows Phone 8 does not support messageBox()!)");
#endif
	}

}
#endif
<|endoftext|>


<commit_before>#ifndef SILICIUM_LINUX_PROCESS_HPP
#define SILICIUM_LINUX_PROCESS_HPP

#include <silicium/sink/ptr_sink.hpp>
#include <silicium/sink/buffering_sink.hpp>
#include <silicium/process_parameters.hpp>
#include <silicium/file_handle.hpp>
#include <boost/filesystem/operations.hpp>
#include <fcntl.h>
#include <sys/wait.h>

namespace Si
{
	namespace detail
	{
		template <class Error>
		inline void copy_all(int source, sink<char, Error> &destination)
		{
			for (;;)
			{
				auto buffer_helper = make_buffering_sink(ref_sink(destination));
				auto const buffer = buffer_helper.make_append_space(std::numeric_limits<std::size_t>::max());
				assert(!buffer.empty());
				auto const rc = read(source, buffer.begin(), buffer.size());
				if (rc == 0)
				{
					break;
				}
				if (rc < 0)
				{
					throw boost::system::system_error(errno, boost::system::system_category());
				}
				buffer_helper.make_append_space(static_cast<std::size_t>(rc));
				buffer_helper.flush_append_space();
			}
		}

		inline void set_close_on_exec(int file)
		{
			fcntl(file, F_SETFD, fcntl(file, F_GETFD) | FD_CLOEXEC);
		}

		struct pipe
		{
			file_handle write, read;

			void close() BOOST_NOEXCEPT
			{
				pipe().swap(*this);
			}

			void swap(pipe &other) BOOST_NOEXCEPT
			{
				write.swap(other.write);
				read.swap(other.read);
			}
		};

		inline pipe make_pipe()
		{
			std::array<int, 2> fds;
			if (::pipe(fds.data()) < 0)
			{
				throw boost::system::system_error(errno, boost::system::system_category());
			}
			pipe result;
			result.read  = file_handle(fds[0]);
			result.write = file_handle(fds[1]);
			return result;
		}
	}

	inline int run_process(process_parameters const &parameters)
	{
		auto executable = parameters.executable.string();
		auto arguments = parameters.arguments;
		std::vector<char *> argument_pointers;
		argument_pointers.emplace_back(const_cast<char *>(executable.c_str()));
		std::transform(begin(arguments), end(arguments), std::back_inserter(argument_pointers), [](std::string &arg)
		{
			return &arg[0];
		});
		argument_pointers.emplace_back(nullptr);

		detail::pipe stdout;
		if (parameters.out)
		{
			stdout = detail::make_pipe();
		}

		auto stdin = detail::make_pipe();
		auto child_error = detail::make_pipe();

		pid_t const forked = fork();
		if (forked < 0)
		{
			throw boost::system::system_error(errno, boost::system::system_category());
		}

		//child
		if (forked == 0)
		{
			auto const fail = [&child_error]()
#if defined(__GNUC__) && !defined(__clang__)
				__attribute__ ((__noreturn__))
#endif
			{
				int error = errno;
				ssize_t written = write(child_error.write.handle, &error, sizeof(error));
				if (written != sizeof(error))
				{
					_exit(1);
				}
				child_error.write.close();
				_exit(0);
			};

			if (parameters.out)
			{
				if (dup2(stdout.write.handle, STDOUT_FILENO) < 0)
				{
					fail();
				}
				if (dup2(stdout.write.handle, STDERR_FILENO) < 0)
				{
					fail();
				}
				stdout.close();
			}

			if (dup2(stdin.read.handle, STDIN_FILENO) < 0)
			{
				fail();
			}
			stdin.close();

			child_error.read.close();
			detail::set_close_on_exec(child_error.write.handle);

			boost::filesystem::current_path(parameters.current_path);

			execvp(parameters.executable.c_str(), argument_pointers.data());
			fail();
		}

		//parent
		else
		{
			child_error.write.close();

			if (parameters.out)
			{
				stdout.write.close();
				detail::copy_all(stdout.read.handle, *parameters.out);
			}
			stdin.read.close();

			int status = 0;
			if (waitpid(forked, &status, 0) < 0)
			{
				throw boost::system::system_error(errno, boost::system::system_category());
			}

			int error = 0;
			ssize_t read_error = read(child_error.read.handle, &error, sizeof(error));
			if (read_error < 0)
			{
				throw boost::system::system_error(errno, boost::system::system_category());
			}
			if (read_error != 0)
			{
				assert(read_error == sizeof(error));
				throw boost::system::system_error(error, boost::system::system_category());
			}

			int const exit_status = WEXITSTATUS(status);
			return exit_status;
		}
	}
}

#endif
<commit_msg>do not inherit file descriptors; kill the child when the parent exits<commit_after>#ifndef SILICIUM_LINUX_PROCESS_HPP
#define SILICIUM_LINUX_PROCESS_HPP

#include <silicium/sink/ptr_sink.hpp>
#include <silicium/sink/buffering_sink.hpp>
#include <silicium/process_parameters.hpp>
#include <silicium/file_handle.hpp>
#include <boost/filesystem/operations.hpp>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/prctl.h>

namespace Si
{
	namespace detail
	{
		template <class Error>
		inline void copy_all(int source, sink<char, Error> &destination)
		{
			for (;;)
			{
				auto buffer_helper = make_buffering_sink(ref_sink(destination));
				auto const buffer = buffer_helper.make_append_space(std::numeric_limits<std::size_t>::max());
				assert(!buffer.empty());
				auto const rc = read(source, buffer.begin(), buffer.size());
				if (rc == 0)
				{
					break;
				}
				if (rc < 0)
				{
					throw boost::system::system_error(errno, boost::system::system_category());
				}
				buffer_helper.make_append_space(static_cast<std::size_t>(rc));
				buffer_helper.flush_append_space();
			}
		}

		inline void set_close_on_exec(int file)
		{
			fcntl(file, F_SETFD, fcntl(file, F_GETFD) | FD_CLOEXEC);
		}

		struct pipe
		{
			file_handle write, read;

			void close() BOOST_NOEXCEPT
			{
				pipe().swap(*this);
			}

			void swap(pipe &other) BOOST_NOEXCEPT
			{
				write.swap(other.write);
				read.swap(other.read);
			}
		};

		inline pipe make_pipe()
		{
			std::array<int, 2> fds;
			if (::pipe(fds.data()) < 0)
			{
				throw boost::system::system_error(errno, boost::system::system_category());
			}
			pipe result;
			result.read  = file_handle(fds[0]);
			result.write = file_handle(fds[1]);
			return result;
		}
	}

	inline int run_process(process_parameters const &parameters)
	{
		auto executable = parameters.executable.string();
		auto arguments = parameters.arguments;
		std::vector<char *> argument_pointers;
		argument_pointers.emplace_back(const_cast<char *>(executable.c_str()));
		std::transform(begin(arguments), end(arguments), std::back_inserter(argument_pointers), [](std::string &arg)
		{
			return &arg[0];
		});
		argument_pointers.emplace_back(nullptr);

		detail::pipe stdout;
		if (parameters.out)
		{
			stdout = detail::make_pipe();
		}

		auto stdin = detail::make_pipe();
		auto child_error = detail::make_pipe();

		pid_t const forked = fork();
		if (forked < 0)
		{
			throw boost::system::system_error(errno, boost::system::system_category());
		}

		//child
		if (forked == 0)
		{
			auto const fail = [&child_error]()
#if defined(__GNUC__) && !defined(__clang__)
				__attribute__ ((__noreturn__))
#endif
			{
				int error = errno;
				ssize_t written = write(child_error.write.handle, &error, sizeof(error));
				if (written != sizeof(error))
				{
					_exit(1);
				}
				child_error.write.close();
				_exit(0);
			};

			if (parameters.out)
			{
				if (dup2(stdout.write.handle, STDOUT_FILENO) < 0)
				{
					fail();
				}
				if (dup2(stdout.write.handle, STDERR_FILENO) < 0)
				{
					fail();
				}
				stdout.close();
			}
			else
			{
				//drop output
				dup2(open("/dev/null", O_RDWR), STDOUT_FILENO);
				dup2(open("/dev/null", O_RDWR), STDERR_FILENO);
			}

			if (dup2(stdin.read.handle, STDIN_FILENO) < 0)
			{
				fail();
			}
			else
			{
				//provide empty input
				dup2(open("/dev/null", O_RDWR), STDIN_FILENO);
			}
			stdin.close();

			child_error.read.close();
			detail::set_close_on_exec(child_error.write.handle);

			boost::filesystem::current_path(parameters.current_path);

			//close inherited file descriptors
			long max_fd = sysconf(_SC_OPEN_MAX);
			for (int i = 3; i < max_fd; ++i)
			{
				close(i);
			}

			//kill the child when the parent exits
			prctl(PR_SET_PDEATHSIG, SIGHUP);

			execvp(parameters.executable.c_str(), argument_pointers.data());
			fail();
		}

		//parent
		else
		{
			child_error.write.close();

			if (parameters.out)
			{
				stdout.write.close();
				detail::copy_all(stdout.read.handle, *parameters.out);
			}
			stdin.read.close();

			int status = 0;
			if (waitpid(forked, &status, 0) < 0)
			{
				throw boost::system::system_error(errno, boost::system::system_category());
			}

			int error = 0;
			ssize_t read_error = read(child_error.read.handle, &error, sizeof(error));
			if (read_error < 0)
			{
				throw boost::system::system_error(errno, boost::system::system_category());
			}
			if (read_error != 0)
			{
				assert(read_error == sizeof(error));
				throw boost::system::system_error(error, boost::system::system_category());
			}

			int const exit_status = WEXITSTATUS(status);
			return exit_status;
		}
	}
}

#endif
<|endoftext|>


<commit_before>/*
 * SminaConverter.cpp
 *
 *  Created on: Jun 4, 2014
 *      Author: dkoes
 *
 *  Convert internal molecular data (ie OBMol) into smina parse tree.
 */

#include "SminaConverter.h"
#include "parsing.h"
#include "PDBQTUtilities.h"

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <map>

namespace SminaConverter {

using namespace OpenBabel;
using namespace std;

MCMolConverter::MCMolConverter(OpenBabel::OBMol& m): mol(m)
{
	//precompute fragments and tree
	int nc = mol.NumConformers();
	mol.AddHydrogens();

	mol.SetAutomaticFormalCharge(false);
	DeleteHydrogens(mol); //leaves just polars

	//we kind of assume a connected molecule
	unsigned best_root_atom = FindFragments(mol, rigid_fragments);
	torsdof=rigid_fragments.size()-1;

	unsigned int root_piece = 0;
    for (unsigned j = 0; j < rigid_fragments.size(); j++)
    {
      if (IsIn((rigid_fragments[j]), best_root_atom)) {root_piece=j; break;} //this is the root rigid molecule fragment
    }

    ConstructTree(tree, rigid_fragments, root_piece, mol, true);

    assert(nc == mol.NumConformers()); //didn't lose any in analysis, did we?
}

//output data for this conformer
void MCMolConverter::convertConformer(unsigned conf, std::ostream& out)
{
	parsing_struct p;
	context c;

	mol.SetConformer(conf);
    OutputTree(mol, c, p, tree, torsdof);

	boost::iostreams::filtering_stream<boost::iostreams::output> strm;
	strm.push(boost::iostreams::gzip_compressor());
	strm.push(out);

	boost::archive::binary_oarchive serialout(strm,boost::archive::no_header|boost::archive::no_tracking);

	serialout << torsdof;
	serialout << p;
	serialout << c;
}

//sets up data structures used by both text and binary
//we link with smina to nsure compatibility
unsigned convertParsing(OBMol& mol, parsing_struct& p, context& c)
{
	mol.AddHydrogens();

	mol.SetAutomaticFormalCharge(false);
	DeleteHydrogens(mol); //leaves just polars

	vector<vector<int> > rigid_fragments; //the vector of all the rigid molecule fragments, using atom indexes
	map<unsigned int, obbranch> tree;

	//we kind of assume a connected molecule
	unsigned best_root_atom = FindFragments(mol, rigid_fragments);
	unsigned torsdof=rigid_fragments.size()-1;

	unsigned int root_piece = 0;
    for (unsigned j = 0; j < rigid_fragments.size(); j++)
    {
      if (IsIn((rigid_fragments[j]), best_root_atom)) {root_piece=j; break;} //this is the root rigid molecule fragment
    }

    ConstructTree(tree, rigid_fragments, root_piece, mol, true);

    OutputTree(mol, c, p, tree, torsdof);

    return torsdof;
}

template <class T>
static void convert(OBMol& mol, T& serialout, ostream& out)
{
	parsing_struct p;
	context c;
	unsigned torsdof = convertParsing(mol, p, c);
	serialout << torsdof;
	serialout << p;
	serialout << c;
}

//text output
void convertText(OBMol& mol, ostream& out)
{
	boost::archive::text_oarchive serialout(out,boost::archive::no_header|boost::archive::no_tracking);
	convert(mol, serialout, out);
}

//binary output
void convertBinary(OBMol& mol,  ostream& out)
{
	//by definition, smina format is gzipped
	boost::iostreams::filtering_stream<boost::iostreams::output> strm;
	strm.push(boost::iostreams::gzip_compressor());
	strm.push(out);

	boost::archive::binary_oarchive serialout(strm,boost::archive::no_header|boost::archive::no_tracking);
	convert(mol, serialout, strm);
}

} //namespace SminaConverter
<commit_msg>bug fix for multiconformer smina conversion<commit_after>/*
 * SminaConverter.cpp
 *
 *  Created on: Jun 4, 2014
 *      Author: dkoes
 *
 *  Convert internal molecular data (ie OBMol) into smina parse tree.
 */

#include "SminaConverter.h"
#include "parsing.h"
#include "PDBQTUtilities.h"

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <map>

namespace SminaConverter {

using namespace OpenBabel;
using namespace std;

MCMolConverter::MCMolConverter(OpenBabel::OBMol& m): mol(m)
{
	//precompute fragments and tree
	int nc = mol.NumConformers();
	mol.AddHydrogens();

	mol.SetAutomaticFormalCharge(false);
	DeleteHydrogens(mol); //leaves just polars

	//we kind of assume a connected molecule
	unsigned best_root_atom = FindFragments(mol, rigid_fragments);
	torsdof=rigid_fragments.size()-1;

	unsigned int root_piece = 0;
    for (unsigned j = 0; j < rigid_fragments.size(); j++)
    {
      if (IsIn((rigid_fragments[j]), best_root_atom)) {root_piece=j; break;} //this is the root rigid molecule fragment
    }

    ConstructTree(tree, rigid_fragments, root_piece, mol, true);

    assert(nc == mol.NumConformers()); //didn't lose any in analysis, did we?
}

//output data for this conformer
void MCMolConverter::convertConformer(unsigned conf, std::ostream& out)
{
	parsing_struct p;
	context c;

	mol.SetConformer(conf);
	std::map<unsigned int, obbranch> tmptree(tree); //tree gets modified by outputtree
    OutputTree(mol, c, p, tmptree, torsdof);

	boost::iostreams::filtering_stream<boost::iostreams::output> strm;
	strm.push(boost::iostreams::gzip_compressor());
	strm.push(out);

	boost::archive::binary_oarchive serialout(strm,boost::archive::no_header|boost::archive::no_tracking);

	serialout << torsdof;
	serialout << p;
	serialout << c;
}

//sets up data structures used by both text and binary
//we link with smina to nsure compatibility
unsigned convertParsing(OBMol& mol, parsing_struct& p, context& c)
{
	mol.AddHydrogens();

	mol.SetAutomaticFormalCharge(false);
	DeleteHydrogens(mol); //leaves just polars

	vector<vector<int> > rigid_fragments; //the vector of all the rigid molecule fragments, using atom indexes
	map<unsigned int, obbranch> tree;

	//we kind of assume a connected molecule
	unsigned best_root_atom = FindFragments(mol, rigid_fragments);
	unsigned torsdof=rigid_fragments.size()-1;

	unsigned int root_piece = 0;
    for (unsigned j = 0; j < rigid_fragments.size(); j++)
    {
      if (IsIn((rigid_fragments[j]), best_root_atom)) {root_piece=j; break;} //this is the root rigid molecule fragment
    }

    ConstructTree(tree, rigid_fragments, root_piece, mol, true);

    OutputTree(mol, c, p, tree, torsdof);

    return torsdof;
}

template <class T>
static void convert(OBMol& mol, T& serialout, ostream& out)
{
	parsing_struct p;
	context c;
	unsigned torsdof = convertParsing(mol, p, c);
	serialout << torsdof;
	serialout << p;
	serialout << c;
}

//text output
void convertText(OBMol& mol, ostream& out)
{
	boost::archive::text_oarchive serialout(out,boost::archive::no_header|boost::archive::no_tracking);
	convert(mol, serialout, out);
}

//binary output
void convertBinary(OBMol& mol,  ostream& out)
{
	//by definition, smina format is gzipped
	boost::iostreams::filtering_stream<boost::iostreams::output> strm;
	strm.push(boost::iostreams::gzip_compressor());
	strm.push(out);

	boost::archive::binary_oarchive serialout(strm,boost::archive::no_header|boost::archive::no_tracking);
	convert(mol, serialout, strm);
}

} //namespace SminaConverter
<|endoftext|>


<commit_before>#include "regexp/regexp2.hpp"
#include <cstdio>
#include <iostream>
#include <fstream>

using namespace SRX;

#define INSERT_HERE Any

int main (int argc, char ** argv)
{
	RegularExpression< Selection<Str<'A','B','C','D','E'>,Str<'D','E','F','G','H'>,Str<'E','F','G','H','I'>,Repeat<4,0,Chr<'A'>>>
 > regexp;

	if (argc >= 2)
	{

		std::ifstream ifs (std::string(argv[1]), std::ifstream::in);

		char buffer[1024];
		//std::string line;

		while (ifs.getline(buffer,1024))
		{
			if (regexp(buffer))
			{
				std::cout << buffer << '\n';
			}
		}
	}
	else
	{
		std::string line;

		while (getline(std::cin,line))
		{
			if (regexp(line))
			{
				std::cout << line << '\n';
			}
		}
	}

	return 0;
}
<commit_msg>Multifile regexp.<commit_after>#include "regexp/regexp2.hpp"
#include <cstdio>
#include <iostream>
#include <fstream>

using namespace SRX;

#define INSERT_HERE Any

int main (int argc, char ** argv)
{
	RegularExpression< Selection<Str<'A','B','C','D','E'>,Str<'D','E','F','G','H'>,Str<'E','F','G','H','I'>,Repeat<4,0,Chr<'A'>>>
 > regexp;

	if (argc == 2)
	{
		std::ifstream ifs (std::string(argv[1]), std::ifstream::in);

		char buffer[1024];
		//std::string line;

		while (ifs.getline(buffer,1024))
		{
			if (regexp(buffer))
			{
				std::cout << buffer << '\n';
			}
		}
	}
	else if (argc >= 2)
	{
		for (int i = 1; i < argc; ++i)
		{
			std::string fname{std::string(argv[i])};
			std::ifstream ifs (fname, std::ifstream::in);

			char buffer[1024];
			//std::string line;

			while (ifs.getline(buffer,1024))
			{
				if (regexp(buffer))
				{
					std::cout << fname << ": " << buffer << '\n';
				}
			}
		}
	}
	else
	{
		std::string line;

		while (getline(std::cin,line))
		{
			if (regexp(line))
			{
				std::cout << line << '\n';
			}
		}
	}

	return 0;
}
<|endoftext|>