<commit_before>/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <graphene/account_history/account_history_plugin.hpp>

#include <graphene/app/impacted.hpp>

#include <graphene/chain/account_evaluator.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/config.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/evaluator.hpp>
#include <graphene/chain/operation_history_object.hpp>
#include <graphene/chain/transaction_evaluation_state.hpp>

#include <fc/smart_ref_impl.hpp>
#include <fc/thread/thread.hpp>

namespace graphene { namespace account_history {

namespace detail
{

class account_history_plugin_impl
{
   public:
      account_history_plugin_impl(account_history_plugin& _plugin)
         : _self( _plugin )
      { }
      virtual ~account_history_plugin_impl();

      /** this method is called as a callback after a block is applied
       * and will process/index all operations that were applied in the block.
       */
      void update_account_histories( const signed_block& b );

      graphene::chain::database& database()
      {
         return _self.database();
      }

      account_history_plugin& _self;
      flat_set<account_id_type> _tracked_accounts;
	  flat_set<account_id_type> _full_history_accounts;
      bool _partial_operations = false;
      primary_index< simple_index< operation_history_object > >* _oho_index;
      uint32_t _max_ops_per_account = -1;
   private:
      /** add one history record, then check and remove the earliest history record */
      void add_account_history( const account_id_type account_id, const operation_history_id_type op_id );

};

account_history_plugin_impl::~account_history_plugin_impl()
{
   return;
}

void account_history_plugin_impl::update_account_histories( const signed_block& b )
{
   graphene::chain::database& db = database();
   const vector<optional< operation_history_object > >& hist = db.get_applied_operations();
   for( const optional< operation_history_object >& o_op : hist )
   {
      optional<operation_history_object> oho;

      auto create_oho = [&]() {
         return optional<operation_history_object>( db.create<operation_history_object>( [&]( operation_history_object& h )
         {
            if( o_op.valid() )
               h = *o_op;
         } ) );
      };

      if( !o_op.valid() || ( _max_ops_per_account == 0 && _partial_operations ) )
      {
         // Note: the 2nd and 3rd checks above are for better performance, when the db is not clean,
         //       they will break consistency of account_stats.total_ops and removed_ops and most_recent_op
         _oho_index->use_next_id();
         continue;
      }
      else if( !_partial_operations )
         // add to the operation history index
         oho = create_oho();

      const operation_history_object& op = *o_op;

      // get the set of accounts this operation applies to
      flat_set<account_id_type> impacted;
      vector<authority> other;
      operation_get_required_authorities( op.op, impacted, impacted, other ); // fee_payer is added here

      if( op.op.which() == operation::tag< account_create_operation >::value )
         impacted.insert( op.result.get<object_id_type>() );
      else
         graphene::app::operation_get_impacted_accounts( op.op, impacted );

      for( auto& a : other )
         for( auto& item : a.account_auths )
            impacted.insert( item.first );

      // be here, either _max_ops_per_account > 0, or _partial_operations == false, or both
      // if _partial_operations == false, oho should have been created above
      // so the only case should be checked here is:
      //    whether need to create oho if _max_ops_per_account > 0 and _partial_operations == true

      // for each operation this account applies to that is in the config link it into the history
      if( _tracked_accounts.size() == 0 ) // tracking all accounts
      {
         // if tracking all accounts, when impacted is not empty (although it will always be),
         //    still need to create oho if _max_ops_per_account > 0 and _partial_operations == true
         //    so always need to create oho if not done
         if (!impacted.empty() && !oho.valid()) { oho = create_oho(); }

         if( _max_ops_per_account > 0 )
         {
            // Note: the check above is for better performance, when the db is not clean,
            //       it breaks consistency of account_stats.total_ops and removed_ops and most_recent_op,
            //       but it ensures it's safe to remove old entries in add_account_history(...)
            for( auto& account_id : impacted )
            {
               // we don't do index_account_keys here anymore, because
               // that indexing now happens in observers' post_evaluate()

               // add history
               add_account_history( account_id, oho->id );
            }
         }
      }
      else // tracking a subset of accounts
      {
         // whether need to create oho if _max_ops_per_account > 0 and _partial_operations == true ?
         // the answer: only need to create oho if a tracked account is impacted and need to save history

         if( _max_ops_per_account > 0 )
         {
            // Note: the check above is for better performance, when the db is not clean,
            //       it breaks consistency of account_stats.total_ops and removed_ops and most_recent_op,
            //       but it ensures it's safe to remove old entries in add_account_history(...)
            for( auto account_id : _tracked_accounts )
            {
               if( impacted.find( account_id ) != impacted.end() )
               {
                  if (!oho.valid()) { oho = create_oho(); }
                  // add history
                  add_account_history( account_id, oho->id );
               }
            }
         }
      }
      if (_partial_operations && ! oho.valid())
         _oho_index->use_next_id();
   }
}

void account_history_plugin_impl::add_account_history( const account_id_type account_id, const operation_history_id_type op_id )
{
   graphene::chain::database& db = database();
   const auto& stats_obj = account_id(db).statistics(db);
   // add new entry
   const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){
       obj.operation_id = op_id;
       obj.account = account_id;
       obj.sequence = stats_obj.total_ops + 1;
       obj.next = stats_obj.most_recent_op;
   });
   db.modify( stats_obj, [&]( account_statistics_object& obj ){
       obj.most_recent_op = ath.id;
       obj.total_ops = ath.sequence;
   });

   flat_set<account_id_type>& full_accounts = _self.full_history_accounts();
   if (full_accounts.count(account_id)){
	   uint32_t num = stats_obj.total_ops - stats_obj.removed_ops;
	   if (num > 100){
		   account_object obj = account_id(db);
		   std::cout << "name of account : " << obj.name <<std::endl;
		   std::cout << "num of history : " << num << std::endl;
	   }
	   return;
   }
   // remove the earliest account history entry if too many
   // _max_ops_per_account is guaranteed to be non-zero outside
   if( stats_obj.total_ops - stats_obj.removed_ops > _max_ops_per_account )
   {
      // look for the earliest entry
      const auto& his_idx = db.get_index_type<account_transaction_history_index>();
      const auto& by_seq_idx = his_idx.indices().get<by_seq>();
      auto itr = by_seq_idx.lower_bound( boost::make_tuple( account_id, 0 ) );
      // make sure don't remove the one just added
      if( itr != by_seq_idx.end() && itr->account == account_id && itr->id != ath.id )
      {
         // if found, remove the entry, and adjust account stats object
         const auto remove_op_id = itr->operation_id;
         const auto itr_remove = itr;
         ++itr;
         db.remove( *itr_remove );
         db.modify( stats_obj, [&]( account_statistics_object& obj ){
             obj.removed_ops = obj.removed_ops + 1;
         });
         // modify previous node's next pointer
         // this should be always true, but just have a check here
         if( itr != by_seq_idx.end() && itr->account == account_id )
         {
            db.modify( *itr, [&]( account_transaction_history_object& obj ){
               obj.next = account_transaction_history_id_type();
            });
         }
         // else need to modify the head pointer, but it shouldn't be true

         // remove the operation history entry (1.11.x) if configured and no reference left
         if( _partial_operations )
         {
            // check for references
            const auto& by_opid_idx = his_idx.indices().get<by_opid>();
            if( by_opid_idx.find( remove_op_id ) == by_opid_idx.end() )
            {
               // if no reference, remove
               db.remove( remove_op_id(db) );
            }
         }
      }
   }
}

} // end namespace detail

account_history_plugin::account_history_plugin() :
   my( new detail::account_history_plugin_impl(*this) )
{
}

account_history_plugin::~account_history_plugin()
{
}

std::string account_history_plugin::plugin_name()const
{
   return "account_history";
}

void account_history_plugin::plugin_set_program_options(
   boost::program_options::options_description& cli,
   boost::program_options::options_description& cfg
   )
{
   cli.add_options()
         ("track-account", boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(), "Account ID to track history for (may specify multiple times)")
         ("partial-operations", boost::program_options::value<bool>(), "Keep only those operations in memory that are related to account history tracking")
         ("max-ops-per-account", boost::program_options::value<uint32_t>(), "Maximum number of operations per account will be kept in memory")
		 ("full-history", boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(), "Accounts have full history")
         ;
   cfg.add(cli);
}

template<typename T>
T dejsonify_test(const string& s)
{
	return fc::json::from_string(s).as<T>();
}

void account_history_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{
	database().applied_block.connect([&](const signed_block& b){ my->update_account_histories(b); });
	my->_oho_index = database().add_index< primary_index< simple_index< operation_history_object > > >();
	database().add_index< primary_index< account_transaction_history_index > >();

	LOAD_VALUE_SET(options, "track-account", my->_tracked_accounts, graphene::chain::account_id_type);
	if (options.count("partial-operations")) {
		my->_partial_operations = options["partial-operations"].as<bool>();
	}
	if (options.count("max-ops-per-account")) {
		my->_max_ops_per_account = options["max-ops-per-account"].as<uint32_t>();
	}
	LOAD_VALUE_SET(options, "full-history", my->_full_history_accounts, graphene::chain::account_id_type);

	if (options.count("full-history")) {
			const std::vector<std::string>& ops = options["full-history"].as<std::vector<std::string>>();
			std::transform(ops.begin(), ops.end(), std::inserter(my->_full_history_accounts, my->_full_history_accounts.end()), &graphene::app::dejsonify<graphene::chain::account_id_type>);
	}

	//if (options.count("full-history")){
	//	const std::vector<std::string>& account_ids = options["full-history"].as<std::vector<std::string>>();
	//	graphene::chain::database& db = database();
	//	const auto& accounts_by_name = db.get_index_type<account_index>().indices().get<by_name>();
	//	my->_full_history_accounts.clear();
	//	for (const auto & name : account_ids){
	//		auto itr = accounts_by_name.find(name);
	//		if (itr != accounts_by_name.end())
	//			my->_full_history_accounts.insert(itr->get_id());
	//	}
	//}
}

