<commit_before>#include "view.hpp"
#include "view-transform.hpp"
#include "output.hpp"
#include <linux/input.h>

class wf_wrot : public wayfire_plugin_t
{
    button_callback call;
    public:
        void init(wayfire_config *config)
        {
            call = [=] (uint32_t x, int, int)
            {
                output->activate_plugin(grab_interface);
                grab_interface->grab();
            };

            output->add_button(WLR_MODIFIER_ALT, BTN_RIGHT, &call);

            grab_interface->callbacks.pointer.motion = [=] (int, int)
            {
                auto view = output->get_top_view();

                if (!view->get_transformer())
                    view->set_transformer(std::unique_ptr<wf_2D_view> (new wf_2D_view(output)));

                auto tr = dynamic_cast<wf_2D_view*> (view->get_transformer());
                view->damage();
                tr->angle += 0.02;
                view->damage();
            };

            grab_interface->callbacks.pointer.button = [=] (uint32_t, uint32_t s)
            {
                if (s == WLR_BUTTON_RELEASED)
                {
                    grab_interface->ungrab();
                    output->deactivate_plugin(grab_interface);
                }
            };
        }
};

extern "C"
{
wayfire_plugin_t *newInstance()
{
    return new wf_wrot;
}
}
<commit_msg>wrot: don't rotate constantly, but following the mouse<commit_after>#include "view.hpp"
#include "view-transform.hpp"
#include "output.hpp"
#include <linux/input.h>

static double cross (double x1, double y1, double x2, double y2) // cross product
{
    return x1 * y2 - x2 * y1;
}

static double vlen(double x1, double y1) // length of vector centered at the origin
{
    return std::sqrt(x1 * x1 + y1 * y1);
}

class wf_wrot : public wayfire_plugin_t
{
    button_callback call;

    int last_x, last_y;
    public:
        void init(wayfire_config *config)
        {
            call = [=] (uint32_t, int x, int y)
            {
                output->activate_plugin(grab_interface);
                grab_interface->grab();

                last_x = x;
                last_y = y;
            };

            output->add_button(WLR_MODIFIER_ALT, BTN_RIGHT, &call);

            grab_interface->callbacks.pointer.motion = [=] (int x, int y)
            {
                auto view = output->get_top_view();

                if (!view->get_transformer())
                    view->set_transformer(std::unique_ptr<wf_2D_view> (new wf_2D_view(output)));

                auto tr = dynamic_cast<wf_2D_view*> (view->get_transformer());

                view->damage();

                auto g = view->get_wm_geometry();

                double cx = g.x + g.width / 2.0;
                double cy = g.y + g.height / 2.0;

                double x1 = last_x - cx, y1 = last_y - cy;
                double x2 = x - cx, y2 = y - cy;

                /* cross(a, b) = |a| * |b| * sin(a, b) */
                tr->angle += std::asin(cross(x1, y1, x2, y2) / vlen(x1, y1) / vlen(x2, y2));

                view->damage();

                last_x = x;
                last_y = y;
            };

            grab_interface->callbacks.pointer.button = [=] (uint32_t, uint32_t s)
            {
                if (s == WLR_BUTTON_RELEASED)
                {
                    grab_interface->ungrab();
                    output->deactivate_plugin(grab_interface);
                }
            };
        }
};

extern "C"
{
wayfire_plugin_t *newInstance()
{
    return new wf_wrot;
}
}
<|endoftext|>


<commit_before>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...))
{
  static L const l_(::std::forward<L>(l));

  struct S
  {
    static R f(A... args) noexcept(noexcept(l_(::std::declval<A>()...)))
    {
      return l_(::std::forward<A>(args)...);
    }
  };

  return &S::f;
}

}

template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_CIFY_HPP
# define GENERIC_CIFY_HPP
# pragma once

#include <utility>

namespace generic
{

namespace
{

template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...))
{
  static L const l_(::std::forward<L>(l));

  struct S
  {
    static R f(A... args) noexcept(noexcept(l_(::std::forward<A>(args)...)))
    {
      return l_(::std::forward<A>(args)...);
    }
  };

  return &S::f;
}

}

template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
  return cify<F, I>(::std::forward<L>(l), F());
}

}

#endif // GENERIC_CIFY_HPP
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993-2011 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// logDetail.cpp : Plugin module for logging server events to stdout
//

#include <iostream>
#include <sstream>
#include <cstring>
#include "bzfsAPI.h"

enum action { join , auth , part };

class LogDetail : public bz_Plugin
{
public:
  virtual const char* Name (){return "Log Detail";}
  virtual void Init ( const char* config);
  virtual void Cleanup ();
  virtual void Event ( bz_EventData *eventData );
private:
  std::string displayPlayerPrivs( int playerID );
  std::string displayCallsign( bz_ApiString callsign );
  std::string displayCallsign( int playerID );
  std::string displayBZid( int playerID );
  std::string displayTeam( bz_eTeamType team );
  virtual void listPlayers( action act, bz_PlayerJoinPartEventData_V1 *data );
};

BZ_PLUGIN(LogDetail)

void LogDetail::Init ( const char* /*commandLine*/ )
{
  Register(bz_eSlashCommandEvent);
  Register(bz_eRawChatMessageEvent);
  Register(bz_eServerMsgEvent);
  Register(bz_ePlayerJoinEvent);
  Register(bz_ePlayerPartEvent);
  Register(bz_ePlayerAuthEvent);
  Register(bz_eMessageFilteredEvent);

  bz_debugMessage(0, "SERVER-STATUS Running");
  bz_debugMessagef(0, "SERVER-MAPNAME %s", bz_getPublicDescription().c_str());
  listPlayers( join , NULL );
}

void LogDetail::Cleanup()
{
  listPlayers( part , NULL );
  bz_debugMessage(0, "SERVER-STATUS Stopped");
  Flush();
}

void LogDetail::Event( bz_EventData *eventData )
{
  bz_ChatEventData_V1 *chatData = (bz_ChatEventData_V1 *) eventData;
  bz_ServerMsgEventData_V1 *serverMsgData = (bz_ServerMsgEventData_V1 *) eventData;
  bz_SlashCommandEventData_V1 *cmdData = (bz_SlashCommandEventData_V1 *) eventData;
  bz_PlayerJoinPartEventData_V1 *joinPartData = (bz_PlayerJoinPartEventData_V1 *) eventData;
  bz_PlayerAuthEventData_V1 *authData = (bz_PlayerAuthEventData_V1 *) eventData;
  bz_MessageFilteredEventData_V1 *filteredData = (bz_MessageFilteredEventData_V1 *) eventData;
  char temp[9] = {0};

  if (eventData) {
    switch (eventData->eventType) {
      case bz_eSlashCommandEvent:
	// Slash commands are case insensitive
	// Tokenize the stream and check the first word
	// /report -> MSG-REPORT
	// anything -> MSG-COMMAND

	strncpy(temp, cmdData->message.c_str(), 8);

	if (strcasecmp( temp, "/REPORT ") == 0) {
	  bz_debugMessagef(0, "MSG-REPORT %s %s",
			   displayCallsign( cmdData->from ).c_str(),
			   cmdData->message.c_str()+8);
	} else {
	  bz_debugMessagef(0, "MSG-COMMAND %s %s",
			   displayCallsign( cmdData->from ).c_str(),
			   cmdData->message.c_str()+1);
	}
	break;
      case bz_eRawChatMessageEvent:
	if ((chatData->to == BZ_ALLUSERS) && (chatData->team == eNoTeam)) {
	  bz_debugMessagef(0, "MSG-BROADCAST %s %s",
			   displayCallsign( chatData->from ).c_str(),
			   chatData->message.c_str());
	} else if (chatData->to == BZ_NULLUSER) {
	  if (chatData->team == eAdministrators) {
	    bz_debugMessagef(0, "MSG-ADMIN %s %s",
			     displayCallsign( chatData->from ).c_str(),
			     chatData->message.c_str());
	  } else {
	    bz_debugMessagef(0, "MSG-TEAM %s %s %s",
			     displayCallsign( chatData->from ).c_str(),
			     displayTeam( chatData->team ).c_str(),
			     chatData->message.c_str());
	  }
	} else {
	  bz_debugMessagef(0, "MSG-DIRECT %s %s %s",
			   displayCallsign( chatData->from ).c_str(),
			   displayCallsign( chatData->to ).c_str(),
			   chatData->message.c_str());
	}
	break;
      case bz_eMessageFilteredEvent:
	bz_debugMessagef(0, "MSG-FILTERED %s %s",
			 displayCallsign( filteredData->playerID ).c_str(),
			 filteredData->filteredMessage.c_str());
	break;
      case bz_eServerMsgEvent:
	if ((serverMsgData->to == BZ_ALLUSERS) && (serverMsgData->team == eNoTeam)) {
	  bz_debugMessagef(0, "MSG-BROADCAST 6:SERVER %s",
			   serverMsgData->message.c_str());
	} else if (serverMsgData->to == BZ_NULLUSER) {
	  if (serverMsgData->team == eAdministrators) {
	    bz_debugMessagef(0, "MSG-ADMIN 6:SERVER %s",
			     serverMsgData->message.c_str());
	  } else {
	    bz_debugMessagef(0, "MSG-TEAM 6:SERVER %s %s",
			     displayTeam( serverMsgData->team ).c_str(),
			     serverMsgData->message.c_str());
	  }
	} else {
	  bz_debugMessagef(0, "MSG-DIRECT 6:SERVER %s %s",
			   displayCallsign( serverMsgData->to ).c_str(),
			   serverMsgData->message.c_str());
	}
	break;
      case bz_ePlayerJoinEvent:
	{
	  if (joinPartData->record) {
	    bz_debugMessagef(0, "PLAYER-JOIN %s #%d%s %s %s",
			     displayCallsign( joinPartData->playerID).c_str(),
			     joinPartData->playerID,
			     displayBZid( joinPartData->playerID ).c_str(),
			     displayTeam( joinPartData->record->team ).c_str(),
			     displayPlayerPrivs( joinPartData->playerID ).c_str());
	    listPlayers( join, joinPartData);
	  }
	}
	break;
      case bz_ePlayerPartEvent:
	bz_debugMessagef(0, "PLAYER-PART %s #%d%s %s",
			 displayCallsign( joinPartData->playerID ).c_str(),
			 joinPartData->playerID,
			 displayBZid( joinPartData->playerID ).c_str(),
			 joinPartData->reason.c_str());
	listPlayers( part, joinPartData);
	break;
      case bz_ePlayerAuthEvent:
	bz_debugMessagef(0, "PLAYER-AUTH %s %s",
			 displayCallsign( authData->playerID ).c_str(),
			 displayPlayerPrivs( authData->playerID ).c_str()),
	listPlayers( join, joinPartData);
	break;
      default :
	break;
    }
  }
}

std::string LogDetail::displayBZid( int playerID )
{
  std::ostringstream bzid;

  bz_BasePlayerRecord *player = bz_getPlayerByIndex( playerID );
  if (player) {
    if (player->globalUser)
      bzid << " BZid:" << player->bzID.c_str();
    bz_freePlayerRecord( player );
  }

  return bzid.str();
}

std::string LogDetail::displayPlayerPrivs( int playerID )
{
  std::ostringstream playerPrivs;

  bz_BasePlayerRecord *player = bz_getPlayerByIndex( playerID );
  if (player) {
    playerPrivs << "IP:" << player->ipAddress.c_str();
    if (player->verified ) playerPrivs << " VERIFIED";
    if (player->globalUser ) playerPrivs << " GLOBALUSER";
    if (player->admin ) playerPrivs << " ADMIN";
    if (player->op ) playerPrivs << " OPERATOR";
    bz_freePlayerRecord( player );
  } else {
    playerPrivs << "IP:0.0.0.0";
  }

  return playerPrivs.str();
}

