fix warnings
This commit is contained in:
Родитель
af6b377f29
Коммит
43c3f19b1c
959
caps/src/nsZip.c
959
caps/src/nsZip.c
|
@ -1,959 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Routines for reading classes from a ZIP/JAR file in the class path.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef XP_MAC
|
||||
#include "macstdlibextras.h" /* for strncasecmp */
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#if !(XP_MAC)
|
||||
#include <sys/types.h>
|
||||
#else
|
||||
#include <types.h>
|
||||
//#include "NSstring.h"
|
||||
#endif
|
||||
#if !(XP_MAC)
|
||||
#include <sys/stat.h>
|
||||
#else
|
||||
#include <stat.h>
|
||||
#endif
|
||||
|
||||
#include "prlog.h"
|
||||
#include "prio.h"
|
||||
#include "prdtoa.h"
|
||||
#ifdef XP_MAC
|
||||
#include "prpriv.h"
|
||||
#else
|
||||
#include "private/prpriv.h"
|
||||
#endif
|
||||
#include "prtypes.h"
|
||||
#include "nsZip.h"
|
||||
#include "zlib.h"
|
||||
#include "xp.h" /* for XP_STRDUP */
|
||||
#include "nsQuickSort.h"
|
||||
#include "prmem.h"
|
||||
#include "prerror.h"
|
||||
|
||||
#ifndef max
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Header signatures
|
||||
*/
|
||||
#define SIGSIZ 4
|
||||
#define LOCSIG "PK\003\004"
|
||||
#define CENSIG "PK\001\002"
|
||||
#define ENDSIG "PK\005\006"
|
||||
|
||||
/*
|
||||
* Header sizes including signatures
|
||||
*/
|
||||
#define LOCHDRSIZ 30
|
||||
#define CENHDRSIZ 46
|
||||
#define ENDHDRSIZ 22
|
||||
|
||||
/*
|
||||
* Header field access macros
|
||||
*/
|
||||
#define CH(b, n) ((unsigned short)(((unsigned char HUGEP *)(b))[n]))
|
||||
#define SH(b, n) ((unsigned long)(CH(b, n) | (CH(b, n+1) << 8)))
|
||||
#define LG(b, n) (SH(b, n) | (SH(b, n+2) << 16))
|
||||
|
||||
/*
|
||||
* Macros for getting local file header (LOC) fields
|
||||
*/
|
||||
#define LOCFLG(b) SH(b, 6) /* encrypt flags */
|
||||
#define LOCHOW(b) SH(b, 8) /* compression method */
|
||||
#define LOCCRC(b) LG(b, 14) /* uncompressed file crc-32 value */
|
||||
#define LOCSIZ(b) LG(b, 18) /* compressed size */
|
||||
#define LOCLEN(b) LG(b, 22) /* uncompressed size */
|
||||
#define LOCNAM(b) SH(b, 26) /* filename size */
|
||||
#define LOCEXT(b) SH(b, 28) /* extra field size */
|
||||
|
||||
/*
|
||||
* Macros for getting central directory header (CEN) fields
|
||||
*/
|
||||
#define CENHOW(b) SH(b, 10) /* compression method */
|
||||
#define CENTIM(b) LG(b, 12) /* file modification time (DOS format) */
|
||||
#define CENSIZ(b) LG(b, 20) /* compressed size */
|
||||
#define CENLEN(b) LG(b, 24) /* uncompressed size */
|
||||
#define CENNAM(b) SH(b, 28) /* length of filename */
|
||||
#define CENEXT(b) SH(b, 30) /* length of extra field */
|
||||
#define CENCOM(b) SH(b, 32) /* file comment length */
|
||||
#define CENOFF(b) LG(b, 42) /* offset of local header */
|
||||
|
||||
/*
|
||||
* Macros for getting end of central directory header (END) fields
|
||||
*/
|
||||
#define ENDSUB(b) SH(b, 8) /* number of entries on this disk */
|
||||
#define ENDTOT(b) SH(b, 10) /* total number of entries */
|
||||
#define ENDSIZ(b) LG(b, 12) /* central directory size */
|
||||
#define ENDOFF(b) LG(b, 16) /* central directory offset */
|
||||
#define ENDCOM(b) SH(b, 20) /* size of zip file comment */
|
||||
|
||||
|
||||
/*
|
||||
* Supported compression types
|
||||
*/
|
||||
#define STORED 0
|
||||
#define DEFLATED 8
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
|
||||
#ifdef NETSCAPE
|
||||
|
||||
#ifdef XP_PC
|
||||
#define strncasecmp(s1, s2, len) strnicmp((s1),(s2),(len))
|
||||
#endif /* XP_PC */
|
||||
|
||||
/*
|
||||
* The following 2 macros are necessary for Win16 since they operate
|
||||
* on huge memory (which is unsupported by the runtime library)...
|
||||
*/
|
||||
#if !defined(XP_PC) || defined(_WIN32)
|
||||
#define NS_ZIP_STRNCMP(buf, key, len) strncmp((buf),(key),(len))
|
||||
#define NS_ZIP_STRNCPY(dst, src, len) strncpy((dst),(src),(len))
|
||||
#define NS_ZIP_STRCPY(dst, src) strcpy((dst), (src))
|
||||
|
||||
#else /* WIN16 only */
|
||||
static int NS_ZIP_STRNCMP(char HUGEP *buf, char *key, int len)
|
||||
{
|
||||
while(len--) {
|
||||
char c1, c2;
|
||||
|
||||
c1 = *buf++;
|
||||
c2 = *key++;
|
||||
if (c1 != c2) {
|
||||
return (c1 < c2) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char HUGEP *NS_ZIP_STRCPY(char HUGEP *dst, char * src)
|
||||
{
|
||||
char HUGEP *ret = dst;
|
||||
|
||||
if (src && dst) {
|
||||
while(*src) {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
*dst = *src;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define NS_ZIP_STRNCPY(dst, src, len) hmemcpy((dst),(src),(len))
|
||||
|
||||
#endif /* XP_PC || _WIN32 */
|
||||
#endif /* NETSCAPE */
|
||||
|
||||
static void
|
||||
ns_zip_errmsg(const char *msg)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PRFileDesc* prfd = PR_GetSpecialFD(PR_StandardError);
|
||||
PR_Write(prfd, msg, strlen(msg));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ns_ziperr(ns_zip_t *zip, const char *msg)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
ns_zip_errmsg("Zip Error: ");
|
||||
ns_zip_errmsg(zip->fn);
|
||||
ns_zip_errmsg(": ");
|
||||
ns_zip_errmsg(msg);
|
||||
ns_zip_errmsg("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*#define ZTRACE*/
|
||||
#ifdef ZTRACE
|
||||
FILE *ns_zlog = NULL;
|
||||
#endif
|
||||
|
||||
/* single open fd cache
|
||||
* this relies on the fact that none of the public routines in here
|
||||
* depend on seek state between operations */
|
||||
|
||||
static ns_zip_t *ns_zip_cache = NULL;
|
||||
static PRMonitor *ns_zlock = NULL;
|
||||
|
||||
static PRBool nsEnsureZip(ns_zip_t *zip)
|
||||
{
|
||||
if(zip != ns_zip_cache) {
|
||||
PRFileDesc *fd;
|
||||
if(ns_zip_cache) {
|
||||
PR_Close(ns_zip_cache->fd);
|
||||
ns_zip_cache->fd = 0;
|
||||
#ifdef ZTRACE
|
||||
if (ns_zlog) fprintf(ns_zlog, "close %s\n", ns_zip_cache->fn);
|
||||
#endif
|
||||
}
|
||||
#ifdef ZTRACE
|
||||
if (ns_zlog) fprintf(ns_zlog,"open %s\n", zip->fn);
|
||||
#endif
|
||||
fd = PR_Open(zip->fn, PR_RDONLY, 0);
|
||||
if (FD_IS_ERROR(fd)) {
|
||||
#if !defined(XP_PC) || defined(_WIN32)
|
||||
/*
|
||||
* perror is not defined for win16 dlls
|
||||
*/
|
||||
perror(zip->fn);
|
||||
#endif
|
||||
ns_zip_cache = NULL;
|
||||
return PR_FALSE;
|
||||
}
|
||||
zip->fd = fd;
|
||||
ns_zip_cache = zip;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
/*
|
||||
* Read exactly 'len' bytes of data into 'buf'. Return PR_TRUE if all bytes
|
||||
* could be read, otherwise return PR_FALSE.
|
||||
*/
|
||||
static PRBool
|
||||
nsZipReadFully(PRFileDesc *fd, void *buf, PRInt32 len)
|
||||
{
|
||||
char HUGEP *bp = (char HUGEP *)buf;
|
||||
PRInt32 segBlock;
|
||||
|
||||
PR_ASSERT( !IsBadHugeWritePtr((void HUGEP *)buf, len) );
|
||||
|
||||
do {
|
||||
segBlock = (len >= 0x10000L) ? (0x10000L - OFFSETOF(bp)) : len;
|
||||
len -= segBlock;
|
||||
|
||||
/*
|
||||
* Read a segment (64K) into the buffer...
|
||||
*/
|
||||
while (segBlock > 0) {
|
||||
PRInt32 rqst, n;
|
||||
|
||||
rqst = (segBlock > 4096) ? 4096 : segBlock;
|
||||
|
||||
n = PR_Read(fd, bp, rqst);
|
||||
if (n <= 0) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
bp += n;
|
||||
segBlock -= n;
|
||||
}
|
||||
} while (len > 0);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#else
|
||||
/*
|
||||
* Read exactly 'len' bytes of data into 'buf'. Return PR_TRUE if all bytes
|
||||
* could be read, otherwise return PR_FALSE.
|
||||
*/
|
||||
static PRBool
|
||||
nsZipReadFully(PRFileDesc *fd, void *buf, PRInt32 len)
|
||||
{
|
||||
char *bp = buf;
|
||||
|
||||
while (len > 0) {
|
||||
PRInt32 n = PR_Read(fd, bp, len);
|
||||
if (n <= 0) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
bp += n;
|
||||
len -= n;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define INBUFSIZ 64
|
||||
|
||||
/*
|
||||
* Find end of central directory (END) header in zip file and set the file
|
||||
* pointer to start of header. Return PR_FALSE if the END header could not be
|
||||
* found, otherwise return PR_TRUE.
|
||||
*/
|
||||
static PRBool
|
||||
nsZipFindEnd(ns_zip_t *zip, char *endbuf)
|
||||
{
|
||||
char buf[INBUFSIZ+SIGSIZ], *bp;
|
||||
PRUint32 len, off, mark;
|
||||
|
||||
/* Need to search backwards from end of file */
|
||||
if ((len = PR_Seek(zip->fd, 0, PR_SEEK_END)) == -1) {
|
||||
#if !defined(XP_PC) || defined(_WIN32)
|
||||
/*
|
||||
* perror is not defined for win16
|
||||
*/
|
||||
perror(zip->fn);
|
||||
#endif
|
||||
return PR_FALSE;
|
||||
}
|
||||
/*
|
||||
* Set limit on how far back we need to search. The END header must be
|
||||
* located within the last 64K bytes of the file.
|
||||
*/
|
||||
mark = max(0, len - 0xffff);
|
||||
/*
|
||||
* Search backwards INBUFSIZ bytes at a time from end of file stopping
|
||||
* when the END header signature has been found. Since the signature
|
||||
* may straddle a buffer boundary, we need to stash the first SIGSIZ-1
|
||||
* bytes of the previous record at the tail of the current record so
|
||||
* that the search can overlap.
|
||||
*/
|
||||
memset(buf, 0, SIGSIZ);
|
||||
for (off = len; off > mark; ) {
|
||||
long n = min(off - mark, INBUFSIZ);
|
||||
memcpy(buf + n, buf, SIGSIZ);
|
||||
if (PR_Seek(zip->fd, off -= n, PR_SEEK_SET) == -1) {
|
||||
#if !defined(XP_PC) || defined(_WIN32)
|
||||
/*
|
||||
* perror is not defined for win16
|
||||
*/
|
||||
perror(zip->fn);
|
||||
#endif
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (!nsZipReadFully(zip->fd, buf, n)) {
|
||||
ns_ziperr(zip, "Fatal read error while searching for END record");
|
||||
return PR_FALSE;
|
||||
}
|
||||
for (bp = buf + n - 1; bp >= buf; --bp) {
|
||||
if (strncmp(bp, ENDSIG, SIGSIZ) == 0) {
|
||||
long endoff = off + (long)bp - (long)buf;
|
||||
if (len - endoff < ENDHDRSIZ) {
|
||||
continue;
|
||||
}
|
||||
if ((buf+n-bp) >= ENDHDRSIZ) {
|
||||
memcpy(endbuf, bp, ENDHDRSIZ);
|
||||
} else {
|
||||
if (PR_Seek(zip->fd, endoff, PR_SEEK_SET) == -1) {
|
||||
#if !defined(XP_PC) || defined(_WIN32)
|
||||
/*
|
||||
* perror is not defined for win16
|
||||
*/
|
||||
perror(zip->fn);
|
||||
#endif
|
||||
}
|
||||
if (!nsZipReadFully(zip->fd, endbuf, ENDHDRSIZ)) {
|
||||
ns_ziperr(zip, "Read error while searching for END record");
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
if (endoff + ENDHDRSIZ + ENDCOM(endbuf) != len) {
|
||||
continue;
|
||||
}
|
||||
if (PR_Seek(zip->fd, endoff, PR_SEEK_SET) == -1) {
|
||||
#if !defined(XP_PC) || defined(_WIN32)
|
||||
/*
|
||||
* perror is not defined for win16
|
||||
*/
|
||||
perror(zip->fn);
|
||||
#endif
|
||||
return PR_FALSE;
|
||||
}
|
||||
zip->endoff = endoff;
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert DOS time to UNIX time
|
||||
*/
|
||||
static time_t
|
||||
ns_zip_unixtime(int dostime)
|
||||
{
|
||||
struct tm tm;
|
||||
|
||||
tm.tm_sec = (dostime << 1) & 0x3e;
|
||||
tm.tm_min = (dostime >> 5) & 0x3f;
|
||||
tm.tm_hour = (dostime >> 11) & 0x1f;
|
||||
tm.tm_mday = (dostime >> 16) & 0x1f;
|
||||
tm.tm_mon = ((dostime >> 21) & 0xf) - 1;
|
||||
tm.tm_year = ((dostime >> 25) & 0x7f) + 1980;
|
||||
return mktime(&tm);
|
||||
}
|
||||
|
||||
static int
|
||||
ns_zip_direlcmp(const void *d1, const void *d2)
|
||||
{
|
||||
return strcmp(((direl_t *)d1)->fn, ((direl_t *)d2)->fn);
|
||||
}
|
||||
|
||||
static int
|
||||
ns_zip_direlcmp2(const void *d1, const void *d2, void *unused)
|
||||
{
|
||||
return strcmp(((direl_t *)d1)->fn, ((direl_t *)d2)->fn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize zip file reader, read in central directory and construct the
|
||||
* lookup table for locating zip file members.
|
||||
*/
|
||||
static PRBool
|
||||
ns_zip_initReader(ns_zip_t *zip)
|
||||
{
|
||||
char endbuf[ENDHDRSIZ];
|
||||
char HUGEP *cenbuf;
|
||||
char HUGEP *cp;
|
||||
PRUint32 locoff;
|
||||
PRUint32 i, cenlen;
|
||||
|
||||
/* Seek to END header and read it in */
|
||||
if (!nsZipFindEnd(zip, endbuf)) {
|
||||
ns_ziperr(zip, "Unable to locate end-of-central-directory record");
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Verify END signature */
|
||||
if (strncmp(endbuf, ENDSIG, SIGSIZ) != 0) {
|
||||
ns_ziperr(zip, "Invalid END signature");
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Get real offset of central directory */
|
||||
zip->cenoff = zip->endoff - ENDSIZ(endbuf);
|
||||
/*
|
||||
* Since there may be a stub prefixed to the ZIP or JAR file, the
|
||||
* the start offset of the first local file (LOC) header will be
|
||||
* the difference between the real offset of the first CEN header
|
||||
* and what is specified in the END header.
|
||||
*/
|
||||
if (zip->cenoff < ENDOFF(endbuf)) {
|
||||
ns_ziperr(zip, "Invalid end-of-central directory header");
|
||||
return PR_FALSE;
|
||||
}
|
||||
locoff = zip->cenoff - ENDOFF(endbuf);
|
||||
/* Get length of central directory */
|
||||
cenlen = ENDSIZ(endbuf);
|
||||
/* Check offset and length */
|
||||
if (zip->cenoff + cenlen != zip->endoff) {
|
||||
ns_ziperr(zip, "Invalid end-of-central-directory header");
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Get total number of central directory entries */
|
||||
zip->nel = ENDTOT(endbuf);
|
||||
/* Check entry count */
|
||||
if (zip->nel * CENHDRSIZ > cenlen) {
|
||||
ns_ziperr(zip, "Invalid end-of-central-directory header");
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Verify that zip file contains only one drive */
|
||||
if (ENDSUB(endbuf) != zip->nel) {
|
||||
ns_ziperr(zip, "Cannot contain more than one drive");
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Seek to first CEN header */
|
||||
if (PR_Seek(zip->fd, zip->cenoff, PR_SEEK_SET) == -1) {
|
||||
#if !defined(XP_PC) || defined(_WIN32)
|
||||
/*
|
||||
* perror is not defined for win16
|
||||
*/
|
||||
perror(zip->fn);
|
||||
#endif
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Allocate file lookup table */
|
||||
CHECK_SIZE_LIMIT( zip->nel * sizeof(direl_t) );
|
||||
if ((zip->dir = PR_MALLOC((size_t)(zip->nel * sizeof(direl_t)))) == 0) {
|
||||
ns_ziperr(zip, "Out of memory allocating lookup table");
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Allocate temporary buffer for contents of central directory */
|
||||
if ((cenbuf = PR_MALLOC(cenlen)) == 0) {
|
||||
ns_ziperr(zip, "Out of memory allocating central directory buffer");
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Read central directory */
|
||||
if (!nsZipReadFully(zip->fd, cenbuf, cenlen)) {
|
||||
ns_ziperr(zip, "Fatal error while reading central directory");
|
||||
PR_Free(cenbuf);
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Scan each header in central directory */
|
||||
for (i = 0, cp = cenbuf; i < zip->nel; i++) {
|
||||
direl_t *dp = &zip->dir[i];
|
||||
PRUint32 n;
|
||||
/* Verify signature of CEN header */
|
||||
if (NS_ZIP_STRNCMP(cp, CENSIG, SIGSIZ) != 0) {
|
||||
ns_ziperr(zip, "Invalid central directory header signature");
|
||||
PR_Free(cenbuf);
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Get file name */
|
||||
n = CENNAM(cp);
|
||||
|
||||
CHECK_SIZE_LIMIT( n+1 );
|
||||
if ((dp->fn = PR_MALLOC((size_t)n + 1)) == 0) {
|
||||
ns_ziperr(zip, "Out of memory reading CEN header file name");
|
||||
PR_Free(cenbuf);
|
||||
return PR_FALSE;
|
||||
}
|
||||
NS_ZIP_STRNCPY(dp->fn, cp + CENHDRSIZ, (size_t) n);
|
||||
dp->fn[n] = '\0';
|
||||
/* Get compression method */
|
||||
dp->method = CENHOW(cp);
|
||||
/* Get real offset of LOC header */
|
||||
dp->off = locoff + CENOFF(cp);
|
||||
/* Get uncompressed file size */
|
||||
dp->len = CENLEN(cp);
|
||||
/* Get compressed file size */
|
||||
dp->size = CENSIZ(cp);
|
||||
/* Check offset and size */
|
||||
if (dp->off + CENSIZ(cp) > zip->cenoff) {
|
||||
ns_ziperr(zip, "Invalid CEN header");
|
||||
PR_Free(cenbuf);
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Get file modification time */
|
||||
dp->mod = (int) CENTIM(cp);
|
||||
/* Skip to next CEN header */
|
||||
cp += CENHDRSIZ + CENNAM(cp) + CENEXT(cp) + CENCOM(cp);
|
||||
if (cp > cenbuf + cenlen) {
|
||||
ns_ziperr(zip, "Invalid CEN header");
|
||||
PR_Free(cenbuf);
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
/* Free temporary buffer */
|
||||
PR_Free(cenbuf);
|
||||
/* Sort directory elements by name */
|
||||
NS_QuickSort(zip->dir, (size_t) zip->nel, sizeof(direl_t), ns_zip_direlcmp2, NULL);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PR_PUBLIC_API(PRBool)
|
||||
ns_zip_lock(void)
|
||||
{
|
||||
if(ns_zlock == NULL)
|
||||
{
|
||||
ns_zlock = PR_NewMonitor();
|
||||
if(ns_zlock == NULL)
|
||||
return PR_FALSE;
|
||||
}
|
||||
PR_EnterMonitor(ns_zlock);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PR_PUBLIC_API(void)
|
||||
ns_zip_unlock(void)
|
||||
{
|
||||
PR_ASSERT(ns_zlock != NULL);
|
||||
|
||||
if(ns_zlock != NULL)
|
||||
{
|
||||
PR_ExitMonitor(ns_zlock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Open ns_zip_t file and initialize file lookup table.
|
||||
*/
|
||||
PR_PUBLIC_API(ns_zip_t *)
|
||||
ns_zip_open(const char *fn)
|
||||
{
|
||||
PRFileDesc *fd;
|
||||
ns_zip_t *zip;
|
||||
|
||||
if (!ns_zip_lock())
|
||||
return NULL;
|
||||
#ifdef ZTRACE
|
||||
if(ns_zlog == NULL) {
|
||||
ns_zlog = fopen("ns_zlog.txt", "w");
|
||||
if (FD_IS_ERROR(fd)) {
|
||||
ns_zlog = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ns_zip_cache)
|
||||
{
|
||||
#ifdef ZTRACE
|
||||
if (ns_zlog) fprintf(ns_zlog, "close %s\n", ns_zip_cache->fn);
|
||||
#endif
|
||||
PR_Close(ns_zip_cache->fd);
|
||||
ns_zip_cache->fd = 0;
|
||||
ns_zip_cache = 0;
|
||||
}
|
||||
|
||||
#ifdef ZTRACE
|
||||
if (ns_zlog) fprintf(ns_zlog, "zip open %s\n", fn);
|
||||
#endif
|
||||
fd = PR_Open(fn, PR_RDONLY, 0);
|
||||
if (FD_IS_ERROR(fd)) {
|
||||
ns_zip_unlock();
|
||||
return 0;
|
||||
}
|
||||
if ((zip = PR_Calloc(1, sizeof(ns_zip_t))) == 0) {
|
||||
ns_zip_errmsg("Out of memory");
|
||||
ns_zip_unlock();
|
||||
return 0;
|
||||
}
|
||||
if ((zip->fn = XP_STRDUP(fn)) == 0) {
|
||||
ns_zip_errmsg("Out of memory");
|
||||
ns_zip_unlock();
|
||||
return 0;
|
||||
}
|
||||
zip->fd = fd;
|
||||
if (!ns_zip_initReader(zip)) {
|
||||
PR_Free(zip->fn);
|
||||
PR_Free(zip);
|
||||
PR_Close(fd);
|
||||
ns_zip_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ns_zip_cache = zip;
|
||||
ns_zip_unlock();
|
||||
return zip;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close zip file and free lookup table
|
||||
*/
|
||||
PR_PUBLIC_API(void)
|
||||
ns_zip_close(ns_zip_t *zip)
|
||||
{
|
||||
PRUint32 i;
|
||||
|
||||
ns_zip_lock();
|
||||
#ifdef ZTRACE
|
||||
if (ns_zlog) fprintf(ns_zlog, "zip close %s\n", zip->fn);
|
||||
#endif
|
||||
PR_Free(zip->fn);
|
||||
if(ns_zip_cache == zip) {
|
||||
PR_Close(zip->fd);
|
||||
ns_zip_cache = NULL;
|
||||
} else {
|
||||
PR_ASSERT(zip->fd == 0);
|
||||
}
|
||||
ns_zip_unlock();
|
||||
|
||||
for (i = 0; i < zip->nel; i++) {
|
||||
PR_Free(zip->dir[i].fn);
|
||||
}
|
||||
PR_Free(zip->dir);
|
||||
PR_Free(zip);
|
||||
}
|
||||
|
||||
static direl_t *
|
||||
ns_zip_lookup(ns_zip_t *zip, const char *fn)
|
||||
{
|
||||
direl_t key;
|
||||
key.fn = (char *)fn;
|
||||
return bsearch(&key, zip->dir, (size_t) zip->nel, sizeof(direl_t), ns_zip_direlcmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return file status for ns_zip_t file member
|
||||
*/
|
||||
PR_PUBLIC_API(PRBool)
|
||||
ns_zip_stat(ns_zip_t *zip, const char *fn, struct stat *sbuf)
|
||||
{
|
||||
direl_t *dp;
|
||||
|
||||
if(zip == NULL)
|
||||
return PR_FALSE;
|
||||
|
||||
dp = ns_zip_lookup(zip, fn);
|
||||
#ifdef ZTRACE
|
||||
if(ns_zlog) fprintf(ns_zlog, "stat %s %s\n", dp ? "found" : "failed", fn);
|
||||
#endif
|
||||
if (dp == 0) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
memset(sbuf, 0, sizeof(struct stat));
|
||||
sbuf->st_size = dp->len;
|
||||
#if 0
|
||||
/* no one uses this stuff yet */
|
||||
sbuf->st_mode = 444;
|
||||
sbuf->st_mtime = ns_zip_unixtime(dp->mod);
|
||||
sbuf->st_atime = sbuf->st_mtime;
|
||||
sbuf->st_ctime = sbuf->st_mtime;
|
||||
#endif
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ns_zip_inflateFully(PRFileDesc *fd, PRUint32 size, void *buf, PRUint32 len, char **msg)
|
||||
{
|
||||
static z_stream *strm;
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
char tmp[16000];
|
||||
char tmpBuf[4096];
|
||||
#else
|
||||
char tmp[32000];
|
||||
#endif /* defined(XP_PC) && !defined(_WIN32) */
|
||||
PRBool ok = PR_TRUE;
|
||||
|
||||
if (strm == 0) {
|
||||
strm = PR_Calloc(1, sizeof(z_stream));
|
||||
if (inflateInit2(strm, -MAX_WBITS) != Z_OK) {
|
||||
*msg = strm->msg;
|
||||
PR_Free(strm);
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(XP_PC) || defined(_WIN32)
|
||||
strm->next_out = buf;
|
||||
strm->avail_out = len;
|
||||
#endif
|
||||
|
||||
while (strm->total_in <= size) {
|
||||
PRInt32 n = size - strm->total_in;
|
||||
if (n > 0) {
|
||||
n = PR_Read(fd, tmp, n > sizeof(tmp) ? sizeof(tmp) : n);
|
||||
if (n == 0) {
|
||||
*msg = "Unexpected EOF";
|
||||
ok = PR_FALSE;
|
||||
goto stop;
|
||||
}
|
||||
if (n < 0) {
|
||||
(void) PR_GetErrorText(*msg);
|
||||
ok = PR_FALSE;
|
||||
goto stop;
|
||||
}
|
||||
}
|
||||
strm->next_in = (Bytef *)tmp;
|
||||
strm->avail_in = n;
|
||||
|
||||
do {
|
||||
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
strm->next_out = tmpBuf;
|
||||
strm->avail_out = sizeof(tmpBuf);
|
||||
#endif /* defined(XP_PC) && !defined(_WIN32) */
|
||||
|
||||
switch (inflate(strm, Z_PARTIAL_FLUSH)) {
|
||||
case Z_OK:
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
{
|
||||
int inflatedLength;
|
||||
inflatedLength = strm->next_out - tmpBuf;
|
||||
NS_ZIP_STRNCPY((char HUGEP *)buf, (char HUGEP *)tmpBuf, inflatedLength);
|
||||
((char HUGEP *)buf)+=inflatedLength;
|
||||
}
|
||||
#endif /* defined(XP_PC) && !defined(_WIN32) */
|
||||
break;
|
||||
case Z_STREAM_END:
|
||||
#if defined(XP_PC) && !defined(_WIN32)
|
||||
{
|
||||
int inflatedLength;
|
||||
inflatedLength = strm->next_out - tmpBuf;
|
||||
NS_ZIP_STRNCPY((char HUGEP *)buf, (char HUGEP *)tmpBuf, inflatedLength);
|
||||
((char HUGEP *)buf)+=inflatedLength;
|
||||
}
|
||||
#endif /* defined(XP_PC) && !defined(_WIN32) */
|
||||
if (strm->total_in != size || strm->total_out != len) {
|
||||
*msg = "Invalid entry compressed size";
|
||||
ok = PR_FALSE;
|
||||
}
|
||||
goto stop;
|
||||
default:
|
||||
*msg = strm->msg;
|
||||
goto stop;
|
||||
}
|
||||
} while (strm->avail_in > 0);
|
||||
}
|
||||
*msg = "Invalid entry compressed size";
|
||||
ok = PR_FALSE;
|
||||
|
||||
stop:
|
||||
inflateReset(strm);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read contents of zip file member into buffer 'buf'. If the size of the
|
||||
* data should exceed 'len' then nothing is read and PR_FALSE is returned.
|
||||
*/
|
||||
PR_PUBLIC_API(PRBool)
|
||||
ns_zip_get(ns_zip_t *zip, const char *fn, void HUGEP *buf, PRInt32 len)
|
||||
{
|
||||
char locbuf[LOCHDRSIZ];
|
||||
long off;
|
||||
direl_t *dp = ns_zip_lookup(zip, fn);
|
||||
|
||||
if (!ns_zip_lock())
|
||||
return PR_FALSE;
|
||||
if(!nsEnsureZip(zip)) {
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#ifdef ZTRACEX
|
||||
if(ns_zlog) fprintf(ns_zlog, "get %s\n", fn);
|
||||
#endif
|
||||
/* Look up file member */
|
||||
if (dp == 0) {
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Check buffer length */
|
||||
if (len != (PRInt32) dp->len) {
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Seek to beginning of LOC header */
|
||||
if (PR_Seek(zip->fd, dp->off, PR_SEEK_SET) == -1) {
|
||||
#if !defined(XP_PC) || defined(_WIN32)
|
||||
/*
|
||||
* perror is not defined for win16
|
||||
*/
|
||||
perror(zip->fn);
|
||||
#endif
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Read LOC header */
|
||||
if (!nsZipReadFully(zip->fd, locbuf, LOCHDRSIZ)) {
|
||||
ns_ziperr(zip, "Fatal error while reading LOC header");
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Verify signature */
|
||||
if (strncmp(locbuf, LOCSIG, SIGSIZ) != 0) {
|
||||
ns_ziperr(zip, "Invalid LOC header signature");
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Make sure file is not encrypted */
|
||||
if ((LOCFLG(locbuf) & 1) == 1) {
|
||||
ns_ziperr(zip, "Member is encrypted");
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Get offset of file data */
|
||||
off = dp->off + LOCHDRSIZ + LOCNAM(locbuf) + LOCEXT(locbuf);
|
||||
if (off + dp->size > zip->cenoff) {
|
||||
ns_ziperr(zip, "Invalid LOC header");
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Seek to file data */
|
||||
if (PR_Seek(zip->fd, off, PR_SEEK_SET) == -1) {
|
||||
#if !defined(XP_PC) || defined(_WIN32)
|
||||
/*
|
||||
* perror is not defined for win16
|
||||
*/
|
||||
perror(zip->fn);
|
||||
#endif
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* Read file data */
|
||||
switch (dp->method) {
|
||||
case STORED:
|
||||
if (!nsZipReadFully(zip->fd, buf, dp->len)) {
|
||||
ns_ziperr(zip, "Fatal error while reading LOC data");
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
break;
|
||||
case DEFLATED: {
|
||||
char *msg = 0;
|
||||
if (!ns_zip_inflateFully(zip->fd, dp->size, buf, dp->len, &msg)) {
|
||||
if (msg != 0) {
|
||||
ns_ziperr(zip, msg);
|
||||
} else {
|
||||
ns_ziperr(zip, "Error while reading compressed zip file entry");
|
||||
}
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ns_ziperr(zip, "Unsupported compression method");
|
||||
ns_zip_unlock();
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
ns_zip_unlock();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return total number of files in the archive that match the suffix.
|
||||
* For example look for all files that end with ".sf"
|
||||
* XXX just look in META??
|
||||
*/
|
||||
PR_PUBLIC_API(PRUint32)
|
||||
ns_zip_get_no_of_elements(ns_zip_t *zip, const char *fn_suffix)
|
||||
{
|
||||
int suf_len = strlen(fn_suffix);
|
||||
PRUint32 nel;
|
||||
PRUint32 i;
|
||||
|
||||
for (i=0, nel=0; i < zip->nel; i++) {
|
||||
char *fn = zip->dir[i].fn;
|
||||
int fn_len = strlen(fn);
|
||||
if (strncasecmp(&fn[fn_len - suf_len], fn_suffix, suf_len) == 0) {
|
||||
nel++;
|
||||
}
|
||||
}
|
||||
return nel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a list of files in the archive that match the filename suffix
|
||||
*/
|
||||
PR_PUBLIC_API(PRUint32)
|
||||
ns_zip_list_files(ns_zip_t *zip, const char *fn_suffix, void HUGEP *buf, PRUint32 len)
|
||||
{
|
||||
int suf_len = strlen(fn_suffix);
|
||||
PRUint32 nel;
|
||||
PRUint32 i;
|
||||
char HUGEP *buf_ptr = buf;
|
||||
char HUGEP *buf_end_ptr = buf_ptr + len;
|
||||
|
||||
for (i=0, nel=0; i < zip->nel; i++) {
|
||||
char *fn = zip->dir[i].fn;
|
||||
int fn_len = strlen(fn);
|
||||
if ((strncasecmp(&fn[fn_len - suf_len], fn_suffix, suf_len) == 0) &&
|
||||
((buf_ptr + fn_len) < buf_end_ptr)) {
|
||||
nel++;
|
||||
NS_ZIP_STRCPY(buf_ptr, fn);
|
||||
buf_ptr += fn_len+1;
|
||||
}
|
||||
}
|
||||
return nel;
|
||||
}
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
|
@ -194,7 +194,7 @@ public:
|
|||
NS_IMETHOD DeleteBranch(const char *branchName);
|
||||
|
||||
NS_IMETHOD CreateChildList(const char* parent_node, char **child_list);
|
||||
NS_IMETHOD NextChild(const char *child_list, PRInt16 *index, char **listchild);
|
||||
NS_IMETHOD NextChild(const char *child_list, PRInt16 *indx, char **listchild);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -272,7 +272,7 @@ nsresult nsPref::useDefaultPrefFile()
|
|||
// There is no locator component. Or perhaps there is a locator, but the
|
||||
// locator couldn't find where to put it. So put it in the cwd (NB, viewer comes here.)
|
||||
// #include nsIComponentManager.h
|
||||
nsresult rv = nsComponentManager::CreateInstance(
|
||||
rv = nsComponentManager::CreateInstance(
|
||||
(const char*)NS_FILESPEC_PROGID,
|
||||
(nsISupports*)nsnull,
|
||||
(const nsID&)nsIFileSpec::GetIID(),
|
||||
|
@ -915,7 +915,7 @@ NS_IMETHODIMP nsPref::SetFilePref(const char *pref_name,
|
|||
// nsPersistentFileDescriptor requires an existing
|
||||
// object. Make it first. COM makes this difficult, of course...
|
||||
nsIFileSpec* tmp = nsnull;
|
||||
nsresult rv = nsComponentManager::CreateInstance(
|
||||
rv = nsComponentManager::CreateInstance(
|
||||
(const char*)NS_FILESPEC_PROGID,
|
||||
(nsISupports*)nsnull,
|
||||
(const nsID&)nsIFileSpec::GetIID(),
|
||||
|
@ -1082,13 +1082,13 @@ NS_IMETHODIMP nsPref::CreateChildList(const char* parent_node, char **child_list
|
|||
return (pcs.childList == NULL) ? PREF_OUT_OF_MEMORY : PREF_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPref::NextChild(const char *child_list, PRInt16 *index, char **listchild)
|
||||
NS_IMETHODIMP nsPref::NextChild(const char *child_list, PRInt16 *indx, char **listchild)
|
||||
{
|
||||
char* temp = (char*)&child_list[*index];
|
||||
char* temp = (char*)&child_list[*indx];
|
||||
char* child = strtok(temp, ";");
|
||||
if (child)
|
||||
{
|
||||
*index += strlen(child) + 1;
|
||||
*indx += strlen(child) + 1;
|
||||
*listchild = child;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1395,7 +1395,7 @@ extern "C" JSBool pref_InitInitialObjects()
|
|||
// Skip files in the special list.
|
||||
if (shouldParse)
|
||||
{
|
||||
for (int j = 0; j < sizeof(specialFiles) / sizeof(char*); j++)
|
||||
for (int j = 0; j < (int) (sizeof(specialFiles) / sizeof(char*)); j++)
|
||||
if (strcmp(leafName, specialFiles[j]) == 0)
|
||||
shouldParse = PR_FALSE;
|
||||
}
|
||||
|
@ -1414,7 +1414,7 @@ extern "C" JSBool pref_InitInitialObjects()
|
|||
NS_IF_RELEASE(child);
|
||||
}
|
||||
// Finally, parse any other special files (platform-specific ones).
|
||||
for (k = 1; k < sizeof(specialFiles) / sizeof(char*); k++)
|
||||
for (k = 1; k < (int) (sizeof(specialFiles) / sizeof(char*)); k++)
|
||||
{
|
||||
nsIFileSpec* specialChild2;
|
||||
if (NS_FAILED(locator->GetFileLocation(nsSpecialFileSpec::App_ComponentsDirectory, &specialChild2)))
|
||||
|
|
|
@ -124,7 +124,7 @@ NET_SortInsert(SortStruct * sort_struct, void * insert_before, void * new_object
|
|||
MODULE_PRIVATE void
|
||||
NET_DoSort(SortStruct * sort_struct, int (*compar) (const void *, const void *, void *))
|
||||
{
|
||||
NS_QuickSort(sort_struct->list, sort_struct->num_entries, sizeof(void *), compar, NULL);
|
||||
NS_QuickSort(sort_struct->list, (unsigned int) (sort_struct->num_entries), sizeof(void *), compar, NULL);
|
||||
}
|
||||
|
||||
/* unloads backwards :(
|
||||
|
|
Загрузка…
Ссылка в новой задаче