<commit_before>/*************************************************************************
 *
 *  $RCSfile: ldapuserprofilebe.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2004-08-03 14:38:54 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards OOurce License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free OOftware; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free OOftware Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free OOftware
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards OOurce License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  OOurce License Version 1.1 (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.openoffice.org/license.html.
 *
 *  OOftware provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE OOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the OOftware.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef EXTENSIONS_CONFIG_LDAP_LDAPUSERPROFILEBE_HXX_
#define EXTENSIONS_CONFIG_LDAP_LDAPUSERPROFILEBE_HXX_
#ifndef EXTENSIONS_CONFIG_LDAP_LDAPUSERPROF_HXX_
#include "ldapuserprof.hxx"
#endif
#ifndef EXTENSIONS_CONFIG_LDAP_LDAPACCESS_HXX_
#include "ldapaccess.hxx"
#endif
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XSINGLELAYERSTRATUM_HPP_
#include <com/sun/star/configuration/backend/XSingleLayerStratum.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif // _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif // _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif // _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_CANNOTCONNECTEXCEPTION_HPP_
#include <com/sun/star/configuration/backend/CannotConnectException.hpp>
#endif
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_INSUFFICIENTACCESSRIGHTSEXCEPTION_HPP_
#include <com/sun/star/configuration/backend/InsufficientAccessRightsException.hpp>
#endif // _COM_SUN_STAR_CONFIGURATION_BACKEND_INSUFFICIENTACCESSRIGHTSEXCEPTION_HPP_
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_CONNECTIONLOSTEXCEPTION_HPP_
#include <com/sun/star/configuration/backend/ConnectionLostException.hpp>
#endif // _COM_SUN_STAR_CONFIGURATION_BACKEND_CONNECTIONLOSTEXCEPTION_HPP_
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#endif // _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_

#ifndef _COM_SUN_STAR_LDAP_LDAPCONNECTIONEXCEPTION_HPP_
#include <com/sun/star/ldap/LdapConnectionException.hpp>
#endif // _COM_SUN_STAR_LDAP_LDAPCONNECTIONEXCEPTION_HPP_

#ifndef _COM_SUN_STAR_LDAP_LDAPGENERICEXCEPTION_HPP_
#include <com/sun/star/ldap/LdapGenericException.hpp>
#endif // _COM_SUN_STAR_LDAP_LDAPGENERICEXCEPTION_HPP_

#ifndef _CPPUHELPER_COMPBASE2_HXX_
#include <cppuhelper/compbase2.hxx>
#endif // _CPPUHELPER_COMPBASE3_HXX_

#ifndef INCLUDED_MAP
#include <map>
#define INCLUDED_MAP
#endif

#define CONTEXT_ITEM_PREFIX_                "/modules/com.sun.star.configuration/bootstrap/"
namespace extensions { namespace config { namespace ldap {

namespace css = com::sun::star ;
namespace uno = css::uno ;
namespace lang = css::lang ;
namespace ldap= css::ldap ;
namespace backend = css::configuration::backend ;
namespace container = css::container;
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
typedef cppu::WeakComponentImplHelper2<backend::XSingleLayerStratum,
                                       lang::XServiceInfo> BackendBase ;

/**
  Implements the PlatformBackend service, a specialization of the
  SingleLayerStratum service for retreiving LDAP user profile
  configuration settings from a LDAP repsoitory.
  */
class LdapUserProfileBe : public BackendBase
{
    public :

        LdapUserProfileBe(const uno::Reference<uno::XComponentContext>& xContext)
            throw(backend::BackendAccessException,
                  backend::BackendSetupException);
        ~LdapUserProfileBe(void) ;

        // XServiceInfo
        virtual rtl::OUString SAL_CALL
            getImplementationName(  )
                throw (uno::RuntimeException) ;

        virtual sal_Bool SAL_CALL
            supportsService( const rtl::OUString& aServiceName )
                throw (uno::RuntimeException) ;

        virtual uno::Sequence<rtl::OUString> SAL_CALL
            getSupportedServiceNames(  )
                throw (uno::RuntimeException) ;

        //XSingleLayerStratum
        virtual uno::Reference<backend::XLayer> SAL_CALL
        getLayer( const rtl::OUString& aLayerId, const rtl::OUString& aTimestamp )
            throw (backend::BackendAccessException,
                   lang::IllegalArgumentException) ;

        virtual uno::Reference<backend::XUpdatableLayer> SAL_CALL
        getUpdatableLayer( const rtl::OUString& aLayerId )
            throw (backend::BackendAccessException,
                   lang::NoSupportException,
                   lang::IllegalArgumentException) ;
         /**
          Provides the implementation name.
          @return   implementation name
          */
        static rtl::OUString SAL_CALL getLdapUserProfileBeName(void) ;
        /**
          Provides the supported services names
          @return   service names
          */
        static uno::Sequence<rtl::OUString> SAL_CALL
            getLdapUserProfileBeServiceNames(void) ;

    private:
        /** Build OO/LDAP attribute mapping table */
        void  initializeMappingTable (const rtl::OUString& aFileMapName);
        /** Check if LDAP is configured */
        bool isLdapConfigured(LdapDefinition& aDefinition);

        bool getLdapStringParam(uno::Reference<container::XNameAccess>& xAccess,
                                const rtl::OUString& aLdapSetting,
                                rtl::OString& aServerParameter);

        void mapGenericException(ldap::LdapGenericException& aException)
            throw (backend::InsufficientAccessRightsException,
                   backend::ConnectionLostException,
                   backend::BackendAccessException);
        /** Connect to LDAP server */
        void connectToLdapServer(const LdapDefinition& aDefinition );
        /** Get URL of OO-to-LDAP Mapping File */
        void getMappingFileUrl(rtl::OUString& aFileUrl,
                               const rtl::OUString& aFileMapName)const;

        /** Service Factory object */
        uno::Reference<lang::XMultiServiceFactory> mFactory;
        /** Component Context */
        uno::Reference<uno::XComponentContext> mContext ;
        /** Mutex for resource protection */
        osl::Mutex mMutex ;
        /** Maping LDAP->00o */
        LdapUserProfileMap mUserProfileMap;
        /** Object for LDAP functionality */
        LdapConnection mLdapConnection;
        /**Currently logged in user */
        rtl::OUString mLoggedOnUser ;
        /** DN of currently logged in user */
        rtl::OString mUserDN;
} ;
//------------------------------------------------------------------------------
}}}

