package Event;

## The constructor method
sub new {
   ## Throw out the first parameter, the class name
   shift @_;

   ## Use the arguments given to the constructor
   my ($DateTime, $ProtocolId, $SourceAddress, $SourcePort,
       $DestinationAddress, $DestinationPort, $EventCount,
       $LogFormat, $IdsString) = @_;

   ## Used for our object reference
   my ($self) = {};

   ## Setup variables that will be maintained inside the object reference
   $self->{DATETIME}                    = $DateTime;
   $self->{PROTOCOL}                    = $ProtocolId;
   $self->{SOURCE_ADDRESS}              = $SourceAddress;
   $self->{SOURCE_ADDRESS_NUMBER}       = &convert_address($SourceAddress);
   $self->{SOURCE_PORT}                 = $SourcePort;
   $self->{DESTINATION_ADDRESS}         = $DestinationAddress;
   $self->{DESTINATION_ADDRESS_NUMBER}  = &convert_address($DestinationAddress);
   $self->{DESTINATION_PORT}            = $DestinationPort;
   $self->{EVENT_COUNT}                 = $EventCount;
   $self->{LOG_FORMAT}                  = $LogFormat;
   $self->{IDS}                         = $IdsString;
   $self->{CREATION_TIME}               = time;
   $self->{DESTINATION_NETMASK_ADDRESS} = undef;
   $self->{SOURCE_NETMASK_ADDRESS}      = undef;

   ## Obtain an object reference for this package
   bless($self);

   ## Return it to the caller
   return $self;
}

## This method is used to obtain the date time for the event
sub getDateTime {
   my ($self) = @_;
   return $self->{DATETIME};
}

## This method is used to obtain the protocol id for the event
sub getProtocol {
   my ($self) = @_;
   return $self->{PROTOCOL};
}

## This method is used to obtain the protocol name for the event
sub getProtocolName {
   my ($self) = @_;

   ## Protocol number to name translation hash
   my (%Protocols) = (
      1  => 'icmp',
      6  => 'tcp',
      17 => 'udp',
   );

   ## Return the protocol name, if defined, otherwise the number
   return (defined $Protocols{ $self->{PROTOCOL} } ?
           $Protocols{ $self->{PROTOCOL} } : $self->{PROTOCOL});
}

## This method is used to obtain the source address for the event
sub getSourceAddress {
   my ($self) = @_;
   return $self->{SOURCE_ADDRESS};
}

## This method is used to obtain the source address
## number for the event
sub getSourceAddressNumber {
   my ($self) = @_;
   return $self->{SOURCE_ADDRESS_NUMBER};
}

## This method is used to obtain the apply the given netmask against
## the source address for the event
sub maskSourceAddress {
   my ($self, $netmask) = @_;

   if (!defined $self->{SOURCE_NETMASK_ADDRESS} ||
        $self->{SOURCE_NETMASK_ADDRESS} ne $netmask) {

      $self->{SOURCE_NETMASK_NUMBER} = &convert_address($netmask);
      $self->{SOURCE_NETMASK_ADDRESS} = $netmask;
      $self->{MASK_SOURCE_ADDRESS} =
            $self->{SOURCE_ADDRESS_NUMBER} &
            $self->{SOURCE_NETMASK_NUMBER};

   }

   return $self->{MASK_SOURCE_ADDRESS};
}

## This method is used to obtain the source port for the event
sub getSourcePort {
   my ($self) = @_;
   return $self->{SOURCE_PORT};
}

## This method is used to obtain the destination address for the event
sub getDestinationAddress {
   my ($self) = @_;
   return $self->{DESTINATION_ADDRESS};
}

## This method is used to obtain the destination address
## number for the event
sub getDestinationAddressNumber {
   my ($self) = @_;
   return $self->{DESTINATION_ADDRESS_NUMBER};
}

