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

#include "paymentservertests.h"

#include "optionsmodel.h"
#include "paymentrequestdata.h"

#include "amount.h"
#include "random.h"
#include "script/script.h"
#include "script/standard.h"
#include "util.h"
#include "utilstrencodings.h"

#include <openssl/x509.h>
#include <openssl/x509_vfy.h>

#include <QFileOpenEvent>
#include <QTemporaryFile>

X509 *parse_b64der_cert(const char* cert_data)
{
    std::vector<unsigned char> data = DecodeBase64(cert_data);
    assert(data.size() > 0);
    const unsigned char* dptr = &data[0];
    X509 *cert = d2i_X509(nullptr, &dptr, data.size());
    assert(cert);
    return cert;
}

//
// Test payment request handling
//

static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsigned char>& data)
{
    RecipientCatcher sigCatcher;
    QObject::connect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
        &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));

    // Write data to a temp file:
    QTemporaryFile f;
    f.open();
    f.write((const char*)&data[0], data.size());
    f.close();

    // Create a QObject, install event filter from PaymentServer
    // and send a file open event to the object
    QObject object;
    object.installEventFilter(server);
    QFileOpenEvent event(f.fileName());
    // If sending the event fails, this will cause sigCatcher to be empty,
    // which will lead to a test failure anyway.
    QCoreApplication::sendEvent(&object, &event);

    QObject::disconnect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
        &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));

    // Return results from sigCatcher
    return sigCatcher.recipient;
}

void PaymentServerTests::paymentServerTests()
{
    SelectParams(CBaseChainParams::MAIN);
    OptionsModel optionsModel;
    PaymentServer* server = new PaymentServer(nullptr, false);
    X509_STORE* caStore = X509_STORE_new();
    X509_STORE_add_cert(caStore, parse_b64der_cert(caCert1_BASE64));
    PaymentServer::LoadRootCAs(caStore);
    server->setOptionsModel(&optionsModel);
    server->uiReady();

    std::vector<unsigned char> data;
    SendCoinsRecipient r;
    QString merchant;

    // Now feed PaymentRequests to server, and observe signals it produces

    // This payment request validates directly against the
    // caCert1 certificate authority:
    data = DecodeBase64(paymentrequest1_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString("testmerchant.org"));

    // Signed, but expired, merchant cert in the request:
    data = DecodeBase64(paymentrequest2_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString(""));

    // 10-long certificate chain, all intermediates valid:
    data = DecodeBase64(paymentrequest3_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString("testmerchant8.org"));

    // Long certificate chain, with an expired certificate in the middle:
    data = DecodeBase64(paymentrequest4_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString(""));

    // Validly signed, but by a CA not in our root CA list:
    data = DecodeBase64(paymentrequest5_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString(""));

    // Try again with no root CA's, verifiedMerchant should be empty:
    caStore = X509_STORE_new();
    PaymentServer::LoadRootCAs(caStore);
    data = DecodeBase64(paymentrequest1_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString(""));

    // Load second root certificate
    caStore = X509_STORE_new();
    X509_STORE_add_cert(caStore, parse_b64der_cert(caCert2_BASE64));
    PaymentServer::LoadRootCAs(caStore);

    QByteArray byteArray;

    // For the tests below we just need the payment request data from
    // paymentrequestdata.h parsed + stored in r.paymentRequest.
    //
    // These tests require us to bypass the following normal client execution flow
    // shown below to be able to explicitly just trigger a certain condition!
    //
    // handleRequest()
    // -> PaymentServer::eventFilter()
    //   -> PaymentServer::handleURIOrFile()
    //     -> PaymentServer::readPaymentRequestFromFile()
    //       -> PaymentServer::processPaymentRequest()

    // Contains a testnet paytoaddress, so payment request network doesn't match client network:
    data = DecodeBase64(paymentrequest1_cert2_BASE64);
    byteArray = QByteArray((const char*)&data[0], data.size());
    r.paymentRequest.parse(byteArray);
    // Ensure the request is initialized, because network "main" is default, even for
    // uninitialized payment requests and that will fail our test here.
    QVERIFY(r.paymentRequest.IsInitialized());
    QCOMPARE(PaymentServer::verifyNetwork(r.paymentRequest.getDetails()), false);

    // Expired payment request (expires is set to 1 = 1970-01-01 00:00:01):
    data = DecodeBase64(paymentrequest2_cert2_BASE64);
    byteArray = QByteArray((const char*)&data[0], data.size());
    r.paymentRequest.parse(byteArray);
    // Ensure the request is initialized
    QVERIFY(r.paymentRequest.IsInitialized());
    // compares 1 < GetTime() == false (treated as expired payment request)
    QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);

    // Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t):
    // 9223372036854775807 (uint64), 9223372036854775807 (int64_t) and -1 (int32_t)
    // -1 is 1969-12-31 23:59:59 (for a 32 bit time values)
    data = DecodeBase64(paymentrequest3_cert2_BASE64);
    byteArray = QByteArray((const char*)&data[0], data.size());
    r.paymentRequest.parse(byteArray);
    // Ensure the request is initialized
    QVERIFY(r.paymentRequest.IsInitialized());
    // compares 9223372036854775807 < GetTime() == false (treated as unexpired payment request)
    QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), false);

    // Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64):
    // 9223372036854775808 (uint64), -9223372036854775808 (int64_t) and 0 (int32_t)
    // 0 is 1970-01-01 00:00:00 (for a 32 bit time values)
    data = DecodeBase64(paymentrequest4_cert2_BASE64);
    byteArray = QByteArray((const char*)&data[0], data.size());
    r.paymentRequest.parse(byteArray);
    // Ensure the request is initialized
    QVERIFY(r.paymentRequest.IsInitialized());
    // compares -9223372036854775808 < GetTime() == true (treated as expired payment request)
    QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);

    // Test BIP70 DoS protection:
    unsigned char randData[BIP70_MAX_PAYMENTREQUEST_SIZE + 1];
    GetRandBytes(randData, sizeof(randData));
    // Write data to a temp file:
    QTemporaryFile tempFile;
    tempFile.open();
    tempFile.write((const char*)randData, sizeof(randData));
    tempFile.close();
    // compares 50001 <= BIP70_MAX_PAYMENTREQUEST_SIZE == false
    QCOMPARE(PaymentServer::verifySize(tempFile.size()), false);

    // Payment request with amount overflow (amount is set to 21000001 BTC):
    data = DecodeBase64(paymentrequest5_cert2_BASE64);
    byteArray = QByteArray((const char*)&data[0], data.size());
    r.paymentRequest.parse(byteArray);
    // Ensure the request is initialized
    QVERIFY(r.paymentRequest.IsInitialized());
    // Extract address and amount from the request
    QList<std::pair<CScript, CAmount> > sendingTos = r.paymentRequest.getPayTo();
    for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) {
        CTxDestination dest;
        if (ExtractDestination(sendingTo.first, dest))
            QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false);
    }

    delete server;
}

void RecipientCatcher::getRecipient(SendCoinsRecipient r)
{
    recipient = r;
}
<commit_msg>Update paymentservertests.cpp<commit_after>// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "paymentservertests.h"

#include "optionsmodel.h"
#include "paymentrequestdata.h"

#include "amount.h"
#include "random.h"
#include "script/script.h"
#include "script/standard.h"
#include "util.h"
#include "utilstrencodings.h"

#include <openssl/x509.h>
#include <openssl/x509_vfy.h>

#include <QFileOpenEvent>
#include <QTemporaryFile>

X509 *parse_b64der_cert(const char* cert_data)
{
    std::vector<unsigned char> data = DecodeBase64(cert_data);
    assert(data.size() > 0);
    const unsigned char* dptr = &data[0];
    X509 *cert = d2i_X509(nullptr, &dptr, data.size());
    assert(cert);
    return cert;
}

//
// Test payment request handling
//

static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsigned char>& data)
{
    RecipientCatcher sigCatcher;
    QObject::connect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
        &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));

    // Write data to a temp file:
    QTemporaryFile f;
    f.open();
    f.write((const char*)&data[0], data.size());
    f.close();

    // Create a QObject, install event filter from PaymentServer
    // and send a file open event to the object
    QObject object;
    object.installEventFilter(server);
    QFileOpenEvent event(f.fileName());
    // If sending the event fails, this will cause sigCatcher to be empty,
    // which will lead to a test failure anyway.
    QCoreApplication::sendEvent(&object, &event);

    QObject::disconnect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
        &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));

    // Return results from sigCatcher
    return sigCatcher.recipient;
}

