<<< Date Index >>>     <<< Thread Index >>>

Re: [1.5.9 bug] Mutt discards the \ character before a digit in "To:"



* Wed May 11 2005 Vincent Lefevre <vincent@xxxxxxxxxx>
> On 2005-05-10 13:32:47 -0400, Derek Martin wrote:
> > On Tue, May 10, 2005 at 06:20:11PM +0200, Vincent Lefevre wrote:
> > > With Mutt 1.5.9, if I try to send a mail to
> > > 
> > >   "blah\1" <a@xxx>
> > > 
> > > (whether I write this from Mutt or from the editor), Mutt writes:
> > > 
> > >       To: blah1 <a@xxx>
> > > 
> > > in the Compose window.
> > 
> > I'm pretty sure that's expected behavior.
> 
> Why would this be the expected behavior?

rfc822.c has rfc822_dequote_comment().
After experimenting it a little, I found it was a bad thing.
If we need to dequote personal names in headers,
we should do it while displaying it; Never while parsing it.
So I made a patch. (attached)

This patch also removes the quoting routine in
rfc822_write_address_single().
ie, We should quote a name by hand if the name contains
one or more of RFC822Specials[]. But who cares?

Well, someone may complain about it.
But please try these strings as "To:" header on the compose menu:
        Foo \1 <foo@bar>
        Foo \\1 <foo@bar>
        Foo \\\1 <foo@bar>
        "Foo \1 <foo@bar>"
        "Foo \\1 <foo@bar>"
You will be surprised and say, "What an inconsistent behavior!"
So, I suggest this patch.


> > Another question would be why that's important... For most purposes
> > the real name portion of an e-mail address is ignored. Just
> > curious... The only reason I could come up with on my own is
> > filtering, but even then it's not hard to write a regex that matches
> > both "blah\1" and blah1.
> 
> I don't think this is important, but this is a bug anyway, IMHO.
> I also wonder if it doesn't hide a more important bug.

The '\\' char represents a YEN mark with some Japanese fonts.
It must be important, it concerns money. ;)
For example, currently I can't send a message to "A \100-shop owner."
(Derek should know there are such shops in Japan. Those shops
sell various goods for 100 yen.)

-- 
tamo

Index: hdrline.c
===================================================================
RCS file: /home/roessler/cvs/mutt/hdrline.c,v
retrieving revision 3.14
diff -p -u -r3.14 hdrline.c
--- hdrline.c   12 Feb 2005 19:12:40 -0000      3.14
+++ hdrline.c   22 May 2005 11:06:04 -0000
@@ -59,7 +59,11 @@ check_for_mailing_list (ADDRESS *adr, ch
     if (mutt_is_subscribed_list (adr))
     {
       if (pfx && buf && buflen)
-       snprintf (buf, buflen, "%s%s", pfx, mutt_get_name (adr));
+      {
+       char *name = mutt_get_name (adr);
+       snprintf (buf, buflen, "%s%s", pfx, name);
+       FREE (&name);
+      }
       return 1;
     }
   }
