Bug 145293 - Import in text format (txt,csv,tab): Should support non-ascii display names and email addresses. r=bienvenu
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Tue, 10 Jul 2012 17:12:42 -0400
changeset 12835 c9097070b4135b14d1088c64413fd4ada2f98c6c
parent 12834 af0fb78b4713f39b3870c9e5e8a7cdc8bda9e55e
child 12836 e6d59effc2e1ea73cd2e160be9f08716ab1ca03f
push idunknown
push userunknown
push dateunknown
reviewersbienvenu
bugs145293
Bug 145293 - Import in text format (txt,csv,tab): Should support non-ascii display names and email addresses. r=bienvenu
mailnews/import/text/src/nsTextAddress.cpp
mailnews/import/text/src/nsTextAddress.h
mailnews/import/text/src/nsTextImport.cpp
--- a/mailnews/import/text/src/nsTextAddress.cpp
+++ b/mailnews/import/text/src/nsTextAddress.cpp
@@ -8,16 +8,19 @@
 #include "nsIAddrDatabase.h"
 #include "nsNativeCharsetUtils.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
 #include "nsILineInputStream.h"
 #include "nsNetUtil.h"
 #include "nsMsgUtils.h"
 #include "mdb.h"
+#include "nsIConverterInputStream.h"
+#include "nsIUnicharLineInputStream.h"
+#include "nsMsgUtils.h"
 
 #include "TextDebugLog.h"
 #include "plstr.h"
 #include "msgCore.h"
 
 #ifndef MOZILLA_INTERNAL_API
 #include "nsMsgI18N.h"
 #define NS_CopyNativeToUnicode(source, dest) \
@@ -35,16 +38,39 @@ nsTextAddress::nsTextAddress()
 }
 
 nsTextAddress::~nsTextAddress()
 {
     NS_IF_RELEASE(m_database);
     NS_IF_RELEASE(m_fieldMap);
 }
 
