Bug 296795: ZipReader doesn't handle non-ASCII characters r=taras
authorWolfgang Germund <wolfgang@germund.name>
Wed, 28 Sep 2011 16:14:45 -0700
changeset 77790 6032f7c15af8ba7c56bcfc174a2d6424d9aa7dfc
parent 77789 ec855ff26e8d8457293b5454a473848e39d2425c
child 77791 7cc26b83a57c5d6386128830116438ecf522596f
push id21239
push usermwu@mozilla.com
push dateThu, 29 Sep 2011 08:20:44 +0000
treeherdermozilla-central@e7854b4d29ba [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstaras
bugs296795
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 296795: ZipReader doesn't handle non-ASCII characters r=taras
caps/src/nsScriptSecurityManager.cpp
modules/libjar/nsIZipReader.idl
modules/libjar/nsJAR.cpp
modules/libjar/nsJAR.h
modules/libjar/nsJARChannel.cpp
modules/libjar/test/unit/data/test_umlaute.zip
modules/libjar/test/unit/test_umlaute.js
modules/libjar/test/unit/xpcshell.ini
modules/libpref/src/Preferences.cpp
xpcom/components/nsComponentManager.cpp
xpinstall/src/nsXPInstallManager.cpp
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -2969,17 +2969,17 @@ nsScriptSecurityManager::SetCanEnableCap
         if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
         systemCertFile->AppendNative(NS_LITERAL_CSTRING("systemSignature.jar"));
         if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
         nsCOMPtr<nsIZipReader> systemCertZip = do_CreateInstance(kZipReaderCID, &rv);
         if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
         rv = systemCertZip->Open(systemCertFile);
         if (NS_SUCCEEDED(rv))
         {
-            rv = systemCertZip->GetCertificatePrincipal(nsnull,
+            rv = systemCertZip->GetCertificatePrincipal(EmptyCString(),
                                                         getter_AddRefs(mSystemCertificate));
             if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
         }
     }
 
     //-- Make sure the caller's principal is the system certificate
     PRBool isEqual = PR_FALSE;
     if (mSystemCertificate)
--- a/modules/libjar/nsIZipReader.idl
+++ b/modules/libjar/nsIZipReader.idl
@@ -86,76 +86,78 @@ interface nsIZipEntry : nsISupports
      * directory foo/ in a zip containing exactly one entry for foo/bar.txt
      * is synthetic.  If the zip file contains an actual entry for a directory,
      * this attribute will be false for the nsIZipEntry for that directory.
      * It is impossible for a file to be synthetic.
      */
     readonly attribute boolean          isSynthetic;
 };
 