@@ -102,6 +106,7 @@ static int first_mailing_list (char *buf
 static void make_from (ENVELOPE *hdr, char *buf, size_t len, int do_lists)
 {
   int me;
+  char *name = NULL;
 
   me = mutt_addr_is_user (hdr->from);
 
@@ -114,13 +119,16 @@ static void make_from (ENVELOPE *hdr, ch
   }
 
   if (me && hdr->to)
-    snprintf (buf, len, "To %s", mutt_get_name (hdr->to));
+    snprintf (buf, len, "To %s", name = mutt_get_name (hdr->to));
   else if (me && hdr->cc)
-    snprintf (buf, len, "Cc %s", mutt_get_name (hdr->cc));
+    snprintf (buf, len, "Cc %s", name = mutt_get_name (hdr->cc));
   else if (hdr->from)
-    strfcpy (buf, mutt_get_name (hdr->from), len);
+    strfcpy (buf, name = mutt_get_name (hdr->from), len);
   else
     *buf = 0;
+
+  if (name)
+    FREE (&name);
 }
 
 static void make_from_addr (ENVELOPE *hdr, char *buf, size_t len, int do_lists)
@@ -492,7 +500,11 @@ hdr_format_str (char *dest,
       break;
 
     case 'n':
-      mutt_format_s (dest, destlen, prefix, mutt_get_name (hdr->env->from));
+      {
+       char *name = mutt_get_name (hdr->env->from);
+       mutt_format_s (dest, destlen, prefix, name);
+       FREE (&name);
+      }
       break;
 
     case 'N':
@@ -587,10 +599,13 @@ hdr_format_str (char *dest,
       if (!check_for_mailing_list (hdr->env->to, "To ", buf2, sizeof (buf2)) &&
          !check_for_mailing_list (hdr->env->cc, "Cc ", buf2, sizeof (buf2)))
       {
+       char *name = NULL;
        if (hdr->env->to)
-         snprintf (buf2, sizeof (buf2), "To %s", mutt_get_name (hdr->env->to));
+         snprintf (buf2, sizeof (buf2), "To %s", name = mutt_get_name 
(hdr->env->to));
        else if (hdr->env->cc)
-         snprintf (buf2, sizeof (buf2), "Cc %s", mutt_get_name (hdr->env->cc));
+         snprintf (buf2, sizeof (buf2), "Cc %s", name = mutt_get_name 
(hdr->env->cc));
+       if (name)
+         FREE (&name);
       }
       mutt_format_s (dest, destlen, prefix, buf2);
       break;
@@ -616,15 +631,22 @@ hdr_format_str (char *dest,
     case 'v':
       if (mutt_addr_is_user (hdr->env->from)) 
       {
+       char *name = NULL;
        if (hdr->env->to)
-         mutt_format_s (buf2, sizeof (buf2), prefix, mutt_get_name 
(hdr->env->to));
+         mutt_format_s (buf2, sizeof (buf2), prefix, name = mutt_get_name 
(hdr->env->to));
        else if (hdr->env->cc)
-         mutt_format_s (buf2, sizeof (buf2), prefix, mutt_get_name 
(hdr->env->cc));
+         mutt_format_s (buf2, sizeof (buf2), prefix, name = mutt_get_name 
(hdr->env->cc));
        else
          *buf2 = 0;
+       if (name)
+         FREE (&name);
       }
       else
-       mutt_format_s (buf2, sizeof (buf2), prefix, mutt_get_name 
(hdr->env->from));
+      {
+       char *name = mutt_get_name (hdr->env->from);
+       mutt_format_s (buf2, sizeof (buf2), prefix, name);
+       FREE (&name);
+      }
       if ((p = strpbrk (buf2, " %@")))
        *p = 0;
       mutt_format_s (dest, destlen, prefix, buf2);
Index: rfc822.c
===================================================================
RCS file: /home/roessler/cvs/mutt/rfc822.c,v
retrieving revision 3.7
diff -p -u -r3.7 rfc822.c
--- rfc822.c    3 Feb 2005 17:01:44 -0000       3.7
+++ rfc822.c    22 May 2005 11:06:05 -0000
@@ -60,28 +60,6 @@ const char *RFC822Errors[] = {
   "bad address spec"
 };
 
-void rfc822_dequote_comment (char *s)
-{
-  char *w = s;
-
-  for (; *s; s++)
-  {
-    if (*s == '\\')
-    {
-      if (!*++s)
-       break; /* error? */
-      *w++ = *s;
-    }
-    else if (*s != '\"')
-    {
-      if (w != s)
-       *w = *s;
-      w++;
-    }
-  }
-  *w = 0;
-}
-
 void rfc822_free_address (ADDRESS **p)
 {
   ADDRESS *t;
@@ -119,6 +97,8 @@ parse_comment (const char *s,
     }
     else if (*s == '\\')
     {
+      if (*commentlen < commentmax)
+       comment[(*commentlen)++] = *s;
       if (!*++s)
        break;
     }
@@ -153,8 +133,8 @@ parse_quote (const char *s, char *token,
       if (!*++s)
        break;
 
-      if (*tokenlen < tokenmax)
-       token[*tokenlen] = *s;
+      if (*tokenlen + 1 < tokenmax)
+       token[++(*tokenlen)] = *s;
     }
     (*tokenlen)++;
     s++;
@@ -451,8 +431,6 @@ ADDRESS *rfc822_parse_adrlist (ADDRESS *
       {
        if (cur->personal)
          FREE (&cur->personal);
-       /* if we get something like "Michael R. Elkins" remove the quotes */
-       rfc822_dequote_comment (phrase);
        cur->personal = safe_strdup (phrase);
       }
       if ((ps = parse_route_addr (s + 1, comment, &commentlen, sizeof 
(comment) - 1, cur)) == NULL)
@@ -531,11 +509,6 @@ rfc822_cat (char *buf, size_t buflen, co
     *pc++ = '"';
     for (; *value && tmplen > 1; value++)
     {
-      if (*value == '\\' || *value == '"')
-      {
-       *pc++ = '\\';
-       tmplen--;
-      }
       *pc++ = *value;
       tmplen--;
     }
@@ -582,40 +555,12 @@ void rfc822_write_address_single (char *
 
   if (addr->personal)
   {
-    if (strpbrk (addr->personal, RFC822Specials))
-    {
-      if (!buflen)
-       goto done;
-      *pbuf++ = '"';
-      buflen--;
-      for (pc = addr->personal; *pc && buflen > 0; pc++)
-      {
-       if (*pc == '"' || *pc == '\\')
-       {
-         if (!buflen)
-           goto done;
-         *pbuf++ = '\\';
-         buflen--;
-       }
-       if (!buflen)
-         goto done;
-       *pbuf++ = *pc;
-       buflen--;
-      }
-      if (!buflen)
-       goto done;
-      *pbuf++ = '"';
-      buflen--;
-    }
-    else
-    {
-      if (!buflen)
-       goto done;
-      strfcpy (pbuf, addr->personal, buflen);
-      len = mutt_strlen (pbuf);
-      pbuf += len;
-      buflen -= len;
-    }
+    if (!buflen)
+      goto done;
+    strfcpy (pbuf, addr->personal, buflen);
+    len = mutt_strlen (pbuf);
+    pbuf += len;
+    buflen -= len;
 
     if (!buflen)
       goto done;
Index: sort.c
===================================================================
RCS file: /home/roessler/cvs/mutt/sort.c,v
retrieving revision 3.7
diff -p -u -r3.7 sort.c
--- sort.c      3 Feb 2005 17:01:44 -0000       3.7
+++ sort.c      22 May 2005 11:06:05 -0000
@@ -90,21 +90,34 @@ int compare_subject (const void *a, cons
   return (SORTCODE (rc));
 }
 
+/* needs freeing */
 const char *mutt_get_name (ADDRESS *a)
 {
   ADDRESS *ali;
+  char *tmp = NULL;
 
   if (a)
   {
     if (option (OPTREVALIAS) && (ali = alias_reverse_lookup (a)) && 
ali->personal)
-      return ali->personal;
+      tmp = safe_strdup (ali->personal);
     else if (a->personal)
-      return a->personal;
+      tmp = safe_strdup (a->personal);
     else if (a->mailbox)
-      return (mutt_addr_for_display (a));
+      tmp = safe_strdup (mutt_addr_for_display (a));
+    if (tmp)
+    {
+      size_t tmplen = mutt_strlen (tmp);
+      if (tmplen > 2 && *tmp == '"' && *(tmp + tmplen - 1) == '"')
+      {
+       char *rv = mutt_substrdup (tmp + 1, tmp + tmplen - 1);
+       FREE (&tmp);
+       return (rv);
+      }
+      return (tmp);
+    }
   }
   /* don't return NULL to avoid segfault when printing/comparing */
-  return ("");
+  return (safe_strdup(""));
 }
 
 int compare_to (const void *a, const void *b)
@@ -117,6 +130,8 @@ int compare_to (const void *a, const voi
   fa = mutt_get_name ((*ppa)->env->to);
   fb = mutt_get_name ((*ppb)->env->to);
   result = mutt_strcasecmp (fa, fb);
+  FREE (&fa);
+  FREE (&fb);
   AUXSORT(result,a,b);
   return (SORTCODE (result));
 }
@@ -131,6 +146,8 @@ int compare_from (const void *a, const v
   fa = mutt_get_name ((*ppa)->env->from);
   fb = mutt_get_name ((*ppb)->env->from);
   result = mutt_strcasecmp (fa, fb);
+  FREE (&fa);
+  FREE (&fb);
   AUXSORT(result,a,b);
   return (SORTCODE (result));
 }