std::string LogDetail::displayCallsign( bz_ApiString callsign )
{
  std::ostringstream result;

  result << strlen( callsign.c_str() ) << ":" << callsign.c_str();

  return result.str();
}

std::string LogDetail::displayCallsign( int playerID )
{
  std::ostringstream callsign;
  bz_BasePlayerRecord *player = bz_getPlayerByIndex( playerID );
  if (player) {
    callsign << strlen( player->callsign.c_str() ) << ":";
    callsign << player->callsign.c_str();
    bz_freePlayerRecord( player );
  } else {
    callsign << "7:UNKNOWN";
  }
  return callsign.str();
}

std::string LogDetail::displayTeam( bz_eTeamType team )
{
  // Display the player team
  switch ( team ) {
    case eRogueTeam:
      return std::string("ROGUE");
    case eRedTeam:
      return std::string("RED");
    case eGreenTeam:
      return std::string("GREEN");
    case eBlueTeam:
      return std::string("BLUE");
    case ePurpleTeam:
      return std::string("PURPLE");
    case eRabbitTeam:
      return std::string("RABBIT");
    case eHunterTeam:
      return std::string("HUNTER");
    case eObservers:
      return std::string("OBSERVER");
    default :
      return std::string("NOTEAM");
  }
}

void LogDetail::listPlayers( action act , bz_PlayerJoinPartEventData_V1 *data )
{
  bz_APIIntList *playerList = bz_newIntList();
  bz_BasePlayerRecord *player = NULL;
  std::ostringstream msg;
  char playerStatus;
  int numPlayers;

  bz_getPlayerIndexList( playerList );

  bz_debugMessage( 4 , "Players:" );
  //
  // Count number of players
  //
  numPlayers = 0;
  for ( unsigned int i = 0; i < playerList->size(); i++ ) {
    player = bz_getPlayerByIndex( playerList->get(i));
    if (player) {
      if ((player->callsign != "") && (act == join || act == auth || (data && (player->playerID != data->playerID))))
	numPlayers++;
      bz_freePlayerRecord( player );
    }
  }

  //
  // Display number of players, callsign, and motto string in the following format:
  //
  // PLAYERS (nn) [G]cc:callsign(ee:mottostring)
  // nn - number of players
  // G	- global auth identifier (+|-| |@)
  // cc - count of characters in player callsign
  // callsign - player callsign
  // ee - count of characters in motto string
  // mottostring - player motto string
  //
  // eg.
  // PLAYERS (2) [@]7:Thumper(16:me@somewhere.net) [ ]3:xxx()
  //
  msg.str("");
  msg << "PLAYERS (" << numPlayers << ") ";
  for ( unsigned int i = 0; i < playerList->size(); i++ ) {
    player = bz_getPlayerByIndex( playerList->get(i));
    if (player) {
      if ((player->callsign != "") && (act == join || act == auth || (data && (player->playerID != data->playerID)))) {
	playerStatus = ' ';
	if (player->globalUser) playerStatus = '+';
	if (player->verified) playerStatus = '+';
	if (player->admin && !bz_hasPerm(player->playerID, bz_perm_hideAdmin)) playerStatus = '@';
	msg << "[" << playerStatus << "]";
	msg << player->callsign.size() << ':';
	msg << player->callsign.c_str();
      }
    }
  }
  bz_debugMessage(0, msg.str().c_str());

  bz_deleteIntList(playerList);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<commit_msg>Add player motto string for PLAYERS data line and fix the output format<commit_after>/* bzflag
 * Copyright (c) 1993-2011 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// logDetail.cpp : Plugin module for logging server events to stdout
//

#include <iostream>
#include <sstream>
#include <cstring>
#include "bzfsAPI.h"

enum action { join , auth , part };

class LogDetail : public bz_Plugin
{
public:
  virtual const char* Name (){return "Log Detail";}
  virtual void Init ( const char* config);
  virtual void Cleanup ();
  virtual void Event ( bz_EventData *eventData );
private:
  std::string displayPlayerPrivs( int playerID );
  std::string displayCallsign( bz_ApiString callsign );
  std::string displayCallsign( int playerID );
  std::string displayBZid( int playerID );
  std::string displayTeam( bz_eTeamType team );
  virtual void listPlayers( action act, bz_PlayerJoinPartEventData_V1 *data );
};

BZ_PLUGIN(LogDetail)

void LogDetail::Init ( const char* /*commandLine*/ )
{
  Register(bz_eSlashCommandEvent);
  Register(bz_eRawChatMessageEvent);
  Register(bz_eServerMsgEvent);
  Register(bz_ePlayerJoinEvent);
  Register(bz_ePlayerPartEvent);
  Register(bz_ePlayerAuthEvent);
  Register(bz_eMessageFilteredEvent);

  bz_debugMessage(0, "SERVER-STATUS Running");
  bz_debugMessagef(0, "SERVER-MAPNAME %s", bz_getPublicDescription().c_str());
  listPlayers( join , NULL );
}

void LogDetail::Cleanup()
{
  listPlayers( part , NULL );
  bz_debugMessage(0, "SERVER-STATUS Stopped");
  Flush();
}

void LogDetail::Event( bz_EventData *eventData )
{
  bz_ChatEventData_V1 *chatData = (bz_ChatEventData_V1 *) eventData;
  bz_ServerMsgEventData_V1 *serverMsgData = (bz_ServerMsgEventData_V1 *) eventData;
  bz_SlashCommandEventData_V1 *cmdData = (bz_SlashCommandEventData_V1 *) eventData;
  bz_PlayerJoinPartEventData_V1 *joinPartData = (bz_PlayerJoinPartEventData_V1 *) eventData;
  bz_PlayerAuthEventData_V1 *authData = (bz_PlayerAuthEventData_V1 *) eventData;
  bz_MessageFilteredEventData_V1 *filteredData = (bz_MessageFilteredEventData_V1 *) eventData;
  char temp[9] = {0};

  if (eventData) {
    switch (eventData->eventType) {
      case bz_eSlashCommandEvent:
	// Slash commands are case insensitive
	// Tokenize the stream and check the first word
	// /report -> MSG-REPORT
	// anything -> MSG-COMMAND

	strncpy(temp, cmdData->message.c_str(), 8);

	if (strcasecmp( temp, "/REPORT ") == 0) {
	  bz_debugMessagef(0, "MSG-REPORT %s %s",
			   displayCallsign( cmdData->from ).c_str(),
			   cmdData->message.c_str()+8);
	} else {
	  bz_debugMessagef(0, "MSG-COMMAND %s %s",
			   displayCallsign( cmdData->from ).c_str(),
			   cmdData->message.c_str()+1);
	}
	break;
      case bz_eRawChatMessageEvent:
	if ((chatData->to == BZ_ALLUSERS) && (chatData->team == eNoTeam)) {
	  bz_debugMessagef(0, "MSG-BROADCAST %s %s",
			   displayCallsign( chatData->from ).c_str(),
			   chatData->message.c_str());
	} else if (chatData->to == BZ_NULLUSER) {
	  if (chatData->team == eAdministrators) {
	    bz_debugMessagef(0, "MSG-ADMIN %s %s",
			     displayCallsign( chatData->from ).c_str(),
			     chatData->message.c_str());
	  } else {
	    bz_debugMessagef(0, "MSG-TEAM %s %s %s",
			     displayCallsign( chatData->from ).c_str(),
			     displayTeam( chatData->team ).c_str(),
			     chatData->message.c_str());
	  }
	} else {
	  bz_debugMessagef(0, "MSG-DIRECT %s %s %s",
			   displayCallsign( chatData->from ).c_str(),
			   displayCallsign( chatData->to ).c_str(),
			   chatData->message.c_str());
	}
	break;
      case bz_eMessageFilteredEvent:
	bz_debugMessagef(0, "MSG-FILTERED %s %s",
			 displayCallsign( filteredData->playerID ).c_str(),
			 filteredData->filteredMessage.c_str());
	break;
      case bz_eServerMsgEvent:
	if ((serverMsgData->to == BZ_ALLUSERS) && (serverMsgData->team == eNoTeam)) {
	  bz_debugMessagef(0, "MSG-BROADCAST 6:SERVER %s",
			   serverMsgData->message.c_str());
	} else if (serverMsgData->to == BZ_NULLUSER) {
	  if (serverMsgData->team == eAdministrators) {
	    bz_debugMessagef(0, "MSG-ADMIN 6:SERVER %s",
			     serverMsgData->message.c_str());
	  } else {
	    bz_debugMessagef(0, "MSG-TEAM 6:SERVER %s %s",
			     displayTeam( serverMsgData->team ).c_str(),
			     serverMsgData->message.c_str());
	  }
	} else {
	  bz_debugMessagef(0, "MSG-DIRECT 6:SERVER %s %s",
			   displayCallsign( serverMsgData->to ).c_str(),
			   serverMsgData->message.c_str());
	}
	break;
      case bz_ePlayerJoinEvent:
	{
	  if (joinPartData->record) {
	    bz_debugMessagef(0, "PLAYER-JOIN %s #%d%s %s %s",
			     displayCallsign( joinPartData->playerID).c_str(),
			     joinPartData->playerID,
			     displayBZid( joinPartData->playerID ).c_str(),
			     displayTeam( joinPartData->record->team ).c_str(),
			     displayPlayerPrivs( joinPartData->playerID ).c_str());
	    listPlayers( join, joinPartData);
	  }
	}
	break;
      case bz_ePlayerPartEvent:
	bz_debugMessagef(0, "PLAYER-PART %s #%d%s %s",
			 displayCallsign( joinPartData->playerID ).c_str(),
			 joinPartData->playerID,
			 displayBZid( joinPartData->playerID ).c_str(),
			 joinPartData->reason.c_str());
	listPlayers( part, joinPartData);
	break;
      case bz_ePlayerAuthEvent:
	bz_debugMessagef(0, "PLAYER-AUTH %s %s",
			 displayCallsign( authData->playerID ).c_str(),
			 displayPlayerPrivs( authData->playerID ).c_str()),
	listPlayers( join, joinPartData);
	break;
      default :
	break;
    }
  }
}

std::string LogDetail::displayBZid( int playerID )
{
  std::ostringstream bzid;

  bz_BasePlayerRecord *player = bz_getPlayerByIndex( playerID );
  if (player) {
    if (player->globalUser)
      bzid << " BZid:" << player->bzID.c_str();
    bz_freePlayerRecord( player );
  }

  return bzid.str();
}

std::string LogDetail::displayPlayerPrivs( int playerID )
{
  std::ostringstream playerPrivs;

  bz_BasePlayerRecord *player = bz_getPlayerByIndex( playerID );
  if (player) {
    playerPrivs << "IP:" << player->ipAddress.c_str();
    if (player->verified ) playerPrivs << " VERIFIED";
    if (player->globalUser ) playerPrivs << " GLOBALUSER";
    if (player->admin ) playerPrivs << " ADMIN";
    if (player->op ) playerPrivs << " OPERATOR";
    bz_freePlayerRecord( player );
  } else {
    playerPrivs << "IP:0.0.0.0";
  }

  return playerPrivs.str();
}

std::string LogDetail::displayCallsign( bz_ApiString callsign )
{
  std::ostringstream result;

  result << strlen( callsign.c_str() ) << ":" << callsign.c_str();

  return result.str();
}