#endif // EXTENSIONS_CONFIG_LDAP_LDAPUSERPROFILE_HXX_
<commit_msg>INTEGRATION: CWS dba15 (1.2.2); FILE MERGED 2004/08/19 17:32:12 cyrillem 1.2.2.1: #i33149# Fix recursion prevention<commit_after>/*************************************************************************
 *
 *  $RCSfile: ldapuserprofilebe.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2004-09-08 17:49:54 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards OOurce License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free OOftware; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free OOftware Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free OOftware
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards OOurce License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  OOurce License Version 1.1 (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.openoffice.org/license.html.
 *
 *  OOftware provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE OOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the OOftware.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef EXTENSIONS_CONFIG_LDAP_LDAPUSERPROFILEBE_HXX_
#define EXTENSIONS_CONFIG_LDAP_LDAPUSERPROFILEBE_HXX_
#ifndef EXTENSIONS_CONFIG_LDAP_LDAPUSERPROF_HXX_
#include "ldapuserprof.hxx"
#endif
#ifndef EXTENSIONS_CONFIG_LDAP_LDAPACCESS_HXX_
#include "ldapaccess.hxx"
#endif
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XSINGLELAYERSTRATUM_HPP_
#include <com/sun/star/configuration/backend/XSingleLayerStratum.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif // _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif // _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif // _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_CANNOTCONNECTEXCEPTION_HPP_
#include <com/sun/star/configuration/backend/CannotConnectException.hpp>
#endif
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_INSUFFICIENTACCESSRIGHTSEXCEPTION_HPP_
#include <com/sun/star/configuration/backend/InsufficientAccessRightsException.hpp>
#endif // _COM_SUN_STAR_CONFIGURATION_BACKEND_INSUFFICIENTACCESSRIGHTSEXCEPTION_HPP_
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_CONNECTIONLOSTEXCEPTION_HPP_
#include <com/sun/star/configuration/backend/ConnectionLostException.hpp>
#endif // _COM_SUN_STAR_CONFIGURATION_BACKEND_CONNECTIONLOSTEXCEPTION_HPP_
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#endif // _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_

#ifndef _CPPUHELPER_COMPBASE2_HXX_
#include <cppuhelper/compbase2.hxx>
#endif // _CPPUHELPER_COMPBASE3_HXX_

#ifndef INCLUDED_MAP
#include <map>
#define INCLUDED_MAP
#endif

#define CONTEXT_ITEM_PREFIX_                "/modules/com.sun.star.configuration/bootstrap/"
namespace extensions { namespace config { namespace ldap {

namespace css = com::sun::star ;
namespace uno = css::uno ;
namespace lang = css::lang ;
namespace ldap= css::ldap ;
namespace backend = css::configuration::backend ;
namespace container = css::container;
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
typedef cppu::WeakComponentImplHelper2<backend::XSingleLayerStratum,
                                       lang::XServiceInfo> BackendBase ;

/**
  Implements the PlatformBackend service, a specialization of the
  SingleLayerStratum service for retreiving LDAP user profile
  configuration settings from a LDAP repsoitory.
  */
class LdapUserProfileBe : public BackendBase
{
    public :

        LdapUserProfileBe(const uno::Reference<uno::XComponentContext>& xContext)
            throw(backend::BackendAccessException,
                  backend::BackendSetupException);
        ~LdapUserProfileBe(void) ;

        // XServiceInfo
        virtual rtl::OUString SAL_CALL
            getImplementationName(  )
                throw (uno::RuntimeException) ;

        virtual sal_Bool SAL_CALL
            supportsService( const rtl::OUString& aServiceName )
                throw (uno::RuntimeException) ;

        virtual uno::Sequence<rtl::OUString> SAL_CALL
            getSupportedServiceNames(  )
                throw (uno::RuntimeException) ;

        //XSingleLayerStratum
        virtual uno::Reference<backend::XLayer> SAL_CALL
        getLayer( const rtl::OUString& aLayerId, const rtl::OUString& aTimestamp )
            throw (backend::BackendAccessException,
                   lang::IllegalArgumentException) ;

        virtual uno::Reference<backend::XUpdatableLayer> SAL_CALL
        getUpdatableLayer( const rtl::OUString& aLayerId )
            throw (backend::BackendAccessException,
                   lang::NoSupportException,
                   lang::IllegalArgumentException) ;
         /**
          Provides the implementation name.
          @return   implementation name
          */
        static rtl::OUString SAL_CALL getLdapUserProfileBeName(void) ;
        /**
          Provides the supported services names
          @return   service names
          */
        static uno::Sequence<rtl::OUString> SAL_CALL
            getLdapUserProfileBeServiceNames(void) ;

    private:
        /** Build OO/LDAP attribute mapping table */
        void  initializeMappingTable (const rtl::OUString& aFileMapName);
        /** Check if LDAP is configured */
        bool isLdapConfigured(LdapDefinition& aDefinition);

        bool getLdapStringParam(uno::Reference<container::XNameAccess>& xAccess,
                                const rtl::OUString& aLdapSetting,
                                rtl::OString& aServerParameter);

        void mapGenericException(ldap::LdapGenericException& aException)
            throw (backend::InsufficientAccessRightsException,
                   backend::ConnectionLostException,
                   backend::BackendAccessException);
        /** Connect to LDAP server */
        void connectToLdapServer(const LdapDefinition& aDefinition );
        /** Get URL of OO-to-LDAP Mapping File */
        void getMappingFileUrl(rtl::OUString& aFileUrl,
                               const rtl::OUString& aFileMapName)const;

        /** Service Factory object */
        uno::Reference<lang::XMultiServiceFactory> mFactory;
        /** Component Context */
        uno::Reference<uno::XComponentContext> mContext ;
        /** Mutex for resource protection */
        osl::Mutex mMutex ;
        /** Maping LDAP->00o */
        LdapUserProfileMap mUserProfileMap;
        /** Object for LDAP functionality */
        LdapConnection mLdapConnection;
        /**Currently logged in user */
        rtl::OUString mLoggedOnUser ;
        /** DN of currently logged in user */
        rtl::OString mUserDN;

        /**
          Because initialising the backend requires to read some configuration,
          there's a risk of infinite recursion (the backend initialisation
          taking place inside the configuration initialisation).
          To prevent this, the following members ensure access to the LDAP
          server details cannot recurse.
          */
        /** Whether we're in the constructor already. */
        static bool mCanReadConfiguration ;
        /** Access protection for mCanReadConfiguration. */
        static osl::Mutex mReadConfigurationLock ;
} ;
//------------------------------------------------------------------------------
}}}

#endif // EXTENSIONS_CONFIG_LDAP_LDAPUSERPROFILE_HXX_
<|endoftext|>


<commit_before>// rogueGenocide.cpp : Defines the entry point for the DLL application.
//

#include "bzfsAPI.h"
#include <string>
#include <map>
#include "global.h"

BZ_GET_PLUGIN_VERSION

// event handler callback
class RogueDeathHandler : public bz_EventHandler
{
public:
        RogueDeathHandler();
        virtual ~RogueDeathHandler();

        virtual void process ( bz_EventData *eventData );

        virtual bool autoDelete ( void ) { return false;} // this will be used for more then one event
protected:

        typedef struct
        {
                int playerID;
                int teamID;
                std::string callsign;
                double startTime;
                double lastUpdateTime;

        }trRogueDeathHandler;

        std::map<int, trRogueDeathHandler > rogueList;
};

RogueDeathHandler	deathHandler;

BZF_PLUGIN_CALL int bz_Load ( const char* commandLine )
{
	bz_debugMessage(4,"rogueGenocide plugin loaded");

	bz_registerEvent(bz_ePlayerDieEvent,BZ_ALL_USERS,&deathHandler);
	bz_registerEvent(bz_ePlayerPartEvent,BZ_ALL_USERS,&deathHandler);
	bz_registerEvent(bz_ePlayerJoinEvent,BZ_ALL_USERS,&deathHandler);

	return 0;
}

BZF_PLUGIN_CALL int bz_Unload ( void )
{
	bz_removeEvent(bz_ePlayerDieEvent,BZ_ALL_USERS,&deathHandler);
	bz_removeEvent(bz_ePlayerPartEvent,BZ_ALL_USERS,&deathHandler);
	bz_removeEvent(bz_ePlayerJoinEvent,BZ_ALL_USERS,&deathHandler);

	bz_debugMessage(4,"rogueGenocide plugin unloaded");
	return 0;
}

RogueDeathHandler::RogueDeathHandler()
{
}

RogueDeathHandler::~RogueDeathHandler()
{
}

void RogueDeathHandler::process ( bz_EventData *eventData )
{

	switch (eventData->eventType)
	{
		default:
			// no clue
			break;

		// wait for a tank death and start checking for genocide and rogues
		case bz_ePlayerDieEvent:
		{
			bz_PlayerDieEventData	*dieData = (bz_PlayerDieEventData*)eventData;
			//if its not a genocide kill, dont care
			if (dieData->flagKilledWith != "G" )
				break;
			// if the tank killed was not a rogue, let the server/client do the normal killing
			if (dieData->teamID != RogueTeam )
				break;
			// if the tank killed was a rogue, and the killer was a rogue, kill the lousy tk'er
			if (dieData->killerTeamID == RogueTeam )
			{
				bz_killPlayer ( dieData->killerID, 0 );
				bz_sendTextMessage(BZ_SERVER,dieData->killerID,"You should be more careful with Genocide");
			// if the tank killed was a rogue, and the killer wasnt, kill all rogues.
			// note the possible issue if the rogue tank being killed has not spawned
			// and if all else fails, just kill all rogues.....nothing wrong with that
			} else {
				for ( std::map<int, trRogueDeathHandler >::iterator itr = rogueList.begin(); itr != rogueList.end(); itr++ )
				{
					bz_killPlayer( itr->first, 0 );
					bz_sendTextMessage(BZ_SERVER,itr->first,"You were a victim of Rogue Genocide");
				}
			}
		}
		break;

		// remove from the rogueLIst if the rogue tank leaves
		case  bz_ePlayerPartEvent:
		{
			std::map<int, trRogueDeathHandler >::iterator itr = rogueList.find( (( bz_PlayerJoinPartEventData*)eventData)->playerID );
			if (itr != rogueList.end())
				rogueList.erase(itr);
        }
		break;

    	// add to the list of rogue tanks playing
		case bz_ePlayerJoinEvent:
		{
			 trRogueDeathHandler   rogueRecord;

			rogueRecord.playerID = (( bz_PlayerJoinPartEventData*)eventData)->playerID;
			rogueRecord.teamID = (( bz_PlayerJoinPartEventData*)eventData)->teamID;
			rogueRecord.callsign = (( bz_PlayerJoinPartEventData*)eventData)->callsign.c_str();
			rogueRecord.lastUpdateTime = (( bz_PlayerJoinPartEventData*)eventData)->time;
			rogueRecord.startTime = rogueRecord.lastUpdateTime;

			if (rogueRecord.teamID == RogueTeam )
			{
				rogueList[(( bz_PlayerJoinPartEventData*)eventData)->playerID] = rogueRecord;
			}
		}
		break;

	}
}
<commit_msg>updated for new bz_killPlayer<commit_after>// rogueGenocide.cpp : Defines the entry point for the DLL application.
//

#include "bzfsAPI.h"
#include <string>
#include <map>
#include "global.h"

BZ_GET_PLUGIN_VERSION

// event handler callback
class RogueDeathHandler : public bz_EventHandler
{
public:
        RogueDeathHandler();
        virtual ~RogueDeathHandler();

        virtual void process ( bz_EventData *eventData );

        virtual bool autoDelete ( void ) { return false;} // this will be used for more then one event
protected:

        typedef struct
        {
                int playerID;
                int teamID;
                std::string callsign;
                double startTime;
                double lastUpdateTime;

        }trRogueDeathHandler;

        std::map<int, trRogueDeathHandler > rogueList;
};

RogueDeathHandler	deathHandler;

BZF_PLUGIN_CALL int bz_Load ( const char* commandLine )
{
	bz_debugMessage(4,"rogueGenocide plugin loaded");

	bz_registerEvent(bz_ePlayerDieEvent,BZ_ALL_USERS,&deathHandler);
	bz_registerEvent(bz_ePlayerPartEvent,BZ_ALL_USERS,&deathHandler);
	bz_registerEvent(bz_ePlayerJoinEvent,BZ_ALL_USERS,&deathHandler);

	return 0;
}

BZF_PLUGIN_CALL int bz_Unload ( void )
{
	bz_removeEvent(bz_ePlayerDieEvent,BZ_ALL_USERS,&deathHandler);
	bz_removeEvent(bz_ePlayerPartEvent,BZ_ALL_USERS,&deathHandler);
	bz_removeEvent(bz_ePlayerJoinEvent,BZ_ALL_USERS,&deathHandler);

	bz_debugMessage(4,"rogueGenocide plugin unloaded");
	return 0;
}

RogueDeathHandler::RogueDeathHandler()
{
}

RogueDeathHandler::~RogueDeathHandler()
{
}

void RogueDeathHandler::process ( bz_EventData *eventData )
{

	switch (eventData->eventType)
	{
		default:
			// no clue
			break;

		// wait for a tank death and start checking for genocide and rogues
		case bz_ePlayerDieEvent:
		{
			bz_PlayerDieEventData	*dieData = (bz_PlayerDieEventData*)eventData;
			//if its not a genocide kill, dont care
			if (dieData->flagKilledWith != "G" )
				break;
			// if the tank killed was not a rogue, let the server/client do the normal killing
			if (dieData->teamID != RogueTeam )
				break;
			// if the tank killed was a rogue, and the killer was a rogue, kill the lousy tk'er
			if (dieData->killerTeamID == RogueTeam )
			{
				bz_killPlayer ( dieData->killerID, 0, dieData->killerID, "G" );
				bz_sendTextMessage(BZ_SERVER,dieData->killerID,"You should be more careful with Genocide");
			// if the tank killed was a rogue, and the killer wasnt, kill all rogues.
			// note the possible issue if the rogue tank being killed has not spawned
			// and if all else fails, just kill all rogues.....nothing wrong with that
			} else {
				for ( std::map<int, trRogueDeathHandler >::iterator itr = rogueList.begin(); itr != rogueList.end(); itr++ )
				{
					bz_killPlayer( itr->first, 0, dieData->killerID, "G" );
					bz_sendTextMessage(BZ_SERVER,itr->first,"You were a victim of Rogue Genocide");
				}
			}
		}
		break;

		// remove from the rogueLIst if the rogue tank leaves
		case  bz_ePlayerPartEvent:
		{
			std::map<int, trRogueDeathHandler >::iterator itr = rogueList.find( (( bz_PlayerJoinPartEventData*)eventData)->playerID );
			if (itr != rogueList.end())
				rogueList.erase(itr);
        }
		break;

    	// add to the list of rogue tanks playing
		case bz_ePlayerJoinEvent:
		{
			 trRogueDeathHandler   rogueRecord;

			rogueRecord.playerID = (( bz_PlayerJoinPartEventData*)eventData)->playerID;
			rogueRecord.teamID = (( bz_PlayerJoinPartEventData*)eventData)->teamID;
			rogueRecord.callsign = (( bz_PlayerJoinPartEventData*)eventData)->callsign.c_str();
			rogueRecord.lastUpdateTime = (( bz_PlayerJoinPartEventData*)eventData)->time;
			rogueRecord.startTime = rogueRecord.lastUpdateTime;

			if (rogueRecord.teamID == RogueTeam )
			{
				rogueList[(( bz_PlayerJoinPartEventData*)eventData)->playerID] = rogueRecord;
			}
		}
		break;

	}
}
<|endoftext|>


<commit_before>/** This file is part of Contacts daemon
 **
 ** Copyright (c) 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
 **
 ** Contact:  Nokia Corporation (info@qt.nokia.com)
 **
 ** GNU Lesser General Public License Usage
 ** This file may be used under the terms of the GNU Lesser General Public License
 ** version 2.1 as published by the Free Software Foundation and appearing in the
 ** file LICENSE.LGPL included in the packaging of this file.  Please review the
 ** following information to ensure the GNU Lesser General Public License version
 ** 2.1 requirements will be met:
 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
 ** In addition, as a special exception, Nokia gives you certain additional rights.
 ** These rights are described in the Nokia Qt LGPL Exception version 1.1, included
 ** in the file LGPL_EXCEPTION.txt in this package.
 **
 ** Other Usage
 ** Alternatively, this file may be used in accordance with the terms and
 ** conditions contained in a signed written agreement between you and Nokia.
 **/

#include <QStringBuilder>

#include <QContactName>
#include <QContactBirthday>

#include <MLocale>

#include <recurrencerule.h>

#include "cdbirthdaycalendar.h"
#include "debug.h"

using namespace Contactsd;

// A random ID.
const QLatin1String calNotebookId("b1376da7-5555-1111-2222-227549c4e570");

CDBirthdayCalendar::CDBirthdayCalendar(SyncMode syncMode, QObject *parent) :
    QObject(parent),
    mCalendar(0),
    mStorage(0)
{
    mCalendar = mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
    mStorage = mKCal::ExtendedCalendar::defaultStorage(mCalendar);

    MLocale * const locale = new MLocale(this);

    if (not locale->isInstalledTrCatalog(QLatin1String("calendar"))) {
        locale->installTrCatalog(QLatin1String("calendar"));
    }

    locale->connectSettings();
    connect(locale, SIGNAL(settingsChanged()), this, SLOT(onLocaleChanged()));

    MLocale::setDefault(*locale);

    mStorage->open();

    mKCal::Notebook::Ptr notebook = mStorage->notebook(calNotebookId);

    if (notebook.isNull()) {
        notebook = createNotebook();
        mStorage->addNotebook(notebook);
    } else {
        // Clear the calendar database if and only if restoring from a backup.
        switch(syncMode) {
        case Incremental:
            // Force calendar name update, if a locale change happened while contactsd was not running.
            onLocaleChanged();
            break;

        case FullSync:
            mStorage->deleteNotebook(notebook);
            notebook = createNotebook();
            mStorage->addNotebook(notebook);
            break;
        }
    }
}

CDBirthdayCalendar::~CDBirthdayCalendar()
{
    if (mStorage) {
        mStorage->close();
    }

    debug() << "Destroyed birthday calendar";
}

mKCal::Notebook::Ptr CDBirthdayCalendar::createNotebook()
{
    return mKCal::Notebook::Ptr(new mKCal::Notebook(calNotebookId,
                                                    qtTrId("qtn_caln_birthdays"),
                                                    QLatin1String(""),
                                                    QLatin1String("#ff0000"),
                                                    false, // Not shared.
                                                    true, // Is master.
                                                    false, // Not synced to Ovi.
                                                    false, // Writable.
                                                    true, // Visible.
                                                    QLatin1String("Birthday-Nokia"),
                                                    QLatin1String(""),
                                                    0));
}

void CDBirthdayCalendar::updateBirthday(const QContact &contact)
{
    // Retrieve contact details.
    const QContactDisplayLabel displayName = contact.detail<QContactDisplayLabel>();
    const QContactBirthday contactBirthday = contact.detail<QContactBirthday>();

    if (displayName.isEmpty() || contactBirthday.isEmpty()) {
        warning() << Q_FUNC_INFO << "Contact without name or birthday, local ID: "
                  << contact.localId();
        return;
    }

    // Retrieve birthday event.
    if (not mStorage->isValidNotebook(calNotebookId)) {
        warning() << Q_FUNC_INFO << "Invalid notebook ID: " << calNotebookId;
        return;
    }

    KCalCore::Event::Ptr event = calendarEvent(contact.localId());

    if (event.isNull()) {
        // Add a new event.
        event = KCalCore::Event::Ptr(new KCalCore::Event());
        event->startUpdates();
        event->setUid(calendarEventId(contact.localId()));
        event->setAllDay(true);
        event->setHasEndDate(false);

        // Ensure events appear as birthdays in the calendar, NB#259710.
        event->setCategories(QStringList() << QLatin1String("BIRTHDAY"));

        if (not mCalendar->addEvent(event, calNotebookId)) {
            warning() << Q_FUNC_INFO << "Failed to add event to calendar";
            return;
        }
    } else {
        // Update the existing event.
        event->setReadOnly(false);
        event->startUpdates();
    }

    // Transfer birthday details from contact to calendar event.
    event->setSummary(displayName.label());

    // Event has only date information, no time.
    event->setDtStart(KDateTime(contactBirthday.date(), QTime(), KDateTime::ClockTime));

    // Must always set the recurrence as it depends on the event date.
    KCalCore::Recurrence * const rule = event->recurrence();
    rule->setStartDateTime(event->dtStart());

    // This is not a boolean, but the frequency of the recurrence: every 1 year.
    rule->setYearly(1);

    // Set the alarms on the event
    event->clearAlarms();
    KCalCore::Alarm::Ptr alarm = event->newAlarm();
    alarm->setDisplayAlarm(event->summary());
    alarm->setStartOffset(KCalCore::Duration(-1, KCalCore::Duration::Days));

    event->setReadOnly(true);
    event->endUpdates();

    // Commit calendar changes.
    if (not mStorage->save()) {
        warning() << Q_FUNC_INFO << "Failed to save event in calendar";
        return;
    }

    debug() << "Updated birthday event in calendar, local ID: " << contact.localId();
}

void CDBirthdayCalendar::deleteBirthday(QContactLocalId contactId)
{
    KCalCore::Event::Ptr event = calendarEvent(contactId);

    if (event.isNull()) {
        debug() << Q_FUNC_INFO << "Not found in calendar:" << contactId;
        return;
    }

    mCalendar->deleteEvent(event);

    if (not mStorage->save()) {
        warning() << Q_FUNC_INFO << "Failed to delete event from calendar";
        return;
    }

    debug() << "Deleted birthday event in calendar, local ID: " << event->uid();
}

QDate CDBirthdayCalendar::birthdayDate(QContactLocalId contactId)
{
    KCalCore::Event::Ptr event = calendarEvent(contactId);

    if (event.isNull()) {
        return QDate();
    }

    return event->dtStart().date();
}

QString CDBirthdayCalendar::summary(QContactLocalId contactId)
{
    KCalCore::Event::Ptr event = calendarEvent(contactId);

    if (event.isNull()) {
        return QString();
    }

    return event->summary();
}

QString CDBirthdayCalendar::calendarEventId(QContactLocalId contactId)
{
    static const QLatin1String calIdExtension("com.nokia.birthday/");
    return calIdExtension + QString::number(contactId);
}

KCalCore::Event::Ptr CDBirthdayCalendar::calendarEvent(QContactLocalId contactId)
{
    const QString eventId = calendarEventId(contactId);

    if (not mStorage->load(eventId)) {
        warning() << Q_FUNC_INFO << "Unable to load event from calendar";
        return KCalCore::Event::Ptr();
    }

    KCalCore::Event::Ptr event = mCalendar->event(eventId);

    if (event.isNull()) {
        debug() << Q_FUNC_INFO << "Not found in calendar:" << contactId;
    }

    return event;
}

void CDBirthdayCalendar::onLocaleChanged()
{
    mKCal::Notebook::Ptr notebook = mStorage->notebook(calNotebookId);

    if (notebook.isNull()) {
        warning() << Q_FUNC_INFO << "Calendar not found while changing locale";
        return;
    }

    const QString name = qtTrId("qtn_caln_birthdays");

    debug() << Q_FUNC_INFO << "Updating calendar name to" << name;
    notebook->setName(name);

    if (not mStorage->updateNotebook(notebook)) {
        warning() << Q_FUNC_INFO << "Could not save calendar";
    }
}
<commit_msg>birthday: Make mkcal happy with whole day events<commit_after>/** This file is part of Contacts daemon
 **
 ** Copyright (c) 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
 **
 ** Contact:  Nokia Corporation (info@qt.nokia.com)
 **
 ** GNU Lesser General Public License Usage
 ** This file may be used under the terms of the GNU Lesser General Public License
 ** version 2.1 as published by the Free Software Foundation and appearing in the
 ** file LICENSE.LGPL included in the packaging of this file.  Please review the
 ** following information to ensure the GNU Lesser General Public License version
 ** 2.1 requirements will be met:
 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
 ** In addition, as a special exception, Nokia gives you certain additional rights.
 ** These rights are described in the Nokia Qt LGPL Exception version 1.1, included
 ** in the file LGPL_EXCEPTION.txt in this package.
 **
 ** Other Usage
 ** Alternatively, this file may be used in accordance with the terms and
 ** conditions contained in a signed written agreement between you and Nokia.
 **/

#include <QStringBuilder>

#include <QContactName>
#include <QContactBirthday>

#include <MLocale>

#include <recurrencerule.h>

#include "cdbirthdaycalendar.h"
#include "debug.h"

using namespace Contactsd;

// A random ID.
const QLatin1String calNotebookId("b1376da7-5555-1111-2222-227549c4e570");

CDBirthdayCalendar::CDBirthdayCalendar(SyncMode syncMode, QObject *parent) :
    QObject(parent),
    mCalendar(0),
    mStorage(0)
{
    mCalendar = mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
    mStorage = mKCal::ExtendedCalendar::defaultStorage(mCalendar);

    MLocale * const locale = new MLocale(this);

    if (not locale->isInstalledTrCatalog(QLatin1String("calendar"))) {
        locale->installTrCatalog(QLatin1String("calendar"));
    }

    locale->connectSettings();
    connect(locale, SIGNAL(settingsChanged()), this, SLOT(onLocaleChanged()));

    MLocale::setDefault(*locale);

    mStorage->open();

    mKCal::Notebook::Ptr notebook = mStorage->notebook(calNotebookId);

    if (notebook.isNull()) {
        notebook = createNotebook();
        mStorage->addNotebook(notebook);
    } else {
        // Clear the calendar database if and only if restoring from a backup.
        switch(syncMode) {
        case Incremental:
            // Force calendar name update, if a locale change happened while contactsd was not running.
            onLocaleChanged();
            break;

        case FullSync:
            mStorage->deleteNotebook(notebook);
            notebook = createNotebook();
            mStorage->addNotebook(notebook);
            break;
        }
    }
}

CDBirthdayCalendar::~CDBirthdayCalendar()
{
    if (mStorage) {
        mStorage->close();
    }

    debug() << "Destroyed birthday calendar";
}

mKCal::Notebook::Ptr CDBirthdayCalendar::createNotebook()
{
    return mKCal::Notebook::Ptr(new mKCal::Notebook(calNotebookId,
                                                    qtTrId("qtn_caln_birthdays"),
                                                    QLatin1String(""),
                                                    QLatin1String("#ff0000"),
                                                    false, // Not shared.
                                                    true, // Is master.
                                                    false, // Not synced to Ovi.
                                                    false, // Writable.
                                                    true, // Visible.
                                                    QLatin1String("Birthday-Nokia"),
                                                    QLatin1String(""),
                                                    0));
}

void CDBirthdayCalendar::updateBirthday(const QContact &contact)
{
    // Retrieve contact details.
    const QContactDisplayLabel displayName = contact.detail<QContactDisplayLabel>();
    const QContactBirthday contactBirthday = contact.detail<QContactBirthday>();

    if (displayName.isEmpty() || contactBirthday.isEmpty()) {
        warning() << Q_FUNC_INFO << "Contact without name or birthday, local ID: "
                  << contact.localId();
        return;
    }

    // Retrieve birthday event.
    if (not mStorage->isValidNotebook(calNotebookId)) {
        warning() << Q_FUNC_INFO << "Invalid notebook ID: " << calNotebookId;
        return;
    }

    KCalCore::Event::Ptr event = calendarEvent(contact.localId());

    if (event.isNull()) {
        // Add a new event.
        event = KCalCore::Event::Ptr(new KCalCore::Event());
        event->startUpdates();
        event->setUid(calendarEventId(contact.localId()));
        event->setAllDay(true);

        // Ensure events appear as birthdays in the calendar, NB#259710.
        event->setCategories(QStringList() << QLatin1String("BIRTHDAY"));

        if (not mCalendar->addEvent(event, calNotebookId)) {
            warning() << Q_FUNC_INFO << "Failed to add event to calendar";
            return;
        }
    } else {
        // Update the existing event.
        event->setReadOnly(false);
        event->startUpdates();
    }

    // Transfer birthday details from contact to calendar event.
    event->setSummary(displayName.label());

    // Event has only date information, no time.
    event->setDtStart(KDateTime(contactBirthday.date(), QTime(), KDateTime::ClockTime));
    event->setDtEnd(KDateTime(contactBirthday.date().addDays(1), QTime(), KDateTime::ClockTime));

    // Must always set the recurrence as it depends on the event date.
    KCalCore::Recurrence * const rule = event->recurrence();
    rule->setStartDateTime(event->dtStart());

    // This is not a boolean, but the frequency of the recurrence: every 1 year.
    rule->setYearly(1);

    // Set the alarms on the event
    event->clearAlarms();
    KCalCore::Alarm::Ptr alarm = event->newAlarm();
    alarm->setDisplayAlarm(event->summary());
    alarm->setStartOffset(KCalCore::Duration(-1, KCalCore::Duration::Days));

    event->setReadOnly(true);
    event->endUpdates();

    // Commit calendar changes.
    if (not mStorage->save()) {
        warning() << Q_FUNC_INFO << "Failed to save event in calendar";
        return;
    }

    debug() << "Updated birthday event in calendar, local ID: " << contact.localId();
}

void CDBirthdayCalendar::deleteBirthday(QContactLocalId contactId)
{
    KCalCore::Event::Ptr event = calendarEvent(contactId);

    if (event.isNull()) {
        debug() << Q_FUNC_INFO << "Not found in calendar:" << contactId;
        return;
    }

    mCalendar->deleteEvent(event);

    if (not mStorage->save()) {
        warning() << Q_FUNC_INFO << "Failed to delete event from calendar";
        return;
    }

    debug() << "Deleted birthday event in calendar, local ID: " << event->uid();
}

QDate CDBirthdayCalendar::birthdayDate(QContactLocalId contactId)
{
    KCalCore::Event::Ptr event = calendarEvent(contactId);

    if (event.isNull()) {
        return QDate();
    }

    return event->dtStart().date();
}

QString CDBirthdayCalendar::summary(QContactLocalId contactId)
{
    KCalCore::Event::Ptr event = calendarEvent(contactId);

    if (event.isNull()) {
        return QString();
    }

    return event->summary();
}

QString CDBirthdayCalendar::calendarEventId(QContactLocalId contactId)
{
    static const QLatin1String calIdExtension("com.nokia.birthday/");
    return calIdExtension + QString::number(contactId);
}

KCalCore::Event::Ptr CDBirthdayCalendar::calendarEvent(QContactLocalId contactId)
{
    const QString eventId = calendarEventId(contactId);

    if (not mStorage->load(eventId)) {
        warning() << Q_FUNC_INFO << "Unable to load event from calendar";
        return KCalCore::Event::Ptr();
    }

    KCalCore::Event::Ptr event = mCalendar->event(eventId);

    if (event.isNull()) {
        debug() << Q_FUNC_INFO << "Not found in calendar:" << contactId;
    }

    return event;
}

void CDBirthdayCalendar::onLocaleChanged()
{
    mKCal::Notebook::Ptr notebook = mStorage->notebook(calNotebookId);

    if (notebook.isNull()) {
        warning() << Q_FUNC_INFO << "Calendar not found while changing locale";
        return;
    }

    const QString name = qtTrId("qtn_caln_birthdays");

    debug() << Q_FUNC_INFO << "Updating calendar name to" << name;
    notebook->setName(name);

    if (not mStorage->updateNotebook(notebook)) {
        warning() << Q_FUNC_INFO << "Could not save calendar";
    }
}
<|endoftext|>


<commit_before>/*
===========================================================================
Daemon BSD Source Code
Copyright (c) 2015, Daemon Developers
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the Daemon developers nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/

#include "common/Common.h"
#include "Crypto.h"
#include <nettle/aes.h>
#include <nettle/base64.h>
#include <nettle/md5.h>
#include <nettle/sha2.h>
// HACK: include this because this pulls in nettle/version.h, which does not
//       exist in older versions of nettle.
#include <nettle/bignum.h>

// Compatibility with old nettle versions
#if !defined(AES256_KEY_SIZE)

#define AES256_KEY_SIZE 32

typedef aes_ctx compat_aes256_ctx;

static void nettle_compat_aes256_set_encrypt_key(compat_aes256_ctx *ctx, const uint8_t *key)
{
	nettle_aes_set_encrypt_key(ctx, AES256_KEY_SIZE, key);
}

static void nettle_compat_aes256_set_decrypt_key(compat_aes256_ctx *ctx, const uint8_t *key)
{
	nettle_aes_set_decrypt_key(ctx, AES256_KEY_SIZE, key);
}

static void nettle_compat_aes256_encrypt(const compat_aes256_ctx *ctx,
						   size_t length, uint8_t *dst,
						   const uint8_t *src)
{
	nettle_aes_encrypt(ctx, length, dst, src);
}

static void nettle_compat_aes256_decrypt(const compat_aes256_ctx *ctx,
						   size_t length, uint8_t *dst,
						   const uint8_t *src)
{
	nettle_aes_decrypt(ctx, length, dst, src);
}

static int nettle_compat_base64_decode_update(base64_decode_ctx *ctx,
		     size_t *dst_length,
		     uint8_t *dst,
		     size_t src_length,
		     const uint8_t *src)
{
	unsigned dst_length_uns = *dst_length;
	return nettle_base64_decode_update(ctx, &dst_length_uns, reinterpret_cast<char*>(dst), src_length, reinterpret_cast<const char*>(src));
}

#undef aes256_set_encrypt_key
#define nettle_aes256_set_encrypt_key nettle_compat_aes256_set_encrypt_key
#define nettle_aes256_set_decrypt_key nettle_compat_aes256_set_decrypt_key
#define nettle_aes256_invert_key      nettle_compat_aes256_invert_key
#define nettle_aes256_encrypt         nettle_compat_aes256_encrypt
#define nettle_aes256_decrypt         nettle_compat_aes256_decrypt
#define aes256_ctx compat_aes256_ctx
#define nettle_base64_decode_update nettle_compat_base64_decode_update

#endif // NETTLE_VERSION_MAJOR < 3

// Nettle 3.4 changed the base64 API to accept char* arguments instead of uint8_t* args. Account
// for this here.
#if NETTLE_VERSION_MAJOR >= 3 && NETTLE_VERSION_MINOR >= 4
static size_t nettle_compat_base64_encode_update(struct base64_encode_ctx *ctx,
		uint8_t *dst,
		size_t length,
		const uint8_t *src)
{
	return nettle_base64_encode_update(ctx,
			reinterpret_cast<char*>(dst),
			length,
			src);
}

static size_t nettle_compat_base64_encode_final(struct base64_encode_ctx *ctx,
		uint8_t *dst)
{
	return nettle_base64_encode_final(ctx, reinterpret_cast<char*>(dst));
}

static int nettle_compat_base64_decode_update(base64_decode_ctx *ctx,
		size_t *dst_length,
		uint8_t *dst,
		size_t src_length,
		const uint8_t *src)
{
	return nettle_base64_decode_update(ctx,
			dst_length,
			dst,
			src_length,
			reinterpret_cast<const char*>(src));
}
#define nettle_base64_encode_update nettle_compat_base64_encode_update
#define nettle_base64_encode_final nettle_compat_base64_encode_final
#define nettle_base64_decode_update nettle_compat_base64_decode_update
#endif // NETTLE_VERSION_MAJOR >= 3 || NETTLE_VERSION_MINOR >= 4

namespace Crypto {

Data RandomData( std::size_t bytes )
{
    Data data( bytes );
    Sys::GenRandomBytes(data.data(), data.size());
    return data;
}

namespace Encoding {

/*
 * Translates binary data into a hexadecimal string
 */
Data HexEncode( const Data& input )
{
    Data output;
    output.reserve(input.size()*2);
    for ( auto byte : input )
    {
        output.push_back(Str::HexDigit((byte & 0xF0) >> 4));
        output.push_back(Str::HexDigit(byte & 0xF));
    }
    return output;
}

/*
 * Translates a hexadecimal string into binary data
 * PRE: input is a valid hexadecimal string
 * POST: output contains the decoded string
 * Returns true on success
 * Note: If the decoding fails, output is unchanged
 */
bool HexDecode( const Data& input, Data& output )
{
    if ( input.size() % 2 )
    {
		return false;
    }

    Data mid( input.size() / 2 );

    for ( std::size_t i = 0; i < input.size(); i += 2 )
    {
        if ( !Str::cisxdigit( input[i] ) || !Str::cisxdigit( input[i+1] ) )
        {
            return false;
        }

        mid[ i / 2 ] = ( Str::GetHex( input[i] ) << 4 ) | Str::GetHex( input[i+1] );
    }

    output = mid;
    return true;
}

/*
 * Translates binary data into a base64 encoded string
 */
Data Base64Encode( const Data& input )
{
    base64_encode_ctx ctx;
    nettle_base64_encode_init( &ctx );

    Data output( BASE64_ENCODE_LENGTH( input.size() ) + BASE64_ENCODE_FINAL_LENGTH );
    int encoded_bytes = nettle_base64_encode_update(
        &ctx, reinterpret_cast<char*>(output.data()), input.size(), input.data()
    );
    encoded_bytes += nettle_base64_encode_final( &ctx, reinterpret_cast<char*>(output.data()) + encoded_bytes );
    output.erase( output.begin() + encoded_bytes, output.end() );
    return output;
}

/*
 * Translates a base64 encoded string into binary data
 * PRE: input is a valid Base64 string
 * POST: output contains the decoded string
 * Returns true on success
 * Note: If the decoding fails, output is unchanged
 */
bool Base64Decode( const Data& input, Data& output )
{
    base64_decode_ctx ctx;
    nettle_base64_decode_init( &ctx );

    Data temp( BASE64_DECODE_LENGTH( input.size() ) );
    std::size_t decoded_bytes = 0;
    if ( !nettle_base64_decode_update( &ctx, &decoded_bytes, temp.data(),
                                       input.size(), reinterpret_cast<const char*>(input.data()) ) )
    {
        return false;
    }

    if ( !nettle_base64_decode_final( &ctx ) )
    {
        return false;
    }

    temp.erase( temp.begin() + decoded_bytes, temp.end() );
    output = temp;
    return true;
}

} // namespace Encoding