void PaymentServerTests::paymentServerTests()
{
    SelectParams(CBaseChainParams::MAIN);
    OptionsModel optionsModel;
    PaymentServer* server = new PaymentServer(nullptr, false);
    X509_STORE* caStore = X509_STORE_new();
    X509_STORE_add_cert(caStore, parse_b64der_cert(caCert1_BASE64));
    PaymentServer::LoadRootCAs(caStore);
    server->setOptionsModel(&optionsModel);
    server->uiReady();

    std::vector<unsigned char> data;
    SendCoinsRecipient r;
    QString merchant;

    // Now feed PaymentRequests to server, and observe signals it produces

    // This payment request validates directly against the
    // caCert1 certificate authority:
    data = DecodeBase64(paymentrequest1_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString("testmerchant.org"));

    // Signed, but expired, merchant cert in the request:
    data = DecodeBase64(paymentrequest2_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString(""));

    // 10-long certificate chain, all intermediates valid:
    data = DecodeBase64(paymentrequest3_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString("testmerchant8.org"));

    // Long certificate chain, with an expired certificate in the middle:
    data = DecodeBase64(paymentrequest4_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString(""));

    // Validly signed, but by a CA not in our root CA list:
    data = DecodeBase64(paymentrequest5_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString(""));

    // Try again with no root CA's, verifiedMerchant should be empty:
    caStore = X509_STORE_new();
    PaymentServer::LoadRootCAs(caStore);
    data = DecodeBase64(paymentrequest1_cert1_BASE64);
    r = handleRequest(server, data);
    r.paymentRequest.getMerchant(caStore, merchant);
    QCOMPARE(merchant, QString(""));

    // Load second root certificate
    caStore = X509_STORE_new();
    X509_STORE_add_cert(caStore, parse_b64der_cert(caCert2_BASE64));
    PaymentServer::LoadRootCAs(caStore);

    QByteArray byteArray;

    // For the tests below we just need the payment request data from
    // paymentrequestdata.h parsed + stored in r.paymentRequest.
    //
    // These tests require us to bypass the following normal client execution flow
    // shown below to be able to explicitly just trigger a certain condition!
    //
    // handleRequest()
    // -> PaymentServer::eventFilter()
    //   -> PaymentServer::handleURIOrFile()
    //     -> PaymentServer::readPaymentRequestFromFile()
    //       -> PaymentServer::processPaymentRequest()

    // Contains a testnet paytoaddress, so payment request network doesn't match client network:
    data = DecodeBase64(paymentrequest1_cert2_BASE64);
    byteArray = QByteArray((const char*)&data[0], data.size());
    r.paymentRequest.parse(byteArray);
    // Ensure the request is initialized, because network "main" is default, even for
    // uninitialized payment requests and that will fail our test here.
    QVERIFY(r.paymentRequest.IsInitialized());
    QCOMPARE(PaymentServer::verifyNetwork(r.paymentRequest.getDetails()), false);

    // Expired payment request (expires is set to 1 = 1970-01-01 00:00:01):
    data = DecodeBase64(paymentrequest2_cert2_BASE64);
    byteArray = QByteArray((const char*)&data[0], data.size());
    r.paymentRequest.parse(byteArray);
    // Ensure the request is initialized
    QVERIFY(r.paymentRequest.IsInitialized());
    // compares 1 < GetTime() == false (treated as expired payment request)
    QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);

    // Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t):
    // 9223372036854775807 (uint64), 9223372036854775807 (int64_t) and -1 (int32_t)
    // -1 is 1969-12-31 23:59:59 (for a 32 bit time values)
    data = DecodeBase64(paymentrequest3_cert2_BASE64);
    byteArray = QByteArray((const char*)&data[0], data.size());
    r.paymentRequest.parse(byteArray);
    // Ensure the request is initialized
    QVERIFY(r.paymentRequest.IsInitialized());
    // compares 9223372036854775807 < GetTime() == false (treated as unexpired payment request)
    QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), false);

    // Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64):
    // 9223372036854775808 (uint64), -9223372036854775808 (int64_t) and 0 (int32_t)
    // 0 is 1970-01-01 00:00:00 (for a 32 bit time values)
    data = DecodeBase64(paymentrequest4_cert2_BASE64);
    byteArray = QByteArray((const char*)&data[0], data.size());
    r.paymentRequest.parse(byteArray);
    // Ensure the request is initialized
    QVERIFY(r.paymentRequest.IsInitialized());
    // compares -9223372036854775808 < GetTime() == true (treated as expired payment request)
    QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);

    // Test BIP70 DoS protection:
    unsigned char randData[BIP70_MAX_PAYMENTREQUEST_SIZE + 1];
    GetRandBytes(randData, sizeof(randData));
    // Write data to a temp file:
    QTemporaryFile tempFile;
    tempFile.open();
    tempFile.write((const char*)randData, sizeof(randData));
    tempFile.close();
    // compares 50001 <= BIP70_MAX_PAYMENTREQUEST_SIZE == false
    QCOMPARE(PaymentServer::verifySize(tempFile.size()), false);

    // Payment request with amount overflow (amount is set to 21000001 BTG):
    data = DecodeBase64(paymentrequest5_cert2_BASE64);
    byteArray = QByteArray((const char*)&data[0], data.size());
    r.paymentRequest.parse(byteArray);
    // Ensure the request is initialized
    QVERIFY(r.paymentRequest.IsInitialized());
    // Extract address and amount from the request
    QList<std::pair<CScript, CAmount> > sendingTos = r.paymentRequest.getPayTo();
    for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) {
        CTxDestination dest;
        if (ExtractDestination(sendingTo.first, dest))
            QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false);
    }

    delete server;
}

void RecipientCatcher::getRecipient(SendCoinsRecipient r)
{
    recipient = r;
}
<|endoftext|>


<commit_before><commit_msg>Remove repetitive comments from Rational.hpp<commit_after><|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#pragma once

#include <string>
#include <iostream>

#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <cstdio>

#include <pficommon/lang/cast.h>
#include <pficommon/text/json.h>

#include "../fv_converter/converter_config.hpp"

using std::string;
using std::cout;
using std::endl;

pid_t fork_process(const char* name, int port = 9199){
  string cmd(BUILD_DIR);
  pid_t child;
  cmd += "/src/server/juba";
  cmd += name;
  child = fork();
  string port_str = pfi::lang::lexical_cast<std::string>(port);
  if(child == 0){
    const char *const argv[6] = {cmd.c_str(), "-p", port_str.c_str(), "-d", ".", NULL};
    int ret = execv(cmd.c_str(), (char **const) argv);
    if(ret < 0){
      perror("execl");
      cout << cmd << " " << child << endl;
    }
  }else if( child < 0 ){
    perror("--");
    return -1;
  }
  usleep(77777); // we wanna be lucky!
  return child;
}

void kill_process(pid_t child){
  if(kill(child, SIGTERM) != 0){
    perror("");
    return;
  }
  int status = 0;
  waitpid(child, &status, 0);
}

std::string config_to_string(const jubatus::fv_converter::converter_config& config) {
  std::stringstream ss;
  ss << pfi::text::json::to_json(config);
  return ss.str();
}

<commit_msg>wait till client can connect to the server<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#pragma once

#include <string>
#include <iostream>

#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <cstdio>

#include <pficommon/lang/cast.h>
#include <pficommon/text/json.h>
#include <pficommon/network/mprpc.h>

#include "../fv_converter/converter_config.hpp"

using std::string;
using std::cout;
using std::endl;

void wait_server(int port) {
  pfi::network::mprpc::rpc_client cli("localhost", port, 10);
  long sleep_time = 1000;
  // 1000 * \sum {i=0..9} 2^i = 1024000 micro sec = 1024 ms
  for (int i = 0; i < 10; ++i) {
    usleep(sleep_time);
    try {
      cli.call<bool()>("dummy")();
      throw std::runtime_error("dummy rpc successed");
    } catch(pfi::network::mprpc::method_not_found& e) {
      return;
    } catch(pfi::network::mprpc::rpc_io_error& e) {
      // wait until the server bigins to listen
    }
    sleep_time *= 2;
  }
  throw std::runtime_error("cannot connect");
}

pid_t fork_process(const char* name, int port = 9199){
  string cmd(BUILD_DIR);
  pid_t child;
  cmd += "/src/server/juba";
  cmd += name;
  child = fork();
  string port_str = pfi::lang::lexical_cast<std::string>(port);
  if(child == 0){
    const char *const argv[6] = {cmd.c_str(), "-p", port_str.c_str(), "-d", ".", NULL};
    int ret = execv(cmd.c_str(), (char **const) argv);
    if(ret < 0){
      perror("execl");
      cout << cmd << " " << child << endl;
    }
  }else if( child < 0 ){
    perror("--");
    return -1;
  }
  wait_server(port);
  return child;
}

void kill_process(pid_t child){
  if(kill(child, SIGTERM) != 0){
    perror("");
    return;
  }
  int status = 0;
  waitpid(child, &status, 0);
}

std::string config_to_string(const jubatus::fv_converter::converter_config& config) {
  std::stringstream ss;
  ss << pfi::text::json::to_json(config);
  return ss.str();
}

<|endoftext|>


<commit_before>/*
* Copyright (c) 2003-2010 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/**
 * \file Windows-specific implementation of file.h
 */

#ifndef __WX__
#include <afx.h>
#endif

#include <Windows.h>
#include <LMCONS.H> // for UNLEN definition
#include <shellapi.h>
#include <shlwapi.h>

#include <io.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fstream>

#include "../typedefs.h"
#include "../file.h"
#include "../dir.h"
#include "../env.h"

const TCHAR pws_os::PathSeparator = _T('\\');

bool pws_os::FileExists(const stringT &filename)
{
  struct _stat statbuf;
  int status;

  status = _tstat(filename.c_str(), &statbuf);
  return (status == 0);
}

bool pws_os::FileExists(const stringT &filename, bool &bReadOnly)
{
  bool retval;
  bReadOnly = false;

  retval = (_taccess(filename.c_str(), R_OK) == 0);
  if (retval) {
    bReadOnly = (_taccess(filename.c_str(), W_OK) != 0);
  }
  return retval;
}

