NAME
    POE::Component::Server::IRC - A fully event-driven networkable IRC
    server daemon module.

SYNOPSIS
      # A fairly simple example:
      use strict;
      use warnings;
      use POE qw(Component::Server::IRC);

      my %config = ( 
                    servername => 'simple.poco.server.irc', 
                    nicklen    => 15,
                    network    => 'SimpleNET'
      );

      my $pocosi = POE::Component::Server::IRC->spawn( config => \%config );

      POE::Session->create(
            package_states => [
               'main' => [qw(_start _default)],
            ],
            heap => { ircd => $pocosi },
      );

      $poe_kernel->run();
      exit 0;

      sub _start {
        my ($kernel,$heap) = @_[KERNEL,HEAP];
        $heap->{ircd}->yield( 'register' );
        # Anyone connecting from the loopback gets spoofed hostname
        $heap->{ircd}->add_auth( mask => '*@localhost', spoof => 'm33p.com', no_tilde => 1 );
        # We have to add an auth as we have specified one above.
        $heap->{ircd}->add_auth( mask => '*@*' );
        # Start a listener on the 'standard' IRC port.
        $heap->{ircd}->add_listener( port => 6667 );
        # Add an operator who can connect from localhost
        $heap->{ircd}->add_operator( { username => 'moo', password => 'fishdont' } );
        undef;
      }

      sub _default {
         my ( $event, $args ) = @_[ ARG0 .. $#_ ];
         print STDOUT "$event: ";
         foreach (@$args) {
         SWITCH: {
                  if ( ref($_) eq 'ARRAY' ) {
                      print STDOUT "[", join ( ", ", @$_ ), "] ";
                      last SWITCH;
                  }
                  if ( ref($_) eq 'HASH' ) {
                      print STDOUT "{", join ( ", ", %$_ ), "} ";
                      last SWITCH;
                  }
                  print STDOUT "'$_' ";
              }
          }
          print STDOUT "\n";
          return 0;    # Don't handle signals.
      }

DESCRIPTION
    POE::Component::Server::IRC is a POE component which implements an IRC
    server ( also referred to as an IRC daemon or IRCd ). It should be
    compliant with the pertient IRC RFCs and is based on reverse engineering
    Hybrid IRCd behaviour with regards to interactions with IRC clients and
    other IRC servers.

    Yes, that's right. POE::Component::Server::IRC is capable of linking to
    form IRC networks. It supports the TS5 server to server protocol and has
    been tested with linking to Hybrid-7 based networks. It should in theory
    work with any TS5-based IRC network.

    POE::Component::Server::IRC also has a services API, which enables one
    to extend the IRCd to create IRC Services. This is fully event-driven (
    of course =] ). There is also a Plugin system, similar to that sported
    by POE::Component::IRC.

CONSTRUCTOR
    "spawn"
        Creates a POE::Session and associated object. The session's heap is
        set to the object, so it is possible to retrieve the object in any
        of your event handlers by using $_[SENDER]->get_heap().

        Returns the object, takes the following parameters:

          'alias', a POE::Kernel alias to set, no default;
          'auth', set to 0 to globally disable IRC authentication, default is auth is enabled;
          'antiflood', set to 0 to globally disable flood protection, default enabled;
          'config', a hashref of configuration options, see configure() method for details;

        If the component is spawned from within another session then that
        session will automagically be registered with the component to
        receive events and be sent an 'ircd_registered' event.

