Back to index

lightning-sunbird  0.9+nobinonly
nsMsgI18N.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 // as does this
00040 #include "nsICharsetConverterManager.h"
00041 #include "nsICharsetAlias.h"
00042 #include "nsIPlatformCharset.h"
00043 #include "nsIServiceManager.h"
00044 #include "nsICharsetConverterManager.h"
00045 
00046 #include "nsISupports.h"
00047 #include "nsIPrefBranch.h"
00048 #include "nsIPrefService.h"
00049 #include "nsIPrefLocalizedString.h"
00050 #include "nsIMimeConverter.h"
00051 #include "msgCore.h"
00052 #include "nsMsgI18N.h"
00053 #include "nsFileSpec.h"
00054 #include "nsFileStream.h"
00055 #include "nsMsgMimeCID.h"
00056 #include "nsMimeTypes.h"
00057 #include "nsIEntityConverter.h"
00058 #include "nsISaveAsCharset.h"
00059 #include "nsHankakuToZenkakuCID.h"
00060 #include "nsXPIDLString.h"
00061 #include "nsString.h"
00062 #include "nsReadableUtils.h"
00063 #include "prmem.h"
00064 #include "nsFileSpec.h"
00065 #include "plstr.h"
00066 
00067 static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
00068 static NS_DEFINE_CID(kEntityConverterCID, NS_ENTITYCONVERTER_CID);
00069 
00070 //
00071 // International functions necessary for composition
00072 //
00073 
00074 nsresult nsMsgI18NConvertFromUnicode(const char* aCharset,
00075                                      const nsAFlatString& inString,
00076                                      nsACString& outString,
00077                                      PRBool aIsCharsetCanonical)
00078 {
00079   if (inString.IsEmpty()) {
00080     outString.Truncate();
00081     return NS_OK;
00082   }
00083   // Note: this will hide a possible error when the unicode text may contain more than one charset.
00084   // (e.g. Latin1 + Japanese). Use nsMsgI18NSaveAsCharset instead to avoid that problem.
00085   else if (!*aCharset || !PL_strcasecmp(aCharset, "us-ascii") ||
00086            !PL_strcasecmp(aCharset, "ISO-8859-1")) {
00087     LossyCopyUTF16toASCII(inString, outString);
00088     return NS_OK;
00089   }
00090   else if (!PL_strcasecmp(aCharset, "UTF-8")) {
00091     CopyUTF16toUTF8(inString, outString);
00092     return NS_OK;
00093   }
00094 
00095   nsresult rv;
00096   nsCOMPtr <nsICharsetConverterManager> ccm = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
00097   NS_ENSURE_SUCCESS(rv, rv);
00098   nsCOMPtr <nsIUnicodeEncoder> encoder;
00099 
00100   // get an unicode converter
00101   if (aIsCharsetCanonical)  // optimize for modified UTF-7 used by IMAP
00102     rv = ccm->GetUnicodeEncoderRaw(aCharset, getter_AddRefs(encoder));
00103   else
00104     rv = ccm->GetUnicodeEncoder(aCharset, getter_AddRefs(encoder));
00105   NS_ENSURE_SUCCESS(rv, rv);
00106   rv = encoder->SetOutputErrorBehavior(nsIUnicodeEncoder::kOnError_Replace, nsnull, '?');
00107   NS_ENSURE_SUCCESS(rv, rv);
00108 
00109   const PRUnichar *originalSrcPtr = inString.get();
00110   const PRUnichar *currentSrcPtr = originalSrcPtr;
00111   PRInt32 originalUnicharLength = inString.Length();
00112   PRInt32 srcLength;
00113   PRInt32 dstLength;
00114   char localbuf[512];
00115   PRInt32 consumedLen = 0;
00116 
00117   outString.Truncate();
00118   // convert
00119   while (consumedLen < originalUnicharLength) {
00120     srcLength = originalUnicharLength - consumedLen;  
00121     dstLength = 512;
00122     rv = encoder->Convert(currentSrcPtr, &srcLength, localbuf, &dstLength);
00123     if (NS_FAILED(rv) || dstLength == 0)
00124       break;
00125     outString.Append(localbuf, dstLength);
00126 
00127     currentSrcPtr += srcLength;
00128     consumedLen = currentSrcPtr - originalSrcPtr; // src length used so far
00129   }
00130   rv = encoder->Finish(localbuf, &dstLength);
00131   if (NS_SUCCEEDED(rv))
00132     outString.Append(localbuf, dstLength);
00133   return rv;
00134 }
00135 
00136 nsresult nsMsgI18NConvertToUnicode(const char* aCharset,
00137                                    const nsAFlatCString& inString, 
00138                                    nsAString& outString,
00139                                    PRBool aIsCharsetCanonical)
00140 {
00141   if (inString.IsEmpty()) {
00142     outString.Truncate();
00143     return NS_OK;
00144   }
00145   else if (!*aCharset || !PL_strcasecmp(aCharset, "us-ascii") ||
00146            !PL_strcasecmp(aCharset, "ISO-8859-1")) {
00147     // Despite its name, it also works for Latin-1.
00148     CopyASCIItoUTF16(inString, outString);
00149     return NS_OK;
00150   }
00151   else if (!PL_strcasecmp(aCharset, "UTF-8")) {
00152     if (IsUTF8(inString)) {
00153       nsAutoString tmp;
00154       CopyUTF8toUTF16(inString, tmp);
00155       if (!tmp.IsEmpty() && tmp.get()[0] == PRUnichar(0xFEFF))
00156         tmp.Cut(0, 1);
00157       outString.Assign(tmp);
00158       return NS_OK;
00159     }
00160     NS_WARNING("Invalid UTF-8 string");
00161     return NS_ERROR_UNEXPECTED;
00162   }
00163 
00164   nsresult rv;
00165   nsCOMPtr <nsICharsetConverterManager> ccm = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
00166   NS_ENSURE_SUCCESS(rv, rv);
00167 
00168   nsCOMPtr <nsIUnicodeDecoder> decoder;
00169 
00170   // get an unicode converter
00171   if (aIsCharsetCanonical)  // optimize for modified UTF-7 used by IMAP
00172     rv = ccm->GetUnicodeDecoderRaw(aCharset, getter_AddRefs(decoder));
00173   else
00174     rv = ccm->GetUnicodeDecoder(aCharset, getter_AddRefs(decoder));
00175   NS_ENSURE_SUCCESS(rv, rv);
00176 
00177   const char *originalSrcPtr = inString.get();
00178   const char *currentSrcPtr = originalSrcPtr;
00179   PRInt32 originalLength = inString.Length();
00180   PRInt32 srcLength;
00181   PRInt32 dstLength;
00182   PRUnichar localbuf[512];
00183   PRInt32 consumedLen = 0;
00184 
00185   outString.Truncate();
00186 
00187   // convert
00188   while (consumedLen < originalLength) {
00189     srcLength = originalLength - consumedLen;  
00190     dstLength = 512;
00191     rv = decoder->Convert(currentSrcPtr, &srcLength, localbuf, &dstLength);
00192     if (NS_FAILED(rv) || dstLength == 0)
00193       break;
00194     outString.Append(localbuf, dstLength);
00195 
00196     currentSrcPtr += srcLength;
00197     consumedLen = currentSrcPtr - originalSrcPtr; // src length used so far
00198   }
00199   return rv;
00200 }
00201 
00202 // Charset used by the file system.
00203 const char * nsMsgI18NFileSystemCharset()
00204 {
00205        /* Get a charset used for the file. */
00206        static nsCAutoString fileSystemCharset;
00207 
00208        if (fileSystemCharset.IsEmpty()) 
00209        {
00210               nsresult rv;
00211               nsCOMPtr <nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
00212         if (NS_SUCCEEDED(rv)) {
00213           rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName,
00214                                            fileSystemCharset);
00215         }
00216 
00217               if (NS_FAILED(rv)) 
00218                      fileSystemCharset.Assign("ISO-8859-1");
00219        }
00220        return fileSystemCharset.get();
00221 }
00222 
00223 // Charset used by the text file.
00224 void nsMsgI18NTextFileCharset(nsACString& aCharset)
00225 {
00226   nsresult rv;
00227   nsCOMPtr <nsIPlatformCharset> platformCharset =
00228     do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
00229   if (NS_SUCCEEDED(rv)) {
00230     rv = platformCharset->GetCharset(kPlatformCharsetSel_PlainTextInFile,
00231                                      aCharset);
00232   }
00233 
00234   if (NS_FAILED(rv))
00235     aCharset.Assign("ISO-8859-1");
00236 }
00237 
00238 // MIME encoder, output string should be freed by PR_FREE
00239 // XXX : fix callers later to avoid allocation and copy
00240 char * nsMsgI18NEncodeMimePartIIStr(const char *header, PRBool structured, const char *charset, PRInt32 fieldnamelen, PRBool usemime) 
00241 {
00242   // No MIME, convert to the outgoing mail charset.
00243   if (PR_FALSE == usemime) {
00244     nsCAutoString convertedStr;
00245     if (NS_SUCCEEDED(ConvertFromUnicode(charset, NS_ConvertUTF8toUTF16(header),
00246                                         convertedStr)))
00247       return PL_strdup(convertedStr.get());
00248     else
00249       return PL_strdup(header);
00250   }
00251 
00252   char *encodedString = nsnull;
00253   nsresult res;
00254   nsCOMPtr<nsIMimeConverter> converter = do_GetService(NS_MIME_CONVERTER_CONTRACTID, &res);
00255   if (NS_SUCCEEDED(res) && nsnull != converter)
00256     res = converter->EncodeMimePartIIStr_UTF8(header, structured, charset, fieldnamelen, kMIME_ENCODED_WORD_SIZE, &encodedString);
00257 
00258   return NS_SUCCEEDED(res) ? encodedString : nsnull;
00259 }
00260 
00261 // Return True if a charset is stateful (e.g. JIS).
00262 PRBool nsMsgI18Nstateful_charset(const char *charset)
00263 {
00264   //TODO: use charset manager's service
00265   return (nsCRT::strcasecmp(charset, "ISO-2022-JP") == 0);
00266 }
00267 
00268 PRBool nsMsgI18Nmultibyte_charset(const char *charset)
00269 {
00270   nsresult res;
00271   nsCOMPtr <nsICharsetConverterManager> ccm = do_GetService(kCharsetConverterManagerCID, &res);
00272   PRBool result = PR_FALSE;
00273 
00274   if (NS_SUCCEEDED(res)) {
00275     nsAutoString charsetData;
00276     res = ccm->GetCharsetData(charset, NS_LITERAL_STRING(".isMultibyte").get(), charsetData);
00277     if (NS_SUCCEEDED(res)) {
00278       result = charsetData.LowerCaseEqualsLiteral("true");
00279     }
00280   }
00281 
00282   return result;
00283 }
00284 
00285 
00286 PRBool nsMsgI18Ncheck_data_in_charset_range(const char *charset, const PRUnichar* inString, char **fallbackCharset)
00287 {
00288   if (!charset || !*charset || !inString || !*inString)
00289     return PR_TRUE;
00290 
00291   nsresult res;
00292   PRBool result = PR_TRUE;
00293   
00294   nsCOMPtr <nsICharsetConverterManager> ccm = do_GetService(kCharsetConverterManagerCID, &res);
00295 
00296   if (NS_SUCCEEDED(res)) {
00297     nsCOMPtr <nsIUnicodeEncoder> encoder;
00298 
00299     // get an unicode converter
00300     res = ccm->GetUnicodeEncoderRaw(charset, getter_AddRefs(encoder));
00301     if(NS_SUCCEEDED(res)) {
00302       const PRUnichar *originalPtr = inString;
00303       PRInt32 originalLen = nsCRT::strlen(inString);
00304       const PRUnichar *currentSrcPtr = originalPtr;
00305       char localBuff[512];
00306       PRInt32 consumedLen = 0;
00307       PRInt32 srcLen;
00308       PRInt32 dstLength;
00309 
00310       // convert from unicode
00311       while (consumedLen < originalLen) {
00312         srcLen = originalLen - consumedLen;
00313         dstLength = 512;
00314         res = encoder->Convert(currentSrcPtr, &srcLen, localBuff, &dstLength);
00315         if (NS_ERROR_UENC_NOMAPPING == res) {
00316           result = PR_FALSE;
00317           break;
00318         }
00319         else if (NS_FAILED(res) || (0 == dstLength))
00320           break;
00321 
00322         currentSrcPtr += srcLen;
00323         consumedLen = currentSrcPtr - originalPtr; // src length used so far
00324       }
00325     }    
00326   }
00327 
00328   // if the conversion was not successful then try fallback to other charsets
00329   if (!result && fallbackCharset) {
00330     nsXPIDLCString convertedString;
00331     res = nsMsgI18NSaveAsCharset("text/plain", charset, inString, 
00332                                  getter_Copies(convertedString), fallbackCharset);
00333     result = (NS_SUCCEEDED(res) && NS_ERROR_UENC_NOMAPPING != res);
00334   }
00335 
00336   return result;
00337 }
00338 
00339 // Simple parser to parse META charset. 
00340 // It only supports the case when the description is within one line. 
00341 const char * 
00342 nsMsgI18NParseMetaCharset(nsFileSpec* fileSpec) 
00343 { 
00344   static char charset[kMAX_CSNAME+1]; 
00345   char buffer[512]; 
00346 
00347   *charset = '\0'; 
00348 
00349   if (fileSpec->IsDirectory()) {
00350     NS_ASSERTION(0,"file is a directory");
00351     return charset; 
00352   }
00353 
00354   nsInputFileStream fileStream(*fileSpec); 
00355 
00356   while (!fileStream.eof() && !fileStream.failed() && 
00357          fileStream.is_open()) { 
00358     fileStream.readline(buffer, 512); 
00359     if (*buffer == nsCRT::CR || *buffer == nsCRT::LF || *buffer == 0) 
00360       continue; 
00361 
00362     PRUint32 len = PL_strlen(buffer);
00363     for (PRUint32 i = 0; i < len; i++) { 
00364       buffer[i] = toupper(buffer[i]); 
00365     } 
00366 
00367     if (PL_strstr(buffer, "/HEAD")) 
00368       break; 
00369 
00370     if (PL_strstr(buffer, "META") && 
00371         PL_strstr(buffer, "HTTP-EQUIV") && 
00372         PL_strstr(buffer, "CONTENT-TYPE") && 
00373         PL_strstr(buffer, "CHARSET")) { 
00374       char *cp = PL_strstr(PL_strstr(buffer, "CHARSET"), "=");
00375       char *newStr;
00376       char *token = cp ? nsCRT::strtok(cp + 1, " \"\'", &newStr) : nsnull;
00377       if (token) { 
00378         PL_strncpy(charset, token, sizeof(charset));
00379         charset[sizeof(charset)-1] = '\0';
00380 
00381         // this function cannot parse a file if it is really
00382         // encoded by one of the following charsets
00383         // so we can say that the charset label must be incorrect for
00384         // the .html if we actually see those charsets parsed
00385         // and we should ignore them
00386         if (!nsCRT::strncasecmp("UTF-16", charset, sizeof("UTF-16")-1) || 
00387             !nsCRT::strncasecmp("UTF-32", charset, sizeof("UTF-32")-1))
00388           charset[0] = '\0';
00389 
00390         break;
00391       } 
00392     } 
00393   } 
00394 
00395   return charset; 
00396 } 
00397 
00398 nsresult nsMsgI18NConvertToEntity(const nsString& inString, nsString* outString)
00399 {
00400   nsresult res;
00401 
00402   outString->Truncate();
00403   nsCOMPtr <nsIEntityConverter> entityConv = do_CreateInstance(kEntityConverterCID, &res);
00404   if(NS_SUCCEEDED(res)) {
00405     PRUnichar *entities = NULL;
00406     res = entityConv->ConvertToEntities(inString.get(), nsIEntityConverter::html40Latin1, &entities);
00407     if (NS_SUCCEEDED(res) && (NULL != entities))
00408       outString->Adopt(entities);
00409   }
00410  
00411   return res;
00412 }
00413 
00414 nsresult nsMsgI18NSaveAsCharset(const char* contentType, const char *charset, 
00415                                 const PRUnichar* inString, char** outString, 
00416                                 char **fallbackCharset, PRBool *isAsciiOnly)
00417 {
00418   NS_ENSURE_ARG_POINTER(contentType);
00419   NS_ENSURE_ARG_POINTER(charset);
00420   NS_ENSURE_ARG_POINTER(inString);
00421   NS_ENSURE_ARG_POINTER(outString);
00422 
00423   *outString = nsnull;
00424 
00425   if (nsCRT::IsAscii(inString)) {
00426     if (isAsciiOnly)
00427       *isAsciiOnly = PR_TRUE;
00428     *outString = nsCRT::strdup(NS_LossyConvertUTF16toASCII(inString).get());
00429     return (nsnull != *outString) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00430   }
00431   if (isAsciiOnly)
00432     *isAsciiOnly = PR_FALSE;
00433 
00434   PRBool bTEXT_HTML = PR_FALSE;
00435   nsresult res;
00436 
00437   if (!nsCRT::strcasecmp(contentType, TEXT_HTML)) {
00438     bTEXT_HTML = PR_TRUE;
00439   }
00440   else if (nsCRT::strcasecmp(contentType, TEXT_PLAIN)) {
00441     return NS_ERROR_ILLEGAL_VALUE;  // not supported type
00442   }
00443 
00444   nsCOMPtr <nsICharsetAlias> calias =
00445     do_GetService(NS_CHARSETALIAS_CONTRACTID, &res);
00446   NS_ENSURE_SUCCESS(res, res);
00447 
00448   nsCAutoString charsetName;
00449   res = calias->GetPreferred(nsDependentCString(charset),
00450                              charsetName);
00451   NS_ENSURE_SUCCESS(res, res);
00452 
00453   // charset converter plus entity, NCR generation
00454   nsCOMPtr <nsISaveAsCharset> conv = do_CreateInstance(NS_SAVEASCHARSET_CONTRACTID, &res);
00455   NS_ENSURE_SUCCESS(res, res);
00456 
00457   // attribute: 
00458   // html text - charset conv then fallback to entity or NCR
00459   // plain text - charset conv then fallback to '?'
00460   if (bTEXT_HTML)
00461     // For ISO-8859-1 only, convert to entity first (always generate entites like &nbsp;).
00462     res = conv->Init(charsetName.get(),
00463                      charsetName.EqualsLiteral("ISO-8859-1") ?
00464                      nsISaveAsCharset::attr_htmlTextDefault :
00465                      nsISaveAsCharset::attr_EntityAfterCharsetConv + nsISaveAsCharset::attr_FallbackDecimalNCR, 
00466                      nsIEntityConverter::html32);
00467   else
00468     // fallback for text/plain: first try transliterate then '?'
00469     res = conv->Init(charsetName.get(), 
00470                      nsISaveAsCharset::attr_FallbackQuestionMark + nsISaveAsCharset::attr_EntityAfterCharsetConv, 
00471                      nsIEntityConverter::transliterate);
00472   NS_ENSURE_SUCCESS(res, res);
00473 
00474   const PRUnichar *input = inString;
00475 
00476   // Mapping characters in a certain range (required for Japanese only)
00477   nsAutoString mapped;
00478   if (charsetName.EqualsLiteral("ISO-2022-JP")) {
00479     static PRInt32 sSendHankakuKana = -1;
00480     if (sSendHankakuKana < 0) {
00481       nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &res));
00482       NS_ENSURE_SUCCESS(res, res);
00483       PRBool sendHankaku;
00484       // Get a hidden 4.x pref with no UI, get it only once.
00485       if (NS_FAILED(prefBranch->GetBoolPref("mailnews.send_hankaku_kana", &sendHankaku)))
00486         sSendHankakuKana = 0;  // no pref means need the mapping
00487       else
00488         sSendHankakuKana = sendHankaku ? 1 : 0;
00489     }
00490 
00491     if (!sSendHankakuKana) {
00492       nsCOMPtr <nsITextTransform> textTransform = do_CreateInstance(NS_HANKAKUTOZENKAKU_CONTRACTID, &res);
00493         
00494       if (NS_SUCCEEDED(res)) {
00495         res = textTransform->Change(inString, nsCRT::strlen(inString), mapped);
00496         if (NS_SUCCEEDED(res))
00497           input = mapped.get();
00498       }
00499     }
00500   }
00501 
00502   // Convert to charset
00503   res = conv->Convert(input, outString);
00504 
00505   // If the converer cannot encode to the charset,
00506   // then fallback to pref sepcified charsets.
00507   if (NS_ERROR_UENC_NOMAPPING == res && !bTEXT_HTML && fallbackCharset) {
00508     nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &res));
00509     NS_ENSURE_SUCCESS(res, res);
00510 
00511     nsCAutoString prefString("intl.fallbackCharsetList.");
00512     prefString.Append(charset);
00513     nsXPIDLCString fallbackList;
00514     res = prefBranch->GetCharPref(prefString.get(), getter_Copies(fallbackList));
00515     // do the fallback only if there is a pref for the charset
00516     if (NS_FAILED(res) || fallbackList.IsEmpty())
00517       return NS_ERROR_UENC_NOMAPPING;
00518 
00519     res = conv->Init(fallbackList.get(), 
00520                      nsISaveAsCharset::attr_FallbackQuestionMark + 
00521                      nsISaveAsCharset::attr_EntityAfterCharsetConv +
00522                      nsISaveAsCharset::attr_CharsetFallback, 
00523                      nsIEntityConverter::transliterate);
00524     NS_ENSURE_SUCCESS(res, res);
00525 
00526     // free whatever we have now
00527     PR_FREEIF(*outString);  
00528 
00529     res = conv->Convert(input, outString);
00530     NS_ENSURE_SUCCESS(res, res);
00531 
00532     // get the actual charset used for the conversion
00533     if (NS_FAILED(conv->GetCharset(fallbackCharset)))
00534       *fallbackCharset = nsnull;
00535   }
00536   // In case of HTML, non ASCII may be encoded as CER, NCR.
00537   // Exclude stateful charset which is 7 bit but not ASCII only.
00538   else if (isAsciiOnly && bTEXT_HTML && *outString &&
00539            !nsMsgI18Nstateful_charset(charsetName.get()))
00540     *isAsciiOnly = nsCRT::IsAscii(*outString);
00541 
00542   return res;
00543 }
00544 
00545 nsresult nsMsgI18NFormatNNTPXPATInNonRFC1522Format(const nsCString& aCharset, 
00546                                                    const nsString& inString, 
00547                                                    nsCString& outString)
00548 {
00549   outString.AssignWithConversion(inString);
00550   return NS_OK;
00551 }
00552 
00553 const char *
00554 nsMsgI18NGetAcceptLanguage(void)
00555 {
00556   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID)); 
00557   if (prefBranch)
00558   {
00559     nsCOMPtr<nsIPrefLocalizedString> prefString;
00560 
00561     prefBranch->GetComplexValue("intl.accept_languages",
00562                                 NS_GET_IID(nsIPrefLocalizedString),
00563                                 getter_AddRefs(prefString));
00564     if (prefString)
00565     {
00566       nsXPIDLString ucsval;
00567       prefString->ToString(getter_Copies(ucsval));
00568       if (!ucsval.IsEmpty())
00569       {
00570         static nsCAutoString acceptLang;
00571         LossyCopyUTF16toASCII(ucsval, acceptLang);
00572         return acceptLang.get();
00573       }
00574     }
00575   }
00576 
00577   // Default Accept-Language
00578   return "en";
00579 }
00580