Bug 858337 - Implement JS header parsing in JSMime, r=irving, sr=Standard8
This commit is contained in:
Родитель
c6bf838db2
Коммит
1d526917d7
|
@ -238,7 +238,6 @@
|
|||
#include "nsStreamConverter.h"
|
||||
#include "nsMimeObjectClassAccess.h"
|
||||
#include "nsMimeConverter.h"
|
||||
#include "nsMsgHeaderParser.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// mime emitter includes
|
||||
|
@ -672,11 +671,9 @@ NS_DEFINE_NAMED_CID(NS_MSGDB_SERVICE_CID);
|
|||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMimeObjectClassAccess)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMimeConverter)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStreamConverter)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgHeaderParser)
|
||||
|
||||
NS_DEFINE_NAMED_CID(NS_MIME_OBJECT_CLASS_ACCESS_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_MIME_CONVERTER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_MSGHEADERPARSER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_MAILNEWS_MIME_STREAM_CONVERTER_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1004,7 +1001,6 @@ const mozilla::Module::CIDEntry kMailNewsCIDs[] = {
|
|||
// Mime Entries
|
||||
{ &kNS_MIME_OBJECT_CLASS_ACCESS_CID, false, NULL, nsMimeObjectClassAccessConstructor },
|
||||
{ &kNS_MIME_CONVERTER_CID, false, NULL, nsMimeConverterConstructor },
|
||||
{ &kNS_MSGHEADERPARSER_CID, false, NULL, nsMsgHeaderParserConstructor },
|
||||
{ &kNS_MAILNEWS_MIME_STREAM_CONVERTER_CID, false, NULL, nsStreamConverterConstructor },
|
||||
{ &kNS_HTML_MIME_EMITTER_CID, false, NULL, nsMimeHtmlDisplayEmitterConstructor},
|
||||
{ &kNS_XML_MIME_EMITTER_CID, false, NULL, nsMimeXmlEmitterConstructor},
|
||||
|
@ -1229,7 +1225,6 @@ const mozilla::Module::ContractIDEntry kMailNewsContracts[] = {
|
|||
// Mime Entries
|
||||
{ NS_MIME_OBJECT_CONTRACTID, &kNS_MIME_OBJECT_CLASS_ACCESS_CID },
|
||||
{ NS_MIME_CONVERTER_CONTRACTID, &kNS_MIME_CONVERTER_CID },
|
||||
{ NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID, &kNS_MSGHEADERPARSER_CID },
|
||||
{ NS_MAILNEWS_MIME_STREAM_CONVERTER_CONTRACTID, &kNS_MAILNEWS_MIME_STREAM_CONVERTER_CID },
|
||||
{ NS_MAILNEWS_MIME_STREAM_CONVERTER_CONTRACTID1, &kNS_MAILNEWS_MIME_STREAM_CONVERTER_CID },
|
||||
{ NS_MAILNEWS_MIME_STREAM_CONVERTER_CONTRACTID2, &kNS_MAILNEWS_MIME_STREAM_CONVERTER_CID },
|
||||
|
|
|
@ -139,6 +139,6 @@ function run_test() {
|
|||
"test5@foo.invalid,test1@com.invalid,test2@com.invalid,test3@com.invalid");
|
||||
|
||||
// test bug 254519 rfc 2047 encoding
|
||||
checkPopulate("=?iso-8859-1?Q?Sure=F6name=2C_Forename__Dr=2E?= <pb@bieringer.invalid>",
|
||||
"\"Sure\u00F6name, Forename Dr.\" <pb@bieringer.invalid>");
|
||||
checkPopulate("=?iso-8859-1?Q?Sure=F6name=2C_Forename_Dr=2E?= <pb@bieringer.invalid>",
|
||||
"\"Sure\u00F6name, Forename Dr.\" <pb@bieringer.invalid>");
|
||||
};
|
||||
|
|
|
@ -38,17 +38,17 @@ const splitRecipientsTests =
|
|||
{ recipients: "A Group:Ed Jones <c@a.invalid>,joe@where.invalid,John <jdoe@one.invalid>;",
|
||||
emailAddressOnly: false,
|
||||
count: 3,
|
||||
result: [ "A Group:Ed Jones <c@a.invalid>", "joe@where.invalid", "John <jdoe@one.invalid>" ]
|
||||
result: [ "Ed Jones <c@a.invalid>", "joe@where.invalid", "John <jdoe@one.invalid>" ]
|
||||
},
|
||||
{ recipients: 'mygroup:;, empty:;, foo@foo.invalid, othergroup:bar@foo.invalid, bar2@foo.invalid;, y@y.invalid, empty:;',
|
||||
emailAddressOnly: true,
|
||||
count: 7,
|
||||
result: [ "mygroup:;", "empty:;", "foo@foo.invalid", "othergroup:bar@foo.invalid", "bar2@foo.invalid", "y@y.invalid", "empty:;" ]
|
||||
count: 4,
|
||||
result: [ "foo@foo.invalid", "bar@foo.invalid", "bar2@foo.invalid", "y@y.invalid" ]
|
||||
},
|
||||
{ recipients: 'Undisclosed recipients:;;;;;;;;;;;;;;;;,,,,,,,,,,,,,,,,',
|
||||
emailAddressOnly: true,
|
||||
count: 1,
|
||||
result: ["\"Undisclosed recipients:;\""]
|
||||
count: 0,
|
||||
result: []
|
||||
},
|
||||
{ recipients: 'a@xxx.invalid; b@xxx.invalid',
|
||||
emailAddressOnly: true,
|
||||
|
@ -73,22 +73,22 @@ const splitRecipientsTests =
|
|||
{ recipients: "A (this: is, a comment;) <a.invalid>; g: (this: is, <a> comment;) C <c.invalid>, d.invalid;",
|
||||
emailAddressOnly: false,
|
||||
count: 3,
|
||||
result: [ 'A (this: is, a comment;) <a.invalid>', 'g: (this: is, <a> comment;) C <c.invalid>', "d.invalid" ]
|
||||
result: [ 'A (this: is, a comment;) <a.invalid>', '(this: is, <a> comment;) C <c.invalid>', "d.invalid <>" ]
|
||||
},
|
||||
{ recipients: 'Mary Smith <mary@x.invalid>, extra:;, group:jdoe@example.invalid; Who? <one@y.invalid>; <boss@nil.invalid>, "Giant; \\"Big\\" Box" <sysservices@example.invalid>, ',
|
||||
emailAddressOnly: false,
|
||||
count: 6,
|
||||
result: [ "Mary Smith <mary@x.invalid>", "extra:;", "group:jdoe@example.invalid;", "Who? <one@y.invalid>", "boss@nil.invalid", 'Giant; \"Big\" Box <sysservices@example.invalid>' ]
|
||||
count: 5,
|
||||
result: [ "Mary Smith <mary@x.invalid>", "jdoe@example.invalid", "Who? <one@y.invalid>", "boss@nil.invalid", 'Giant; \"Big\" Box <sysservices@example.invalid>' ]
|
||||
},
|
||||
{ recipients: 'Undisclosed recipients: a@foo.invalid ;;extra:;',
|
||||
emailAddressOnly: true,
|
||||
count: 2,
|
||||
result: [ '\"Undisclosed recipients: a\"@foo.invalid ;', 'extra:;' ]
|
||||
count: 1,
|
||||
result: [ 'a@foo.invalid' ]
|
||||
},
|
||||
{ recipients: 'Undisclosed recipients:;;extra:a@foo.invalid;',
|
||||
emailAddressOnly: true,
|
||||
count: 2,
|
||||
result: [ '\"Undisclosed recipients:;\"', 'extra:a@foo.invalid;' ]
|
||||
count: 1,
|
||||
result: [ 'a@foo.invalid' ]
|
||||
},
|
||||
{ recipients: "",
|
||||
emailAddressOnly: false,
|
||||
|
|
|
@ -35,9 +35,4 @@
|
|||
#define NS_MIME_OBJECT_CONTRACTID \
|
||||
"@mozilla.org/messenger/mimeobject;1"
|
||||
|
||||
// {932C53A5-F398-11d2-82B7-444553540002}
|
||||
#define NS_MSGHEADERPARSER_CID \
|
||||
{ 0x932c53a5, 0xf398, 0x11d2, \
|
||||
{ 0x82, 0xb7, 0x44, 0x45, 0x53, 0x54, 0x0, 0x2 } }
|
||||
|
||||
#endif // nsMessageMimeCID_h__
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource:///modules/jsmime.jsm");
|
||||
Components.utils.import("resource:///modules/mimeParser.jsm");
|
||||
Components.utils.import("resource:///modules/XPCOMUtils.jsm");
|
||||
|
||||
|
@ -36,5 +37,229 @@ MimeHeaders.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
var components = [MimeHeaders];
|
||||
// These are prototypes for nsIMsgHeaderParser implementation
|
||||
var Mailbox = {
|
||||
toString: function () {
|
||||
return this.name ? this.name + " <" + this.email + ">" : this.email;
|
||||
}
|
||||
};
|
||||
|
||||
var EmailGroup = {
|
||||
toString: function () {
|
||||
return this.name + ": " + [x.toString() for (x of this.group)].join(", ");
|
||||
}
|
||||
};
|
||||
|
||||
function MimeAddressParser() {
|
||||
}
|
||||
MimeAddressParser.prototype = {
|
||||
classDescription: "Mime message header parser implementation",
|
||||
classID: Components.ID("96bd8769-2d0e-4440-963d-22b97fb3ba77"),
|
||||
contractID: "@mozilla.org/messenger/headerparser;1",
|
||||
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIMsgHeaderParser]),
|
||||
|
||||
parseEncodedHeader: function (aHeader, aCharset, aPreserveGroups, count) {
|
||||
aHeader = aHeader || "";
|
||||
let value = MimeParser.parseHeaderField(aHeader,
|
||||
MimeParser.HEADER_ADDRESS | MimeParser.HEADER_OPTION_ALL_I18N, aCharset);
|
||||
return this._fixArray(value, aPreserveGroups, count);
|
||||
},
|
||||
parseDecodedHeader: function (aHeader, aPreserveGroups, count) {
|
||||
aHeader = aHeader || "";
|
||||
let value = MimeParser.parseHeaderField(aHeader, MimeParser.HEADER_ADDRESS);
|
||||
return this._fixArray(value, aPreserveGroups, count);
|
||||
},
|
||||
|
||||
// A helper method for parse*Header that takes into account the desire to
|
||||
// preserve group and also tweaks the output to support the prototypes for the
|
||||
// XPIDL output.
|
||||
_fixArray: function (addresses, preserveGroups, count) {
|
||||
function resetPrototype(obj, prototype) {
|
||||
let prototyped = Object.create(prototype);
|
||||
for (var key in obj)
|
||||
prototyped[key] = obj[key];
|
||||
return prototyped;
|
||||
}
|
||||
let outputArray = [];
|
||||
for (let element of addresses) {
|
||||
if ('group' in element) {
|
||||
// Fix up the prototypes of the group and the list members
|
||||
element = resetPrototype(element, EmailGroup);
|
||||
element.group = element.group.map(e => resetPrototype(e, Mailbox));
|
||||
|
||||
// Add to the output array
|
||||
if (preserveGroups)
|
||||
outputArray.push(element);
|
||||
else
|
||||
outputArray = outputArray.concat(element.group);
|
||||
} else {
|
||||
element = resetPrototype(element, Mailbox);
|
||||
outputArray.push(element);
|
||||
}
|
||||
}
|
||||
|
||||
if (count)
|
||||
count.value = outputArray.length;
|
||||
return outputArray;
|
||||
},
|
||||
|
||||
makeMimeHeader: function (addresses, length) {
|
||||
// Don't output any necessary continuations, so make line length as large as
|
||||
// possible first.
|
||||
let options = {
|
||||
softMargin: 900,
|
||||
hardMargin: 900,
|
||||
useASCII: false // We don't want RFC 2047 encoding here.
|
||||
};
|
||||
let handler = {
|
||||
value: "",
|
||||
deliverData: function (str) { this.value += str; },
|
||||
deliverEOF: function () {}
|
||||
};
|
||||
let emitter = new jsmime.headeremitter.makeStreamingEmitter(handler,
|
||||
options);
|
||||
emitter.addAddresses(addresses);
|
||||
emitter.finish(true);
|
||||
return handler.value.replace(/\r\n( |$)/g, '');
|
||||
},
|
||||
|
||||
extractFirstName: function (aHeader) {
|
||||
let address = this.parseDecodedHeader(aHeader, false)[0];
|
||||
return address.name || address.email;
|
||||
},
|
||||
|
||||
removeDuplicateAddresses: function (aAddrs, aOtherAddrs) {
|
||||
// This is actually a rather complicated algorithm, especially if we want to
|
||||
// preserve group structure. Basically, we use a set to identify which
|
||||
// headers we have seen and therefore want to remove. To work in several
|
||||
// various forms of edge cases, we need to normalize the entries in that
|
||||
// structure.
|
||||
function normalize(email) {
|
||||
// XXX: This algorithm doesn't work with IDN yet. It looks like we have to
|
||||
// convert from IDN then do lower case, but I haven't confirmed yet.
|
||||
return email.toLowerCase();
|
||||
}
|
||||
|
||||
// The filtration function, which removes email addresses that are
|
||||
// duplicates of those we have already seen.
|
||||
function filterAccept(e) {
|
||||
if ('email' in e) {
|
||||
// If we've seen the address, don't keep this one; otherwise, add it to
|
||||
// the list.
|
||||
let key = normalize(e.email);
|
||||
if (allAddresses.has(key))
|
||||
return false;
|
||||
allAddresses.add(key);
|
||||
} else {
|
||||
// Groups -> filter out all the member addresses.
|
||||
e.group = e.group.filter(filterAccept);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// First, collect all of the emails to forcibly delete.
|
||||
let allAddresses = Set();
|
||||
for (let element of this.parseDecodedHeader(aOtherAddrs, false)) {
|
||||
allAddresses.add(normalize(element.email));
|
||||
}
|
||||
|
||||
// The actual data to filter
|
||||
let filtered = this.parseDecodedHeader(aAddrs, true).filter(filterAccept);
|
||||
return this.makeMimeHeader(filtered);
|
||||
},
|
||||
|
||||
makeMailboxObject: function (aName, aEmail) {
|
||||
let object = Object.create(Mailbox);
|
||||
object.name = aName;
|
||||
object.email = aEmail;
|
||||
return object;
|
||||
},
|
||||
|
||||
makeGroupObject: function (aName, aMembers) {
|
||||
let object = Object.create(EmailGroup);
|
||||
object.name = aName;
|
||||
object.members = aMembers;
|
||||
return object;
|
||||
},
|
||||
|
||||
makeFromDisplayAddress: function (aDisplay, count) {
|
||||
// The basic idea is to split on every comma, so long as there is a
|
||||
// preceding @.
|
||||
let output = [];
|
||||
while (aDisplay.length) {
|
||||
let at = aDisplay.indexOf('@');
|
||||
let comma = aDisplay.indexOf(',', at + 1);
|
||||
let addr;
|
||||
if (comma > 0) {
|
||||
addr = aDisplay.substr(0, comma);
|
||||
aDisplay = aDisplay.substr(comma + 1);
|
||||
} else {
|
||||
addr = aDisplay;
|
||||
aDisplay = "";
|
||||
}
|
||||
output.push(this._makeSingleAddress(addr.trimLeft()));
|
||||
}
|
||||
if (count)
|
||||
count.value = output.length;
|
||||
return output;
|
||||
},
|
||||
|
||||
/// Construct a single email address from a name <local@domain> token.
|
||||
_makeSingleAddress: function (aDisplayName) {
|
||||
if (aDisplayName.contains('<')) {
|
||||
let lbracket = aDisplayName.lastIndexOf('<');
|
||||
let rbracket = aDisplayName.lastIndexOf('>');
|
||||
// If there are multiple spaces between the display name and the bracket,
|
||||
// strip off only a single space.
|
||||
return this.makeMailboxObject(
|
||||
lbracket == 0 ? '' : aDisplayName.slice(0, lbracket - 1),
|
||||
aDisplayName.slice(lbracket + 1, rbracket));
|
||||
} else {
|
||||
return this.makeMailboxObject('', aDisplayName);
|
||||
}
|
||||
},
|
||||
|
||||
// What follows is the deprecated API that will be removed shortly.
|
||||
|
||||
parseHeadersWithArray: function (aHeader, aAddrs, aNames, aFullNames) {
|
||||
let addrs = [], names = [], fullNames = [];
|
||||
let allAddresses = this.parseEncodedHeader(aHeader, undefined, false);
|
||||
// Don't index the dummy empty address.
|
||||
if (aHeader.trim() == "")
|
||||
allAddresses = [];
|
||||
for (let address of allAddresses) {
|
||||
addrs.push(address.email);
|
||||
names.push(address.name || null);
|
||||
fullNames.push(address.toString());
|
||||
}
|
||||
|
||||
aAddrs.value = addrs;
|
||||
aNames.value = names;
|
||||
aFullNames.value = fullNames;
|
||||
return allAddresses.length;
|
||||
},
|
||||
|
||||
extractHeaderAddressMailboxes: function (aLine) {
|
||||
return [addr.email for (addr of this.parseDecodedHeader(aLine))].join(", ");
|
||||
},
|
||||
|
||||
extractHeaderAddressNames: function (aLine) {
|
||||
return [addr.name || addr.email for
|
||||
(addr of this.parseDecodedHeader(aLine))].join(", ");
|
||||
},
|
||||
|
||||
extractHeaderAddressName: function (aLine) {
|
||||
let addrs = [addr.name || addr.email for
|
||||
(addr of this.parseDecodedHeader(aLine))];
|
||||
return addrs.length == 0 ? "" : addrs[0];
|
||||
},
|
||||
|
||||
makeMimeAddress: function (aName, aEmail) {
|
||||
let object = this.makeMailboxObject(aName, aEmail);
|
||||
return this.makeMimeHeader([object]);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
var components = [MimeHeaders, MimeAddressParser];
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
||||
|
|
|
@ -178,6 +178,13 @@ var MimeParser = {
|
|||
|
||||
// Parameters for parseHeaderField
|
||||
|
||||
/**
|
||||
* Parse the header as if it were unstructured.
|
||||
*
|
||||
* This results in the same string if no other options are specified. If other
|
||||
* options are specified, this causes the string to be modified appropriately.
|
||||
*/
|
||||
HEADER_UNSTRUCTURED: 0x00,
|
||||
/**
|
||||
* Parse the header as if it were in the form text; attr=val; attr=val.
|
||||
*
|
||||
|
@ -185,6 +192,28 @@ var MimeParser = {
|
|||
* headers used by MIME as opposed to messages.
|
||||
*/
|
||||
HEADER_PARAMETER: 0x02,
|
||||
/**
|
||||
* Parse the header as if it were a sequence of mailboxes.
|
||||
*/
|
||||
HEADER_ADDRESS: 0x03,
|
||||
|
||||
/**
|
||||
* This decodes parameter values according to RFC 2231.
|
||||
*
|
||||
* This flag means nothing if HEADER_PARAMETER is not specified.
|
||||
*/
|
||||
HEADER_OPTION_DECODE_2231: 0x10,
|
||||
/**
|
||||
* This decodes the inline encoded-words that are in RFC 2047.
|
||||
*/
|
||||
HEADER_OPTION_DECODE_2047: 0x20,
|
||||
/**
|
||||
* This converts the header from a raw string to proper Unicode.
|
||||
*/
|
||||
HEADER_OPTION_ALLOW_RAW: 0x40,
|
||||
|
||||
/// Convenience for all three of the above.
|
||||
HEADER_OPTION_ALL_I18N: 0x70,
|
||||
|
||||
/**
|
||||
* Parse a header field according to the specification given by flags.
|
||||
|
@ -192,23 +221,36 @@ var MimeParser = {
|
|||
* Permissible flags begin with one of the HEADER_* flags, which may be or'd
|
||||
* with any of the HEADER_OPTION_* flags to modify the result appropriately.
|
||||
*
|
||||
* If a charset-aware option (HEADER_OPTION_DECODE_2231 or
|
||||
* HEADER_OPTION_DECODE_2047) is used, the charset parameter, if present, is
|
||||
* the default charset to assume if no charset is found. If this parameter is
|
||||
* not present, UTF-8 will be assumed to be the default. Furthermore, if any
|
||||
* of these options are used, resulting strings will be normalized to full
|
||||
* Unicode.
|
||||
* If the option HEADER_OPTION_ALLOW_RAW is passed, the charset parameter, if
|
||||
* present, is the charset to fallback to if the header is not decodable as
|
||||
* UTF-8 text. If HEADER_OPTION_ALLOW_RAW is passed but the charset parameter
|
||||
* is not provided, then no fallback decoding will be done. If
|
||||
* HEADER_OPTION_ALLOW_RAW is not passed, then no attempt will be made to
|
||||
* convert charsets.
|
||||
*
|
||||
* @param text The value of a MIME or message header to parse.
|
||||
* @param flags A set of flags that controls interpretation of the header.
|
||||
* @param charset A default charset to assume if no information may be found.
|
||||
*/
|
||||
parseHeaderField: function MimeParser_parseHeaderField(text, flags, charset) {
|
||||
// If we have a raw string, convert it to Unicode first
|
||||
if (flags & MimeParser.HEADER_OPTION_ALLOW_RAW)
|
||||
text = jsmime.headerparser.convert8BitHeader(text, charset);
|
||||
|
||||
// The low 4 bits indicate the type of the header we are parsing. All of the
|
||||
// higher-order bits are flags.
|
||||
switch (flags & 0x0f) {
|
||||
case MimeParser.HEADER_UNSTRUCTURED:
|
||||
if (flags & MimeParser.HEADER_OPTION_DECODE_2047)
|
||||
text = jsmime.headerparser.decodeRFC2047Words(text);
|
||||
return text;
|
||||
case MimeParser.HEADER_PARAMETER:
|
||||
return jsmime.headerparser.parseParameterHeader(text, false, false);
|
||||
return jsmime.headerparser.parseParameterHeader(text,
|
||||
(flags & MimeParser.HEADER_OPTION_DECODE_2047) != 0,
|
||||
(flags & MimeParser.HEADER_OPTION_DECODE_2231) != 0);
|
||||
case MimeParser.HEADER_ADDRESS:
|
||||
return jsmime.headerparser.parseAddressingHeader(text,
|
||||
(flags & MimeParser.HEADER_OPTION_DECODE_2047) != 0);
|
||||
default:
|
||||
throw "Illegal type of header field";
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ SOURCES += [
|
|||
'mimeunty.cpp',
|
||||
'nsMimeConverter.cpp',
|
||||
'nsMimeObjectClassAccess.cpp',
|
||||
'nsMsgHeaderParser.cpp',
|
||||
'nsSimpleMimeConverterStub.cpp',
|
||||
'nsStreamConverter.cpp',
|
||||
]
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
component {d1258011-f391-44fd-992e-c6f4b461a42f} mimeJSComponents.js
|
||||
component {96bd8769-2d0e-4440-963d-22b97fb3ba77} mimeJSComponents.js
|
||||
contract @mozilla.org/messenger/mimeheaders;1 {d1258011-f391-44fd-992e-c6f4b461a42f}
|
||||
contract @mozilla.org/messenger/headerparser;1 {96bd8769-2d0e-4440-963d-22b97fb3ba77}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,77 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/********************************************************************************************************
|
||||
|
||||
Interface for parsing RFC-822 addresses.
|
||||
|
||||
*********************************************************************************************************/
|
||||
|
||||
#ifndef nsMSGRFCPARSER_h__
|
||||
#define nsMSGRFCPARSER_h__
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsIMsgHeaderParser.h" /* include the interface we are going to support */
|
||||
#include "nsIMimeConverter.h"
|
||||
#include "comi18n.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
/*
|
||||
* RFC-822 parser
|
||||
*/
|
||||
|
||||
class nsMsgHeaderParser: public nsIMsgHeaderParser
|
||||
{
|
||||
public:
|
||||
nsMsgHeaderParser();
|
||||
virtual ~nsMsgHeaderParser();
|
||||
|
||||
/* this macro defines QueryInterface, AddRef and Release for this class */
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGHEADERPARSER
|
||||
|
||||
/**
|
||||
* Given a string which contains a list of Header addresses, parses it into
|
||||
* their component names and mailboxes.
|
||||
*
|
||||
* @param aLine The header line to parse.
|
||||
* @param aNames A string of the names in the header line. The names
|
||||
* are separated by null-terminators.
|
||||
* This param may be null if the caller does not want
|
||||
* this part of the result.
|
||||
* @param aAddresses A string of the addresses in the header line. The
|
||||
* addresses are separated by null-terminators.
|
||||
* This param may be null if the caller does not want
|
||||
* this part of the result.
|
||||
* @param aNumAddresses The number of addresses in the header. If this is
|
||||
* negative, there has been an error parsing the
|
||||
* header.
|
||||
*/
|
||||
static nsresult ParseHeaderAddresses(const char *aLine, char **aNames,
|
||||
char **aAddresses, uint32_t *aNumAddresses);
|
||||
|
||||
static nsresult UnquotePhraseOrAddr(const char *line, bool preserveIntegrity,
|
||||
char **result);
|
||||
static nsresult UnquotePhraseOrAddrWString(const char16_t *line,
|
||||
bool preserveIntegrity,
|
||||
char16_t **result);
|
||||
};
|
||||
|
||||
class MsgAddressObject MOZ_FINAL : public msgIAddressObject
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_MSGIADDRESSOBJECT
|
||||
|
||||
MsgAddressObject(const nsAString &aName, const nsAString &aEmail);
|
||||
|
||||
private:
|
||||
nsString mName;
|
||||
nsString mEmail;
|
||||
};
|
||||
|
||||
#endif /* nsMSGRFCPARSER_h__ */
|
|
@ -44,28 +44,20 @@ function run_test() {
|
|||
// More complicated examples drawn from RFC 2822
|
||||
["\"Joe Q. Public\" <john.q.public@example.com>,Test <\"abc!x.yz\"@foo.invalid>, Test <test@[xyz!]>,\"Giant; \\\"Big\\\" Box\" <sysservices@example.net>",
|
||||
"john.q.public@example.com, \"abc!x.yz\"@foo.invalid, test@[xyz!], sysservices@example.net",
|
||||
"\"Joe Q. Public\", Test, Test, \"Giant; \\\"Big\\\" Box\"",
|
||||
"Joe Q. Public, Test, Test, Giant; \"Big\" Box",
|
||||
// extractHeaderAddressName returns unquoted names, hence the difference.
|
||||
"Joe Q. Public" ],
|
||||
// Bug 549931
|
||||
["Undisclosed recipients:;",
|
||||
"\"Undisclosed recipients:;\"", // Mailboxes
|
||||
"\"Undisclosed recipients:;\"", // Address Names
|
||||
"Undisclosed recipients:;"] // Address Name
|
||||
"", // Mailboxes
|
||||
"", // Address Names
|
||||
""] // Address Name
|
||||
];
|
||||
|
||||
// this used to cause memory read overruns
|
||||
let addresses = {}, names = {}, fullAddresses = {};
|
||||
MailServices.headerParser.parseHeadersWithArray("\" \"@a a;b", addresses, names, fullAddresses);
|
||||
|
||||
// This checks that the mime header parser doesn't march past the end
|
||||
// of strings with ":;" in them. The second ":;" is required to force the
|
||||
// parser to keep going.
|
||||
do_check_eq(MailServices.headerParser.extractHeaderAddressMailboxes(
|
||||
"undisclosed-recipients:;\0:; foo <ghj@veryveryveryverylongveryveryveryveryinvalidaddress.invalid>"),
|
||||
"undisclosed-recipients:;");
|
||||
|
||||
do_check_eq(MailServices.headerParser.extractHeaderAddressMailboxes("<a;a@invalid"), "");
|
||||
|
||||
// Test - empty strings
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ function run_test() {
|
|||
expectedResult: "foo bar <test@foo.invalid>" },
|
||||
{ addrs: "foo bar <test@foo.invalid>",
|
||||
otherAddrs: "foo bar <test@foo.invalid>",
|
||||
expectedResult: null },
|
||||
expectedResult: "" },
|
||||
{ addrs: "foo bar <test@foo.invalid>, abc@foo.invalid",
|
||||
otherAddrs: "foo bar <test@foo.invalid>",
|
||||
expectedResult: "abc@foo.invalid" },
|
||||
|
@ -44,7 +44,17 @@ function run_test() {
|
|||
expectedResult: "\u00F6foo <ghj@foo.invalid>" },
|
||||
{ addrs: "foo\u00D0 bar <foo@bar.invalid>, \u00F6foo <ghj@foo.invalid>, foo\u00D0 bar <foo@bar.invalid>",
|
||||
otherAddrs: "\u00F6foo <ghj@foo.invalid>",
|
||||
expectedResult: "foo\u00D0 bar <foo@bar.invalid>" }
|
||||
expectedResult: "foo\u00D0 bar <foo@bar.invalid>" },
|
||||
// Test email groups
|
||||
{ addrs: "A group: foo bar <foo@bar.invalid>, foo <ghj@foo.invalid>;",
|
||||
otherAddrs: "foo <ghj@foo.invalid>",
|
||||
expectedResult: "A group: foo bar <foo@bar.invalid>;" },
|
||||
{ addrs: "A group: foo bar <foo@bar.invalid>, foo <ghj@foo.invalid>;",
|
||||
otherAddrs: "foo bar <ghj@foo.invalid>",
|
||||
expectedResult: "A group: foo bar <foo@bar.invalid>;" },
|
||||
{ addrs: "A group: foo bar <foo@bar.invalid>;, foo <ghj@foo.invalid>",
|
||||
otherAddrs: "foo <foo@bar.invalid>",
|
||||
expectedResult: "A group: ; , foo <ghj@foo.invalid>" },
|
||||
];
|
||||
|
||||
// Test - empty strings
|
||||
|
|
Загрузка…
Ссылка в новой задаче