void pws_os::AddDrive(stringT &path)
{
  using namespace pws_os;
  // Adds a drive letter to the path if not there, unless
  // it's a UNC path (\\host\sharename...)
  if (!(path[0] == '\\' && path[1] == '\\')) {
    stringT drive, dir, file, ext;
    splitpath(path, drive, dir, file, ext);

    if (drive.empty()) {
      const stringT exedir = getexecdir();
      stringT exeDrive, dummy;
      splitpath(exedir, exeDrive, dummy, dummy, dummy);
      path = makepath(exeDrive, dir, file, ext);
    }
  }
}

static bool FileOP(const stringT &src, const stringT &dst,
                   UINT wFunc)
{
  // wrapper for SHFileOperation() for moving or copying from src to dst
  // create any intervening directories as necessary & automatically
  TCHAR szSource[_MAX_PATH + 1];
  TCHAR szDestination[_MAX_PATH + 1];

  // SHFileOperation() acts very oddly if files are missing a drive
  // (eg, renames to pwsafeN.psa instead of pwsafe.ibak)

  stringT srcD(src), dstD(dst);
  pws_os::AddDrive(srcD);
  pws_os::AddDrive(dstD);

  if (srcD.length() >= _MAX_PATH || dstD.length() >= _MAX_PATH)
    return false;

  const TCHAR *lpsz_current = srcD.c_str();
  const TCHAR *lpsz_new = dstD.c_str();

#if (_MSC_VER >= 1400)
  _tcscpy_s(szSource, _MAX_PATH, lpsz_current);
  _tcscpy_s(szDestination, _MAX_PATH, lpsz_new);
#else
  _tcscpy(szSource, lpsz_current);
  _tcscpy(szDestination, lpsz_new);
#endif

  // Must end with double NULL
  szSource[srcD.length() + 1] = TCHAR('\0');
  szDestination[dstD.length() + 1] = TCHAR('\0');

  SHFILEOPSTRUCT sfop;
  memset(&sfop, 0, sizeof(sfop));
  sfop.hwnd = GetActiveWindow();
  sfop.wFunc = wFunc;
  sfop.pFrom = szSource;
  sfop.pTo = szDestination;
  sfop.fFlags = FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_SILENT | FOF_NOERRORUI;

  return (SHFileOperation(&sfop) == 0);
}

bool pws_os::RenameFile(const stringT &oldname, const stringT &newname)
{
  _tremove(newname.c_str()); // otherwise rename may fail if newname exists
  return FileOP(oldname, newname, FO_MOVE);
}

extern bool pws_os::CopyAFile(const stringT &from, const stringT &to)
{
  return FileOP(from, to, FO_COPY);
}

bool pws_os::DeleteAFile(const stringT &filename)
{
  return DeleteFile(filename.c_str()) == TRUE;
}

void pws_os::FindFiles(const stringT &filter, std::vector<stringT> &res)
{
  res.clear();
  _tfinddata_t fileinfo;
  intptr_t handle = _tfindfirst(filter.c_str(), &fileinfo);
  if (handle == -1)
    return;

  do {
    res.push_back(LPCTSTR(fileinfo.name));
  } while (_tfindnext(handle, &fileinfo) == 0);

  _findclose(handle);
}

/*
* The file lock/unlock functions were first implemented (in 2.08)
* with Posix semantics (using open(_O_CREATE|_O_EXCL) to detect
* an existing lock.
* This fails to check liveness of the locker process, specifically,
* if a user just turns of her PC, the lock file will remain.
* So, I'm keeping the Posix code under idef POSIX_FILE_LOCK,
* and re-implementing using the Win32 API, whose semantics
* supposedly protect against this scenario.
* Thanks to Frank (xformer) for discussion on the subject.
*/

static stringT GetLockFileName(const stringT &filename)
{
  ASSERT(!filename.empty());
  // derive lock filename from filename
  stringT retval(filename, 0, filename.find_last_of(TCHAR('.')));
  retval += _T(".plk");
  return retval;
}

static void GetLocker(const stringT &lock_filename, stringT &locker)
{
  locker = _T("Unable to determine locker");
  // read locker data ("user@machine:nnnnnnnn") from file
  TCHAR lockerStr[UNLEN + MAX_COMPUTERNAME_LENGTH + 11];
  // flags here counter (my) intuition, but see
  // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/creating_and_opening_files.asp
  HANDLE h2 = ::CreateFile(lock_filename.c_str(),
                           GENERIC_READ,
                           FILE_SHARE_WRITE,
                           NULL,
                           OPEN_EXISTING,
                           (FILE_ATTRIBUTE_NORMAL |
                            // (Lockheed Martin) Secure Coding  11-14-2007
                            SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION),
                           NULL);
  // Make sure it's a file and not a pipe.  (Lockheed Martin) Secure Coding  11-14-2007
  if (h2 != INVALID_HANDLE_VALUE) {
    if (::GetFileType( h2 ) != FILE_TYPE_DISK) {
      ::CloseHandle( h2 );
      h2 = INVALID_HANDLE_VALUE;
    }
  }
  // End of Change.  (Lockheed Martin) Secure Coding  11-14-2007

  if (h2 != INVALID_HANDLE_VALUE) {
    DWORD bytesRead;
    (void)::ReadFile(h2, lockerStr, sizeof(lockerStr)-1,
                     &bytesRead, NULL);
    CloseHandle(h2);
    if (bytesRead > 0) {
      lockerStr[bytesRead/sizeof(TCHAR)] = TCHAR('\0');
      locker = lockerStr;
    } // read info from lock file
  }
}

bool pws_os::LockFile(const stringT &filename, stringT &locker,
                      HANDLE &lockFileHandle, int &LockCount)
{
  const stringT lock_filename = GetLockFileName(filename);
  stringT s_locker;
  const stringT user = pws_os::getusername();
  const stringT host = pws_os::gethostname();
  const stringT pid = pws_os::getprocessid();

  // Use Win32 API for locking - supposedly better at
  // detecting dead locking processes
  if (lockFileHandle != INVALID_HANDLE_VALUE) {
    // here if we've open another (or same) dbase previously,
    // need to unlock it. A bit inelegant...
    // If app was minimized and ClearData() called, we've a small
    // potential for a TOCTTOU issue here. Worse case, lock
    // will fail.

    const stringT cs_me = user + _T("@") + host + _T(":") + pid;
    GetLocker(lock_filename, s_locker);

    if (cs_me == s_locker) {
      LockCount++;
      locker.clear();
      return true;
    } else {
      pws_os::UnlockFile(filename, lockFileHandle, LockCount);
    }
  }

  // Since ::CreateFile can't create directories, we need to check it exists
  // first and, if not, try and create it.
  // This is primarily for the config directory in the local APPDATA directory
  // but will also be called for the database lock file - and since the database
  // is already there, it is a bit of a redundant check but easier than coding
  // for every different situation.
  stringT sDrive, sDir, sName, sExt;
  pws_os::splitpath(lock_filename, sDrive, sDir, sName, sExt);
  stringT sNewDir = sDrive + sDir;
	DWORD dwAttrib = GetFileAttributes(sNewDir.c_str());
  DWORD dwerr(0);
  if (dwAttrib == INVALID_FILE_ATTRIBUTES)
    dwerr = GetLastError();

  BOOL brc(TRUE);
  if (dwerr == ERROR_FILE_NOT_FOUND ||
      (dwAttrib != INVALID_FILE_ATTRIBUTES) &&
      !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
    SECURITY_ATTRIBUTES secatt = {0};
    secatt.nLength = sizeof(secatt);
    brc = ::CreateDirectory(sNewDir.c_str(), &secatt);
  }

  // Obviously, if we can't create the directory - don't bother trying to
  // create the lock file!
  if (brc) {
    lockFileHandle = ::CreateFile(lock_filename.c_str(),
                                  GENERIC_WRITE,
                                  FILE_SHARE_READ,
                                  NULL,
                                  CREATE_ALWAYS, // rely on share to fail if exists!
                                  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH |
                                  // (Lockheed Martin) Secure Coding  11-14-2007
                                  SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION,
                                  NULL);

    // Make sure it's a file and not a pipe.  (Lockheed Martin) Secure Coding  11-14-2007
    if (lockFileHandle != INVALID_HANDLE_VALUE) {
      if (::GetFileType( lockFileHandle ) != FILE_TYPE_DISK) {
        ::CloseHandle( lockFileHandle );
        lockFileHandle = INVALID_HANDLE_VALUE;
      }
    }
    // End of Change.  (Lockheed Martin) Secure Coding  11-14-2007
  }

  if (lockFileHandle == INVALID_HANDLE_VALUE) {
    DWORD error = GetLastError();
    switch (error) {
    case ERROR_SHARING_VIOLATION: // already open by a live process
      GetLocker(lock_filename, s_locker);
      locker = s_locker.c_str();
      break;
    default:
      locker = _T("Cannot create lock file - no permission in directory?");
      break;
    } // switch (error)
    return false;
  } else { // valid filehandle, write our info
    DWORD numWrit, sumWrit;
    BOOL write_status;
    write_status = ::WriteFile(lockFileHandle,
                               user.c_str(), user.length() * sizeof(TCHAR),
                               &sumWrit, NULL);
    write_status &= ::WriteFile(lockFileHandle,
                                _T("@"), sizeof(TCHAR),
                                &numWrit, NULL);
    sumWrit += numWrit;
    write_status &= ::WriteFile(lockFileHandle,
                                host.c_str(), host.length() * sizeof(TCHAR),
                                &numWrit, NULL);
    sumWrit += numWrit;
    write_status &= ::WriteFile(lockFileHandle,
                                _T(":"), sizeof(TCHAR),
                                &numWrit, NULL);
    sumWrit += numWrit;
    write_status &= ::WriteFile(lockFileHandle,
                                pid.c_str(), pid.length() * sizeof(TCHAR),
                                &numWrit, NULL);
    sumWrit += numWrit;
    ASSERT(sumWrit > 0);
    LockCount++;
    return (write_status == TRUE);
  }
}