namespace Hash {

Data Sha256( const Data& input )
{
    sha256_ctx ctx;
    nettle_sha256_init( &ctx );
    nettle_sha256_update( &ctx, input.size(), input.data() );
    Data output( SHA256_DIGEST_SIZE  );
    nettle_sha256_digest( &ctx, SHA256_DIGEST_SIZE, output.data() );
    return output;
}

Data Md5( const Data& input )
{
    md5_ctx ctx;
    nettle_md5_init( &ctx );
    nettle_md5_update( &ctx, input.size(), input.data() );
    Data output( MD5_DIGEST_SIZE );
    nettle_md5_digest( &ctx, MD5_DIGEST_SIZE, output.data() );
    return output;
}

} // namespace Hash

/*
 * Adds PKCS#7 padding to the data
 */
void AddPadding( Data& target, std::size_t block_size )
{
    auto pad = block_size - target.size() % block_size;
    target.resize( target.size() + pad, pad );
}

/*
 * Encrypts using the AES256 algorthim
 * PRE: Key is 256-bit (32 octects) long
 * POST: output contains the encrypted data
 * Notes: plain_text will be padded using the PKCS#7 algorthm,
 *        if the decoding fails, output is unchanged
 * Returns true on success
 */
bool Aes256Encrypt( Data plain_text, const Data& key, Data& output )
{
    if ( key.size() != AES256_KEY_SIZE )
    {
        return false;
    }
    aes256_ctx ctx;
    nettle_aes256_set_encrypt_key( &ctx, key.data() );
    AddPadding( plain_text, AES_BLOCK_SIZE );
    output.resize( plain_text.size(), 0 );
    nettle_aes256_encrypt( &ctx, plain_text.size(),
        output.data(), plain_text.data() );
    nettle_aes256_decrypt( &ctx, plain_text.size(),
        plain_text.data(), output.data() );
    return true;
}

