Fix for bug 134277. Better managment (encoding/decoding) of double-quote in addresses. R=taka, SR=bienvenu

git-svn-id: svn://10.0.0.236/trunk@121546 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
ducarroz%netscape.com
2002-05-15 20:17:48 +00:00
parent 9328ab89eb
commit 091e637cb7
7 changed files with 1268 additions and 1043 deletions

View File

@@ -44,6 +44,7 @@ var gNumberOfCols = 0;
var gDragService = Components.classes["@mozilla.org/widget/dragservice;1"].getService();
gDragService = gDragService.QueryInterface(Components.interfaces.nsIDragService);
gMimeHeaderParser = null;
/**
* global variable inherited from MsgComposeCommands.js
@@ -129,37 +130,59 @@ function Recipients2CompFields(msgCompFields)
var ng_Sep = "";
var follow_Sep = "";
gMimeHeaderParser = Components.classes["@mozilla.org/messenger/headerparser;1"].getService(Components.interfaces.nsIMsgHeaderParser);
var recipientType;
var inputField;
while ((inputField = awGetInputElement(i)))
var fieldValue;
var recipient;
while ((inputField = awGetInputElement(i)))
{
fieldValue = inputField.value;
if (fieldValue == null)
fieldValue = inputField.getAttribute("value");
if (fieldValue != "")
{
var fieldValue = inputField.value;
recipientType = awGetPopupElement(i).selectedItem.getAttribute("value");
recipient = null;
if (fieldValue == null)
fieldValue = inputField.getAttribute("value");
if (fieldValue != "")
switch (recipientType)
{
switch (awGetPopupElement(i).selectedItem.getAttribute("value"))
{
case "addr_to" : addrTo += to_Sep + fieldValue; to_Sep = ","; break;
case "addr_cc" : addrCc += cc_Sep + fieldValue; cc_Sep = ","; break;
case "addr_bcc" : addrBcc += bcc_Sep + fieldValue; bcc_Sep = ","; break;
case "addr_reply" : addrReply += reply_Sep + fieldValue; reply_Sep = ","; break;
case "addr_newsgroups" : addrNg += ng_Sep + fieldValue; ng_Sep = ","; break;
case "addr_followup" : addrFollow += follow_Sep + fieldValue; follow_Sep = ","; break;
case "addr_other" : addrOther += sOther_header + ": " + fieldValue + "\n"; break;
}
case "addr_to" :
case "addr_cc" :
case "addr_bcc" :
case "addr_reply" :
try {
recipient = gMimeHeaderParser.reformatUnquotedAddresses(fieldValue);
} catch (ex) {recipient = fieldValue;}
break;
}
i ++;
}
msgCompFields.to = addrTo;
msgCompFields.cc = addrCc;
msgCompFields.bcc = addrBcc;
msgCompFields.replyTo = addrReply;
msgCompFields.newsgroups = addrNg;
msgCompFields.followupTo = addrFollow;
msgCompFields.otherRandomHeaders = addrOther;
switch (recipientType)
{
case "addr_to" : addrTo += to_Sep + recipient; to_Sep = ","; break;
case "addr_cc" : addrCc += cc_Sep + recipient; cc_Sep = ","; break;
case "addr_bcc" : addrBcc += bcc_Sep + recipient; bcc_Sep = ","; break;
case "addr_reply" : addrReply += reply_Sep + recipient; reply_Sep = ","; break;
case "addr_newsgroups" : addrNg += ng_Sep + fieldValue; ng_Sep = ","; break;
case "addr_followup" : addrFollow += follow_Sep + fieldValue; follow_Sep = ","; break;
case "addr_other" : addrOther += sOther_header + ": " + fieldValue + "\n"; break;
}
}
i ++;
}
msgCompFields.to = addrTo;
msgCompFields.cc = addrCc;
msgCompFields.bcc = addrBcc;
msgCompFields.replyTo = addrReply;
msgCompFields.newsgroups = addrNg;
msgCompFields.followupTo = addrFollow;
msgCompFields.otherRandomHeaders = addrOther;
gMimeHeaderParser = null;
}
else
dump("Message Compose Error: msgCompFields is null (ExtractRecipients)");
@@ -168,6 +191,8 @@ function Recipients2CompFields(msgCompFields)
function CompFields2Recipients(msgCompFields, msgType)
{
if (msgCompFields) {
gMimeHeaderParser = Components.classes["@mozilla.org/messenger/headerparser;1"].getService(Components.interfaces.nsIMsgHeaderParser);
var listbox = document.getElementById('addressingWidget');
var newListBoxNode = listbox.cloneNode(false);
var listBoxColsClone = listbox.firstChild.cloneNode(true);
@@ -209,6 +234,8 @@ function CompFields2Recipients(msgCompFields, msgType)
parent.replaceChild(newListBoxNode, listbox);
awFitDummyRows(2);
setTimeout("awFinishCopyNodes();", 0);
gMimeHeaderParser = null; //Release the mime parser
}
}
@@ -261,8 +288,18 @@ function awSetInputAndPopupFromArray(inputArray, popupValue, parentNode, templat
{
if ( inputArray && popupValue )
{
var recipient;
for ( var index = 0; index < inputArray.count; index++ )
_awSetInputAndPopup(inputArray.StringAt(index), popupValue, parentNode, templateNode);
{
recipient = null;
if (gMimeHeaderParser)
try {
recipient = gMimeHeaderParser.unquotePhraseOrAddrWString(inputArray.StringAt(index), true);
} catch (ex) {};
if (!recipient)
recipient = inputArray.StringAt(index)
_awSetInputAndPopup(recipient, popupValue, parentNode, templateNode);
}
}
}

View File

@@ -52,105 +52,109 @@ interface nsISimpleEnumerator;
[scriptable, uuid(10A88A11-729E-11d2-804A-006008128C4E)]
interface nsIMsgHeaderParser : nsISupports {
void parseHeadersWithArray(in wstring aLine,
[array, size_is(count)] out wstring aEmailAddresses,
[array, size_is(count)] out wstring aNames,
[array, size_is(count)] out wstring aFullNames,
[retval] out unsigned long count);
void parseHeadersWithArray(in wstring aLine,
[array, size_is(count)] out wstring aEmailAddresses,
[array, size_is(count)] out wstring aNames,
[array, size_is(count)] out wstring aFullNames,
[retval] out unsigned long count);
/* Given a string which contains a list of Header addresses, parses it into
their component names and mailboxes.
/* Given a string which contains a list of Header addresses, parses it into
their component names and mailboxes.
The returned value is the number of addresses, or a negative error code;
the names and addresses are returned into the provided pointers as
consecutive null-terminated strings. It is up to the caller to free them.
Note that some of the strings may be zero-length.
The caller may pass nsnull for charset and it will be interpreted as "us-ascii".
Either of the provided pointers may be NULL if the caller is not interested
in those components.
*/
[noscript] void parseHeaderAddresses (in string charset, in string line, out string names,
out string addresses, out PRUint32 numAddresses);
/* Given a string which contains a list of Header addresses, returns a
comma-seperated list of just the `mailbox' portions.
The returned value is the number of addresses, or a negative error code;
the names and addresses are returned into the provided pointers as
consecutive null-terminated strings. It is up to the caller to free them.
Note that some of the strings may be zero-length.
The caller may pass nsnull for charset and it will be interpreted as "us-ascii".
Caller must call PL_strfree on returnValue (which is allocated by the function)
*/
[noscript] void extractHeaderAddressMailboxes (in string charset, in string line, out string mailboxes);
Either of the provided pointers may be NULL if the caller is not interested
in those components.
*/
[noscript] void parseHeaderAddresses (in string charset, in string line, out string names,
out string addresses, out PRUint32 numAddresses);
/* Given a string which contains a list of Header addresses, returns a
comma-seperated list of just the `user name' portions. If any of
the addresses doesn't have a name, then the mailbox is used instead.
/* Given a string which contains a list of Header addresses, returns a
comma-seperated list of just the `mailbox' portions.
The caller may pass nsnull for charset and it will be interpreted as "us-ascii".
Caller must PL_strfree usernames.
*/
[noscript] void extractHeaderAddressNames (in string charset, in string line, out string userNames);
Caller must call PL_strfree on returnValue (which is allocated by the function)
*/
[noscript] void extractHeaderAddressMailboxes (in string charset, in string line, out string mailboxes);
/* Like MSG_ExtractHeaderAddressNames(), but only returns the first name
in the list, if there is more than one.
The caller may pass nsnull for charset and it will be interpreted as "us-ascii".
Caller must call PL_strfree on name
*/
[noscript] void extractHeaderAddressName (in string charset, in string line, out string name);
/* Given a string which contains a list of Header addresses, returns a new
string with the same data, but inserts missing commas, parses and reformats
it, and wraps long lines with newline-tab.
/* Given a string which contains a list of Header addresses, returns a
comma-seperated list of just the `user name' portions. If any of
the addresses doesn't have a name, then the mailbox is used instead.
The caller may pass nsnull for charset and it will be interpreted as "us-ascii".
Caller must call PL_strfree on reformattedAddress
*/
[noscript] void reformatHeaderAddresses (in string charset, in string line,
out string reformattedAddress);
Caller must PL_strfree usernames.
*/
[noscript] void extractHeaderAddressNames (in string charset, in string line, out string userNames);
/* Returns a copy of ADDRS which may have had some addresses removed.
Addresses are removed if they are already in either ADDRS or OTHER_ADDRS.
(If OTHER_ADDRS contain addresses which are not in ADDRS, they are not
added. That argument is for passing in addresses that were already
mentioned in other header fields.)
/* Like MSG_ExtractHeaderAddressNames(), but only returns the first name
in the list, if there is more than one.
The caller may pass nsnull for charset and it will be interpreted as "us-ascii".
Addresses are considered to be the same if they contain the same mailbox
part (case-insensitive.) Real names and other comments are not compared.
Caller must call PL_strfree on name
*/
[noscript] void extractHeaderAddressName (in string charset, in string line, out string name);
removeAliasesToMe allows the address parser to use the preference which
contains regular expressions which also mean 'me' for the purpose of
stripping the user's email address(es) out of addrs
/* Given a string which contains a list of Header addresses, returns a new
string with the same data, but inserts missing commas, parses and reformats
it, and wraps long lines with newline-tab.
The caller may pass nsnull for charset and it will be interpreted as "us-ascii".
Caller must call PL_strfree on newAddress which is the return value.
*/
[noscript] void removeDuplicateAddresses (in string charset, in string addrs, in string other_addrs,
in PRBool removeAliasesToMe, out string newAddress);
Caller must call PL_strfree on reformattedAddress
*/
[noscript] void reformatHeaderAddresses (in string charset, in string line,
out string reformattedAddress);
/* Returns a copy of ADDRS which may have had some addresses removed.
Addresses are removed if they are already in either ADDRS or OTHER_ADDRS.
(If OTHER_ADDRS contain addresses which are not in ADDRS, they are not
added. That argument is for passing in addresses that were already
mentioned in other header fields.)
/* Given an e-mail address and a person's name, cons them together into a
single string of the form "name <address>", doing all the necessary quoting.
A new string is returned, which you must free when you're done with it.
Addresses are considered to be the same if they contain the same mailbox
part (case-insensitive.) Real names and other comments are not compared.
removeAliasesToMe allows the address parser to use the preference which
contains regular expressions which also mean 'me' for the purpose of
stripping the user's email address(es) out of addrs
The caller may pass nsnull for charset and it will be interpreted as "us-ascii".
Caller must call PL_strfree on fullAddress (this is the out parameter)
*/
[noscript] string makeFullAddress (in string charset, in string name, in string addr);
wstring makeFullAddressWString (in wstring name, in wstring addr);
Caller must call PL_strfree on newAddress which is the return value.
*/
[noscript] void removeDuplicateAddresses (in string charset, in string addrs, in string other_addrs,
in PRBool removeAliasesToMe, out string newAddress);
/* MSG_ParseHeaderAddresses returns quoted parsable addresses
This function removes the quoting if you want to show the
names to users. e.g. summary file, address book
*/
[noscript] void unquotePhraseOrAddr (in string charset, in string line, out string lineout);
/* Given an e-mail address and a person's name, cons them together into a
single string of the form "name <address>", doing all the necessary quoting.
A new string is returned, which you must free when you're done with it.
The caller may pass nsnull for charset and it will be interpreted as "us-ascii".
Caller must call PL_strfree on fullAddress (this is the out parameter)
*/
[noscript] string makeFullAddress (in string charset, in string name, in string addr);
wstring makeFullAddressWString (in wstring name, in wstring addr);
/* This function removes the quoting if you want to show the
names to users. e.g. summary file, address book. If preserveIntegrity is set to true,
quote will not be removed in case the name part of the email contains a comma.
*/
[noscript] string unquotePhraseOrAddr (in string line, in boolean preserveIntegrity);
wstring unquotePhraseOrAddrWString (in wstring line, in boolean preserveIntegrity);
/* Given a string, will make it safe to use by adding missing quote and escaping needed quote */
wstring reformatUnquotedAddresses(in wstring line);
};