void pws_os::UnlockFile(const stringT &filename,
                        HANDLE &lockFileHandle, int &LockCount)
{
  const stringT user = pws_os::getusername();
  const stringT host = pws_os::gethostname();
  const stringT pid = pws_os::getprocessid();

  // Use Win32 API for locking - supposedly better at
  // detecting dead locking processes
  if (lockFileHandle != INVALID_HANDLE_VALUE) {
    stringT locker;
    const stringT lock_filename = GetLockFileName(filename);
    const stringT cs_me = user + _T("@") + host + _T(":") + pid;
    GetLocker(lock_filename, locker);

    if (cs_me == locker && LockCount > 1) {
      LockCount--;
    } else {
      LockCount = 0;
      CloseHandle(lockFileHandle);
      lockFileHandle = INVALID_HANDLE_VALUE;
      DeleteFile(lock_filename.c_str());
    }
  }
}

bool pws_os::IsLockedFile(const stringT &filename)
{
  const stringT lock_filename = GetLockFileName(filename);
  // under this scheme, we need to actually try to open the file to determine
  // if it's locked.
  HANDLE h = CreateFile(lock_filename.c_str(),
                        GENERIC_WRITE,
                        FILE_SHARE_READ,
                        NULL,
                        OPEN_EXISTING, // don't create one!
                        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH |
                        // (Lockheed Martin) Secure Coding  11-14-2007
                        SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION,
                        NULL);

  // Make sure it's a file and not a pipe.  (Lockheed Martin) Secure Coding  11-14-2007
  if (h != INVALID_HANDLE_VALUE) {
    if (::GetFileType( h ) != FILE_TYPE_DISK) {
      ::CloseHandle( h );
      h = INVALID_HANDLE_VALUE;
    }
  }
  // End of Change.  (Lockheed Martin) Secure Coding  11-14-2007

  if (h == INVALID_HANDLE_VALUE) {
    DWORD error = GetLastError();
    if (error == ERROR_SHARING_VIOLATION)
      return true;
    else
      return false; // couldn't open it, probably doesn't exist.
  } else {
    CloseHandle(h); // here if exists but lockable.
    return false;
  }
}

std::FILE *pws_os::FOpen(const stringT &filename, const TCHAR *mode)
{
  std::FILE *fd = NULL;
#if (_MSC_VER >= 1400)
  _tfopen_s(&fd, filename.c_str(), mode);
#else
  fd = _tfopen(m_filename.c_str(), mode);
#endif
  return fd;
}

long pws_os::fileLength(std::FILE *fp) {
  if (fp != NULL) {
    long pos = std::ftell(fp);
    std::fseek(fp, 0, SEEK_END);
    long len = ftell(fp);
    std::fseek(fp, pos, SEEK_SET);
    return len;
  } else
    return 0;
}
<commit_msg>Don't crash if MRU list not full<commit_after>/*
* Copyright (c) 2003-2010 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/**
 * \file Windows-specific implementation of file.h
 */

#ifndef __WX__
#include <afx.h>
#endif

#include <Windows.h>
#include <LMCONS.H> // for UNLEN definition
#include <shellapi.h>
#include <shlwapi.h>

#include <io.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fstream>

#include "../typedefs.h"
#include "../file.h"
#include "../dir.h"
#include "../env.h"

const TCHAR pws_os::PathSeparator = _T('\\');

bool pws_os::FileExists(const stringT &filename)
{
  struct _stat statbuf;
  int status;

  status = _tstat(filename.c_str(), &statbuf);
  return (status == 0);
}

bool pws_os::FileExists(const stringT &filename, bool &bReadOnly)
{
  bool retval;
  bReadOnly = false;

  retval = (_taccess(filename.c_str(), R_OK) == 0);
  if (retval) {
    bReadOnly = (_taccess(filename.c_str(), W_OK) != 0);
  }
  return retval;
}

void pws_os::AddDrive(stringT &path)
{
  // Adds a drive letter to the path if not there, unless
  // empty string  or it's a UNC path (\\host\sharename...)
  using namespace pws_os;
  if(path.empty())
    return;
  if (!(path[0] == '\\' && path[1] == '\\')) {
    stringT drive, dir, file, ext;
    splitpath(path, drive, dir, file, ext);

    if (drive.empty()) {
      const stringT exedir = getexecdir();
      stringT exeDrive, dummy;
      splitpath(exedir, exeDrive, dummy, dummy, dummy);
      path = makepath(exeDrive, dir, file, ext);
    }
  }
}

static bool FileOP(const stringT &src, const stringT &dst,
                   UINT wFunc)
{
  // wrapper for SHFileOperation() for moving or copying from src to dst
  // create any intervening directories as necessary & automatically
  TCHAR szSource[_MAX_PATH + 1];
  TCHAR szDestination[_MAX_PATH + 1];

  // SHFileOperation() acts very oddly if files are missing a drive
  // (eg, renames to pwsafeN.psa instead of pwsafe.ibak)

  stringT srcD(src), dstD(dst);
  pws_os::AddDrive(srcD);
  pws_os::AddDrive(dstD);

  if (srcD.length() >= _MAX_PATH || dstD.length() >= _MAX_PATH)
    return false;

  const TCHAR *lpsz_current = srcD.c_str();
  const TCHAR *lpsz_new = dstD.c_str();

#if (_MSC_VER >= 1400)
  _tcscpy_s(szSource, _MAX_PATH, lpsz_current);
  _tcscpy_s(szDestination, _MAX_PATH, lpsz_new);
#else
  _tcscpy(szSource, lpsz_current);
  _tcscpy(szDestination, lpsz_new);
#endif

  // Must end with double NULL
  szSource[srcD.length() + 1] = TCHAR('\0');
  szDestination[dstD.length() + 1] = TCHAR('\0');

  SHFILEOPSTRUCT sfop;
  memset(&sfop, 0, sizeof(sfop));
  sfop.hwnd = GetActiveWindow();
  sfop.wFunc = wFunc;
  sfop.pFrom = szSource;
  sfop.pTo = szDestination;
  sfop.fFlags = FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_SILENT | FOF_NOERRORUI;

  return (SHFileOperation(&sfop) == 0);
}

bool pws_os::RenameFile(const stringT &oldname, const stringT &newname)
{
  _tremove(newname.c_str()); // otherwise rename may fail if newname exists
  return FileOP(oldname, newname, FO_MOVE);
}

extern bool pws_os::CopyAFile(const stringT &from, const stringT &to)
{
  return FileOP(from, to, FO_COPY);
}

bool pws_os::DeleteAFile(const stringT &filename)
{
  return DeleteFile(filename.c_str()) == TRUE;
}

void pws_os::FindFiles(const stringT &filter, std::vector<stringT> &res)
{
  res.clear();
  _tfinddata_t fileinfo;
  intptr_t handle = _tfindfirst(filter.c_str(), &fileinfo);
  if (handle == -1)
    return;

  do {
    res.push_back(LPCTSTR(fileinfo.name));
  } while (_tfindnext(handle, &fileinfo) == 0);

  _findclose(handle);
}

/*
* The file lock/unlock functions were first implemented (in 2.08)
* with Posix semantics (using open(_O_CREATE|_O_EXCL) to detect
* an existing lock.
* This fails to check liveness of the locker process, specifically,
* if a user just turns of her PC, the lock file will remain.
* So, I'm keeping the Posix code under idef POSIX_FILE_LOCK,
* and re-implementing using the Win32 API, whose semantics
* supposedly protect against this scenario.
* Thanks to Frank (xformer) for discussion on the subject.
*/

static stringT GetLockFileName(const stringT &filename)
{
  ASSERT(!filename.empty());
  // derive lock filename from filename
  stringT retval(filename, 0, filename.find_last_of(TCHAR('.')));
  retval += _T(".plk");
  return retval;
}