void account_history_plugin::plugin_startup()
{
}

flat_set<account_id_type> account_history_plugin::tracked_accounts() const
{
   return my->_tracked_accounts;
}

flat_set<account_id_type> account_history_plugin::full_history_accounts() const
{
	return my->_full_history_accounts;
}

} }
<commit_msg>fix bug graphene::chain::account_id_type from string<commit_after>/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <graphene/account_history/account_history_plugin.hpp>

#include <graphene/app/impacted.hpp>

#include <graphene/chain/account_evaluator.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/config.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/evaluator.hpp>
#include <graphene/chain/operation_history_object.hpp>
#include <graphene/chain/transaction_evaluation_state.hpp>

#include <fc/smart_ref_impl.hpp>
#include <fc/thread/thread.hpp>

namespace graphene { namespace account_history {

namespace detail
{

class account_history_plugin_impl
{
   public:
      account_history_plugin_impl(account_history_plugin& _plugin)
         : _self( _plugin )
      { }
      virtual ~account_history_plugin_impl();

      /** this method is called as a callback after a block is applied
       * and will process/index all operations that were applied in the block.
       */
      void update_account_histories( const signed_block& b );

      graphene::chain::database& database()
      {
         return _self.database();
      }

      account_history_plugin& _self;
      flat_set<account_id_type> _tracked_accounts;
	  flat_set<account_id_type> _full_history_accounts;
      bool _partial_operations = false;
      primary_index< simple_index< operation_history_object > >* _oho_index;
      uint32_t _max_ops_per_account = -1;
   private:
      /** add one history record, then check and remove the earliest history record */
      void add_account_history( const account_id_type account_id, const operation_history_id_type op_id );

};

account_history_plugin_impl::~account_history_plugin_impl()
{
   return;
}

void account_history_plugin_impl::update_account_histories( const signed_block& b )
{
   graphene::chain::database& db = database();
   const vector<optional< operation_history_object > >& hist = db.get_applied_operations();
   for( const optional< operation_history_object >& o_op : hist )
   {
      optional<operation_history_object> oho;

      auto create_oho = [&]() {
         return optional<operation_history_object>( db.create<operation_history_object>( [&]( operation_history_object& h )
         {
            if( o_op.valid() )
               h = *o_op;
         } ) );
      };

      if( !o_op.valid() || ( _max_ops_per_account == 0 && _partial_operations ) )
      {
         // Note: the 2nd and 3rd checks above are for better performance, when the db is not clean,
         //       they will break consistency of account_stats.total_ops and removed_ops and most_recent_op
         _oho_index->use_next_id();
         continue;
      }
      else if( !_partial_operations )
         // add to the operation history index
         oho = create_oho();

      const operation_history_object& op = *o_op;

      // get the set of accounts this operation applies to
      flat_set<account_id_type> impacted;
      vector<authority> other;
      operation_get_required_authorities( op.op, impacted, impacted, other ); // fee_payer is added here

      if( op.op.which() == operation::tag< account_create_operation >::value )
         impacted.insert( op.result.get<object_id_type>() );
      else
         graphene::app::operation_get_impacted_accounts( op.op, impacted );

      for( auto& a : other )
         for( auto& item : a.account_auths )
            impacted.insert( item.first );

      // be here, either _max_ops_per_account > 0, or _partial_operations == false, or both
      // if _partial_operations == false, oho should have been created above
      // so the only case should be checked here is:
      //    whether need to create oho if _max_ops_per_account > 0 and _partial_operations == true

      // for each operation this account applies to that is in the config link it into the history
      if( _tracked_accounts.size() == 0 ) // tracking all accounts
      {
         // if tracking all accounts, when impacted is not empty (although it will always be),
         //    still need to create oho if _max_ops_per_account > 0 and _partial_operations == true
         //    so always need to create oho if not done
         if (!impacted.empty() && !oho.valid()) { oho = create_oho(); }

         if( _max_ops_per_account > 0 )
         {
            // Note: the check above is for better performance, when the db is not clean,
            //       it breaks consistency of account_stats.total_ops and removed_ops and most_recent_op,
            //       but it ensures it's safe to remove old entries in add_account_history(...)
            for( auto& account_id : impacted )
            {
               // we don't do index_account_keys here anymore, because
               // that indexing now happens in observers' post_evaluate()

               // add history
               add_account_history( account_id, oho->id );
            }
         }
      }
      else // tracking a subset of accounts
      {
         // whether need to create oho if _max_ops_per_account > 0 and _partial_operations == true ?
         // the answer: only need to create oho if a tracked account is impacted and need to save history

         if( _max_ops_per_account > 0 )
         {
            // Note: the check above is for better performance, when the db is not clean,
            //       it breaks consistency of account_stats.total_ops and removed_ops and most_recent_op,
            //       but it ensures it's safe to remove old entries in add_account_history(...)
            for( auto account_id : _tracked_accounts )
            {
               if( impacted.find( account_id ) != impacted.end() )
               {
                  if (!oho.valid()) { oho = create_oho(); }
                  // add history
                  add_account_history( account_id, oho->id );
               }
            }
         }
      }
      if (_partial_operations && ! oho.valid())
         _oho_index->use_next_id();
   }
}

void account_history_plugin_impl::add_account_history( const account_id_type account_id, const operation_history_id_type op_id )
{
   graphene::chain::database& db = database();
   const auto& stats_obj = account_id(db).statistics(db);
   // add new entry
   const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){
       obj.operation_id = op_id;
       obj.account = account_id;
       obj.sequence = stats_obj.total_ops + 1;
       obj.next = stats_obj.most_recent_op;
   });
   db.modify( stats_obj, [&]( account_statistics_object& obj ){
       obj.most_recent_op = ath.id;
       obj.total_ops = ath.sequence;
   });

   const flat_set<account_id_type>& full_accounts = _self.full_history_accounts();
   if (full_accounts.count(account_id)){
	   uint32_t num = stats_obj.total_ops - stats_obj.removed_ops;
	   if (num > 100){
		   account_object obj = account_id(db);
		   std::cout << "name of account : " << obj.name <<std::endl;
		   std::cout << "num of history : " << num << std::endl;
	   }
	   return;
   }
   // remove the earliest account history entry if too many
   // _max_ops_per_account is guaranteed to be non-zero outside
   if( stats_obj.total_ops - stats_obj.removed_ops > _max_ops_per_account )
   {
      // look for the earliest entry
      const auto& his_idx = db.get_index_type<account_transaction_history_index>();
      const auto& by_seq_idx = his_idx.indices().get<by_seq>();
      auto itr = by_seq_idx.lower_bound( boost::make_tuple( account_id, 0 ) );
      // make sure don't remove the one just added
      if( itr != by_seq_idx.end() && itr->account == account_id && itr->id != ath.id )
      {
         // if found, remove the entry, and adjust account stats object
         const auto remove_op_id = itr->operation_id;
         const auto itr_remove = itr;
         ++itr;
         db.remove( *itr_remove );
         db.modify( stats_obj, [&]( account_statistics_object& obj ){
             obj.removed_ops = obj.removed_ops + 1;
         });
         // modify previous node's next pointer
         // this should be always true, but just have a check here
         if( itr != by_seq_idx.end() && itr->account == account_id )
         {
            db.modify( *itr, [&]( account_transaction_history_object& obj ){
               obj.next = account_transaction_history_id_type();
            });
         }
         // else need to modify the head pointer, but it shouldn't be true

         // remove the operation history entry (1.11.x) if configured and no reference left
         if( _partial_operations )
         {
            // check for references
            const auto& by_opid_idx = his_idx.indices().get<by_opid>();
            if( by_opid_idx.find( remove_op_id ) == by_opid_idx.end() )
            {
               // if no reference, remove
               db.remove( remove_op_id(db) );
            }
         }
      }
   }
}

} // end namespace detail

account_history_plugin::account_history_plugin() :
   my( new detail::account_history_plugin_impl(*this) )
{
}

account_history_plugin::~account_history_plugin()
{
}

std::string account_history_plugin::plugin_name()const
{
   return "account_history";
}

void account_history_plugin::plugin_set_program_options(
   boost::program_options::options_description& cli,
   boost::program_options::options_description& cfg
   )
{
   cli.add_options()
         ("track-account", boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(), "Account ID to track history for (may specify multiple times)")
         ("partial-operations", boost::program_options::value<bool>(), "Keep only those operations in memory that are related to account history tracking")
         ("max-ops-per-account", boost::program_options::value<uint32_t>(), "Maximum number of operations per account will be kept in memory")
		 ("full-history", boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(), "Accounts have full history")
         ;
   cfg.add(cli);
}

template<typename T>
T dejsonify_test(const string& s)
{
	return fc::json::from_string(s).as<T>();
}

void account_history_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{
	database().applied_block.connect([&](const signed_block& b){ my->update_account_histories(b); });
	my->_oho_index = database().add_index< primary_index< simple_index< operation_history_object > > >();
	database().add_index< primary_index< account_transaction_history_index > >();

	LOAD_VALUE_SET(options, "track-account", my->_tracked_accounts, graphene::chain::account_id_type);
	if (options.count("partial-operations")) {
		my->_partial_operations = options["partial-operations"].as<bool>();
	}
	if (options.count("max-ops-per-account")) {
		my->_max_ops_per_account = options["max-ops-per-account"].as<uint32_t>();
	}

	if (options.count("full-history")) {
			const std::vector<std::string>& ops = options["full-history"].as<std::vector<std::string>>();
    std::transform(ops.begin(), ops.end(), std::inserter(my->_full_history_accounts, my->_full_history_accounts.end()), [](string s){
      return fc::variant(s).as<graphene::chain::account_id_type>();
    });
	}

	//if (options.count("full-history")){
	//	const std::vector<std::string>& account_ids = options["full-history"].as<std::vector<std::string>>();
	//	graphene::chain::database& db = database();
	//	const auto& accounts_by_name = db.get_index_type<account_index>().indices().get<by_name>();
	//	my->_full_history_accounts.clear();
	//	for (const auto & name : account_ids){
	//		auto itr = accounts_by_name.find(name);
	//		if (itr != accounts_by_name.end())
	//			my->_full_history_accounts.insert(itr->get_id());
	//	}
	//}
}

