Index: message.c
===================================================================
--- message.c	(revision 82984251647b3b99416bd132fa0c86750546b1e0)
+++ message.c	(revision dd16bddb5693f2d50fa1ad5379e256aac2fd48d9)
@@ -341,4 +341,9 @@
   m->type=OWL_MESSAGE_TYPE_AIM;
 }
+
+void owl_message_set_type(owl_message *m, int type)
+{
+  m->type=type;
+}
 						
 int owl_message_is_type_admin(owl_message *m)
@@ -396,4 +401,9 @@
 {
   m->direction=OWL_MESSAGE_DIRECTION_NONE;
+}
+
+void owl_message_set_direction(owl_message *m, int direction)
+{
+  m->direction=direction;
 }
 
@@ -631,4 +641,26 @@
 }
 
+int owl_message_parse_type(char *type) {
+  if(!strcmp(type, "admin")) {
+    return OWL_MESSAGE_TYPE_ADMIN;
+  } else if(!strcmp(type, "zephyr")) {
+    return OWL_MESSAGE_TYPE_ZEPHYR;
+  } if(!strcmp(type, "aim")) {
+    return OWL_MESSAGE_TYPE_AIM;
+  } else if(!strcmp(type, "jabber")) {
+    return OWL_MESSAGE_TYPE_JABBER;
+  } else if(!strcmp(type, "icq")) {
+    return OWL_MESSAGE_TYPE_ICQ;
+  } else if(!strcmp(type, "yahoo")) {
+    return OWL_MESSAGE_TYPE_YAHOO;
+  } else if(!strcmp(type, "msn")) {
+    return OWL_MESSAGE_TYPE_MSN;
+  } else if(!strcmp(type, "loopback")) {
+    return OWL_MESSAGE_TYPE_LOOPBACK;
+  } else {
+    return OWL_MESSAGE_TYPE_GENERIC;
+  }
+}
+
 char *owl_message_get_direction(owl_message *m) {
   switch (m->direction) {
@@ -644,4 +676,15 @@
 }
 
+int owl_message_parse_direction(char *d) {
+  if(!strcmp(d, "in")) {
+    return OWL_MESSAGE_DIRECTION_IN;
+  } else if(!strcmp(d, "out")) {
+    return OWL_MESSAGE_DIRECTION_OUT;
+  } else {
+    return OWL_MESSAGE_DIRECTION_NONE;
+  }
+}
+
+
 char *owl_message_get_login(owl_message *m) {
   if (owl_message_is_login(m)) {
@@ -653,4 +696,5 @@
   }
 }
+
 
 char *owl_message_get_header(owl_message *m) {
Index: perlglue.xs
===================================================================
--- perlglue.xs	(revision 6922eddf979a8bdbf46a21cad138b787a7719f46)
+++ perlglue.xs	(revision dd16bddb5693f2d50fa1ad5379e256aac2fd48d9)
@@ -1,2 +1,3 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 static const char fileIdent[] = "$Id$";
 
@@ -90,5 +91,4 @@
 		cmd.description = description;
 		cmd.validctx = OWL_CTX_ANY;
-
 		cmd.cmd_aliased_to = NULL;
 		cmd.cmd_args_fn = NULL;
@@ -98,4 +98,37 @@
 		cmd.cmd_ctxv_fn = NULL;
 		cmd.cmd_ctxi_fn = NULL;
+		owl_cmddict_add_cmd(owl_global_get_cmddict(&g), &cmd);
 
-		owl_cmddict_add_cmd(owl_global_get_cmddict(&g), &cmd);
+void queue_message(msg)
+	SV *msg
+	PREINIT:
+		char * key;
+		char * val;
+		owl_message *m;
+		HV * hash;
+		HE * ent;
+		I32 count;
+		I32 len;
+	CODE:
+		if(!SvROK(msg) || SvTYPE(SvRV(msg)) != SVt_PVHV) {
+			croak("Usage: owl::queue_message($message)");
+		}
+		
+		hash = (HV*)SvRV(msg);
+		m = owl_malloc(sizeof(owl_message));
+		owl_message_init(m);
+		
+		count = hv_iterinit(hash);
+		while((ent = hv_iternext(hash))) {
+			key = hv_iterkey(ent, &len);
+			val = SvPV_nolen(hv_iterval(hash, ent));
+			if(!strcmp(key, "type")) {
+				owl_message_set_type(m, owl_message_parse_type(val));
+			} else if(!strcmp(key, "direction")) {
+				owl_message_set_direction(m, owl_message_parse_direction(val));
+			} else {
+				owl_message_set_attribute(m, key, val);
+			}
+		}
+
+		owl_global_messagequeue_addmsg(&g, m);
Index: perlwrap.pm
===================================================================
--- perlwrap.pm	(revision 6922eddf979a8bdbf46a21cad138b787a7719f46)
+++ perlwrap.pm	(revision dd16bddb5693f2d50fa1ad5379e256aac2fd48d9)
@@ -62,4 +62,13 @@
 package owl::Message;
 
+sub new {
+    my $class = shift;
+    my %args = (@_);
+    if($class eq __PACKAGE__ && $args{type}) {
+        $class = "owl::Message::" . ucfirst $args{type};
+    }
+    return bless {%args}, $class;
+}
+
 sub type        { return shift->{"type"}; }
 sub direction   { return shift->{"direction"}; }
@@ -84,4 +93,5 @@
 sub is_admin    { return (shift->{"type"} eq "admin"); }
 sub is_generic  { return (shift->{"type"} eq "generic"); }
+sub is_jabber   { return (shift->{"type"} eq "jabber"); }
 
 # These are overridden by appropriate message types
@@ -251,4 +261,11 @@
 #####################################################################
 
+package owl::Message::Jabber;
+
+@ISA = qw( owl::Message );
+
+#####################################################################
+#####################################################################
+
 # switch to package main when we're done
 package main;
