text:
#include <graphene/app/api.hpp>
#include <graphene/app/api_access.hpp>
#include <graphene/app/application.hpp>
#include <graphene/app/plugin.hpp>

#include <graphene/chain/db_with.hpp>
#include <graphene/chain/genesis_state.hpp>
#include <graphene/protocol/fee_schedule.hpp>
#include <graphene/protocol/types.hpp>

#include <graphene/egenesis/egenesis.hpp>

#include <graphene/net/core_messages.hpp>
#include <graphene/net/exceptions.hpp>

#include <graphene/utilities/key_conversion.hpp>
#include <graphene/chain/worker_evaluator.hpp>

#include <fc/asio.hpp>
#include <fc/io/fstream.hpp>
#include <fc/rpc/api_connection.hpp>
#include <fc/rpc/websocket_api.hpp>
#include <fc/crypto/base64.hpp>

#include <boost/filesystem/path.hpp>
#include <boost/signals2.hpp>
#include <boost/range/algorithm/reverse.hpp>
#include <boost/algorithm/string.hpp>

#include <iostream>

#include <fc/log/file_appender.hpp>
#include <fc/log/logger.hpp>
#include <fc/log/logger_config.hpp>

#include <boost/range/adaptor/reversed.hpp>

namespace graphene { namespace app {
using net::item_hash_t;
using net::item_id;
using net::message;
using net::block_message;
using net::trx_message;

using chain::block_header;
using chain::signed_block_header;
using chain::signed_block;
using chain::block_id_type;

using std::vector;

namespace bpo = boost::program_options;

namespace detail {

   graphene::chain::genesis_state_type create_example_genesis() {
      auto nathan_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan")));
      dlog("Allocating all stake to ${key}", ("key", utilities::key_to_wif(nathan_key)));
      graphene::chain::genesis_state_type initial_state;
      initial_state.initial_parameters.get_mutable_fees() = fee_schedule::get_default();
      initial_state.initial_active_witnesses = GRAPHENE_DEFAULT_MIN_WITNESS_COUNT;
      initial_state.initial_timestamp = time_point_sec(time_point::now().sec_since_epoch() /
            initial_state.initial_parameters.block_interval *
            initial_state.initial_parameters.block_interval);
      for( uint64_t i = 0; i < initial_state.initial_active_witnesses; ++i )
      {
         auto name = "init"+fc::to_string(i);
         initial_state.initial_accounts.emplace_back(name,
                                                     nathan_key.get_public_key(),
                                                     nathan_key.get_public_key(),
                                                     true);
         initial_state.initial_committee_candidates.push_back({name});
         initial_state.initial_witness_candidates.push_back({name, nathan_key.get_public_key()});
      }

      initial_state.initial_accounts.emplace_back("nathan", nathan_key.get_public_key());
      initial_state.initial_balances.push_back({nathan_key.get_public_key(),
                                                GRAPHENE_SYMBOL,
                                                GRAPHENE_MAX_SHARE_SUPPLY});
      initial_state.initial_chain_id = fc::sha256::hash( "BOGUS" );

      return initial_state;
   }

}

}}

#include "application_impl.hxx"

