Index: message.c
===================================================================
--- message.c	(revision 7dcef0312dbb22b5bb46c6e0e72c5508ed26c284)
+++ message.c	(revision 8f95fc4df16c054fb3cb7a40d5d1c60da8d18587)
@@ -39,5 +39,5 @@
 
   owl_message_set_hostname(m, "");
-  m->attributes = g_ptr_array_new();
+  g_datalist_init(&m->attributes);
   
   /* save the time */
@@ -54,25 +54,6 @@
 void owl_message_set_attribute(owl_message *m, const char *attrname, const char *attrvalue)
 {
-  int i;
-  owl_pair *p = NULL, *pair = NULL;
-
-  attrname = g_intern_string(attrname);
-
-  /* look for an existing pair with this key, */
-  for (i = 0; i < m->attributes->len; i++) {
-    p = m->attributes->pdata[i];
-    if (owl_pair_get_key(p) == attrname) {
-      g_free(owl_pair_get_value(p));
-      pair = p;
-      break;
-    }
-  }
-
-  if(pair ==  NULL) {
-    pair = g_slice_new(owl_pair);
-    owl_pair_create(pair, attrname, NULL);
-    g_ptr_array_add(m->attributes, pair);
-  }
-  owl_pair_set_value(pair, owl_validate_or_convert(attrvalue));
+  g_datalist_set_data_full(&m->attributes, attrname,
+			   owl_validate_or_convert(attrvalue), g_free);
 }
 
@@ -82,27 +63,5 @@
 const char *owl_message_get_attribute_value(const owl_message *m, const char *attrname)
 {
-  int i;
-  owl_pair *p;
-  GQuark quark;
-
-  quark = g_quark_try_string(attrname);
-  if (quark == 0)
-    /* don't bother inserting into string table */
-    return NULL;
-  attrname = g_quark_to_string(quark);
-
-  for (i = 0; i < m->attributes->len; i++) {
-    p = m->attributes->pdata[i];
-    if (owl_pair_get_key(p) == attrname) {
-      return(owl_pair_get_value(p));
-    }
-  }
-
-  /*
-  owl_function_debugmsg("No attribute %s found for message %i",
-			attrname,
-			owl_message_get_id(m));
-  */
-  return(NULL);
+  return g_datalist_get_data(&((owl_message *)m)->attributes, attrname);
 }
 
@@ -111,30 +70,19 @@
  * function to indent fmtext.
  */
-void owl_message_attributes_tofmtext(const owl_message *m, owl_fmtext *fm) {
-  int i;
-  owl_pair *p;
+static void owl_message_attribute_tofmtext(GQuark key_id, gpointer data, gpointer fm)
+{
   char *buff, *tmpbuff;
 
+  tmpbuff = owl_text_indent(data, 19, false);
+  buff = g_strdup_printf("  %-15.15s: %s\n", g_quark_to_string(key_id), tmpbuff);
+  g_free(tmpbuff);
+  owl_fmtext_append_normal(fm, buff);
+  g_free(buff);
+}
+
+void owl_message_attributes_tofmtext(const owl_message *m, owl_fmtext *fm)
+{
   owl_fmtext_init_null(fm);
-
-  for (i = 0; i < m->attributes->len; i++) {
-    p = m->attributes->pdata[i];
-
-    buff = g_strdup(owl_pair_get_value(p));
-    if (buff) {
-      tmpbuff = owl_text_indent(buff, 19, false);
-      g_free(buff);
-      buff = g_strdup_printf("  %-15.15s: %s\n", owl_pair_get_key(p), tmpbuff);
-      g_free(tmpbuff);
-    }
-
-    if(buff == NULL) {
-      buff = g_strdup_printf("  %-15.15s: %s\n", owl_pair_get_key(p), "<error>");
-      if(buff == NULL)
-        buff=g_strdup("   <error>\n");
-    }
-    owl_fmtext_append_normal(fm, buff);
-    g_free(buff);
-  }
+  g_datalist_foreach(&((owl_message *)m)->attributes, owl_message_attribute_tofmtext, fm);
 }
 
@@ -1006,6 +954,4 @@
 void owl_message_cleanup(owl_message *m)
 {
-  int i;
-  owl_pair *p;
 #ifdef HAVE_LIBZEPHYR    
   if (m->has_notice) {
@@ -1016,11 +962,5 @@
 
   /* free all the attributes */
-  for (i = 0; i < m->attributes->len; i++) {
-    p = m->attributes->pdata[i];
-    g_free(owl_pair_get_value(p));
-    g_slice_free(owl_pair, p);
-  }
-
-  g_ptr_array_free(m->attributes, true);
+  g_datalist_clear(&m->attributes);
  
   owl_message_invalidate_format(m);
Index: owl.h
===================================================================
--- owl.h	(revision ca1fb26a9a22aea6ecd68b0150859ef065c6afc5)
+++ owl.h	(revision 8f95fc4df16c054fb3cb7a40d5d1c60da8d18587)
@@ -356,5 +356,5 @@
   int delete;
   const char *hostname;
-  GPtrArray *attributes;          /* this is a list of pairs */
+  GData *attributes;
   char *timestr;
   time_t time;
Index: perlconfig.c
===================================================================
--- perlconfig.c	(revision 7dcef0312dbb22b5bb46c6e0e72c5508ed26c284)
+++ perlconfig.c	(revision 8f95fc4df16c054fb3cb7a40d5d1c60da8d18587)
@@ -69,4 +69,10 @@
 }
 
+static void owl_perlconfig_store_attribute(GQuark key_id, gpointer data, gpointer h)
+{
+  (void)hv_store(h, g_quark_to_string(key_id), strlen(data),
+                 owl_new_sv(data), 0);
+}
+
 CALLER_OWN SV *owl_perlconfig_message2hashref(const owl_message *m)
 {
@@ -76,6 +82,4 @@
   char *ptr, *utype, *blessas;
   const char *f;
-  int i;
-  const owl_pair *pair;
   const owl_filter *wrap;
 
@@ -112,9 +116,5 @@
   }
 
-  for (i = 0; i < m->attributes->len; i++) {
-    pair = m->attributes->pdata[i];
-    (void)hv_store(h, owl_pair_get_key(pair), strlen(owl_pair_get_key(pair)),
-                   owl_new_sv(owl_pair_get_value(pair)),0);
-  }
+  g_datalist_foreach(&((owl_message *)m)->attributes, owl_perlconfig_store_attribute, h);
   
   MSG2H(h, type);