-[scriptable, uuid(7bb925d6-833a-486c-8ef2-9bc15c670a60)]
+[scriptable, uuid(8fbf5023-3827-4fbc-a464-5db546e7f747)]
 interface nsIZipReader : nsISupports
 {
     /**
      * Opens a zip file for reading.
      * It is allowed to open with another file, 
      * but it needs to be closed first with close().
      */
     void open(in nsIFile zipFile);
 
     /**
      * Opens a zip file inside a zip file for reading.
      */
-    void openInner(in nsIZipReader zipReader, in string zipEntry);
+    void openInner(in nsIZipReader zipReader, in AUTF8String zipEntry);
 
     /**
      * The file that represents the zip with which this zip reader was
      * initialized.
      */
     readonly attribute nsIFile file;
 
     /**
      * Closes a zip reader. Subsequent attempts to extract files or read from
      * its input stream will result in an error.
      */
     void close();
 
     /**
      * Tests the integrity of the archive by performing a CRC check 
      * on each item expanded into memory.  If an entry is specified
-     * the integrity of only that item is tested.  If NULL is passed 
-     * in the integrity of all items in the archive are tested.  
+     * the integrity of only that item is tested.  If null (javascript)
+     * or EmptyCString() (c++) is passed in the integrity of all items 
+     * in the archive are tested.  
      */
-    void test(in string aEntryName);
+    void test(in AUTF8String aEntryName);
 
     /**
      * Extracts a zip entry into a local file specified by outFile.
      * The entry must be stored in the zip in either uncompressed or
      * DEFLATE-compressed format for the extraction to be successful.
      * If the entry is a directory, the directory will be extracted
      * non-recursively.
      */
-    void extract(in string zipEntry, in nsIFile outFile);
+    void extract(in AUTF8String zipEntry, in nsIFile outFile);
 
     /**
      * Returns a nsIZipEntry describing a specified zip entry.
      */
-    nsIZipEntry getEntry(in string zipEntry);
+    nsIZipEntry getEntry(in AUTF8String zipEntry);
 
     /**
      * Checks whether the zipfile contains an entry specified by entryName.
      */
     boolean hasEntry(in AUTF8String zipEntry);
  
     /**
      * Returns a string enumerator containing the matching entry names.
      *
      * @param aPattern
      *   A regular expression used to find matching entries in the zip file.
-     *   Set this parameter to null to get all entries; otherwise, use the
+     *   Set this parameter to null (javascript) or EmptyCString() (c++) or "*" 
+     *   to get all entries; otherwise, use the
      *   following syntax:
      *
      *   o * matches anything
      *   o ? matches one character
      *   o $ matches the end of the string
      *   o [abc] matches one occurrence of a, b, or c. The only character that
      *           must be escaped inside the brackets is ].  ^ and - must never
      *           appear in the first and second positions within the brackets, 
@@ -182,51 +184,51 @@ interface nsIZipReader : nsISupports
      *       special characters unless otherwise specified.
      *   o All other characters match case-sensitively.
      *
      *   An aPattern not conforming to this syntax has undefined behavior.
      *
      * @throws NS_ERROR_ILLEGAL_VALUE on many but not all invalid aPattern
      *                                values.
      */
-    nsIUTF8StringEnumerator findEntries(in string aPattern);
+    nsIUTF8StringEnumerator findEntries(in AUTF8String aPattern);
 
     /**
      * Returns an input stream containing the contents of the specified zip
      * entry.
      * @param zipEntry the name of the entry to open the stream from
      */
-    nsIInputStream getInputStream(in string zipEntry);
+    nsIInputStream getInputStream(in AUTF8String zipEntry);
 
     /**
      * Returns an input stream containing the contents of the specified zip
      * entry. If the entry refers to a directory (ends with '/'), a directory stream 
      * is opened, otherwise the contents of the file entry is returned.
      * @param aJarSpec the Spec of the URI for the JAR (only used for directory streams)
      * @param zipEntry the name of the entry to open the stream from
      */
-    nsIInputStream getInputStreamWithSpec(in AUTF8String aJarSpec, in string zipEntry);
+    nsIInputStream getInputStreamWithSpec(in AUTF8String aJarSpec, in AUTF8String zipEntry);
 
      /**
      * Returns an object describing the entity which signed 
      * an entry. parseManifest must be called first. If aEntryName is an
      * entry in the jar, getInputStream must be called after parseManifest.
      * If aEntryName is an external file which has meta-information 
      * stored in the jar, verifyExternalFile (not yet implemented) must 
      * be called before getPrincipal.
      */
-    nsIPrincipal getCertificatePrincipal(in string aEntryName);   
+    nsIPrincipal getCertificatePrincipal(in AUTF8String aEntryName);   
     
     readonly attribute PRUint32 manifestEntriesCount;
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIZipReaderCache
 
-[scriptable, uuid(52c45d86-0cc3-11d4-986e-00c04fa0cf4a)]
+[scriptable, uuid(72fc56e5-3e6e-4d11-8967-26ab96071032)]
 interface nsIZipReaderCache : nsISupports
 {
     /**
      * Initializes a new zip reader cache. 
      * @param cacheSize - the number of released entries to maintain before
      *   beginning to throw some out (note that the number of outstanding
      *   entries can be much greater than this number -- this is the count
      *   for those otherwise unused entries)
@@ -246,34 +248,30 @@ interface nsIZipReaderCache : nsISupport
      */
     nsIZipReader getZip(in nsIFile zipFile);
 
     /**
      * Returns a (possibly shared) nsIZipReader for a zip inside another zip
      *
      * See getZip
      */
-    nsIZipReader getInnerZip(in nsIFile zipFile, in string zipEntry);
+    nsIZipReader getInnerZip(in nsIFile zipFile, in AUTF8String zipEntry);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 
 %{C++
 
 #define NS_ZIPREADER_CID                             \
-{ /* 7526a738-9632-11d3-8cd9-0060b0fc14a3 */         \
-    0x7526a738,                                      \
-    0x9632,                                          \
-    0x11d3,                                          \
-    {0x8c, 0xd9, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
+{ /* 88e2fd0b-f7f4-480c-9483-7846b00e8dad */         \
+   0x88e2fd0b, 0xf7f4, 0x480c,                       \
+  { 0x94, 0x83, 0x78, 0x46, 0xb0, 0x0e, 0x8d, 0xad } \
 }
 
 #define NS_ZIPREADERCACHE_CID                        \
-{ /* 1b117e16-0cad-11d4-986e-00c04fa0cf4a */         \
-    0x1b117e16,                                      \
-    0x0cad,                                          \
-    0x11d4,                                          \
-    {0x98, 0x6e, 0x00, 0xc0, 0x4f, 0xa0, 0xcf, 0x4a} \
+{ /* 608b7f6f-4b60-40d6-87ed-d933bf53d8c1 */         \
+   0x608b7f6f, 0x4b60, 0x40d6,                       \
+  { 0x87, 0xed, 0xd9, 0x33, 0xbf, 0x53, 0xd8, 0xc1 } \
 }
 
 %}
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/modules/libjar/nsJAR.cpp
+++ b/modules/libjar/nsJAR.cpp
@@ -183,36 +183,35 @@ nsJAR::Open(nsIFile* zipFile)
   if (zip) {
     mZip = zip;
     return NS_OK;
   }
   return mZip->OpenArchive(zipFile);
 }
 
 NS_IMETHODIMP
-nsJAR::OpenInner(nsIZipReader *aZipReader, const char *aZipEntry)
+nsJAR::OpenInner(nsIZipReader *aZipReader, const nsACString &aZipEntry)
 {
   NS_ENSURE_ARG_POINTER(aZipReader);
-  NS_ENSURE_ARG_POINTER(aZipEntry);
   if (mOpened) return NS_ERROR_FAILURE; // Already open!
 
   PRBool exist;
-  nsresult rv = aZipReader->HasEntry(nsDependentCString(aZipEntry), &exist);
+  nsresult rv = aZipReader->HasEntry(aZipEntry, &exist);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(exist, NS_ERROR_FILE_NOT_FOUND);
 
   rv = aZipReader->GetFile(getter_AddRefs(mZipFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mOpened = PR_TRUE;
 
   mOuterZipEntry.Assign(aZipEntry);
 
   nsRefPtr<nsZipHandle> handle;
-  rv = nsZipHandle::Init(static_cast<nsJAR*>(aZipReader)->mZip.get(), aZipEntry,
+  rv = nsZipHandle::Init(static_cast<nsJAR*>(aZipReader)->mZip.get(), PromiseFlatCString(aZipEntry).get(),
                          getter_AddRefs(handle));
   if (NS_FAILED(rv))
     return rv;
 
   return mZip->OpenArchive(handle);
 }
 
 NS_IMETHODIMP
@@ -237,33 +236,33 @@ nsJAR::Close()
     mZip.forget();
     mZip = new nsZipArchive();
     return NS_OK;
   }
   return mZip->CloseArchive();
 }
 
 NS_IMETHODIMP
-nsJAR::Test(const char *aEntryName)
+nsJAR::Test(const nsACString &aEntryName)
 {
-  return mZip->Test(aEntryName);
+  return mZip->Test(aEntryName.IsEmpty()? nsnull : PromiseFlatCString(aEntryName).get());
 }
 
 NS_IMETHODIMP
-nsJAR::Extract(const char *zipEntry, nsIFile* outFile)
+nsJAR::Extract(const nsACString &aEntryName, nsIFile* outFile)
 {
   // nsZipArchive and zlib are not thread safe
   // we need to use a lock to prevent bug #51267
   MutexAutoLock lock(mLock);
 
   nsresult rv;
   nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(outFile, &rv);
   if (NS_FAILED(rv)) return rv;
 
-  nsZipItem *item = mZip->GetItem(zipEntry);
+  nsZipItem *item = mZip->GetItem(PromiseFlatCString(aEntryName).get());
   NS_ENSURE_TRUE(item, NS_ERROR_FILE_TARGET_DOES_NOT_EXIST);
 
   // Remove existing file or directory so we set permissions correctly.
   // If it's a directory that already exists and contains files, throw
   // an exception and return.
 
   //XXX Bug 332139:
   //XXX If we guarantee that rv in the case of a non-empty directory
@@ -300,19 +299,19 @@ nsJAR::Extract(const char *zipEntry, nsI
   // nsIFile needs milliseconds, while prtime is in microseconds.
   // non-fatal if this fails, ignore errors
   outFile->SetLastModifiedTime(item->LastModTime() / PR_USEC_PER_MSEC);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP    
-nsJAR::GetEntry(const char *aEntryName, nsIZipEntry* *result)
+nsJAR::GetEntry(const nsACString &aEntryName, nsIZipEntry* *result)
 {
-  nsZipItem* zipItem = mZip->GetItem(aEntryName);
+  nsZipItem* zipItem = mZip->GetItem(PromiseFlatCString(aEntryName).get());
   NS_ENSURE_TRUE(zipItem, NS_ERROR_FILE_TARGET_DOES_NOT_EXIST);
 
   nsJARItem* jarItem = new nsJARItem(zipItem);
   NS_ENSURE_TRUE(jarItem, NS_ERROR_OUT_OF_MEMORY);
 
   NS_ADDREF(*result = jarItem);
   return NS_OK;
 }
@@ -320,73 +319,73 @@ nsJAR::GetEntry(const char *aEntryName, 
 NS_IMETHODIMP
 nsJAR::HasEntry(const nsACString &aEntryName, PRBool *result)
 {
   *result = mZip->GetItem(PromiseFlatCString(aEntryName).get()) != nsnull;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsJAR::FindEntries(const char *aPattern, nsIUTF8StringEnumerator **result)
+nsJAR::FindEntries(const nsACString &aPattern, nsIUTF8StringEnumerator **result)
 {
   NS_ENSURE_ARG_POINTER(result);
 
   nsZipFind *find;
-  nsresult rv = mZip->FindInit(aPattern, &find);
+  nsresult rv = mZip->FindInit(aPattern.IsEmpty()? nsnull : PromiseFlatCString(aPattern).get(), &find);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsIUTF8StringEnumerator *zipEnum = new nsJAREnumerator(find);
   if (!zipEnum) {
     delete find;
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   NS_ADDREF(*result = zipEnum);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsJAR::GetInputStream(const char* aFilename, nsIInputStream** result)
+nsJAR::GetInputStream(const nsACString &aFilename, nsIInputStream** result)
 {
   return GetInputStreamWithSpec(EmptyCString(), aFilename, result);
 }
 
 NS_IMETHODIMP
 nsJAR::GetInputStreamWithSpec(const nsACString& aJarDirSpec, 
-                          const char* aEntryName, nsIInputStream** result)
+                          const nsACString &aEntryName, nsIInputStream** result)
 {
-  NS_ENSURE_ARG_POINTER(aEntryName);
   NS_ENSURE_ARG_POINTER(result);
 
   // Watch out for the jar:foo.zip!/ (aDir is empty) top-level special case!
   nsZipItem *item = nsnull;
-  if (*aEntryName) {
+  const char *entry = PromiseFlatCString(aEntryName).get();
+  if (*entry) {
     // First check if item exists in jar
-    item = mZip->GetItem(aEntryName);
+    item = mZip->GetItem(entry);
     if (!item) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
   }
   nsJARInputStream* jis = new nsJARInputStream();
   // addref now so we can call InitFile/InitDirectory()
   NS_ENSURE_TRUE(jis, NS_ERROR_OUT_OF_MEMORY);
   NS_ADDREF(*result = jis);
 
   nsresult rv = NS_OK;
   if (!item || item->IsDirectory()) {
-    rv = jis->InitDirectory(this, aJarDirSpec, aEntryName);
+    rv = jis->InitDirectory(this, aJarDirSpec, entry);
   } else {
     rv = jis->InitFile(this, item);
   }
   if (NS_FAILED(rv)) {
     NS_RELEASE(*result);
   }
   return rv;
 }
 
 NS_IMETHODIMP
-nsJAR::GetCertificatePrincipal(const char* aFilename, nsIPrincipal** aPrincipal)
+nsJAR::GetCertificatePrincipal(const nsACString &aFilename, nsIPrincipal** aPrincipal)
 {
   //-- Parameter check
   if (!aPrincipal)
     return NS_ERROR_NULL_POINTER;
   *aPrincipal = nsnull;
 
   // Don't check signatures in the omnijar - this is only
   // interesting for extensions/XPIs.
@@ -396,20 +395,21 @@ nsJAR::GetCertificatePrincipal(const cha
 
   //-- Parse the manifest
   nsresult rv = ParseManifest();
   if (NS_FAILED(rv)) return rv;
   if (mGlobalStatus == JAR_NO_MANIFEST)
     return NS_OK;
 
   PRInt16 requestedStatus;
-  if (aFilename)
+  const char *filename = PromiseFlatCString(aFilename).get();
+  if (*filename)
   {
     //-- Find the item
-    nsCStringKey key(aFilename);
+    nsCStringKey key(filename);
     nsJARManifestItem* manItem = static_cast<nsJARManifestItem*>(mManifestData.Get(&key));
     if (!manItem)
       return NS_OK;
     //-- Verify the item against the manifest
     if (!manItem->entryVerified)
     {
       nsXPIDLCString entryData;
       PRUint32 entryDataLen;
@@ -419,17 +419,17 @@ nsJAR::GetCertificatePrincipal(const cha
       if (NS_FAILED(rv)) return rv;
     }
     requestedStatus = manItem->status;
   }
   else // User wants identity of signer w/o verifying any entries
     requestedStatus = mGlobalStatus;
 
   if (requestedStatus != JAR_VALID_MANIFEST)
-    ReportError(aFilename, requestedStatus);
+    ReportError(filename, requestedStatus);
   else // Valid signature
   {
     *aPrincipal = mPrincipal;
     NS_IF_ADDREF(*aPrincipal);
   }
   return NS_OK;
 }
 
@@ -447,17 +447,17 @@ nsJAR::GetJarPath(nsACString& aResult)
 
   return mZipFile->GetNativePath(aResult);
 }
 
 //----------------------------------------------
 // nsJAR private implementation
 //----------------------------------------------
 nsresult 
-nsJAR::LoadEntry(const char* aFilename, char** aBuf, PRUint32* aBufLen)
+nsJAR::LoadEntry(const nsACString &aFilename, char** aBuf, PRUint32* aBufLen)
 {
   //-- Get a stream for reading the file
   nsresult rv;
   nsCOMPtr<nsIInputStream> manifestStream;
   rv = GetInputStream(aFilename, getter_AddRefs(manifestStream));
   if (NS_FAILED(rv)) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
   
   //-- Read the manifest file into memory
@@ -524,17 +524,17 @@ nsJAR::ReadLine(const char** src)
 nsresult
 nsJAR::ParseManifest()
 {
   //-- Verification Step 1
   if (mParsedManifest)
     return NS_OK;
   //-- (1)Manifest (MF) file
   nsCOMPtr<nsIUTF8StringEnumerator> files;
-  nsresult rv = FindEntries(JAR_MF_SEARCH_STRING, getter_AddRefs(files));
+  nsresult rv = FindEntries(nsDependentCString(JAR_MF_SEARCH_STRING), getter_AddRefs(files));
   if (!files) rv = NS_ERROR_FAILURE;
   if (NS_FAILED(rv)) return rv;
 
   //-- Load the file into memory
   PRBool more;
   rv = files->HasMore(&more);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!more)
@@ -554,58 +554,58 @@ nsJAR::ParseManifest()
   if (more)
   {
     mParsedManifest = PR_TRUE;
     return NS_ERROR_FILE_CORRUPTED; // More than one MF file
   }
 
   nsXPIDLCString manifestBuffer;
   PRUint32 manifestLen;
-  rv = LoadEntry(manifestFilename.get(), getter_Copies(manifestBuffer), &manifestLen);
+  rv = LoadEntry(manifestFilename, getter_Copies(manifestBuffer), &manifestLen);
   if (NS_FAILED(rv)) return rv;
 
   //-- Parse it
   rv = ParseOneFile(manifestBuffer, JAR_MF);
   if (NS_FAILED(rv)) return rv;
 
   //-- (2)Signature (SF) file
   // If there are multiple signatures, we select one.
-  rv = FindEntries(JAR_SF_SEARCH_STRING, getter_AddRefs(files));
+  rv = FindEntries(nsDependentCString(JAR_SF_SEARCH_STRING), getter_AddRefs(files));
   if (!files) rv = NS_ERROR_FAILURE;
   if (NS_FAILED(rv)) return rv;
   //-- Get an SF file
   rv = files->HasMore(&more);
   if (NS_FAILED(rv)) return rv;
   if (!more)
   {
     mGlobalStatus = JAR_NO_MANIFEST;
     mParsedManifest = PR_TRUE;
     return NS_OK;
   }
   rv = files->GetNext(manifestFilename);
   if (NS_FAILED(rv)) return rv;
 
-  rv = LoadEntry(manifestFilename.get(), getter_Copies(manifestBuffer), &manifestLen);
+  rv = LoadEntry(manifestFilename, getter_Copies(manifestBuffer), &manifestLen);
   if (NS_FAILED(rv)) return rv;
   
   //-- Get its corresponding signature file
   nsCAutoString sigFilename(manifestFilename);
   PRInt32 extension = sigFilename.RFindChar('.') + 1;
   NS_ASSERTION(extension != 0, "Manifest Parser: Missing file extension.");
   (void)sigFilename.Cut(extension, 2);
   nsXPIDLCString sigBuffer;
   PRUint32 sigLen;
   {
     nsCAutoString tempFilename(sigFilename); tempFilename.Append("rsa", 3);
-    rv = LoadEntry(tempFilename.get(), getter_Copies(sigBuffer), &sigLen);
+    rv = LoadEntry(tempFilename, getter_Copies(sigBuffer), &sigLen);
   }
   if (NS_FAILED(rv))
   {
     nsCAutoString tempFilename(sigFilename); tempFilename.Append("RSA", 3);
-    rv = LoadEntry(tempFilename.get(), getter_Copies(sigBuffer), &sigLen);
+    rv = LoadEntry(tempFilename, getter_Copies(sigBuffer), &sigLen);
   }
   if (NS_FAILED(rv))
   {
     mGlobalStatus = JAR_NO_MANIFEST;
     mParsedManifest = PR_TRUE;
     return NS_OK;
   }
 
@@ -1147,17 +1147,17 @@ nsZipReaderCache::GetZip(nsIFile* zipFil
       mZips.Put(&key, static_cast<nsIZipReader*>(zip)); // AddRefs to 2
     NS_ASSERTION(!collision, "horked");
   }
   *result = zip;
   return rv;
 }
 
 NS_IMETHODIMP
-nsZipReaderCache::GetInnerZip(nsIFile* zipFile, const char *entry,
+nsZipReaderCache::GetInnerZip(nsIFile* zipFile, const nsACString &entry,
                               nsIZipReader* *result)
 {
   NS_ENSURE_ARG_POINTER(zipFile);
 
   nsCOMPtr<nsIZipReader> outerZipReader;
   nsresult rv = GetZip(zipFile, getter_AddRefs(outerZipReader));
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/modules/libjar/nsJAR.h
+++ b/modules/libjar/nsJAR.h
@@ -142,17 +142,17 @@ class nsJAR : public nsIZipReader
     nsZipReaderCache*        mCache;          // if cached, this points to the cache it's contained in
     mozilla::Mutex           mLock;	
     PRInt64                  mMtime;
     PRInt32                  mTotalItemsInManifest;
     PRBool                   mOpened;
 
     nsresult ParseManifest();
     void     ReportError(const char* aFilename, PRInt16 errorCode);
-    nsresult LoadEntry(const char* aFilename, char** aBuf, 
+    nsresult LoadEntry(const nsACString &aFilename, char** aBuf, 
                        PRUint32* aBufLen = nsnull);
     PRInt32  ReadLine(const char** src); 
     nsresult ParseOneFile(const char* filebuf, PRInt16 aFileType);
     nsresult VerifyEntry(nsJARManifestItem* aEntry, const char* aEntryData, 
                          PRUint32 aLen);
 
     nsresult CalculateDigest(const char* aInBuf, PRUint32 aInBufLen,
                              nsCString& digest);
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -144,21 +144,21 @@ nsJARInputThunk::EnsureJarStream()
     nsresult rv;
     if (ENTRY_IS_DIRECTORY(mJarEntry)) {
         // A directory stream also needs the Spec of the FullJarURI
         // because is included in the stream data itself.
 
         NS_ENSURE_STATE(!mJarDirSpec.IsEmpty());
 
         rv = mJarReader->GetInputStreamWithSpec(mJarDirSpec,
-                                                mJarEntry.get(),
+                                                mJarEntry,
                                                 getter_AddRefs(mJarStream));
     }
     else {
-        rv = mJarReader->GetInputStream(mJarEntry.get(),
+        rv = mJarReader->GetInputStream(mJarEntry,
                                         getter_AddRefs(mJarStream));
     }
     if (NS_FAILED(rv)) {
         // convert to the proper result if the entry wasn't found
         // so that error pages work
         if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
             rv = NS_ERROR_FILE_NOT_FOUND;
         return rv;
@@ -298,17 +298,17 @@ nsJARChannel::CreateJarInput(nsIZipReade
     if (NS_FAILED(rv))
         return rv;
 
     nsCOMPtr<nsIZipReader> reader;
     if (jarCache) {
         if (mInnerJarEntry.IsEmpty())
             rv = jarCache->GetZip(mJarFile, getter_AddRefs(reader));
         else 
-            rv = jarCache->GetInnerZip(mJarFile, mInnerJarEntry.get(),
+            rv = jarCache->GetInnerZip(mJarFile, mInnerJarEntry,
                                        getter_AddRefs(reader));
     } else {
         // create an uncached jar reader
         nsCOMPtr<nsIZipReader> outerReader = do_CreateInstance(kZipReaderCID, &rv);
         if (NS_FAILED(rv))
             return rv;
 
         rv = outerReader->Open(mJarFile);
@@ -317,17 +317,17 @@ nsJARChannel::CreateJarInput(nsIZipReade
 
         if (mInnerJarEntry.IsEmpty())
             reader = outerReader;
         else {
             reader = do_CreateInstance(kZipReaderCID, &rv);
             if (NS_FAILED(rv))
                 return rv;
 
-            rv = reader->OpenInner(outerReader, mInnerJarEntry.get());
+            rv = reader->OpenInner(outerReader, mInnerJarEntry);
         }
     }
     if (NS_FAILED(rv))
         return rv;
 
     mJarInput = new nsJARInputThunk(reader, mJarURI, mJarEntry, jarCache);
     if (!mJarInput)
         return NS_ERROR_OUT_OF_MEMORY;
@@ -530,17 +530,17 @@ nsJARChannel::GetOwner(nsISupports **res
 
     //-- Verify signature, if one is present, and set owner accordingly
     nsCOMPtr<nsIZipReader> jarReader;
     mJarInput->GetJarReader(getter_AddRefs(jarReader));
     if (!jarReader)
         return NS_ERROR_NOT_INITIALIZED;
 
     nsCOMPtr<nsIPrincipal> cert;
-    rv = jarReader->GetCertificatePrincipal(mJarEntry.get(), getter_AddRefs(cert));
+    rv = jarReader->GetCertificatePrincipal(mJarEntry, getter_AddRefs(cert));
     if (NS_FAILED(rv)) return rv;
 
     if (cert) {
         nsCAutoString certFingerprint;
         rv = cert->GetFingerprint(certFingerprint);
         if (NS_FAILED(rv)) return rv;
 
         nsCAutoString subjectName;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d147138e185ab6a40eaab58cf13f79943785b64e
GIT binary patch
literal 179
zc$^FHW@h1HVBlb2c-_clpSS9ZKRW{h0|;|7$S{<o7MH{y-lJDiQ4$)$$-rDS$;l6d
zODnh;7+GF0GcbUO!%GftJG_T0z?+dtjv1F}5)2@~2*gVoK`a!rSs`YlnH%8E$_CNI
M$PfsmeZWQl06OL;AOHXW
new file mode 100644
--- /dev/null
+++ b/modules/libjar/test/unit/test_umlaute.js
@@ -0,0 +1,40 @@
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+function run_test() {
+  var dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); 
+  var tmpDir = dirService.get("TmpD", Ci.nsIFile); 
+
+  var zipfile = do_get_file("data/test_umlaute.zip");
+
+  var testFile = tmpDir.clone();
+  testFile.append("test_\u00FC.txt");
+  if (testFile.exists()) {
+    testFile.remove(false);
+  }
+
+  var zipreader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(Ci.nsIZipReader);
+  zipreader.open(zipfile);
+
+  var entries = zipreader.findEntries(null);
+  do_check_true(entries.hasMore()); 
+
+  var entryName = entries.getNext();
+  do_check_eq(entryName, "test_\u00FC.txt");
+
+  do_check_true(zipreader.hasEntry(entryName));
+
+  var target = tmpDir.clone();
+  target.append(entryName);
+  target.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0640);
+
+  zipreader.extract(entryName, target);
+
+  var entry = zipreader.getEntry(entryName);
+  do_check_true(entry != null);
+
+  zipreader.test(entryName);
+
+  zipreader.close();
+}
--- a/modules/libjar/test/unit/xpcshell.ini
+++ b/modules/libjar/test/unit/xpcshell.ini
@@ -15,8 +15,10 @@ tail =
 [test_bug637286.js]
 [test_bug658093.js]
 [test_corrupt_536911.js]
 [test_corrupt_541828.js]
 [test_dirjar_bug525755.js]
 [test_jarinput_stream_zipreader_reference.js]
 [test_not_found.js]
 [test_uncompressed.js]
+[test_umlaute.js]
+
--- a/modules/libpref/src/Preferences.cpp
+++ b/modules/libpref/src/Preferences.cpp
@@ -467,30 +467,30 @@ Preferences::ReadExtensionPrefs(nsILocal
   nsresult rv;
   nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = reader->Open(aFile);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIUTF8StringEnumerator> files;
-  rv = reader->FindEntries("defaults/preferences/*.(J|j)(S|s)$",
+  rv = reader->FindEntries(nsDependentCString("defaults/preferences/*.(J|j)(S|s)$"),
                            getter_AddRefs(files));
   NS_ENSURE_SUCCESS(rv, rv);
 
   char buffer[4096];
 
   PRBool more;
   while (NS_SUCCEEDED(rv = files->HasMore(&more)) && more) {
     nsCAutoString entry;
     rv = files->GetNext(entry);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIInputStream> stream;
-    rv = reader->GetInputStream(entry.get(), getter_AddRefs(stream));
+    rv = reader->GetInputStream(entry, getter_AddRefs(stream));
     NS_ENSURE_SUCCESS(rv, rv);
 
     PRUint32 avail, read;
 
     PrefParseState ps;
     PREF_InitParseState(&ps, PREF_ReaderCallback, NULL);
     while (NS_SUCCEEDED(rv = stream->Available(&avail)) && avail) {
       rv = stream->Read(buffer, 4096, &read);
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -532,17 +532,17 @@ GetExtension(nsILocalFile* file)
 
 static already_AddRefed<nsIInputStream>
 LoadEntry(nsIZipReader* aReader, const char* aName)
 {
     if (!aReader)
         return NULL;
 
     nsCOMPtr<nsIInputStream> is;
-    nsresult rv = aReader->GetInputStream(aName, getter_AddRefs(is));
+    nsresult rv = aReader->GetInputStream(nsDependentCString(aName), getter_AddRefs(is));
     if (NS_FAILED(rv))
         return NULL;
 
     return is.forget();
 }
 
 void
 nsComponentManagerImpl::RegisterJarManifest(NSLocationType aType, nsIZipReader* aReader,
--- a/xpinstall/src/nsXPInstallManager.cpp
+++ b/xpinstall/src/nsXPInstallManager.cpp
@@ -633,25 +633,25 @@ VerifySigning(nsIZipReader* hZip, nsIPri
 
     PRBool hasCert;
     aPrincipal->GetHasCertificate(&hasCert);
     if (!hasCert)
         return NS_ERROR_FAILURE;
 
     // See if the archive is signed at all first
     nsCOMPtr<nsIPrincipal> principal;
-    nsresult rv = hZip->GetCertificatePrincipal(nsnull, getter_AddRefs(principal));
+    nsresult rv = hZip->GetCertificatePrincipal(EmptyCString(), getter_AddRefs(principal));
     if (NS_FAILED(rv) || !principal)
         return NS_ERROR_FAILURE;
 
     PRUint32 entryCount = 0;
 
     // first verify all files in the jar are also in the manifest.
     nsCOMPtr<nsIUTF8StringEnumerator> entries;
-    rv = hZip->FindEntries(nsnull, getter_AddRefs(entries));
+    rv = hZip->FindEntries(EmptyCString(), getter_AddRefs(entries));
     if (NS_FAILED(rv))
         return rv;
 
     PRBool more;
     nsCAutoString name;
     while (NS_SUCCEEDED(entries->HasMore(&more)) && more)
     {
         rv = entries->GetNext(name);
@@ -662,17 +662,17 @@ VerifySigning(nsIZipReader* hZip, nsIPri
         if ((name.Last() == '/') ||
             (PL_strncasecmp("META-INF/", name.get(), 9) == 0))
             continue;
 
         // Count the entries to be verified
         entryCount++;
 
         // Each entry must be signed
-        rv = hZip->GetCertificatePrincipal(name.get(), getter_AddRefs(principal));
+        rv = hZip->GetCertificatePrincipal(name, getter_AddRefs(principal));
         if (NS_FAILED(rv) || !principal) return NS_ERROR_FAILURE;
 
         PRBool equal;
         rv = principal->Equals(aPrincipal, &equal);
         if (NS_FAILED(rv) || !equal) return NS_ERROR_FAILURE;
     }
 
     // next verify all files in the manifest are in the archive.
@@ -708,31 +708,31 @@ OpenAndValidateArchive(nsIZipReader* hZi
     nsresult rv =jarFile->Clone(getter_AddRefs(jFile));
     if (NS_SUCCEEDED(rv))
         rv = hZip->Open(jFile);
 
     if (NS_FAILED(rv))
         return nsInstall::CANT_READ_ARCHIVE;
 
     // CRC check the integrity of all items in this archive
-    rv = hZip->Test(nsnull);
+    rv = hZip->Test(EmptyCString());
     if (NS_FAILED(rv))
     {
         NS_WARNING("CRC check of archive failed!");
         return nsInstall::CANT_READ_ARCHIVE;
     }
 
     rv = VerifySigning(hZip, aPrincipal);
     if (NS_FAILED(rv))
     {
         NS_WARNING("Signing check of archive failed!");
         return nsInstall::INVALID_SIGNATURE;
     }
 
-    if (NS_FAILED(hZip->Test("install.rdf")))
+    if (NS_FAILED(hZip->Test(nsDependentCString("install.rdf"))))
     {
         NS_WARNING("Archive did not contain an install manifest!");
         return nsInstall::NO_INSTALL_SCRIPT;
     }
 
     return nsInstall::SUCCESS;
 }