## This method is used to obtain the apply the given netmask against
## the destination address for the event
sub maskDestinationAddress {
   my ($self, $netmask) = @_;

   if (!defined $self->{DESTINATION_NETMASK_ADDRESS} ||
        $self->{DESTINATION_NETMASK_ADDRESS} ne $netmask) {

      $self->{DESTINATION_NETMASK_NUMBER} = &convert_address($netmask);
      $self->{DESTINATION_NETMASK_ADDRESS} = $netmask;
      $self->{MASK_DESTINATION_ADDRESS} =
            $self->{DESTINATION_ADDRESS_NUMBER} &
            $self->{DESTINATION_NETMASK_NUMBER};

   }

   return $self->{MASK_DESTINATION_ADDRESS};
}

## This method is used to obtain the destination port for the event
sub getDestinationPort {
   my ($self) = @_;
   return $self->{DESTINATION_PORT};
}

## This method is used to obtain the event count for the event
sub getEventCount {
   my ($self) = @_;
   return $self->{EVENT_COUNT};
}

## This method is used to obtain the log format for the event
sub getLogFormat {
   my ($self) = @_;
   return $self->{LOG_FORMAT};
}

## This method is used to obtain the ids string for the event
sub getIdsString {
   my ($self) = @_;
   return $self->{IDS};
}

## This method is used to obtain the time value when the event was created
sub getCreationTime {
   my ($self) = @_;
   return $self->{CREATION_TIME};
}

## This method is used to obtain all of the values in a string formatted
## for a HTTP GET
sub getHttpGetArguments {
   my ($self) = @_;
   return join('&',
      join('=', 'ProtocolID',     $self->{PROTOCOL}),
      join('=', 'AttackerIP',     $self->{SOURCE_ADDRESS}),
      join('=', 'SrcPort',        $self->{SOURCE_PORT}),
      join('=', 'VictimIP',       $self->{DESTINATION_ADDRESS}),
      join('=', 'DestPort',       $self->{DESTINATION_PORT}),
      join('=', 'AttackCount',    $self->{EVENT_COUNT}),
      join('=', 'AttackDateTime', $self->{DATETIME}),
      join('=', 'LogFormat',      $self->{LOG_FORMAT})) . $self->{IDS};
}

## This method will set the event count and return the new value
sub setEventCount {
   my ($self, $count) = @_;
   $self->{EVENT_COUNT} = $count;
   return $self->{EVENT_COUNT};
}

## This method will increment the event count, and then return the new
## event count value
sub addEventCount {
   my ($self, $increment) = @_;
   $self->{EVENT_COUNT} += $increment;
   return $self->{EVENT_COUNT};
}

## This method will replace the destination address with a new one given
## as an argument.
sub setDestinationAddress {
   my ($self, $DestinationAddress) = @_;
   $self->{DESTINATION_ADDRESS} = $DestinationAddress;
   return $self->{DESTINATION_ADDRESS};
}

## Check if this event object is considered valid
sub isValid {
   my ($self) = @_;

   ## Check if critical data elements are valid
   if (length($self->{DATETIME}) > 0           &&
      length($self->{SOURCE_ADDRESS}) > 0      &&
      length($self->{DESTINATION_ADDRESS}) > 0 &&
      $self->{PROTOCOL} != 0                   &&
      $self->{SOURCE_PORT} != 0                &&
      $self->{DESTINATION_PORT} != 0           &&
      $self->{EVENT_COUNT} > 0) {
      ## return non-zero for true
      return 1;
   } else {
      ## return zero for false
      return 0;
   }
}

## This static method is used to convert the ip address to/from
## a 32-bit number
sub convert_address {
   my ($IpAddress) = @_;
   my (@octets);

   @octets = split(/\./,$IpAddress);

   if (@octets == 4) {
      ## Convert the address to a number
      return ($octets[0] << 24) | ($octets[1] << 16) |
         ($octets[2] << 8) | $octets[3];
   } else {
      ## Convert the number to an address
      return sprintf("%u.%u.%u.%u", (($IpAddress & 0xff000000) >> 24),
         (($IpAddress & 0x00ff0000) >> 16), (($IpAddress & 0x0000ff00) >> 8),
         ($IpAddress & 0x000000ff));
   }
}

1;
