Index: perl/modules/IRC/lib/BarnOwl/Message/IRC.pm
===================================================================
--- perl/modules/IRC/lib/BarnOwl/Message/IRC.pm	(revision b38b0b2afddb97da1a781f31558c159618326b31)
+++ perl/modules/IRC/lib/BarnOwl/Message/IRC.pm	(revision 2c40dc0c6f1c381d54ea774fddc8be468c648535)
@@ -45,5 +45,6 @@
 
 # display
-sub context {shift->{channel};}
+sub context {shift->{network};}
+sub subcontext {shift->{recipient};}
 
 sub long_sender {shift->{from} || ""};
Index: perl/modules/IRC/lib/BarnOwl/Module/IRC.pm
===================================================================
--- perl/modules/IRC/lib/BarnOwl/Module/IRC.pm	(revision b38b0b2afddb97da1a781f31558c159618326b31)
+++ perl/modules/IRC/lib/BarnOwl/Module/IRC.pm	(revision 2c40dc0c6f1c381d54ea774fddc8be468c648535)
@@ -6,9 +6,9 @@
 =head1 NAME
 
-BarnOwl::Module::Jabber
+BarnOwl::Module::IRC
 
 =head1 DESCRIPTION
 
-This module implements Jabber support for barnowl.
+This module implements IRC support for barnowl.
 
 =cut
@@ -22,5 +22,5 @@
 use Getopt::Long;
 
-our $VERSION = 0.01;
+our $VERSION = 0.02;
 
 our $irc;
@@ -30,7 +30,8 @@
 
 sub startup {
-    BarnOwl::new_variable_string(ircnick => {default => $ENV{USER}});
-    BarnOwl::new_variable_string(ircuser => {default => $ENV{USER}});
-    BarnOwl::new_variable_string(ircname => {default => ""});
+    BarnOwl::new_variable_string('irc:nick', {default => $ENV{USER}});
+    BarnOwl::new_variable_string('irc:user', {default => $ENV{USER}});
+    BarnOwl::new_variable_string('irc:name', {default => ""});
+    BarnOwl::new_variable_bool('irc:spew', {default => 0});
     register_commands();
     register_handlers();
@@ -40,5 +41,5 @@
 sub shutdown {
     for my $conn (values %ircnets) {
-        $conn->disconnect;
+        $conn->disconnect();
     }
 }
@@ -63,4 +64,5 @@
     BarnOwl::new_command('irc-disconnect' => \&cmd_disconnect);
     BarnOwl::new_command('irc-msg'     => \&cmd_msg);
+    BarnOwl::new_command('irc-join' => \&cmd_join);
 }
 
@@ -76,7 +78,7 @@
     my $cmd = shift;
 
-    my $nick = BarnOwl::getvar('ircnick');
-    my $username = BarnOwl::getvar('ircuser');
-    my $ircname = BarnOwl::getvar('ircname');
+    my $nick = BarnOwl::getvar('irc:nick');
+    my $username = BarnOwl::getvar('irc:user');
+    my $ircname = BarnOwl::getvar('irc:name');
     my $host;
     my $port;
@@ -90,5 +92,7 @@
             "alias=s"    => \$alias,
             "ssl"        => \$ssl,
-            "password=s" => \$password);
+            "password=s" => \$password,
+            "port=i"     => \$port,
+        );
         $host = shift @ARGV or die("Usage: $cmd HOST\n");
         if(!$alias) {
@@ -126,4 +130,5 @@
     my $conn = get_connection(\@_);
     my $to = shift or die("Usage: $cmd NICK\n");
+    # handle multiple recipients?
     if(@_) {
         process_msg($conn, $to, join(" ", @_));
@@ -148,11 +153,18 @@
         body        => $body,
         sender      => $conn->nick,
-        isprivate   => 'true',
+        is_private($to) ?
+          (isprivate  => 'true') : (),
         replycmd    => "irc-msg $to",
-        replysendercmd => "irc-msg " . $conn->nick
+        replysendercmd => "irc-msg $to"
        );
     BarnOwl::queue_message($msg);
 }
 