void account_history_plugin::plugin_startup()
{
}

flat_set<account_id_type> account_history_plugin::tracked_accounts() const
{
   return my->_tracked_accounts;
}

flat_set<account_id_type> account_history_plugin::full_history_accounts() const
{
	return my->_full_history_accounts;
}

} }
<|endoftext|>


<commit_before>//
// Copyright (c) 2018 The nanoFramework project contributors
// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved
// Portions Copyright (c) Microsoft Corporation.  All rights reserved.
// See LICENSE file in the project root for full license information.
//

#include <ssl.h>
#include "mbedtls.h"
#include "mbedtls/debug.h"

bool ssl_generic_init_internal( int sslMode, int sslVerify, const char* certificate,
    int certLength, const char* certPassword, int& sslContextHandle, bool isServer )
{
    (void)sslMode;
    (void)certPassword;

    int sslContexIndex = -1;
    int authMode = MBEDTLS_SSL_VERIFY_NONE;
    int endpoint = 0;

    ///////////////////////
    mbedtls_x509_crt ca;

    mbedTLS_NFContext* context;

    ///////////////////////

    for(uint32_t i=0; i<ARRAYSIZE(g_SSL_Driver.m_sslContextArray); i++)
    {
        if(g_SSL_Driver.m_sslContextArray[i].SslContext == NULL)
        {
            sslContexIndex = i;
            break;
        }
    }

    if(sslContexIndex == -1) return FALSE;

    // create and init mbedTLS nanoFramework context
    // this needs to be freed in ssl_exit_context_internal
    context = (mbedTLS_NFContext*)platform_malloc(sizeof(mbedTLS_NFContext));
    if(context == NULL)
    {
        goto error;
    }

    // allocate memory for net context
    context->server_fd = (mbedtls_net_context*)platform_malloc(sizeof(mbedtls_net_context));
    if(context->server_fd == NULL)
    {
        goto error;
    }

    if(isServer)
    {
        endpoint = MBEDTLS_SSL_IS_SERVER;

        // TODO NOT IMPLEMENTED
        // // TODO:  we should be setting up the CA list
    }
    else
    {
        endpoint = MBEDTLS_SSL_IS_CLIENT;
    }

    // create and init CTR_DRBG
    // this needs to be freed in ssl_exit_context_internal
    context->ctr_drbg = (mbedtls_ctr_drbg_context*)platform_malloc(sizeof(mbedtls_ctr_drbg_context));
    if(context->ctr_drbg == NULL)
    {
        goto error;
    }
    mbedtls_ctr_drbg_init( context->ctr_drbg );

    // create and init SSL context
    // this needs to be freed in ssl_exit_context_internal
    context->ssl = (mbedtls_ssl_context*)platform_malloc(sizeof(mbedtls_ssl_context));
    if(context->ssl == NULL)
    {
        goto error;
    }
    mbedtls_ssl_init(context->ssl);

    // create and init SSL configuration
    // this needs to be freed in ssl_exit_context_internal
    context->conf = (mbedtls_ssl_config*)platform_malloc(sizeof(mbedtls_ssl_config));
    if(context->conf == NULL)
    {
        goto error;
    }

    mbedtls_ssl_config_init( context->conf );
    mbedtls_x509_crt_init( &ca );

    // create and init entropy context
    // this needs to be freed in ssl_exit_context_internal
    context->entropy = (mbedtls_entropy_context*)platform_malloc(sizeof(mbedtls_entropy_context));
    if(context->entropy == NULL)
    {
        goto error;
    }
    mbedtls_entropy_init( context->entropy );

    // TODO: review if we can add some instance-unique data to the custom argument bellow
    if( mbedtls_ctr_drbg_seed( context->ctr_drbg, mbedtls_entropy_func, context->entropy, NULL, 0 ) != 0 )
    {
        // ctr_drbg_seed_failed
        goto error;
    }

    if( mbedtls_ssl_config_defaults( context->conf,
                endpoint,
                MBEDTLS_SSL_TRANSPORT_STREAM,
                MBEDTLS_SSL_PRESET_DEFAULT ) != 0 )
    {
        // ssl_config_defaults_failed
        goto error;
    }

    // configure protocol
    switch((SslProtocols)sslMode)
    {
        case SslProtocols_SSLv3:
            context->conf->min_major_ver = 3;
            context->conf->min_minor_ver = 0;
            context->conf->max_major_ver = 3;
            context->conf->max_minor_ver = 0;
            break;

        case SslProtocols_TLSv1:
            context->conf->min_major_ver = 1;
            context->conf->min_minor_ver = 0;
            context->conf->max_major_ver = 1;
            context->conf->max_minor_ver = 0;
            break;

        case SslProtocols_TLSv11:
            context->conf->min_major_ver = 1;
            context->conf->min_minor_ver = 1;
            context->conf->max_major_ver = 1;
            context->conf->max_minor_ver = 1;
            break;

        case SslProtocols_TLSv12:
            context->conf->min_major_ver = 1;
            context->conf->min_minor_ver = 2;
            context->conf->max_major_ver = 1;
            context->conf->max_minor_ver = 2;
            break;

        default:
            // shouldn't reach here!
            return FALSE;
    }

    mbedtls_ssl_conf_rng( context->conf, mbedtls_ctr_drbg_random, context->ctr_drbg );

    // parse certificate if passed
    if(certificate != NULL && certLength > 0)
    {
        if(mbedtls_x509_crt_parse( &ca, (const unsigned char*)certificate, certLength ) != 0)
        {
            // x509_crt_parse_failed
            goto error;
        }

        mbedtls_ssl_conf_ca_chain( context->conf, &ca, NULL );
        mbedtls_ssl_conf_authmode( context->conf, MBEDTLS_SSL_VERIFY_REQUIRED );
    }

    // set certificate verification
    // the current options provided by mbed TLS are only verify or don't verify
    if((SslVerification)sslVerify == SslVerification_CertificateRequired)
    {
        authMode = MBEDTLS_SSL_VERIFY_REQUIRED;
    }
    mbedtls_ssl_conf_authmode( context->conf, authMode );

    // set bellow the threshold level for debug messages
    // check mbed TLS mbedtls/debug.h header for details.
    // Debug levels:
    // 0 No debug
    // 1 Error
    // 2 State change
    // 3 Informational
    // 4 Verbose
    mbedtls_debug_set_threshold( 2 );
    mbedtls_ssl_conf_dbg( context->conf, nf_debug, stdout );

    if( mbedtls_ssl_setup( context->ssl, context->conf ) != 0 )
    {
        // ssl_setup_failed
        goto error;
    }

    //////////////////////////////////////

    g_SSL_Driver.m_sslContextArray[sslContexIndex].SslContext = context;
    g_SSL_Driver.m_sslContextCount++;

    sslContextHandle = sslContexIndex;

    return TRUE;

error:

    // check for any memory allocation that needs to be freed before exiting
    if(context->ssl != NULL) platform_free(context->ssl);
    if(context->conf != NULL) platform_free(context->conf);
    if(context->entropy != NULL) platform_free(context->entropy);
    if(context->ctr_drbg != NULL) platform_free(context->ctr_drbg);
    if(context->server_fd != NULL) platform_free(context->server_fd);
    if(context != NULL) platform_free(context);

    return FALSE;
}
<commit_msg>Fix certificate parsing in mbed TLS init<commit_after>//
// Copyright (c) 2018 The nanoFramework project contributors
// Portions Copyright (c) 2006-2015, ARM Limited, All Rights Reserved
// Portions Copyright (c) Microsoft Corporation.  All rights reserved.
// See LICENSE file in the project root for full license information.
//

#include <ssl.h>
#include "mbedtls.h"
#include "mbedtls/debug.h"