/*
 * Encrypts using the AES256 algorthim
 * PRE: Key is 256-bit (32 octects) long,
 *      cypher_text.size() is an integer multiple of the AES block size
 * POST: output contains the decrypted data
 * Note: If the decoding fails, output is unchanged
 * Returns true on success
 */
bool Aes256Decrypt( Data cypher_text, const Data& key, Data& output )
{
    if ( key.size() != AES256_KEY_SIZE || cypher_text.size() % AES_BLOCK_SIZE )
    {
        return false;
    }

    aes256_ctx ctx;
    nettle_aes256_set_decrypt_key( &ctx, key.data() );
    output.resize( cypher_text.size(), 0 );
    nettle_aes256_decrypt( &ctx, cypher_text.size(),
        output.data(), cypher_text.data() );

    // Strip the PKCS#7 padding
    if ( !output.empty() )
    {
        output.erase(output.end() - output.back(), output.end());
    }

    return true;
}

} // namespace Crypto
<commit_msg>Fix compile error in base64 functions.<commit_after>/*
===========================================================================
Daemon BSD Source Code
Copyright (c) 2015, Daemon Developers
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the Daemon developers nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/

#include "common/Common.h"
#include "Crypto.h"
#include <nettle/aes.h>
#include <nettle/base64.h>
#include <nettle/md5.h>
#include <nettle/sha2.h>
// HACK: include this because this pulls in nettle/version.h, which does not
//       exist in older versions of nettle.
#include <nettle/bignum.h>

// Compatibility with old nettle versions
#if !defined(AES256_KEY_SIZE)

#define AES256_KEY_SIZE 32

typedef aes_ctx compat_aes256_ctx;

static void nettle_compat_aes256_set_encrypt_key(compat_aes256_ctx *ctx, const uint8_t *key)
{
	nettle_aes_set_encrypt_key(ctx, AES256_KEY_SIZE, key);
}

static void nettle_compat_aes256_set_decrypt_key(compat_aes256_ctx *ctx, const uint8_t *key)
{
	nettle_aes_set_decrypt_key(ctx, AES256_KEY_SIZE, key);
}

static void nettle_compat_aes256_encrypt(const compat_aes256_ctx *ctx,
						   size_t length, uint8_t *dst,
						   const uint8_t *src)
{
	nettle_aes_encrypt(ctx, length, dst, src);
}

static void nettle_compat_aes256_decrypt(const compat_aes256_ctx *ctx,
						   size_t length, uint8_t *dst,
						   const uint8_t *src)
{
	nettle_aes_decrypt(ctx, length, dst, src);
}

static int nettle_compat_base64_decode_update(base64_decode_ctx *ctx,
		     size_t *dst_length,
		     uint8_t *dst,
		     size_t src_length,
		     const uint8_t *src)
{
	unsigned dst_length_uns = *dst_length;
	return nettle_base64_decode_update(ctx, &dst_length_uns, dst, src_length, src);
}

#undef aes256_set_encrypt_key
#define nettle_aes256_set_encrypt_key nettle_compat_aes256_set_encrypt_key
#define nettle_aes256_set_decrypt_key nettle_compat_aes256_set_decrypt_key
#define nettle_aes256_invert_key      nettle_compat_aes256_invert_key
#define nettle_aes256_encrypt         nettle_compat_aes256_encrypt
#define nettle_aes256_decrypt         nettle_compat_aes256_decrypt
#define aes256_ctx compat_aes256_ctx
#define nettle_base64_decode_update nettle_compat_base64_decode_update

#endif // NETTLE_VERSION_MAJOR < 3

// Nettle 3.4 changed the base64 API to accept char* arguments instead of uint8_t* args. Account
// for this here.
#if (NETTLE_VERSION_MAJOR * 100 + NETTLE_VERSION_MINOR) >= 304
static size_t nettle_compat_base64_encode_update(struct base64_encode_ctx *ctx,
		uint8_t *dst,
		size_t length,
		const uint8_t *src)
{
	return nettle_base64_encode_update(ctx,
			reinterpret_cast<char*>(dst),
			length,
			src);
}

static size_t nettle_compat_base64_encode_final(struct base64_encode_ctx *ctx,
		uint8_t *dst)
{
	return nettle_base64_encode_final(ctx, reinterpret_cast<char*>(dst));
}

static int nettle_compat_base64_decode_update(base64_decode_ctx *ctx,
		size_t *dst_length,
		uint8_t *dst,
		size_t src_length,
		const uint8_t *src)
{
	return nettle_base64_decode_update(ctx,
			dst_length,
			dst,
			src_length,
			reinterpret_cast<const char*>(src));
}
#define nettle_base64_encode_update nettle_compat_base64_encode_update
#define nettle_base64_encode_final nettle_compat_base64_encode_final
#define nettle_base64_decode_update nettle_compat_base64_decode_update
#endif // Nettle version >= 3.4

namespace Crypto {

Data RandomData( std::size_t bytes )
{
    Data data( bytes );
    Sys::GenRandomBytes(data.data(), data.size());
    return data;
}

namespace Encoding {

/*
 * Translates binary data into a hexadecimal string
 */