namespace graphene { namespace app { namespace detail {

void application_impl::reset_p2p_node(const fc::path& data_dir)
{ try {
   _p2p_network = std::make_shared<net::node>("BitShares Reference Implementation");

   _p2p_network->load_configuration(data_dir / "p2p");
   _p2p_network->set_node_delegate(this);

   if( _options->count("seed-node") )
   {
      auto seeds = _options->at("seed-node").as<vector<string>>();
      _p2p_network->add_seed_nodes(seeds);
   }

   if( _options->count("seed-nodes") )
   {
      auto seeds_str = _options->at("seed-nodes").as<string>();
      auto seeds = fc::json::from_string(seeds_str).as<vector<string>>(2);
      _p2p_network->add_seed_nodes(seeds);
   }
   else
   {
      // https://bitsharestalk.org/index.php/topic,23715.0.html
      vector<string> seeds = {
         #include "../egenesis/seed-nodes.txt"
      };
      _p2p_network->add_seed_nodes(seeds);
   }

   if( _options->count("p2p-endpoint") )
      _p2p_network->listen_on_endpoint(fc::ip::endpoint::from_string(_options->at("p2p-endpoint").as<string>()), true);
   else
      _p2p_network->listen_on_port(0, false);
   _p2p_network->listen_to_p2p_network();
   ilog("Configured p2p node to listen on ${ip}", ("ip", _p2p_network->get_actual_listening_endpoint()));

   _p2p_network->connect_to_p2p_network();
   _p2p_network->sync_from(net::item_id(net::core_message_type_enum::block_message_type,
                                        _chain_db->head_block_id()),
                           std::vector<uint32_t>());
} FC_CAPTURE_AND_RETHROW() }

void application_impl::new_connection( const fc::http::websocket_connection_ptr& c )
{
   auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(c, GRAPHENE_NET_MAX_NESTED_OBJECTS);
   auto login = std::make_shared<graphene::app::login_api>( std::ref(*_self) );
   login->enable_api("database_api");

   wsc->register_api(login->database());
   wsc->register_api(fc::api<graphene::app::login_api>(login));
   c->set_session_data( wsc );

   std::string username = "*";
   std::string password = "*";

    // Try to extract login information from "Authorization" header if present
   std::string auth = c->get_request_header("Authorization");
   if( boost::starts_with(auth, "Basic ") ) {

      FC_ASSERT( auth.size() > 6 );
      auto user_pass = fc::base64_decode(auth.substr(6));

      std::vector<std::string> parts;
      boost::split( parts, user_pass, boost::is_any_of(":") );

      FC_ASSERT(parts.size() == 2);

      username = parts[0];
      password = parts[1];
   }

   login->login(username, password);
}

void application_impl::reset_websocket_server()
{ try {
   if( !_options->count("rpc-endpoint") )
      return;

   string proxy_forward_header;
   if( _options->count("proxy-forwarded-for-header") )
      proxy_forward_header = _options->at("proxy-forwarded-for-header").as<string>();

   _websocket_server = std::make_shared<fc::http::websocket_server>( proxy_forward_header );
   _websocket_server->on_connection( std::bind(&application_impl::new_connection, this, std::placeholders::_1) );

   ilog("Configured websocket rpc to listen on ${ip}", ("ip",_options->at("rpc-endpoint").as<string>()));
   _websocket_server->listen( fc::ip::endpoint::from_string(_options->at("rpc-endpoint").as<string>()) );
   _websocket_server->start_accept();
} FC_CAPTURE_AND_RETHROW() }

void application_impl::reset_websocket_tls_server()
{ try {
   if( !_options->count("rpc-tls-endpoint") )
      return;
   if( !_options->count("server-pem") )
   {
      wlog( "Please specify a server-pem to use rpc-tls-endpoint" );
      return;
   }

   string proxy_forward_header;
   if( _options->count("proxy-forwarded-for-header") )
      proxy_forward_header = _options->at("proxy-forwarded-for-header").as<string>();

   string password = _options->count("server-pem-password") ? _options->at("server-pem-password").as<string>() : "";
   _websocket_tls_server = std::make_shared<fc::http::websocket_tls_server>(
                                 _options->at("server-pem").as<string>(), password, proxy_forward_header );
   _websocket_tls_server->on_connection( std::bind(&application_impl::new_connection, this, std::placeholders::_1) );

   ilog("Configured websocket TLS rpc to listen on ${ip}", ("ip",_options->at("rpc-tls-endpoint").as<string>()));
   _websocket_tls_server->listen( fc::ip::endpoint::from_string(_options->at("rpc-tls-endpoint").as<string>()) );
   _websocket_tls_server->start_accept();
} FC_CAPTURE_AND_RETHROW() }

void application_impl::set_dbg_init_key( graphene::chain::genesis_state_type& genesis, const std::string& init_key )
{
   flat_set< std::string > initial_witness_names;
   public_key_type init_pubkey( init_key );
   for( uint64_t i=0; i<genesis.initial_active_witnesses; i++ )
      genesis.initial_witness_candidates[i].block_signing_key = init_pubkey;
}

void application_impl::set_api_limit() {
   if (_options->count("api-limit-get-account-history-operations")) {
      _app_options.api_limit_get_account_history_operations = _options->at("api-limit-get-account-history-operations").as<uint64_t>();
   }
   if(_options->count("api-limit-get-account-history")){
      _app_options.api_limit_get_account_history = _options->at("api-limit-get-account-history").as<uint64_t>();
   }
   if(_options->count("api-limit-get-grouped-limit-orders")){
      _app_options.api_limit_get_grouped_limit_orders = _options->at("api-limit-get-grouped-limit-orders").as<uint64_t>();
   }
   if(_options->count("api-limit-get-relative-account-history")){
       _app_options.api_limit_get_relative_account_history = _options->at("api-limit-get-relative-account-history").as<uint64_t>();
   }
   if(_options->count("api-limit-get-account-history-by-operations")){
       _app_options.api_limit_get_account_history_by_operations = _options->at("api-limit-get-account-history-by-operations").as<uint64_t>();
   }
   if(_options->count("api-limit-get-asset-holders")){
       _app_options.api_limit_get_asset_holders = _options->at("api-limit-get-asset-holders").as<uint64_t>();
   }
   if(_options->count("api-limit-get-key-references")){
       _app_options.api_limit_get_key_references = _options->at("api-limit-get-key-references").as<uint64_t>();
   }
   if(_options->count("api-limit-get-htlc-by")) {
      _app_options.api_limit_get_htlc_by = _options->at("api-limit-get-htlc-by").as<uint64_t>();
   }
   if(_options->count("api-limit-get-full-accounts")) {
      _app_options.api_limit_get_full_accounts = _options->at("api-limit-get-full-accounts").as<uint64_t>();
   }
   if(_options->count("api-limit-get-full-accounts-lists")) {
      _app_options.api_limit_get_full_accounts_lists = _options->at("api-limit-get-full-accounts-lists").as<uint64_t>();
   }
   if(_options->count("api-limit-get-top-voters")) {
      _app_options.api_limit_get_top_voters = _options->at("api-limit-get-top-voters").as<uint64_t>();
   }
   if(_options->count("api-limit-get-call-orders")) {
      _app_options.api_limit_get_call_orders = _options->at("api-limit-get-call-orders").as<uint64_t>();
   }
   if(_options->count("api-limit-get-settle-orders")) {
      _app_options.api_limit_get_settle_orders = _options->at("api-limit-get-settle-orders").as<uint64_t>();
   }
   if(_options->count("api-limit-get-assets")) {
      _app_options.api_limit_get_assets = _options->at("api-limit-get-assets").as<uint64_t>();
   }
   if(_options->count("api-limit-get-limit-orders")){
      _app_options.api_limit_get_limit_orders = _options->at("api-limit-get-limit-orders").as<uint64_t>();
   }
   if(_options->count("api-limit-get-limit-orders-by-account")){
      _app_options.api_limit_get_limit_orders_by_account = _options->at("api-limit-get-limit-orders-by-account").as<uint64_t>();
   }
   if(_options->count("api-limit-get-order-book")){
      _app_options.api_limit_get_order_book = _options->at("api-limit-get-order-book").as<uint64_t>();
   }
   if(_options->count("api-limit-list-htlcs")){
      _app_options.api_limit_list_htlcs = _options->at("api-limit-list-htlcs").as<uint64_t>();
   }
   if(_options->count("api-limit-lookup-accounts")) {
      _app_options.api_limit_lookup_accounts = _options->at("api-limit-lookup-accounts").as<uint64_t>();
   }
   if(_options->count("api-limit-lookup-witness-accounts")) {
      _app_options.api_limit_lookup_witness_accounts = _options->at("api-limit-lookup-witness-accounts").as<uint64_t>();
   }
   if(_options->count("api-limit-lookup-committee-member-accounts")) {
      _app_options.api_limit_lookup_committee_member_accounts = _options->at("api-limit-lookup-committee-member-accounts").as<uint64_t>();
   }
   if(_options->count("api-limit-lookup-vote-ids")) {
      _app_options.api_limit_lookup_vote_ids = _options->at("api-limit-lookup-vote-ids").as<uint64_t>();
   }
   if(_options->count("api-limit-get-account-limit-orders")) {
      _app_options.api_limit_get_account_limit_orders = _options->at("api-limit-get-account-limit-orders").as<uint64_t>();
   }
   if(_options->count("api-limit-get-collateral-bids")) {
      _app_options.api_limit_get_collateral_bids = _options->at("api-limit-get-collateral-bids").as<uint64_t>();
   }
   if(_options->count("api-limit-get-top-markets")) {
      _app_options.api_limit_get_top_markets = _options->at("api-limit-get-top-markets").as<uint64_t>();
   }
   if(_options->count("api-limit-get-trade-history")) {
      _app_options.api_limit_get_trade_history = _options->at("api-limit-get-trade-history").as<uint64_t>();
   }
   if(_options->count("api-limit-get-trade-history-by-sequence")) {
      _app_options.api_limit_get_trade_history_by_sequence = _options->at("api-limit-get-trade-history-by-sequence").as<uint64_t>();
   }
   if(_options->count("api-limit-get-withdraw-permissions-by-giver")) {
      _app_options.api_limit_get_withdraw_permissions_by_giver = _options->at("api-limit-get-withdraw-permissions-by-giver").as<uint64_t>();
   }
   if(_options->count("api-limit-get-withdraw-permissions-by-recipient")) {
      _app_options.api_limit_get_withdraw_permissions_by_recipient = _options->at("api-limit-get-withdraw-permissions-by-recipient").as<uint64_t>();
   }
   if(_options->count("api-limit-get-liquidity-pools")) {
      _app_options.api_limit_get_liquidity_pools = _options->at("api-limit-get-liquidity-pools").as<uint64_t>();
   }
   if(_options->count("api-limit-get-tickets")) {
      _app_options.api_limit_get_tickets = _options->at("api-limit-get-tickets").as<uint64_t>();
   }
}

void application_impl::startup()
{ try {
   fc::create_directories(_data_dir / "blockchain");

   auto initial_state = [this] {
      ilog("Initializing database...");
      if( _options->count("genesis-json") )
      {
         std::string genesis_str;
         fc::read_file_contents( _options->at("genesis-json").as<boost::filesystem::path>(), genesis_str );
         graphene::chain::genesis_state_type genesis = fc::json::from_string( genesis_str ).as<graphene::chain::genesis_state_type>( 20 );
         bool modified_genesis = false;
         if( _options->count("genesis-timestamp") )
         {
            genesis.initial_timestamp = fc::time_point_sec( fc::time_point::now() )
                                      + genesis.initial_parameters.block_interval
                                      + _options->at("genesis-timestamp").as<uint32_t>();
            genesis.initial_timestamp -= ( genesis.initial_timestamp.sec_since_epoch()
                                           % genesis.initial_parameters.block_interval );
            modified_genesis = true;

            ilog(
               "Used genesis timestamp:  ${timestamp} (PLEASE RECORD THIS)",
               ("timestamp", genesis.initial_timestamp.to_iso_string())
            );
         }
         if( _options->count("dbg-init-key") )
         {
            std::string init_key = _options->at( "dbg-init-key" ).as<string>();
            FC_ASSERT( genesis.initial_witness_candidates.size() >= genesis.initial_active_witnesses );
            set_dbg_init_key( genesis, init_key );
            modified_genesis = true;
            ilog("Set init witness key to ${init_key}", ("init_key", init_key));
         }
         if( modified_genesis )
         {
            wlog("WARNING:  GENESIS WAS MODIFIED, YOUR CHAIN ID MAY BE DIFFERENT");
            genesis_str += "BOGUS";
            genesis.initial_chain_id = fc::sha256::hash( genesis_str );
         }
         else
            genesis.initial_chain_id = fc::sha256::hash( genesis_str );
         return genesis;
      }
      else
      {
         std::string egenesis_json;
         graphene::egenesis::compute_egenesis_json( egenesis_json );
         FC_ASSERT( egenesis_json != "" );
         FC_ASSERT( graphene::egenesis::get_egenesis_json_hash() == fc::sha256::hash( egenesis_json ) );
         auto genesis = fc::json::from_string( egenesis_json ).as<graphene::chain::genesis_state_type>( 20 );
         genesis.initial_chain_id = fc::sha256::hash( egenesis_json );
         return genesis;
      }
   };

   if( _options->count("resync-blockchain") )
      _chain_db->wipe(_data_dir / "blockchain", true);

   flat_map<uint32_t,block_id_type> loaded_checkpoints;
   if( _options->count("checkpoint") )
   {
      auto cps = _options->at("checkpoint").as<vector<string>>();
      loaded_checkpoints.reserve( cps.size() );
      for( auto cp : cps )
      {
         auto item = fc::json::from_string(cp).as<std::pair<uint32_t,block_id_type> >( 2 );
         loaded_checkpoints[item.first] = item.second;
      }
   }
   _chain_db->add_checkpoints( loaded_checkpoints );

   if( _options->count("enable-standby-votes-tracking") )
   {
      _chain_db->enable_standby_votes_tracking( _options->at("enable-standby-votes-tracking").as<bool>() );
   }

   if( _options->count("replay-blockchain") || _options->count("revalidate-blockchain") )
      _chain_db->wipe( _data_dir / "blockchain", false );

   try
   {
      // these flags are used in open() only, i. e. during replay
      uint32_t skip;
      if( _options->count("revalidate-blockchain") ) // see also handle_block()
      {
         if( !loaded_checkpoints.empty() )
            wlog( "Warning - revalidate will not validate before last checkpoint" );
         if( _options->count("force-validate") )
            skip = graphene::chain::database::skip_nothing;
         else
            skip = graphene::chain::database::skip_transaction_signatures;
      }
      else // no revalidate, skip most checks
         skip = graphene::chain::database::skip_witness_signature |
                graphene::chain::database::skip_block_size_check |
                graphene::chain::database::skip_merkle_check |
                graphene::chain::database::skip_transaction_signatures |
                graphene::chain::database::skip_transaction_dupe_check |
                graphene::chain::database::skip_tapos_check |
                graphene::chain::database::skip_witness_schedule_check;

      graphene::chain::detail::with_skip_flags( *_chain_db, skip, [this,&initial_state] () {
         _chain_db->open( _data_dir / "blockchain", initial_state, GRAPHENE_CURRENT_DB_VERSION );
      });
   }
   catch( const fc::exception& e )
   {
      elog( "Caught exception ${e} in open(), you might want to force a replay", ("e", e.to_detail_string()) );
      throw;
   }

   if( _options->count("force-validate") )
   {
      ilog( "All transaction signatures will be validated" );
      _force_validate = true;
   }

   if ( _options->count("enable-subscribe-to-all") )
      _app_options.enable_subscribe_to_all = _options->at( "enable-subscribe-to-all" ).as<bool>();

   set_api_limit();

   if( _active_plugins.find( "market_history" ) != _active_plugins.end() )
      _app_options.has_market_history_plugin = true;

   if( _active_plugins.find( "api_helper_indexes" ) != _active_plugins.end() )
      _app_options.has_api_helper_indexes_plugin = true;

   if( _options->count("api-access") ) {

      fc::path api_access_file = _options->at("api-access").as<boost::filesystem::path>();

      FC_ASSERT( fc::exists(api_access_file),
            "Failed to load file from ${path}", ("path", api_access_file) );

      _apiaccess = fc::json::from_file( api_access_file ).as<api_access>( 20 );
      ilog( "Using api access file from ${path}",
            ("path", api_access_file) );
   }
   else
   {
      // TODO:  Remove this generous default access policy
      // when the UI logs in properly
      _apiaccess = api_access();
      api_access_info wild_access;
      wild_access.password_hash_b64 = "*";
      wild_access.password_salt_b64 = "*";
      wild_access.allowed_apis.push_back( "database_api" );
      wild_access.allowed_apis.push_back( "network_broadcast_api" );
      wild_access.allowed_apis.push_back( "history_api" );
      wild_access.allowed_apis.push_back( "orders_api" );
      wild_access.allowed_apis.push_back( "custom_operations_api" );
      _apiaccess.permission_map["*"] = wild_access;
   }

   reset_p2p_node(_data_dir);
   reset_websocket_server();
   reset_websocket_tls_server();
} FC_LOG_AND_RETHROW() }

optional< api_access_info > application_impl::get_api_access_info(const string& username)const
{
   optional< api_access_info > result;
   auto it = _apiaccess.permission_map.find(username);
   if( it == _apiaccess.permission_map.end() )
   {
      it = _apiaccess.permission_map.find("*");
      if( it == _apiaccess.permission_map.end() )
         return result;
   }
   return it->second;
}

void application_impl::set_api_access_info(const string& username, api_access_info&& permissions)
{
   _apiaccess.permission_map.insert(std::make_pair(username, std::move(permissions)));
}

/**
 * If delegate has the item, the network has no need to fetch it.
 */
bool application_impl::has_item(const net::item_id& id)
{
   try
   {
      if( id.item_type == graphene::net::block_message_type )
         return _chain_db->is_known_block(id.item_hash);
      else
         return _chain_db->is_known_transaction(id.item_hash);
   }
   FC_CAPTURE_AND_RETHROW( (id) )
}

/**
 * @brief allows the application to validate an item prior to broadcasting to peers.
 *
 * @param sync_mode true if the message was fetched through the sync process, false during normal operation
 * @returns true if this message caused the blockchain to switch forks, false if it did not
 *
 * @throws exception if error validating the item, otherwise the item is safe to broadcast on.
 */
bool application_impl::handle_block(const graphene::net::block_message& blk_msg, bool sync_mode,
                          std::vector<fc::uint160_t>& contained_transaction_message_ids)
{ try {

   auto latency = fc::time_point::now() - blk_msg.block.timestamp;
   if (!sync_mode || blk_msg.block.block_num() % 10000 == 0)
   {
      const auto& witness = blk_msg.block.witness(*_chain_db);
      const auto& witness_account = witness.witness_account(*_chain_db);
      auto last_irr = _chain_db->get_dynamic_global_properties().last_irreversible_block_num;
      ilog("Got block: #${n} ${bid} time: ${t} transaction(s): ${x} latency: ${l} ms from: ${w}  irreversible: ${i} (-${d})",
           ("t",blk_msg.block.timestamp)
           ("n", blk_msg.block.block_num())
           ("bid", blk_msg.block.id())
           ("x", blk_msg.block.transactions.size())
           ("l", (latency.count()/1000))
           ("w",witness_account.name)
           ("i",last_irr)("d",blk_msg.block.block_num()-last_irr) );
   }
   GRAPHENE_ASSERT( latency.count()/1000 > -5000,
                    graphene::net::block_timestamp_in_future_exception,
                    "Rejecting block with timestamp in the future", );

   try {
      const uint32_t skip = (_is_block_producer | _force_validate) ?
                               database::skip_nothing : database::skip_transaction_signatures;
      bool result = valve.do_serial( [this,&blk_msg,skip] () {
         _chain_db->precompute_parallel( blk_msg.block, skip ).wait();
      }, [this,&blk_msg,skip] () {
         // TODO: in the case where this block is valid but on a fork that's too old for us to switch to,
         // you can help the network code out by throwing a block_older_than_undo_history exception.
         // when the net code sees that, it will stop trying to push blocks from that chain, but
         // leave that peer connected so that they can get sync blocks from us
         return _chain_db->push_block( blk_msg.block, skip );
      });

      // the block was accepted, so we now know all of the transactions contained in the block
      if (!sync_mode)
      {
         // if we're not in sync mode, there's a chance we will be seeing some transactions
         // included in blocks before we see the free-floating transaction itself.  If that
         // happens, there's no reason to fetch the transactions, so  construct a list of the
         // transaction message ids we no longer need.
         // during sync, it is unlikely that we'll see any old
         contained_transaction_message_ids.reserve( contained_transaction_message_ids.size()
                                                    + blk_msg.block.transactions.size() );
         for (const processed_transaction& transaction : blk_msg.block.transactions)
         {
            graphene::net::trx_message transaction_message(transaction);
            contained_transaction_message_ids.emplace_back(graphene::net::message(transaction_message).id());
         }
      }

      return result;
   } catch ( const graphene::chain::unlinkable_block_exception& e ) {
      // translate to a graphene::net exception
      elog("Error when pushing block:\n${e}", ("e", e.to_detail_string()));
      FC_THROW_EXCEPTION( graphene::net::unlinkable_block_exception,
                          "Error when pushing block:\n${e}",
                          ("e", e.to_detail_string()) );
   } catch( const fc::exception& e ) {
      elog("Error when pushing block:\n${e}", ("e", e.to_detail_string()));
      throw;
   }

   if( !_is_finished_syncing && !sync_mode )
   {
      _is_finished_syncing = true;
      _self->syncing_finished();
   }
} FC_CAPTURE_AND_RETHROW( (blk_msg)(sync_mode) ) return false; }

void application_impl::handle_transaction(const graphene::net::trx_message& transaction_message)
{ try {
   static fc::time_point last_call;
   static int trx_count = 0;
   ++trx_count;
   auto now = fc::time_point::now();
   if( now - last_call > fc::seconds(1) ) {
      ilog("Got ${c} transactions from network", ("c",trx_count) );
      last_call = now;
      trx_count = 0;
   }

   _chain_db->precompute_parallel( transaction_message.trx ).wait();
   _chain_db->push_transaction( transaction_message.trx );
} FC_CAPTURE_AND_RETHROW( (transaction_message) ) }

void application_impl::handle_message(const message& message_to_process)
{
   // not a transaction, not a block
   FC_THROW( "Invalid Message Type" );
}

bool application_impl::is_included_block(const block_id_type& block_id)
{
  uint32_t block_num = block_header::num_from_id(block_id);
  block_id_type block_id_in_preferred_chain = _chain_db->get_block_id_for_num(block_num);
  return block_id == block_id_in_preferred_chain;
}

/**
 * Assuming all data elements are ordered in some way, this method should
 * return up to limit ids that occur *after* the last ID in synopsis that
 * we recognize.
 *
 * On return, remaining_item_count will be set to the number of items
 * in our blockchain after the last item returned in the result,
 * or 0 if the result contains the last item in the blockchain
 */
std::vector<item_hash_t> application_impl::get_block_ids(const std::vector<item_hash_t>& blockchain_synopsis,
                                               uint32_t& remaining_item_count,
                                               uint32_t limit)
{ try {
   vector<block_id_type> result;
   remaining_item_count = 0;
   if( _chain_db->head_block_num() == 0 )
      return result;

   result.reserve(limit);
   block_id_type last_known_block_id;

   if (blockchain_synopsis.empty() ||
       (blockchain_synopsis.size() == 1 && blockchain_synopsis[0] == block_id_type()))
   {
     // peer has sent us an empty synopsis meaning they have no blocks.
     // A bug in old versions would cause them to send a synopsis containing block 000000000
     // when they had an empty blockchain, so pretend they sent the right thing here.

     // do nothing, leave last_known_block_id set to zero
   }
   else
   {
     bool found_a_block_in_synopsis = false;
     for (const item_hash_t& block_id_in_synopsis : boost::adaptors::reverse(blockchain_synopsis))
       if (block_id_in_synopsis == block_id_type() ||
           (_chain_db->is_known_block(block_id_in_synopsis) && is_included_block(block_id_in_synopsis)))
       {
         last_known_block_id = block_id_in_synopsis;
         found_a_block_in_synopsis = true;
         break;
       }
     if (!found_a_block_in_synopsis)
       FC_THROW_EXCEPTION( graphene::net::peer_is_on_an_unreachable_fork,
                           "Unable to provide a list of blocks starting at any of the blocks in peer's synopsis" );
   }
   for( uint32_t num = block_header::num_from_id(last_known_block_id);
        num <= _chain_db->head_block_num() && result.size() < limit;
        ++num )
      if( num > 0 )
         result.push_back(_chain_db->get_block_id_for_num(num));

   if( !result.empty() && block_header::num_from_id(result.back()) < _chain_db->head_block_num() )
      remaining_item_count = _chain_db->head_block_num() - block_header::num_from_id(result.back());

   return result;
} FC_CAPTURE_AND_RETHROW( (blockchain_synopsis)(remaining_item_count)(limit) ) }

/**
 * Given the hash of the requested data, fetch the body.
 */
message application_impl::get_item(const item_id& id)
{ try {
  // ilog("Request for item ${id}", ("id", id));
   if( id.item_type == graphene::net::block_message_type )
   {
      auto opt_block = _chain_db->fetch_block_by_id(id.item_hash);
      if( !opt_block )
         elog("Couldn't find block ${id} -- corresponding ID in our chain is ${id2}",
              ("id", id.item_hash)("id2", _chain_db->get_block_id_for_num(block_header::num_from_id(id.item_hash))));
      FC_ASSERT( opt_block.valid() );
      // ilog("Serving up block #${num}", ("num", opt_block->block_num()));
      return block_message(std::move(*opt_block));
   }
   return trx_message( _chain_db->get_recent_transaction( id.item_hash ) );
} FC_CAPTURE_AND_RETHROW( (id) ) }

chain_id_type application_impl::get_chain_id() const
{
   return _chain_db->get_chain_id();
}

/**
 * Returns a synopsis of the blockchain used for syncing.  This consists of a list of
 * block hashes at intervals exponentially increasing towards the genesis block.
 * When syncing to a peer, the peer uses this data to determine if we're on the same
 * fork as they are, and if not, what blocks they need to send us to get us on their
 * fork.
 *
 * In the over-simplified case, this is a straighforward synopsis of our current
 * preferred blockchain; when we first connect up to a peer, this is what we will be sending.
 * It looks like this:
 *   If the blockchain is empty, it will return the empty list.
 *   If the blockchain has one block, it will return a list containing just that block.
 *   If it contains more than one block:
 *     the first element in the list will be the hash of the highest numbered block that
 *         we cannot undo
 *     the second element will be the hash of an item at the half way point in the undoable
 *         segment of the blockchain
 *     the third will be ~3/4 of the way through the undoable segment of the block chain
 *     the fourth will be at ~7/8...
 *       &c.
 *     the last item in the list will be the hash of the most recent block on our preferred chain
 * so if the blockchain had 26 blocks labeled a - z, the synopsis would be:
 *    a n u x z
 * the idea being that by sending a small (<30) number of block ids, we can summarize a huge
 * blockchain.  The block ids are more dense near the end of the chain where because we are
 * more likely to be almost in sync when we first connect, and forks are likely to be short.
 * If the peer we're syncing with in our example is on a fork that started at block 'v',
 * then they will reply to our synopsis with a list of all blocks starting from block 'u',
 * the last block they know that we had in common.
 *
 * In the real code, there are several complications.
 *
 * First, as an optimization, we don't usually send a synopsis of the entire blockchain, we
 * send a synopsis of only the segment of the blockchain that we have undo data for.  If their
 * fork doesn't build off of something in our undo history, we would be unable to switch, so there's
 * no reason to fetch the blocks.
 *
 * Second, when a peer replies to our initial synopsis and gives us a list of the blocks they think
 * we are missing, they only send a chunk of a few thousand blocks at once.  After we get those
 * block ids, we need to request more blocks by sending another synopsis (we can't just say "send me
 * the next 2000 ids" because they may have switched forks themselves and they don't track what
 * they've sent us).  For faster performance, we want to get a fairly long list of block ids first,
 * then start downloading the blocks.
 * The peer doesn't handle these follow-up block id requests any different from the initial request;
 * it treats the synopsis we send as our blockchain and bases its response entirely off that.  So to
 * get the response we want (the next chunk of block ids following the last one they sent us, or,
 * failing that, the shortest fork off of the last list of block ids they sent), we need to construct
 * a synopsis as if our blockchain was made up of:
 *    1. the blocks in our block chain up to the fork point (if there is a fork) or the head block (if no fork)
 *    2. the blocks we've already pushed from their fork (if there's a fork)
 *    3. the block ids they've previously sent us
 * Segment 3 is handled in the p2p code, it just tells us the number of blocks it has (in
 * number_of_blocks_after_reference_point) so we can leave space in the synopsis for them.
 * We're responsible for constructing the synopsis of Segments 1 and 2 from our active blockchain and
 * fork database.  The reference_point parameter is the last block from that peer that has been
 * successfully pushed to the blockchain, so that tells us whether the peer is on a fork or on
 * the main chain.
 */
std::vector<item_hash_t> application_impl::get_blockchain_synopsis(const item_hash_t& reference_point,
                                                         uint32_t number_of_blocks_after_reference_point)
{ try {
    std::vector<item_hash_t> synopsis;
    synopsis.reserve(30);
    uint32_t high_block_num;
    uint32_t non_fork_high_block_num;
    uint32_t low_block_num = _chain_db->last_non_undoable_block_num();
    std::vector<block_id_type> fork_history;

    if (reference_point != item_hash_t())
    {
      // the node is asking for a summary of the block chain up to a specified
      // block, which may or may not be on a fork
      // for now, assume it's not on a fork
      if (is_included_block(reference_point))
      {
        // reference_point is a block we know about and is on the main chain
        uint32_t reference_point_block_num = block_header::num_from_id(reference_point);
        assert(reference_point_block_num > 0);
        high_block_num = reference_point_block_num;
        non_fork_high_block_num = high_block_num;

        if (reference_point_block_num < low_block_num)
        {
          // we're on the same fork (at least as far as reference_point) but we've passed
          // reference point and could no longer undo that far if we diverged after that
          // block.  This should probably only happen due to a race condition where
          // the network thread calls this function, and then immediately pushes a bunch of blocks,
          // then the main thread finally processes this function.
          // with the current framework, there's not much we can do to tell the network
          // thread what our current head block is, so we'll just pretend that
          // our head is actually the reference point.
          // this *may* enable us to fetch blocks that we're unable to push, but that should
          // be a rare case (and correctly handled)
          low_block_num = reference_point_block_num;
        }
      }
      else
      {
        // block is a block we know about, but it is on a fork
        try
        {
          fork_history = _chain_db->get_block_ids_on_fork(reference_point);
          // returns a vector where the last element is the common ancestor with the preferred chain,
          // and the first element is the reference point you passed in
          assert(fork_history.size() >= 2);

          if( fork_history.front() != reference_point )
          {
             edump( (fork_history)(reference_point) );
             assert(fork_history.front() == reference_point);
          }
          block_id_type last_non_fork_block = fork_history.back();
          fork_history.pop_back();  // remove the common ancestor
          boost::reverse(fork_history);

          if (last_non_fork_block == block_id_type()) // if the fork goes all the way back to genesis (does graphene's fork db allow this?)
            non_fork_high_block_num = 0;
          else
            non_fork_high_block_num = block_header::num_from_id(last_non_fork_block);

          high_block_num = non_fork_high_block_num + fork_history.size();
          assert(high_block_num == block_header::num_from_id(fork_history.back()));
        }
        catch (const fc::exception& e)
        {
          // unable to get fork history for some reason.  maybe not linked?
          // we can't return a synopsis of its chain
          elog( "Unable to construct a blockchain synopsis for reference hash ${hash}: ${exception}",
                ("hash", reference_point)("exception", e) );
          throw;
        }
        if (non_fork_high_block_num < low_block_num)
        {
          wlog("Unable to generate a usable synopsis because the peer we're generating it for forked too long ago "
               "(our chains diverge after block #${non_fork_high_block_num} but only undoable to block #${low_block_num})",
               ("low_block_num", low_block_num)
               ("non_fork_high_block_num", non_fork_high_block_num));
          FC_THROW_EXCEPTION(graphene::net::block_older_than_undo_history, "Peer is are on a fork I'm unable to switch to");
        }
      }
    }
    else
    {
      // no reference point specified, summarize the whole block chain
      high_block_num = _chain_db->head_block_num();
      non_fork_high_block_num = high_block_num;
      if (high_block_num == 0)
        return synopsis; // we have no blocks
    }

    if( low_block_num == 0)
       low_block_num = 1;

    // at this point:
    // low_block_num is the block before the first block we can undo,
    // non_fork_high_block_num is the block before the fork (if the peer is on a fork, or otherwise it is the same as high_block_num)
    // high_block_num is the block number of the reference block, or the end of the chain if no reference provided

    // true_high_block_num is the ending block number after the network code appends any item ids it
    // knows about that we don't
    uint32_t true_high_block_num = high_block_num + number_of_blocks_after_reference_point;
    do
    {
      // for each block in the synopsis, figure out where to pull the block id from.
      // if it's <= non_fork_high_block_num, we grab it from the main blockchain;
      // if it's not, we pull it from the fork history
      if (low_block_num <= non_fork_high_block_num)
        synopsis.push_back(_chain_db->get_block_id_for_num(low_block_num));
      else
        synopsis.push_back(fork_history[low_block_num - non_fork_high_block_num - 1]);
      low_block_num += (true_high_block_num - low_block_num + 2) / 2;
    }
    while (low_block_num <= high_block_num);

    //idump((synopsis));
    return synopsis;
} FC_CAPTURE_AND_RETHROW() }

/**
 * Call this after the call to handle_message succeeds.
 *
 * @param item_type the type of the item we're synchronizing, will be the same as item passed to the sync_from() call
 * @param item_count the number of items known to the node that haven't been sent to handle_item() yet.
 *                   After `item_count` more calls to handle_item(), the node will be in sync
 */
void application_impl::sync_status(uint32_t item_type, uint32_t item_count)
{
   // any status reports to GUI go here
}

/**
 * Call any time the number of connected peers changes.
 */
void application_impl::connection_count_changed(uint32_t c)
{
  // any status reports to GUI go here
}

uint32_t application_impl::get_block_number(const item_hash_t& block_id)
{ try {
   return block_header::num_from_id(block_id);
} FC_CAPTURE_AND_RETHROW( (block_id) ) }

/**
 * Returns the time a block was produced (if block_id = 0, returns genesis time).
 * If we don't know about the block, returns time_point_sec::min()
 */
fc::time_point_sec application_impl::get_block_time(const item_hash_t& block_id)
{ try {
   auto opt_block = _chain_db->fetch_block_by_id( block_id );
   if( opt_block.valid() ) return opt_block->timestamp;
   return fc::time_point_sec::min();
} FC_CAPTURE_AND_RETHROW( (block_id) ) }

item_hash_t application_impl::get_head_block_id() const
{
   return _chain_db->head_block_id();
}

uint32_t application_impl::estimate_last_known_fork_from_git_revision_timestamp(uint32_t unix_timestamp) const
{
   return 0; // there are no forks in graphene
}

void application_impl::error_encountered(const std::string& message, const fc::oexception& error)
{
   // notify GUI or something cool
}

uint8_t application_impl::get_current_block_interval_in_seconds() const
{
   return _chain_db->get_global_properties().parameters.block_interval;
}

} } } // namespace graphene namespace app namespace detail