METHODS
  CONFIGURATION & CONTROL
    These methods provide mechanisms for configuring and controlling the
    IRCd component.

    "configure"
        Configures your new shiny IRCd.

        Takes a number of parameters:

          'servername', a name to bless your shiny new IRCd with, default 'poco.server.irc';
          'serverdesc', a description for your IRCd, default 'Poco? POCO? POCO!';
          'network', the name of the IRC network you will be creating, default 'poconet';
          'nicklen', the max length of nicknames to support, default is 9.
                     NB: the nicklen must be the same on all servers on your IRC network;
          'maxtargets', max number of targets a user can send PRIVMSG/NOTICE's to, default 4;
          'maxchannels', max number of channels users may join, default 15;
          'version', change the server version that is reported;
          'admin', an arrayref consisting of the 3 lines that will be returned by ADMIN;
          'info', an arrayref consisting of lines to be returned by INFO;
          'ophacks', set to true to enable oper hacks;
          'whoisactually', set this to 0 so only opers can see 338 replies to WHOIS queries, default is 1;

    "session_id"
        Takes no arguments. Returns the ID of the component's session. Ideal
        for posting events to the component.

    "yield"
        This method provides an alternative object based means of posting
        events to the component. First argument is the event to post,
        following arguments are sent as arguments to the resultant post.

    "call"
        This method provides an alternative object based means of calling
        events to the component. First argument is the event to call,
        following arguments are sent as arguments to the resultant call.

    "shutdown"
        Takes no arguments. Terminates the component. Removes all listeners
        and connectors. Disconnects all current client and server
        connections.

    "add_operator"
        This adds an O line to the IRCd. Takes a number of parameters:

          'username', the username of the IRC oper, mandatory;
          'password', the password, mandatory;
          'ipmask', either a scalar ipmask or an arrayref of Net::Netmask objects;

        A scalar ipmask can be contain '*' to match any number of characters
        or '?' to match one character. If no 'ipmask' is provided, operators
        are only allowed to OPER from the loopback interface.

        'password' can be either plain-text, "crypt"'d or unix/apache md5.
        See "mkpasswd" function in POE::Component::Server::IRC::Common for
        generating passwords.

    "del_operator"
        Takes a single argument, the username to remove.

    "add_peer"
        Adds peer servers that we will allow to connect to us and who we
        will connect to. Takes the following parameters:

          'name', the name of the server. This is the IRC name, not hostname, mandatory;
          'pass', the password they must supply to us, mandatory;
          'rpass', the password we need to supply to them, mandatory;
          'type', the type of server, 'c' for a connecting server, 'r' for one
                  that we will connect to;
          'raddress', the remote address to connect to, implies 'type' eq 'r';
          'rport', the remote port to connect to, default is 6667;
          'ipmask', either a scalar ipmask or an arrayref of Net::Netmask objects;
          'auto', if set to true value will automatically connect to remote server if type is 'r';

        Additionally, if POE::Filter::Zlib::Stream is installed, ziplinks
        between POE::Component::Server::IRC ircds are supported:

          'zip', set to a true value to enable ziplink support. This must be done on both ends of the connection;

    "del_peer"
        Takes a single argument, the peer to remove. This does not
        disconnect the said peer if it is currently connected.

    "add_auth"
        By default the IRCd allows any user@host to connect to the server
        without a password. Configuring auths enables you to control who can
        connect and set passwords required to connect.

        Takes a number of parameters:

          'mask', a user@host or user@ipaddress mask to match against, mandatory;
          'password', if specified any client matching the mask must provide this to connect;
          'spoof', if specified any client matching the mask will have their hostname changed to this;
          'no_tilde', if specified the '~' prefix is removed from their username;

        Auth masks are processed in order of addition.

        If auth masks have been defined, then a connecting user *must* match
        one of the masks in order to be authorised to connect. This is a
        feature >;)

    "del_auth"
        Takes a single argument, the mask to remove.

    "add_denial"
        Takes one mandatory argument and one optional. The first mandatory
        argument is a Net::Netmask object that will be used to check
        connecting IP addresses against. The second optional argument is a
        reason string for the denial.

    "del_denial"
        Takes one mandatory argument, a Net::Netmask object to remove from
        the current denial list.

    "add_exemption"
        Takes one mandatory argument, a Net::Netmask object that will be
        checked against connecting IP addresses for exemption from denials.

    "del_exemption"
        Takes one mandatory argument, a Net::Netmask object to remove from
        the current exemption list.

  STATE MANIPULATION
    The STATE contains all the salient information regarding nicknames,
    channels and peers. These methods allow you to query and manipulate this
    information.

    "server_name"
        No arguments, returns the name of the ircd.

    "server_version"
        No arguments, returns the software version of the ircd.

    "server_created"
        No arguments, returns a string signifying when the ircd was created.

    "server_config"
        Takes one argument, the server configuration value to query.

    "state_nicks"
        Takes no arguments, returns a list of all nicknames in the state.

    "state_chans"
        Takes no arguments, returns a list of all channels in the state.

    "state_peers"
        Takes no arguments, returns a list of all irc servers in the state.

    "state_nick_exists"
        Takes one argument, a nickname, returns true or false dependent on
        whether the given nickname exists or not.

    "state_chan_exists"
        Takes one argument, a channel name, returns true or false dependent
        on whether the given channel exists or not.

    "state_peer_exists"
        Takes one argument, a peer server name, returns true or false
        dependent on whether the given peer exists or not.

    "state_user_full"
        Takes one argument, a nickname, returns that users full
        nick!user@host if they exist, undef if they don't.

    "state_user_nick"
        Takes one argument, a nickname, returns the proper nickname for that
        user. Returns undef if the nick doesn't exist.

    "state_user_umode"
        Takes one argument, a nickname, returns that users mode setting.

    "state_user_is_operator"
        Takes one argument, a nickname, returns true or false dependent on
        whether the given nickname is an IRC operator or not.

    "state_user_chans"
        Takes one argument, a nickname, returns a list of channels that that
        nick is a member of.

    "state_user_server"
        Takes one argument, a nickname, returns the name of the peer server
        that that user is connected from.

    "state_chan_list"
        Takes one argument, a channel name, returns a list of the member
        nicks on that channel.

    "state_chan_list_prefixed"
        Takes one argument, a channel name, returns a list of the member
        nicks on that channel, nicknames will be prefixed with @%+ if they
        are +o +h or +v, respectively.

    "state_chan_topic"
        Takes one argument, a channel name, returns undef if no topic is set
        on that channel, or an arrayref consisting of the topic, who set it
        and the time they set it.

    "state_chan_mode_set"
        Takes two arguments, a channel name and a channel mode character.
        Returns true if that channel mode is set, false otherwise.

    "state_is_chan_member"
        Takes two arguments, a nick and a channel name. Returns true if that
        nick is on channel, false otherwise.

    "state_user_chan_mode"
        Takes two arguments, a nick and a channel name. Returns that nicks
        status ( +ohv or '' ) on that channel.

    "state_is_chan_op"
        Takes two arguments, a nick and a channel name. Returns true if that
        nick is an channel operator, false otherwise.

    "state_is_chan_hop"
        Takes two arguments, a nick and a channel name. Returns true if that
        nick is an channel half-operator, false otherwise.

    "state_has_chan_voice"
        Takes two arguments, a nick and a channel name. Returns true if that
        nick has channel voice, false otherwise.

    "daemon_server_kill"
        Takes two arguments, a nickname and a comment ( which is optional );
        Issues a SERVER KILL of the given nick;

    "daemon_server_mode"
        First argument is a channel name, remaining arguments are channel
        modes and their parameters to apply.

    "daemon_server_kick"
        Takes two arguments that are mandatory and an optional one: channel
        name, nickname of the user to kick and a pithy comment.

    "daemon_server_remove"
        Takes two arguments that are mandatory and an optional one: channel
        name, nickname of the user to remove and a pithy comment.

    "daemon_server_wallops"
        Takes one argument, the message text to send.