bool ssl_generic_init_internal( int sslMode, int sslVerify, const char* certificate,
    int certLength, const char* certPassword, int& sslContextHandle, bool isServer )
{
    (void)sslMode;
    (void)certPassword;

    int sslContexIndex = -1;
    int authMode = MBEDTLS_SSL_VERIFY_NONE;
    int endpoint = 0;

    ///////////////////////
    mbedtls_x509_crt ca;

    mbedTLS_NFContext* context;

    ///////////////////////

    for(uint32_t i=0; i<ARRAYSIZE(g_SSL_Driver.m_sslContextArray); i++)
    {
        if(g_SSL_Driver.m_sslContextArray[i].SslContext == NULL)
        {
            sslContexIndex = i;
            break;
        }
    }

    if(sslContexIndex == -1) return FALSE;

    // create and init mbedTLS nanoFramework context
    // this needs to be freed in ssl_exit_context_internal
    context = (mbedTLS_NFContext*)platform_malloc(sizeof(mbedTLS_NFContext));
    if(context == NULL)
    {
        goto error;
    }

    // allocate memory for net context
    context->server_fd = (mbedtls_net_context*)platform_malloc(sizeof(mbedtls_net_context));
    if(context->server_fd == NULL)
    {
        goto error;
    }

    if(isServer)
    {
        endpoint = MBEDTLS_SSL_IS_SERVER;

        // TODO NOT IMPLEMENTED
        // // TODO:  we should be setting up the CA list
    }
    else
    {
        endpoint = MBEDTLS_SSL_IS_CLIENT;
    }

    // create and init CTR_DRBG
    // this needs to be freed in ssl_exit_context_internal
    context->ctr_drbg = (mbedtls_ctr_drbg_context*)platform_malloc(sizeof(mbedtls_ctr_drbg_context));
    if(context->ctr_drbg == NULL)
    {
        goto error;
    }
    mbedtls_ctr_drbg_init( context->ctr_drbg );

    // create and init SSL context
    // this needs to be freed in ssl_exit_context_internal
    context->ssl = (mbedtls_ssl_context*)platform_malloc(sizeof(mbedtls_ssl_context));
    if(context->ssl == NULL)
    {
        goto error;
    }
    mbedtls_ssl_init(context->ssl);

    // create and init SSL configuration
    // this needs to be freed in ssl_exit_context_internal
    context->conf = (mbedtls_ssl_config*)platform_malloc(sizeof(mbedtls_ssl_config));
    if(context->conf == NULL)
    {
        goto error;
    }

    mbedtls_ssl_config_init( context->conf );
    mbedtls_x509_crt_init( &ca );

    // create and init entropy context
    // this needs to be freed in ssl_exit_context_internal
    context->entropy = (mbedtls_entropy_context*)platform_malloc(sizeof(mbedtls_entropy_context));
    if(context->entropy == NULL)
    {
        goto error;
    }
    mbedtls_entropy_init( context->entropy );

    // TODO: review if we can add some instance-unique data to the custom argument bellow
    if( mbedtls_ctr_drbg_seed( context->ctr_drbg, mbedtls_entropy_func, context->entropy, NULL, 0 ) != 0 )
    {
        // ctr_drbg_seed_failed
        goto error;
    }

    if( mbedtls_ssl_config_defaults( context->conf,
                endpoint,
                MBEDTLS_SSL_TRANSPORT_STREAM,
                MBEDTLS_SSL_PRESET_DEFAULT ) != 0 )
    {
        // ssl_config_defaults_failed
        goto error;
    }

    // configure protocol
    switch((SslProtocols)sslMode)
    {
        case SslProtocols_SSLv3:
            context->conf->min_major_ver = 3;
            context->conf->min_minor_ver = 0;
            context->conf->max_major_ver = 3;
            context->conf->max_minor_ver = 0;
            break;

        case SslProtocols_TLSv1:
            context->conf->min_major_ver = 1;
            context->conf->min_minor_ver = 0;
            context->conf->max_major_ver = 1;
            context->conf->max_minor_ver = 0;
            break;

        case SslProtocols_TLSv11:
            context->conf->min_major_ver = 1;
            context->conf->min_minor_ver = 1;
            context->conf->max_major_ver = 1;
            context->conf->max_minor_ver = 1;
            break;

        case SslProtocols_TLSv12:
            context->conf->min_major_ver = 1;
            context->conf->min_minor_ver = 2;
            context->conf->max_major_ver = 1;
            context->conf->max_minor_ver = 2;
            break;

        default:
            // shouldn't reach here!
            return FALSE;
    }

    mbedtls_ssl_conf_rng( context->conf, mbedtls_ctr_drbg_random, context->ctr_drbg );

    // parse certificate if passed
    if(certificate != NULL && certLength > 0)
    {
        // need to add an extra byte here because the mbed TLS API is expecting
        // the buffer length INCLUDING the terminator
        if(mbedtls_x509_crt_parse( &ca, (const unsigned char*)certificate, certLength + 1 ) != 0)
        {
            // x509_crt_parse_failed
            goto error;
        }

        mbedtls_ssl_conf_ca_chain( context->conf, &ca, NULL );
    }

    // set certificate verification
    // the current options provided by mbed TLS are only verify or don't verify
    if((SslVerification)sslVerify == SslVerification_CertificateRequired)
    {
        authMode = MBEDTLS_SSL_VERIFY_REQUIRED;
    }
    mbedtls_ssl_conf_authmode( context->conf, authMode );

    // set bellow the threshold level for debug messages
    // check mbed TLS mbedtls/debug.h header for details.
    // Debug levels:
    // 0 No debug
    // 1 Error
    // 2 State change
    // 3 Informational
    // 4 Verbose
    mbedtls_debug_set_threshold( 2 );
    mbedtls_ssl_conf_dbg( context->conf, nf_debug, stdout );

    if( mbedtls_ssl_setup( context->ssl, context->conf ) != 0 )
    {
        // ssl_setup_failed
        goto error;
    }

    //////////////////////////////////////

    g_SSL_Driver.m_sslContextArray[sslContexIndex].SslContext = context;
    g_SSL_Driver.m_sslContextCount++;

    sslContextHandle = sslContexIndex;

    return TRUE;

error:

    // check for any memory allocation that needs to be freed before exiting
    if(context->ssl != NULL) platform_free(context->ssl);
    if(context->conf != NULL) platform_free(context->conf);
    if(context->entropy != NULL) platform_free(context->entropy);
    if(context->ctr_drbg != NULL) platform_free(context->ctr_drbg);
    if(context->server_fd != NULL) platform_free(context->server_fd);
    if(context != NULL) platform_free(context);

    return FALSE;
}
<|endoftext|>


