our
$AUTHORITY
=
'cpan:HINRIK'
;
$POE::Component::IRC::Plugin::Console::VERSION
=
'6.93'
;
use
POE
qw(Wheel::SocketFactory Wheel::ReadWrite Filter::IRCD Filter::Line Filter::Stackable)
;
sub
new {
my
$package
=
shift
;
croak
"$package requires an even number of arguments"
if
@_
& 1;
my
%self
=
@_
;
return
bless
\
%self
,
$package
;
}
sub
PCI_register {
my
(
$self
,
$irc
) =
splice
@_
, 0, 2;
$self
->{irc} =
$irc
;
$irc
->plugin_register(
$self
,
'SERVER'
,
qw(all)
);
$irc
->plugin_register(
$self
,
'USER'
,
qw(all)
);
POE::Session->create(
object_states
=> [
$self
=> [
qw(_client_error _client_flush _client_input _listener_accept _listener_failed _start _shutdown)
],
],
);
return
1;
}
sub
PCI_unregister {
my
(
$self
,
$irc
) =
splice
@_
, 0, 2;
delete
$self
->{irc};
$poe_kernel
->post(
$self
->{SESSION_ID} =>
'_shutdown'
);
$poe_kernel
->refcount_decrement(
$self
->{SESSION_ID}, __PACKAGE__ );
return
1;
}
sub
_dump {
my
(
$arg
) =
@_
;
if
(
ref
$arg
eq
'ARRAY'
) {
my
@elems
;
for
my
$elem
(
@$arg
) {
push
@elems
, _dump(
$elem
);
}
return
'['
.
join
(
', '
,
@elems
) .
']'
;
}
elsif
(
ref
$arg
eq
'HASH'
) {
my
@pairs
;
for
my
$key
(
keys
%$arg
) {
push
@pairs
, [
$key
, _dump(
$arg
->{
$key
})];
}
return
'{'
.
join
(
', '
,
map
{
"$_->[0] => $_->[1]"
}
@pairs
) .
'}'
;
}
elsif
(
ref
$arg
) {
return
overload::StrVal(
$arg
);
}
elsif
(
defined
$arg
) {
return
$arg
if
looks_like_number(
$arg
);
return
"'"
.decode_irc(
$arg
).
"'"
;
}
else
{
return
'undef'
;
}
}
sub
_default {
my
(
$self
,
$irc
,
$event
) =
splice
@_
, 0, 3;
return
PCI_EAT_NONE
if
$event
eq
'S_raw'
;
pop
@_
;
my
@args
=
map
{
$$_
}
@_
;
my
@output
;
for
my
$i
(0..
$#args
) {
push
@output
,
"ARG$i: "
. _dump(
$args
[
$i
]);
}
for
my
$wheel_id
(
keys
%{
$self
->{wheels} } ) {
next
if
(
$self
->{
exit
}->{
$wheel_id
} or ( not
defined
(
$self
->{wheels}->{
$wheel_id
} ) ) );
next
if
!
$self
->{authed}{
$wheel_id
};
$self
->{wheels}->{
$wheel_id
}->put(
"$event: "
.
join
(
', '
,
@output
));
}
return
PCI_EAT_NONE;
}
sub
_start {
my
(
$kernel
,
$self
) =
@_
[KERNEL, OBJECT];
$self
->{SESSION_ID} =
$_
[SESSION]->ID();
$kernel
->refcount_increment(
$self
->{SESSION_ID}, __PACKAGE__ );
$self
->{ircd_filter} = POE::Filter::Stackable->new(
Filters
=> [
POE::Filter::Line->new(),
POE::Filter::IRCD->new(),
]);
$self
->{listener} = POE::Wheel::SocketFactory->new(
BindAddress
=>
'localhost'
,
BindPort
=>
$self
->{bindport} || 0,
SuccessEvent
=>
'_listener_accept'
,
FailureEvent
=>
'_listener_failed'
,
Reuse
=>
'yes'
,
);
if
(
$self
->{listener}) {
$self
->{irc}->send_event(
'irc_console_service'
=>
$self
->{listener}->
getsockname
() );
}
else
{
$self
->{irc}->plugin_del(
$self
);
}
return
;
}
sub
_listener_accept {
my
(
$kernel
,
$self
,
$socket
,
$peeradr
,
$peerport
)
=
@_
[KERNEL, OBJECT, ARG0 .. ARG2];
my
$wheel
= POE::Wheel::ReadWrite->new(
Handle
=>
$socket
,
InputFilter
=>
$self
->{ircd_filter},
OutputFilter
=> POE::Filter::Line->new(),
InputEvent
=>
'_client_input'
,
ErrorEvent
=>
'_client_error'
,
FlushedEvent
=>
'_client_flush'
,
);
if
( !
defined
$wheel
) {
$self
->{irc}->send_event(
'irc_console_rw_fail'
=>
$peeradr
=>
$peerport
);
return
;
}
my
$wheel_id
=
$wheel
->ID();
$self
->{wheels}->{
$wheel_id
} =
$wheel
;
$self
->{authed}->{
$wheel_id
} = 0;
$self
->{
exit
}->{
$wheel_id
} = 0;
$self
->{irc}->send_event(
'irc_console_connect'
=>
$peeradr
=>
$peerport
=>
$wheel_id
);
return
;
}
sub
_listener_failed {
delete
$_
[OBJECT]->{listener};
return
;
}
sub
_client_input {
my
(
$kernel
,
$self
,
$input
,
$wheel_id
) =
@_
[KERNEL, OBJECT, ARG0, ARG1];
if
(
$self
->{authed}->{
$wheel_id
} &&
lc
(
$input
->{command} ) eq
'exit'
) {
$self
->{
exit
}->{
$wheel_id
} = 1;
if
(
defined
$self
->{wheels}->{
$wheel_id
}) {
$self
->{wheels}->{
$wheel_id
}->put(
"ERROR * quiting *"
);
}
return
;
}
if
(
$self
->{authed}->{
$wheel_id
} ) {
$self
->{irc}->yield(
lc
(
$input
->{command} ) => @{
$input
->{params} } );
return
;
}
if
(
lc
(
$input
->{command} ) eq
'pass'
&&
$input
->{params}->[0] eq
$self
->{password} ) {
$self
->{authed}->{
$wheel_id
} = 1;
$self
->{wheels}->{
$wheel_id
}->put(
'NOTICE * Password accepted *'
);
$self
->{irc}->send_event(
'irc_console_authed'
=>
$wheel_id
);
return
;
}
$self
->{wheels}->{
$wheel_id
}->put(
'NOTICE * Password required * enter PASS <password> *'
);
return
;
}
sub
_client_flush {
my
(
$self
,
$wheel_id
) =
@_
[OBJECT, ARG0];
return
if
!
$self
->{
exit
}->{
$wheel_id
};
delete
$self
->{wheels}->{
$wheel_id
};
return
;
}
sub
_client_error {
my
(
$self
,
$wheel_id
) =
@_
[OBJECT, ARG3];
delete
$self
->{wheels}->{
$wheel_id
};
delete
$self
->{authed}->{
$wheel_id
};
$self
->{irc}->send_event(
'irc_console_close'
=>
$wheel_id
);
return
;
}
sub
_shutdown {
my
(
$kernel
,
$self
) =
@_
[KERNEL, OBJECT];
delete
$self
->{listener};
delete
$self
->{wheels};
delete
$self
->{authed};
return
;
}
sub
getsockname
{
my
$self
=
shift
;
return
if
!
$self
->{listener};
return
$self
->{listener}->
getsockname
();
}
1;