static void GetLocker(const stringT &lock_filename, stringT &locker)
{
  locker = _T("Unable to determine locker");
  // read locker data ("user@machine:nnnnnnnn") from file
  TCHAR lockerStr[UNLEN + MAX_COMPUTERNAME_LENGTH + 11];
  // flags here counter (my) intuition, but see
  // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/creating_and_opening_files.asp
  HANDLE h2 = ::CreateFile(lock_filename.c_str(),
                           GENERIC_READ,
                           FILE_SHARE_WRITE,
                           NULL,
                           OPEN_EXISTING,
                           (FILE_ATTRIBUTE_NORMAL |
                            // (Lockheed Martin) Secure Coding  11-14-2007
                            SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION),
                           NULL);
  // Make sure it's a file and not a pipe.  (Lockheed Martin) Secure Coding  11-14-2007
  if (h2 != INVALID_HANDLE_VALUE) {
    if (::GetFileType( h2 ) != FILE_TYPE_DISK) {
      ::CloseHandle( h2 );
      h2 = INVALID_HANDLE_VALUE;
    }
  }
  // End of Change.  (Lockheed Martin) Secure Coding  11-14-2007

  if (h2 != INVALID_HANDLE_VALUE) {
    DWORD bytesRead;
    (void)::ReadFile(h2, lockerStr, sizeof(lockerStr)-1,
                     &bytesRead, NULL);
    CloseHandle(h2);
    if (bytesRead > 0) {
      lockerStr[bytesRead/sizeof(TCHAR)] = TCHAR('\0');
      locker = lockerStr;
    } // read info from lock file
  }
}

bool pws_os::LockFile(const stringT &filename, stringT &locker,
                      HANDLE &lockFileHandle, int &LockCount)
{
  const stringT lock_filename = GetLockFileName(filename);
  stringT s_locker;
  const stringT user = pws_os::getusername();
  const stringT host = pws_os::gethostname();
  const stringT pid = pws_os::getprocessid();

  // Use Win32 API for locking - supposedly better at
  // detecting dead locking processes
  if (lockFileHandle != INVALID_HANDLE_VALUE) {
    // here if we've open another (or same) dbase previously,
    // need to unlock it. A bit inelegant...
    // If app was minimized and ClearData() called, we've a small
    // potential for a TOCTTOU issue here. Worse case, lock
    // will fail.

    const stringT cs_me = user + _T("@") + host + _T(":") + pid;
    GetLocker(lock_filename, s_locker);

    if (cs_me == s_locker) {
      LockCount++;
      locker.clear();
      return true;
    } else {
      pws_os::UnlockFile(filename, lockFileHandle, LockCount);
    }
  }

  // Since ::CreateFile can't create directories, we need to check it exists
  // first and, if not, try and create it.
  // This is primarily for the config directory in the local APPDATA directory
  // but will also be called for the database lock file - and since the database
  // is already there, it is a bit of a redundant check but easier than coding
  // for every different situation.
  stringT sDrive, sDir, sName, sExt;
  pws_os::splitpath(lock_filename, sDrive, sDir, sName, sExt);
  stringT sNewDir = sDrive + sDir;
	DWORD dwAttrib = GetFileAttributes(sNewDir.c_str());
  DWORD dwerr(0);
  if (dwAttrib == INVALID_FILE_ATTRIBUTES)
    dwerr = GetLastError();

  BOOL brc(TRUE);
  if (dwerr == ERROR_FILE_NOT_FOUND ||
      (dwAttrib != INVALID_FILE_ATTRIBUTES) &&
      !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
    SECURITY_ATTRIBUTES secatt = {0};
    secatt.nLength = sizeof(secatt);
    brc = ::CreateDirectory(sNewDir.c_str(), &secatt);
  }

  // Obviously, if we can't create the directory - don't bother trying to
  // create the lock file!
  if (brc) {
    lockFileHandle = ::CreateFile(lock_filename.c_str(),
                                  GENERIC_WRITE,
                                  FILE_SHARE_READ,
                                  NULL,
                                  CREATE_ALWAYS, // rely on share to fail if exists!
                                  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH |
                                  // (Lockheed Martin) Secure Coding  11-14-2007
                                  SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION,
                                  NULL);

    // Make sure it's a file and not a pipe.  (Lockheed Martin) Secure Coding  11-14-2007
    if (lockFileHandle != INVALID_HANDLE_VALUE) {
      if (::GetFileType( lockFileHandle ) != FILE_TYPE_DISK) {
        ::CloseHandle( lockFileHandle );
        lockFileHandle = INVALID_HANDLE_VALUE;
      }
    }
    // End of Change.  (Lockheed Martin) Secure Coding  11-14-2007
  }

  if (lockFileHandle == INVALID_HANDLE_VALUE) {
    DWORD error = GetLastError();
    switch (error) {
    case ERROR_SHARING_VIOLATION: // already open by a live process
      GetLocker(lock_filename, s_locker);
      locker = s_locker.c_str();
      break;
    default:
      locker = _T("Cannot create lock file - no permission in directory?");
      break;
    } // switch (error)
    return false;
  } else { // valid filehandle, write our info
    DWORD numWrit, sumWrit;
    BOOL write_status;
    write_status = ::WriteFile(lockFileHandle,
                               user.c_str(), user.length() * sizeof(TCHAR),
                               &sumWrit, NULL);
    write_status &= ::WriteFile(lockFileHandle,
                                _T("@"), sizeof(TCHAR),
                                &numWrit, NULL);
    sumWrit += numWrit;
    write_status &= ::WriteFile(lockFileHandle,
                                host.c_str(), host.length() * sizeof(TCHAR),
                                &numWrit, NULL);
    sumWrit += numWrit;
    write_status &= ::WriteFile(lockFileHandle,
                                _T(":"), sizeof(TCHAR),
                                &numWrit, NULL);
    sumWrit += numWrit;
    write_status &= ::WriteFile(lockFileHandle,
                                pid.c_str(), pid.length() * sizeof(TCHAR),
                                &numWrit, NULL);
    sumWrit += numWrit;
    ASSERT(sumWrit > 0);
    LockCount++;
    return (write_status == TRUE);
  }
}

void pws_os::UnlockFile(const stringT &filename,
                        HANDLE &lockFileHandle, int &LockCount)
{
  const stringT user = pws_os::getusername();
  const stringT host = pws_os::gethostname();
  const stringT pid = pws_os::getprocessid();

  // Use Win32 API for locking - supposedly better at
  // detecting dead locking processes
  if (lockFileHandle != INVALID_HANDLE_VALUE) {
    stringT locker;
    const stringT lock_filename = GetLockFileName(filename);
    const stringT cs_me = user + _T("@") + host + _T(":") + pid;
    GetLocker(lock_filename, locker);

    if (cs_me == locker && LockCount > 1) {
      LockCount--;
    } else {
      LockCount = 0;
      CloseHandle(lockFileHandle);
      lockFileHandle = INVALID_HANDLE_VALUE;
      DeleteFile(lock_filename.c_str());
    }
  }
}

bool pws_os::IsLockedFile(const stringT &filename)
{
  const stringT lock_filename = GetLockFileName(filename);
  // under this scheme, we need to actually try to open the file to determine
  // if it's locked.
  HANDLE h = CreateFile(lock_filename.c_str(),
                        GENERIC_WRITE,
                        FILE_SHARE_READ,
                        NULL,
                        OPEN_EXISTING, // don't create one!
                        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH |
                        // (Lockheed Martin) Secure Coding  11-14-2007
                        SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION,
                        NULL);

  // Make sure it's a file and not a pipe.  (Lockheed Martin) Secure Coding  11-14-2007
  if (h != INVALID_HANDLE_VALUE) {
    if (::GetFileType( h ) != FILE_TYPE_DISK) {
      ::CloseHandle( h );
      h = INVALID_HANDLE_VALUE;
    }
  }
  // End of Change.  (Lockheed Martin) Secure Coding  11-14-2007

  if (h == INVALID_HANDLE_VALUE) {
    DWORD error = GetLastError();
    if (error == ERROR_SHARING_VIOLATION)
      return true;
    else
      return false; // couldn't open it, probably doesn't exist.
  } else {
    CloseHandle(h); // here if exists but lockable.
    return false;
  }
}

std::FILE *pws_os::FOpen(const stringT &filename, const TCHAR *mode)
{
  std::FILE *fd = NULL;
#if (_MSC_VER >= 1400)
  _tfopen_s(&fd, filename.c_str(), mode);
#else
  fd = _tfopen(m_filename.c_str(), mode);
#endif
  return fd;
}