Data HexEncode( const Data& input )
{
    Data output;
    output.reserve(input.size()*2);
    for ( auto byte : input )
    {
        output.push_back(Str::HexDigit((byte & 0xF0) >> 4));
        output.push_back(Str::HexDigit(byte & 0xF));
    }
    return output;
}

/*
 * Translates a hexadecimal string into binary data
 * PRE: input is a valid hexadecimal string
 * POST: output contains the decoded string
 * Returns true on success
 * Note: If the decoding fails, output is unchanged
 */
bool HexDecode( const Data& input, Data& output )
{
    if ( input.size() % 2 )
    {
		return false;
    }

    Data mid( input.size() / 2 );

    for ( std::size_t i = 0; i < input.size(); i += 2 )
    {
        if ( !Str::cisxdigit( input[i] ) || !Str::cisxdigit( input[i+1] ) )
        {
            return false;
        }

        mid[ i / 2 ] = ( Str::GetHex( input[i] ) << 4 ) | Str::GetHex( input[i+1] );
    }

    output = mid;
    return true;
}

/*
 * Translates binary data into a base64 encoded string
 */
Data Base64Encode( const Data& input )
{
    base64_encode_ctx ctx;
    nettle_base64_encode_init( &ctx );

    Data output( BASE64_ENCODE_LENGTH( input.size() ) + BASE64_ENCODE_FINAL_LENGTH );
    int encoded_bytes = nettle_base64_encode_update(
        &ctx, output.data(), input.size(), input.data()
    );
    encoded_bytes += nettle_base64_encode_final( &ctx, output.data() + encoded_bytes );
    output.erase( output.begin() + encoded_bytes, output.end() );
    return output;
}

/*
 * Translates a base64 encoded string into binary data
 * PRE: input is a valid Base64 string
 * POST: output contains the decoded string
 * Returns true on success
 * Note: If the decoding fails, output is unchanged
 */
bool Base64Decode( const Data& input, Data& output )
{
    base64_decode_ctx ctx;
    nettle_base64_decode_init( &ctx );

    Data temp( BASE64_DECODE_LENGTH( input.size() ) );
    std::size_t decoded_bytes = 0;
    if ( !nettle_base64_decode_update( &ctx, &decoded_bytes, temp.data(),
                                       input.size(), input.data() ) )
    {
        return false;
    }

    if ( !nettle_base64_decode_final( &ctx ) )
    {
        return false;
    }

    temp.erase( temp.begin() + decoded_bytes, temp.end() );
    output = temp;
    return true;
}

} // namespace Encoding

namespace Hash {

Data Sha256( const Data& input )
{
    sha256_ctx ctx;
    nettle_sha256_init( &ctx );
    nettle_sha256_update( &ctx, input.size(), input.data() );
    Data output( SHA256_DIGEST_SIZE  );
    nettle_sha256_digest( &ctx, SHA256_DIGEST_SIZE, output.data() );
    return output;
}

Data Md5( const Data& input )
{
    md5_ctx ctx;
    nettle_md5_init( &ctx );
    nettle_md5_update( &ctx, input.size(), input.data() );
    Data output( MD5_DIGEST_SIZE );
    nettle_md5_digest( &ctx, MD5_DIGEST_SIZE, output.data() );
    return output;
}

} // namespace Hash