+sub cmd_join {
+    my $cmd = shift;
+    my $conn = get_connection(\@_);
+    my $chan = shift or die("Usage: $cmd channel\n");
+    $conn->join($chan);
+}
 
 ################################################################################
@@ -177,7 +189,14 @@
 
 sub get_connection_by_alias {
-    die("No such ircnet: $alias\n") unless exists $ircnets{$key};
+    my $key = shift;
+    die("No such ircnet: $key\n") unless exists $ircnets{$key};
     return $ircnets{$key};
 }
 
+# Determines if the given message recipient is a username, as opposed to
+# a channel that starts with # or &.
+sub is_private {
+    return shift !~ /^[\#\&]/;
+}
+
 1;
Index: perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm
===================================================================
--- perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm	(revision b38b0b2afddb97da1a781f31558c159618326b31)
+++ perl/modules/IRC/lib/BarnOwl/Module/IRC/Connection.pm	(revision 2c40dc0c6f1c381d54ea774fddc8be468c648535)
@@ -15,6 +15,7 @@
 =cut
 
-use base qw(Net::IRC::Connection Class::Accessor);
+use base qw(Net::IRC::Connection Class::Accessor Exporter);
 __PACKAGE__->mk_accessors(qw(alias channels));
+our @EXPORT_OK = qw(&is_private);
 
 use BarnOwl;
@@ -30,7 +31,8 @@
     bless($self, $class);
 
-    $self->add_global_handler(endofmotd => sub { goto &on_connect });
-    $self->add_global_handler(msg => sub { goto &on_msg });
-    $self->add_global_handler(notice => sub { goto &on_msg });
+    $self->add_global_handler(376 => sub { goto &on_connect });
+    $self->add_global_handler(['msg', 'notice', 'public', 'caction'],
+            sub { goto &on_msg });
+    $self->add_global_handler(cping => sub { goto &on_ping });
     $self->add_default_handler(sub { goto &on_event; });
 
@@ -49,5 +51,7 @@
 sub on_msg {
     my ($self, $evt) = @_;
-    my $replycmd = "irc-msg " . $evt->nick;
+    my ($recipient) = $evt->to;
+    my $body = strip_irc_formatting([$evt->args]->[0]);
+    $body = BarnOwl::Style::boldify($evt->nick.' '.$body) if $evt->type eq 'caction';
     my $msg = BarnOwl::Message->new(
         type        => 'IRC',
@@ -55,15 +59,31 @@
         server      => $self->server,
         network     => $self->alias,
-        recipient   => $self->nick,
-        body        => strip_irc_formatting([$evt->args]->[0]),
+        recipient   => $recipient,
+        body        => $body,
         sender      => $evt->nick,
         hostname    => $evt->host,
         from        => $evt->from,
-        notice      => $evt->type eq 'notice' ? 'true' : '',
-        isprivate   => 'true',
-        replycmd    => $replycmd,
-        replysendercmd => $replycmd
+        $evt->type eq 'notice' ?
+          (notice     => 'true') : (),
+        is_private($recipient) ?
+          (isprivate  => 'true') : (),
+        replycmd    => 'irc-msg ' .
+            (is_private($recipient) ? $evt->nick : $recipient),
+        replysendercmd => 'irc-msg ' . $evt->nick,
        );
     BarnOwl::queue_message($msg);
+}
+
+sub on_ping {
+    my ($self, $evt) = @_;
+    $self->ctcp_reply($evt->nick, join (' ', ($evt->args)));
+}
+
+sub on_event {
+    my ($self, $evt) = @_;
+    BarnOwl::admin_message("IRC",
+            "Unhandled IRC event of type " . $evt->type . ":\n"
+            . strip_irc_formatting(join("\n", $evt->args)))
+        if BarnOwl::getvar('irc:spew') eq 'on';
 }
 
@@ -83,4 +103,9 @@
 }
 
+# Determines if the given message recipient is a username, as opposed to
+# a channel that starts with # or &.
+sub is_private {
+    return shift !~ /^[\#\&]/;
+}
 
 1;
