/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ #include "mozilla/mailnews/MimeHeaderParser.h" #include "mozilla/DebugOnly.h" #include "nsMemory.h" #include "nsCOMPtr.h" #include "nsIMsgHeaderParser.h" #include "mozilla/Components.h" namespace mozilla { namespace mailnews { void detail::DoConversion(const nsTArray& aUTF16Array, nsTArray& aUTF8Array) { uint32_t count = aUTF16Array.Length(); aUTF8Array.SetLength(count); for (uint32_t i = 0; i < count; ++i) CopyUTF16toUTF8(aUTF16Array[i], aUTF8Array[i]); } void MakeMimeAddress(const nsACString& aName, const nsACString& aEmail, nsACString& full) { nsAutoString utf16Address; MakeMimeAddress(NS_ConvertUTF8toUTF16(aName), NS_ConvertUTF8toUTF16(aEmail), utf16Address); CopyUTF16toUTF8(utf16Address, full); } void MakeMimeAddress(const nsAString& aName, const nsAString& aEmail, nsAString& full) { nsCOMPtr headerParser( components::HeaderParser::Service()); nsCOMPtr address; headerParser->MakeMailboxObject(aName, aEmail, getter_AddRefs(address)); nsTArray> addresses; addresses.AppendElement(address); headerParser->MakeMimeHeader(addresses, full); } void MakeDisplayAddress(const nsAString& aName, const nsAString& aEmail, nsAString& full) { nsCOMPtr headerParser( components::HeaderParser::Service()); nsCOMPtr object; headerParser->MakeMailboxObject(aName, aEmail, getter_AddRefs(object)); object->ToString(full); } void RemoveDuplicateAddresses(const nsACString& aHeader, const nsACString& aOtherEmails, nsACString& result) { nsCOMPtr headerParser( components::HeaderParser::Service()); headerParser->RemoveDuplicateAddresses(aHeader, aOtherEmails, result); } ///////////////////////////////////////////// // These are the core shim methods we need // ///////////////////////////////////////////// nsCOMArray DecodedHeader(const nsAString& aHeader) { nsCOMArray retval; if (aHeader.IsEmpty()) { return retval; } nsCOMPtr headerParser( components::HeaderParser::Service()); NS_ENSURE_TRUE(headerParser, retval); nsTArray> addresses; nsresult rv = headerParser->ParseDecodedHeader(aHeader, false, addresses); MOZ_ASSERT(NS_SUCCEEDED(rv), "Javascript jsmime returned an error!"); if (NS_SUCCEEDED(rv) && addresses.Length() > 0) { retval.SetCapacity(addresses.Length()); for (auto& addr : addresses) { retval.AppendElement(addr); } } return retval; } nsCOMArray EncodedHeader(const nsACString& aHeader, const char* aCharset) { nsCOMArray retval; if (aHeader.IsEmpty()) { return retval; } nsCOMPtr headerParser( components::HeaderParser::Service()); NS_ENSURE_TRUE(headerParser, retval); nsTArray> addresses; nsresult rv = headerParser->ParseEncodedHeader(aHeader, aCharset, false, addresses); MOZ_ASSERT(NS_SUCCEEDED(rv), "This should never fail!"); if (NS_SUCCEEDED(rv) && addresses.Length() > 0) { retval.SetCapacity(addresses.Length()); for (auto& addr : addresses) { retval.AppendElement(addr); } } return retval; } nsCOMArray EncodedHeaderW(const nsAString& aHeader) { nsCOMArray retval; if (aHeader.IsEmpty()) { return retval; } nsCOMPtr headerParser( components::HeaderParser::Service()); NS_ENSURE_TRUE(headerParser, retval); nsTArray> addresses; nsresult rv = headerParser->ParseEncodedHeaderW(aHeader, addresses); MOZ_ASSERT(NS_SUCCEEDED(rv), "This should never fail!"); if (NS_SUCCEEDED(rv) && addresses.Length() > 0) { retval.SetCapacity(addresses.Length()); for (auto& addr : addresses) { retval.AppendElement(addr); } } return retval; } void ExtractAllAddresses(const nsCOMArray& aHeader, nsTArray& names, nsTArray& emails) { uint32_t count = aHeader.Length(); // Prefill arrays before we start names.SetLength(count); emails.SetLength(count); for (uint32_t i = 0; i < count; i++) { aHeader[i]->GetName(names[i]); aHeader[i]->GetEmail(emails[i]); } if (count == 1 && names[0].IsEmpty() && emails[0].IsEmpty()) { names.Clear(); emails.Clear(); } } void ExtractDisplayAddresses(const nsCOMArray& aHeader, nsTArray& displayAddrs) { uint32_t count = aHeader.Length(); displayAddrs.SetLength(count); for (uint32_t i = 0; i < count; i++) aHeader[i]->ToString(displayAddrs[i]); if (count == 1 && displayAddrs[0].IsEmpty()) displayAddrs.Clear(); } ///////////////////////////////////////////////// // All of these are based on the above methods // ///////////////////////////////////////////////// void ExtractEmails(const nsCOMArray& aHeader, nsTArray& emails) { nsTArray names; ExtractAllAddresses(aHeader, names, emails); } void ExtractEmail(const nsCOMArray& aHeader, nsACString& email) { AutoTArray names; AutoTArray emails; ExtractAllAddresses(aHeader, names, emails); if (emails.Length() > 0) CopyUTF16toUTF8(emails[0], email); else email.Truncate(); } void ExtractFirstAddress(const nsCOMArray& aHeader, nsACString& name, nsACString& email) { AutoTArray names, emails; ExtractAllAddresses(aHeader, names, emails); if (names.Length() > 0) { CopyUTF16toUTF8(names[0], name); CopyUTF16toUTF8(emails[0], email); } else { name.Truncate(); email.Truncate(); } } void ExtractFirstAddress(const nsCOMArray& aHeader, nsAString& name, nsACString& email) { AutoTArray names, emails; ExtractAllAddresses(aHeader, names, emails); if (names.Length() > 0) { name = names[0]; CopyUTF16toUTF8(emails[0], email); } else { name.Truncate(); email.Truncate(); } } void ExtractName(const nsCOMArray& aHeader, nsACString& name) { nsCString email; ExtractFirstAddress(aHeader, name, email); if (name.IsEmpty()) name = email; } void ExtractName(const nsCOMArray& aHeader, nsAString& name) { AutoTArray names; AutoTArray emails; ExtractAllAddresses(aHeader, names, emails); if (names.Length() > 0) { if (names[0].IsEmpty()) name = emails[0]; else name = names[0]; } else { name.Truncate(); } } } // namespace mailnews } // namespace mozilla