/*
 * Adds PKCS#7 padding to the data
 */
void AddPadding( Data& target, std::size_t block_size )
{
    auto pad = block_size - target.size() % block_size;
    target.resize( target.size() + pad, pad );
}

/*
 * Encrypts using the AES256 algorthim
 * PRE: Key is 256-bit (32 octects) long
 * POST: output contains the encrypted data
 * Notes: plain_text will be padded using the PKCS#7 algorthm,
 *        if the decoding fails, output is unchanged
 * Returns true on success
 */
bool Aes256Encrypt( Data plain_text, const Data& key, Data& output )
{
    if ( key.size() != AES256_KEY_SIZE )
    {
        return false;
    }
    aes256_ctx ctx;
    nettle_aes256_set_encrypt_key( &ctx, key.data() );
    AddPadding( plain_text, AES_BLOCK_SIZE );
    output.resize( plain_text.size(), 0 );
    nettle_aes256_encrypt( &ctx, plain_text.size(),
        output.data(), plain_text.data() );
    nettle_aes256_decrypt( &ctx, plain_text.size(),
        plain_text.data(), output.data() );
    return true;
}

/*
 * Encrypts using the AES256 algorthim
 * PRE: Key is 256-bit (32 octects) long,
 *      cypher_text.size() is an integer multiple of the AES block size
 * POST: output contains the decrypted data
 * Note: If the decoding fails, output is unchanged
 * Returns true on success
 */
bool Aes256Decrypt( Data cypher_text, const Data& key, Data& output )
{
    if ( key.size() != AES256_KEY_SIZE || cypher_text.size() % AES_BLOCK_SIZE )
    {
        return false;
    }

    aes256_ctx ctx;
    nettle_aes256_set_decrypt_key( &ctx, key.data() );
    output.resize( cypher_text.size(), 0 );
    nettle_aes256_decrypt( &ctx, cypher_text.size(),
        output.data(), cypher_text.data() );

    // Strip the PKCS#7 padding
    if ( !output.empty() )
    {
        output.erase(output.end() - output.back(), output.end());
    }

    return true;
}

} // namespace Crypto
<|endoftext|>


<commit_before>/* OpenHoW
 * Copyright (C) 2017-2019 Mark Sowden <markelswo@gmail.com>
 *
 * 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, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */

#include "../engine.h"
#include "../script/script_config.h"
#include "shaders.h"

static std::map<std::string, hwShaderProgram*> programs;
static hwShaderProgram* fallbackShaderProgram = nullptr;

// For resetting following rebuild
static std::string lastProgramName;

/**
 * Validate the default shader set has been loaded.
 */
static void Shaders_ValidateDefault() {
	const char* defaultShadersStrings[] = {
		"generic_untextured",
		"generic_textured",
		"generic_textured_lit",

		"debug_normals",
		"debug_test",
	};

	for ( unsigned int i = 0; i < plArrayElements( defaultShaders ); ++i ) {
		hwShaderProgram* program = Shaders_GetProgram( defaultShadersStrings[ i ] );
		if ( program == nullptr ) {
			Error( "Failed to fetch default shader, \"%s\"!\n", defaultShaders[ i ] );
		}

		if ( i == 0 ) {
			fallbackShaderProgram = program;
		}
	}
}

static void Shaders_CacheShaderProgram( const char* path ) {
	const char* fileName = plGetFileName( path );
	if ( fileName == nullptr ) {
		LogWarn( "Failed to get filename for shader program, \"%s\"!\n", path );
		return;
	}

	// Provide a copy, minus the extension
	std::string shortFileName( fileName, 0, strlen( fileName ) - 8 );

	try {
		ScriptConfig config( path );

		config.EnterChildNode( "gl3" );

		std::string vertPath = config.GetStringProperty( "vertPath" );
		std::string fragPath = config.GetStringProperty( "fragPath" );

		if ( vertPath.empty() || fragPath.empty()) {
			// GetStringProperty throws warnings for this case, so just return
			return;
		}

		hwShaderProgram* program = new hwShaderProgram( vertPath, fragPath );
		programs.insert( std::pair<std::string, hwShaderProgram*>( shortFileName, program ));
	} catch ( const std::exception& error ) {
		LogWarn( "Failed to register shader program, %s!\n", error.what());
	}
}

static void Shaders_ClearPrograms() {
	for ( const auto& program : programs ) {
		program.second->Disable();
		delete program.second;
	}

	programs.clear();
}

static void Shaders_CachePrograms() {
	Shaders_ClearPrograms();

	char scanPath[PL_SYSTEM_MAX_PATH];
	snprintf( scanPath, sizeof( scanPath ), "%s/shaders", u_get_base_path());
	plScanDirectory( scanPath, "program", Shaders_CacheShaderProgram, false );

	// Recursive searches through dependencies... This needs revisiting!
	const char* modPath = u_get_mod_path();
	if ( modPath[ 0 ] != '\0' ) {
		snprintf( scanPath, sizeof( scanPath ), "%s/shaders", u_get_full_path());
		plScanDirectory( scanPath, "program", Shaders_CacheShaderProgram, false );
	}

	Shaders_ValidateDefault();
}

static void Cmd_RebuildShaderProgramCache( unsigned int argc, char* argv[] ) {
	u_unused( argc );
	u_unused( argv );

	Shaders_CachePrograms();
}

static void Cmd_RebuildShaderPrograms( unsigned int argc, char* argv[] ) {
	u_unused( argc );
	u_unused( argv );

	for ( const auto& program : programs ) {
		try {
			program.second->Rebuild();
		} catch ( const std::exception& exception ) {
			LogWarn( "Failed to rebuild shader program, \"%s\" (%s)!\n", program.first.c_str(), exception.what());
		}
	}

	Shaders_SetProgramByName( lastProgramName );
}

static void Cmd_RebuildShaderProgram( unsigned int argc, char* argv[] ) {
	if( argc == 0 ) {
		LogWarn( "Please provide the name of the shader program you wish to rebuild!\n" );
		return;
	} else if( argc > 1 ) {
		LogWarn( "Too many arguments, please provide only the name of the shader program you wish to rebuild!\n" );
		return;
	}

	const char* shaderProgramArg = argv[0];
	if( shaderProgramArg == NULL ) {
		LogWarn( "Invalid argument provided, please try again!\n" );
		return;
	}

	hwShaderProgram* shaderProgram = Shaders_GetProgram( shaderProgramArg );
	if( shaderProgram == nullptr ) {
		return;
	}

	try {
		shaderProgram->Rebuild();
	} catch( const std::exception& exception ) {
		LogWarn( "Failed to rebuild shader program, \"%s\" (%s)!\n", shaderProgramArg, exception.what());
	}
}

void Shaders_Initialize() {
	plRegisterConsoleCommand( "rebuildShaderPrograms", Cmd_RebuildShaderPrograms, "Rebuild all shader programs" );
	plRegisterConsoleCommand( "rebuildShaderProgram", Cmd_RebuildShaderProgram, "Rebuild specified shader program" );
	plRegisterConsoleCommand( "rebuildShaderProgramCache", Cmd_RebuildShaderProgramCache,
		"Rebuild shader program cache" );

	Shaders_CachePrograms();
}

void Shaders_Shutdown() {
	Shaders_ClearPrograms();
}

hwShaderProgram* Shaders_GetProgram( const std::string& name ) {
	const auto& i = programs.find( name );
	if ( i == programs.end()) {
		LogWarn( "Failed to find shader program, \"%s\"!\n", name.c_str());
		return nullptr;
	}

	return i->second;
}

void Shaders_SetProgram( hwShaderProgram* shaderProgram ) {
	shaderProgram->Enable();
}

void Shaders_SetProgramByName( const std::string& name ) {
	hwShaderProgram* shaderProgram = Shaders_GetProgram( name );
	if ( shaderProgram == nullptr ) {
		shaderProgram = fallbackShaderProgram;
	}

	Shaders_SetProgram( shaderProgram );
}

hwShaderProgram::hwShaderProgram( const std::string& vertPath, const std::string& fragPath ) {
	shaderProgram = plCreateShaderProgram();
	if ( shaderProgram == nullptr ) {
		throw std::runtime_error( plGetError());
	}

	try {
		RegisterShaderStage( vertPath.c_str(), PL_SHADER_TYPE_VERTEX );
		RegisterShaderStage( fragPath.c_str(), PL_SHADER_TYPE_FRAGMENT );
	} catch ( ... ) {
		plDestroyShaderProgram( shaderProgram, true );
		throw;
	}

	plLinkShaderProgram( shaderProgram );

	this->vertPath = vertPath;
	this->fragPath = fragPath;
}

hwShaderProgram::~hwShaderProgram() {
	plDestroyShaderProgram( shaderProgram, true );
}

void hwShaderProgram::Rebuild() {
	PLShaderProgram* newShaderProgram = plCreateShaderProgram();
	if ( newShaderProgram ) {
		throw std::runtime_error( plGetError());
	}

	PLShaderProgram* oldProgram = shaderProgram;
	shaderProgram = newShaderProgram;

	try {
		RegisterShaderStage( vertPath.c_str(), PL_SHADER_TYPE_VERTEX );
		RegisterShaderStage( fragPath.c_str(), PL_SHADER_TYPE_FRAGMENT );
	} catch ( const std::exception& exception ) {
		plDestroyShaderProgram( shaderProgram, true );
		shaderProgram = oldProgram;
		throw;
	}

	plLinkShaderProgram( shaderProgram );

	plDestroyShaderProgram( oldProgram, true );
}

void hwShaderProgram::Enable() {
	plSetShaderProgram( shaderProgram );
}

void hwShaderProgram::Disable() {
	plSetShaderProgram( nullptr );
}

void hwShaderProgram::RegisterShaderStage( const char* path, PLShaderType type ) {
	if ( !plRegisterShaderStageFromDisk( shaderProgram, u_find( path ), type )) {
		throw std::runtime_error( plGetError());
	}
}
<commit_msg>allow list of cached shader programs to be listed via command<commit_after>/* OpenHoW
 * Copyright (C) 2017-2019 Mark Sowden <markelswo@gmail.com>
 *
 * 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, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */

#include "../engine.h"
#include "../script/script_config.h"
#include "shaders.h"

static std::map<std::string, hwShaderProgram*> programs;
static hwShaderProgram* fallbackShaderProgram = nullptr;

// For resetting following rebuild
static std::string lastProgramName;

/**
 * Validate the default shader set has been loaded.
 */
static void Shaders_ValidateDefault() {
	const char* defaultShadersStrings[] = {
		"generic_untextured",
		"generic_textured",
		"generic_textured_lit",

		"debug_normals",
		"debug_test",
	};

	for ( unsigned int i = 0; i < plArrayElements( defaultShaders ); ++i ) {
		hwShaderProgram* program = Shaders_GetProgram( defaultShadersStrings[ i ] );
		if ( program == nullptr ) {
			Error( "Failed to fetch default shader, \"%s\"!\n", defaultShaders[ i ] );
		}

		if ( i == 0 ) {
			fallbackShaderProgram = program;
		}
	}
}