namespace graphene { namespace app {

application::application()
   : my(new detail::application_impl(this))
{}

application::~application()
{
   if( my->_p2p_network )
   {
      my->_p2p_network->close();
      my->_p2p_network.reset();
   }
   if( my->_chain_db )
   {
      my->_chain_db->close();
   }
}

void application::set_program_options(boost::program_options::options_description& command_line_options,
                                      boost::program_options::options_description& configuration_file_options) const
{
   configuration_file_options.add_options()
         ("p2p-endpoint", bpo::value<string>(), "Endpoint for P2P node to listen on")
         ("seed-node,s", bpo::value<vector<string>>()->composing(),
          "P2P nodes to connect to on startup (may specify multiple times)")
         ("seed-nodes", bpo::value<string>()->composing(),
          "JSON array of P2P nodes to connect to on startup")
         ("checkpoint,c", bpo::value<vector<string>>()->composing(),
          "Pairs of [BLOCK_NUM,BLOCK_ID] that should be enforced as checkpoints.")
         ("rpc-endpoint", bpo::value<string>()->implicit_value("127.0.0.1:8090"),
          "Endpoint for websocket RPC to listen on")
         ("rpc-tls-endpoint", bpo::value<string>()->implicit_value("127.0.0.1:8089"),
          "Endpoint for TLS websocket RPC to listen on")
         ("server-pem,p", bpo::value<string>()->implicit_value("server.pem"), "The TLS certificate file for this server")
         ("server-pem-password,P", bpo::value<string>()->implicit_value(""), "Password for this certificate")
         ("proxy-forwarded-for-header", bpo::value<string>()->implicit_value("X-Forwarded-For-Client"),
          "A HTTP header similar to X-Forwarded-For (XFF), used by the RPC server to extract clients' address info, "
          "usually added by a trusted reverse proxy")
         ("genesis-json", bpo::value<boost::filesystem::path>(), "File to read Genesis State from")
         ("dbg-init-key", bpo::value<string>(), "Block signing key to use for init witnesses, overrides genesis file")
         ("api-access", bpo::value<boost::filesystem::path>(), "JSON file specifying API permissions")
         ("io-threads", bpo::value<uint16_t>()->implicit_value(0), "Number of IO threads, default to 0 for auto-configuration")
         ("enable-subscribe-to-all", bpo::value<bool>()->implicit_value(true),
          "Whether allow API clients to subscribe to universal object creation and removal events")
         ("enable-standby-votes-tracking", bpo::value<bool>()->implicit_value(true),
          "Whether to enable tracking of votes of standby witnesses and committee members. "
          "Set it to true to provide accurate data to API clients, set to false for slightly better performance.")
         ("api-limit-get-account-history-operations",boost::program_options::value<uint64_t>()->default_value(100),
          "For history_api::get_account_history_operations to set max limit value")
         ("api-limit-get-account-history",boost::program_options::value<uint64_t>()->default_value(100),
          "For history_api::get_account_history to set max limit value")
         ("api-limit-get-grouped-limit-orders",boost::program_options::value<uint64_t>()->default_value(101),
          "For orders_api::get_grouped_limit_orders to set max limit value")
         ("api-limit-get-relative-account-history",boost::program_options::value<uint64_t>()->default_value(100),
          "For history_api::get_relative_account_history to set max limit value")
         ("api-limit-get-account-history-by-operations",boost::program_options::value<uint64_t>()->default_value(100),
          "For history_api::get_account_history_by_operations to set max limit value")
         ("api-limit-get-asset-holders",boost::program_options::value<uint64_t>()->default_value(100),
          "For asset_api::get_asset_holders to set max limit value")
         ("api-limit-get-key-references",boost::program_options::value<uint64_t>()->default_value(100),
          "For database_api_impl::get_key_references to set max limit value")
         ("api-limit-get-htlc-by",boost::program_options::value<uint64_t>()->default_value(100),
          "For database_api_impl::get_htlc_by_from and get_htlc_by_to to set max limit value")
         ("api-limit-get-full-accounts",boost::program_options::value<uint64_t>()->default_value(50),
          "For database_api_impl::get_full_accounts to set max accounts to query at once")
         ("api-limit-get-full-accounts-lists",boost::program_options::value<uint64_t>()->default_value(500),
          "For database_api_impl::get_full_accounts to set max items to return in the lists")
         ("api-limit-get-top-voters",boost::program_options::value<uint64_t>()->default_value(200),
          "For database_api_impl::get_top_voters to set max limit value")
         ("api-limit-get-call-orders",boost::program_options::value<uint64_t>()->default_value(300),
          "For database_api_impl::get_call_orders and get_call_orders_by_account to set max limit value")
         ("api-limit-get-settle-orders",boost::program_options::value<uint64_t>()->default_value(300),
          "For database_api_impl::get_settle_orders and get_settle_orders_by_account to set max limit value")
         ("api-limit-get-assets",boost::program_options::value<uint64_t>()->default_value(101),
          "For database_api_impl::list_assets and get_assets_by_issuer to set max limit value")
         ("api-limit-get-limit-orders",boost::program_options::value<uint64_t>()->default_value(300),
          "For database_api_impl::get_limit_orders to set max limit value")
         ("api-limit-get-limit-orders-by-account",boost::program_options::value<uint64_t>()->default_value(101),
          "For database_api_impl::get_limit_orders_by_account to set max limit value")
         ("api-limit-get-order-book",boost::program_options::value<uint64_t>()->default_value(50),
          "For database_api_impl::get_order_book to set max limit value")
         ("api-limit-lookup-accounts",boost::program_options::value<uint64_t>()->default_value(1000),
          "For database_api_impl::lookup_accounts to set max limit value")
         ("api-limit-lookup-witness-accounts",boost::program_options::value<uint64_t>()->default_value(1000),
          "For database_api_impl::lookup_witness_accounts to set max limit value")
         ("api-limit-lookup-committee-member-accounts",boost::program_options::value<uint64_t>()->default_value(1000),
          "For database_api_impl::lookup_committee_member_accounts to set max limit value")
         ("api-limit-lookup-vote-ids",boost::program_options::value<uint64_t>()->default_value(1000),
          "For database_api_impl::lookup_vote_ids to set max limit value")
         ("api-limit-get-account-limit-orders",boost::program_options::value<uint64_t>()->default_value(101),
          "For database_api_impl::get_account_limit_orders to set max limit value")
         ("api-limit-get-collateral-bids",boost::program_options::value<uint64_t>()->default_value(100),
          "For database_api_impl::get_collateral_bids to set max limit value")
         ("api-limit-get-top-markets",boost::program_options::value<uint64_t>()->default_value(100),
          "For database_api_impl::get_top_markets to set max limit value")
         ("api-limit-get-trade-history",boost::program_options::value<uint64_t>()->default_value(100),
          "For database_api_impl::get_trade_history to set max limit value")
         ("api-limit-get-trade-history-by-sequence",boost::program_options::value<uint64_t>()->default_value(100),
          "For database_api_impl::get_trade_history_by_sequence to set max limit value")
         ("api-limit-get-withdraw-permissions-by-giver",boost::program_options::value<uint64_t>()->default_value(101),
          "For database_api_impl::get_withdraw_permissions_by_giver to set max limit value")
         ("api-limit-get-withdraw-permissions-by-recipient",boost::program_options::value<uint64_t>()->default_value(101),
          "For database_api_impl::get_withdraw_permissions_by_recipient to set max limit value")
         ("api-limit-get-liquidity-pools",boost::program_options::value<uint64_t>()->default_value(101),
          "For database_api_impl::get_liquidity_pools_* to set max limit value")
         ("api-limit-get-tickets",boost::program_options::value<uint64_t>()->default_value(101),
          "For database_api_impl::get_tickets_* to set max limit value")
         ;
   command_line_options.add(configuration_file_options);
   command_line_options.add_options()
         ("replay-blockchain", "Rebuild object graph by replaying all blocks without validation")
         ("revalidate-blockchain", "Rebuild object graph by replaying all blocks with full validation")
         ("resync-blockchain", "Delete all blocks and re-sync with network from scratch")
         ("force-validate", "Force validation of all transactions during normal operation")
         ("genesis-timestamp", bpo::value<uint32_t>(),
          "Replace timestamp from genesis.json with current time plus this many seconds (experts only!)")
         ;
   command_line_options.add(_cli_options);
   configuration_file_options.add(_cfg_options);
}

void application::initialize(const fc::path& data_dir, const boost::program_options::variables_map& options)
{
   my->_data_dir = data_dir;
   my->_options = &options;

   if ( options.count("io-threads") )
   {
      const uint16_t num_threads = options["io-threads"].as<uint16_t>();
      fc::asio::default_io_service_scope::set_num_threads(num_threads);
   }
}

void application::startup()
{
   try {
      my->startup();
   } catch ( const fc::exception& e ) {
      elog( "${e}", ("e",e.to_detail_string()) );
      throw;
   } catch ( ... ) {
      elog( "unexpected exception" );
      throw;
   }
}

void application::set_api_limit()
{
   try {
      my->set_api_limit();
   } catch ( const fc::exception& e ) {
      elog( "${e}", ("e",e.to_detail_string()) );
      throw;
   } catch ( ... ) {
      elog( "unexpected exception" );
      throw;
   }
}
std::shared_ptr<abstract_plugin> application::get_plugin(const string& name) const
{
   return my->_active_plugins[name];
}

bool application::is_plugin_enabled(const string& name) const
{
   return !(my->_active_plugins.find(name) == my->_active_plugins.end());
}

net::node_ptr application::p2p_node()
{
   return my->_p2p_network;
}

std::shared_ptr<chain::database> application::chain_database() const
{
   return my->_chain_db;
}

void application::set_block_production(bool producing_blocks)
{
   my->_is_block_producer = producing_blocks;
}

optional< api_access_info > application::get_api_access_info( const string& username )const
{
   return my->get_api_access_info( username );
}

void application::set_api_access_info(const string& username, api_access_info&& permissions)
{
   my->set_api_access_info(username, std::move(permissions));
}

bool application::is_finished_syncing() const
{
   return my->_is_finished_syncing;
}

void graphene::app::application::enable_plugin(const string& name)
{
   FC_ASSERT(my->_available_plugins[name], "Unknown plugin '" + name + "'");
   my->_active_plugins[name] = my->_available_plugins[name];
   my->_active_plugins[name]->plugin_set_app(this);
}

void graphene::app::application::add_available_plugin(std::shared_ptr<graphene::app::abstract_plugin> p)
{
   my->_available_plugins[p->plugin_name()] = p;
}

void application::shutdown_plugins()
{
   for( auto& entry : my->_active_plugins )
      entry.second->plugin_shutdown();
   return;
}
void application::shutdown()
{
   if( my->_p2p_network )
      my->_p2p_network->close();
   if( my->_chain_db )
   {
      my->_chain_db->close();
      my->_chain_db = nullptr;
   }
}

void application::initialize_plugins( const boost::program_options::variables_map& options )
{
   for( auto& entry : my->_active_plugins )
      entry.second->plugin_initialize( options );
   return;
}

void application::startup_plugins()
{
   for( auto& entry : my->_active_plugins )
   {
      entry.second->plugin_startup();
      ilog( "Plugin ${name} started", ( "name", entry.second->plugin_name() ) );
   }
   return;
}

const application_options& application::get_options()
{
   return my->_app_options;
}

// namespace detail
} }