View File

@@ -637,6 +637,8 @@ RFC822AddressList * construct_addresslist(char *s)
if (!addrspec && displayname) {
*s = '\0';
list->addrspec = nsCRT::strdup(displayname);
/* and don't forget to free the display name in the list, in that case it's bogus */
PR_FREEIF(list->displayname);
}
/* prepare for next address */
addrspec = displayname = nsnull;
@@ -659,7 +661,11 @@ RFC822AddressList * construct_addresslist(char *s)
/* deal with addr-spec only address comes at last */
if (!addrspec && displayname)
{
list->addrspec = nsCRT::strdup(displayname);
/* and don't forget to free the display name in the list, in that case it's bogus */
PR_FREEIF(list->displayname);
}
return listhead;
}

View File

@@ -62,6 +62,7 @@
#include "nsCExternalHandlerService.h"
#include "nsIMIMEService.h"
#include "nsIMIMEInfo.h"
#include "nsIMsgHeaderParser.h"
//
// Header strings...
@@ -698,6 +699,28 @@ MimeGetNamedString(PRInt32 id)
return retString;
}
/* given an address string passed though parameter "address", this one will be converted
and returned through the same parameter. The original string will be destroyed
*/
static void UnquoteMimeAddress(nsIMsgHeaderParser* parser, char** address)
{
if (parser && address && *address && **address)
{
char *result;
if (NS_SUCCEEDED(parser->UnquotePhraseOrAddr(*address, PR_FALSE, &result)))
{
if (result && *result)
{
PR_Free(*address);
*address = result;
return;
}
PR_FREEIF(result);
}
}
return;
}
static void
mime_insert_all_headers(char **body,
@@ -705,6 +728,8 @@ mime_insert_all_headers(char **body,
MSG_ComposeFormat composeFormat,
char *mailcharset)
{
nsCOMPtr<nsIMsgHeaderParser> parser = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID);
PRBool htmlEdit = (composeFormat == nsIMsgCompFormat::HTML);
char *newBody = NULL;
char *html_tag = nsnull;
@@ -800,10 +825,16 @@ mime_insert_all_headers(char **body,
*/
if (nsCRT::strcasecmp(name, "bcc") != 0)
{
if (htmlEdit) mime_fix_up_html_address(&c2);
if (htmlEdit)
mime_fix_up_html_address(&c2);
mime_intl_insert_message_header_1(&newBody, &c2, name, name, mailcharset,
htmlEdit);
if (!nsCRT::strcasecmp(name, "resent-from") || !nsCRT::strcasecmp(name, "from") ||
!nsCRT::strcasecmp(name, "resent-to") || !nsCRT::strcasecmp(name, "to") ||
!nsCRT::strcasecmp(name, "resent-cc") || !nsCRT::strcasecmp(name, "cc") ||
!nsCRT::strcasecmp(name, "reply-to"))
UnquoteMimeAddress(parser, &c2);
mime_intl_insert_message_header_1(&newBody, &c2, name, name, mailcharset, htmlEdit);
}
PR_Free(name);
PR_Free(c2);
@@ -838,27 +869,21 @@ mime_insert_normal_headers(char **body,
MSG_ComposeFormat composeFormat,
char *mailcharset)
{
char *newBody = NULL;
char *newBody = nsnull;
char *subject = MimeHeaders_get(headers, HEADER_SUBJECT, PR_FALSE, PR_FALSE);
char *resent_comments = MimeHeaders_get(headers, HEADER_RESENT_COMMENTS,
PR_FALSE, PR_FALSE);
char *resent_date = MimeHeaders_get(headers, HEADER_RESENT_DATE, PR_FALSE,
PR_TRUE);
char *resent_from = MimeHeaders_get(headers, HEADER_RESENT_FROM, PR_FALSE,
PR_TRUE);
char *resent_comments = MimeHeaders_get(headers, HEADER_RESENT_COMMENTS, PR_FALSE, PR_FALSE);
char *resent_date = MimeHeaders_get(headers, HEADER_RESENT_DATE, PR_FALSE, PR_TRUE);
char *resent_from = MimeHeaders_get(headers, HEADER_RESENT_FROM, PR_FALSE, PR_TRUE);
char *resent_to = MimeHeaders_get(headers, HEADER_RESENT_TO, PR_FALSE, PR_TRUE);
char *resent_cc = MimeHeaders_get(headers, HEADER_RESENT_CC, PR_FALSE, PR_TRUE);
char *date = MimeHeaders_get(headers, HEADER_DATE, PR_FALSE, PR_TRUE);
char *from = MimeHeaders_get(headers, HEADER_FROM, PR_FALSE, PR_TRUE);
char *reply_to = MimeHeaders_get(headers, HEADER_REPLY_TO, PR_FALSE, PR_TRUE);
char *organization = MimeHeaders_get(headers, HEADER_ORGANIZATION,
PR_FALSE, PR_FALSE);
char *organization = MimeHeaders_get(headers, HEADER_ORGANIZATION, PR_FALSE, PR_FALSE);
char *to = MimeHeaders_get(headers, HEADER_TO, PR_FALSE, PR_TRUE);
char *cc = MimeHeaders_get(headers, HEADER_CC, PR_FALSE, PR_TRUE);
char *newsgroups = MimeHeaders_get(headers, HEADER_NEWSGROUPS, PR_FALSE,
PR_TRUE);
char *followup_to = MimeHeaders_get(headers, HEADER_FOLLOWUP_TO, PR_FALSE,
PR_TRUE);
char *newsgroups = MimeHeaders_get(headers, HEADER_NEWSGROUPS, PR_FALSE, PR_TRUE);
char *followup_to = MimeHeaders_get(headers, HEADER_FOLLOWUP_TO, PR_FALSE, PR_TRUE);
char *references = MimeHeaders_get(headers, HEADER_REFERENCES, PR_FALSE, PR_TRUE);
const char *html_tag = nsnull;
if (*body)
@@ -871,6 +896,15 @@ mime_insert_normal_headers(char **body,
resent_from = MimeHeaders_get(headers, HEADER_RESENT_SENDER, PR_FALSE,
PR_TRUE);
nsCOMPtr<nsIMsgHeaderParser> parser = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID);
UnquoteMimeAddress(parser, &resent_from);
UnquoteMimeAddress(parser, &resent_to);
UnquoteMimeAddress(parser, &resent_cc);
UnquoteMimeAddress(parser, &reply_to);
UnquoteMimeAddress(parser, &from);
UnquoteMimeAddress(parser, &to);
UnquoteMimeAddress(parser, &cc);
if (htmlEdit)
{
NS_MsgSACopy(&(newBody), "<HTML> <BR><BR>");
@@ -1047,6 +1081,12 @@ mime_insert_micro_headers(char **body,
if (!date)
date = MimeHeaders_get(headers, HEADER_RESENT_DATE, PR_FALSE, PR_TRUE);
nsCOMPtr<nsIMsgHeaderParser> parser = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID);
UnquoteMimeAddress(parser, &resent_from);
UnquoteMimeAddress(parser, &from);
UnquoteMimeAddress(parser, &to);
UnquoteMimeAddress(parser, &cc);
if (htmlEdit)
{
NS_MsgSACopy(&(newBody), "<HTML> <BR><BR>");

View File

@@ -62,26 +62,6 @@ ParseRFC822Addresses (const char *line,
return 0;
}
/* Given a name or address that might have been quoted
it will take out the escape and double quotes
The caller is responsible for freeing the resulting
string.
*/
int
UnquotePhraseOrAddr (char *line, char** lineout)
{
nsresult res;
nsCOMPtr<nsIMsgHeaderParser> pHeader = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID, &res);
if (NS_SUCCEEDED(res) && pHeader)
{
pHeader->UnquotePhraseOrAddr(NULL, line, lineout);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
/* Given a string which contains a list of RFC822 addresses, returns a
comma-seperated list of just the `mailbox' portions.
*/

View File

@@ -51,17 +51,6 @@ ParseRFC822Addresses (const char *line,
char **names,
char **addresses);
/* Given a name or address that might have been quoted
it will take out the escape and double quotes
The caller is responsible for freeing the resulting
string.
*/
int
UnquotePhraseOrAddr (char *line, char** lineout);
/* Given a string which contains a list of RFC822 addresses, returns a
comma-seperated list of just the `mailbox' portions.
*/
char *
ExtractRFC822AddressMailboxes (const char *line);

File diff suppressed because it is too large Load Diff