Update of /cvsroot/mahogany/M/src/mail
In directory usw-pr-cvs1:/tmp/cvs-serv22547/src/mail

Modified Files:
        AddressCC.cpp 
Log Message:
better handling for the messages with invalid addresses, also don't use fixed size 
buffers required by c-client any more

Index: AddressCC.cpp
===================================================================
RCS file: /cvsroot/mahogany/M/src/mail/AddressCC.cpp,v
retrieving revision 1.15
retrieving revision 1.16
diff -b -u -2 -r1.15 -r1.16
--- AddressCC.cpp       7 Jan 2002 00:21:13 -0000       1.15
+++ AddressCC.cpp       22 Feb 2002 19:55:41 -0000      1.16
@@ -48,10 +48,10 @@
 // ----------------------------------------------------------------------------
 
-// the max size of the buffer holding the address: this is horribly dangerous
-// as there are *NO* buffer size checks in c-client which means that we just
-// die horribly if the buffer is overflown -- but what to do except
-// complaining to MRC who'd just tell me that he doesn't care about such
-// "minor" problem? #$#$^$%&^%^&!!
-static const size_t MAX_ADDRESS_LEN = 16384;
+// Adr2String parameters
+enum Adr2StringWhich
+{
+   Adr2String_All,
+   Adr2String_FirstOnly
+};
 
 // ----------------------------------------------------------------------------
@@ -60,5 +60,11 @@
 
 // return string containing all addresses or just the first one from this list
-static String Adr2String(ADDRESS *adr, bool all = true);
+static String Adr2String(ADDRESS *adr,
+                         Adr2StringWhich which = Adr2String_All,
+                         bool *error = NULL);
+
+// return the string containing just the email part of the address (this always
+// works with one address only, not the entire list)
+static String Adr2Email(ADDRESS *adr);
 
 // ============================================================================
@@ -89,5 +95,5 @@
 String AddressCC::GetAddress() const
 {
-   return Adr2String(m_adr, false /* just the first one */);
+   return Adr2String(m_adr, Adr2String_FirstOnly);
 }
 
@@ -124,14 +130,5 @@
 String AddressCC::GetEMail() const
 {
-   String email;
-
-   // FIXME: again, c-client doesn't check size of the buffer!
-   char *buf = email.GetWriteBuf(MAX_ADDRESS_LEN);
-   *buf = '\0';
-   rfc822_address(buf, m_adr);
-   email.UngetWriteBuf();
-   email.Shrink();
-
-   return email;
+   return Adr2Email(m_adr);
 }
 
@@ -179,14 +176,4 @@
    while ( adr )
    {
-      // c-client generates dummy addresses when it can't parse the original
-      // address, filter them out
-      if ( adr->error ||
-            (adr->mailbox && !strcmp(adr->mailbox, "INVALID_ADDRESS")) ||
-            (adr->host && !strcmp(adr->host, ERRHOST)) )
-      {
-         DBGMESSAGE(("Skipping bad address '%s'.", Adr2String(adr).c_str()));
-      }
-      else // good address, store
-      {
          // c-client mungles unqualified addresses, undo it
          if ( adr->host && !strcmp(adr->host, BADHOST) )
@@ -213,5 +200,4 @@
 
          addrCur = addr;
-      }
 
       adr = adr->next;
@@ -317,5 +303,8 @@
    }
 
-   return new AddressListCC(adr);
+   AddressListCC *addrList = new AddressListCC(adr);
+   addrList->m_addressHeader = address;
+
+   return addrList;
 }
 
@@ -345,5 +334,13 @@
    if ( m_addrCC )
    {
-      address = Adr2String(m_addrCC->m_adr);
+      bool error;
+      address = Adr2String(m_addrCC->m_adr, Adr2String_All, &error);
+
+      // when an error occurs, prefer to show the original address as is, if we
+      // have it - this gives max info to the user
+      if ( error && !m_addressHeader.empty() )
+      {
+         address = m_addressHeader;
+      }
    }
    //else: no valid addresses at all
@@ -394,26 +391,156 @@
 // ============================================================================
 