std::string LogDetail::displayCallsign( int playerID )
{
  std::ostringstream callsign;
  bz_BasePlayerRecord *player = bz_getPlayerByIndex( playerID );
  if (player) {
    callsign << strlen( player->callsign.c_str() ) << ":";
    callsign << player->callsign.c_str();
    bz_freePlayerRecord( player );
  } else {
    callsign << "7:UNKNOWN";
  }
  return callsign.str();
}

std::string LogDetail::displayTeam( bz_eTeamType team )
{
  // Display the player team
  switch ( team ) {
    case eRogueTeam:
      return std::string("ROGUE");
    case eRedTeam:
      return std::string("RED");
    case eGreenTeam:
      return std::string("GREEN");
    case eBlueTeam:
      return std::string("BLUE");
    case ePurpleTeam:
      return std::string("PURPLE");
    case eRabbitTeam:
      return std::string("RABBIT");
    case eHunterTeam:
      return std::string("HUNTER");
    case eObservers:
      return std::string("OBSERVER");
    default :
      return std::string("NOTEAM");
  }
}

void LogDetail::listPlayers( action act , bz_PlayerJoinPartEventData_V1 *data )
{
  bz_APIIntList *playerList = bz_newIntList();
  bz_BasePlayerRecord *player = NULL;
  std::ostringstream msg;
  char playerStatus;
  int numPlayers;

  bz_getPlayerIndexList( playerList );

  bz_debugMessage( 4 , "Players:" );
  //
  // Count number of players
  //
  numPlayers = 0;
  for ( unsigned int i = 0; i < playerList->size(); i++ ) {
    player = bz_getPlayerByIndex( playerList->get(i));
    if (player) {
      if ((player->callsign != "") && (act == join || act == auth || (data && (player->playerID != data->playerID))))
	numPlayers++;
      bz_freePlayerRecord( player );
    }
  }

  //
  // Display number of players, callsign, and motto string in the following format:
  //
  // PLAYERS (nn) [G]cc:callsign(ee:mottostring)
  // nn - number of players
  // G	- global auth identifier (+|-| |@)
  // cc - count of characters in player callsign
  // callsign - player callsign
  // ee - count of characters in motto string
  // mottostring - player motto string
  //
  // eg.
  // PLAYERS (2) [@]7:Thumper(16:me@somewhere.net) [ ]3:xxx()
  //
  msg.str("");
  msg << "PLAYERS (" << numPlayers << ")";
  for ( unsigned int i = 0; i < playerList->size(); i++ ) {
    player = bz_getPlayerByIndex( playerList->get(i));
    if (player) {
      if ((player->callsign != "") && (act == join || act == auth || (data && (player->playerID != data->playerID)))) {
	playerStatus = ' ';
	if (player->globalUser) playerStatus = '+';
	if (player->verified) playerStatus = '+';
	if (player->admin && !bz_hasPerm(player->playerID, bz_perm_hideAdmin)) playerStatus = '@';
	msg << " [" << playerStatus << "]";
	msg << player->callsign.size() << ':';
	msg << player->callsign.c_str() << "(" << bz_getPlayerMotto(player->playerID) << ")";
      }
    }
  }
  bz_debugMessage(0, msg.str().c_str());

  bz_deleteIntList(playerList);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2003-2008  Justin Karneges <justin@affinix.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

// since keyring files are often modified by creating a new copy and
//   overwriting the original file, this messes up Qt's file watching
//   capability since the original file goes away.  to work around this
//   problem, we'll watch the directories containing the keyring files
//   instead of watching the actual files themselves.
//
// FIXME: qca 2.0.1 FileWatch has this logic already, so we can probably
//   simplify this class.

#include "qca_safetimer.h"
#include "qca_support.h"
#include "ringwatch.h"
#include <QFileInfo>

using namespace QCA;

namespace gpgQCAPlugin
{

RingWatch::RingWatch(QObject *parent)
	: QObject(parent)
{
}

RingWatch::~RingWatch()
{
	clear();
}

void RingWatch::add(const QString &filePath)
{
	QFileInfo fi(filePath);
	QString path = fi.absolutePath();

	// watching this path already?
	DirWatch *dirWatch = 0;
	foreach(const DirItem &di, dirs)
	{
		if(di.dirWatch->dirName() == path)
		{
			dirWatch = di.dirWatch;
			break;
		}
	}

	// if not, make a watcher
	if(!dirWatch)
	{
		//printf("creating dirwatch for [%s]\n", qPrintable(path));

		DirItem di;
		di.dirWatch = new DirWatch(path, this);
		connect(di.dirWatch, SIGNAL(changed()), SLOT(dirChanged()));

		di.changeTimer = new SafeTimer(this);
		di.changeTimer->setSingleShot(true);
		connect(di.changeTimer, SIGNAL(timeout()), SLOT(handleChanged()));

		dirWatch = di.dirWatch;
		dirs += di;
	}

	FileItem i;
	i.dirWatch = dirWatch;
	i.fileName = fi.fileName();
	i.exists = fi.exists();
	if(i.exists)
	{
		i.size = fi.size();
		i.lastModified = fi.lastModified();
	}
	files += i;

	//printf("watching [%s] in [%s]\n", qPrintable(fi.fileName()), qPrintable(i.dirWatch->dirName()));
}

void RingWatch::clear()
{
	files.clear();

	foreach(const DirItem &di, dirs)
	{
		delete di.changeTimer;
		delete di.dirWatch;
	}

	dirs.clear();
}

void RingWatch::dirChanged()
{
	DirWatch *dirWatch = (DirWatch *)sender();

	int at = -1;
	for(int n = 0; n < dirs.count(); ++n)
	{
		if(dirs[n].dirWatch == dirWatch)
		{
			at = n;
			break;
		}
	}
	if(at == -1)
		return;

	// we get a ton of change notifications for the dir when
	//   something happens..   let's collect them and only
	//   report after 100ms

	if(!dirs[at].changeTimer->isActive())
		dirs[at].changeTimer->start(100);
}

void RingWatch::handleChanged()
{
	SafeTimer *t = (SafeTimer *)sender();

	int at = -1;
	for(int n = 0; n < dirs.count(); ++n)
	{
		if(dirs[n].changeTimer == t)
		{
			at = n;
			break;
		}
	}
	if(at == -1)
		return;

	DirWatch *dirWatch = dirs[at].dirWatch;
	QString dir = dirWatch->dirName();

	// see which files changed
	QStringList changeList;
	for(int n = 0; n < files.count(); ++n)
	{
		FileItem &i = files[n];
		QString filePath = dir + '/' + i.fileName;
		QFileInfo fi(filePath);

		// if the file didn't exist, and still doesn't, skip
		if(!i.exists && !fi.exists())
			continue;

		// size/lastModified should only get checked here if
		//   the file existed and still exists
		if(fi.exists() != i.exists || fi.size() != i.size || fi.lastModified() != i.lastModified)
		{
			changeList += filePath;

			i.exists = fi.exists();
			if(i.exists)
			{
				i.size = fi.size();
				i.lastModified = fi.lastModified();
			}
		}
	}

	foreach(const QString &s, changeList)
	emit changed(s);
}

} // end namespace gpgQCAPlugin
<commit_msg>gnupg: resolve symbolic links<commit_after>/*
 * Copyright (C) 2003-2008  Justin Karneges <justin@affinix.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

// since keyring files are often modified by creating a new copy and
//   overwriting the original file, this messes up Qt's file watching
//   capability since the original file goes away.  to work around this
//   problem, we'll watch the directories containing the keyring files
//   instead of watching the actual files themselves.
//
// FIXME: qca 2.0.1 FileWatch has this logic already, so we can probably
//   simplify this class.

#include "qca_safetimer.h"
#include "qca_support.h"
#include "ringwatch.h"
#include <QFileInfo>

using namespace QCA;

namespace gpgQCAPlugin
{

RingWatch::RingWatch(QObject *parent)
	: QObject(parent)
{
}

RingWatch::~RingWatch()
{
	clear();
}

void RingWatch::add(const QString &filePath)
{
	QFileInfo fi(filePath);
	// Try to avoid symbolic links
	QString path = fi.canonicalPath();
	if (path.isEmpty())
		path = fi.absolutePath();

	// watching this path already?
	DirWatch *dirWatch = 0;
	foreach(const DirItem &di, dirs)
	{
		if(di.dirWatch->dirName() == path)
		{
			dirWatch = di.dirWatch;
			break;
		}
	}

	// if not, make a watcher
	if(!dirWatch)
	{
		//printf("creating dirwatch for [%s]\n", qPrintable(path));

		DirItem di;
		di.dirWatch = new DirWatch(path, this);
		connect(di.dirWatch, SIGNAL(changed()), SLOT(dirChanged()));

		di.changeTimer = new SafeTimer(this);
		di.changeTimer->setSingleShot(true);
		connect(di.changeTimer, SIGNAL(timeout()), SLOT(handleChanged()));

		dirWatch = di.dirWatch;
		dirs += di;
	}

	FileItem i;
	i.dirWatch = dirWatch;
	i.fileName = fi.fileName();
	i.exists = fi.exists();
	if(i.exists)
	{
		i.size = fi.size();
		i.lastModified = fi.lastModified();
	}
	files += i;

	//printf("watching [%s] in [%s]\n", qPrintable(fi.fileName()), qPrintable(i.dirWatch->dirName()));
}

void RingWatch::clear()
{
	files.clear();

	foreach(const DirItem &di, dirs)
	{
		delete di.changeTimer;
		delete di.dirWatch;
	}

	dirs.clear();
}

void RingWatch::dirChanged()
{
	DirWatch *dirWatch = (DirWatch *)sender();

	int at = -1;
	for(int n = 0; n < dirs.count(); ++n)
	{
		if(dirs[n].dirWatch == dirWatch)
		{
			at = n;
			break;
		}
	}
	if(at == -1)
		return;

	// we get a ton of change notifications for the dir when
	//   something happens..   let's collect them and only
	//   report after 100ms

	if(!dirs[at].changeTimer->isActive())
		dirs[at].changeTimer->start(100);
}

void RingWatch::handleChanged()
{
	SafeTimer *t = (SafeTimer *)sender();

	int at = -1;
	for(int n = 0; n < dirs.count(); ++n)
	{
		if(dirs[n].changeTimer == t)
		{
			at = n;
			break;
		}
	}
	if(at == -1)
		return;

	DirWatch *dirWatch = dirs[at].dirWatch;
	QString dir = dirWatch->dirName();

	// see which files changed
	QStringList changeList;
	for(int n = 0; n < files.count(); ++n)
	{
		FileItem &i = files[n];
		QString filePath = dir + '/' + i.fileName;
		QFileInfo fi(filePath);

		// if the file didn't exist, and still doesn't, skip
		if(!i.exists && !fi.exists())
			continue;

		// size/lastModified should only get checked here if
		//   the file existed and still exists
		if(fi.exists() != i.exists || fi.size() != i.size || fi.lastModified() != i.lastModified)
		{
			changeList += filePath;

			i.exists = fi.exists();
			if(i.exists)
			{
				i.size = fi.size();
				i.lastModified = fi.lastModified();
			}
		}
	}

	foreach(const QString &s, changeList)
	emit changed(s);
}

} // end namespace gpgQCAPlugin
<|endoftext|>


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

#include "bzfsAPI.h"
#include "plugin_utils.h"

#include <string>
#include <vector>

class SuperUser : public bz_Plugin
{
public:
  virtual const char* Name (){return "SuperUser";}
  virtual void Init ( const char* config);

  virtual void Event ( bz_EventData * /* eventData */ );

protected:
  std::vector<std::string> GetUserInfo(const char* bzID );

  PluginConfig Users;
};

BZ_PLUGIN(SuperUser)