<commit_before>/**
 *  kmacctcachedimap.cpp
 *
 *  Copyright (c) 2002-2004 Bo Thorsen <bo@klaralvdalens-datakonsult.se>
 *  Copyright (c) 2002-2003 Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of this program with any edition of
 *  the Qt library by Trolltech AS, Norway (or with modified versions
 *  of Qt that use the same license as Qt), and distribute linked
 *  combinations including the two.  You must obey the GNU General
 *  Public License in all respects for all of the code used other than
 *  Qt.  If you modify this file, you may extend this exception to
 *  your version of the file, but you are not obligated to do so.  If
 *  you do not wish to do so, delete this exception statement from
 *  your version.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "kmacctcachedimap.h"
using KMail::SieveConfig;

#include "imapprogressdialog.h"
using KMail::IMAPProgressDialog;

#include "kmbroadcaststatus.h"
#include "kmfoldertree.h"
#include "kmfoldermgr.h"
#include "kmfiltermgr.h"
#include "kmfoldercachedimap.h"
#include "kmmainwin.h"
#include "kmkernel.h"

#include <kio/passdlg.h>
#include <kio/scheduler.h>
#include <kio/slave.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <kapplication.h>
#include <kconfig.h>

KMAcctCachedImap::KMAcctCachedImap( KMAcctMgr* aOwner,
				    const QString& aAccountName )
  : KMail::ImapAccountBase( aOwner, aAccountName ), mFolder( 0 ),
    mProgressDialogEnabled( true ), mSyncActive( false )
{
  // Never EVER set this for the cached IMAP account
  mAutoExpunge = false;

  connect(KMBroadcastStatus::instance(), SIGNAL(signalAbortRequested()),
          this, SLOT(slotAbortRequested()));
  connect(&mIdleTimer, SIGNAL(timeout()), SLOT(slotIdleTimeout()));
}

//-----------------------------------------------------------------------------
KMAcctCachedImap::~KMAcctCachedImap()
{
  killAllJobs( true );
  delete mProgressDlg;
}

//-----------------------------------------------------------------------------
QString KMAcctCachedImap::type() const
{
  return "cachedimap";
}

void KMAcctCachedImap::init() {
  ImapAccountBase::init();

  setProgressDialogEnabled( true );
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::pseudoAssign( const KMAccount * a ) {
  mIdleTimer.stop();
  killAllJobs( true );
  if (mFolder)
  {
    mFolder->setContentState(KMFolderCachedImap::imapNoInformation);
    mFolder->setSubfolderState(KMFolderCachedImap::imapNoInformation);
  }

  setProgressDialogEnabled(static_cast<const KMAcctCachedImap*>(a)->isProgressDialogEnabled());

  ImapAccountBase::pseudoAssign( a );
}

void KMAcctCachedImap::setPrefixHook() {
  if ( mFolder ) mFolder->setImapPath( prefix() );
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::setImapFolder(KMFolderCachedImap *aFolder)
{
  mFolder = aFolder;
  mFolder->setImapPath(mPrefix);
  mFolder->setAccount( this );
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::setAutoExpunge( bool /*aAutoExpunge*/ )
{
  // Never EVER set this for the cached IMAP account
  mAutoExpunge = false;
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::slotSlaveError(KIO::Slave *aSlave, int errorCode,
  const QString &errorMsg)
{
  if (aSlave != mSlave) return;
  if (errorCode == KIO::ERR_SLAVE_DIED) slaveDied();
  if (errorCode == KIO::ERR_COULD_NOT_LOGIN) mAskAgain = TRUE;

  // Note: HEAD has a killAllJobs() call here

  // check if we still display an error
  if ( !mErrorDialogIsActive )
  {
    mErrorDialogIsActive = true;
    KMessageBox::messageBox(kapp->activeWindow(), KMessageBox::Error,
          KIO::buildErrorString(errorCode, errorMsg),
          i18n("Error"));
    mErrorDialogIsActive = false;
  } else
    kdDebug(5006) << "suppressing error:" << errorMsg << endl;

  mSyncActive = false;
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::displayProgress()
{
   mIdle = false;
   mIdleTimer.start( 15000 );
  /*
  if (mProgressEnabled == mapJobData.isEmpty())
  {
    mProgressEnabled = !mapJobData.isEmpty();
    KMBroadcastStatus::instance()->setStatusProgressEnable( "I" + mName,
      mProgressEnabled );
    if (!mProgressEnabled) kmkernel->filterMgr()->deref(true);
  }
  mIdle = FALSE;
  if( mapJobData.isEmpty() )
    mIdleTimer.start(0);
  else
    mIdleTimer.stop();
  int total = 0, done = 0;
  // This is a loop, but it seems that we can currently have only one job at a time in this map.
  for (QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
    it != mapJobData.end(); ++it)
  {
    total += (*it).total; // always ==1 (in kmfoldercachedimap.cpp)
    if( (*it).parent )
      done += static_cast<KMFolderCachedImap*>((*it).parent)->progress();
    else
      done += (*it).done;
  }
  if (total == 0) // can't happen
  {
    mTotal = 0;
    return;
  }
  //if (total > mTotal) mTotal = total;
  //done += mTotal - total;

  KMBroadcastStatus::instance()->setStatusProgressPercent( "I" + mName,
                                                           done / total );

  //100*done / mTotal );
  */
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::slotIdleTimeout()
{
  if (mIdle) // STEFFEN: Hacked this to always disconnect
  {
    if (mSlave) KIO::Scheduler::disconnectSlave(mSlave);
    mSlave = NULL;
    mIdleTimer.stop();
  } else {
    if (mSlave)
    {
      QByteArray packedArgs;
      QDataStream stream( packedArgs, IO_WriteOnly);

      stream << (int) 'N';

      KIO::SimpleJob *job = KIO::special(getUrl(), packedArgs, FALSE);
      KIO::Scheduler::assignJobToSlave(mSlave, job);
      connect(job, SIGNAL(result(KIO::Job *)),
        this, SLOT(slotSimpleResult(KIO::Job *)));
    }
    else mIdleTimer.stop();
  }
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::slotAbortRequested()
{
  killAllJobs();
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::killAllJobs( bool disconnectSlave )
{
  QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
  for (it = mapJobData.begin(); it != mapJobData.end(); ++it)
    if ((*it).parent)
    {
      KMFolderCachedImap *fld = static_cast<KMFolderCachedImap*>((*it).parent->storage());
      fld->resetSyncState();
      fld->setContentState(KMFolderCachedImap::imapNoInformation);
      fld->setSubfolderState(KMFolderCachedImap::imapNoInformation);
      fld->sendFolderComplete(FALSE);
    }
  if (mSlave && mapJobData.begin() != mapJobData.end())
  {
    mSlave->kill();
    mSlave = 0;
  }
  mapJobData.clear();

  // Clear the joblist. Make SURE to stop the job emitting "finished"
  for( QPtrListIterator<CachedImapJob> it( mJobList ); it.current(); ++it )
    it.current()->setPassiveDestructor( true );
  mJobList.setAutoDelete(true);
  mJobList.clear();
  mJobList.setAutoDelete(false);
  displayProgress();

  if ( disconnectSlave && slave() ) {
    KIO::Scheduler::disconnectSlave( slave() );
    mSlave = 0;
  }

  // Finally allow new syncs to proceed
  mSyncActive = false;
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::killJobsForItem(KMFolderTreeItem * fti)
{
  QMap<KIO::Job *, jobData>::Iterator it = mapJobData.begin();
  while (it != mapJobData.end())
  {
    if (it.data().parent == fti->folder())
    {
      killAllJobs();
      break;
    }
    else ++it;
  }
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::slotSimpleResult(KIO::Job * job)
{
  JobIterator it = findJob( job );
  bool quiet = false;
  if (it != mapJobData.end())
  {
    quiet = (*it).quiet;
    removeJob(it);
  }
  if (job->error())
  {
    if (!quiet) slotSlaveError(mSlave, job->error(),
        job->errorText() );
    if (job->error() == KIO::ERR_SLAVE_DIED) slaveDied();
    mSyncActive = false;
  }
  displayProgress();
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::processNewMail( KMFolderCachedImap* folder,
				       bool interactive )
{
  // This should never be set for a cached IMAP account
  mAutoExpunge = false;

  // Guard against parallel runs
  if( mSyncActive ) {
    kdDebug(5006) << "Already processing new mail, won't start again\n";
    return;
  }
  mSyncActive = true;

  emit newMailsProcessed(-1);
  if( interactive && isProgressDialogEnabled() ) {
    imapProgressDialog()->clear();
    imapProgressDialog()->show();
    imapProgressDialog()->raise();
  }

  folder->setAccount(this);
  connect(folder, SIGNAL(folderComplete(KMFolderCachedImap*, bool)),
	  this, SLOT(postProcessNewMail(KMFolderCachedImap*, bool)));
  folder->serverSync( interactive && isProgressDialogEnabled() );
  checkDone(false, 0);
}

void KMAcctCachedImap::postProcessNewMail( KMFolderCachedImap* folder, bool )
{
  mSyncActive = false;
  setCheckingMail( false );
  emit finishedCheck(false);
  disconnect(folder, SIGNAL(folderComplete(KMFolderCachedImap*, bool)),
      this, SLOT(postProcessNewMail(KMFolderCachedImap*, bool)));
  //postProcessNewMail(static_cast<KMFolder*>(folder));
}

//
//
// read/write config
//
//

void KMAcctCachedImap::readConfig( /*const*/ KConfig/*Base*/ & config ) {
  ImapAccountBase::readConfig( config );
  setProgressDialogEnabled( config.readBoolEntry( "progressdialog", true ) );
}

void KMAcctCachedImap::writeConfig( KConfig/*Base*/ & config ) /*const*/ {
  ImapAccountBase::writeConfig( config );
  config.writeEntry( "progressdialog", isProgressDialogEnabled() );
}

void KMAcctCachedImap::invalidateIMAPFolders()
{
  invalidateIMAPFolders( mFolder );
}

void KMAcctCachedImap::invalidateIMAPFolders( KMFolderCachedImap* folder )
{
  if( !folder || !folder->folder() )
    return;

  folder->setAccount(this);

  QStringList strList;
  QValueList<QGuardedPtr<KMFolder> > folderList;
  kmkernel->dimapFolderMgr()->createFolderList( &strList, &folderList,
						folder->folder()->child(), QString::null,
						false );
  QValueList<QGuardedPtr<KMFolder> >::Iterator it;
  mCountRemainChecks = 0;
  mCountLastUnread = 0;

  if( folderList.count() > 0 )
    for( it = folderList.begin(); it != folderList.end(); ++it ) {
      KMFolder *folder = *it;
      if( folder && folder->folderType() == KMFolderTypeCachedImap ) {
	KMFolderCachedImap *cfolder = static_cast<KMFolderCachedImap*>(folder->storage());
	// This invalidates the folder completely
	cfolder->setUidValidity("INVALID");
	cfolder->writeUidCache();
      }
    }
  folder->setUidValidity("INVALID");
  folder->writeUidCache();

  processNewMail(false);
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::listDirectory(QString path, bool onlySubscribed,
    bool secondStep, KMFolder* parent, bool reset)
{
  ImapAccountBase::listDirectory( path, onlySubscribed, secondStep, parent, reset );
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::listDirectory()
{
  mFolder->listDirectory();
}

IMAPProgressDialog* KMAcctCachedImap::imapProgressDialog() const
{
  if( !mProgressDlg ) {
    mProgressDlg = new IMAPProgressDialog( KMKernel::self()->mainWin() );
  }
  return mProgressDlg;
}

#include "kmacctcachedimap.moc"
<commit_msg>Don't disconnect folderComplete signals that have just been connected by the next round of queued mail checks as a result of a finishedCheck signal.<commit_after>/**
 *  kmacctcachedimap.cpp
 *
 *  Copyright (c) 2002-2004 Bo Thorsen <bo@klaralvdalens-datakonsult.se>
 *  Copyright (c) 2002-2003 Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of this program with any edition of
 *  the Qt library by Trolltech AS, Norway (or with modified versions
 *  of Qt that use the same license as Qt), and distribute linked
 *  combinations including the two.  You must obey the GNU General
 *  Public License in all respects for all of the code used other than
 *  Qt.  If you modify this file, you may extend this exception to
 *  your version of the file, but you are not obligated to do so.  If
 *  you do not wish to do so, delete this exception statement from
 *  your version.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "kmacctcachedimap.h"
using KMail::SieveConfig;

#include "imapprogressdialog.h"
using KMail::IMAPProgressDialog;

#include "kmbroadcaststatus.h"
#include "kmfoldertree.h"
#include "kmfoldermgr.h"
#include "kmfiltermgr.h"
#include "kmfoldercachedimap.h"
#include "kmmainwin.h"
#include "kmkernel.h"

#include <kio/passdlg.h>
#include <kio/scheduler.h>
#include <kio/slave.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <kapplication.h>
#include <kconfig.h>

KMAcctCachedImap::KMAcctCachedImap( KMAcctMgr* aOwner,
				    const QString& aAccountName )
  : KMail::ImapAccountBase( aOwner, aAccountName ), mFolder( 0 ),
    mProgressDialogEnabled( true ), mSyncActive( false )
{
  // Never EVER set this for the cached IMAP account
  mAutoExpunge = false;

  connect(KMBroadcastStatus::instance(), SIGNAL(signalAbortRequested()),
          this, SLOT(slotAbortRequested()));
  connect(&mIdleTimer, SIGNAL(timeout()), SLOT(slotIdleTimeout()));
}

//-----------------------------------------------------------------------------
KMAcctCachedImap::~KMAcctCachedImap()
{
  killAllJobs( true );
  delete mProgressDlg;
}

//-----------------------------------------------------------------------------
QString KMAcctCachedImap::type() const
{
  return "cachedimap";
}

void KMAcctCachedImap::init() {
  ImapAccountBase::init();

  setProgressDialogEnabled( true );
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::pseudoAssign( const KMAccount * a ) {
  mIdleTimer.stop();
  killAllJobs( true );
  if (mFolder)
  {
    mFolder->setContentState(KMFolderCachedImap::imapNoInformation);
    mFolder->setSubfolderState(KMFolderCachedImap::imapNoInformation);
  }

  setProgressDialogEnabled(static_cast<const KMAcctCachedImap*>(a)->isProgressDialogEnabled());

  ImapAccountBase::pseudoAssign( a );
}

void KMAcctCachedImap::setPrefixHook() {
  if ( mFolder ) mFolder->setImapPath( prefix() );
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::setImapFolder(KMFolderCachedImap *aFolder)
{
  mFolder = aFolder;
  mFolder->setImapPath(mPrefix);
  mFolder->setAccount( this );
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::setAutoExpunge( bool /*aAutoExpunge*/ )
{
  // Never EVER set this for the cached IMAP account
  mAutoExpunge = false;
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::slotSlaveError(KIO::Slave *aSlave, int errorCode,
  const QString &errorMsg)
{
  if (aSlave != mSlave) return;
  if (errorCode == KIO::ERR_SLAVE_DIED) slaveDied();
  if (errorCode == KIO::ERR_COULD_NOT_LOGIN) mAskAgain = TRUE;

  // Note: HEAD has a killAllJobs() call here

  // check if we still display an error
  if ( !mErrorDialogIsActive )
  {
    mErrorDialogIsActive = true;
    KMessageBox::messageBox(kapp->activeWindow(), KMessageBox::Error,
          KIO::buildErrorString(errorCode, errorMsg),
          i18n("Error"));
    mErrorDialogIsActive = false;
  } else
    kdDebug(5006) << "suppressing error:" << errorMsg << endl;

  mSyncActive = false;
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::displayProgress()
{
   mIdle = false;
   mIdleTimer.start( 15000 );
  /*
  if (mProgressEnabled == mapJobData.isEmpty())
  {
    mProgressEnabled = !mapJobData.isEmpty();
    KMBroadcastStatus::instance()->setStatusProgressEnable( "I" + mName,
      mProgressEnabled );
    if (!mProgressEnabled) kmkernel->filterMgr()->deref(true);
  }
  mIdle = FALSE;
  if( mapJobData.isEmpty() )
    mIdleTimer.start(0);
  else
    mIdleTimer.stop();
  int total = 0, done = 0;
  // This is a loop, but it seems that we can currently have only one job at a time in this map.
  for (QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
    it != mapJobData.end(); ++it)
  {
    total += (*it).total; // always ==1 (in kmfoldercachedimap.cpp)
    if( (*it).parent )
      done += static_cast<KMFolderCachedImap*>((*it).parent)->progress();
    else
      done += (*it).done;
  }
  if (total == 0) // can't happen
  {
    mTotal = 0;
    return;
  }
  //if (total > mTotal) mTotal = total;
  //done += mTotal - total;

  KMBroadcastStatus::instance()->setStatusProgressPercent( "I" + mName,
                                                           done / total );

  //100*done / mTotal );
  */
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::slotIdleTimeout()
{
  if (mIdle) // STEFFEN: Hacked this to always disconnect
  {
    if (mSlave) KIO::Scheduler::disconnectSlave(mSlave);
    mSlave = NULL;
    mIdleTimer.stop();
  } else {
    if (mSlave)
    {
      QByteArray packedArgs;
      QDataStream stream( packedArgs, IO_WriteOnly);

      stream << (int) 'N';

      KIO::SimpleJob *job = KIO::special(getUrl(), packedArgs, FALSE);
      KIO::Scheduler::assignJobToSlave(mSlave, job);
      connect(job, SIGNAL(result(KIO::Job *)),
        this, SLOT(slotSimpleResult(KIO::Job *)));
    }
    else mIdleTimer.stop();
  }
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::slotAbortRequested()
{
  killAllJobs();
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::killAllJobs( bool disconnectSlave )
{
  QMap<KIO::Job*, jobData>::Iterator it = mapJobData.begin();
  for (it = mapJobData.begin(); it != mapJobData.end(); ++it)
    if ((*it).parent)
    {
      KMFolderCachedImap *fld = static_cast<KMFolderCachedImap*>((*it).parent->storage());
      fld->resetSyncState();
      fld->setContentState(KMFolderCachedImap::imapNoInformation);
      fld->setSubfolderState(KMFolderCachedImap::imapNoInformation);
      fld->sendFolderComplete(FALSE);
    }
  if (mSlave && mapJobData.begin() != mapJobData.end())
  {
    mSlave->kill();
    mSlave = 0;
  }
  mapJobData.clear();

  // Clear the joblist. Make SURE to stop the job emitting "finished"
  for( QPtrListIterator<CachedImapJob> it( mJobList ); it.current(); ++it )
    it.current()->setPassiveDestructor( true );
  mJobList.setAutoDelete(true);
  mJobList.clear();
  mJobList.setAutoDelete(false);
  displayProgress();

  if ( disconnectSlave && slave() ) {
    KIO::Scheduler::disconnectSlave( slave() );
    mSlave = 0;
  }

  // Finally allow new syncs to proceed
  mSyncActive = false;
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::killJobsForItem(KMFolderTreeItem * fti)
{
  QMap<KIO::Job *, jobData>::Iterator it = mapJobData.begin();
  while (it != mapJobData.end())
  {
    if (it.data().parent == fti->folder())
    {
      killAllJobs();
      break;
    }
    else ++it;
  }
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::slotSimpleResult(KIO::Job * job)
{
  JobIterator it = findJob( job );
  bool quiet = false;
  if (it != mapJobData.end())
  {
    quiet = (*it).quiet;
    removeJob(it);
  }
  if (job->error())
  {
    if (!quiet) slotSlaveError(mSlave, job->error(),
        job->errorText() );
    if (job->error() == KIO::ERR_SLAVE_DIED) slaveDied();
    mSyncActive = false;
  }
  displayProgress();
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::processNewMail( KMFolderCachedImap* folder,
				       bool interactive )
{
  // This should never be set for a cached IMAP account
  mAutoExpunge = false;

  // Guard against parallel runs
  if( mSyncActive ) {
    kdDebug(5006) << "Already processing new mail, won't start again\n";
    return;
  }
  mSyncActive = true;

  emit newMailsProcessed(-1);
  if( interactive && isProgressDialogEnabled() ) {
    imapProgressDialog()->clear();
    imapProgressDialog()->show();
    imapProgressDialog()->raise();
  }

  folder->setAccount(this);
  connect(folder, SIGNAL(folderComplete(KMFolderCachedImap*, bool)),
	  this, SLOT(postProcessNewMail(KMFolderCachedImap*, bool)));
  folder->serverSync( interactive && isProgressDialogEnabled() );
}

void KMAcctCachedImap::postProcessNewMail( KMFolderCachedImap* folder, bool )
{
  mSyncActive = false;
  disconnect(folder, SIGNAL(folderComplete(KMFolderCachedImap*, bool)),
             this, SLOT(postProcessNewMail(KMFolderCachedImap*, bool)));
  setCheckingMail( false );
  emit finishedCheck(false);
   //postProcessNewMail(static_cast<KMFolder*>(folder));
}

//
//
// read/write config
//
//

void KMAcctCachedImap::readConfig( /*const*/ KConfig/*Base*/ & config ) {
  ImapAccountBase::readConfig( config );
  setProgressDialogEnabled( config.readBoolEntry( "progressdialog", true ) );
}

void KMAcctCachedImap::writeConfig( KConfig/*Base*/ & config ) /*const*/ {
  ImapAccountBase::writeConfig( config );
  config.writeEntry( "progressdialog", isProgressDialogEnabled() );
}

void KMAcctCachedImap::invalidateIMAPFolders()
{
  invalidateIMAPFolders( mFolder );
}

void KMAcctCachedImap::invalidateIMAPFolders( KMFolderCachedImap* folder )
{
  if( !folder || !folder->folder() )
    return;

  folder->setAccount(this);

  QStringList strList;
  QValueList<QGuardedPtr<KMFolder> > folderList;
  kmkernel->dimapFolderMgr()->createFolderList( &strList, &folderList,
						folder->folder()->child(), QString::null,
						false );
  QValueList<QGuardedPtr<KMFolder> >::Iterator it;
  mCountRemainChecks = 0;
  mCountLastUnread = 0;

  if( folderList.count() > 0 )
    for( it = folderList.begin(); it != folderList.end(); ++it ) {
      KMFolder *folder = *it;
      if( folder && folder->folderType() == KMFolderTypeCachedImap ) {
	KMFolderCachedImap *cfolder = static_cast<KMFolderCachedImap*>(folder->storage());
	// This invalidates the folder completely
	cfolder->setUidValidity("INVALID");
	cfolder->writeUidCache();
      }
    }
  folder->setUidValidity("INVALID");
  folder->writeUidCache();

  processNewMail(false);
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::listDirectory(QString path, bool onlySubscribed,
    bool secondStep, KMFolder* parent, bool reset)
{
  ImapAccountBase::listDirectory( path, onlySubscribed, secondStep, parent, reset );
}

//-----------------------------------------------------------------------------
void KMAcctCachedImap::listDirectory()
{
  mFolder->listDirectory();
}

IMAPProgressDialog* KMAcctCachedImap::imapProgressDialog() const
{
  if( !mProgressDlg ) {
    mProgressDlg = new IMAPProgressDialog( KMKernel::self()->mainWin() );
  }
  return mProgressDlg;
}

#include "kmacctcachedimap.moc"
<|endoftext|>


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

#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/browser_action_test_util.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/mock_host_resolver.h"

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoNoScript) {
  ASSERT_TRUE(StartTestServer());

  // Loads a simple extension which attempts to change the title of every page
  // that loads to "modified".
  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("incognito")
      .AppendASCII("content_scripts")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  Browser* otr_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);
  TabContents* tab = otr_browser->GetSelectedTabContents();

  // Verify the script didn't run.
  bool result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->render_view_host(), L"",
      L"window.domAutomationController.send(document.title == 'Unmodified')",
      &result));
  EXPECT_TRUE(result);
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoYesScript) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(StartTestServer());

  // Load a dummy extension. This just tests that we don't regress a
  // crash fix when multiple incognito- and non-incognito-enabled extensions
  // are mixed.
  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("content_scripts")
      .AppendASCII("all_frames")));

  // Loads a simple extension which attempts to change the title of every page
  // that loads to "modified".
  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("content_scripts")));

  // Dummy extension #2.
  ASSERT_TRUE(LoadExtension(test_data_dir_
      .AppendASCII("content_scripts").AppendASCII("isolated_world1")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  Browser* otr_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);
  TabContents* tab = otr_browser->GetSelectedTabContents();

  // Verify the script ran.
  bool result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->render_view_host(), L"",
      L"window.domAutomationController.send(document.title == 'modified')",
      &result));
  EXPECT_TRUE(result);
}

// Tests that an extension which is enabled for incognito mode doesn't
// accidentially create and incognito profile.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DontCreateIncognitoProfile) {
  ASSERT_FALSE(browser()->profile()->HasOffTheRecordProfile());
  ASSERT_TRUE(
      RunExtensionTestIncognito("incognito/enumerate_tabs")) << message_;
  ASSERT_FALSE(browser()->profile()->HasOffTheRecordProfile());
}

// TODO(kochi): Flaky at r65757 and after on buildbot for ChromiumOS.
// http://crosbug.com/9049
#if defined(OS_CHROMEOS)
#define MAYBE_Incognito FLAKY_Incognito
#else
#define MAYBE_Incognito Incognito
#endif

// Tests that the APIs in an incognito-enabled extension work properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_Incognito) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(StartTestServer());

  ResultCatcher catcher;

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("apis")));

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

// Hangs flakily on mac and linux: http://crbug.com/53991
#if defined(OS_MACOSX) || defined(OS_LINUX)
#define MAYBE_IncognitoSplitMode DISABLED_IncognitoSplitMode
#else
#define MAYBE_IncognitoSplitMode IncognitoSplitMode
#endif

// Tests that the APIs in an incognito-enabled split-mode extension work
// properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_IncognitoSplitMode) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(StartTestServer());

  // We need 2 ResultCatchers because we'll be running the same test in both
  // regular and incognito mode.
  ResultCatcher catcher;
  catcher.RestrictToProfile(browser()->profile());
  ResultCatcher catcher_incognito;
  catcher_incognito.RestrictToProfile(
      browser()->profile()->GetOffTheRecordProfile());

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("split")));

  // Wait for both extensions to be ready before telling them to proceed.
  ExtensionTestMessageListener listener("waiting", true);
  EXPECT_TRUE(listener.WaitUntilSatisfied());
  ExtensionTestMessageListener listener_incognito("waiting", true);
  EXPECT_TRUE(listener_incognito.WaitUntilSatisfied());
  listener.Reply("go");
  listener_incognito.Reply("go");

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
  EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
}

// Tests that the APIs in an incognito-disabled extension don't see incognito
// events or callbacks.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoDisabled) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(StartTestServer());

  ResultCatcher catcher;

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtension(test_data_dir_
      .AppendASCII("incognito").AppendASCII("apis_disabled")));

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

// Test that opening a popup from an incognito browser window works properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoPopup) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(StartTestServer());

  ResultCatcher catcher;

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("popup")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  Browser* incognito_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);

  // Simulate the incognito's browser action being clicked.
  BrowserActionTestUtil(incognito_browser).Press(0);

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
<commit_msg>Reverts r65780.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/extensions/browser_action_test_util.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/ui_test_utils.h"
#include "net/base/mock_host_resolver.h"

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoNoScript) {
  ASSERT_TRUE(StartTestServer());

  // Loads a simple extension which attempts to change the title of every page
  // that loads to "modified".
  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("incognito")
      .AppendASCII("content_scripts")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  Browser* otr_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);
  TabContents* tab = otr_browser->GetSelectedTabContents();

  // Verify the script didn't run.
  bool result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->render_view_host(), L"",
      L"window.domAutomationController.send(document.title == 'Unmodified')",
      &result));
  EXPECT_TRUE(result);
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoYesScript) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(StartTestServer());

  // Load a dummy extension. This just tests that we don't regress a
  // crash fix when multiple incognito- and non-incognito-enabled extensions
  // are mixed.
  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("content_scripts")
      .AppendASCII("all_frames")));

  // Loads a simple extension which attempts to change the title of every page
  // that loads to "modified".
  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("content_scripts")));

  // Dummy extension #2.
  ASSERT_TRUE(LoadExtension(test_data_dir_
      .AppendASCII("content_scripts").AppendASCII("isolated_world1")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  Browser* otr_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);
  TabContents* tab = otr_browser->GetSelectedTabContents();

  // Verify the script ran.
  bool result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->render_view_host(), L"",
      L"window.domAutomationController.send(document.title == 'modified')",
      &result));
  EXPECT_TRUE(result);
}

