This commit is contained in:
sspitzer%netscape.com 1999-07-03 00:39:28 +00:00
Родитель af6b377f29
Коммит 43c3f19b1c
3 изменённых файлов: 9 добавлений и 968 удалений

Просмотреть файл

@ -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 :(