void SuperUser::Init ( const char* commandLine)
{
  if (commandLine == NULL || strlen(commandLine) == 0)
    bz_debugMessage(0,"SuperUser plugin needs a user file to work from");
  else
    Users.read(commandLine);

  bz_debugMessage(4,"SAMPLE_PLUGIN plugin loaded");
  Register(bz_ePlayerJoinEvent);

  // init events here with Register();
}

std::vector<std::string> SuperUser::GetUserInfo(const char* bzID )
{
  std::vector<std::string> perms;

  std::string info = Users.item("Users",bzID);

  if (info.size() > 0)
    perms = tokenize(info,std::string(","),-1,true);

  return perms;
}

void SuperUser::Event ( bz_EventData * eventData  )
{
  bz_PlayerJoinPartEventData_V1 *joinData = (bz_PlayerJoinPartEventData_V1*)eventData;

  std::vector<std::string> perms = GetUserInfo(joinData->record->bzID.c_str());

  for (size_t i = 0; i < perms.size(); i++)
    bz_grantPerm(joinData->playerID,perms[i].c_str());
}
// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<commit_msg>Fix superUser "plugin loaded" message<commit_after>// SAMPLE_PLUGIN.cpp : Defines the entry point for the DLL application.
//

#include "bzfsAPI.h"
#include "plugin_utils.h"

#include <string>
#include <vector>

class SuperUser : public bz_Plugin
{
public:
  virtual const char* Name (){return "SuperUser";}
  virtual void Init ( const char* config);

  virtual void Event ( bz_EventData * /* eventData */ );

protected:
  std::vector<std::string> GetUserInfo(const char* bzID );

  PluginConfig Users;
};

BZ_PLUGIN(SuperUser)

void SuperUser::Init ( const char* commandLine)
{
  if (commandLine == NULL || strlen(commandLine) == 0)
    bz_debugMessage(0,"SuperUser plugin needs a user file to work from");
  else
    Users.read(commandLine);

  bz_debugMessage(4,"SuperUser plugin loaded");
  Register(bz_ePlayerJoinEvent);

  // init events here with Register();
}

std::vector<std::string> SuperUser::GetUserInfo(const char* bzID )
{
  std::vector<std::string> perms;

  std::string info = Users.item("Users",bzID);

  if (info.size() > 0)
    perms = tokenize(info,std::string(","),-1,true);

  return perms;
}

void SuperUser::Event ( bz_EventData * eventData  )
{
  bz_PlayerJoinPartEventData_V1 *joinData = (bz_PlayerJoinPartEventData_V1*)eventData;

  std::vector<std::string> perms = GetUserInfo(joinData->record->bzID.c_str());

  for (size_t i = 0; i < perms.size(); i++)
    bz_grantPerm(joinData->playerID,perms[i].c_str());
}
// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (people-users@projects.maemo.org)
**
** This file is part of contactsd.
**
** If you have questions regarding the use of this file, please contact
** Nokia at people-users@projects.maemo.org.
**
** This library is free software; 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 Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "cdtpquery.h"
#include "cdtpstorage.h"
#include "debug.h"
#include "sparqlconnectionmanager.h"

using namespace Contactsd;

/* --- CDTpQueryBuilder --- */

CDTpQueryBuilder::CDTpQueryBuilder()
{
}

void CDTpQueryBuilder::append(const UpdateBase &q)
{
    mQueries.append(q);
}

void CDTpQueryBuilder::prepend(const UpdateBase &q)
{
    mQueries.prepend(q);
}

void CDTpQueryBuilder::append(const CDTpQueryBuilder &builder)
{
    mQueries.append(builder.mQueries);
}

void CDTpQueryBuilder::prepend(const CDTpQueryBuilder &builder)
{
    // Poor man's QList::prepend - QTBUG-4312
    QList<UpdateBase> tmp;
    tmp.append(builder.mQueries);
    tmp.append(mQueries);
    mQueries = tmp;
}

QString CDTpQueryBuilder::sparql(Options::SparqlOptions options) const
{
    QString rawQuery;
    Q_FOREACH (const UpdateBase &q, mQueries) {
        rawQuery += q.sparql(options);
        rawQuery += QLatin1String("\n");
    }

    return rawQuery;
}

QSparqlQuery CDTpQueryBuilder::sparqlQuery() const
{
    return QSparqlQuery(sparql(Options::DefaultSparqlOptions | Options::GroupPatterns),
            QSparqlQuery::InsertStatement);
}

/* --- CDTpSparqlQuery --- */

CDTpSparqlQuery::CDTpSparqlQuery(const CDTpQueryBuilder &builder, QObject *parent)
        : QObject(parent), mErrorSet(false)
{
    static uint counter = 0;
    mId = ++counter;
    mTime.start();

    debug() << "query" << mId << "started";
    debug() << builder.sparql(Options::DefaultSparqlOptions | Options::GroupPatterns | Options::PrettyPrint);

    QSparqlConnection &connection = com::nokia::contactsd::SparqlConnectionManager::defaultConnection();
    QSparqlResult *result = connection.exec(builder.sparqlQuery());

    if (not result) {
        warning() << Q_FUNC_INFO << " - QSparqlConnection::exec() == 0";
        deleteLater();
        return;
    }
    if (result->hasError()) {
        warning() << Q_FUNC_INFO << result->lastError().message();
        delete result;
        deleteLater();
        return;
    }

    result->setParent(this);
    connect(result, SIGNAL(finished()), SLOT(onQueryFinished()), Qt::QueuedConnection);
}

void CDTpSparqlQuery::onQueryFinished()
{
    QSparqlResult *result = qobject_cast<QSparqlResult *>(sender());

    if (not result) {
        warning() << "QSparqlQuery finished with error:" << "Invalid signal sender";
        mErrorSet = true;
    } else {
        if (result->hasError()) {
            mErrorSet = true;
            mError = result->lastError();
            warning() << "QSparqlQuery finished with error:" << mError.message();
        }
        result->deleteLater();
    }

    debug() << "query" << mId << "finished. Time elapsed (ms):" << mTime.elapsed();

    Q_EMIT finished(this);

    deleteLater();
}

/* --- CDTpAccountsSparqlQuery --- */

CDTpAccountsSparqlQuery::CDTpAccountsSparqlQuery(const QList<CDTpAccountPtr> &accounts,
    const CDTpQueryBuilder &builder, QObject *parent)
        : CDTpSparqlQuery(builder, parent), mAccounts(accounts)
{
}

CDTpAccountsSparqlQuery::CDTpAccountsSparqlQuery(const CDTpAccountPtr &accountWrapper,
    const CDTpQueryBuilder &builder, QObject *parent)
        : CDTpSparqlQuery(builder, parent), mAccounts(QList<CDTpAccountPtr>() << accountWrapper)
{
}

<commit_msg>Changes: Do not add explicitely Options::GroupPatterns, it is set by default now<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (people-users@projects.maemo.org)
**
** This file is part of contactsd.
**
** If you have questions regarding the use of this file, please contact
** Nokia at people-users@projects.maemo.org.
**
** This library is free software; 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 Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "cdtpquery.h"
#include "cdtpstorage.h"
#include "debug.h"
#include "sparqlconnectionmanager.h"

using namespace Contactsd;

/* --- CDTpQueryBuilder --- */

CDTpQueryBuilder::CDTpQueryBuilder()
{
}

void CDTpQueryBuilder::append(const UpdateBase &q)
{
    mQueries.append(q);
}

void CDTpQueryBuilder::prepend(const UpdateBase &q)
{
    mQueries.prepend(q);
}

void CDTpQueryBuilder::append(const CDTpQueryBuilder &builder)
{
    mQueries.append(builder.mQueries);
}

void CDTpQueryBuilder::prepend(const CDTpQueryBuilder &builder)
{
    // Poor man's QList::prepend - QTBUG-4312
    QList<UpdateBase> tmp;
    tmp.append(builder.mQueries);
    tmp.append(mQueries);
    mQueries = tmp;
}

QString CDTpQueryBuilder::sparql(Options::SparqlOptions options) const
{
    QString rawQuery;
    Q_FOREACH (const UpdateBase &q, mQueries) {
        rawQuery += q.sparql(options);
        rawQuery += QLatin1String("\n");
    }

    return rawQuery;
}

QSparqlQuery CDTpQueryBuilder::sparqlQuery() const
{
    return QSparqlQuery(sparql(), QSparqlQuery::InsertStatement);
}

/* --- CDTpSparqlQuery --- */

CDTpSparqlQuery::CDTpSparqlQuery(const CDTpQueryBuilder &builder, QObject *parent)
        : QObject(parent), mErrorSet(false)
{
    static uint counter = 0;
    mId = ++counter;
    mTime.start();

    debug() << "query" << mId << "started";
    debug() << builder.sparql(Options::DefaultSparqlOptions | Options::PrettyPrint);

    QSparqlConnection &connection = com::nokia::contactsd::SparqlConnectionManager::defaultConnection();
    QSparqlResult *result = connection.exec(builder.sparqlQuery());

    if (not result) {
        warning() << Q_FUNC_INFO << " - QSparqlConnection::exec() == 0";
        deleteLater();
        return;
    }
    if (result->hasError()) {
        warning() << Q_FUNC_INFO << result->lastError().message();
        delete result;
        deleteLater();
        return;
    }

    result->setParent(this);
    connect(result, SIGNAL(finished()), SLOT(onQueryFinished()), Qt::QueuedConnection);
}

void CDTpSparqlQuery::onQueryFinished()
{
    QSparqlResult *result = qobject_cast<QSparqlResult *>(sender());

    if (not result) {
        warning() << "QSparqlQuery finished with error:" << "Invalid signal sender";
        mErrorSet = true;
    } else {
        if (result->hasError()) {
            mErrorSet = true;
            mError = result->lastError();
            warning() << "QSparqlQuery finished with error:" << mError.message();
        }
        result->deleteLater();
    }

    debug() << "query" << mId << "finished. Time elapsed (ms):" << mTime.elapsed();

    Q_EMIT finished(this);

    deleteLater();
}

/* --- CDTpAccountsSparqlQuery --- */

CDTpAccountsSparqlQuery::CDTpAccountsSparqlQuery(const QList<CDTpAccountPtr> &accounts,
    const CDTpQueryBuilder &builder, QObject *parent)
        : CDTpSparqlQuery(builder, parent), mAccounts(accounts)
{
}

CDTpAccountsSparqlQuery::CDTpAccountsSparqlQuery(const CDTpAccountPtr &accountWrapper,
    const CDTpQueryBuilder &builder, QObject *parent)
        : CDTpSparqlQuery(builder, parent), mAccounts(QList<CDTpAccountPtr>() << accountWrapper)
{
}

<|endoftext|>


<commit_before>/*
 * DamageMap.cpp
 *
 *  Created on: 13/07/2010
 *      Author: victor
 */

#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/tangible/weapon/WeaponObject.h"
#include "ThreatMap.h"
#include "server/zone/objects/tangible/tasks/ClearThreatStateTask.h"
#include "server/zone/objects/tangible/tasks/RemoveAggroTask.h"
#include "ThreatMapClearObserversTask.h"

void ThreatMapEntry::addDamage(WeaponObject* weapon, uint32 damage) {
	addDamage(weapon->getXpType(), damage);
}

void ThreatMapEntry::addDamage(String xp, uint32 damage) {
	int idx = find(xp);

	if (idx == -1) {
		put(xp, damage);

	} else {
		uint32* dmg = &elementAt(idx).getValue();

		*dmg = *dmg + damage;
	}
}

void ThreatMapEntry::setThreatState(uint64 state) {
	if(!threatBitmask & state)
		threatBitmask |= state;

}

bool ThreatMapEntry::hasState(uint64 state) {
	if(threatBitmask & state)
		return true;

	return false;
}