text:
namespace Microsoft.Azure.Batch.Protocol.Models
{
    using Microsoft.Rest;
    using Newtonsoft.Json;
    using System.Linq;

    /// <summary>
    /// A name-value pair associated with a Batch service resource.
    /// </summary>
    /// <remarks>
    /// The Batch service does not assign any meaning to this metadata; it is
    /// solely for the use of user code.
    /// </remarks>
    public partial class MetadataItem
    {
        /// <summary>
        /// Initializes a new instance of the MetadataItem class.
        /// </summary>
        public MetadataItem()
        {
            CustomInit();
        }

        /// <summary>
        /// Initializes a new instance of the MetadataItem class.
        /// </summary>
        /// <param name="name">The name of the metadata item.</param>
        /// <param name="value">The value of the metadata item.</param>
        public MetadataItem(string name, string value)
        {
            Name = name;
            Value = value;
            CustomInit();
        }

        /// <summary>
        /// An initialization method that performs custom operations like setting defaults
        /// </summary>
        partial void CustomInit();

        /// <summary>
        /// Gets or sets the name of the metadata item.
        /// </summary>
        [JsonProperty(PropertyName = "name")]
        public string Name { get; set; }

        /// <summary>
        /// Gets or sets the value of the metadata item.
        /// </summary>
        [JsonProperty(PropertyName = "value")]
        public string Value { get; set; }