-static String Adr2String(ADDRESS *adr, bool all)
+// we reimplement rfc822_write_address() and related functions here because the
+// c-client function doesn't respect the buffer size which leads to easily
+// reproducible buffer overflows and MRC refuses to fix it! <sigh>
+
+// wspecials and rspecials string from c-client
+static const char *WORD_SPECIALS = " ()<>@,;:\\\"[]";
+const char *ALL_SPECIALS =  "()<>@,;:\\\"[].";
+
+// this one is the replacement for rfc822_cat()
+static String Rfc822Quote(const char *src, const char *specials)
+{
+   String dest;
+
+   // do we have any specials at all?
+   if ( strpbrk(src, specials) )
+   {
+      // need to quote
+      dest = '"';
+
+      while ( *src )
+      {
+         switch ( *src )
+         {
+            case '\\':
+            case '"':
+               // need to quote
+               dest += '\\';
+               break;
+         }
+
+         dest += *src++;
+      }
+
+      // closing quote
+      dest += '"';
+   }
+   else // no specials at all, easy case
+   {
+      dest = src;
+   }
+
+   return dest;
+}
+
+// rfc822_address() replacement
+static String Adr2Email(ADDRESS *adr)
+{
+   String email;
+
+   // do we have email at all?
+   if ( adr && adr->host )
+   {
+      email.reserve(256);
+
+      // deal with the A-D-L
+      if ( adr->adl )
+      {
+         email << adr->adl << ':';
+      }
+
+      // and now the mailbox name: we quote all characters forbidden in a word
+      email << Rfc822Quote(adr->mailbox, WORD_SPECIALS);
+
+      // passing the NULL host suppresses printing the full address
+      if ( *adr->host != '@' )
+      {
+         email << '@' << adr->host;
+      }
+   }
+
+   return email;
+}
+
+// rfc822_write_address() replacement with some extra functionality
+static String Adr2String(ADDRESS *adr, Adr2StringWhich which, bool *error)
 {
    String address;
-   CHECK( adr, address, "invalid address" );
+   address.reserve(1024);
+
+   if ( error )
+   {
+      // not yet
+      *error = false;
+   }
 
-   // if we need only one address, prevent rfc822_write_address() from
-   // traversing the entire address list by temporarily setting the next
-   // pointer to NULL
-   ADDRESS *adrNextOld = all ? NULL : adr->next;
-   if ( adrNextOld )
-      adr->next = NULL;
-
-   // FIXME: there is no way to get the address length from c-client, how to
-   //        prevent it from overwriting our buffer??
-   char *buf = address.GetWriteBuf(MAX_ADDRESS_LEN);
-   *buf = '\0';
-   rfc822_write_address(buf, adr);
-   address.UngetWriteBuf();
-   address.Shrink();
+   bool first = true;
+   for ( size_t groupDepth = 0; adr; adr = adr->next )
+   {
+      // is this a valid address?
+      if ( adr->host && !strcmp(adr->host, ERRHOST) )
+      {
+         // tell the caller that we had a problem
+         if ( error )
+            *error = true;
+
+         // stop at the first invalid address, there is nothing (but garbage in
+         // the worst case) following it anyhow
+         break;
+      }
 
-   if ( adrNextOld )
-      adr->next = adrNextOld;
+      if ( first )
+      {
+         // no more during the next iteration
+         first = false;
+      }
+      else // not the first address
+      {
+         // do we need the subsequent ones?
+         if ( which != Adr2String_All )
+         {
+            // no
+            break;
+         }
+
+         if ( !groupDepth )
+         {
+            // separate from the previous one
+            address << ", ";
+         }
+      }
+
+      // ordinary address?
+      if ( adr->host )
+      {
+         // simple case?
+         if ( !(adr->personal || adr->adl) )
+         {
+            address << Adr2Email(adr);
+         }
+         else // no, must use phrase <route-addr> form
+         {
+            if ( adr->personal )
+               address << Rfc822Quote(adr->personal, ALL_SPECIALS);
+
+            address << " <" << Adr2Email(adr) << '>';
+         }
+      }
+      else if ( adr->mailbox ) // start of group?
+      {
+         // yes, write group name
+         address << Rfc822Quote(adr->mailbox, ALL_SPECIALS) << ": ";
+
+         // in a group
+         groupDepth++;
+      }
+      else if ( groupDepth ) // must be end of group (but be paranoid)
+      {
+         address += ';';
+
+         groupDepth--;
+      }
+   }
 
    return address;


_______________________________________________
Mahogany-cvsupdates mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/mahogany-cvsupdates

Reply via email to