static void Shaders_CacheShaderProgram( const char* path ) {
	const char* fileName = plGetFileName( path );
	if ( fileName == nullptr ) {
		LogWarn( "Failed to get filename for shader program, \"%s\"!\n", path );
		return;
	}

	// Provide a copy, minus the extension
	std::string shortFileName( fileName, 0, strlen( fileName ) - 8 );

	try {
		ScriptConfig config( path );

		config.EnterChildNode( "gl3" );

		std::string vertPath = config.GetStringProperty( "vertPath" );
		std::string fragPath = config.GetStringProperty( "fragPath" );

		if ( vertPath.empty() || fragPath.empty()) {
			// GetStringProperty throws warnings for this case, so just return
			return;
		}

		hwShaderProgram* program = new hwShaderProgram( vertPath, fragPath );
		programs.insert( std::pair<std::string, hwShaderProgram*>( shortFileName, program ));
	} catch ( const std::exception& error ) {
		LogWarn( "Failed to register shader program (%s)!\n", error.what());
	}
}

static void Shaders_ClearPrograms() {
	for ( const auto& program : programs ) {
		program.second->Disable();
		delete program.second;
	}

	programs.clear();
}

static void Shaders_CachePrograms() {
	Shaders_ClearPrograms();

	char scanPath[PL_SYSTEM_MAX_PATH];
	snprintf( scanPath, sizeof( scanPath ), "%s/shaders", u_get_base_path());
	plScanDirectory( scanPath, "program", Shaders_CacheShaderProgram, false );

	// Recursive searches through dependencies... This needs revisiting!
	const char* modPath = u_get_mod_path();
	if ( modPath[ 0 ] != '\0' ) {
		snprintf( scanPath, sizeof( scanPath ), "%s/shaders", u_get_full_path());
		plScanDirectory( scanPath, "program", Shaders_CacheShaderProgram, false );
	}

	Shaders_ValidateDefault();
}

static void Cmd_ListShaderPrograms( unsigned int argc, char* argv[] ) {
	u_unused( argc );
	u_unused( argv );

	std::string list = "\n";
	for ( const auto& program : programs ) {
		list += program.first + "\n";
	}

	LogInfo( "%s\n", list.c_str() );
}

static void Cmd_RebuildShaderProgramCache( unsigned int argc, char* argv[] ) {
	u_unused( argc );
	u_unused( argv );

	Shaders_CachePrograms();
}

static void Cmd_RebuildShaderPrograms( unsigned int argc, char* argv[] ) {
	u_unused( argc );
	u_unused( argv );

	for ( const auto& program : programs ) {
		try {
			program.second->Rebuild();
		} catch ( const std::exception& exception ) {
			LogWarn( "Failed to rebuild shader program, \"%s\" (%s)!\n", program.first.c_str(), exception.what());
		}
	}

	Shaders_SetProgramByName( lastProgramName );
}

static void Cmd_RebuildShaderProgram( unsigned int argc, char* argv[] ) {
	if( argc == 0 ) {
		LogWarn( "Please provide the name of the shader program you wish to rebuild!\n" );
		return;
	} else if( argc > 1 ) {
		LogWarn( "Too many arguments, please provide only the name of the shader program you wish to rebuild!\n" );
		return;
	}

	const char* shaderProgramArg = argv[0];
	if( shaderProgramArg == NULL ) {
		LogWarn( "Invalid argument provided, please try again!\n" );
		return;
	}

	hwShaderProgram* shaderProgram = Shaders_GetProgram( shaderProgramArg );
	if( shaderProgram == nullptr ) {
		return;
	}

	try {
		shaderProgram->Rebuild();
	} catch( const std::exception& exception ) {
		LogWarn( "Failed to rebuild shader program, \"%s\" (%s)!\n", shaderProgramArg, exception.what());
	}
}

void Shaders_Initialize() {
	plRegisterConsoleCommand( "listShaderPrograms", Cmd_ListShaderPrograms, "Lists all of the cached shader programs" );
	plRegisterConsoleCommand( "rebuildShaderPrograms", Cmd_RebuildShaderPrograms, "Rebuild all shader programs" );
	plRegisterConsoleCommand( "rebuildShaderProgram", Cmd_RebuildShaderProgram, "Rebuild specified shader program" );
	plRegisterConsoleCommand( "rebuildShaderProgramCache", Cmd_RebuildShaderProgramCache,
		"Rebuild shader program cache" );

	Shaders_CachePrograms();
}

void Shaders_Shutdown() {
	Shaders_ClearPrograms();
}

hwShaderProgram* Shaders_GetProgram( const std::string& name ) {
	const auto& i = programs.find( name );
	if ( i == programs.end()) {
		LogWarn( "Failed to find shader program, \"%s\"!\n", name.c_str());
		return nullptr;
	}

	return i->second;
}

void Shaders_SetProgram( hwShaderProgram* shaderProgram ) {
	shaderProgram->Enable();
}

void Shaders_SetProgramByName( const std::string& name ) {
	hwShaderProgram* shaderProgram = Shaders_GetProgram( name );
	if ( shaderProgram == nullptr ) {
		shaderProgram = fallbackShaderProgram;
	}

	Shaders_SetProgram( shaderProgram );
}

hwShaderProgram::hwShaderProgram( const std::string& vertPath, const std::string& fragPath ) {
	shaderProgram = plCreateShaderProgram();
	if ( shaderProgram == nullptr ) {
		throw std::runtime_error( plGetError());
	}

	try {
		RegisterShaderStage( vertPath.c_str(), PL_SHADER_TYPE_VERTEX );
		RegisterShaderStage( fragPath.c_str(), PL_SHADER_TYPE_FRAGMENT );
	} catch ( ... ) {
		plDestroyShaderProgram( shaderProgram, true );
		throw;
	}

	plLinkShaderProgram( shaderProgram );

	this->vertPath = vertPath;
	this->fragPath = fragPath;
}

hwShaderProgram::~hwShaderProgram() {
	plDestroyShaderProgram( shaderProgram, true );
}

void hwShaderProgram::Rebuild() {
	PLShaderProgram* newShaderProgram = plCreateShaderProgram();
	if ( newShaderProgram ) {
		throw std::runtime_error( plGetError());
	}

	PLShaderProgram* oldProgram = shaderProgram;
	shaderProgram = newShaderProgram;

	try {
		RegisterShaderStage( vertPath.c_str(), PL_SHADER_TYPE_VERTEX );
		RegisterShaderStage( fragPath.c_str(), PL_SHADER_TYPE_FRAGMENT );
	} catch ( const std::exception& exception ) {
		plDestroyShaderProgram( shaderProgram, true );
		shaderProgram = oldProgram;
		throw;
	}

	plLinkShaderProgram( shaderProgram );

	plDestroyShaderProgram( oldProgram, true );
}

void hwShaderProgram::Enable() {
	plSetShaderProgram( shaderProgram );
}

void hwShaderProgram::Disable() {
	plSetShaderProgram( nullptr );
}