INPUT EVENTS
    These are POE events that can be sent to the component.

    "register"
        Takes no arguments. Registers a session to receive events from the
        component.

    "unregister"
        Takes no arguments. Unregisters a previously registered session.

    "add_listener"
        Takes a number of arguments. Adds a new listener.

                'port', the TCP port to listen on. Default is a random port;
                'auth', enable or disable auth sub-system for this listener. Default enabled;
                'bindaddr', specify a local address to bind the listener to;
                'listenqueue', change the SocketFactory's ListenQueue;

        A listener is required to accept connections from clients.

    "del_listener"
        Takes either 'port' or 'listener':

                'listener' is a previously returned listener ID;
                'port', listening TCP port;

        The listener will be deleted. Note: any connected clients on that
        port will not be disconnected.

    "add_spoofed_nick"
        Takes a single argument a hashref which should have the following
        keys:

          'nick', the nickname to add, mandatory;
          'user', the ident you want the nick to have, default same as nick;
          'hostname', the hostname, defaults to the server name;
          'umode', specify whether this is to be an IRCop etc, default 'i';
          'ts', unixtime, default is time(), best not to meddle;

        Note: spoofed nicks are currently only really functional for use as
        IRC services;

    "del_spoofed_nick"
        Takes a single mandatory argument, the spoofed nickname to remove.
        Optionally, you may specify a quit message for the spoofed nick.

    The following input events are for the benefit of spoofed nicks. All
    require a nickname of a spoofed nick as the first argument.

    "daemon_cmd_join"
        Takes two arguments, a spoofed nick and a channel name to join.

    "daemon_cmd_part"
        Takes two arguments, a spoofed nick and a channel name to part from.

    "daemon_cmd_mode"
        Takes at least three arguments, a spoofed nick, a channel and a
        channel mode to apply. Additional arguments are parameters for the
        channel modes.

    "daemon_cmd_kick"
        Takes at least three arguments, a spoofed nick, a channel name and
        the nickname of a user to kick from that channel. You may supply a
        fourth argument which will be the kick comment.

    "daemon_cmd_topic"
        Takes three arguments, a spoofed nick, a channel name and the topic
        to set on that channel. If the third argument is an empty string
        then the channel topic will be unset.

    "daemon_cmd_nick"
        Takes two arguments, a spoofed nick and a new nickname to change to.

    "daemon_cmd_gline"
        Takes three arguments, a spoofed nick, a user@host mask to gline and
        a reason for the gline.

    "daemon_cmd_kline"
        Takes a number of arguments depending on where the KLINE is to be
        applied and for how long:

        To set a permanent KLINE:

          $poe_kernel->post( 'ircd', 
                             'daemon_cmd_kline', 
                             $spoofed_nick,
                             $nick || $user_host_mask,
                             $reason,
          );

        To set a temporary 10 minute KLINE:

          $poe_kernel->post( 'ircd', 
                             'daemon_cmd_kline', 
                             $spoofed_nick,
                             10,
                             $nick || $user_host_mask,
                             $reason,
          );

        To set a temporary 10 minute KLINE on all servers:

          $poe_kernel->post( 'ircd', 
                             'daemon_cmd_kline', 
                             $spoofed_nick,
                             10,
                             $nick || $user_host_mask,
                             'on',
                             '*',
                             $reason,
          );

    "daemon_cmd_unkline"
        Removes a KLINE as indicated by the user@host mask supplied.

        To remove a KLINE:

          $poe_kernel->post( 'ircd', 
                             'daemon_cmd_unkline', 
                             $spoofed_nick,
                             $user_host_mask,
          );

        To remove a KLINE from all servers:

          $poe_kernel->post( 'ircd', 
                             'daemon_cmd_unkline', 
                             $spoofed_nick,
                             $user_host_mask,
                             'on',
                             '*',
          );

    "daemon_cmd_rkline"
        Used to set a regex based KLINE. The regex given must be based on a
        user@host mask.

        To set a permanent RKLINE:

          $poe_kernel->post( 'ircd', 
                             'daemon_cmd_rkline', 
                             $spoofed_nick,
                             '^.*$@^(yahoo|google|microsoft)\.com$',
                             $reason,
          );

        To set a temporary 10 minute RKLINE:

          $poe_kernel->post( 'ircd', 
                             'daemon_cmd_rkline', 
                             $spoofed_nick,
                             10,
                             '^.*$@^(yahoo|google|microsoft)\.com$',
                             $reason,
          );

        To set a temporary 10 minute RKLINE on all servers:

          $poe_kernel->post( 'ircd', 
                             'daemon_cmd_kline', 
                             $spoofed_nick,
                             10,
                             '^.*$@^(yahoo|google|microsoft)\.com$',
                             'on',
                             '*',
                             $reason,
          );

    "daemon_cmd_sjoin"
        Takes two arguments a spoofed nickname and an existing channel name.
        This command will then manipulate the channel timestamp to clear all
        modes on that channel, including existing channel operators, reset
        the channel mode to '+nt', the spoofed nick will then join the
        channel and gain channel ops.

    "daemon_cmd_privmsg"
        Takes three arguments, a spoofed nickname, a target ( which can be a
        nickname or a channel name ) and whatever text you wish to send.

    "daemon_cmd_notice"
        Takes three arguments, a spoofed nickname, a target ( which can be a
        nickname or a channel name ) and whatever text you wish to send.

    "daemon_cmd_locops"
        Takes two arguments, a spoofed nickname and the text message to send
        to local operators.

    "daemon_cmd_wallops"
        Takes two arguments, a spoofed nickname and the text message to send
        to all operators.

    "daemon_cmd_operwall"
        Takes two arguments, a spoofed nickname and the text message to send
        to all operators.