long pws_os::fileLength(std::FILE *fp) {
  if (fp != NULL) {
    long pos = std::ftell(fp);
    std::fseek(fp, 0, SEEK_END);
    long len = ftell(fp);
    std::fseek(fp, pos, SEEK_SET);
    return len;
  } else
    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/shell_integration.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

ShellIntegration::DefaultWebClientSetPermission
    ShellIntegration::CanSetAsDefaultProtocolClient() {
  // Allowed as long as the browser can become the operating system default
  // browser.
  return CanSetAsDefaultBrowser();
}

ShellIntegration::ShortcutInfo::ShortcutInfo()
    : is_platform_app(false),
      create_on_desktop(false),
      create_in_applications_menu(false),
      create_in_quick_launch_bar(false) {
}

ShellIntegration::ShortcutInfo::~ShortcutInfo() {}

static const struct ShellIntegration::AppModeInfo* gAppModeInfo = NULL;

// static
void ShellIntegration::SetAppModeInfo(const struct AppModeInfo* info) {
  gAppModeInfo = info;
}

// static
const struct ShellIntegration::AppModeInfo* ShellIntegration::AppModeInfo() {
  return gAppModeInfo;
}

// static
bool ShellIntegration::IsRunningInAppMode() {
  return gAppModeInfo != NULL;
}

// static
CommandLine ShellIntegration::CommandLineArgsForLauncher(
    const GURL& url,
    const std::string& extension_app_id,
    bool is_platform_app,
    const FilePath& profile_path) {
  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
  CommandLine new_cmd_line(CommandLine::NO_PROGRAM);

  // Use the same UserDataDir for new launches that we currently have set.
  FilePath user_data_dir = cmd_line.GetSwitchValuePath(switches::kUserDataDir);
  if (!user_data_dir.empty()) {
    // Make sure user_data_dir is an absolute path.
    if (file_util::AbsolutePath(&user_data_dir) &&
        file_util::PathExists(user_data_dir)) {
      new_cmd_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir);
    }
  }

#if defined(OS_CHROMEOS)
  FilePath profile = cmd_line.GetSwitchValuePath(switches::kLoginProfile);
  if (!profile.empty())
    new_cmd_line.AppendSwitchPath(switches::kLoginProfile, profile);
#else
  if (!profile_path.empty() && !extension_app_id.empty())
    new_cmd_line.AppendSwitchPath(switches::kProfileDirectory, profile_path);
#endif

  // If |extension_app_id| is present, we use the kAppId switch rather than
  // the kApp switch (the launch url will be read from the extension app
  // during launch.
  if (!extension_app_id.empty()) {
    new_cmd_line.AppendSwitchASCII(switches::kAppId, extension_app_id);
    if (is_platform_app)
      new_cmd_line.AppendSwitch(switches::kEnableExperimentalExtensionApis);
  } else {
    // Use '--app=url' instead of just 'url' to launch the browser with minimal
    // chrome.
    // Note: Do not change this flag!  Old Gears shortcuts will break if you do!
    new_cmd_line.AppendSwitchASCII(switches::kApp, url.spec());
  }
  return new_cmd_line;
}

#if !defined(OS_WIN)
// static
bool ShellIntegration::SetAsDefaultBrowserInteractive() {
  return false;
}
#endif

bool ShellIntegration::DefaultWebClientObserver::IsOwnedByWorker() {
  return false;
}

bool ShellIntegration::DefaultWebClientObserver::
    IsInteractiveSetDefaultPermitted() {
  return false;
}

///////////////////////////////////////////////////////////////////////////////
// ShellIntegration::DefaultWebClientWorker
//

ShellIntegration::DefaultWebClientWorker::DefaultWebClientWorker(
    DefaultWebClientObserver* observer)
    : observer_(observer) {
}

void ShellIntegration::DefaultWebClientWorker::StartCheckIsDefault() {
  if (observer_) {
    observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
    BrowserThread::PostTask(
        BrowserThread::FILE, FROM_HERE,
        base::Bind(
            &DefaultWebClientWorker::ExecuteCheckIsDefault, this));
  }
}

void ShellIntegration::DefaultWebClientWorker::StartSetAsDefault() {
  bool interactive_permitted = false;
  if (observer_) {
    observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
    interactive_permitted = observer_->IsInteractiveSetDefaultPermitted();
  }
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&DefaultWebClientWorker::ExecuteSetAsDefault, this,
                 interactive_permitted));
}

void ShellIntegration::DefaultWebClientWorker::ObserverDestroyed() {
  // Our associated view has gone away, so we shouldn't call back to it if
  // our worker thread returns after the view is dead.
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  observer_ = NULL;
}

///////////////////////////////////////////////////////////////////////////////
// DefaultWebClientWorker, private:

void ShellIntegration::DefaultWebClientWorker::ExecuteCheckIsDefault() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DefaultWebClientState state = CheckIsDefault();
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(
          &DefaultWebClientWorker::CompleteCheckIsDefault, this, state));
}

void ShellIntegration::DefaultWebClientWorker::CompleteCheckIsDefault(
    DefaultWebClientState state) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  UpdateUI(state);
  // The worker has finished everything it needs to do, so free the observer
  // if we own it.
  if (observer_ && observer_->IsOwnedByWorker()) {
    delete observer_;
    observer_ = NULL;
  }
}

void ShellIntegration::DefaultWebClientWorker::ExecuteSetAsDefault(
    bool interactive_permitted) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  bool result = SetAsDefault(interactive_permitted);
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&DefaultWebClientWorker::CompleteSetAsDefault, this, result));
}

void ShellIntegration::DefaultWebClientWorker::CompleteSetAsDefault(
    bool succeeded) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  // First tell the observer what the SetAsDefault call has returned.
  if (observer_)
    observer_->OnSetAsDefaultConcluded(succeeded);
  // Set as default completed, check again to make sure it stuck...
  StartCheckIsDefault();
}

void ShellIntegration::DefaultWebClientWorker::UpdateUI(
    DefaultWebClientState state) {
  if (observer_) {
    switch (state) {
      case NOT_DEFAULT_WEB_CLIENT:
        observer_->SetDefaultWebClientUIState(STATE_NOT_DEFAULT);
        break;
      case IS_DEFAULT_WEB_CLIENT:
        observer_->SetDefaultWebClientUIState(STATE_IS_DEFAULT);
        break;
      case UNKNOWN_DEFAULT_WEB_CLIENT:
        observer_->SetDefaultWebClientUIState(STATE_UNKNOWN);
        break;
      default:
        break;
    }
  }
}

///////////////////////////////////////////////////////////////////////////////
// ShellIntegration::DefaultBrowserWorker
//

ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker(
    DefaultWebClientObserver* observer)
    : DefaultWebClientWorker(observer) {
}

///////////////////////////////////////////////////////////////////////////////
// DefaultBrowserWorker, private:

ShellIntegration::DefaultWebClientState
ShellIntegration::DefaultBrowserWorker::CheckIsDefault() {
  return ShellIntegration::IsDefaultBrowser();
}

bool ShellIntegration::DefaultBrowserWorker::SetAsDefault(
    bool interactive_permitted) {
  bool result = false;
  switch (ShellIntegration::CanSetAsDefaultBrowser()) {
    case ShellIntegration::SET_DEFAULT_UNATTENDED:
      result = ShellIntegration::SetAsDefaultBrowser();
      break;
    case ShellIntegration::SET_DEFAULT_INTERACTIVE:
      if (interactive_permitted)
        result = ShellIntegration::SetAsDefaultBrowserInteractive();
      break;
    default:
      NOTREACHED();
  }

  return result;
}

///////////////////////////////////////////////////////////////////////////////
// ShellIntegration::DefaultProtocolClientWorker
//

ShellIntegration::DefaultProtocolClientWorker::DefaultProtocolClientWorker(
    DefaultWebClientObserver* observer, const std::string& protocol)
    : DefaultWebClientWorker(observer),
      protocol_(protocol) {
}

///////////////////////////////////////////////////////////////////////////////
// DefaultProtocolClientWorker, private:

ShellIntegration::DefaultWebClientState
ShellIntegration::DefaultProtocolClientWorker::CheckIsDefault() {
  return ShellIntegration::IsDefaultProtocolClient(protocol_);
}

bool ShellIntegration::DefaultProtocolClientWorker::SetAsDefault(
    bool interactive_permitted) {
  return ShellIntegration::SetAsDefaultProtocolClient(protocol_);
}
<commit_msg>Fix command line for app shortcuts<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/shell_integration.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

ShellIntegration::DefaultWebClientSetPermission
    ShellIntegration::CanSetAsDefaultProtocolClient() {
  // Allowed as long as the browser can become the operating system default
  // browser.
  return CanSetAsDefaultBrowser();
}

ShellIntegration::ShortcutInfo::ShortcutInfo()
    : is_platform_app(false),
      create_on_desktop(false),
      create_in_applications_menu(false),
      create_in_quick_launch_bar(false) {
}

ShellIntegration::ShortcutInfo::~ShortcutInfo() {}

static const struct ShellIntegration::AppModeInfo* gAppModeInfo = NULL;

// static
void ShellIntegration::SetAppModeInfo(const struct AppModeInfo* info) {
  gAppModeInfo = info;
}

// static
const struct ShellIntegration::AppModeInfo* ShellIntegration::AppModeInfo() {
  return gAppModeInfo;
}

// static
bool ShellIntegration::IsRunningInAppMode() {
  return gAppModeInfo != NULL;
}

// static
CommandLine ShellIntegration::CommandLineArgsForLauncher(
    const GURL& url,
    const std::string& extension_app_id,
    bool is_platform_app,
    const FilePath& profile_path) {
  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
  CommandLine new_cmd_line(CommandLine::NO_PROGRAM);

  // Use the same UserDataDir for new launches that we currently have set.
  FilePath user_data_dir = cmd_line.GetSwitchValuePath(switches::kUserDataDir);
  if (!user_data_dir.empty()) {
    // Make sure user_data_dir is an absolute path.
    if (file_util::AbsolutePath(&user_data_dir) &&
        file_util::PathExists(user_data_dir)) {
      new_cmd_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir);
    }
  }

#if defined(OS_CHROMEOS)
  FilePath profile = cmd_line.GetSwitchValuePath(switches::kLoginProfile);
  if (!profile.empty())
    new_cmd_line.AppendSwitchPath(switches::kLoginProfile, profile);
#else
  if (!profile_path.empty() && !extension_app_id.empty())
    new_cmd_line.AppendSwitchPath(switches::kProfileDirectory,
                                  profile_path.BaseName());
