Index: ChangeLog
===================================================================
--- ChangeLog	(revision e1735071f01cf66130ed9f11875bfadf289315ba)
+++ ChangeLog	(revision e50cd5686952dc31173cfd67f7ebf1d6893945eb)
@@ -54,4 +54,12 @@
 		 sane on admin messages.
 	Added opera to the allowed options to the webbrowser variable.
+	Fixed some buffer overruns in the "reply" command.
+	When repying to "all" on a message that begins with "CC:" (eg, sent 
+	         with "zwrite -C", the reply line will be constructed
+		 from the sender and the usernames on the CC: line
+		 of the message being replied to.
+	There is no such thing as C-R, so left C-r as it is but added:
+	         M-r --- edit reply to all
+	         M-R --- edit reply to sender
 	
 1.2.1-pre-1
Index: functions.c
===================================================================
--- functions.c	(revision ae9e6be1895f1cd07dd578471f94909f444b2a6e)
+++ functions.c	(revision e50cd5686952dc31173cfd67f7ebf1d6893945eb)
@@ -1355,5 +1355,5 @@
    * if enter = 1 then don't wait for editing
    */
-  char buff[1024];
+  char *buff, *oldbuff;
   owl_message *m;
   owl_filter *f;
@@ -1362,5 +1362,5 @@
     owl_function_makemsg("No message selected");
   } else {
-    char *class, *inst, *to;
+    char *class, *inst, *to, *cc=NULL;
     
     m=owl_view_get_element(owl_global_get_current_view(&g), owl_global_get_curmsg(&g));
@@ -1395,4 +1395,5 @@
 	inst=owl_message_get_instance(m);
 	to=owl_message_get_recipient(m);
+	cc=owl_message_get_cc(m);
 	if (!strcmp(to, "") || !strcmp(to, "*")) {
 	  to="";
@@ -1405,17 +1406,29 @@
       
       /* create the command line */
-      strcpy(buff, "zwrite");
+      buff = owl_strdup("zwrite");
       if (strcasecmp(class, "message")) {
-	sprintf(buff, "%s -c %s%s%s", buff, owl_getquoting(class), class, owl_getquoting(class));
+	buff = owl_sprintf("%s -c %s%s%s", oldbuff=buff, owl_getquoting(class), class, owl_getquoting(class));
+	owl_free(oldbuff);
       }
       if (strcasecmp(inst, "personal")) {
-	sprintf(buff, "%s -i %s%s%s", buff, owl_getquoting(inst), inst, owl_getquoting(inst));
+	buff = owl_sprintf("%s -i %s%s%s", oldbuff=buff, owl_getquoting(inst), inst, owl_getquoting(inst));
+	owl_free(oldbuff);
       }
       if (*to != '\0') {
-	char *tmp;
+	char *tmp, *oldtmp;
 	tmp=pretty_sender(to);
-	sprintf(buff, "%s %s", buff, tmp);
+	if (cc) {
+	  tmp = owl_util_uniq(oldtmp=tmp, cc, "-");
+	  owl_free(oldtmp);
+	  buff = owl_sprintf("%s -C %s", oldbuff=buff, tmp);
+	  owl_free(oldbuff);
+	} else {
+	  tmp=pretty_sender(to);
+	  buff = owl_sprintf("%s %s", oldbuff=buff, tmp);
+	  owl_free(oldbuff);
+	}
 	owl_free(tmp);
       }
+      if (cc) owl_free(cc);
 
       if (enter) {
@@ -1427,4 +1440,5 @@
 	owl_function_start_command(buff);
       }
+      owl_free(buff);
     }
   }
Index: keys.c
===================================================================
--- keys.c	(revision 10b866d633f70e1c8778b601ad1cc1b6596e8563)
+++ keys.c	(revision e50cd5686952dc31173cfd67f7ebf1d6893945eb)
@@ -244,5 +244,6 @@
   BIND_CMD("R",   "reply sender",     "reply to sender of the current message");
   BIND_CMD("C-r", "reply -e",         "reply to the current message, but allow editing of recipient");
-  BIND_CMD("C-R", "reply -e sender",  "reply to sender of the current message, but allow editing of recipient");
+  BIND_CMD("M-r", "reply -e",         "reply to the current message, but allow editing of recipient");
+  BIND_CMD("M-R", "reply -e sender",  "reply to sender of the current message, but allow editing of recipient");
 		  
   BIND_CMD("w",   "openurl",          "open a URL using a webbrowser");
Index: message.c
===================================================================
--- message.c	(revision 1aee7d914de75510e7cf09c452bad63b2dad2166)
+++ message.c	(revision e50cd5686952dc31173cfd67f7ebf1d6893945eb)
@@ -607,4 +607,19 @@
 }
 
+/* caller must free return value. */
+char *owl_message_get_cc(owl_message *m) {
+  char *cur, *out, *end;
+
+  cur = owl_message_get_body(m);
+  while (*cur && *cur==' ') cur++;
+  if (strncasecmp(cur, "cc:", 2)) return(NULL);
+  cur+=3;
+  while (*cur && *cur==' ') cur++;
+  out = owl_strdup(cur);
+  end = strchr(out, '\n');
+  if (end) end[0] = '\0';
+  return(out);
+}
+
 int owl_message_get_id(owl_message *m) {
   return(m->id);
Index: util.c
===================================================================
--- util.c	(revision e1c4636a284110b07d889065fbb569709fa701d9)
+++ util.c	(revision e50cd5686952dc31173cfd67f7ebf1d6893945eb)
@@ -298,4 +298,38 @@
   return(ret);
 }
+
+/* Caller must free response. 
+   Takes in strings which are space-separated lists of tokens
+   and returns a single string containing no token more than once.
+   If prohibit is non-null, no token may start with a character
+   in prohibit.
+*/
+char *owl_util_uniq(char *A, char *B, char *prohibit) {
+  char *cat, **tok;
+  int toklen, i, j, first=1;
+  cat = owl_malloc(strlen(A)+strlen(B)+3);
+  strcpy(cat, A);
+  strcat(cat, " ");
+  strcat(cat, B);
+  tok = atokenize(cat, " ", &toklen);
+  strcpy(cat, "");
+  for (i=0; i<toklen; i++) {
+    int dup=0;
+    for (j=0; j<i; j++) {
+      if (!strcmp(tok[i], tok[j])) dup=1;
+    }
+    if (!dup && (!prohibit || !strchr(prohibit, tok[i][0]))) {
+      if (!first) {
+	strcat(cat, " ");
+      }
+      first=0;
+      strcat(cat, tok[i]);
+    }
+  }
+  atokenize_free(tok, toklen);
+  return(cat);
+}
+
+
 
 /* returns if a string is only whitespace */
@@ -482,4 +516,11 @@
 	      !strcmp("meep", skiptokens("foo 'bar quux' meep", 2)));
 
+  FAIL_UNLESS("owl_util_uniq 1", 
+	      !strcmp("foo bar x", owl_util_uniq("foo", "bar x", "-")));
+  FAIL_UNLESS("owl_util_uniq 2", 
+	      !strcmp("foo bar x", owl_util_uniq("foo", "bar -y x", "-")));
+  FAIL_UNLESS("owl_util_uniq 3", 
+	      !strcmp("meep foo bar", owl_util_uniq("meep foo", "bar foo meep", "-")));
+
   if (numfailed) printf("*** WARNING: failures encountered with owl_util\n");
   printf("END testing owl_util (%d failures)\n", numfailed);
