diff --git a/mozilla/modules/libjar/nsZipArchive.cpp b/mozilla/modules/libjar/nsZipArchive.cpp index 2f8bd707e32..d6b4f84eb74 100644 --- a/mozilla/modules/libjar/nsZipArchive.cpp +++ b/mozilla/modules/libjar/nsZipArchive.cpp @@ -24,16 +24,26 @@ /* * This module implements a simple archive extractor for the PKZIP format. + * + * The underlying nsZipArchive is NOT thread-safe. Do not pass references + * or pointers to it across thread boundaries. */ -#include -#include "nscore.h" -#include "prmem.h" -#include "prio.h" -#include "plstr.h" -#include "prlog.h" -#include "xp_regexp.h" +#ifndef STANDALONE + #include "nscore.h" + #include "prmem.h" + #include "prio.h" + #include "plstr.h" + #include "xp_regexp.h" + #define ZFILE_CREATE PR_WRONLY | PR_CREATE_FILE + #define READTYPE PRInt32 +#else + #include "zipstub.h" + #undef NETSCAPE // undoes prtypes damage in zlib.h + #define ZFILE_CREATE "wb" + #define READTYPE PRUint32 +#endif /* STANDALONE */ #include "zlib.h" @@ -65,15 +75,15 @@ PR_PUBLIC_API(PRInt32) ZIP_OpenArchive( const char * zipname, void** hZip ) PRInt32 status; /*--- error check args ---*/ - if ( hZip == NULL ) + if ( hZip == 0 ) return ZIP_ERR_PARAM; /*--- NULL output to prevent use by bozos who don't check errors ---*/ - *hZip = NULL; + *hZip = 0; /*--- create and open the archive ---*/ nsZipArchive* zip = new nsZipArchive(); - if ( zip == NULL ) + if ( zip == 0 ) return ZIP_ERR_MEMORY; status = zip->OpenArchive(zipname); @@ -98,7 +108,7 @@ PR_PUBLIC_API(PRInt32) ZIP_OpenArchive( const char * zipname, void** hZip ) PR_PUBLIC_API(PRInt32) ZIP_CloseArchive( void** hZip ) { /*--- error check args ---*/ - if ( hZip == NULL || *hZip == NULL ) + if ( hZip == 0 || *hZip == 0 ) return ZIP_ERR_PARAM; nsZipArchive* zip = NS_STATIC_CAST(nsZipArchive*,*hZip); @@ -106,7 +116,7 @@ PR_PUBLIC_API(PRInt32) ZIP_CloseArchive( void** hZip ) return ZIP_ERR_PARAM; /* whatever it is isn't one of ours! */ /*--- close the archive ---*/ - *hZip = NULL; + *hZip = 0; delete zip; return ZIP_OK; @@ -126,7 +136,7 @@ PR_PUBLIC_API(PRInt32) ZIP_CloseArchive( void** hZip ) PR_PUBLIC_API(PRInt32) ZIP_ExtractFile( void* hZip, const char * filename, const char * outname ) { /*--- error check args ---*/ - if ( hZip == NULL ) + if ( hZip == 0 ) return ZIP_ERR_PARAM; nsZipArchive* zip = NS_STATIC_CAST(nsZipArchive*,hZip); @@ -148,15 +158,15 @@ PR_PUBLIC_API(PRInt32) ZIP_ExtractFile( void* hZip, const char * filename, const * @param pattern regexp to match files in archive, the usual shell expressions. * NULL pattern also matches all files, faster than "*" */ -PR_EXTERN(PRInt32) ZIP_FindInit( void* hZip, const char * pattern ) +PR_PUBLIC_API(void*) ZIP_FindInit( void* hZip, const char * pattern ) { /*--- error check args ---*/ - if ( hZip == NULL ) - return ZIP_ERR_PARAM; + if ( hZip == 0 ) + return 0; nsZipArchive* zip = NS_STATIC_CAST(nsZipArchive*,hZip); if ( zip->kMagic != ZIP_MAGIC ) - return ZIP_ERR_PARAM; /* whatever it is isn't one of ours! */ + return 0; /* whatever it is isn't one of ours! */ /*--- initialize the pattern search ---*/ return zip->FindInit( pattern ); @@ -171,26 +181,48 @@ PR_EXTERN(PRInt32) ZIP_FindInit( void* hZip, const char * pattern ) * the name is too large for the buffer, and ZIP_ERR_FNF when there are no * more files that match the pattern * - * @param hZip handle obtained from ZIP_OpenArchive + * @param hFind handle obtained from ZIP_FindInit * @param outbuf buffer to receive next filename * @param bufsize size of allocated buffer */ -PR_EXTERN(PRInt32) ZIP_FindNext( void* hZip, char * outbuf, PRUint16 bufsize ) +PR_PUBLIC_API(PRInt32) ZIP_FindNext( void* hFind, char * outbuf, PRUint16 bufsize ) { /*--- error check args ---*/ - if ( hZip == NULL ) + if ( hFind == 0 ) return ZIP_ERR_PARAM; - nsZipArchive* zip = NS_STATIC_CAST(nsZipArchive*,hZip); - if ( zip->kMagic != ZIP_MAGIC ) + nsZipFind* find = NS_STATIC_CAST(nsZipFind*,hFind); + if ( find->kMagic != ZIPFIND_MAGIC ) return ZIP_ERR_PARAM; /* whatever it is isn't one of ours! */ /*--- return next filename file ---*/ - return zip->FindNext( outbuf, bufsize ); + return find->mArchive->FindNext( find, outbuf, bufsize ); } +/** + * ZIP_FindFree + * + * Releases allocated memory associated with the find token + * + * @param hFind handle obtained from ZIP_FindInit + */ +PR_PUBLIC_API(PRInt32) ZIP_FindFree( void* hFind ) +{ + /*--- error check args ---*/ + if ( hFind == 0 ) + return ZIP_ERR_PARAM; + + nsZipFind* find = NS_STATIC_CAST(nsZipFind*,hFind); + if ( find->kMagic != ZIPFIND_MAGIC ) + return ZIP_ERR_PARAM; /* whatever it is isn't one of ours! */ + + /* free the find structure */ + return find->mArchive->FindFree( find ); +} + + @@ -205,16 +237,16 @@ PR_EXTERN(PRInt32) ZIP_FindNext( void* hZip, char * outbuf, PRUint16 bufsize ) PRInt32 nsZipArchive::OpenArchive( const char * aArchiveName ) { //-- validate arguments - if ( aArchiveName == NULL || *aArchiveName == '\0') + if ( aArchiveName == 0 || *aArchiveName == '\0') return ZIP_ERR_PARAM; //-- not allowed to do two opens on the same object! - if ( mFd != NULL ) + if ( mFd != 0 ) return ZIP_ERR_GENERAL; //-- open the physical file mFd = PR_Open( aArchiveName, PR_RDONLY, 0 ); - if ( mFd == NULL ) + if ( mFd == 0 ) return ZIP_ERR_DISK; //-- get table of contents for archive @@ -229,12 +261,12 @@ PRInt32 nsZipArchive::OpenArchive( const char * aArchiveName ) PRInt32 nsZipArchive::ExtractFile(const char* aFilename, const char* aOutname) { //-- sanity check arguments - if ( aFilename == NULL || aOutname == NULL ) + if ( aFilename == 0 || aOutname == 0 ) return ZIP_ERR_PARAM; //-- find file information const nsZipItem* item = GetFileItem( aFilename ); - if ( item == NULL ) + if ( item == 0 ) return ZIP_ERR_FNF; //-- extract the file using appropriate method @@ -257,43 +289,39 @@ PRInt32 nsZipArchive::ExtractFile(const char* aFilename, const char* aOutname) //--------------------------------------------- // nsZipArchive::FindInit //--------------------------------------------- -PRInt32 nsZipArchive::FindInit( const char * aPattern ) +nsZipFind* nsZipArchive::FindInit( const char * aPattern ) { + PRBool regExp; + char* pattern = 0; + // validate the pattern - if ( aPattern != NULL ) + if ( aPattern ) + { switch (XP_RegExpValid( (char*)aPattern )) { case INVALID_SXP: - return ZIP_ERR_PARAM; + return 0; case NON_SXP: - mPatternIsRegExp = PR_FALSE; + regExp = PR_FALSE; break; case VALID_SXP: - mPatternIsRegExp = PR_TRUE; + regExp = PR_TRUE; break; default: - // unexpected/undoc'ed return value + // undocumented return value from RegExpValid! PR_ASSERT( PR_FALSE ); - return ZIP_ERR_GENERAL; + return 0; } - // clear the old pattern - if ( mPattern != NULL ) - { - PL_strfree( mPattern ); - mPattern = NULL; + pattern = PL_strdup( aPattern ); + if ( !pattern ) + return 0; } - // re-initialize pattern state - mPatternSlot = 0; - mPatternItem = NULL; - if ( aPattern != NULL ) - mPattern = PL_strdup( aPattern ); - - return ZIP_OK; + return new nsZipFind( this, pattern, regExp ); } @@ -301,32 +329,35 @@ PRInt32 nsZipArchive::FindInit( const char * aPattern ) //--------------------------------------------- // nsZipArchive::FindNext //--------------------------------------------- -PRInt32 nsZipArchive::FindNext( char * aBuf, PRUint16 aSize ) +PRInt32 nsZipArchive::FindNext( nsZipFind* aFind, char * aBuf, PRUint16 aSize ) { PRInt32 status; PRBool found = PR_FALSE; - PRUint32 slot = mPatternSlot; - nsZipItem* item = mPatternItem; + PRUint16 slot = aFind->mSlot; + nsZipItem* item = aFind->mItem; + + if ( aFind->mArchive != this || aBuf == 0 ) + return ZIP_ERR_PARAM; // we start from last match, look for next while ( slot < ZIP_TABSIZE && !found ) { - if ( item != NULL ) + if ( item != 0 ) item = item->next; // move to next in current chain else item = mFiles[slot]; // starting a new slot - if ( item == NULL ) + if ( item == 0 ) { // no more in this chain, move to next slot ++slot; continue; } - else if ( mPattern == NULL ) + else if ( aFind->mPattern == 0 ) found = PR_TRUE; // always match - else if ( mPatternIsRegExp ) - found = XP_RegExpMatch( item->name, mPattern, PR_FALSE ); + else if ( aFind->mRegExp ) + found = XP_RegExpMatch( item->name, aFind->mPattern, PR_FALSE ); else - found = ( PL_strcmp( item->name, mPattern ) == 0 ); + found = ( PL_strcmp( item->name, aFind->mPattern ) == 0 ); } if ( found ) @@ -343,10 +374,11 @@ PRInt32 nsZipArchive::FindNext( char * aBuf, PRUint16 aSize ) status = ZIP_ERR_FNF; // save state for next Find. For 'smallbuf' we give user another chance + // to find this same match. if ( status != ZIP_ERR_SMALLBUF ) { - mPatternSlot = slot; - mPatternItem = item; + aFind->mSlot = slot; + aFind->mItem = item; } return status; @@ -354,6 +386,20 @@ PRInt32 nsZipArchive::FindNext( char * aBuf, PRUint16 aSize ) +//--------------------------------------------- +// nsZipArchive::FindFree +//--------------------------------------------- +PRInt32 nsZipArchive::FindFree( nsZipFind* aFind ) +{ + if ( aFind->mArchive != this ) + return ZIP_ERR_PARAM; + + delete aFind; + return ZIP_OK; +} + + + //*********************************************************** @@ -369,7 +415,7 @@ PRInt32 nsZipArchive::BuildFileList() PRInt32 status = ZIP_OK; PRUint32 sig = 0L; PRUint32 namelen, extralen; - PRUint16 hash; + PRUint32 hash; ZipLocal Local; @@ -417,13 +463,13 @@ PRInt32 nsZipArchive::BuildFileList() extralen = xtoint( Local.extrafield_len ); item = new nsZipItem(); - if ( item != NULL ) + if ( item != 0 ) { item->name = new char[namelen+1]; - if ( item->name != NULL ) + if ( item->name != 0 ) { - if ( PR_Read( mFd, item->name, namelen ) == (PRInt32)namelen ) + if ( PR_Read( mFd, item->name, namelen ) == (READTYPE)namelen ) { item->name[namelen] = 0; item->namelen = namelen; @@ -480,12 +526,12 @@ PRInt32 nsZipArchive::CopyItemToDisk( const nsZipItem* aItem, const char* aOutna { PRInt32 status = ZIP_OK; PRUint32 chunk, pos, size; - PRFileDesc* fOut = NULL; + PRFileDesc* fOut = 0; - PR_ASSERT( aItem != NULL && aOutname != NULL ); + PR_ASSERT( aItem != 0 && aOutname != 0 ); char* buf = (char*)PR_Malloc(ZIP_BUFLEN); - if ( buf == NULL ) + if ( buf == 0 ) return ZIP_ERR_MEMORY; //-- find start of file in archive @@ -496,8 +542,8 @@ PRInt32 nsZipArchive::CopyItemToDisk( const nsZipItem* aItem, const char* aOutna } //-- open output file - fOut = PR_Open( aOutname, PR_WRONLY | PR_CREATE_FILE, 0644); - if ( fOut == NULL ) + fOut = PR_Open( aOutname, ZFILE_CREATE , 0644); + if ( fOut == 0 ) { status = ZIP_ERR_DISK; goto cleanup; @@ -509,14 +555,14 @@ PRInt32 nsZipArchive::CopyItemToDisk( const nsZipItem* aItem, const char* aOutna { chunk = (pos+ZIP_BUFLEN <= size) ? ZIP_BUFLEN : size - pos; - if ( PR_Read( mFd, buf, chunk ) != (PRInt32)chunk ) + if ( PR_Read( mFd, buf, chunk ) != (READTYPE)chunk ) { //-- unexpected end of data in archive status = ZIP_ERR_CORRUPT; break; } - if ( PR_Write( fOut, buf, chunk ) < (PRInt32)chunk ) + if ( PR_Write( fOut, buf, chunk ) < (READTYPE)chunk ) { //-- Couldn't write all the data (disk full?) status = ZIP_ERR_DISK; @@ -525,7 +571,7 @@ PRInt32 nsZipArchive::CopyItemToDisk( const nsZipItem* aItem, const char* aOutna } cleanup: - if ( fOut != NULL ) + if ( fOut != 0 ) PR_Close( fOut ); PR_FREEIF( buf ); @@ -539,11 +585,11 @@ cleanup: //--------------------------------------------- const nsZipItem* nsZipArchive::GetFileItem( const char * aFilename ) { - PR_ASSERT( aFilename != NULL ); + PR_ASSERT( aFilename != 0 ); nsZipItem* item = mFiles[ HashName(aFilename) ]; - for ( ; item != NULL; item = item->next ) + for ( ; item != 0; item = item->next ) { if ( 0 == PL_strcmp( aFilename, item->name ) ) break; //-- found it @@ -557,12 +603,12 @@ const nsZipItem* nsZipArchive::GetFileItem( const char * aFilename ) //--------------------------------------------- // nsZipArchive::HashName //--------------------------------------------- -PRUint16 nsZipArchive::HashName( const char* aName ) +PRUint32 nsZipArchive::HashName( const char* aName ) { - PRUint16 val = 0; + PRUint32 val = 0; PRUint8* c; - PR_ASSERT( aName != NULL ); + PR_ASSERT( aName != 0 ); for ( c = (PRUint8*)aName; *c != 0; c++ ) { val = val*37 + *c; @@ -580,17 +626,17 @@ PRInt32 nsZipArchive::InflateItemToDisk( const nsZipItem* aItem, const char* aOu { PRInt32 status = ZIP_OK; PRUint32 chunk, inpos, outpos, size; - PRFileDesc* fOut = NULL; + PRFileDesc* fOut = 0; z_stream zs; int zerr; PRBool bInflating = PR_FALSE; - PR_ASSERT( aItem != NULL && aOutname != NULL ); + PR_ASSERT( aItem != 0 && aOutname != 0 ); //-- allocate deflation buffers Bytef *inbuf = (Bytef*)PR_Malloc(ZIP_BUFLEN); Bytef *outbuf = (Bytef*)PR_Malloc(ZIP_BUFLEN); - if ( inbuf == NULL || outbuf == NULL ) + if ( inbuf == 0 || outbuf == 0 ) { status = ZIP_ERR_MEMORY; goto cleanup; @@ -604,8 +650,8 @@ PRInt32 nsZipArchive::InflateItemToDisk( const nsZipItem* aItem, const char* aOu } //-- open output file - fOut = PR_Open( aOutname, PR_WRONLY | PR_CREATE_FILE, 0644); - if ( fOut == NULL ) + fOut = PR_Open( aOutname, ZFILE_CREATE, 0644); + if ( fOut == 0 ) { status = ZIP_ERR_DISK; goto cleanup; @@ -637,7 +683,7 @@ PRInt32 nsZipArchive::InflateItemToDisk( const nsZipItem* aItem, const char* aOu inpos = zs.total_in; // input position chunk = ( inpos + ZIP_BUFLEN <= size ) ? ZIP_BUFLEN : size - inpos; - if ( PR_Read( mFd, inbuf, chunk ) != (PRInt32)chunk ) + if ( PR_Read( mFd, inbuf, chunk ) != (READTYPE)chunk ) { //-- unexpected end of data status = ZIP_ERR_CORRUPT; @@ -670,7 +716,7 @@ PRInt32 nsZipArchive::InflateItemToDisk( const nsZipItem* aItem, const char* aOu if ( zerr == Z_STREAM_END && outpos < zs.total_out ) { chunk = zs.total_out - outpos; - if ( PR_Write( fOut, outbuf, chunk ) < (PRInt32)chunk ) + if ( PR_Write( fOut, outbuf, chunk ) < (READTYPE)chunk ) { status = ZIP_ERR_DISK; } @@ -693,7 +739,7 @@ cleanup: inflateEnd( &zs ); } - if ( fOut != NULL ) + if ( fOut != 0 ) PR_Close( fOut ); PR_FREEIF( inbuf ); @@ -709,19 +755,18 @@ cleanup: //------------------------------------------ nsZipArchive::nsZipArchive() - : kMagic(ZIP_MAGIC), mFd(NULL), mPattern(NULL), - mPatternSlot(ZIP_TABSIZE), mPatternItem(NULL) + : kMagic(ZIP_MAGIC), mFd(0) { // initialize the table to NULL for ( int i = 0; i < ZIP_TABSIZE; ++i) { - mFiles[i] = NULL; + mFiles[i] = 0; } } nsZipArchive::~nsZipArchive() { // close the file if open - if ( mFd != NULL ) { + if ( mFd != 0 ) { PR_Close(mFd); } @@ -730,35 +775,55 @@ nsZipArchive::~nsZipArchive() for ( int i = 0; i < ZIP_TABSIZE; ++i) { pItem = mFiles[i]; - while ( pItem != NULL ) + while ( pItem != 0 ) { mFiles[i] = pItem->next; delete pItem; pItem = mFiles[i]; } } - - if ( mPattern != NULL ) { - PL_strfree(mPattern); - } } + //------------------------------------------ // nsZipItem constructor and destructor //------------------------------------------ -nsZipItem::nsZipItem() : name(NULL),next(NULL) {} +nsZipItem::nsZipItem() : name(0),next(0) {} nsZipItem::~nsZipItem() { - if (name != NULL ) + if (name != 0 ) delete [] name; } + +//------------------------------------------ +// nsZipFind constructor and destructor +//------------------------------------------ + +nsZipFind::nsZipFind( nsZipArchive* aZip, char* aPattern, PRBool aRegExp ) +: kMagic(ZIPFIND_MAGIC), + mArchive(aZip), + mPattern(aPattern), + mSlot(0), + mItem(0), + mRegExp(aRegExp) +{} + +nsZipFind::~nsZipFind() +{ + if (mPattern != 0 ) + PL_strfree( mPattern ); +} + + + + //------------------------------------------ // helper functions //------------------------------------------ @@ -771,7 +836,7 @@ nsZipItem::~nsZipItem() */ static PRUint16 xtoint (unsigned char *ii) { - return (PRUint16) (ii [0]) | ((PRUint16) ii [1] << 8); + return (PRUint16) ((ii [0]) | (ii [1] << 8)); } /* diff --git a/mozilla/modules/libjar/nsZipArchive.h b/mozilla/modules/libjar/nsZipArchive.h index 6eee4b2fb64..771daa831c6 100644 --- a/mozilla/modules/libjar/nsZipArchive.h +++ b/mozilla/modules/libjar/nsZipArchive.h @@ -22,11 +22,16 @@ * Daniel Veditz */ -#include "prtypes.h" -#define ZIP_MAGIC 0x5F5A4950L /* "_ZIP" */ -#define ZIP_TABSIZE 256 -#define ZIP_BUFLEN 32767 +#define ZIP_MAGIC 0x5A49505FL /* "ZIP_" */ +#define ZIPFIND_MAGIC 0x5A495046L /* "ZIPF" */ +#define ZIP_TABSIZE 256 +#define ZIP_BUFLEN 32767 + + + + +class nsZipFind; /** * nsZipItem -- a helper class for nsZipArchive @@ -60,6 +65,7 @@ private: + /** * nsZipArchive -- a class for reading the PKZIP file format. * @@ -97,21 +103,35 @@ public: */ PRInt32 ExtractFile( const char * aFilename, const char * aOutname ); - PRInt32 FindInit( const char * aPattern ); - PRInt32 FindNext( char * aBuf, PRUint16 aSize ); + /** + * FindInit + * + * Initializes a search for files in the archive. FindNext() returns + * the actual matches. FindFree() must be called when you're done + * + * @param aPattern a string or RegExp pattern to search for + * (may be NULL to find all files in archive) + * @return a structure used in FindNext. NULL indicates error + */ + nsZipFind* FindInit( const char * aPattern ); + + /** + * FindNext + * + * @param aFind the Find structure returned by FindInit + * @param aBuf A buffer to hold filenames that match pattern + * @param aSize size of the buffer + */ + PRInt32 FindNext( nsZipFind* aFind, char * aBuf, PRUint16 aSize ); + + PRInt32 FindFree( nsZipFind *aFind ); private: //--- private members --- PRFileDesc *mFd; - nsZipItem* mFiles[ZIP_TABSIZE]; - char* mPattern; - PRUint16 mPatternSlot; - nsZipItem* mPatternItem; - PRBool mPatternIsRegExp; - //--- private methods --- nsZipArchive& operator=(const nsZipArchive& rhs); // prevent assignments @@ -120,7 +140,37 @@ private: PRInt32 BuildFileList(); PRInt32 CopyItemToDisk( const nsZipItem* aItem, const char* aOutname ); const nsZipItem* GetFileItem( const char * aFilename ); - PRUint16 HashName( const char* aName ); + PRUint32 HashName( const char* aName ); PRInt32 InflateItemToDisk( const nsZipItem* aItem, const char* aOutname ); }; + + + +/** + * nsZipFind + * + * a helper class for nsZipArchive, representing a search + */ +class nsZipFind +{ + friend class nsZipArchive; + friend PR_EXTERN(PRInt32) ZIP_FindNext( void*, char*, PRUint16 ); + friend PR_EXTERN(PRInt32) ZIP_FindFree( void* ); +public: + const PRInt32 kMagic; + + nsZipFind( nsZipArchive* aZip, char* aPattern, PRBool regExp ); + ~nsZipFind(); + +private: + nsZipArchive* mArchive; + char* mPattern; + PRUint16 mSlot; + nsZipItem* mItem; + PRBool mRegExp; + + //-- prevent copies and assignments + nsZipFind& operator=(const nsZipFind& rhs); + nsZipFind(const nsZipFind& rhs); +}; diff --git a/mozilla/modules/libjar/zipfile.h b/mozilla/modules/libjar/zipfile.h index e6189c30290..ca810e3ef6e 100644 --- a/mozilla/modules/libjar/zipfile.h +++ b/mozilla/modules/libjar/zipfile.h @@ -32,7 +32,6 @@ * * Currently only compression mode 8 (or none) is supported. */ -#include "prtypes.h" #define ZIP_OK 0 @@ -66,8 +65,10 @@ PR_EXTERN(PRInt32) ZIP_ExtractFile( void* hZip, const char * filename, const cha /* Functions to list the files contained in the archive * - * FindInit() initializes the search with the pattern, then FindNext() is - * called to get the matching filenames if any. + * FindInit() initializes the search with the pattern and returns a find token, + * or NULL on an error. Then FindNext() is called with the token to get the + * matching filenames if any. When done you must call FindFree() with the + * token to release memory. * * a NULL pattern will find all the files in the archive, otherwise the * pattern must be a shell regexp type pattern. @@ -76,8 +77,9 @@ PR_EXTERN(PRInt32) ZIP_ExtractFile( void* hZip, const char * filename, const cha * will return ZIP_ERR_SMALLBUF. When no more matches can be found in * the archive it will return ZIP_ERR_FNF */ -PR_EXTERN(PRInt32) ZIP_FindInit( void* hZip, const char * pattern ); -PR_EXTERN(PRInt32) ZIP_FindNext( void* hZip, char * outbuf, PRUint16 bufsize ); +PR_EXTERN(void*) ZIP_FindInit( void* hZip, const char * pattern ); +PR_EXTERN(PRInt32) ZIP_FindNext( void* hFind, char * outbuf, PRUint16 bufsize ); +PR_EXTERN(PRInt32) ZIP_FindFree( void* hFind ); PR_END_EXTERN_C