This file is indexed.

/usr/share/perl5/Net/IRC.pm is in libnet-irc-perl 0.75-8.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
#####################################################################
#                                                                   #
#   Net::IRC -- Object-oriented Perl interface to an IRC server     #
#                                                                   #
#   IRC.pm: A nifty little wrapper that makes your life easier.     #
#                                                                   #
#          Copyright (c) 1997 Greg Bacon & Dennis Taylor.           #
#                       All rights reserved.                        #
#                                                                   #
#      This module is free software; you can redistribute or        #
#      modify it under the terms of Perl's Artistic License.        #
#                                                                   #
#####################################################################
# $Id: IRC.pm,v 1.10 2004/04/30 18:02:51 jmuhlich Exp $


package Net::IRC;

BEGIN { require 5.004; }    # needs IO::* and $coderef->(@args) syntax 

use Net::IRC::Connection;
use Net::IRC::EventQueue;
use IO::Select;
use Carp;


# grab the drop-in replacement for time() from Time::HiRes, if it's available
BEGIN {
   Time::HiRes->import('time') if eval "require Time::HiRes";
}


use strict;
use vars qw($VERSION);

$VERSION = "0.75";

sub new {
  my $proto = shift;
  
  my $self = {
    '_conn'             => [],
    '_connhash'         => {},
    '_error'            => IO::Select->new(),
    '_debug'            => 0,
    '_schedulequeue'    => new Net::IRC::EventQueue(),
    '_outputqueue'      => new Net::IRC::EventQueue(),
    '_read'             => IO::Select->new(),
    '_timeout'          => 1,
    '_write'            => IO::Select->new(),
  };
  
  bless $self, $proto;
  
  return $self;
}

sub outputqueue {
  my $self = shift;
  return $self->{_outputqueue};
}

sub schedulequeue {
  my $self = shift;
  return $self->{_schedulequeue};
}

# Front end to addfh(), below. Sets it to read by default.
# Takes at least 1 arg:  an object to add to the select loop.
#           (optional)   a flag string to pass to addfh() (see below)
sub addconn {
  my ($self, $conn) = @_;
  
  $self->addfh( $conn->socket, $conn->can('parse'), ($_[2] || 'r'), $conn);
}