OUTPUT EVENTS
    After a session has registered with the component it will receive the
    following events:

    "ircd_registered"
          Emitted: when a session registers with the component;
          Target: the registering session;
          Args:
                ARG0, the component's object;

    "ircd_unregistered"
          Emitted: when a session unregisters with the component;
          Target: the unregistering session;
          Args: none

    ircd_listener_add
          Emitted: on a successful add_listener() call;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the listening port;
                ARG1, the listener id;

    ircd_listener_del
          Emitted: on a successful del_listener() call;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the listening port;
                ARG1, the listener id;

    ircd_listener_failure
          Emitted: when a listener wheel fails;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the listener id;
                ARG1, the name of the operation that failed;
                ARG2, numeric value for $!;
                ARG3, string value for $!;

    ircd_daemon_server
          Emitted: when a server is introduced onto the network;
          Target: all plugins and registered sessions;
          Args:
                ARG0, server name;
                ARG1, the name of the server that is introducing them;
                ARG2, Hop count;
                ARG3, Server description;

    ircd_daemon_squit
          Emitted: when a server quits the network;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the server name;

    ircd_daemon_nick
          Emitted: when a user is introduced onto the network or a user changes nick;
          Target: all plugins and registered sessions;
          Args: ( new nick ):
                ARG0, nickname;
                ARG1, hop count;
                ARG2, Time Stamp (TS);
                ARG3, umode;
                ARG4, ident;
                ARG5, hostname;
                ARG6, servername;
                ARG7, Real Name;

          Args: ( nick change ):
                ARG0, the full user (nick!ident@host);
                ARG1, the nickname they are changing to;

    ircd_daemon_umode
          Emitted: when a user performs a umode change;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, the umode changes they made;

    ircd_daemon_quit
          Emitted: when a user quits or the server they are on squits;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, Quit message;

    ircd_daemon_join
          Emitted: when a user joins a channel;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, the channel name;

    ircd_daemon_part
          Emitted: when a user parts a channel;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, the channel name;
                ARG2, part message or nickname;

    ircd_daemon_kick
          Emitted: when a user is kicked from a channel;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host) of the kicker;
                ARG1, the channel name;
                ARG2, the nick of the kicked person;
                ARG3, some pithy comment;

    ircd_daemon_mode
          Emitted: when a mode is changed on a channel;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host) or servername;
                ARG1, Channel name;
                ARG2 .. $#_: modes and arguments;

    ircd_daemon_topic
          Emitted: when a topic changes on a channel;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, Channel name;
                ARG2, the new topic;

    ircd_daemon_public
          Emitted: on channel targetted privmsg, a spoofed nick must be on the channel;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, the channel name;
                ARG2, what was said;

    ircd_daemon_privmsg
          Emitted: when someone sends a privmsg to a spoofed nick;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, the spoofed nick targetted;
                ARG2, what was said;

    ircd_daemon_notice
          Emitted: when someone sends a notice to a spoofed nick or channel;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, the spoofed nick targetted or channel spoofed nick is on;
                ARG2, what was said;

    ircd_daemon_invite
          Emitted: when someone invites a spoofed nick to a channel;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, the spoofed nick targetted;
                ARG2, the channel invited to;

    ircd_daemon_rehash
          Emitted: when an oper issues REHASH command;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);

    ircd_daemon_die
          Emitted: when an oper issues DIE command;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);

        Note: the component will shutdown, this is a feature;

    ircd_daemon_gline
          Emitted: when an oper issues GLINE command;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, user mask;
                ARG2, host mask;
                ARG3, Reason;

    ircd_daemon_kline
          Emitted: when an oper issues KLINE command;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, target for the KLINE;
                ARG2, duration in seconds;
                ARG3, user mask;
                ARG4, host mask;
                ARG5, Reason;

    ircd_daemon_rkline
          Emitted: when an oper issues RKLINE command;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, target for the RKLINE;
                ARG2, duration in seconds;
                ARG3, user mask;
                ARG4, host mask;
                ARG5, Reason;

    ircd_daemon_unkline
          Emitted: when an oper UNKLINEs a KLINE;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, target for the UNKLINE;
                ARG2, user mask;
                ARG3, host mask;

    ircd_daemon_locops
          Emitted: when an oper issues a LOCOPS;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, the locops message;

    ircd_daemon_operwall
          Emitted: when an oper issues a WALLOPS or OPERWALL;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the full user (nick!ident@host);
                ARG1, the wallops or operwall message;

    ircd_daemon_wallops
          Emitted: when a server issues a WALLOPS;
          Target: all plugins and registered sessions;
          Args:
                ARG0, the server name;
                ARG1, the wallops message;