// Tests that an extension which is enabled for incognito mode doesn't
// accidentially create and incognito profile.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DontCreateIncognitoProfile) {
  ASSERT_FALSE(browser()->profile()->HasOffTheRecordProfile());
  ASSERT_TRUE(
      RunExtensionTestIncognito("incognito/enumerate_tabs")) << message_;
  ASSERT_FALSE(browser()->profile()->HasOffTheRecordProfile());
}

// Tests that the APIs in an incognito-enabled extension work properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Incognito) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(StartTestServer());

  ResultCatcher catcher;

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("apis")));

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

// Hangs flakily on mac and linux: http://crbug.com/53991
#if defined(OS_MACOSX) || defined(OS_LINUX)
#define MAYBE_IncognitoSplitMode DISABLED_IncognitoSplitMode
#else
#define MAYBE_IncognitoSplitMode IncognitoSplitMode
#endif

// Tests that the APIs in an incognito-enabled split-mode extension work
// properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_IncognitoSplitMode) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(StartTestServer());

  // We need 2 ResultCatchers because we'll be running the same test in both
  // regular and incognito mode.
  ResultCatcher catcher;
  catcher.RestrictToProfile(browser()->profile());
  ResultCatcher catcher_incognito;
  catcher_incognito.RestrictToProfile(
      browser()->profile()->GetOffTheRecordProfile());

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("split")));

  // Wait for both extensions to be ready before telling them to proceed.
  ExtensionTestMessageListener listener("waiting", true);
  EXPECT_TRUE(listener.WaitUntilSatisfied());
  ExtensionTestMessageListener listener_incognito("waiting", true);
  EXPECT_TRUE(listener_incognito.WaitUntilSatisfied());
  listener.Reply("go");
  listener_incognito.Reply("go");

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
  EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
}