# Adds a filehandle to the select loop. Tasty and flavorful.
# Takes 3 args:  a filehandle or socket to add
#                a coderef (can be undef) to pass the ready filehandle to for
#                  user-specified reading/writing/error handling.
#    (optional)  a string with r/w/e flags, similar to C's fopen() syntax,
#                  except that you can combine flags (i.e., "rw").
#    (optional)  an object that the coderef is a method of
sub addfh {
  my ($self, $fh, $code, $flag, $obj) = @_;
  my ($letter);
  
  die "Not enough arguments to IRC->addfh()" unless defined $code;
  
  if ($flag) {
    foreach $letter (split(//, lc $flag)) {
      if ($letter eq 'r') {
        $self->{_read}->add( $fh );
      } elsif ($letter eq 'w') {
        $self->{_write}->add( $fh );
      } elsif ($letter eq 'e') {
        $self->{_error}->add( $fh );
      }
    }
  } else {
    $self->{_read}->add( $fh );
  }
  
  $self->{_connhash}->{$fh} = [ $code, $obj ];
}

# Sets or returns the debugging flag for this object.
# Takes 1 optional arg: a new boolean value for the flag.
sub debug {
  my $self = shift;
  
  if (@_) {
    $self->{_debug} = $_[0];
  }
  return $self->{_debug};
}

# Goes through one iteration of the main event loop. Useful for integrating
# other event-based systems (Tk, etc.) with Net::IRC.
# Takes no args.
sub do_one_loop {
  my $self = shift;
  my ($ev, $sock, $time, $nexttimer, $timeout);
  my (undef, undef, undef, $caller) = caller(1);

  $time = time();             # no use calling time() all the time.

  if(!$self->outputqueue->is_empty) {
    my $outputevent = undef;
    while(defined($outputevent = $self->outputqueue->head)
          && $outputevent->time <= $time) {
      $outputevent = $self->outputqueue->dequeue();
      $outputevent->content->{coderef}->(@{$outputevent->content->{args}});
    }
    $nexttimer = $self->outputqueue->head->time if !$self->outputqueue->is_empty();
  }

  # we don't want to bother waiting on input or running
  # scheduled events if we're just flushing the output queue
  # so we bail out here
  return if defined($caller) and $caller eq 'Net::IRC::flush_output_queue';

  # Check the queue for scheduled events to run.
  if(!$self->schedulequeue->is_empty) {
    my $scheduledevent = undef;
    while(defined($scheduledevent = $self->schedulequeue->head) && $scheduledevent->time <= $time) {
      $scheduledevent = $self->schedulequeue->dequeue();
      $scheduledevent->content->{coderef}->(@{$scheduledevent->content->{args}});
    }
    if(!$self->schedulequeue->is_empty()
       && $nexttimer
       && $self->schedulequeue->head->time < $nexttimer) {
      $nexttimer = $self->schedulequeue->head->time;
    }
  }

  # Block until input arrives, then hand the filehandle over to the
  # user-supplied coderef. Look! It's a freezer full of government cheese!
  
  if ($nexttimer) {
    $timeout = $nexttimer - $time < $self->{_timeout}
    ? $nexttimer - $time : $self->{_timeout};
  } else {
    $timeout = $self->{_timeout};
  }
  foreach $ev (IO::Select->select($self->{_read},
                                  $self->{_write},
                                  $self->{_error},
                                  $timeout)) {
    foreach $sock (@{$ev}) {
      my $conn = $self->{_connhash}->{$sock};
      $conn or next;
    
      # $conn->[0] is a code reference to a handler sub.
      # $conn->[1] is optionally an object which the
      #    handler sub may be a method of.
      
      $conn->[0]->($conn->[1] ? ($conn->[1], $sock) : $sock);
    }
  }
}

sub flush_output_queue {
  my $self = shift;

  while(!$self->outputqueue->is_empty()) {
    $self->do_one_loop();
  }
}

# Creates and returns a new Connection object.
# Any args here get passed to Connection->connect().
sub newconn {
  my $self = shift;
  my $conn = Net::IRC::Connection->new($self, @_);
  
  return if $conn->error;
  return $conn;
}

# Takes the args passed to it by Connection->schedule()... see it for details.
sub enqueue_scheduled_event {
  my $self = shift;
  my $time = shift;
  my $coderef = shift;
  my @args = @_;

  return $self->schedulequeue->enqueue($time, { coderef => $coderef, args => \@args });
}

# Takes a scheduled event ID to remove from the queue.
# Returns the deleted coderef, if you actually care.
sub dequeue_scheduled_event {
  my ($self, $id) = @_;
  $self->schedulequeue->dequeue($id);
}

# Takes the args passed to it by Connection->schedule()... see it for details.
sub enqueue_output_event {
  my $self = shift;
  my $time = shift;
  my $coderef = shift;
  my @args = @_;

  return $self->outputqueue->enqueue($time, { coderef => $coderef, args => \@args });
}

# Takes a scheduled event ID to remove from the queue.
# Returns the deleted coderef, if you actually care.
sub dequeue_output_event {
  my ($self, $id) = @_;
  $self->outputqueue->dequeue($id);
}

# Front-end for removefh(), below.
# Takes 1 arg:  a Connection (or DCC or whatever) to remove.
sub removeconn {
  my ($self, $conn) = @_;
  
  $self->removefh( $conn->socket );
}

# Given a filehandle, removes it from all select lists. You get the picture.
sub removefh {
  my ($self, $fh) = @_;
  
  $self->{_read}->remove( $fh );
  $self->{_write}->remove( $fh );
  $self->{_error}->remove( $fh );
  delete $self->{_connhash}->{$fh};
}

# Begin the main loop. Wheee. Hope you remembered to set up your handlers
# first... (takes no args, of course)
sub start {
  my $self = shift;
  
  while (1) {
    $self->do_one_loop();
  }
}

# Sets or returns the current timeout, in seconds, for the select loop.
# Takes 1 optional arg:  the new value for the timeout, in seconds.
# Fractional timeout values are just fine, as per the core select().
sub timeout {
  my $self = shift;
  
  if (@_) { $self->{_timeout} = $_[0] }
  return $self->{_timeout};
}

1;


__END__


=head1 NAME

Net::IRC - Perl interface to the Internet Relay Chat protocol

=head1 SYNOPSIS

    use Net::IRC;

    $irc = new Net::IRC;
    $conn = $irc->newconn(Nick    => 'some_nick',
                          Server  => 'some.irc.server.com',
	                  Port    =>  6667,
			  Ircname => 'Some witty comment.');
    $irc->start;

=head1 DESCRIPTION

Welcome to Net::IRC, a work in progress. First intended to be a quick tool
for writing an IRC script in Perl, Net::IRC has grown into a comprehensive
Perl implementation of the IRC protocol (RFC 1459), developed by several
members of the EFnet IRC channel #perl, and maintained in channel #net-irc.

There are 4 component modules which make up Net::IRC:

=over

=item *

Net::IRC

The wrapper for everything else, containing methods to generate
Connection objects (see below) and a connection manager which does an event
loop on all available filehandles. Sockets or files which are readable (or
writable, or whatever you want it to select() for) get passed to user-supplied
handler subroutines in other packages or in user code.

=item *

Net::IRC::Connection

The big time sink on this project. Each Connection instance is a
single connection to an IRC server. The module itself contains methods for
every single IRC command available to users (Net::IRC isn't designed for
writing servers, for obvious reasons), methods to set, retrieve, and call
handler functions which the user can set (more on this later), and too many
cute comments. Hey, what can I say, we were bored.

=item *

Net::IRC::Event

Kind of a struct-like object for storing info about things that the
IRC server tells you (server responses, channel talk, joins and parts, et
cetera). It records who initiated the event, who it affects, the event
type, and any other arguments provided for that event. Incidentally, the
only argument passed to a handler function.

=item *

Net::IRC::DCC

The analogous object to Connection.pm for connecting, sending and
retrieving with the DCC protocol. Instances of DCC.pm are invoked from
C<Connection-E<gt>new_{send,get,chat}> in the same way that
C<IRC-E<gt>newconn> invokes C<Connection-E<gt>new>. This will make more
sense later, we promise.

=back

The central concept that Net::IRC is built around is that of handlers
(or hooks, or callbacks, or whatever the heck you feel like calling them).
We tried to make it a completely event-driven model, a la Tk -- for every
conceivable type of event that your client might see on IRC, you can give
your program a custom subroutine to call. But wait, there's more! There are
3 levels of handler precedence:

=over

=item *

Default handlers

Considering that they're hardwired into Net::IRC, these won't do
much more than the bare minimum needed to keep the client listening on the
server, with an option to print (nicely formatted, of course) what it hears
to whatever filehandles you specify (STDOUT by default). These get called
only when the user hasn't defined any of his own handlers for this event.

=item *

User-definable global handlers

The user can set up his own subroutines to replace the default
actions for I<every> IRC connection managed by your program. These only get
invoked if the user hasn't set up a per-connection handler for the same
event.

=item *

User-definable per-connection handlers

Simple: this tells a single connection what to do if it gets an event of
this type. Supersedes global handlers if any are defined for this event.

=back

And even better, you can choose to call your custom handlers before
or after the default handlers instead of replacing them, if you wish. In
short, it's not perfect, but it's about as good as you can get and still be
documentable, given the sometimes horrendous complexity of the IRC protocol.


=head1 GETTING STARTED

=head2 Initialization

To start a Net::IRC script, you need two things: a Net::IRC object, and a
Net::IRC::Connection object. The Connection object does the dirty work of
connecting to the server; the IRC object handles the input and output for it.
To that end, say something like this:

    use Net::IRC;

    $irc = new Net::IRC;

    $conn = $irc->newconn(Nick    => 'some_nick',
                          Server  => 'some.irc.server.com');

...or something similar. Acceptable parameters to newconn() are:

=over

=item *

Nick

The nickname you'll be known by on IRC, often limited to a maximum of 9
letters. Acceptable characters for a nickname are C<[\w{}[]\`^|-]>. If
you don't specify a nick, it defaults to your username.

=item *

Server

The IRC server to connect to. There are dozens of them across several
widely-used IRC networks, but the oldest and most popular is EFNet (Eris
Free Net), home to #perl. See http://www.irchelp.org/ for lists of
popular servers, or ask a friend.

=item *

Port

The port to connect to this server on. By custom, the default is 6667.

=item *

Username

On systems not running identd, you can set the username for your user@host
to anything you wish. Note that some IRC servers won't allow connections from
clients which don't run identd.

=item *

Ircname

A short (maybe 60 or so chars) piece of text, originally intended to display
your real name, which people often use for pithy quotes and URLs. Defaults to
the contents of your GECOS field.

=item *

Password

If the IRC server you're trying to write a bot for is
password-protected, no problem. Just say "C<Password => 'foo'>" and
you're set.

=item *

SSL

If you wish to connect to an irc server which is using SSL, set this to a
true value.  Ie: "C<SSL => 1>".
    
=back

=head2 Handlers

Once that's over and done with, you need to set up some handlers if you want
your bot to do anything more than sit on a connection and waste resources.
Handlers are references to subroutines which get called when a specific event
occurs. Here's a sample handler sub:

    # What to do when the bot successfully connects.
    sub on_connect {
        my $self = shift;

        print "Joining #IRC.pm...";
        $self->join("#IRC.pm");
        $self->privmsg("#IRC.pm", "Hi there.");
    }

The arguments to a handler function are always the same:

=over

=item $_[0]:

The Connection object that's calling it.

=item $_[1]:

An Event object (see below) that describes what the handler is responding to.

=back

Got it? If not, see the examples in the irctest script that came with this
distribution. Anyhow, once you've defined your handler subroutines, you need
to add them to the list of handlers as either a global handler (affects all
Connection objects) or a local handler (affects only a single Connection). To
do so, say something along these lines:

    $self->add_global_handler('376', \&on_connect);     # global
    $self->add_handler('msg', \&on_msg);                # local

376, incidentally, is the server number for "end of MOTD", which is an event
that the server sends to you after you're connected. See Event.pm for a list
of all possible numeric codes. The 'msg' event gets called whenever someone
else on IRC sends your client a private message. For a big list of possible
events, see the B<Event List> section in the documentation for
Net::IRC::Event.

=head2 Getting Connected

When you've set up all your handlers, the following command will put your
program in an infinite loop, grabbing input from all open connections and
passing it off to the proper handlers:

    $irc->start;

Note that new connections can be added and old ones dropped from within your
handlers even after you call this. Just don't expect any code below the call
to C<start()> to ever get executed.

If you're tying Net::IRC into another event-based module, such as perl/Tk,
there's a nifty C<do_one_loop()> method provided for your convenience. Calling
C<$irc-E<gt>do_one_loop()> runs through the IRC.pm event loop once, hands
all ready filehandles over to the appropriate handler subs, then returns
control to your program.

=head1 METHOD DESCRIPTIONS

This section contains only the methods in IRC.pm itself. Lists of the
methods in Net::IRC::Connection, Net::IRC::Event, or Net::IRC::DCC are in
their respective modules' documentation; just C<perldoc Net::IRC::Connection>
(or Event or DCC or whatever) to read them. Functions take no arguments
unless otherwise specified in their description.

By the way, expect Net::IRC to use AutoLoader sometime in the future, once
it becomes a little more stable.

=over

=item *

addconn()

Adds the specified object's socket to the select loop in C<do_one_loop()>.
This is mostly for the use of Connection and DCC objects (and for pre-0.5
compatibility)... for most (read: all) purposes, you can just use C<addfh()>,
described below.

Takes at least 1 arg:

=over

=item 0.

An object whose socket needs to be added to the select loop

=item 1.

B<Optional:> A string consisting of one or more of the letters r, w, and e.
Passed directly to C<addfh()>... see the description below for more info.

=back

=item *

addfh()

This sub takes a user's socket or filehandle and a sub to handle it with and
merges it into C<do_one_loop()>'s list of select()able filehandles. This makes
integration with other event-based systems (Tk, for instance) a good deal
easier than in previous releases.

Takes at least 2 args:

=over

=item 0.

A socket or filehandle to monitor

=item 1.

A reference to a subroutine. When C<select()> determines that the filehandle
is ready, it passes the filehandle to this (presumably user-supplied) sub,
where you can read from it, write to it, etc. as your script sees fit.

=item 2.

B<Optional:> A string containing any combination of the letters r, w or e
(standing for read, write, and error, respectively) which determines what
conditions you're expecting on that filehandle. For example, this line
select()s $fh (a filehandle, of course) for both reading and writing:

    $irc->addfh( $fh, \&callback, "rw" );

=back

=item *

do_one_loop()

C<select()>s on all open filehandles and passes any ready ones to the
appropriate handler subroutines. Also responsible for executing scheduled
events from C<Net::IRC::Connection-E<gt>schedule()> on time.

=item *

new()

A fairly vanilla constructor which creates and returns a new Net::IRC object.

=item *

newconn()

Creates and returns a new Connection object. All arguments are passed straight
to C<Net::IRC::Connection-E<gt>new()>; examples of common arguments can be
found in the B<Synopsis> or B<Getting Started> sections.

=item *

removeconn()

Removes the specified object's socket from C<do_one_loop()>'s list of
select()able filehandles. This is mostly for the use of Connection and DCC
objects (and for pre-0.5 compatibility)... for most (read: all) purposes,
you can just use C<removefh()>, described below.

Takes 1 arg:

=over

=item 0.

An object whose socket or filehandle needs to be removed from the select loop

=back

=item *

removefh()

This method removes a given filehandle from C<do_one_loop()>'s list of
selectable filehandles.

Takes 1 arg:

=over

=item 0.

A socket or filehandle to remove

=back

=item *

start()

Starts an infinite event loop which repeatedly calls C<do_one_loop()> to
read new events from all open connections and pass them off to any
applicable handlers.

=item *

timeout()

Sets or returns the current C<select()> timeout for the main event loop, in
seconds (fractional amounts allowed). See the documentation for the
C<select()> function for more info.

Takes 1 optional arg:

=over

=item 0.

B<Optional:> A new value for the C<select()> timeout for this IRC object.

=back

=item *

flush_output_queue()

Flushes any waiting messages in the output queue if pacing is enabled. This
method will not return until the output queue is empty.

=over

=back

=head1 AUTHORS

=over

=item *

Conceived and initially developed by Greg Bacon E<lt>gbacon@adtran.comE<gt>
and Dennis Taylor E<lt>dennis@funkplanet.comE<gt>.

=item *

Ideas and large amounts of code donated by Nat "King" Torkington
E<lt>gnat@frii.comE<gt>.

=item *

Currently being hacked on, hacked up, and worked over by the members of the
Net::IRC developers mailing list. For details, see
http://www.execpc.com/~corbeau/irc/list.html .

=back

=head1 URL

Up-to-date source and information about the Net::IRC project can be found at
http://www.sourceforge.net/projects/net-irc/ .

=head1 SEE ALSO

=over

=item *

perl(1).

=item *

RFC 1459: The Internet Relay Chat Protocol

=item *

http://www.irchelp.org/, home of fine IRC resources.

=back

=cut