void ThreatMapEntry::clearThreatState(uint64 state) {
	if(threatBitmask & state)
		threatBitmask &= ~state;
}

void ThreatMap::registerObserver(CreatureObject* target) {

	if(threatMapObserver == NULL) {
		threatMapObserver = new ThreatMapObserver(self);
		threatMapObserver->deploy();
	}

	target->registerObserver(ObserverEventType::HEALINGPERFORMED, threatMapObserver);
}

void ThreatMap::removeObservers() {
	if (size() == 0)
		return;

	Reference<ThreatMapClearObserversTask*> task = new ThreatMapClearObserversTask(*this, threatMapObserver);
	Core::getTaskManager()->executeTask(task);

	//moved this to a task so it executes async in a different thread to avoid deadlocks
	/*Locker locker(self);

	for (int i = 0; i < size(); ++i) {
		CreatureObject* creature = elementAt(i).getKey();

		if (creature != NULL && threatMapObserver != NULL) {
			Locker clocker(creature, self);

			creature->dropObserver(ObserverEventType::HEALINGPERFORMED, threatMapObserver);
		}
	}*/
}

void ThreatMap::addDamage(CreatureObject* target, uint32 damage, String xp) {
	Locker locker(&lockMutex);

	int idx = find(target);
	String xpToAward = "";

	if (xp == "") {
		WeaponObject* weapon = target->getWeapon();
		xpToAward = weapon->getXpType();
	} else
		xpToAward = xp;

	if (idx == -1) {
		ThreatMapEntry entry;
		entry.addDamage(xpToAward, damage);
		entry.addAggro(1);

		put(target, entry);
		registerObserver(target);

	} else {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->addDamage(xpToAward, damage);
		entry->addAggro(1);
	}
}

void ThreatMap::removeAll() {
	removeObservers();
	VectorMap<ManagedReference<CreatureObject*> , ThreatMapEntry>::removeAll();
	currentThreat = NULL;
	threatMatrix.clear();
}

void ThreatMap::dropDamage(CreatureObject* target) {
	Locker llocker(&lockMutex);

	drop(target);

	llocker.release();

	if (currentThreat == target)
		currentThreat = NULL;

	if (threatMapObserver != NULL) {
		target->dropObserver(ObserverEventType::HEALINGPERFORMED, threatMapObserver);
	}
}

bool ThreatMap::setThreatState(CreatureObject* target, uint64 state, uint64 duration, uint64 cooldown) {
	Locker locker(&lockMutex);

	if((hasState(state) && isUniqueState(state))
			|| !cooldownTimerMap.isPast(String::valueOf(state)))
		return false;

	int idx = find(target);

	if (idx == -1) {
		ThreatMapEntry entry;
		entry.setThreatState(state);
		put(target, entry);
		registerObserver(target);

	} else {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->setThreatState(state);
	}

	if(duration > 0) {
		ClearThreatStateTask* clearThreat = new ClearThreatStateTask(self, target, state);
		clearThreat->schedule(duration);
	}

	if(cooldown > 0) {
		cooldownTimerMap.updateToCurrentAndAddMili(String::valueOf(state), duration + cooldown);
	}

	if(isUniqueState(state)) {
		cooldownTimerMap.updateToCurrentTime("doEvaluation");
	}

#ifdef DEBUG
	System::out << "Setting threat state on "  << target->getObjectID() << ": " << state << endl;
#endif

	return true;
}

bool ThreatMap::hasState(uint64 state) {
	Locker locker(&lockMutex);

	for (int i = 0; i < size(); ++i) {
		ThreatMapEntry* entry = &elementAt(i).getValue();
		if(entry->hasState(state))
			return true;
	}

	return false;
}

bool ThreatMap::isUniqueState(uint64 state) {
	return state & ThreatStates::UNIQUESTATE;
}

void ThreatMap::clearThreatState(CreatureObject* target, uint64 state) {
	Locker locker(&lockMutex);

	int idx = find(target);

	if (idx != -1) {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->clearThreatState(state);

#ifdef DEBUG
		System::out << "Clearing threat state on "  << target->getObjectID() << ": " << state << endl;
#endif
	}
}

uint32 ThreatMap::getTotalDamage() {
	Locker locker(&lockMutex);

	uint32 totalDamage = 0;

	for (int i = 0; i < size(); ++i) {
		ThreatMapEntry* entry = &elementAt(i).getValue();

		for (int j = 0; j < entry->size(); ++j) {
			uint32 damage = entry->elementAt(j).getValue();

			totalDamage += damage;
		}
	}

	return totalDamage;
}

CreatureObject* ThreatMap::getHighestDamagePlayer() {
	Locker locker(&lockMutex);

	uint32 maxDamage = 0;
	CreatureObject* player = NULL;

	for (int i = 0; i < size(); ++i) {
		ThreatMapEntry* entry = &elementAt(i).getValue();

		uint32 totalDamage = 0;

		for (int j = 0; j < entry->size(); ++j) {
			uint32 damage = entry->elementAt(j).getValue();

			totalDamage += damage;
		}

		CreatureObject* creature = elementAt(i).getKey();

		if (totalDamage > maxDamage && creature->isPlayerCreature()) {
			maxDamage = totalDamage;
			player = cast<CreatureObject*>(creature);
		}
	}

	return player;
}

CreatureObject* ThreatMap::getHighestThreatCreature() {
	Locker locker(&lockMutex);

	if(currentThreat != NULL
			&& !currentThreat->isDead()
			&& !currentThreat->isIncapacitated()
			&& !cooldownTimerMap.isPast("doEvaluation"))
		return currentThreat;

	threatMatrix.clear();

	for (int i = 0; i < size(); ++i) {
		ThreatMapEntry* entry = &elementAt(i).getValue();
		CreatureObject* creature = elementAt(i).getKey();

		threatMatrix.add(creature, entry);
	}

	currentThreat = threatMatrix.getLargestThreat();

	cooldownTimerMap.updateToCurrentAndAddMili("doEvaluation", ThreatMap::EVALUATIONCOOLDOWN);
	return currentThreat;
}

void ThreatMap::addAggro(CreatureObject* target, int value, uint64 duration) {
	Locker locker(&lockMutex);

	int idx = find(target);

	if (idx == -1) {
		ThreatMapEntry entry;
		entry.addAggro(value);
		put(target, entry);
		registerObserver(target);

	} else {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->addAggro(value);
	}

	if(duration > 0) {
		RemoveAggroTask* removeAggroTask = new RemoveAggroTask(self, target, value);
		removeAggroTask->schedule(duration);
	}
}

void ThreatMap::removeAggro(CreatureObject* target, int value) {
	Locker locker(&lockMutex);

	int idx = find(target);

	if (idx != -1) {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->removeAggro(value);
	}
}

void ThreatMap::clearAggro(CreatureObject* target) {
	Locker locker(&lockMutex);

	int idx = find(target);

	if (idx != -1) {
		ThreatMapEntry entry;
		entry.clearAggro();
	}
}

void ThreatMap::addHeal(CreatureObject* target, int value) {
	Locker locker(&lockMutex);

	int idx = find(target);

	if (idx == -1) {
		ThreatMapEntry entry;
		entry.addHeal(value);
		entry.addAggro(2);
		put(target, entry);
		registerObserver(target);

	} else {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->addHeal(value);
		entry->addAggro(2);
	}
}
<commit_msg>(unstable) [fixed] stability issues<commit_after>/*
 * DamageMap.cpp
 *
 *  Created on: 13/07/2010
 *      Author: victor
 */

#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/tangible/weapon/WeaponObject.h"
#include "ThreatMap.h"
#include "server/zone/objects/tangible/tasks/ClearThreatStateTask.h"
#include "server/zone/objects/tangible/tasks/RemoveAggroTask.h"
#include "ThreatMapClearObserversTask.h"

void ThreatMapEntry::addDamage(WeaponObject* weapon, uint32 damage) {
	addDamage(weapon->getXpType(), damage);
}

void ThreatMapEntry::addDamage(String xp, uint32 damage) {
	int idx = find(xp);

	if (idx == -1) {
		put(xp, damage);

	} else {
		uint32* dmg = &elementAt(idx).getValue();

		*dmg = *dmg + damage;
	}
}

void ThreatMapEntry::setThreatState(uint64 state) {
	if(!threatBitmask & state)
		threatBitmask |= state;

}

bool ThreatMapEntry::hasState(uint64 state) {
	if(threatBitmask & state)
		return true;

	return false;
}

void ThreatMapEntry::clearThreatState(uint64 state) {
	if(threatBitmask & state)
		threatBitmask &= ~state;
}

void ThreatMap::registerObserver(CreatureObject* target) {

	if(threatMapObserver == NULL) {
		threatMapObserver = new ThreatMapObserver(self);
		threatMapObserver->deploy();
	}

	target->registerObserver(ObserverEventType::HEALINGPERFORMED, threatMapObserver);
}

void ThreatMap::removeObservers() {
	if (size() == 0)
		return;

	Reference<ThreatMapClearObserversTask*> task = new ThreatMapClearObserversTask(*this, threatMapObserver);
	Core::getTaskManager()->executeTask(task);

	//moved this to a task so it executes async in a different thread to avoid deadlocks
	/*Locker locker(self);

	for (int i = 0; i < size(); ++i) {
		CreatureObject* creature = elementAt(i).getKey();

		if (creature != NULL && threatMapObserver != NULL) {
			Locker clocker(creature, self);

			creature->dropObserver(ObserverEventType::HEALINGPERFORMED, threatMapObserver);
		}
	}*/
}

void ThreatMap::addDamage(CreatureObject* target, uint32 damage, String xp) {
	Locker locker(&lockMutex);

	int idx = find(target);
	String xpToAward = "";

	if (xp == "") {
		WeaponObject* weapon = target->getWeapon();
		xpToAward = weapon->getXpType();
	} else
		xpToAward = xp;

	if (idx == -1) {
		ThreatMapEntry entry;
		entry.addDamage(xpToAward, damage);
		entry.addAggro(1);

		put(target, entry);
		registerObserver(target);

	} else {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->addDamage(xpToAward, damage);
		entry->addAggro(1);
	}
}

void ThreatMap::removeAll() {
	Locker llocker(&lockMutex);

	removeObservers();
	VectorMap<ManagedReference<CreatureObject*> , ThreatMapEntry>::removeAll();
	currentThreat = NULL;
	threatMatrix.clear();
}

void ThreatMap::dropDamage(CreatureObject* target) {
	Locker llocker(&lockMutex);

	drop(target);

	llocker.release();

	if (currentThreat == target)
		currentThreat = NULL;

	if (threatMapObserver != NULL) {
		target->dropObserver(ObserverEventType::HEALINGPERFORMED, threatMapObserver);
	}
}

bool ThreatMap::setThreatState(CreatureObject* target, uint64 state, uint64 duration, uint64 cooldown) {
	Locker locker(&lockMutex);

	if((hasState(state) && isUniqueState(state))
			|| !cooldownTimerMap.isPast(String::valueOf(state)))
		return false;

	int idx = find(target);

	if (idx == -1) {
		ThreatMapEntry entry;
		entry.setThreatState(state);
		put(target, entry);
		registerObserver(target);

	} else {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->setThreatState(state);
	}

	if(duration > 0) {
		ClearThreatStateTask* clearThreat = new ClearThreatStateTask(self, target, state);
		clearThreat->schedule(duration);
	}

	if(cooldown > 0) {
		cooldownTimerMap.updateToCurrentAndAddMili(String::valueOf(state), duration + cooldown);
	}

	if(isUniqueState(state)) {
		cooldownTimerMap.updateToCurrentTime("doEvaluation");
	}

#ifdef DEBUG
	System::out << "Setting threat state on "  << target->getObjectID() << ": " << state << endl;
#endif

	return true;
}