// Tests that the APIs in an incognito-disabled extension don't see incognito
// events or callbacks.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoDisabled) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(StartTestServer());

  ResultCatcher catcher;

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  ASSERT_TRUE(LoadExtension(test_data_dir_
      .AppendASCII("incognito").AppendASCII("apis_disabled")));

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}

// Test that opening a popup from an incognito browser window works properly.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoPopup) {
  host_resolver()->AddRule("*", "127.0.0.1");
  ASSERT_TRUE(StartTestServer());

  ResultCatcher catcher;

  ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
      .AppendASCII("incognito").AppendASCII("popup")));

  // Open incognito window and navigate to test page.
  ui_test_utils::OpenURLOffTheRecord(
      browser()->profile(),
      test_server()->GetURL("files/extensions/test_file.html"));

  Browser* incognito_browser = BrowserList::FindBrowserWithType(
      browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL,
      false);

  // Simulate the incognito's browser action being clicked.
  BrowserActionTestUtil(incognito_browser).Press(0);

  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
<|endoftext|>


<commit_before><commit_msg>Planning: consider multiple obstacles in side pass.<commit_after><|endoftext|>


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

#include "chrome/browser/ui/touch/frame/keyboard_container_view.h"

#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/views/dom_view.h"
#include "chrome/common/url_constants.h"
#include "content/browser/site_instance.h"
#include "content/browser/tab_contents/tab_contents.h"

namespace {

// Make the provided view and all of its descendents unfocusable.
void MakeViewHierarchyUnfocusable(views::View* view) {
  view->set_focusable(false);
  for (int i = 0; i < view->child_count(); ++i) {
    MakeViewHierarchyUnfocusable(view->GetChildViewAt(i));
  }
}

}  // namepsace

// static
const char KeyboardContainerView::kViewClassName[] =
    "browser/ui/touch/frame/KeyboardContainerView";

///////////////////////////////////////////////////////////////////////////////
// KeyboardContainerView, public:

KeyboardContainerView::KeyboardContainerView(Profile* profile, Browser* browser)
    : dom_view_(new DOMView),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          extension_function_dispatcher_(profile, this)),
      browser_(browser) {
  GURL keyboard_url(chrome::kChromeUIKeyboardURL);
  dom_view_->Init(profile,
      SiteInstance::CreateSiteInstanceForURL(profile, keyboard_url));
  dom_view_->LoadURL(keyboard_url);

  dom_view_->SetVisible(true);
  AddChildView(dom_view_);

  // We have Inited the dom_view. So we must have a tab contents.
  Observe(dom_view_->tab_contents());
}

KeyboardContainerView::~KeyboardContainerView() {
}

std::string KeyboardContainerView::GetClassName() const {
  return kViewClassName;
}

void KeyboardContainerView::Layout() {
  // TODO(bryeung): include a border between the keyboard and the client view
  dom_view_->SetBounds(0, 0, width(), height());
}

Browser* KeyboardContainerView::GetBrowser() {
  return browser_;
}

gfx::NativeView KeyboardContainerView::GetNativeViewOfHost() {
  return dom_view_->native_view();
}

TabContents* KeyboardContainerView::GetAssociatedTabContents() const {
  return dom_view_->tab_contents();
}

void KeyboardContainerView::ViewHierarchyChanged(bool is_add,
                                                 View* parent,
                                                 View* child) {
  if (is_add && parent == this)
    MakeViewHierarchyUnfocusable(child);
}

bool KeyboardContainerView::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(KeyboardContainerView, message)
    IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void KeyboardContainerView::OnRequest(
    const ExtensionHostMsg_Request_Params& request) {
  extension_function_dispatcher_.Dispatch(request,
      dom_view_->tab_contents()->render_view_host());
}
<commit_msg>Mark any descendant child view of the keyboard unfocusable.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/touch/frame/keyboard_container_view.h"

#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/views/dom_view.h"
#include "chrome/common/url_constants.h"
#include "content/browser/site_instance.h"
#include "content/browser/tab_contents/tab_contents.h"