+nsresult nsTextAddress::GetUnicharLineStreamForFile(nsIFile *aFile,
+                                                    nsIInputStream *aInputStream,
+                                                    nsIUnicharLineInputStream **aStream)
+{
+  nsCAutoString charset;
+  nsresult rv = MsgDetectCharsetFromFile(aFile, charset);
+  if (NS_FAILED(rv)) {
+    IMPORT_LOG0( "*** Error checking address file for charset detection\n");
+    return rv;
+  }
+
+  nsCOMPtr<nsIConverterInputStream> converterStream =
+    do_CreateInstance("@mozilla.org/intl/converter-input-stream;1", &rv);
+  if (NS_SUCCEEDED(rv)) {
+    rv = converterStream->Init(aInputStream,
+                               charset.get(),
+                               8192,
+                               nsIConverterInputStream::DEFAULT_REPLACEMENT_CHARACTER);
+  }
+
+  return CallQueryInterface(converterStream, aStream);
+}
+
 nsresult nsTextAddress::ImportAddresses(bool *pAbort, const PRUnichar *pName, nsIFile *pSrc, nsIAddrDatabase *pDb, nsIImportFieldMap *fieldMap, nsString& errors, PRUint32 *pProgress)
 {
   // Open the source file for reading, read each line and process it!
   NS_IF_RELEASE(m_database);
   NS_IF_RELEASE(m_fieldMap);
   m_database = pDb;
   m_fieldMap = fieldMap;
   NS_ADDREF(m_fieldMap);
@@ -72,32 +98,36 @@ nsresult nsTextAddress::ImportAddresses(
   bool skipRecord = false;
 
   rv = m_fieldMap->GetSkipFirstRecord(&skipRecord);
   if (NS_FAILED(rv)) {
     IMPORT_LOG0("*** Error checking to see if we should skip the first record\n");
     return rv;
   }
 
-  nsCOMPtr<nsILineInputStream> lineStream(do_QueryInterface(inputStream, &rv));
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIUnicharLineInputStream> lineStream;
+  rv = GetUnicharLineStreamForFile(pSrc, inputStream, getter_AddRefs(lineStream));
+  if (NS_FAILED(rv)) {
+    IMPORT_LOG0("*** Error opening converter stream for importer\n");
+    return rv;
+  }
 
   bool more = true;
-  nsCString line;
+  nsAutoString line;
 
   // Skip the first record if the user has requested it.
   if (skipRecord)
     rv = ReadRecord(lineStream, line, &more);
 
   while (!(*pAbort) && more && NS_SUCCEEDED(rv)) {
     // Read the line in
     rv = ReadRecord(lineStream, line, &more);
     if (NS_SUCCEEDED(rv)) {
       // Now proces it to add it to the database
-      rv = ProcessLine(line.get(), line.Length(), errors);
+      rv = ProcessLine(line, errors);
 
       if (NS_FAILED(rv)) {
         IMPORT_LOG0("*** Error processing text record.\n");
       }
     }
     if (NS_SUCCEEDED(rv) && pProgress) {
       // This won't be totally accurate, but its the best we can do
       // considering that lineStream won't give us how many bytes
@@ -112,22 +142,24 @@ nsresult nsTextAddress::ImportAddresses(
   if (NS_FAILED(rv)) {
     IMPORT_LOG0("*** Error reading the address book - probably incorrect ending\n");
     return NS_ERROR_FAILURE;
   }
 
   return pDb->Commit(nsAddrDBCommitType::kLargeCommit);
 }
 
-nsresult nsTextAddress::ReadRecord(nsILineInputStream *aLineStream, nsCString &aLine, bool *aMore)
+nsresult nsTextAddress::ReadRecord(nsIUnicharLineInputStream *aLineStream,
+                                   nsAString &aLine,
+                                   bool *aMore)
 {
   bool more = true;
   PRUint32 numQuotes = 0;
   nsresult rv;
-  nsCString line;
+  nsAutoString line;
 
   // ensure aLine is empty
   aLine.Truncate();
 
   do {
     if (!more) {
       // No more, so we must have an incorrect file.
       rv = NS_ERROR_FAILURE;
@@ -135,27 +167,27 @@ nsresult nsTextAddress::ReadRecord(nsILi
     else {
       // Read the line and append it
       rv = aLineStream->ReadLine(line, &more);
       if (NS_SUCCEEDED(rv)) {
         if (!aLine.IsEmpty())
           aLine.AppendLiteral(MSG_LINEBREAK);
         aLine.Append(line);
 
-        numQuotes += MsgCountChar(line, '"');
+        numQuotes += line.CountChar(PRUnichar('"'));
       }
     }
     // Continue whilst everything is ok, and we have an odd number of quotes.
   } while (NS_SUCCEEDED(rv) && (numQuotes % 2 != 0));
 
   *aMore = more;
   return rv;
 }
 
-nsresult nsTextAddress::ReadRecordNumber(nsIFile *aSrc, nsCString &aLine, PRInt32 rNum)
+nsresult nsTextAddress::ReadRecordNumber(nsIFile *aSrc, nsAString &aLine, PRInt32 rNum)
 {
   nsCOMPtr<nsIInputStream> inputStream;
   nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), aSrc);
   if (NS_FAILED(rv)) {
     IMPORT_LOG0("*** Error opening address file for reading\n");
     return rv;
   }
 
@@ -164,18 +196,22 @@ nsresult nsTextAddress::ReadRecordNumber
 
   rv = inputStream->Available(&bytesLeft);
   if (NS_FAILED(rv)) {
     IMPORT_LOG0("*** Error checking address file for eof\n");
     inputStream->Close();
     return rv;
   }
 
-  nsCOMPtr<nsILineInputStream> lineStream(do_QueryInterface(inputStream, &rv));
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIUnicharLineInputStream> lineStream;
+  rv = GetUnicharLineStreamForFile(aSrc, inputStream, getter_AddRefs(lineStream));
+  if (NS_FAILED(rv)) {
+    IMPORT_LOG0("*** Error opening converter stream for importer\n");
+    return rv;
+  }
 
   bool more = true;
 
   while (more && (rIndex <= rNum)) {
     rv = ReadRecord(lineStream, aLine, &more);
     if (NS_FAILED(rv)) {
       inputStream->Close();
       return rv;
@@ -186,158 +222,147 @@ nsresult nsTextAddress::ReadRecordNumber
     }
 
     rIndex++;
   }
 
   return NS_ERROR_FAILURE;
 }
 
-PRInt32 nsTextAddress::CountFields(const char *pLine, PRInt32 maxLen, char delim)
+PRInt32 nsTextAddress::CountFields(const nsAString &aLine, PRUnichar delim)
 {
-    const char *pChar = pLine;
-    PRInt32 len = 0;
+    PRInt32 pos = 0;
+    PRInt32 maxLen = aLine.Length();
     PRInt32 count = 0;
-    char tab = '\t';
+    PRUnichar tab = PRUnichar('\t');
+    PRUnichar doubleQuote = PRUnichar('"');
 
     if (delim == tab)
-        tab = 0;
+        tab = PRUnichar('\0');
 
-    while (len < maxLen) {
-        while (((*pChar == ' ') || (*pChar == tab)) && (len < maxLen)) {
-            pChar++;
-            len++;
+    while (pos < maxLen) {
+        while (((aLine[pos] == PRUnichar(' ')) || (aLine[pos] == tab)) &&
+               (pos < maxLen)) {
+            pos++;
         }
-        if ((len < maxLen) && (*pChar == '"')) {
-            pChar++;
-            len++;
-            while ((len < maxLen) && (*pChar != '"')) {
-                len++;
-                pChar++;
-                if (((len + 1) < maxLen) && (*pChar == '"') && (*(pChar + 1) == '"')) {
-                    len += 2;
-                    pChar += 2;
+        if ((pos < maxLen) && (aLine[pos] == doubleQuote)) {
+            pos++;
+            while ((pos < maxLen) && (aLine[pos] != doubleQuote)) {
+                pos++;
+                if (((pos + 1) < maxLen) &&
+                    (aLine[pos] == doubleQuote) &&
+                    (aLine[pos + 1] == doubleQuote)) {
+                    pos += 2;
                 }
             }
-            if (len < maxLen) {
-                pChar++;
-                len++;
-            }
+            if (pos < maxLen)
+                pos++;
         }
-        while ((len < maxLen) && (*pChar != delim)) {
-            len++;
-            pChar++;
-        }
+        while ((pos < maxLen) && (aLine[pos] != delim))
+            pos++;
 
         count++;
-        pChar++;
-        len++;
+        pos++;
     }
 
     return count;
 }
 
-bool nsTextAddress::GetField(const char *pLine, PRInt32 maxLen, PRInt32 index, nsCString& field, char delim)
+bool nsTextAddress::GetField(const nsAString &aLine,
+                             PRInt32 index,
+                             nsString &field,
+                             PRUnichar delim)
 {
     bool result = false;
-    const char *pChar = pLine;
-    PRInt32 len = 0;
-    char tab = '\t';
+    PRInt32 pos = 0;
+    PRInt32 maxLen = aLine.Length();
+    PRUnichar tab = PRUnichar('\t');
+    PRUnichar doubleQuote = PRUnichar('"');
 
     field.Truncate();
 
     if (delim == tab)
         tab = 0;
 
-    while (index && (len < maxLen)) {
-        while (((*pChar == ' ') || (*pChar == tab)) && (len < maxLen)) {
-            pChar++;
-            len++;
+    while (index && (pos < maxLen)) {
+        while (((aLine[pos] == PRUnichar(' ')) || (aLine[pos] == tab)) &&
+               (pos < maxLen)) {
+            pos++;
         }
-        if (len >= maxLen)
+        if (pos >= maxLen)
             break;
-        if (*pChar == '"') {
+        if (aLine[pos] == doubleQuote) {
             do {
-                len++;
-                pChar++;
-                if (((len + 1) < maxLen) && (*pChar == '"') && (*(pChar + 1) == '"')) {
-                    len += 2;
-                    pChar += 2;
+                pos++;
+                if (((pos + 1) < maxLen) &&
+                    (aLine[pos] == doubleQuote) &&
+                    (aLine[pos + 1] == doubleQuote)) {
+                    pos += 2;
                 }
-            } while ((len < maxLen) && (*pChar != '"'));
-            if (len < maxLen) {
-                pChar++;
-                len++;
-            }
+            } while ((pos < maxLen) && (aLine[pos] != doubleQuote));
+            if (pos < maxLen)
+                pos++;
         }
-        if (len >= maxLen)
+        if (pos >= maxLen)
             break;
 
-        while ((len < maxLen) && (*pChar != delim)) {
-            len++;
-            pChar++;
-        }
+        while ((pos < maxLen) && (aLine[pos] != delim))
+            pos++;
 
-        if (len >= maxLen)
+        if (pos >= maxLen)
             break;
 
         index--;
-        pChar++;
-        len++;
+        pos++;
     }
 
-    if (len >= maxLen) {
+    if (pos >= maxLen)
         return result;
-    }
 
     result = true;
 
-    while ((len < maxLen) && ((*pChar == ' ') || (*pChar == tab))) {
-        len++;
-        pChar++;
-    }
+    while ((pos < maxLen) && ((aLine[pos] == ' ') || (aLine[pos] == tab)))
+        pos++;
 
-    const char *pStart = pChar;
-    PRInt32        fLen = 0;
-    bool          quoted = false;
-    if (*pChar == '"') {
-        pStart++;
+    PRInt32 fLen = 0;
+    PRInt32 startPos = pos;
+    bool    quoted = false;
+    if (aLine[pos] == '"') {
         fLen = -1;
         do {
-            pChar++;
-            len++;
+            pos++;
             fLen++;
-            if (((len + 1) < maxLen) && (*pChar == '"') && (*(pChar + 1) == '"')) {
+            if (((pos + 1) < maxLen) &&
+                (aLine[pos] == doubleQuote) &&
+                (aLine[pos + 1] == doubleQuote)) {
                 quoted = true;
-                len += 2;
-                pChar += 2;
+                pos += 2;
                 fLen += 2;
             }
-        } while ((len < maxLen) && (*pChar != '"'));
+        } while ((pos < maxLen) && (aLine[pos] != doubleQuote));
     }
     else {
-        while ((len < maxLen) && (*pChar != delim)) {
-            pChar++;
-            len++;
+        while ((pos < maxLen) && (aLine[pos] != delim)) {
+            pos++;
             fLen++;
         }
     }
 
     if (!fLen) {
         return result;
     }
 
-    field.Append(pStart, fLen);
+    field.Append(nsDependentSubstring(aLine, startPos, fLen));
     field.Trim(kWhitespace);
 
     if (quoted) {
       PRInt32 offset = field.Find(NS_LITERAL_CSTRING("\"\""));
       while (offset != -1) {
         field.Cut(offset, 1);
-        offset = field.Find(NS_LITERAL_CSTRING("\"\""), offset + 1);
+        offset = field.Find(NS_LITERAL_STRING("\"\""), offset + 1);
       }
     }
 
     return result;
 }
 
 nsresult nsTextAddress::DetermineDelim(nsIFile *aSrc)
 {
@@ -348,86 +373,88 @@ nsresult nsTextAddress::DetermineDelim(n
     return rv;
   }
 
   PRInt32 lineCount = 0;
   PRInt32 tabCount = 0;
   PRInt32 commaCount = 0;
   PRInt32 tabLines = 0;
   PRInt32 commaLines = 0;
-  nsCAutoString line;
+  nsAutoString line;
   bool more = true;
 
-  nsCOMPtr<nsILineInputStream> lineStream(do_QueryInterface(inputStream, &rv));
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIUnicharLineInputStream> lineStream;
+  rv = GetUnicharLineStreamForFile(aSrc, inputStream, getter_AddRefs(lineStream));
+  if (NS_FAILED(rv)) {
+    IMPORT_LOG0("*** Error opening converter stream for importer\n");
+    return rv;
+  }
 
   while (more && NS_SUCCEEDED(rv) && (lineCount < 100)) {
     rv = lineStream->ReadLine(line, &more);
     if (NS_SUCCEEDED(rv)) {
-      tabCount = CountFields(line.get(), line.Length(), '\t');
-      commaCount = CountFields(line.get(), line.Length(), ',');
+      tabCount = CountFields(line, PRUnichar('\t'));
+      commaCount = CountFields(line, PRUnichar(','));
       if (tabCount > commaCount)
         tabLines++;
       else if (commaCount)
         commaLines++;
     }
     lineCount++;
   }
 
   rv = inputStream->Close();
 
   if (tabLines > commaLines)
-    m_delim = '\t';
+    m_delim = PRUnichar('\t');
   else
-    m_delim = ',';
+    m_delim = PRUnichar(',');
 
   IMPORT_LOG2( "Tab count = %d, Comma count = %d\n", tabLines, commaLines);
 
   return rv;
 }
 
 /*
     This is where the real work happens!
     Go through the field map and set the data in a new database row
 */
-nsresult nsTextAddress::ProcessLine(const char *pLine, PRInt32 len, nsString& errors)
+nsresult nsTextAddress::ProcessLine(const nsAString &aLine, nsString& errors)
 {
     if (!m_fieldMap) {
         IMPORT_LOG0("*** Error, text import needs a field map\n");
         return NS_ERROR_FAILURE;
     }
 
     nsresult rv;
 
     // Wait until we get our first non-empty field, then create a new row,
     // fill in the data, then add the row to the database.
     nsCOMPtr<nsIMdbRow> newRow;
-    nsString    uVal;
-    nsCString    fieldVal;
+    nsAutoString   fieldVal;
     PRInt32        fieldNum;
     PRInt32        numFields = 0;
-    bool          active;
+    bool           active;
     rv = m_fieldMap->GetMapSize(&numFields);
     for (PRInt32 i = 0; (i < numFields) && NS_SUCCEEDED(rv); i++) {
         active = false;
         rv = m_fieldMap->GetFieldMap(i, &fieldNum);
         if (NS_SUCCEEDED(rv))
             rv = m_fieldMap->GetFieldActive(i, &active);
         if (NS_SUCCEEDED(rv) && active) {
-            if (GetField(pLine, len, i, fieldVal, m_delim)) {
+            if (GetField(aLine, i, fieldVal, m_delim)) {
                 if (!fieldVal.IsEmpty()) {
                     if (!newRow) {
                         rv = m_database->GetNewRow(getter_AddRefs(newRow));
                         if (NS_FAILED(rv)) {
                             IMPORT_LOG0("*** Error getting new address database row\n");
                         }
                     }
                     if (newRow) {
-                        NS_CopyNativeToUnicode(fieldVal, uVal);
-                        rv = m_fieldMap->SetFieldValue(m_database, newRow, fieldNum, uVal.get());
+                        rv = m_fieldMap->SetFieldValue(m_database, newRow, fieldNum, fieldVal.get());
                     }
                 }
             }
             else
                 break;
         }
         else if (active) {
           IMPORT_LOG1("*** Error getting field map for index %ld\n", (long) i);
--- a/mailnews/import/text/src/nsTextAddress.h
+++ b/mailnews/import/text/src/nsTextAddress.h
@@ -10,42 +10,45 @@
 #include "nsCOMPtr.h"
 #include "nsStringGlue.h"
 #include "nsIImportFieldMap.h"
 #include "nsIImportService.h"
 
 class nsIAddrDatabase;
 class nsIFile;
 class nsIInputStream;
-class nsILineInputStream;
+class nsIUnicharLineInputStream;
 
 /////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////
 
 class nsTextAddress {
 public:
   nsTextAddress();
   virtual ~nsTextAddress();
 
   nsresult ImportAddresses(bool *pAbort, const PRUnichar *pName, nsIFile *pSrc, nsIAddrDatabase *pDb, nsIImportFieldMap *fieldMap, nsString& errors, PRUint32 *pProgress);
 
   nsresult DetermineDelim(nsIFile *pSrc);
-  char GetDelim(void) { return m_delim;}
+  PRUnichar GetDelim(void) { return m_delim; }
 
-  static nsresult ReadRecordNumber(nsIFile *pSrc, nsCString &aLine, PRInt32 rNum);
-  static bool GetField(const char *pLine, PRInt32 maxLen, PRInt32 index, nsCString& field, char delim);
+  static nsresult ReadRecordNumber(nsIFile *pSrc, nsAString &aLine, PRInt32 rNum);
+  static bool GetField(const nsAString &aLine, PRInt32 index, nsString &field, PRUnichar delim);
 
 private:
-  nsresult ProcessLine(const char *pLine, PRInt32 len, nsString& errors);
+  nsresult ProcessLine(const nsAString &aLine, nsString &errors);
 
-  static PRInt32 CountFields(const char *pLine, PRInt32 maxLen, char delim);
-  static nsresult ReadRecord(nsILineInputStream *pSrc, nsCString &aLine, bool *aMore);
+  static PRInt32 CountFields(const nsAString &aLine, PRUnichar delim);
+  static nsresult ReadRecord(nsIUnicharLineInputStream *pSrc, nsAString &aLine, bool *aMore);
+  static nsresult GetUnicharLineStreamForFile(nsIFile *aFile,
+                                              nsIInputStream *aInputStream,
+                                              nsIUnicharLineInputStream **aStream);
 
-  char m_delim;
+  PRUnichar m_delim;
   PRInt32 m_LFCount;
   PRInt32 m_CRCount;
   nsIAddrDatabase *m_database;
   nsIImportFieldMap *m_fieldMap;
   nsCOMPtr<nsIImportService> m_pService;
 };
 
 
--- a/mailnews/import/text/src/nsTextImport.cpp
+++ b/mailnews/import/text/src/nsTextImport.cpp
@@ -96,24 +96,24 @@ private:
   void SaveFieldMap(nsIImportFieldMap *pMap);
 
   static void ReportSuccess(nsString& name, nsString *pStream,
                             nsIStringBundle* pBundle);
   static void SetLogs(nsString& success, nsString& error, PRUnichar **pError,
                       PRUnichar **pSuccess);
   static void ReportError(PRInt32 errorNum, nsString& name, nsString *pStream,
                           nsIStringBundle* pBundle);
-  static void SanitizeSampleData(nsCString& val);
+  static void SanitizeSampleData(nsString& val);
 
 private:
   nsTextAddress m_text;
   bool m_haveDelim;
   nsCOMPtr<nsIFile> m_fileLoc;
   nsCOMPtr<nsIStringBundle> m_notProxyBundle;
-  char m_delim;
+  PRUnichar m_delim;
   PRUint32 m_bytesImported;
 };
 
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
 
 nsTextImport::nsTextImport()
 {
@@ -512,23 +512,23 @@ NS_IMETHODIMP ImportAddressImpl::GetNeed
   }
 
   if (isLDIF)
     *_retval = false;
 
   return NS_OK;
 }
 
-void ImportAddressImpl::SanitizeSampleData(nsCString& val)
+void ImportAddressImpl::SanitizeSampleData(nsString& val)
 {
   // remove any line-feeds...
-  PRInt32 offset = val.Find(NS_LITERAL_CSTRING("\x0D\x0A"));
+  PRInt32 offset = val.Find(NS_LITERAL_STRING("\x0D\x0A"));
   while (offset != -1) {
-    val.Replace(offset, 2, ", ");
-    offset = val.Find(NS_LITERAL_CSTRING("\x0D\x0A"), offset + 2);
+    val.Replace(offset, 2, NS_LITERAL_STRING(", "));
+    offset = val.Find(NS_LITERAL_STRING("\x0D\x0A"), offset + 2);
   }
   offset = val.FindChar(13);
   while (offset != -1) {
     val.Replace(offset, 1, ',');
     offset = val.FindChar(13, offset + 2);
   }
   offset = val.FindChar(10);
   while (offset != -1) {
@@ -565,31 +565,27 @@ NS_IMETHODIMP ImportAddressImpl::GetSamp
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!fileExists) {
     *pFound = false;
     *pStr = NS_strdup(&term);
     return NS_OK;
   }
 
-  nsCString line;
+  nsAutoString line;
   rv = nsTextAddress::ReadRecordNumber(m_fileLoc, line, index);
   if (NS_SUCCEEDED(rv)) {
     nsString str;
-    nsCString field;
-    nsString uField;
+    nsString field;
     PRInt32 fNum = 0;
-    while (nsTextAddress::GetField(line.get(), line.Length(), fNum, field, m_delim)) {
+    while (nsTextAddress::GetField(line, fNum, field, m_delim)) {
       if (fNum)
         str.Append(PRUnichar('\n'));
       SanitizeSampleData(field);
-      rv = nsMsgI18NConvertToUnicode(nsMsgI18NFileSystemCharset(),
-                                     field, uField);
-
-      str.Append(uField);
+      str.Append(field);
       fNum++;
       field.Truncate();
     }
 
     *pStr = ToNewUnicode(str);
     *pFound = true;
 
     /* IMPORT_LOG1("Sample data: %S\n", str.get()); */