bool ThreatMap::hasState(uint64 state) {
	Locker locker(&lockMutex);

	for (int i = 0; i < size(); ++i) {
		ThreatMapEntry* entry = &elementAt(i).getValue();
		if(entry->hasState(state))
			return true;
	}

	return false;
}

bool ThreatMap::isUniqueState(uint64 state) {
	return state & ThreatStates::UNIQUESTATE;
}

void ThreatMap::clearThreatState(CreatureObject* target, uint64 state) {
	Locker locker(&lockMutex);

	int idx = find(target);

	if (idx != -1) {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->clearThreatState(state);

#ifdef DEBUG
		System::out << "Clearing threat state on "  << target->getObjectID() << ": " << state << endl;
#endif
	}
}

uint32 ThreatMap::getTotalDamage() {
	Locker locker(&lockMutex);

	uint32 totalDamage = 0;

	for (int i = 0; i < size(); ++i) {
		ThreatMapEntry* entry = &elementAt(i).getValue();

		for (int j = 0; j < entry->size(); ++j) {
			uint32 damage = entry->elementAt(j).getValue();

			totalDamage += damage;
		}
	}

	return totalDamage;
}

CreatureObject* ThreatMap::getHighestDamagePlayer() {
	Locker locker(&lockMutex);

	uint32 maxDamage = 0;
	CreatureObject* player = NULL;

	for (int i = 0; i < size(); ++i) {
		ThreatMapEntry* entry = &elementAt(i).getValue();

		uint32 totalDamage = 0;

		for (int j = 0; j < entry->size(); ++j) {
			uint32 damage = entry->elementAt(j).getValue();

			totalDamage += damage;
		}

		CreatureObject* creature = elementAt(i).getKey();

		if (totalDamage > maxDamage && creature->isPlayerCreature()) {
			maxDamage = totalDamage;
			player = cast<CreatureObject*>(creature);
		}
	}

	return player;
}

CreatureObject* ThreatMap::getHighestThreatCreature() {
	Locker locker(&lockMutex);

	if(currentThreat != NULL
			&& !currentThreat->isDead()
			&& !currentThreat->isIncapacitated()
			&& !cooldownTimerMap.isPast("doEvaluation"))
		return currentThreat;

	threatMatrix.clear();

	for (int i = 0; i < size(); ++i) {
		ThreatMapEntry* entry = &elementAt(i).getValue();
		CreatureObject* creature = elementAt(i).getKey();

		threatMatrix.add(creature, entry);
	}

	currentThreat = threatMatrix.getLargestThreat();

	cooldownTimerMap.updateToCurrentAndAddMili("doEvaluation", ThreatMap::EVALUATIONCOOLDOWN);
	return currentThreat;
}

void ThreatMap::addAggro(CreatureObject* target, int value, uint64 duration) {
	Locker locker(&lockMutex);

	int idx = find(target);

	if (idx == -1) {
		ThreatMapEntry entry;
		entry.addAggro(value);
		put(target, entry);
		registerObserver(target);

	} else {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->addAggro(value);
	}

	if(duration > 0) {
		RemoveAggroTask* removeAggroTask = new RemoveAggroTask(self, target, value);
		removeAggroTask->schedule(duration);
	}
}

void ThreatMap::removeAggro(CreatureObject* target, int value) {
	Locker locker(&lockMutex);

	int idx = find(target);

	if (idx != -1) {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->removeAggro(value);
	}
}

void ThreatMap::clearAggro(CreatureObject* target) {
	Locker locker(&lockMutex);

	int idx = find(target);

	if (idx != -1) {
		ThreatMapEntry entry;
		entry.clearAggro();
	}
}

void ThreatMap::addHeal(CreatureObject* target, int value) {
	Locker locker(&lockMutex);

	int idx = find(target);

	if (idx == -1) {
		ThreatMapEntry entry;
		entry.addHeal(value);
		entry.addAggro(2);
		put(target, entry);
		registerObserver(target);

	} else {
		ThreatMapEntry* entry = &elementAt(idx).getValue();
		entry->addHeal(value);
		entry->addAggro(2);
	}
}
<|endoftext|>


<commit_before>#include <thread>
#include <ctime>
#include <QSettings>
#include <iostream>

#include "lirch_plugin.h"
#include "userlist_messages.h"
#include "user_status.h"
#include "received_messages.h"
#include "notify_messages.h"
#include "grinder_messages.h"
#include "lirch_constants.h"
#include "nick_messages.h"
#include "channel_messages.h"

using namespace std;

message sendNick(QString str, QString)
{
	if (str.startsWith("/nick "))
	{
		return nick_message::create(str.section(' ',1));
	}
	return empty_message::create();
}

class userlist_timer : public message_data
{
public:
	virtual std::unique_ptr<message_data> copy() const {return std::unique_ptr<message_data>(nullptr);}
	static message create() {return message_create("userlist_timer", nullptr);}
};

class list_channels : public message_data
{
public:
	virtual std::unique_ptr<message_data> copy() const {return std::unique_ptr<message_data>(new list_channels(*this));}
	static message create(const QString &fch, const QString &dch) {return message_create("list_channels", new list_channels(fch,dch));}
	list_channels(const QString &fch, const QString &dch) : filterChannel(fch), destinationChannel(dch) {}

	QString filterChannel;
	QString destinationChannel;
};

message sendList(QString text, QString channel)
{
	return list_channels::create(text.section(QChar(' '), 1), channel);
}

//updates all of the relevent fields of out status map based on the received message
void updateSenderStatus(plugin_pipe p, message m, unordered_map<QString, user_status> & userList)
{

	if (m.type=="received")
	{
		auto message=dynamic_cast<received_message *>(m.getdata());
		userList[message->nick].nick=message->nick;
		userList[message->nick].channels.insert(message->channel);
		userList[message->nick].ip=message->ipAddress;
		userList[message->nick].lastseen=time(NULL);
	}

	if (m.type=="received_status")
	{
		auto message=dynamic_cast<received_status_message *>(m.getdata());
		userList[message->nick].lastseen=time(NULL);
		userList[message->nick].nick=message->nick;
		userList[message->nick].ip=message->ipAddress;

		if (message->subtype==received_status_message_subtype::LEFT)
		{
			userList[message->nick].channels.erase(message->channel);
			if (message->channel=="")
			{
				for(const auto & iterator:userList[message->nick].channels)
					p.write(notify_message::create(iterator,message->nick + " has logged off."));
				userList.erase(message->nick);
			}
			else
				p.write(notify_message::create(message->channel,message->nick+" has left channel "+message->channel+"."));
		}
		else if (message->subtype==received_status_message_subtype::HERE)
		{
			userList[message->nick].channels.insert(message->channel);
		}
		else if (message->subtype==received_status_message_subtype::WHOHERE)
		{
			p.write(here_message::create(message->channel));
			userList[message->nick].channels.insert(message->channel);
		}
		else if (message->subtype==received_status_message_subtype::NICK)
		{
			//message->channel is storing the old nickname of the user in the case that it is a nick type received.
			//if it is, remove the person of the old nickname
			user_status oldNickInfo = userList[message->channel];
			oldNickInfo.nick=message->nick;
			userList.erase(message->channel);
			userList[message->nick]=oldNickInfo;
		}

	}

	p.write(userlist_message::create(userList));
}

void askForUsers(plugin_pipe p, QString channel)
{
	for(int i=0; i<20; i++)
	{
		p.write(who_is_here_message::create(channel));
		this_thread::sleep_for(chrono::milliseconds(50));
	}
}

//validateName also sets old nick to new nick if it is acceptable
bool setNick(plugin_pipe p, unordered_map<QString, user_status> & userList,QString & oldNick, QString newNick)
{
	if (userList.count(newNick) && newNick!=LIRCH_DEFAULT_NICK)
		return false;
	else
	{
		p.write(changed_nick_message::create(oldNick,newNick));
		oldNick = newNick;
		return true;
	}
}

void populateDefaultChannel(plugin_pipe p)
{
	QSettings settings(QSettings::IniFormat, QSettings::UserScope, LIRCH_COMPANY_NAME, LIRCH_PRODUCT_NAME);
	settings.beginGroup("UserData");
	QString defaultNick = settings.value("nick",LIRCH_DEFAULT_NICK).value<QString>();
	settings.sync();
	settings.endGroup();

	askForUsers(p,"default");

	if (defaultNick.toUtf8().size() > 64)
	{
		p.write(notify_message::create("","Default nick too long.  You are spartacus."));
		return;
	}

	p.write(nick_message::create(defaultNick));

}

void run(plugin_pipe p, string name)
{
	p.write(registration_message::create(0, name, "userlist_request"));
	p.write(registration_message::create(0, name, "userlist_timer"));
	p.write(registration_message::create(30000, name, "received"));
	p.write(registration_message::create(30000, name, "received_status"));
	p.write(registration_message::create(0, name, "list_channels"));
	p.write(registration_message::create(0, name, "handler_ready"));
	p.write(registration_message::create(0, name, "leave_channel"));
	p.write(registration_message::create(-30000, name, "nick"));

	unordered_map<QString, user_status> userList;

	QString currentNick = LIRCH_DEFAULT_NICK;

	std::thread populate(populateDefaultChannel,p);
	populate.detach();

	p.write(register_handler::create("/nick", sendNick));

	while (true)
	{
		message m=p.blocking_read();
		if (m.type=="shutdown")
		{
			return;
		}
		else if (m.type=="registration_status")
		{
			auto s=dynamic_cast<registration_status *>(m.getdata());
			if (!s)
				continue;

			if (!s->status)
			{
				if ((0>=s->priority && s->priority>-200) || (30000>=s->priority && s->priority>29000))
					p.write(registration_message::create(s->priority-1, name, s->type));
				else
					return;
			}
			else
			{
				if (s->type=="userlist_timer")
				{
					p.write(userlist_timer::create());
				}
				else if (s->type=="list_channels")
				{
					p.write(register_handler::create("/list", sendList));
				}
			}
		}
		else if (m.type=="userlist_request")
		{
			p.write(userlist_message::create(userList));
		}
		else if (m.type=="userlist_timer")
		{
			time_t now=time(NULL);
			//Remove all nicks that haven't been seen in 2 minutes
			decltype(userList.begin()) i;
			while ((i=std::find_if(userList.begin(), userList.end(), [now](const std::pair<const QString &, const user_status &> &p) {return p.second.lastseen<now-2*60;}))!=userList.end())
			{
				for(auto iter = i->second.channels.begin(); iter!=i->second.channels.end(); iter++)
					p.write(notify_message::create(*iter, i->first + " has logged off."));
				userList.erase(i);
			}
			p.write(userlist_message::create(userList));
			thread([](plugin_pipe p)
			{
				this_thread::sleep_for(chrono::seconds(10));
				p.write(userlist_timer::create());
			}, p).detach();
		}
		else if (m.type=="handler_ready")
		{
			p.write(register_handler::create("/list", sendList));

			p.write(register_handler::create("/nick", sendNick));
		}
		else if (m.type=="received" || m.type=="received_status")
		{
			p.write(m.decrement_priority());
			updateSenderStatus(p,m,userList);
		}
		else if (m.type=="nick")
		{
			auto s=dynamic_cast<nick_message *>(m.getdata());
			if (!s)
				continue;
			p.write(m.decrement_priority());
			if (s->nick.toUtf8().size() > 64)
			{
				p.write(notify_message::create("","Nick too long.  Keeping old nick."));
				continue;
			}
			QString newNick=s->nick;
			QString oldNick=currentNick;
			if (setNick(p,userList,currentNick,newNick))
				p.write(sendable_notify_message::create("",oldNick+" has changed their nick to "+newNick+"."));
			else
				p.write(notify_message::create("","Nick taken.  Keeping old nick."));
		}
		else if (m.type=="list_channels")
		{
			auto s=dynamic_cast<list_channels *>(m.getdata());
			if (!s)
				continue;
			for (auto &i : userList)
			{
				if (s->filterChannel=="" || i.second.channels.count(s->filterChannel)!=0)
				{
					QStringList channelList;
					for (auto &c : i.second.channels)
						channelList.append(c);
					p.write(notify_message::create(s->destinationChannel, QObject::tr("User %1 (%2) was last seen at %3 and is in the following channels: %4").arg(i.second.nick, i.second.ip.toString(), ctime(&i.second.lastseen), channelList.join(" "))));
				}
			}
		}
		else
			p.write(m.decrement_priority());
	}
}