namespace {

// Make the provided view and all of its descendents unfocusable.
void MakeViewHierarchyUnfocusable(views::View* view) {
  view->set_focusable(false);
  for (int i = 0; i < view->child_count(); ++i) {
    MakeViewHierarchyUnfocusable(view->GetChildViewAt(i));
  }
}

}  // namepsace

// static
const char KeyboardContainerView::kViewClassName[] =
    "browser/ui/touch/frame/KeyboardContainerView";

///////////////////////////////////////////////////////////////////////////////
// KeyboardContainerView, public:

KeyboardContainerView::KeyboardContainerView(Profile* profile, Browser* browser)
    : dom_view_(new DOMView),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          extension_function_dispatcher_(profile, this)),
      browser_(browser) {
  GURL keyboard_url(chrome::kChromeUIKeyboardURL);
  dom_view_->Init(profile,
      SiteInstance::CreateSiteInstanceForURL(profile, keyboard_url));
  dom_view_->LoadURL(keyboard_url);

  dom_view_->SetVisible(true);
  AddChildView(dom_view_);

  // We have Inited the dom_view. So we must have a tab contents.
  Observe(dom_view_->tab_contents());
}

KeyboardContainerView::~KeyboardContainerView() {
}

std::string KeyboardContainerView::GetClassName() const {
  return kViewClassName;
}

void KeyboardContainerView::Layout() {
  // TODO(bryeung): include a border between the keyboard and the client view
  dom_view_->SetBounds(0, 0, width(), height());
}

Browser* KeyboardContainerView::GetBrowser() {
  return browser_;
}

gfx::NativeView KeyboardContainerView::GetNativeViewOfHost() {
  return dom_view_->native_view();
}

TabContents* KeyboardContainerView::GetAssociatedTabContents() const {
  return dom_view_->tab_contents();
}

void KeyboardContainerView::ViewHierarchyChanged(bool is_add,
                                                 View* parent,
                                                 View* child) {
  if (is_add && Contains(child))
    MakeViewHierarchyUnfocusable(child);
}

bool KeyboardContainerView::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(KeyboardContainerView, message)
    IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void KeyboardContainerView::OnRequest(
    const ExtensionHostMsg_Request_Params& request) {
  extension_function_dispatcher_.Dispatch(request,
      dom_view_->tab_contents()->render_view_host());
}
<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2012
  \file      main.cpp
  \author      (lord.tiran@gmail.com)
  \date      13.05.2012
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#include <iostream>
#define BOOST_TEST_MODULE RDORealFormatTest
#include <boost/test/included/unit_test.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
// --------------------------------------------------------------------------------

BOOST_AUTO_TEST_SUITE(RDORealFormatTest)

BOOST_AUTO_TEST_CASE(MantissaPrecision)
{
	double value = 10e+007;
	std::stringstream stream;
	stream << value;

	std::string str = stream.str();
	std::cout << str;

	BOOST_CHECK(stream.str() == "1e+008");
}

BOOST_AUTO_TEST_SUITE_END() // RDORealFormatTest
<commit_msg> - использование boost::format<commit_after>/*!
  \copyright (c) RDO-Team, 2012
  \file      main.cpp
  \author      (lord.tiran@gmail.com)
  \date      13.05.2012
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#include <iostream>
#include <boost/format.hpp>
#define BOOST_TEST_MODULE RDORealFormatTest
#include <boost/test/included/unit_test.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
// --------------------------------------------------------------------------------

BOOST_AUTO_TEST_SUITE(RDORealFormatTest)

BOOST_AUTO_TEST_CASE(MantissaPrecision)
{
	double value = 10e+007;
	std::stringstream stream;
	stream << boost::format("%1$.10E") % value;

	std::string str = stream.str();
	std::cout << str;

	BOOST_CHECK(stream.str() == "1.0000000000E+008");
}

BOOST_AUTO_TEST_SUITE_END() // RDORealFormatTest
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/utils/imageProcs/p9_ring_identification.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#ifndef _P9_RING_IDENT_H_
#define _P9_RING_IDENT_H_
#include <stddef.h>
#ifdef WIN32
    #include "win32_stdint.h"
#else
    #ifdef __sun
        #include <sys/int_types.h>
    #else
        #include <stdint.h>
    #endif
#endif
#include <stdlib.h>
#include <string.h>
#include <p9_ring_id.h>

// MVPD Ring ID list structure.
typedef struct
{
    const char*  ringName;
    RingID       ringId;
    uint8_t      instanceIdMin;    // the min instanceId
    uint8_t      instanceIdMax;    // the max instanceId
    uint8_t      vpdKeyword;
    uint8_t      vpdRingClass;     // Indicates std, gptr, or ex instance.
} RingIdList;

typedef struct
{
    const RingIdList* ringIdList;
    uint32_t    ringIdListSize;
} VPDRingList;

extern const VPDRingList ALL_VPD_RINGS[];

extern const uint32_t    RING_ID_LIST_CHIP_SIZE, RING_ID_LIST_CORE_SIZE,
       RING_ID_LIST_CME_SIZE, RING_ID_LIST_CC_SIZE;

#if defined(WIN32) || defined(__sun)
    extern const RingIdList  RING_ID_LIST_PDG[], RING_ID_LIST_PDR[];
    extern const uint32_t    RING_ID_LIST_PG_SIZE, RING_ID_LIST_PR_SIZE;
#endif

// Enumerated VPD keyword values.
// Note! This is DIFFERENT from the MvpdKeyword list in fapiMvpdAccess.H which
//       can't be used in this file since it's not, per se, a fapi file. So
//       these values need to be translated in xip_customize when passing the
//       mvpdKeyword to getMvpdRing();
enum VpdKeyword
{
    VPD_KEYWORD_PDG = 0,
    VPD_KEYWORD_PDR = 1,
    NUM_OF_VPD_TYPES = 2,
};

enum VpdRingClass
{
    VPD_RING_CLASS_NEST = 0,   // Indicates NEST [common] rings, except GPTR #G rings.
    VPD_RING_CLASS_GPTR = 1,   // Indicates GPTR #G [common]rings
    VPD_RING_CLASS_EQ = 2,     // Indicates EQ [common] rings
    VPD_RING_CLASS_EX = 3,     // Indicates EX [common] rings
    VPD_RING_CLASS_EC = 4,     // Indicates EC [common] rings
    VPD_RING_CLASS_EQ_INS = 5, // Indicates EQ instance rings
    VPD_RING_CLASS_EX_INS = 6, // Indicates EX instance rings
    VPD_RING_CLASS_EC_INS = 7, // Indicates EC instance rings
    VPD_RING_CLASS_LAST = 8,
};

#define MVPD_END_OF_DATA_MAGIC (uint32_t)0x454E4400 // "END "

#endif
<commit_msg>GPTR/Overlays stage-2 support<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/utils/imageProcs/p9_ring_identification.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#ifndef _P9_RING_IDENT_H_
#define _P9_RING_IDENT_H_
#include <stddef.h>
#ifdef WIN32
    #include "win32_stdint.h"
#else
    #ifdef __sun
        #include <sys/int_types.h>
    #else
        #include <stdint.h>
    #endif
#endif
#include <stdlib.h>
#include <string.h>
#include <p9_ring_id.h>

// MVPD Ring ID list structure.
typedef struct
{
    const char*  ringName;
    RingID       ringId;
    uint8_t      instanceIdMin;    // the min instanceId
    uint8_t      instanceIdMax;    // the max instanceId
    uint8_t      vpdKeyword;
    uint8_t      vpdRingClass;     // Indicates std, gptr, or ex instance.
} RingIdList;

typedef struct
{
    const RingIdList* ringIdList;
    uint32_t    ringIdListSize;
} VPDRingList;

extern const VPDRingList ALL_VPD_RINGS[];

extern const uint32_t    RING_ID_LIST_CHIP_SIZE, RING_ID_LIST_CORE_SIZE,
       RING_ID_LIST_CME_SIZE, RING_ID_LIST_CC_SIZE;

#if defined(WIN32) || defined(__sun)
    extern const RingIdList  RING_ID_LIST_PDG[], RING_ID_LIST_PDR[];
    extern const uint32_t    RING_ID_LIST_PG_SIZE, RING_ID_LIST_PR_SIZE;
#endif

// Enumerated VPD keyword values.
// Note! This is DIFFERENT from the MvpdKeyword list in fapiMvpdAccess.H which
//       can't be used in this file since it's not, per se, a fapi file. So
//       these values need to be translated in xip_customize when passing the
//       mvpdKeyword to getMvpdRing();
enum VpdKeyword
{
    VPD_KEYWORD_PDG = 0,
    VPD_KEYWORD_PDR = 1,
    NUM_OF_VPD_TYPES = 2,
};

enum VpdRingClass
{
    VPD_RING_CLASS_NEST = 0,   // Indicates NEST [common] rings, except GPTR #G rings.
    VPD_RING_CLASS_GPTR_NEST = 1,   // Indicates GPTR #G [common]rings-NEST
    VPD_RING_CLASS_GPTR_EQ = 2,   // Indicates GPTR #G [common]rings-EQ
    VPD_RING_CLASS_GPTR_EX = 3,   // Indicates GPTR #G [common]rings-EX
    VPD_RING_CLASS_GPTR_EC = 4,   // Indicates GPTR #G [common]rings-EC
    VPD_RING_CLASS_EQ = 5,     // Indicates EQ [common] rings
    VPD_RING_CLASS_EX = 6,     // Indicates EX [common] rings
    VPD_RING_CLASS_EC = 7,     // Indicates EC [common] rings
    VPD_RING_CLASS_EQ_INS = 8, // Indicates EQ instance rings
    VPD_RING_CLASS_EX_INS = 9, // Indicates EX instance rings
    VPD_RING_CLASS_EC_INS = 10, // Indicates EC instance rings
    VPD_RING_CLASS_LAST = 11,
};

#define MVPD_END_OF_DATA_MAGIC (uint32_t)0x454E4400 // "END "

#endif
<|endoftext|>