#endif

  // If |extension_app_id| is present, we use the kAppId switch rather than
  // the kApp switch (the launch url will be read from the extension app
  // during launch.
  if (!extension_app_id.empty()) {
    new_cmd_line.AppendSwitchASCII(switches::kAppId, extension_app_id);
    if (is_platform_app)
      new_cmd_line.AppendSwitch(switches::kEnableExperimentalExtensionApis);
  } else {
    // Use '--app=url' instead of just 'url' to launch the browser with minimal
    // chrome.
    // Note: Do not change this flag!  Old Gears shortcuts will break if you do!
    new_cmd_line.AppendSwitchASCII(switches::kApp, url.spec());
  }
  return new_cmd_line;
}

#if !defined(OS_WIN)
// static
bool ShellIntegration::SetAsDefaultBrowserInteractive() {
  return false;
}
#endif

bool ShellIntegration::DefaultWebClientObserver::IsOwnedByWorker() {
  return false;
}

bool ShellIntegration::DefaultWebClientObserver::
    IsInteractiveSetDefaultPermitted() {
  return false;
}

///////////////////////////////////////////////////////////////////////////////
// ShellIntegration::DefaultWebClientWorker
//

ShellIntegration::DefaultWebClientWorker::DefaultWebClientWorker(
    DefaultWebClientObserver* observer)
    : observer_(observer) {
}

void ShellIntegration::DefaultWebClientWorker::StartCheckIsDefault() {
  if (observer_) {
    observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
    BrowserThread::PostTask(
        BrowserThread::FILE, FROM_HERE,
        base::Bind(
            &DefaultWebClientWorker::ExecuteCheckIsDefault, this));
  }
}

void ShellIntegration::DefaultWebClientWorker::StartSetAsDefault() {
  bool interactive_permitted = false;
  if (observer_) {
    observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
    interactive_permitted = observer_->IsInteractiveSetDefaultPermitted();
  }
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&DefaultWebClientWorker::ExecuteSetAsDefault, this,
                 interactive_permitted));
}

void ShellIntegration::DefaultWebClientWorker::ObserverDestroyed() {
  // Our associated view has gone away, so we shouldn't call back to it if
  // our worker thread returns after the view is dead.
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  observer_ = NULL;
}

///////////////////////////////////////////////////////////////////////////////
// DefaultWebClientWorker, private:

void ShellIntegration::DefaultWebClientWorker::ExecuteCheckIsDefault() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DefaultWebClientState state = CheckIsDefault();
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(
          &DefaultWebClientWorker::CompleteCheckIsDefault, this, state));
}

void ShellIntegration::DefaultWebClientWorker::CompleteCheckIsDefault(
    DefaultWebClientState state) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  UpdateUI(state);
  // The worker has finished everything it needs to do, so free the observer
  // if we own it.
  if (observer_ && observer_->IsOwnedByWorker()) {
    delete observer_;
    observer_ = NULL;
  }
}

void ShellIntegration::DefaultWebClientWorker::ExecuteSetAsDefault(
    bool interactive_permitted) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  bool result = SetAsDefault(interactive_permitted);
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&DefaultWebClientWorker::CompleteSetAsDefault, this, result));
}

void ShellIntegration::DefaultWebClientWorker::CompleteSetAsDefault(
    bool succeeded) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  // First tell the observer what the SetAsDefault call has returned.
  if (observer_)
    observer_->OnSetAsDefaultConcluded(succeeded);
  // Set as default completed, check again to make sure it stuck...
  StartCheckIsDefault();
}

void ShellIntegration::DefaultWebClientWorker::UpdateUI(
    DefaultWebClientState state) {
  if (observer_) {
    switch (state) {
      case NOT_DEFAULT_WEB_CLIENT:
        observer_->SetDefaultWebClientUIState(STATE_NOT_DEFAULT);
        break;
      case IS_DEFAULT_WEB_CLIENT:
        observer_->SetDefaultWebClientUIState(STATE_IS_DEFAULT);
        break;
      case UNKNOWN_DEFAULT_WEB_CLIENT:
        observer_->SetDefaultWebClientUIState(STATE_UNKNOWN);
        break;
      default:
        break;
    }
  }
}

///////////////////////////////////////////////////////////////////////////////
// ShellIntegration::DefaultBrowserWorker
//

ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker(
    DefaultWebClientObserver* observer)
    : DefaultWebClientWorker(observer) {
}

///////////////////////////////////////////////////////////////////////////////
// DefaultBrowserWorker, private:

ShellIntegration::DefaultWebClientState
ShellIntegration::DefaultBrowserWorker::CheckIsDefault() {
  return ShellIntegration::IsDefaultBrowser();
}

bool ShellIntegration::DefaultBrowserWorker::SetAsDefault(
    bool interactive_permitted) {
  bool result = false;
  switch (ShellIntegration::CanSetAsDefaultBrowser()) {
    case ShellIntegration::SET_DEFAULT_UNATTENDED:
      result = ShellIntegration::SetAsDefaultBrowser();
      break;
    case ShellIntegration::SET_DEFAULT_INTERACTIVE:
      if (interactive_permitted)
        result = ShellIntegration::SetAsDefaultBrowserInteractive();
      break;
    default:
      NOTREACHED();
  }

  return result;
}

///////////////////////////////////////////////////////////////////////////////
// ShellIntegration::DefaultProtocolClientWorker
//

ShellIntegration::DefaultProtocolClientWorker::DefaultProtocolClientWorker(
    DefaultWebClientObserver* observer, const std::string& protocol)
    : DefaultWebClientWorker(observer),
      protocol_(protocol) {
}

///////////////////////////////////////////////////////////////////////////////
// DefaultProtocolClientWorker, private:

ShellIntegration::DefaultWebClientState
ShellIntegration::DefaultProtocolClientWorker::CheckIsDefault() {
  return ShellIntegration::IsDefaultProtocolClient(protocol_);
}

bool ShellIntegration::DefaultProtocolClientWorker::SetAsDefault(
    bool interactive_permitted) {
  return ShellIntegration::SetAsDefaultProtocolClient(protocol_);
}
<|endoftext|>


<commit_before>#include <osg/GL>
#include <osg/ColorMatrix>

using namespace osg;

ColorMatrix::ColorMatrix()
{
}

ColorMatrix::~ColorMatrix()
{
}

void ColorMatrix::apply(State&) const
{
//    std::cout<<"applying matrix"<<_matrix<<std::endl;

    glMatrixMode( GL_COLOR );
    glLoadMatrixf( _matrix.ptr() );
    glMatrixMode( GL_MODELVIEW );
}
<commit_msg>Added check for GL_ARB_imaging extension to osg;:ColorMatrix<commit_after>#include <osg/GL>
#include <osg/GLExtensions>
#include <osg/ColorMatrix>

using namespace osg;

ColorMatrix::ColorMatrix()
{
}

ColorMatrix::~ColorMatrix()
{
}

void ColorMatrix::apply(State&) const
{
//    std::cout<<"applying matrix"<<_matrix<<std::endl;
    static bool s_ARB_imaging = isGLExtensionSupported("GL_ARB_imaging");
	if (s_ARB_imaging)
	{
		glMatrixMode( GL_COLOR );
		glLoadMatrixf( _matrix.ptr() );
		glMatrixMode( GL_MODELVIEW );
	}
}
<|endoftext|>


<commit_before><commit_msg>Adding in a constant for hover slide opacity so that the hover is more visible in different windows variations (e.g., aero).<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/flags_ui.h"

#include <string>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources_standard.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/cros_settings.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#endif

using content::WebContents;
using content::WebUIMessageHandler;

namespace {

ChromeWebUIDataSource* CreateFlagsUIHTMLSource() {
  ChromeWebUIDataSource* source =
      new ChromeWebUIDataSource(chrome::kChromeUIFlagsHost);

  source->AddLocalizedString("flagsLongTitle", IDS_FLAGS_LONG_TITLE);
  source->AddLocalizedString("flagsTableTitle", IDS_FLAGS_TABLE_TITLE);
  source->AddLocalizedString("flagsNoExperimentsAvailable",
                             IDS_FLAGS_NO_EXPERIMENTS_AVAILABLE);
  source->AddLocalizedString("flagsWarningHeader", IDS_FLAGS_WARNING_HEADER);
  source->AddLocalizedString("flagsBlurb", IDS_FLAGS_WARNING_TEXT);
  source->AddLocalizedString("flagsNotSupported", IDS_FLAGS_NOT_AVAILABLE);
  source->AddLocalizedString("flagsRestartNotice", IDS_FLAGS_RELAUNCH_NOTICE);
  source->AddLocalizedString("flagsRestartButton", IDS_FLAGS_RELAUNCH_BUTTON);
  source->AddLocalizedString("disable", IDS_FLAGS_DISABLE);
  source->AddLocalizedString("enable", IDS_FLAGS_ENABLE);
#if defined(OS_CHROMEOS)
  // Set the strings to show which user can actually change the flags
  source->AddLocalizedString("ownerOnly", IDS_OPTIONS_ACCOUNTS_OWNER_ONLY);
  std::string owner;
  chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
  source->AddString("ownerUserId", UTF8ToUTF16(owner));
#endif

  source->set_json_path("strings.js");
  source->add_resource_path("flags.js", IDR_FLAGS_JS);

  int idr = IDR_FLAGS_HTML;
#if defined (OS_CHROMEOS)
  if (!chromeos::UserManager::Get()->current_user_is_owner())
    idr = IDR_FLAGS_HTML_WARNING;
#endif
  source->set_default_resource(idr);
  return source;
}

////////////////////////////////////////////////////////////////////////////////
//
// FlagsDOMHandler
//
////////////////////////////////////////////////////////////////////////////////

// The handler for Javascript messages for the about:flags page.
class FlagsDOMHandler : public WebUIMessageHandler {
 public:
  FlagsDOMHandler() {}
  virtual ~FlagsDOMHandler() {}