<commit_msg>changed nick setting around a bit, also made channel populate on join and empty on leave<commit_after>#include <thread>
#include <ctime>
#include <QSettings>
#include <iostream>

#include "lirch_plugin.h"
#include "userlist_messages.h"
#include "user_status.h"
#include "received_messages.h"
#include "notify_messages.h"
#include "grinder_messages.h"
#include "lirch_constants.h"
#include "nick_messages.h"
#include "channel_messages.h"

using namespace std;

message sendNick(QString str, QString)
{
	if (str.startsWith("/nick "))
	{
		return nick_message::create(str.section(' ',1));
	}
	return empty_message::create();
}

class userlist_timer : public message_data
{
public:
	virtual std::unique_ptr<message_data> copy() const {return std::unique_ptr<message_data>(nullptr);}
	static message create() {return message_create("userlist_timer", nullptr);}
};

class list_channels : public message_data
{
public:
	virtual std::unique_ptr<message_data> copy() const {return std::unique_ptr<message_data>(new list_channels(*this));}
	static message create(const QString &fch, const QString &dch) {return message_create("list_channels", new list_channels(fch,dch));}
	list_channels(const QString &fch, const QString &dch) : filterChannel(fch), destinationChannel(dch) {}

	QString filterChannel;
	QString destinationChannel;
};

message sendList(QString text, QString channel)
{
	return list_channels::create(text.section(QChar(' '), 1), channel);
}

//updates all of the relevent fields of out status map based on the received message
void updateSenderStatus(plugin_pipe p, message m, unordered_map<QString, user_status> & userList)
{

	if (m.type=="received")
	{
		auto message=dynamic_cast<received_message *>(m.getdata());
		userList[message->nick].nick=message->nick;
		userList[message->nick].channels.insert(message->channel);
		userList[message->nick].ip=message->ipAddress;
		userList[message->nick].lastseen=time(NULL);
	}

	if (m.type=="received_status")
	{
		auto message=dynamic_cast<received_status_message *>(m.getdata());
		userList[message->nick].lastseen=time(NULL);
		userList[message->nick].nick=message->nick;
		userList[message->nick].ip=message->ipAddress;

		if (message->subtype==received_status_message_subtype::LEFT)
		{
			userList[message->nick].channels.erase(message->channel);
			if (message->channel=="")
			{
				for(const auto & iterator:userList[message->nick].channels)
					p.write(notify_message::create(iterator,message->nick + " has logged off."));
				userList.erase(message->nick);
			}
			else
				p.write(notify_message::create(message->channel,message->nick+" has left channel "+message->channel+"."));
		}
		else if (message->subtype==received_status_message_subtype::HERE)
		{
			userList[message->nick].channels.insert(message->channel);
		}
		else if (message->subtype==received_status_message_subtype::WHOHERE)
		{
			p.write(here_message::create(message->channel));
			userList[message->nick].channels.insert(message->channel);
		}
		else if (message->subtype==received_status_message_subtype::NICK)
		{
			//message->channel is storing the old nickname of the user in the case that it is a nick type received.
			//if it is, remove the person of the old nickname
			user_status oldNickInfo = userList[message->channel];
			oldNickInfo.nick=message->nick;
			userList.erase(message->channel);
			userList[message->nick]=oldNickInfo;
			p.write(sendable_notify_message::create("",message->channel+" has changed their nick to "+message->nick+"."));
		}

	}

	p.write(userlist_message::create(userList));
}

void askForUsers(plugin_pipe p, QString channel)
{
	for(int i=0; i<20; i++)
	{
		p.write(who_is_here_message::create(channel));
		this_thread::sleep_for(chrono::milliseconds(50));
	}
}

//validateName also sets old nick to new nick if it is acceptable
bool setNick(plugin_pipe p, unordered_map<QString, user_status> & userList,QString & oldNick, QString newNick)
{
	if (userList.count(newNick) && newNick!=LIRCH_DEFAULT_NICK)
	{
		p.write(notify_message::create("","Nick taken.  Keeping old nick."));
		return false;
	}
	else if (newNick.toUtf8().size() > 64)
	{
		p.write(notify_message::create("","Nick too long.  Keeping old nick."));
		return false;
	}
	else
	{
		p.write(changed_nick_message::create(oldNick,newNick));
		oldNick = newNick;
		return true;
	}
}

void populateDefaultChannel(plugin_pipe p)
{
	QSettings settings(QSettings::IniFormat, QSettings::UserScope, LIRCH_COMPANY_NAME, LIRCH_PRODUCT_NAME);
	settings.beginGroup("UserData");
	QString defaultNick = settings.value("nick",LIRCH_DEFAULT_NICK).value<QString>();
	settings.sync();
	settings.endGroup();

	askForUsers(p,"default");

	if (defaultNick.toUtf8().size() > 64)
	{
		p.write(notify_message::create("","Default nick too long.  You are spartacus."));
		return;
	}

	p.write(nick_message::create(defaultNick));

}

void run(plugin_pipe p, string name)
{
	p.write(registration_message::create(0, name, "userlist_request"));
	p.write(registration_message::create(0, name, "userlist_timer"));
	p.write(registration_message::create(30000, name, "received"));
	p.write(registration_message::create(30000, name, "received_status"));
	p.write(registration_message::create(0, name, "list_channels"));
	p.write(registration_message::create(0, name, "handler_ready"));
	p.write(registration_message::create(0, name, "leave_channel"));
	p.write(registration_message::create(0, name, "set_channel"));
	p.write(registration_message::create(-30000, name, "nick"));

	unordered_map<QString, user_status> userList;

	QString currentNick = LIRCH_DEFAULT_NICK;

	std::thread populate(populateDefaultChannel,p);
	populate.detach();

	p.write(register_handler::create("/nick", sendNick));

	while (true)
	{
		message m=p.blocking_read();
		if (m.type=="shutdown")
		{
			return;
		}
		else if (m.type=="registration_status")
		{
			auto s=dynamic_cast<registration_status *>(m.getdata());
			if (!s)
				continue;

			if (!s->status)
			{
				if ((0>=s->priority && s->priority>-200) || (30000>=s->priority && s->priority>29000))
					p.write(registration_message::create(s->priority-1, name, s->type));
				else
					return;
			}
			else
			{
				if (s->type=="userlist_timer")
				{
					p.write(userlist_timer::create());
				}
				else if (s->type=="list_channels")
				{
					p.write(register_handler::create("/list", sendList));
				}
			}
		}
		else if (m.type=="userlist_request")
		{
			p.write(userlist_message::create(userList));
		}
		else if (m.type=="userlist_timer")
		{
			time_t now=time(NULL);
			//Remove all nicks that haven't been seen in 2 minutes
			decltype(userList.begin()) i;
			while ((i=std::find_if(userList.begin(), userList.end(), [now](const std::pair<const QString &, const user_status &> &p) {return p.second.lastseen<now-2*60;}))!=userList.end())
			{
				for(auto iter = i->second.channels.begin(); iter!=i->second.channels.end(); iter++)
					p.write(notify_message::create(*iter, i->first + " has logged off."));
				userList.erase(i);
			}
			p.write(userlist_message::create(userList));
			thread([](plugin_pipe p)
			{
				this_thread::sleep_for(chrono::seconds(10));
				p.write(userlist_timer::create());
			}, p).detach();
		}
		else if (m.type=="handler_ready")
		{
			p.write(register_handler::create("/list", sendList));

			p.write(register_handler::create("/nick", sendNick));
		}
		else if (m.type=="received" || m.type=="received_status")
		{
			p.write(m.decrement_priority());
			updateSenderStatus(p,m,userList);
		}
		else if (m.type=="nick")
		{
			auto s=dynamic_cast<nick_message *>(m.getdata());
			if (!s)
				continue;
			p.write(m.decrement_priority());
			setNick(p,userList,currentNick,s->nick);
		}
		else if (m.type=="list_channels")
		{
			auto s=dynamic_cast<list_channels *>(m.getdata());
			if (!s)
				continue;
			for (auto &i : userList)
			{
				if (s->filterChannel=="" || i.second.channels.count(s->filterChannel)!=0)
				{
					QStringList channelList;
					for (auto &c : i.second.channels)
						channelList.append(c);
					p.write(notify_message::create(s->destinationChannel, QObject::tr("User %1 (%2) was last seen at %3 and is in the following channels: %4").arg(i.second.nick, i.second.ip.toString(), ctime(&i.second.lastseen), channelList.join(" "))));
				}
			}
		}
		else if (m.type == "set_channel")
		{
			auto s=dynamic_cast<set_channel_message *>(m.getdata());
			if (!s)
				continue;
			p.write(m.decrement_priority());

			askForUsers(p,s->channel);
		}
		else if (m.type == "leave_channel")
		{
			auto s=dynamic_cast<leave_channel_message *>(m.getdata());
			if (!s)
				continue;
			p.write(m.decrement_priority());

			for(auto & person:userList)
			{
				person.second.channels.erase(s->channel);
			}
		}
		else
			p.write(m.decrement_priority());
	}
}

<|endoftext|>


<commit_before>// Copyright 2021 Code Intelligence GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "libfuzzer_driver.h"

#include <rules_jni.h>

#include <algorithm>
#include <filesystem>
#include <fstream>
#include <random>
#include <string>
#include <vector>

#include "absl/strings/match.h"
#include "absl/strings/str_format.h"
#include "fuzz_target_runner.h"
#include "gflags/gflags.h"
#include "glog/logging.h"
#include "jvm_tooling.h"

using namespace std::string_literals;

// Defined by glog
DECLARE_bool(log_prefix);

// Defined in libfuzzer_callbacks.cpp
DECLARE_bool(fake_pcs);

// Defined in jvm_tooling.cpp
DECLARE_string(id_sync_file);

// Defined in fuzz_target_runner.cpp
DECLARE_string(coverage_report);

// This symbol is defined by sanitizers if linked into Jazzer or in
// sanitizer_symbols.cpp if no sanitizer is used.
extern "C" void __sanitizer_set_death_callback(void (*)());

// We apply a patch to libFuzzer to make it call this function instead of
// __sanitizer_set_death_callback to pass us the death callback.
extern "C" [[maybe_unused]] void __jazzer_set_death_callback(
    void (*callback)()) {
  jazzer::AbstractLibfuzzerDriver::libfuzzer_print_crashing_input_ = callback;
  __sanitizer_set_death_callback(callback);
}