        /// <summary>
        /// Validate the object.
        /// </summary>
        /// <exception cref="ValidationException">
        /// Thrown if validation fails
        /// </exception>
        public virtual void Validate()
        {
            if (Name == null)
            {
                throw new ValidationException(ValidationRules.CannotBeNull, "Name");
            }
            if (Value == null)
            {
                throw new ValidationException(ValidationRules.CannotBeNull, "Value");
            }
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/core/utility.hpp"

#include <stdio.h>

using namespace cv;

static void print_help()
{
    printf("\nDemo stereo matching converting L and R images into disparity and point clouds\n");
    printf("\nUsage: stereo_match <left_image> <right_image> [--algorithm=bm|sgbm|hh|var] [--blocksize=<block_size>]\n"
           "[--max-disparity=<max_disparity>] [--scale=scale_factor>] [-i <intrinsic_filename>] [-e <extrinsic_filename>]\n"
           "[--no-display] [-o <disparity_image>] [-p <point_cloud_file>]\n");
}

static void saveXYZ(const char* filename, const Mat& mat)
{
    const double max_z = 1.0e4;
    FILE* fp = fopen(filename, "wt");
    for(int y = 0; y < mat.rows; y++)
    {
        for(int x = 0; x < mat.cols; x++)
        {
            Vec3f point = mat.at<Vec3f>(y, x);
            if(fabs(point[2] - max_z) < FLT_EPSILON || fabs(point[2]) > max_z) continue;
            fprintf(fp, "%f %f %f\n", point[0], point[1], point[2]);
        }
    }
    fclose(fp);
}

int main(int argc, char** argv)
{
    const char* algorithm_opt = "--algorithm=";
    const char* maxdisp_opt = "--max-disparity=";
    const char* blocksize_opt = "--blocksize=";
    const char* nodisplay_opt = "--no-display";
    const char* scale_opt = "--scale=";

    if(argc < 3)
    {
        print_help();
        return 0;
    }
    const char* img1_filename = 0;
    const char* img2_filename = 0;
    const char* intrinsic_filename = 0;
    const char* extrinsic_filename = 0;
    const char* disparity_filename = 0;
    const char* point_cloud_filename = 0;

    enum { STEREO_BM=0, STEREO_SGBM=1, STEREO_HH=2, STEREO_VAR=3 };
    int alg = STEREO_SGBM;
    int SADWindowSize = 0, numberOfDisparities = 0;
    bool no_display = false;
    float scale = 1.f;

    Ptr<StereoBM> bm = createStereoBM(16,9);
    Ptr<StereoSGBM> sgbm = createStereoSGBM(0,16,3);
    StereoVar var;

    for( int i = 1; i < argc; i++ )
    {
        if( argv[i][0] != '-' )
        {
            if( !img1_filename )
                img1_filename = argv[i];
            else
                img2_filename = argv[i];
        }
        else if( strncmp(argv[i], algorithm_opt, strlen(algorithm_opt)) == 0 )
        {
            char* _alg = argv[i] + strlen(algorithm_opt);
            alg = strcmp(_alg, "bm") == 0 ? STEREO_BM :
                  strcmp(_alg, "sgbm") == 0 ? STEREO_SGBM :
                  strcmp(_alg, "hh") == 0 ? STEREO_HH :
                  strcmp(_alg, "var") == 0 ? STEREO_VAR : -1;
            if( alg < 0 )
            {
                printf("Command-line parameter error: Unknown stereo algorithm\n\n");
                print_help();
                return -1;
            }
        }
        else if( strncmp(argv[i], maxdisp_opt, strlen(maxdisp_opt)) == 0 )
        {
            if( sscanf( argv[i] + strlen(maxdisp_opt), "%d", &numberOfDisparities ) != 1 ||
                numberOfDisparities < 1 || numberOfDisparities % 16 != 0 )
            {
                printf("Command-line parameter error: The max disparity (--maxdisparity=<...>) must be a positive integer divisible by 16\n");
                print_help();
                return -1;
            }
        }
        else if( strncmp(argv[i], blocksize_opt, strlen(blocksize_opt)) == 0 )
        {
            if( sscanf( argv[i] + strlen(blocksize_opt), "%d", &SADWindowSize ) != 1 ||
                SADWindowSize < 1 || SADWindowSize % 2 != 1 )
            {
                printf("Command-line parameter error: The block size (--blocksize=<...>) must be a positive odd number\n");
                return -1;
            }
        }
        else if( strncmp(argv[i], scale_opt, strlen(scale_opt)) == 0 )
        {
            if( sscanf( argv[i] + strlen(scale_opt), "%f", &scale ) != 1 || scale < 0 )
            {
                printf("Command-line parameter error: The scale factor (--scale=<...>) must be a positive floating-point number\n");
                return -1;
            }
        }
        else if( strcmp(argv[i], nodisplay_opt) == 0 )
            no_display = true;
        else if( strcmp(argv[i], "-i" ) == 0 )
            intrinsic_filename = argv[++i];
        else if( strcmp(argv[i], "-e" ) == 0 )
            extrinsic_filename = argv[++i];
        else if( strcmp(argv[i], "-o" ) == 0 )
            disparity_filename = argv[++i];
        else if( strcmp(argv[i], "-p" ) == 0 )
            point_cloud_filename = argv[++i];
        else
        {
            printf("Command-line parameter error: unknown option %s\n", argv[i]);
            return -1;
        }
    }

    if( !img1_filename || !img2_filename )
    {
        printf("Command-line parameter error: both left and right images must be specified\n");
        return -1;
    }

    if( (intrinsic_filename != 0) ^ (extrinsic_filename != 0) )
    {
        printf("Command-line parameter error: either both intrinsic and extrinsic parameters must be specified, or none of them (when the stereo pair is already rectified)\n");
        return -1;
    }

    if( extrinsic_filename == 0 && point_cloud_filename )
    {
        printf("Command-line parameter error: extrinsic and intrinsic parameters must be specified to compute the point cloud\n");
        return -1;
    }

    int color_mode = alg == STEREO_BM ? 0 : -1;
    Mat img1 = imread(img1_filename, color_mode);
    Mat img2 = imread(img2_filename, color_mode);

    if( scale != 1.f )
    {
        Mat temp1, temp2;
        int method = scale < 1 ? INTER_AREA : INTER_CUBIC;
        resize(img1, temp1, Size(), scale, scale, method);
        img1 = temp1;
        resize(img2, temp2, Size(), scale, scale, method);
        img2 = temp2;
    }

    Size img_size = img1.size();

    Rect roi1, roi2;
    Mat Q;

    if( intrinsic_filename )
    {
        // reading intrinsic parameters
        FileStorage fs(intrinsic_filename, FileStorage::READ);
        if(!fs.isOpened())
        {
            printf("Failed to open file %s\n", intrinsic_filename);
            return -1;
        }

        Mat M1, D1, M2, D2;
        fs["M1"] >> M1;
        fs["D1"] >> D1;
        fs["M2"] >> M2;
        fs["D2"] >> D2;

        M1 *= scale;
        M2 *= scale;

        fs.open(extrinsic_filename, FileStorage::READ);
        if(!fs.isOpened())
        {
            printf("Failed to open file %s\n", extrinsic_filename);
            return -1;
        }

        Mat R, T, R1, P1, R2, P2;
        fs["R"] >> R;
        fs["T"] >> T;

        stereoRectify( M1, D1, M2, D2, img_size, R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, -1, img_size, &roi1, &roi2 );

        Mat map11, map12, map21, map22;
        initUndistortRectifyMap(M1, D1, R1, P1, img_size, CV_16SC2, map11, map12);
        initUndistortRectifyMap(M2, D2, R2, P2, img_size, CV_16SC2, map21, map22);

        Mat img1r, img2r;
        remap(img1, img1r, map11, map12, INTER_LINEAR);
        remap(img2, img2r, map21, map22, INTER_LINEAR);

        img1 = img1r;
        img2 = img2r;
    }

    numberOfDisparities = numberOfDisparities > 0 ? numberOfDisparities : ((img_size.width/8) + 15) & -16;

    bm->setROI1(roi1);
    bm->setROI2(roi2);
    bm->setPreFilterCap(31);
    bm->setBlockSize(SADWindowSize > 0 ? SADWindowSize : 9);
    bm->setMinDisparity(0);
    bm->setNumDisparities(numberOfDisparities);
    bm->setTextureThreshold(10);
    bm->setUniquenessRatio(15);
    bm->setSpeckleWindowSize(100);
    bm->setSpeckleRange(32);
    bm->setDisp12MaxDiff(1);

    sgbm->setPreFilterCap(63);
    int sgbmWinSize = SADWindowSize > 0 ? SADWindowSize : 3;
    sgbm->setBlockSize(sgbmWinSize);

    int cn = img1.channels();

    sgbm->setP1(8*cn*sgbmWinSize*sgbmWinSize);
    sgbm->setP2(32*cn*sgbmWinSize*sgbmWinSize);
    sgbm->setMinDisparity(0);
    sgbm->setNumDisparities(numberOfDisparities);
    sgbm->setUniquenessRatio(10);
    sgbm->setSpeckleWindowSize(100);
    sgbm->setSpeckleRange(32);
    sgbm->setDisp12MaxDiff(1);
    sgbm->setMode(alg == STEREO_HH ? StereoSGBM::MODE_HH : StereoSGBM::MODE_SGBM);

    var.levels = 3;                                 // ignored with USE_AUTO_PARAMS
    var.pyrScale = 0.5;                             // ignored with USE_AUTO_PARAMS
    var.nIt = 25;
    var.minDisp = -numberOfDisparities;
    var.maxDisp = 0;
    var.poly_n = 3;
    var.poly_sigma = 0.0;
    var.fi = 15.0f;
    var.lambda = 0.03f;
    var.penalization = var.PENALIZATION_TICHONOV;   // ignored with USE_AUTO_PARAMS
    var.cycle = var.CYCLE_V;                        // ignored with USE_AUTO_PARAMS
    var.flags = var.USE_SMART_ID | var.USE_AUTO_PARAMS | var.USE_INITIAL_DISPARITY | var.USE_MEDIAN_FILTERING ;

    Mat disp, disp8;
    //Mat img1p, img2p, dispp;
    //copyMakeBorder(img1, img1p, 0, 0, numberOfDisparities, 0, IPL_BORDER_REPLICATE);
    //copyMakeBorder(img2, img2p, 0, 0, numberOfDisparities, 0, IPL_BORDER_REPLICATE);

    int64 t = getTickCount();
    if( alg == STEREO_BM )
        bm->compute(img1, img2, disp);
    else if( alg == STEREO_VAR ) {
        var(img1, img2, disp);
    }
    else if( alg == STEREO_SGBM || alg == STEREO_HH )
        sgbm->compute(img1, img2, disp);
    t = getTickCount() - t;
    printf("Time elapsed: %fms\n", t*1000/getTickFrequency());

    //disp = dispp.colRange(numberOfDisparities, img1p.cols);
    if( alg != STEREO_VAR )
        disp.convertTo(disp8, CV_8U, 255/(numberOfDisparities*16.));
    else
        disp.convertTo(disp8, CV_8U);
    if( !no_display )
    {
        namedWindow("left", 1);
        imshow("left", img1);
        namedWindow("right", 1);
        imshow("right", img2);
        namedWindow("disparity", 0);
        imshow("disparity", disp8);
        printf("press any key to continue...");
        fflush(stdout);
        waitKey();
        printf("\n");
    }

    if(disparity_filename)
        imwrite(disparity_filename, disp8);

    if(point_cloud_filename)
    {
        printf("storing the point cloud...");
        fflush(stdout);
        Mat xyz;
        reprojectImageTo3D(disp, xyz, Q, true);
        saveXYZ(point_cloud_filename, xyz);
        printf("\n");
    }

    return 0;
}


text:
[![travis-ci.org](https://travis-ci.org/jonestimd/neo4j-rest-java.svg?branch=master)](https://travis-ci.org/jonestimd/neo4j-rest-java?branch=master)
[![codecov.io](https://codecov.io/github/jonestimd/neo4j-rest-java/coverage.svg?branch=master)](https://codecov.io/github/jonestimd/neo4j-rest-java?branch=master)

Java REST client for Neo4j database

### Features
- Executes Cypher queries using Neo4j's transaction API
  - Combines multiple queries in a single HTTP request
  - Streams results for reduced memory requirement
- Automatically Pings transaction URL during long running task
  - Prevents transaction timeout
  - Configurable ping frequency

### Basic Usage
```Java
import java.util.Timer;
import io.github.jonestimd.neo4j.client.http.ApacheHttpDriver;
import io.github.jonestimd.neo4j.client.http.HttpDriver;
import io.github.jonestimd.neo4j.client.transaction.TransactionManager;
import io.github.jonestimd.neo4j.client.transaction.request.Statement;
import io.github.jonestimd.neo4j.client.transaction.response.Node;
import io.github.jonestimd.neo4j.client.transaction.response.Relationship;
import io.github.jonestimd.neo4j.client.transaction.response.Response;
import io.github.jonestimd.neo4j.client.transaction.response.StatementResult;

import static java.util.Collections.*;
import static io.github.jonestimd.neo4j.client.transaction.Transaction.*;

// configure the transaction manager
String baseUrl = "http://localhost:7474/db/data/transaction";
HttpDriver httpDriver = new ApacheHttpDriver("neo4j", "neo4j", "localhost", 7474);
Timer pingTimer = new Timer("ping timer", true);
TransactionManager transactionManager = new TransactionManager(httpDriver, baseUrl,
       DEFAULT_JSON_FACTORY, pingTimer, 45000L);

// run a query
Response response = transactionManager.doInTransaction(tx -> tx.execute(
        new Statement("match p=(n:Item {itemId: {id}})<--(x) return n, p", singletonMap("id", 1L))));

// process the results
while (response.next()) {
    StatementResult result = response.getResult();
    while (result.next()) {
        result.getColumn("n");
        result.getColumn("p");
        result.getMeta("n");
        result.getMeta("p");
        result.getNodes();
        result.getRelationships();
    }
}
```


text:
namespace shell_integration {

// TODO: crbug/115375 to track implementation for following methods.
bool SetAsDefaultBrowser() {
  NOTIMPLEMENTED();
  return false;
}

bool SetAsDefaultProtocolClient(const std::string& protocol) {
  NOTIMPLEMENTED();
  return false;
}

DefaultWebClientSetPermission GetDefaultWebClientSetPermission() {
  NOTIMPLEMENTED();
  return SET_DEFAULT_NOT_ALLOWED;
}

std::u16string GetApplicationNameForProtocol(const GURL& url) {
  NOTIMPLEMENTED();
  return std::u16string();
}

DefaultWebClientState GetDefaultBrowser() {
  NOTIMPLEMENTED();
  return UNKNOWN_DEFAULT;
}

bool IsFirefoxDefaultBrowser() {
  return false;
}

DefaultWebClientState IsDefaultProtocolClient(const std::string& protocol) {
  NOTIMPLEMENTED();
  return UNKNOWN_DEFAULT;
}

}  // namespace shell_integration


text:
<?php

namespace app\modules\admin\models\search;

use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\modules\blog\models\BlogTags;

/**
 * BlogTagsSearch represents the model behind the search form about `app\modules\blog\models\BlogTags`.
 */
class BlogTagsSearch extends BlogTags
{
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['id', 'frequency'], 'integer'],
            [['name'], 'safe'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function scenarios()
    {
        // bypass scenarios() implementation in the parent class
        return Model::scenarios();
    }

    /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params)
    {
        $query = BlogTags::find();

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);

        $this->load($params);

        if (!$this->validate()) {
            // uncomment the following line if you do not want to return any records when validation fails
            // $query->where('0=1');
            return $dataProvider;
        }

        $query->andFilterWhere([
            'id' => $this->id,
            'frequency' => $this->frequency,
        ]);

        $query->andFilterWhere(['like', 'name', $this->name]);

        return $dataProvider;
    }
}


text: export * from './filterInterface';


text:
"""
This module contains the C{L{TrustRoot}} class, which helps handle
trust root checking.  This module is used by the
C{L{openid.server.server}} module, but it is also available to server
implementers who wish to use it for additional trust root checking.

It also implements relying party return_to URL verification, based on
the realm.
"""

__all__ = [
    'TrustRoot',
    'RP_RETURN_TO_URL_TYPE',
    'extractReturnToURLs',
    'returnToMatches',
    'verifyReturnTo',
]

from openid import urinorm
from openid.yadis import services

from urllib.parse import urlparse, urlunparse
import re
import logging

############################################
_protocols = ['http', 'https']
_top_level_domains = [
    'ac', 'ad', 'ae', 'aero', 'af', 'ag', 'ai', 'al', 'am', 'an', 'ao', 'aq',
    'ar', 'arpa', 'as', 'asia', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb', 'bd',
    'be', 'bf', 'bg', 'bh', 'bi', 'biz', 'bj', 'bm', 'bn', 'bo', 'br', 'bs',
    'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cat', 'cc', 'cd', 'cf', 'cg', 'ch',
    'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'com', 'coop', 'cr', 'cu', 'cv', 'cx',
    'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'do', 'dz', 'ec', 'edu', 'ee', 'eg',
    'er', 'es', 'et', 'eu', 'fi', 'fj', 'fk', 'fm', 'fo', 'fr', 'ga', 'gb',
    'gd', 'ge', 'gf', 'gg', 'gh', 'gi', 'gl', 'gm', 'gn', 'gov', 'gp', 'gq',
    'gr', 'gs', 'gt', 'gu', 'gw', 'gy', 'hk', 'hm', 'hn', 'hr', 'ht', 'hu',
    'id', 'ie', 'il', 'im', 'in', 'info', 'int', 'io', 'iq', 'ir', 'is', 'it',
    'je', 'jm', 'jo', 'jobs', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp',
    'kr', 'kw', 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt',
    'lu', 'lv', 'ly', 'ma', 'mc', 'md', 'me', 'mg', 'mh', 'mil', 'mk', 'ml',
    'mm', 'mn', 'mo', 'mobi', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'museum',
    'mv', 'mw', 'mx', 'my', 'mz', 'na', 'name', 'nc', 'ne', 'net', 'nf', 'ng',
    'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om', 'org', 'pa', 'pe', 'pf',
    'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'pro', 'ps', 'pt', 'pw', 'py',
    'qa', 're', 'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd', 'se', 'sg',
    'sh', 'si', 'sj', 'sk', 'sl', 'sm', 'sn', 'so', 'sr', 'st', 'su', 'sv',
    'sy', 'sz', 'tc', 'td', 'tel', 'tf', 'tg', 'th', 'tj', 'tk', 'tl', 'tm',
    'tn', 'to', 'tp', 'tr', 'travel', 'tt', 'tv', 'tw', 'tz', 'ua', 'ug', 'uk',
    'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws',
    'xn--0zwm56d', 'xn--11b5bs3a9aj6g', 'xn--80akhbyknj4f', 'xn--9t4b11yi5a',
    'xn--deba0ad', 'xn--g6w251d', 'xn--hgbk6aj7f53bba', 'xn--hlcj6aya9esc7a',
    'xn--jxalpdlp', 'xn--kgbechtv', 'xn--zckzah', 'ye', 'yt', 'yu', 'za', 'zm',
    'zw'
]

# Build from RFC3986, section 3.2.2. Used to reject hosts with invalid
# characters.
host_segment_re = re.compile(
    r"(?:[-a-zA-Z0-9!$&'\(\)\*+,;=._~]|%[a-zA-Z0-9]{2})+$")

class RealmVerificationRedirected(Exception):
    """Attempting to verify this realm resulted in a redirect.

    @since: 2.1.0
    """

    def __init__(self, relying_party_url, rp_url_after_redirects):
        self.relying_party_url = relying_party_url
        self.rp_url_after_redirects = rp_url_after_redirects

    def __str__(self):
        return ("Attempting to verify %r resulted in "
                "redirect to %r" % (self.relying_party_url,
                                    self.rp_url_after_redirects))

def _parseURL(url):
    try:
        url = urinorm.urinorm(url)
    except ValueError:
        return None
    proto, netloc, path, params, query, frag = urlparse(url)
    if not path:
        # Python <2.4 does not parse URLs with no path properly
        if not query and '?' in netloc:
            netloc, query = netloc.split('?', 1)

        path = '/'

    path = urlunparse(('', '', path, params, query, frag))

    if ':' in netloc:
        try:
            host, port = netloc.split(':')
        except ValueError:
            return None

        if not re.match(r'\d+$', port):
            return None
    else:
        host = netloc
        port = ''

    host = host.lower()
    if not host_segment_re.match(host):
        return None

    return proto, host, port, path

class TrustRoot(object):
    """
    This class represents an OpenID trust root.  The C{L{parse}}
    classmethod accepts a trust root string, producing a
    C{L{TrustRoot}} object.  The method OpenID server implementers
    would be most likely to use is the C{L{isSane}} method, which
    checks the trust root for given patterns that indicate that the
    trust root is too broad or points to a local network resource.

    @sort: parse, isSane
    """

    def __init__(self, unparsed, proto, wildcard, host, port, path):
        self.unparsed = unparsed
        self.proto = proto
        self.wildcard = wildcard
        self.host = host
        self.port = port
        self.path = path

    def isSane(self):
        """
        This method checks the to see if a trust root represents a
        reasonable (sane) set of URLs.  'http://*.com/', for example
        is not a reasonable pattern, as it cannot meaningfully specify
        the site claiming it.  This function attempts to find many
        related examples, but it can only work via heuristics.
        Negative responses from this method should be treated as
        advisory, used only to alert the user to examine the trust
        root carefully.

        @return: Whether the trust root is sane

        @rtype: C{bool}
        """

        if self.host == 'localhost':
            return True

        host_parts = self.host.split('.')
        if self.wildcard:
            assert host_parts[0] == '', host_parts
            del host_parts[0]

        # If it's an absolute domain name, remove the empty string
        # from the end.
        if host_parts and not host_parts[-1]:
            del host_parts[-1]

        if not host_parts:
            return False

        # Do not allow adjacent dots
        if '' in host_parts:
            return False

        tld = host_parts[-1]
        if tld not in _top_level_domains:
            return False

        if len(host_parts) == 1:
            return False

        if self.wildcard:
            if len(tld) == 2 and len(host_parts[-2]) <= 3:
                # It's a 2-letter tld with a short second to last segment
                # so there needs to be more than two segments specified
                # (e.g. *.co.uk is insane)
                return len(host_parts) > 2

        # Passed all tests for insanity.
        return True

    def validateURL(self, url):
        """
        Validates a URL against this trust root.

        @param url: The URL to check

        @type url: C{str}

        @return: Whether the given URL is within this trust root.

        @rtype: C{bool}
        """

        url_parts = _parseURL(url)
        if url_parts is None:
            return False

        proto, host, port, path = url_parts

        if proto != self.proto:
            return False

        if port != self.port:
            return False

        if '*' in host:
            return False

        if not self.wildcard:
            if host != self.host:
                return False
        elif ((not host.endswith(self.host)) and ('.' + host) != self.host):
            return False

        if path != self.path:
            path_len = len(self.path)
            trust_prefix = self.path[:path_len]
            url_prefix = path[:path_len]

            # must be equal up to the length of the path, at least
            if trust_prefix != url_prefix:
                return False

            # These characters must be on the boundary between the end
            # of the trust root's path and the start of the URL's
            # path.
            if '?' in self.path:
                allowed = '&'
            else:
                allowed = '?/'

            return (self.path[-1] in allowed or path[path_len] in allowed)

        return True

    def parse(cls, trust_root):
        """
        This method creates a C{L{TrustRoot}} instance from the given
        input, if possible.

        @param trust_root: This is the trust root to parse into a
        C{L{TrustRoot}} object.

        @type trust_root: C{str}

        @return: A C{L{TrustRoot}} instance if trust_root parses as a
        trust root, C{None} otherwise.

        @rtype: C{NoneType} or C{L{TrustRoot}}
        """
        url_parts = _parseURL(trust_root)
        if url_parts is None:
            return None

        proto, host, port, path = url_parts

        # check for valid prototype
        if proto not in _protocols:
            return None

        # check for URI fragment
        if path.find('#') != -1:
            return None

        # extract wildcard if it is there
        if host.find('*', 1) != -1:
            # wildcard must be at start of domain:  *.foo.com, not foo.*.com
            return None

        if host.startswith('*'):
            # Starts with star, so must have a dot after it (if a
            # domain is specified)
            if len(host) > 1 and host[1] != '.':
                return None

            host = host[1:]
            wilcard = True
        else:
            wilcard = False

        # we have a valid trust root
        tr = cls(trust_root, proto, wilcard, host, port, path)

        return tr

    parse = classmethod(parse)

    def checkSanity(cls, trust_root_string):
        """str -> bool

        is this a sane trust root?
        """
        trust_root = cls.parse(trust_root_string)
        if trust_root is None:
            return False
        else:
            return trust_root.isSane()

    checkSanity = classmethod(checkSanity)

    def checkURL(cls, trust_root, url):
        """quick func for validating a url against a trust root.  See the
        TrustRoot class if you need more control."""
        tr = cls.parse(trust_root)
        return tr is not None and tr.validateURL(url)

    checkURL = classmethod(checkURL)

    def buildDiscoveryURL(self):
        """Return a discovery URL for this realm.

        This function does not check to make sure that the realm is
        valid. Its behaviour on invalid inputs is undefined.

        @rtype: str

        @returns: The URL upon which relying party discovery should be run
            in order to verify the return_to URL

        @since: 2.1.0
        """
        if self.wildcard:
            # Use "www." in place of the star
            assert self.host.startswith('.'), self.host
            www_domain = 'www' + self.host
            return '%s://%s%s' % (self.proto, www_domain, self.path)
        else:
            return self.unparsed

    def __repr__(self):
        return "TrustRoot(%r, %r, %r, %r, %r, %r)" % (
            self.unparsed, self.proto, self.wildcard, self.host, self.port,
            self.path)

    def __str__(self):
        return repr(self)

# The URI for relying party discovery, used in realm verification.
#
# XXX: This should probably live somewhere else (like in
# openid.consumer or openid.yadis somewhere)
RP_RETURN_TO_URL_TYPE = 'http://specs.openid.net/auth/2.0/return_to'

def _extractReturnURL(endpoint):
    """If the endpoint is a relying party OpenID return_to endpoint,
    return the endpoint URL. Otherwise, return None.

    This function is intended to be used as a filter for the Yadis
    filtering interface.

    @see: C{L{openid.yadis.services}}
    @see: C{L{openid.yadis.filters}}

    @param endpoint: An XRDS BasicServiceEndpoint, as returned by
        performing Yadis dicovery.

    @returns: The endpoint URL or None if the endpoint is not a
        relying party endpoint.
    @rtype: str or NoneType
    """
    if endpoint.matchTypes([RP_RETURN_TO_URL_TYPE]):
        return endpoint.uri
    else:
        return None

def returnToMatches(allowed_return_to_urls, return_to):
    """Is the return_to URL under one of the supplied allowed
    return_to URLs?

    @since: 2.1.0
    """

    for allowed_return_to in allowed_return_to_urls:
        # A return_to pattern works the same as a realm, except that
        # it's not allowed to use a wildcard. We'll model this by
        # parsing it as a realm, and not trying to match it if it has
        # a wildcard.

        return_realm = TrustRoot.parse(allowed_return_to)
        if (  # Parses as a trust root
                return_realm is not None and

                # Does not have a wildcard
                not return_realm.wildcard and

                # Matches the return_to that we passed in with it
                return_realm.validateURL(return_to)):
            return True

    # No URL in the list matched
    return False

def getAllowedReturnURLs(relying_party_url):
    """Given a relying party discovery URL return a list of return_to URLs.

    @since: 2.1.0
    """
    (rp_url_after_redirects, return_to_urls) = services.getServiceEndpoints(
        relying_party_url, _extractReturnURL)

    if rp_url_after_redirects != relying_party_url:
        # Verification caused a redirect
        raise RealmVerificationRedirected(relying_party_url,
                                          rp_url_after_redirects)

    return return_to_urls

# _vrfy parameter is there to make testing easier
def verifyReturnTo(realm_str, return_to, _vrfy=getAllowedReturnURLs):
    """Verify that a return_to URL is valid for the given realm.

    This function builds a discovery URL, performs Yadis discovery on
    it, makes sure that the URL does not redirect, parses out the
    return_to URLs, and finally checks to see if the current return_to
    URL matches the return_to.

    @raises DiscoveryFailure: When Yadis discovery fails
    @returns: True if the return_to URL is valid for the realm

    @since: 2.1.0
    """
    realm = TrustRoot.parse(realm_str)
    if realm is None:
        # The realm does not parse as a URL pattern
        return False

    try:
        allowable_urls = _vrfy(realm.buildDiscoveryURL())
    except RealmVerificationRedirected as err:
        logging.exception(str(err))
        return False

    if returnToMatches(allowable_urls, return_to):
        return True
    else:
        logging.error("Failed to validate return_to %r for realm %r, was not "
                      "in %s" % (return_to, realm_str, allowable_urls))
        return False


text:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE TupleSections #-}

-- | http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbinstance-processorfeature.html

module Stratosphere.ResourceProperties.RDSDBInstanceProcessorFeature where

import Stratosphere.ResourceImports

-- | Full data type definition for RDSDBInstanceProcessorFeature. See
-- 'rdsdbInstanceProcessorFeature' for a more convenient constructor.
data RDSDBInstanceProcessorFeature =
  RDSDBInstanceProcessorFeature
  { _rDSDBInstanceProcessorFeatureName :: Maybe (Val Text)
  , _rDSDBInstanceProcessorFeatureValue :: Maybe (Val Text)
  } deriving (Show, Eq)

instance ToJSON RDSDBInstanceProcessorFeature where
  toJSON RDSDBInstanceProcessorFeature{..} =
    object $
    catMaybes
    [ fmap (("Name",) . toJSON) _rDSDBInstanceProcessorFeatureName
    , fmap (("Value",) . toJSON) _rDSDBInstanceProcessorFeatureValue
    ]

-- | Constructor for 'RDSDBInstanceProcessorFeature' containing required
-- fields as arguments.
rdsdbInstanceProcessorFeature
  :: RDSDBInstanceProcessorFeature
rdsdbInstanceProcessorFeature  =
  RDSDBInstanceProcessorFeature
  { _rDSDBInstanceProcessorFeatureName = Nothing
  , _rDSDBInstanceProcessorFeatureValue = Nothing
  }

-- | http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbinstance-processorfeature.html#cfn-rds-dbinstance-processorfeature-name
rdsdbipfName :: Lens' RDSDBInstanceProcessorFeature (Maybe (Val Text))
rdsdbipfName = lens _rDSDBInstanceProcessorFeatureName (\s a -> s { _rDSDBInstanceProcessorFeatureName = a })

-- | http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbinstance-processorfeature.html#cfn-rds-dbinstance-processorfeature-value
rdsdbipfValue :: Lens' RDSDBInstanceProcessorFeature (Maybe (Val Text))
rdsdbipfValue = lens _rDSDBInstanceProcessorFeatureValue (\s a -> s { _rDSDBInstanceProcessorFeatureValue = a })


text:
    Contains minor help functions to improve on lua

]]--

-- add startswith function to string object
startsWith = function(self, piece)
  return string.sub(self, 1, string.len(piece)) == piece
end

rawset(_G.string, "startsWith", startsWith)

-- create color gradient. taken from http://love2d.org/wiki/Gradients
-- argument: gradient {color1, color2, color3, ..., direction = 'horizontal' or 'vertical'}
function gradient(colors)
    local direction = colors.direction or "horizontal"
    if direction == "horizontal" then
        direction = true
    elseif direction == "vertical" then
        direction = false
    else
        error("Invalid direction '" .. tostring(direction) "' for gradient.  Horizontal or vertical expected.")
    end
    local result = love.image.newImageData(direction and 1 or #colors, direction and #colors or 1)
    for i, color in ipairs(colors) do
        local x, y
        if direction then
            x, y = 0, i - 1
        else
            x, y = i - 1, 0
        end
        result:setPixel(x, y, color[1], color[2], color[3], color[4] or 255)
    end
    result = love.graphics.newImage(result)
    result:setFilter('linear', 'linear')
    return result
end

function drawinrect(img, x, y, w, h, r, ox, oy, kx, ky)
    return -- tail call for a little extra bit of efficiency
    love.graphics.draw(img, x, y, r, w / img:getWidth(), h / img:getHeight(), ox, oy, kx, ky)
end


text:
<!DOCTYPE html>

    <title>Json&XML在线转换及格式化验证工具 - 星柒天iTanken</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="HandheldFriendly" content="True" />
    <meta name="MobileOptimized" content="320" />
    <meta http-equiv="Cache-Control" content="max-age=7200" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="robots" content="all" />
    <meta name="author" content="StarSevenSky" />
    <meta name="keywords" content="json,json在线解析,json格式化,json格式验证,json转xml,xml转json"/>
    <meta name="description" content=""/>
    <link href="http://cdn.bootcss.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
    <link href="http://cdn.bootcss.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
    <link href="res/base.css" rel="stylesheet">

            itanken.cn/iTools/jsonx

                更多工具

        <textarea id="json-src" placeholder="请在此输入json字符串或XML字符串..."   class="form-control adapter_height"  style="height:550px;padding:20px;border:0;border-right:solid 1px #ddd;border-bottom:solid 1px #ddd;border-radius:0;resize: none; outline:none;">    {"tools": [
    { "name":"zixizixi" , "site":"http://zixizixi.com" },
    { "name":"itanken" , "site":"http://itanken.cn" },
    { "name":"github" , "site":"http://github.com" }
    ]
    }</textarea>

        <form id="form-save" method="POST"><input type="hidden" value="" id="txt-content" name="content"></form>

2014-2016 itanken.cn Code from Json.cn


text:
	<title>James Villiers's panel show appearances</title>

	<link rel="stylesheet" media="all" href="../style.css" type="text/css"/>

James Villiers's panel show appearances

James Villiers (born 1933-09-29[ref]) has appeared in 2 episodes between 1971-1971.  James Villiers on IMDB. James Villiers on Wikipedia.

1971

1971-10-25 / Call My Bluff

1971-10-18 / Call My Bluff


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using Xunit;

namespace WebApiDoodle.Web.Test {

    public class NullUpCurrentPrincipalAttribute : BeforeAfterTestAttribute {

        public override void Before(MethodInfo methodUnderTest) {

            Thread.CurrentPrincipal = null;
        }
    }
}


text:
package samples.testng.agent;

import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.Assert;
import org.testng.annotations.Test;
import samples.singleton.StaticHelper;
import samples.singleton.StaticService;

import static org.easymock.EasyMock.expect;
import static org.powermock.api.easymock.PowerMock.*;

/**
 * Test class to demonstrate static, static+final, static+native and
 * static+final+native methods mocking.
 *
 * @author Johan Haleby
 * @author Jan Kronquist
 */
@PrepareForTest( { StaticService.class, StaticHelper.class })
public class MockStaticTest {

	@Test
	public void testMockStatic() throws Exception {
		mockStatic(StaticService.class);
		String expected = "Hello altered World";
		expect(StaticService.say("hello")).andReturn("Hello altered World");
		replay(StaticService.class);

		String actual = StaticService.say("hello");

		verify(StaticService.class);
		Assert.assertEquals(expected, actual);

		// Singleton still be mocked by now.
		try {
			StaticService.say("world");
			Assert.fail("Should throw AssertionError!");
		} catch (AssertionError e) {
			Assert.assertEquals("\n  Unexpected method call say(\"world\"):", e.getMessage());
		}
	}

	@Test
	public void testMockStaticFinal() throws Exception {
		mockStatic(StaticService.class);
		String expected = "Hello altered World";
		expect(StaticService.sayFinal("hello")).andReturn("Hello altered World");
		replay(StaticService.class);

		String actual = StaticService.sayFinal("hello");

		verify(StaticService.class);
		Assert.assertEquals(expected, actual);

		// Singleton still be mocked by now.
		try {
			StaticService.sayFinal("world");
			Assert.fail("Should throw AssertionError!");
		} catch (AssertionError e) {
			Assert.assertEquals("\n  Unexpected method call sayFinal(\"world\"):", e.getMessage());
		}
	}
}