  // WebUIMessageHandler implementation.
  virtual void RegisterMessages() OVERRIDE;

  // Callback for the "requestFlagsExperiments" message.
  void HandleRequestFlagsExperiments(const ListValue* args);

  // Callback for the "enableFlagsExperiment" message.
  void HandleEnableFlagsExperimentMessage(const ListValue* args);

  // Callback for the "restartBrowser" message. Restores all tabs on restart.
  void HandleRestartBrowser(const ListValue* args);

 private:
  DISALLOW_COPY_AND_ASSIGN(FlagsDOMHandler);
};

void FlagsDOMHandler::RegisterMessages() {
  web_ui()->RegisterMessageCallback("requestFlagsExperiments",
      base::Bind(&FlagsDOMHandler::HandleRequestFlagsExperiments,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("enableFlagsExperiment",
      base::Bind(&FlagsDOMHandler::HandleEnableFlagsExperimentMessage,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("restartBrowser",
      base::Bind(&FlagsDOMHandler::HandleRestartBrowser,
                 base::Unretained(this)));
}

void FlagsDOMHandler::HandleRequestFlagsExperiments(const ListValue* args) {
  DictionaryValue results;
  results.Set("flagsExperiments",
              about_flags::GetFlagsExperimentsData(
                  g_browser_process->local_state()));
  results.SetBoolean("needsRestart",
                     about_flags::IsRestartNeededToCommitChanges());
  web_ui()->CallJavascriptFunction("returnFlagsExperiments", results);
}

void FlagsDOMHandler::HandleEnableFlagsExperimentMessage(
    const ListValue* args) {
  DCHECK_EQ(2u, args->GetSize());
  if (args->GetSize() != 2)
    return;

  std::string experiment_internal_name;
  std::string enable_str;
  if (!args->GetString(0, &experiment_internal_name) ||
      !args->GetString(1, &enable_str))
    return;

  about_flags::SetExperimentEnabled(
      g_browser_process->local_state(),
      experiment_internal_name,
      enable_str == "true");
}

void FlagsDOMHandler::HandleRestartBrowser(const ListValue* args) {
  BrowserList::AttemptRestart();
}

}  // namespace

///////////////////////////////////////////////////////////////////////////////
//
// FlagsUI
//
///////////////////////////////////////////////////////////////////////////////

FlagsUI::FlagsUI(content::WebUI* web_ui) : WebUIController(web_ui) {
  web_ui->AddMessageHandler(new FlagsDOMHandler());

  // Set up the about:flags source.
  Profile* profile = Profile::FromWebUI(web_ui);
  profile->GetChromeURLDataManager()->AddDataSource(CreateFlagsUIHTMLSource());
}

// static
RefCountedMemory* FlagsUI::GetFaviconResourceBytes() {
  return ResourceBundle::GetSharedInstance().
      LoadDataResourceBytes(IDR_FLAGS);
}

// static
void FlagsUI::RegisterPrefs(PrefService* prefs) {
  prefs->RegisterListPref(prefs::kEnabledLabsExperiments);
}
<commit_msg>chromeos: Allow chrome://flags to show up when running on a linux desktop.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/flags_ui.h"

#include <string>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources_standard.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/cros_settings.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/system/runtime_environment.h"
#endif

using content::WebContents;
using content::WebUIMessageHandler;

namespace {

ChromeWebUIDataSource* CreateFlagsUIHTMLSource() {
  ChromeWebUIDataSource* source =
      new ChromeWebUIDataSource(chrome::kChromeUIFlagsHost);

  source->AddLocalizedString("flagsLongTitle", IDS_FLAGS_LONG_TITLE);
  source->AddLocalizedString("flagsTableTitle", IDS_FLAGS_TABLE_TITLE);
  source->AddLocalizedString("flagsNoExperimentsAvailable",
                             IDS_FLAGS_NO_EXPERIMENTS_AVAILABLE);
  source->AddLocalizedString("flagsWarningHeader", IDS_FLAGS_WARNING_HEADER);
  source->AddLocalizedString("flagsBlurb", IDS_FLAGS_WARNING_TEXT);
  source->AddLocalizedString("flagsNotSupported", IDS_FLAGS_NOT_AVAILABLE);
  source->AddLocalizedString("flagsRestartNotice", IDS_FLAGS_RELAUNCH_NOTICE);
  source->AddLocalizedString("flagsRestartButton", IDS_FLAGS_RELAUNCH_BUTTON);
  source->AddLocalizedString("disable", IDS_FLAGS_DISABLE);
  source->AddLocalizedString("enable", IDS_FLAGS_ENABLE);
#if defined(OS_CHROMEOS)
  // Set the strings to show which user can actually change the flags
  source->AddLocalizedString("ownerOnly", IDS_OPTIONS_ACCOUNTS_OWNER_ONLY);
  std::string owner;
  chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
  source->AddString("ownerUserId", UTF8ToUTF16(owner));
#endif

  source->set_json_path("strings.js");
  source->add_resource_path("flags.js", IDR_FLAGS_JS);

  int idr = IDR_FLAGS_HTML;
#if defined (OS_CHROMEOS)
  if (!chromeos::UserManager::Get()->current_user_is_owner() &&
      chromeos::system::runtime_environment::IsRunningOnChromeOS())
    idr = IDR_FLAGS_HTML_WARNING;
#endif
  source->set_default_resource(idr);
  return source;
}

////////////////////////////////////////////////////////////////////////////////
//
// FlagsDOMHandler
//
////////////////////////////////////////////////////////////////////////////////

// The handler for Javascript messages for the about:flags page.
class FlagsDOMHandler : public WebUIMessageHandler {
 public:
  FlagsDOMHandler() {}
  virtual ~FlagsDOMHandler() {}

  // WebUIMessageHandler implementation.
  virtual void RegisterMessages() OVERRIDE;

  // Callback for the "requestFlagsExperiments" message.
  void HandleRequestFlagsExperiments(const ListValue* args);

  // Callback for the "enableFlagsExperiment" message.
  void HandleEnableFlagsExperimentMessage(const ListValue* args);

  // Callback for the "restartBrowser" message. Restores all tabs on restart.
  void HandleRestartBrowser(const ListValue* args);

 private:
  DISALLOW_COPY_AND_ASSIGN(FlagsDOMHandler);
};

void FlagsDOMHandler::RegisterMessages() {
  web_ui()->RegisterMessageCallback("requestFlagsExperiments",
      base::Bind(&FlagsDOMHandler::HandleRequestFlagsExperiments,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("enableFlagsExperiment",
      base::Bind(&FlagsDOMHandler::HandleEnableFlagsExperimentMessage,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("restartBrowser",
      base::Bind(&FlagsDOMHandler::HandleRestartBrowser,
                 base::Unretained(this)));
}

void FlagsDOMHandler::HandleRequestFlagsExperiments(const ListValue* args) {
  DictionaryValue results;
  results.Set("flagsExperiments",
              about_flags::GetFlagsExperimentsData(
                  g_browser_process->local_state()));
  results.SetBoolean("needsRestart",
                     about_flags::IsRestartNeededToCommitChanges());
  web_ui()->CallJavascriptFunction("returnFlagsExperiments", results);
}

void FlagsDOMHandler::HandleEnableFlagsExperimentMessage(
    const ListValue* args) {
  DCHECK_EQ(2u, args->GetSize());
  if (args->GetSize() != 2)
    return;

  std::string experiment_internal_name;
  std::string enable_str;
  if (!args->GetString(0, &experiment_internal_name) ||
      !args->GetString(1, &enable_str))
    return;

  about_flags::SetExperimentEnabled(
      g_browser_process->local_state(),
      experiment_internal_name,
      enable_str == "true");
}

void FlagsDOMHandler::HandleRestartBrowser(const ListValue* args) {
  BrowserList::AttemptRestart();
}

}  // namespace

///////////////////////////////////////////////////////////////////////////////
//
// FlagsUI
//
///////////////////////////////////////////////////////////////////////////////

FlagsUI::FlagsUI(content::WebUI* web_ui) : WebUIController(web_ui) {
  web_ui->AddMessageHandler(new FlagsDOMHandler());

  // Set up the about:flags source.
  Profile* profile = Profile::FromWebUI(web_ui);
  profile->GetChromeURLDataManager()->AddDataSource(CreateFlagsUIHTMLSource());
}

// static
RefCountedMemory* FlagsUI::GetFaviconResourceBytes() {
  return ResourceBundle::GetSharedInstance().
      LoadDataResourceBytes(IDR_FLAGS);
}

// static
void FlagsUI::RegisterPrefs(PrefService* prefs) {
  prefs->RegisterListPref(prefs::kEnabledLabsExperiments);
}
<|endoftext|>