Index: functions.c
===================================================================
--- functions.c	(revision 2cfc6d7937fafd2aa67f247fa4de3ef41aba1783)
+++ functions.c	(revision 2cfc6d7937fafd2aa67f247fa4de3ef41aba1783)
@@ -2501,4 +2501,32 @@
 }
 
+static char *owl_function_smartfilter_cc(const owl_message *m) {
+  const char *ccs;
+  char *filtname;
+  char *text;
+  owl_filter *f;
+
+  ccs = owl_message_get_attribute_value(m, "zephyr_ccs");
+
+  filtname = owl_sprintf("conversation-%s", ccs);
+  owl_text_tr(filtname, ' ', '-');
+
+  if (owl_global_get_filter(&g, filtname)) {
+    return filtname;
+  }
+
+  text = owl_sprintf("type ^zephyr$ and filter personal and "
+                     "zephyr_ccs ^%s%s%s$",
+                     owl_getquoting(ccs), ccs, owl_getquoting(ccs));
+
+  f = owl_filter_new_fromstring(filtname, text);
+
+  owl_global_add_filter(&g, f);
+
+  owl_free(text);
+
+  return filtname;
+}
+
 /* Create a filter based on the current message.  Returns the name of
  * a filter or null.  The caller must free this name.
@@ -2554,4 +2582,8 @@
   if (owl_message_is_type_zephyr(m)) {
     if (owl_message_is_personal(m) || owl_message_is_loginout(m)) {
+      if (owl_message_get_attribute_value(m, "zephyr_ccs") != NULL) {
+        return owl_function_smartfilter_cc(m);
+      }
+
       if (owl_message_is_direction_in(m)) {
         zperson=short_zuser(owl_message_get_sender(m));
Index: logging.c
===================================================================
--- logging.c	(revision 91634ec817b2d3dfda0c429002c8450e4f2404d5)
+++ logging.c	(revision 839697d886ff0c8987d4f6233e92a81a5157faed)
@@ -128,4 +128,5 @@
   char filename[MAXPATHLEN], *logpath;
   char *to, *temp;
+  GList *cc;
 
   /* expand ~ in path names */
@@ -135,15 +136,14 @@
   if (owl_message_is_type_zephyr(m)) {
     /* If this has CC's, do all but the "recipient" which we'll do below */
-    to = owl_message_get_cc_without_recipient(m);
-    if (to != NULL) {
-      temp = strtok(to, " ");
-      while (temp != NULL) {
-          temp = short_zuser(temp);
-          snprintf(filename, MAXPATHLEN, "%s/%s", logpath, temp);
-          owl_log_append(m, filename);
-          temp = strtok(NULL, " ");
-      }
-      owl_free(to);
-    }
+    cc = owl_message_get_cc_without_recipient(m);
+    while (cc != NULL) {
+      temp = short_zuser(cc->data);
+      snprintf(filename, MAXPATHLEN, "%s/%s", logpath, temp);
+      owl_log_append(m, filename);
+
+      owl_free(cc->data);
+      cc = g_list_delete_link(cc, cc);
+    }
+
     to = short_zuser(owl_message_get_recipient(m));
   } else if (owl_message_is_type_jabber(m)) {
@@ -325,17 +325,16 @@
      * the sender, as well.
      */
-    char *cc, *temp;
+    char *temp;
+    GList *cc;
     cc = owl_message_get_cc_without_recipient(m);
-    if (cc != NULL) {
-      temp = strtok(cc, " ");
-      while (temp != NULL) {
-        temp = short_zuser(temp);
-        if (strcasecmp(temp, frombuff) != 0) {
-          snprintf(filename, MAXPATHLEN, "%s/%s", logpath, temp);
-          owl_log_append(m, filename);
-        }
-        temp = strtok(NULL, " ");
+    while (cc != NULL) {
+      temp = short_zuser(cc->data);
+      if (strcasecmp(temp, frombuff) != 0) {
+        snprintf(filename, MAXPATHLEN, "%s/%s", logpath, temp);
+        owl_log_append(m, filename);
       }
-      owl_free(cc);
+
+      owl_free(cc->data);
+      cc = g_list_delete_link(cc, cc);
     }
   }
Index: message.c
===================================================================
--- message.c	(revision c314f397830b8cfa20a9540a606bad42845e7d9f)
+++ message.c	(revision c314f397830b8cfa20a9540a606bad42845e7d9f)
@@ -593,8 +593,9 @@
 
 /* caller must free return value */
-char *owl_message_get_cc_without_recipient(const owl_message *m)
-{
-  char *cc, *out, *end, *shortuser, *recip;
+GList *owl_message_get_cc_without_recipient(const owl_message *m)
+{
+  char *cc, *shortuser, *recip;
   const char *user;
+  GList *out = NULL;
 
   cc = owl_message_get_cc(m);
@@ -603,6 +604,4 @@
 
   recip = short_zuser(owl_message_get_recipient(m));
-  out = owl_malloc(strlen(cc) + 2);
-  end = out;
 
   user = strtok(cc, " ");
@@ -610,20 +609,12 @@
     shortuser = short_zuser(user);
     if (strcasecmp(shortuser, recip) != 0) {
-      strcpy(end, user);
-      end[strlen(user)] = ' ';
-      end += strlen(user) + 1;
+      out = g_list_prepend(out, owl_strdup(user));
     }
     owl_free(shortuser);
     user = strtok(NULL, " ");
   }
-  end[0] = '\0';
 
   owl_free(recip);
   owl_free(cc);
-
-  if (strlen(out) == 0) {
-    owl_free(out);
-    out = NULL;
-  }
 
   return(out);
@@ -741,4 +732,39 @@
   owl_message_set_recipient(m, "looprecip");
   owl_message_set_isprivate(m);
+}
+
+void owl_message_save_ccs(owl_message *m) {
+  GList *cc;
+  char *tmp;
+
+  cc = owl_message_get_cc_without_recipient(m);
+
+  if (cc != NULL) {
+    GString *recips = g_string_new("");
+    cc = g_list_prepend(cc, short_zuser(owl_message_get_sender(m)));
+    cc = g_list_prepend(cc, short_zuser(owl_message_get_recipient(m)));
+    cc = g_list_sort(cc, (GCompareFunc)strcasecmp);
+
+    while(cc != NULL) {
+      /* Collapse any identical entries */
+      while (cc->next && strcasecmp(cc->data, cc->next->data) == 0) {
+        owl_free(cc->data);
+        cc = g_list_delete_link(cc, cc);
+      }
+
+      tmp = short_zuser(cc->data);
+      g_string_append(recips, tmp);
+
+      owl_free(tmp);
+      owl_free(cc->data);
+      cc = g_list_delete_link(cc, cc);
+
+      if (cc)
+        g_string_append_c(recips, ' ');
+    }
+
+    owl_message_set_attribute(m, "zephyr_ccs", recips->str);
+    g_string_free(recips, true);
+  }
 }
 
@@ -878,4 +904,6 @@
     }
   }
+
+  owl_message_save_ccs(m);
 }
 #else
@@ -972,4 +1000,6 @@
     owl_message_set_isprivate(m);
   }
+
+  owl_message_save_ccs(m);
 }
 