void hwShaderProgram::RegisterShaderStage( const char* path, PLShaderType type ) {
	if ( !plRegisterShaderStageFromDisk( shaderProgram, u_find( path ), type )) {
		throw std::runtime_error( plGetError());
	}
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016 zScale Technology GmbH <legal@zscale.io>
 * Authors:
 *   - Paul Asmuth <paul@zscale.io>
 *   - Laura Schlimmer <laura@zscale.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * 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 license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include <eventql/eventql.h>
#include <eventql/util/stdtypes.h>
#include <eventql/util/application.h>
#include <eventql/util/cli/flagparser.h>
#include <eventql/util/csv/BinaryCSVOutputStream.h>
#include <eventql/util/http/httpclient.h>
#include <eventql/util/json/jsonoutputstream.h>
#include "eventql/util/thread/FixedSizeThreadPool.h"
#include "eventql/util/util/SimpleRateLimit.h"
#include <eventql/util/mysql/MySQL.h>
#include <eventql/util/mysql/MySQLConnection.h>

using namespace eventql;

void run(const cli::FlagParser& flags) {
  auto source_table = flags.getString("source_table");
  auto destination_table = flags.getString("destination_table");
  auto shard_size = flags.getInt("shard_size");
  auto mysql_addr = flags.getString("mysql");
  auto host = flags.getString("host");
  auto port = flags.getInt("port");
  auto db = flags.getString("database");

  logInfo("mysql2evql", "Connecting to MySQL Server...");

  util::mysql::mysqlInit();
  auto mysql_conn = util::mysql::MySQLConnection::openConnection(URI(mysql_addr));

  logInfo(
      "mysql2evql",
      "Analyzing the input table. This might take a few minutes...");

  auto schema = mysql_conn->getTableSchema(source_table);
  logDebug("mysql2evql", "Table Schema:\n$0", schema->toString());
  Vector<String> column_names;
  for (const auto& field : schema->fields()) {
    column_names.emplace_back(field.name);
  }

  /* count rows */
  auto count_rows_qry = StringUtil::format(
      "SELECT count(*) FROM `$0`;",
      source_table);

  size_t num_rows = 0;
  size_t num_rows_uploaded = 0;
  mysql_conn->executeQuery(
      count_rows_qry,
      [&num_rows] (const Vector<String>& row) -> bool {
    if (row.size() == 1) num_rows = std::stoull(row[0]);
    return false;
  });

  if (num_rows == 0) {
    logError(
        "mysql2evql",
        "Table '$0' appears to be empty",
        source_table);
    return;
  }

  auto num_shards = (num_rows + shard_size - 1) / shard_size;
  logDebug("mysql2evql", "Splitting into $0 shards", num_shards);

  /* status line */
  util::SimpleRateLimitedFn status_line(
      kMicrosPerSecond,
      [&num_rows_uploaded, num_rows] () {
    logInfo(
        "mysql2evql",
        "[$0%] Uploading... $1/$2 rows",
        (size_t) ((num_rows_uploaded / (double) num_rows) * 100),
        num_rows_uploaded,
        num_rows);
  });

  /* upload rows */
  size_t nshard = 0;
  size_t num_rows_shard = 0;
  Buffer shard_data;
  json::JSONOutputStream json(BufferOutputStream::fromBuffer(&shard_data));

  auto get_rows_qry = StringUtil::format("SELECT * FROM `$0`;", source_table);
  mysql_conn->executeQuery(
      get_rows_qry,
      [&] (const Vector<String>& column_values) -> bool {
    ++num_rows_shard;
    ++num_rows_uploaded;

    if (num_rows_shard > 1) {
      json.addComma();
    }

    json.beginObject();
    json.addObjectEntry("database");
    json.addString(db);
    json.addComma();
    json.addObjectEntry("table");
    json.addString(destination_table);
    json.addComma();
    json.addObjectEntry("data");
    json.beginObject();

    for (size_t i = 0; i < column_names.size() && i < column_values.size(); ++i) {
      if (i > 0 ){
        json.addComma();
      }

      json.addObjectEntry(column_names[i]);
      json.addString(column_values[i]);
    }

    json.endObject();
    json.endObject();

    if (num_rows_shard == shard_size ||
        num_rows_uploaded == num_rows) {
      logDebug(
          "mysql2evql",
          "Uploading shard $0; size=$1MB",
          nshard + 1,
          shard_data.size() / 1000000.0);

      auto insert_uri = StringUtil::format(
          "http://$0:$1/api/v1/tables/insert",
          host,
          port);

      http::HTTPMessage::HeaderList auth_headers;
      if (flags.isSet("auth_token")) {
        auth_headers.emplace_back(
            "Authorization",
            StringUtil::format("Token $0", flags.getString("auth_token")));
      //} else if (!cfg_.getPassword().isEmpty()) {
      //  auth_headers.emplace_back(
      //      "Authorization",
      //      StringUtil::format("Basic $0",
      //          util::Base64::encode(
      //              cfg_.getUser() + ":" + cfg_.getPassword().get())));
      }

      http::HTTPClient http_client;
      auto upload_res = http_client.executeRequest(
          http::HTTPRequest::mkPost(
              insert_uri,
              "[" + shard_data.toString() + "]",
              auth_headers));

      logDebug("mysql2evql", "Upload finished: $0", insert_uri);
      if (upload_res.statusCode() != 201) {
        RAISE(kRuntimeError, upload_res.body().toString());
      }

      shard_data.clear();
      num_rows_shard = 0;
      ++nshard;
    }

    if (num_rows_uploaded < num_rows) {
      status_line.runMaybe();
      return true;
    } else {
      return false;
    }
  });

  status_line.runForce();

  logInfo("mysql2evql", "Upload finished successfully :)");
  exit(0);
}

int main(int argc, const char** argv) {
  Application::init();
  Application::logToStderr("mysql2evql");

  cli::FlagParser flags;

  flags.defineFlag(
      "loglevel",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.defineFlag(
      "source_table",
      cli::FlagParser::T_STRING,
      true,
      "t",
      NULL,
      "table name",
      "<name>");

  flags.defineFlag(
      "destination_table",
      cli::FlagParser::T_STRING,
      true,
      "t",
      NULL,
      "table name",
      "<name>");

  flags.defineFlag(
      "host",
      cli::FlagParser::T_STRING,
      true,
      "h",
      NULL,
      "eventql server hostname",
      "<host>");

  flags.defineFlag(
      "port",
      cli::FlagParser::T_INTEGER,
      true,
      "p",
      NULL,
      "eventql server port",
      "<port>");

  flags.defineFlag(
      "database",
      cli::FlagParser::T_STRING,
      false,
      "db",
      "",
      "eventql database",
      "<database>");

  flags.defineFlag(
      "auth_token",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "auth token",
      "<token>");

  flags.defineFlag(
      "mysql",
      cli::FlagParser::T_STRING,
      true,
      "x",
      "mysql://localhost:3306/mydb?user=root",
      "MySQL connection string",
      "<url>");

  flags.defineFlag(
      "shard_size",
      cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "128",
      "shard size",
      "<num>");

  try {
    flags.parseArgv(argc, argv);
  } catch (const StandardException& e) {
    logError("mysql2evql", "$0", e.what());
    auto stdout_os = OutputStream::getStdout();
    flags.printUsage(stdout_os.get());
    return 0;
  }

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  try {
    run(flags);
  } catch (const StandardException& e) {
    logError("mysql2evql", "[FATAL ERROR] $0", e.what());
  }

  return 0;
}
<commit_msg>mysql2evql uploadTable method<commit_after>/**
 * Copyright (c) 2016 zScale Technology GmbH <legal@zscale.io>
 * Authors:
 *   - Paul Asmuth <paul@zscale.io>
 *   - Laura Schlimmer <laura@zscale.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * 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 license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include <eventql/eventql.h>
#include <eventql/util/stdtypes.h>
#include <eventql/util/application.h>
#include <eventql/util/cli/flagparser.h>
#include <eventql/util/csv/BinaryCSVOutputStream.h>
#include <eventql/util/http/httpclient.h>
#include <eventql/util/json/jsonoutputstream.h>
#include "eventql/util/thread/FixedSizeThreadPool.h"
#include "eventql/util/util/SimpleRateLimit.h"
#include <eventql/util/mysql/MySQL.h>
#include <eventql/util/mysql/MySQLConnection.h>

using namespace eventql;

Status uploadTable(
    const String& host,
    const uint64_t port,
    http::HTTPMessage::HeaderList* auth_headers,
    Buffer* shard_data,
    const size_t nshard) {
  logDebug(
      "mysql2evql",
      "Uploading shard $0; size=$1MB",
      nshard + 1,
      shard_data->size() / 1000000.0);

  auto insert_uri = StringUtil::format(
      "http://$0:$1/api/v1/tables/insert",
      host,
      port);

  http::HTTPClient http_client;
  auto upload_res = http_client.executeRequest(
      http::HTTPRequest::mkPost(
          insert_uri,
          "[" + shard_data->toString() + "]",
          *auth_headers));

  logDebug("mysql2evql", "Upload finished: $0", insert_uri);
  if (upload_res.statusCode() != 201) {
    return Status(eRuntimeError, upload_res.body().toString());
  }

  return Status::success();
}

void run(const cli::FlagParser& flags) {
  auto source_table = flags.getString("source_table");
  auto destination_table = flags.getString("destination_table");
  auto shard_size = flags.getInt("shard_size");
  auto mysql_addr = flags.getString("mysql");
  auto host = flags.getString("host");
  auto port = flags.getInt("port");
  auto db = flags.getString("database");

  logInfo("mysql2evql", "Connecting to MySQL Server...");

  util::mysql::mysqlInit();
  auto mysql_conn = util::mysql::MySQLConnection::openConnection(URI(mysql_addr));

  logInfo(
      "mysql2evql",
      "Analyzing the input table. This might take a few minutes...");

  auto schema = mysql_conn->getTableSchema(source_table);
  logDebug("mysql2evql", "Table Schema:\n$0", schema->toString());
  Vector<String> column_names;
  for (const auto& field : schema->fields()) {
    column_names.emplace_back(field.name);
  }

  /* count rows */
  auto count_rows_qry = StringUtil::format(
      "SELECT count(*) FROM `$0`;",
      source_table);

  size_t num_rows = 0;
  size_t num_rows_uploaded = 0;
  mysql_conn->executeQuery(
      count_rows_qry,
      [&num_rows] (const Vector<String>& row) -> bool {
    if (row.size() == 1) num_rows = std::stoull(row[0]);
    return false;
  });

  if (num_rows == 0) {
    logError(
        "mysql2evql",
        "Table '$0' appears to be empty",
        source_table);
    return;
  }

  auto num_shards = (num_rows + shard_size - 1) / shard_size;
  logDebug("mysql2evql", "Splitting into $0 shards", num_shards);

  /* status line */
  util::SimpleRateLimitedFn status_line(
      kMicrosPerSecond,
      [&num_rows_uploaded, num_rows] () {
    logInfo(
        "mysql2evql",
        "[$0%] Uploading... $1/$2 rows",
        (size_t) ((num_rows_uploaded / (double) num_rows) * 100),
        num_rows_uploaded,
        num_rows);
  });

  /* upload rows */
  size_t nshard = 0;
  size_t num_rows_shard = 0;

  http::HTTPMessage::HeaderList auth_headers;
  if (flags.isSet("auth_token")) {
    auth_headers.emplace_back(
        "Authorization",
        StringUtil::format("Token $0", flags.getString("auth_token")));
  //} else if (!cfg_.getPassword().isEmpty()) {
  //  auth_headers.emplace_back(
  //      "Authorization",
  //      StringUtil::format("Basic $0",
  //          util::Base64::encode(
  //              cfg_.getUser() + ":" + cfg_.getPassword().get())));
  }

  Buffer shard_data;
  json::JSONOutputStream json(BufferOutputStream::fromBuffer(&shard_data));

  auto get_rows_qry = StringUtil::format("SELECT * FROM `$0`;", source_table);
  mysql_conn->executeQuery(
      get_rows_qry,
      [&] (const Vector<String>& column_values) -> bool {
    ++num_rows_shard;
    ++num_rows_uploaded;

    if (num_rows_shard > 1) {
      json.addComma();
    }

    json.beginObject();
    json.addObjectEntry("database");
    json.addString(db);
    json.addComma();
    json.addObjectEntry("table");
    json.addString(destination_table);
    json.addComma();
    json.addObjectEntry("data");
    json.beginObject();

    for (size_t i = 0; i < column_names.size() && i < column_values.size(); ++i) {
      if (i > 0 ){
        json.addComma();
      }

      json.addObjectEntry(column_names[i]);
      json.addString(column_values[i]);
    }

    json.endObject();
    json.endObject();

    if (num_rows_shard == shard_size) {
      uploadTable(host, port, &auth_headers, &shard_data, nshard);
      shard_data.clear();
      num_rows_shard = 0;
      ++nshard;
    }

    if (num_rows_uploaded < num_rows) {
      status_line.runMaybe();
      return true;
    } else {
      if (num_rows_shard > 0) {
        uploadTable(host, port, &auth_headers, &shard_data, nshard);
      }
      return false;
    }
  });

  status_line.runForce();

  logInfo("mysql2evql", "Upload finished successfully :)");
  exit(0);
}

int main(int argc, const char** argv) {
  Application::init();
  Application::logToStderr("mysql2evql");

  cli::FlagParser flags;

  flags.defineFlag(
      "loglevel",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.defineFlag(
      "source_table",
      cli::FlagParser::T_STRING,
      true,
      "t",
      NULL,
      "table name",
      "<name>");

  flags.defineFlag(
      "destination_table",
      cli::FlagParser::T_STRING,
      true,
      "t",
      NULL,
      "table name",
      "<name>");

  flags.defineFlag(
      "host",
      cli::FlagParser::T_STRING,
      true,
      "h",
      NULL,
      "eventql server hostname",
      "<host>");

  flags.defineFlag(
      "port",
      cli::FlagParser::T_INTEGER,
      true,
      "p",
      NULL,
      "eventql server port",
      "<port>");

  flags.defineFlag(
      "database",
      cli::FlagParser::T_STRING,
      false,
      "db",
      "",
      "eventql database",
      "<database>");

  flags.defineFlag(
      "auth_token",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "auth token",
      "<token>");

  flags.defineFlag(
      "mysql",
      cli::FlagParser::T_STRING,
      true,
      "x",
      "mysql://localhost:3306/mydb?user=root",
      "MySQL connection string",
      "<url>");

  flags.defineFlag(
      "shard_size",
      cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "128",
      "shard size",
      "<num>");

  try {
    flags.parseArgv(argc, argv);
  } catch (const StandardException& e) {
    logError("mysql2evql", "$0", e.what());
    auto stdout_os = OutputStream::getStdout();
    flags.printUsage(stdout_os.get());
    return 0;
  }

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  try {
    run(flags);
  } catch (const StandardException& e) {
    logError("mysql2evql", "[FATAL ERROR] $0", e.what());
  }

  return 0;
}
<|endoftext|>