PLUGIN SYSTEM
    Plugins are a way of handling output events from the component with
    plugin object handlers that are loaded and processed within the
    component event dispatch system.

    Events are processed with the dispatch system, first by plugin handlers
    within the component itself, then by loaded plugins, then dispatched to
    registered sessions.

    The general architecture of using the plugins should be:

            # Import the stuff...
            use POE;
            use POE::Component::Server::IRC;
            use POE::Component::Server::IRC::Plugin::ExamplePlugin;

            # Create the IRC server here
            my $irc = POE::Component::Server::IRC->spawn() or die 'Nooo!';

            # Create our session here
            POE::Session->create( ... );

            # Create the plugin
            # Of course it could be something like $plugin = MyPlugin->new();
            my $plugin = POE::Component::Server::IRC::Plugin::ExamplePlugin->new( ... );

            # Hook it up!
            $irc->plugin_add( 'ExamplePlugin', $plugin );

            # OOPS, we lost the plugin object!
            my $pluginobj = $irc->plugin_get( 'ExamplePlugin' );

            # We want a list of plugins and objects
            my $hashref = $irc->plugin_list();

            # Oh! We want a list of plugin aliases.
            my @aliases = keys %{ $irc->plugin_list() };

            # Ah, we want to remove the plugin
            $plugin = $irc->plugin_del( 'ExamplePlugin' );

    The plugins themselves will conform to the standard API described here:

            # Import the constants
            use POE::Component::Server::IRC::Plugin qw( :ALL );

            # Our constructor
            sub new {
                    ...
            }

            # Required entry point for POE::Component::Server::IRC
            sub PCSI_register {
                    my( $self, $irc ) = @_;

                    # Register events we are interested in
                    $irc->plugin_register( $self, 'SERVER', qw(all) );

                    # Return success
                    return 1;
            }

            # Required exit point for POE::Component::Server::IRC
            sub PCSI_unregister {
                    my( $self, $irc ) = @_;

                    # PCSI will automatically unregister events for the plugin

                    # Do some cleanup...

                    # Return success
                    return 1;
            }

            # Registered events will be sent to methods starting with IRC_
            # If the plugin registered for SERVER - daemon_join
            sub IRCD_daemon_join {
                    my( $self, $irc, @args ) = @_;
                
                    # @args will be an array of scalar references.

                    # Return an exit code
                    return PCSI_EAT_NONE;
            }

            # Default handler for events that do not have a corresponding plugin method defined.
            sub _default {
                    my( $self, $irc, $event ) = splice @_, 0, 3;

                    print "Default called for $event\n";

                    # Return an exit code
                    return PCSI_EAT_NONE;
            }

    Available methods to use on the POE::Component::Server::IRC object:

    plugin_add
        Accepts two arguments:

          The alias for the plugin
          The actual plugin object

        The alias is there for the user to refer to it, as it is possible to
        have multiple plugins of the same kind active in one PCSI object.

        This method will call $plugin->PCSI_register( $ircd )

        Returns 1 if plugin was initialized, undef if not.

    plugin_get
        Accepts one argument: The alias for the plugin

        Returns the plugin object if it was found, undef if not.

    plugin_del
        Accepts one argument: The alias for the plugin or the plugin object
        itself

        This method will call $plugin->PCSI_unregister( $ircd )

        Returns the plugin object if the plugin was removed, undef if not.

    plugin_list
        Has no arguments.

        Returns a hashref of plugin objects, keyed on alias, or an empty
        list if there are no plugins loaded.

    The following methods are called on the PCSI object from within the
    plugin object:

    plugin_register
        Accepts the following arguments: The plugin object The type of the
        hook ( 'SERVER' ) The event name(s) to watch

        The event names can be as many as possible, or an arrayref. They
        correspond to the ircd_* events listed in
        POE::Component::Server::IRC, and naturally, arbitrary events too.

        You do not need to supply events with ircd_ in front of them, just
        the names.

        It is possible to register for all events by specifying 'all' as an
        event.

        Returns 1 if everything checked out fine, undef if something's
        seriously wrong

    plugin_unregister
        Accepts the following arguments: The plugin object The type of the
        hook ( 'SERVER' ) The event name(s) to unwatch

        The event names can be as many as possible, or an arrayref. They
        correspond to the ircd_* events listed in
        POE::Component::Server::IRC, and naturally, arbitrary events too.

        You do not need to supply events with ircd_ in front of them, just
        the names.

        Returns 1 if all the event name(s) was unregistered, undef if some
        was not found

    The following two OUTPUT events are generated on plugin
    registration/unregistration:

    ircd_plugin_add
        This event will be triggered after a plugin is added. It receives
        two arguments, the first being the plugin name, and the second being
        the plugin object.

    ircd_plugin_del
        This event will be triggered after a plugin is deleted. It receives
        two arguments, the first being the plugin name, and the second being
        the plugin object.

    Plugin handler methods receive the PCSI object as their first argument.
    The remaining arguments are scalar references to the event arguments.

    The exit code of plugin handlers is important. Your handlers *must*
    return one of the following:

    PCSI_EAT_NONE
                This means the event will continue to be processed by remaining plugins and
                finally, sent to interested sessions that registered for it.

    PCSI_EAT_CLIENT
                This means the event will continue to be processed by remaining plugins but
                it will not be sent to any sessions that registered for it.

    PCSI_EAT_PLUGIN
                This means the event will not be processed by remaining plugins, it will go
                straight to interested sessions.

    PCSI_EAT_ALL
                This means the event will be completely discarded, no plugin or session will see it.

    The above constants can be included in your plugin packages by importing
    the :ALL tag from POE::Component::Server::IRC::Plugin as so:

      use POE::Component::Server::IRC::Plugin qw(:ALL);

AUTHOR
    Chris 'BinGOs' Williams

LICENSE
    Copyright "(c)" Chris Williams

    This module may be used, modified, and distributed under the same terms
    as Perl itself. Please see the license that came with your Perl
    distribution for details.

KUDOS
    Rocco Caputo for creating POE.

    Buu for pestering me when I started to procrastinate =]

SEE ALSO
    Net::Netmask

    POE POE <http://poe.perl.org/>

    POE::Component::Server::IRC::Backend

    Hybrid IRCD <http://ircd-hybrid.com/>

    TSOra <http://www.idolnet.org/docs/README.TSora>

    RFC 2810 <http://www.faqs.org/rfcs/rfc2810.html>

    RFC 2811 <http://www.faqs.org/rfcs/rfc2811.html>

    RFC 2812 <http://www.faqs.org/rfcs/rfc2812.html>

    RFC 2813 <http://www.faqs.org/rfcs/rfc2813.html>