namespace {
char *additional_arg;
std::vector<char *> modified_argv;

std::string GetNewTempFilePath() {
  auto temp_dir = std::filesystem::temp_directory_path();

  std::string temp_filename_suffix(32, '\0');
  std::random_device rng;
  std::uniform_int_distribution<short> dist(0, 'z' - 'a');
  std::generate_n(temp_filename_suffix.begin(), temp_filename_suffix.length(),
                  [&rng, &dist] { return static_cast<char>('a' + dist(rng)); });

  auto temp_path = temp_dir / ("jazzer-" + temp_filename_suffix);
  if (std::filesystem::exists(temp_path))
    throw std::runtime_error("Random temp file path exists: " +
                             temp_path.string());
  return temp_path.generic_string();
}
}  // namespace

namespace jazzer {
// A libFuzzer-registered callback that outputs the crashing input, but does
// not include a stack trace.
void (*AbstractLibfuzzerDriver::libfuzzer_print_crashing_input_)() = nullptr;

AbstractLibfuzzerDriver::AbstractLibfuzzerDriver(
    int *argc, char ***argv, const std::string &usage_string) {
  gflags::SetUsageMessage(usage_string);
  // Disable glog log prefixes to mimic libFuzzer output.
  FLAGS_log_prefix = false;
  google::InitGoogleLogging((*argv)[0]);
  rules_jni_init((*argv)[0]);

  auto argv_start = *argv;
  auto argv_end = *argv + *argc;

  if (std::find(argv_start, argv_end, "-use_value_profile=1"s) != argv_end) {
    FLAGS_fake_pcs = true;
  }

  // All libFuzzer flags start with a single dash, our arguments all start with
  // a double dash. We can thus filter out the arguments meant for gflags by
  // taking only those with a leading double dash.
  std::vector<char *> our_args = {*argv_start};
  std::copy_if(
      argv_start, argv_end, std::back_inserter(our_args),
      [](const auto arg) { return absl::StartsWith(std::string(arg), "--"); });
  int our_argc = our_args.size();
  char **our_argv = our_args.data();
  // Let gflags consume its flags, but keep them in the argument list in case
  // libFuzzer forwards the command line (e.g. with -jobs or -minimize_crash).
  gflags::ParseCommandLineFlags(&our_argc, &our_argv, false);

  if (std::any_of(argv_start, argv_end, [](const std::string_view &arg) {
        return absl::StartsWith(arg, "-fork=") ||
               absl::StartsWith(arg, "-jobs=") ||
               absl::StartsWith(arg, "-merge=");
      })) {
    if (!FLAGS_coverage_report.empty()) {
      LOG(WARNING) << "WARN: --coverage_report does not support parallel "
                      "fuzzing and has been disabled";
      FLAGS_coverage_report = "";
    }
    if (FLAGS_id_sync_file.empty()) {
      // Create an empty temporary file used for coverage ID synchronization and
      // pass its path to the agent in every child process. This requires adding
      // the argument to argv for it to be picked up by libFuzzer, which then
      // forwards it to child processes.
      FLAGS_id_sync_file = GetNewTempFilePath();
      std::string new_arg =
          absl::StrFormat("--id_sync_file=%s", FLAGS_id_sync_file);
      // This argument can be accessed by libFuzzer at any (later) time and thus
      // cannot be safely freed by us.
      additional_arg = strdup(new_arg.c_str());
      modified_argv = std::vector<char *>(argv_start, argv_end);
      modified_argv.push_back(additional_arg);
      // Terminate modified_argv.
      modified_argv.push_back(nullptr);
      // Modify argv and argc for libFuzzer. modified_argv must not be changed
      // after this point.
      *argc += 1;
      *argv = modified_argv.data();
      argv_start = *argv;
      argv_end = *argv + *argc;
    }
    // Creates the file, truncating it if it exists.
    std::ofstream touch_file(FLAGS_id_sync_file, std::ios_base::trunc);

    auto cleanup_fn = [] {
      try {
        std::filesystem::remove(std::filesystem::path(FLAGS_id_sync_file));
      } catch (...) {
        // We should not throw exceptions during shutdown.
      }
    };
    std::atexit(cleanup_fn);
  }

  initJvm(*argv_start);
}

void AbstractLibfuzzerDriver::initJvm(const std::string &executable_path) {
  jvm_ = std::make_unique<jazzer::JVM>(executable_path);
}

LibfuzzerDriver::LibfuzzerDriver(int *argc, char ***argv)
    : AbstractLibfuzzerDriver(argc, argv, getUsageString()) {
  // the FuzzTargetRunner can only be initialized after the fuzzer callbacks
  // have been registered otherwise link errors would occur
  runner_ = std::make_unique<jazzer::FuzzTargetRunner>(*jvm_);
}

std::string LibfuzzerDriver::getUsageString() {
  return R"(Test java fuzz targets using libFuzzer. Usage:
  jazzer --cp=<java_class_path> --target_class=<fuzz_target_class> <libfuzzer_arguments...>)";
}

RunResult LibfuzzerDriver::TestOneInput(const uint8_t *data,
                                        const std::size_t size) {
  // pass the fuzzer input to the java fuzz target
  return runner_->Run(data, size);
}

void LibfuzzerDriver::DumpReproducer(const uint8_t *data, std::size_t size) {
  return runner_->DumpReproducer(data, size);
}

}  // namespace jazzer
<commit_msg>Return native path to temp file in driver<commit_after>// Copyright 2021 Code Intelligence GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "libfuzzer_driver.h"

#include <rules_jni.h>

#include <algorithm>
#include <filesystem>
#include <fstream>
#include <random>
#include <string>
#include <vector>

#include "absl/strings/match.h"
#include "absl/strings/str_format.h"
#include "fuzz_target_runner.h"
#include "gflags/gflags.h"
#include "glog/logging.h"
#include "jvm_tooling.h"

using namespace std::string_literals;

// Defined by glog
DECLARE_bool(log_prefix);

// Defined in libfuzzer_callbacks.cpp
DECLARE_bool(fake_pcs);

// Defined in jvm_tooling.cpp
DECLARE_string(id_sync_file);

// Defined in fuzz_target_runner.cpp
DECLARE_string(coverage_report);

// This symbol is defined by sanitizers if linked into Jazzer or in
// sanitizer_symbols.cpp if no sanitizer is used.
extern "C" void __sanitizer_set_death_callback(void (*)());

// We apply a patch to libFuzzer to make it call this function instead of
// __sanitizer_set_death_callback to pass us the death callback.
extern "C" [[maybe_unused]] void __jazzer_set_death_callback(
    void (*callback)()) {
  jazzer::AbstractLibfuzzerDriver::libfuzzer_print_crashing_input_ = callback;
  __sanitizer_set_death_callback(callback);
}

namespace {
char *additional_arg;
std::vector<char *> modified_argv;

std::string GetNewTempFilePath() {
  auto temp_dir = std::filesystem::temp_directory_path();

  std::string temp_filename_suffix(32, '\0');
  std::random_device rng;
  std::uniform_int_distribution<short> dist(0, 'z' - 'a');
  std::generate_n(temp_filename_suffix.begin(), temp_filename_suffix.length(),
                  [&rng, &dist] { return static_cast<char>('a' + dist(rng)); });

  auto temp_path = temp_dir / ("jazzer-" + temp_filename_suffix);
  if (std::filesystem::exists(temp_path))
    throw std::runtime_error("Random temp file path exists: " +
                             temp_path.string());
  return temp_path.string();
}
}  // namespace

namespace jazzer {
// A libFuzzer-registered callback that outputs the crashing input, but does
// not include a stack trace.
void (*AbstractLibfuzzerDriver::libfuzzer_print_crashing_input_)() = nullptr;

AbstractLibfuzzerDriver::AbstractLibfuzzerDriver(
    int *argc, char ***argv, const std::string &usage_string) {
  gflags::SetUsageMessage(usage_string);
  // Disable glog log prefixes to mimic libFuzzer output.
  FLAGS_log_prefix = false;
  google::InitGoogleLogging((*argv)[0]);
  rules_jni_init((*argv)[0]);

  auto argv_start = *argv;
  auto argv_end = *argv + *argc;

  if (std::find(argv_start, argv_end, "-use_value_profile=1"s) != argv_end) {
    FLAGS_fake_pcs = true;
  }

  // All libFuzzer flags start with a single dash, our arguments all start with
  // a double dash. We can thus filter out the arguments meant for gflags by
  // taking only those with a leading double dash.
  std::vector<char *> our_args = {*argv_start};
  std::copy_if(
      argv_start, argv_end, std::back_inserter(our_args),
      [](const auto arg) { return absl::StartsWith(std::string(arg), "--"); });
  int our_argc = our_args.size();
  char **our_argv = our_args.data();
  // Let gflags consume its flags, but keep them in the argument list in case
  // libFuzzer forwards the command line (e.g. with -jobs or -minimize_crash).
  gflags::ParseCommandLineFlags(&our_argc, &our_argv, false);

  if (std::any_of(argv_start, argv_end, [](const std::string_view &arg) {
        return absl::StartsWith(arg, "-fork=") ||
               absl::StartsWith(arg, "-jobs=") ||
               absl::StartsWith(arg, "-merge=");
      })) {
    if (!FLAGS_coverage_report.empty()) {
      LOG(WARNING) << "WARN: --coverage_report does not support parallel "
                      "fuzzing and has been disabled";
      FLAGS_coverage_report = "";
    }
    if (FLAGS_id_sync_file.empty()) {
      // Create an empty temporary file used for coverage ID synchronization and
      // pass its path to the agent in every child process. This requires adding
      // the argument to argv for it to be picked up by libFuzzer, which then
      // forwards it to child processes.
      FLAGS_id_sync_file = GetNewTempFilePath();
      std::string new_arg =
          absl::StrFormat("--id_sync_file=%s", FLAGS_id_sync_file);
      // This argument can be accessed by libFuzzer at any (later) time and thus
      // cannot be safely freed by us.
      additional_arg = strdup(new_arg.c_str());
      modified_argv = std::vector<char *>(argv_start, argv_end);
      modified_argv.push_back(additional_arg);
      // Terminate modified_argv.
      modified_argv.push_back(nullptr);
      // Modify argv and argc for libFuzzer. modified_argv must not be changed
      // after this point.
      *argc += 1;
      *argv = modified_argv.data();
      argv_start = *argv;
      argv_end = *argv + *argc;
    }
    // Creates the file, truncating it if it exists.
    std::ofstream touch_file(FLAGS_id_sync_file, std::ios_base::trunc);

    auto cleanup_fn = [] {
      try {
        std::filesystem::remove(std::filesystem::path(FLAGS_id_sync_file));
      } catch (...) {
        // We should not throw exceptions during shutdown.
      }
    };
    std::atexit(cleanup_fn);
  }

  initJvm(*argv_start);
}

void AbstractLibfuzzerDriver::initJvm(const std::string &executable_path) {
  jvm_ = std::make_unique<jazzer::JVM>(executable_path);
}

LibfuzzerDriver::LibfuzzerDriver(int *argc, char ***argv)
    : AbstractLibfuzzerDriver(argc, argv, getUsageString()) {
  // the FuzzTargetRunner can only be initialized after the fuzzer callbacks
  // have been registered otherwise link errors would occur
  runner_ = std::make_unique<jazzer::FuzzTargetRunner>(*jvm_);
}

std::string LibfuzzerDriver::getUsageString() {
  return R"(Test java fuzz targets using libFuzzer. Usage:
  jazzer --cp=<java_class_path> --target_class=<fuzz_target_class> <libfuzzer_arguments...>)";
}

RunResult LibfuzzerDriver::TestOneInput(const uint8_t *data,
                                        const std::size_t size) {
  // pass the fuzzer input to the java fuzz target
  return runner_->Run(data, size);
}

void LibfuzzerDriver::DumpReproducer(const uint8_t *data, std::size_t size) {
  return runner_->DumpReproducer(data, size);
}

}  // namespace jazzer
<|endoftext|>