mailnews/intl/nsCharsetConverterManager.cpp
author Rob Lemley <rob@thunderbird.net>
Mon, 27 Apr 2020 19:51:09 -0400
changeset 38064 39e1d01fb0c37b7f70bc92d58a9a06f8148e6981
parent 34305 babef6da7d89f1715921953da0fd0d95a5bb4f49
child 39007 1aa86015cd87b30709412551835bf902025cd7d1
permissions -rw-r--r--
Bug 1577518 - Update libgcrypt to version 1.8.5. r=kaie

/* -*- 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/. */

#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsUnicharUtils.h"
#include "nsCharsetAlias.h"
#include "nsICharsetConverterManager.h"
#include "nsIStringBundle.h"
#include "nsTArray.h"
#include "mozilla/Services.h"

#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
#include "../base/util/nsMsgI18N.h"

// just for CONTRACTIDs
#include "nsCharsetConverterManager.h"

static nsCOMPtr<nsIStringBundle> sDataBundle;
static nsCOMPtr<nsIStringBundle> sTitleBundle;

// Class nsCharsetConverterManager [implementation]

NS_IMPL_ISUPPORTS(nsCharsetConverterManager, nsICharsetConverterManager)

nsCharsetConverterManager::nsCharsetConverterManager() {}

nsCharsetConverterManager::~nsCharsetConverterManager() {
  sDataBundle = nullptr;
  sTitleBundle = nullptr;
}

static nsresult LoadBundle(const char* aBundleURLSpec,
                           nsIStringBundle** aResult) {
  nsCOMPtr<nsIStringBundleService> sbServ =
      mozilla::services::GetStringBundleService();
  if (!sbServ) return NS_ERROR_FAILURE;

  return sbServ->CreateBundle(aBundleURLSpec, aResult);
}

static nsresult GetBundleValueInner(nsIStringBundle* aBundle, const char* aName,
                                    const nsString& aProp, nsAString& aResult) {
  nsAutoString key;

  CopyASCIItoUTF16(mozilla::MakeStringSpan(aName), key);
  ToLowerCase(key);  // we lowercase the main comparison key
  key.Append(aProp);

  return aBundle->GetStringFromName(NS_ConvertUTF16toUTF8(key).get(), aResult);
}

static nsresult GetBundleValue(nsIStringBundle* aBundle, const char* aName,
                               const nsString& aProp, nsAString& aResult) {
  nsresult rv = NS_OK;

  nsAutoString value;
  rv = GetBundleValueInner(aBundle, aName, aProp, value);
  if (NS_FAILED(rv)) return rv;

  aResult = value;

  return NS_OK;
}

static nsresult GetCharsetDataImpl(const char* aCharset, const char16_t* aProp,
                                   nsAString& aResult) {
  NS_ENSURE_ARG_POINTER(aCharset);
  // aProp can be nullptr

  if (!sDataBundle) {
    nsresult rv = LoadBundle("resource://gre-resources/charsetData.properties",
                             getter_AddRefs(sDataBundle));
    if (NS_FAILED(rv)) return rv;
  }

  return GetBundleValue(sDataBundle, aCharset, nsDependentString(aProp),
                        aResult);
}

// static
bool nsCharsetConverterManager::IsInternal(const nsACString& aCharset) {
  nsAutoString str;
  // fully qualify to possibly avoid vtable call
  nsresult rv = GetCharsetDataImpl(PromiseFlatCString(aCharset).get(),
                                   u".isInternal", str);

  return NS_SUCCEEDED(rv);
}

//----------------------------------------------------------------------------//----------------------------------------------------------------------------
// Interface nsICharsetConverterManager [implementation]

// XXX Improve the implementation of this method. Right now, it is build on
// top of the nsCharsetAlias service. We can make the nsCharsetAlias
// better, with its own hash table (not the StringBundle anymore) and
// a nicer file format.
NS_IMETHODIMP
nsCharsetConverterManager::GetCharsetAlias(const char* aCharset,
                                           nsACString& aResult) {
  NS_ENSURE_ARG_POINTER(aCharset);

  // We try to obtain the preferred name for this charset from the charset
  // aliases.
  nsresult rv;

  rv = nsCharsetAlias::GetPreferred(nsDependentCString(aCharset), aResult);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}

NS_IMETHODIMP
nsCharsetConverterManager::GetCharsetTitle(const char* aCharset,
                                           nsAString& aResult) {
  NS_ENSURE_ARG_POINTER(aCharset);

  if (!sTitleBundle) {
    nsresult rv =
        LoadBundle("chrome://messenger/locale/charsetTitles.properties",
                   getter_AddRefs(sTitleBundle));
    NS_ENSURE_SUCCESS(rv, rv);
  }

  return GetBundleValue(sTitleBundle, aCharset, NS_LITERAL_STRING(".title"),
                        aResult);
}

NS_IMETHODIMP
nsCharsetConverterManager::GetCharsetData(const char* aCharset,
                                          const char16_t* aProp,
                                          nsAString& aResult) {
  return GetCharsetDataImpl(aCharset, aProp, aResult);
}

NS_IMETHODIMP
nsCharsetConverterManager::GetCharsetLangGroup(const char* aCharset,
                                               nsACString& aResult) {
  // resolve the charset first
  nsAutoCString charset;

  nsresult rv = GetCharsetAlias(aCharset, charset);
  NS_ENSURE_SUCCESS(rv, rv);

  // fully qualify to possibly avoid vtable call
  return nsCharsetConverterManager::GetCharsetLangGroupRaw(charset.get(),
                                                           aResult);
}

NS_IMETHODIMP
nsCharsetConverterManager::GetCharsetLangGroupRaw(const char* aCharset,
                                                  nsACString& aResult) {
  nsAutoString langGroup;
  // fully qualify to possibly avoid vtable call
  nsresult rv = nsCharsetConverterManager::GetCharsetData(
      aCharset, u".LangGroup", langGroup);

  if (NS_SUCCEEDED(rv)) {
    ToLowerCase(langGroup);  // use lowercase for all language groups
    aResult = NS_ConvertUTF16toUTF8(langGroup);
  }

  return rv;
}

NS_IMETHODIMP
nsCharsetConverterManager::Utf7ToUnicode(const nsACString& aSrc,
                                         nsAString& aDest) {
  return CopyUTF7toUTF16(aSrc, aDest);
}

NS_IMETHODIMP
nsCharsetConverterManager::Mutf7ToUnicode(const nsACString& aSrc,
                                          nsAString& aDest) {
  return CopyMUTF7toUTF16(aSrc, aDest);
}

NS_IMETHODIMP
nsCharsetConverterManager::UnicodeToMutf7(const nsAString& aSrc,
                                          nsACString& aDest) {
  return CopyUTF16toMUTF7(aSrc, aDest);
}