📄 jar.c
字号:
/*0465./ * info: Arg passed to loadJARFileEntries
/*0466./ *=======================================================================*/
/*0467*/
/*0468*/void
/*0469*/loadJARFileEntries(JAR_INFO entry,
/*0470*/ JARFileTestFunction testFunction,
/*0471*/ JARFileRunFunction runFunction,
/*0472*/ void *info)
/*0473*/{
/*0474*/ const char *name;
/*0475*/ unsigned int nameLength;
/*0476*/
/*0477*/#if JAR_FILES_USE_STDIO
/*0478*/ unsigned char *p = (unsigned char *)str_buffer; /* temporary storage */
/*0479*/ FILE *file = entry->u.jar.file;
/*0480*/ unsigned long offset = entry->u.jar.cenOffset;
/*0481*/#else
/*0482*/ /* Start at the beginning of the central header */
/*0483*/ unsigned const char *p = entry->u.mjar.cenPtr;
/*0484*/#endif
/*0485*/ for (;;) {
/*0486*/
/*0487*/#if JAR_FILES_USE_STDIO
/*0488*/ if (/* Go to the next central header */
/*0489*/ (fseek(file, offset, SEEK_SET) < 0)
/*0490*/ /* Read the bytes */
/*0491*/ || (fread(p, sizeof(char), CENHDRSIZ, file) != CENHDRSIZ)
/*0492*/ ) {
/*0493*/ break;
/*0494*/ }
/*0495*/ /* Set offset to the next central header */
/*0496*/#endif
/*0497*/ if (GETSIG(p) != CENSIG) {
/*0498*/ /* We've reached the end of the headers */
/*0499*/ break;
/*0500*/ }
/*0501*/
/*0502*/ name = (const char *)p + CENHDRSIZ;
/*0503*/ nameLength = CENNAM(p);
/*0504*/
/*0505*/#if JAR_FILES_USE_STDIO
/*0506*/ if (fread(p+CENHDRSIZ, sizeof(char), nameLength, file) != nameLength) {
/*0507*/ break;
/*0508*/ }
/*0509*/ /* We need to update the offset now, rather than later, since
/*0510./ * the temporary buffer might get overwritten.
/*0511./ */
/*0512*/ offset += CENHDRSIZ + nameLength + CENEXT(p) + CENCOM(p);
/*0513*/#endif
/*0514*/ if (name[nameLength - 1] != '/') {
/*0515*/ START_TEMPORARY_ROOTS
/*0516*/ DECLARE_TEMPORARY_ROOT(JAR_INFO, entryX, entry);
/*0517*/ int extraBytes = 0;
/*0518*/ if (testFunction(name, nameLength, &extraBytes, info)) {
/*0519*/ long length;
/*0520*/ unsigned char *value =
/*0521*/ loadJARFileEntryInternal(entryX, p, &length, extraBytes);
/*0522*/ runFunction(name, nameLength, value, length, info);
/*0523*/ }
/*0524*/ entry = entryX;
/*0525*/ END_TEMPORARY_ROOTS
/*0526*/ }
/*0527*/#if !JAR_FILES_USE_STDIO
/*0528*/ p += CENHDRSIZ + nameLength + CENEXT(p) + CENCOM(p);
/*0529*/#endif
/*0530*/ }
/*0531*/}
/*0532*/
/*0533*//*=========================================================================
/*0534./ * FUNCTION: loadJARFileEntryInternal()
/*0535./ * OVERVIEW: Internal function for reading a jar file
/*0536./ *
/*0537./ * parameters:
/*0538./ * JAR_INFO: structure returned by openJARFile.
/*0539./ * centralInfo: pointer to info in central directory for this entry
/*0540./ * lengthP: On return, contains length of the entry (not including
/*0541./ * padding caused by extraBytes)
/*0542./ * extraBytes: Pad the entry with this many extra bytes at the front.
/*0543./ * returns:
/*0544./ * result of decompressing the Jar entry.
/*0545./ *
/*0546./ * NOTE: If JAR_FILES_USE_STDIO, then centralInfo points at str_buffer,
/*0547./ * which contains the central header. If !JAR_FILES_USE_STDIO, then
/*0548./ * centralInfo points at the actual bytes.
/*0549./ */
/*0550*/
/*0551*/static void *
/*0552*/loadJARFileEntryInternal(JAR_INFO entry, const unsigned char *centralInfo,
/*0553*/ long *lengthP, int extraBytes)
/*0554*/{
/*0555*/ unsigned long decompLen = CENLEN(centralInfo); /* the decompressed length */
/*0556*/ unsigned long compLen = CENSIZ(centralInfo); /* the compressed length */
/*0557*/ unsigned long method = CENHOW(centralInfo); /* how it is stored */
/*0558*/ unsigned long expectedCRC = CENCRC(centralInfo); /* expected CRC */
/*0559*/ unsigned long actualCRC;
/*0560*/ unsigned char *result = NULL;
/*0561*/
/*0562*/#if JAR_FILES_USE_STDIO
/*0563*/ FILE *file = entry->u.jar.file;
/*0564*/ unsigned long locOffset = entry->u.jar.locOffset;
/*0565*/ unsigned char *p = (unsigned char *)str_buffer;
/*0566*/#else
/*0567*/ unsigned const char *locPtr = entry->u.mjar.locPtr;
/*0568*/ const unsigned char *p;
/*0569*/#endif
/*0570*/
/*0571*/ /* Make sure file is not encrypted */
/*0572*/ if ((CENFLG(centralInfo) & 1) == 1) {
/*0573*/ goto errorReturn;
/*0574*/ }
/*0575*/
/*0576*/ /* This may cause a GC, so we have to extract out of "entry" all the
/*0577./ * info we need, before calling this.
/*0578./ */
/*0579*/ result = (unsigned char *)mallocBytes(extraBytes + decompLen);
/*0580*/#if !COMPILING_FOR_KVM
/*0581*/ if (result == NULL) {
/*0582*/ goto errorReturn;
/*0583*/ }
/*0584*/#endif
/*0585*/
/*0586*/#if JAR_FILES_USE_STDIO
/*0587*/ if (/* Go to the beginning of the LOC header */
/*0588*/ (fseek(file, locOffset + CENOFF(centralInfo), SEEK_SET) < 0)
/*0589*/ /* Read it */
/*0590*/ || (fread(p, sizeof(char), LOCHDRSIZ, file) != LOCHDRSIZ)
/*0591*/ /* Skip over name and extension, if any */
/*0592*/ || (fseek(file, LOCNAM(p) + LOCEXT(p), SEEK_CUR) < 0)) {
/*0593*/ goto errorReturn;
/*0594*/ }
/*0595*/#else
/*0596*/ /* Go to the beginning of the LOC header */
/*0597*/ p = locPtr + CENOFF(centralInfo);
/*0598*/ /* Skip over the actual bits of the header */
/*0599*/ p += LOCHDRSIZ + LOCNAM(p) + LOCEXT(p);
/*0600*/#endif
/*0601*/
/*0602*/ switch (method) {
/*0603*/ case STORED:
/*0604*/ /* The actual bits are right there in the file */
/*0605*/ if (compLen != decompLen) {
/*0606*/ goto errorReturn;
/*0607*/ }
/*0608*/#if JAR_FILES_USE_STDIO
/*0609*/ fread(result + extraBytes, sizeof(char), decompLen, file);
/*0610*/#else
/*0611*/ memcpy(result + extraBytes, p, decompLen);
/*0612*/#endif
/*0613*/ break;
/*0614*/
/*0615*/ case DEFLATED: {
/*0616*/ bool_t inflateOK;
/*0617*/ START_TEMPORARY_ROOTS
/*0618*/ DECLARE_TEMPORARY_ROOT_FROM_BASE(unsigned char*,
/*0619*/ decompData,
/*0620*/ result + extraBytes, result);
/*0621*/#if JAR_FILES_USE_STDIO
/*0622*/ void *arg = file;
/*0623*/#else
/*0624*/ void *arg = &p;
/*0625*/#endif
/*0626*/ inflateOK = inflate(arg, jar_getByte, compLen,
/*0627*/ &decompData, decompLen);
/*0628*/ /* The inflater can allocate memory, so we need to regenerate
/*0629./ * value from decompData. */
/*0630*/ result = decompData - extraBytes;
/*0631*/ END_TEMPORARY_ROOTS
/*0632*/ if (!inflateOK) {
/*0633*/ goto errorReturn;
/*0634*/ }
/*0635*/ break;
/*0636*/ }
/*0637*/
/*0638*/ default:
/*0639*/ /* Unknown method */
/*0640*/ goto errorReturn;
/*0641*/ break;
/*0642*/ }
/*0643*/
/*0644*/ if (result != NULL) {
/*0645*/ actualCRC = jarCRC32(result + extraBytes, decompLen);
/*0646*/ if (actualCRC != expectedCRC) {
/*0647*/ goto errorReturn;
/*0648*/ }
/*0649*/ }
/*0650*/ *lengthP = decompLen;
/*0651*/ return (void *)result;
/*0652*/
/*0653*/errorReturn:
/*0654*/ freeBytes(result);
/*0655*/ *lengthP = 0;
/*0656*/ return NULL;
/*0657*/}
/*0658*/
/*0659*//*=========================================================================
/*0660./ * FUNCTION: jarCRC32
/*0661./ * OVERVIEW: Returns the CRC of an array of bytes, using the same
/*0662./ * algorithm as used by the JAR reader.
/*0663./ * INTERFACE:
/*0664./ * parameters: data: pointer to the array of bytes
/*0665./ * length: length of data, in bytes
/*0666./ * returns: CRC
/*0667./ *=======================================================================*/
/*0668*/
/*0669*/static unsigned long
/*0670*/jarCRC32(unsigned char *data, unsigned long length) {
/*0671*/ unsigned long crc = 0xFFFFFFFF;
/*0672*/ unsigned int j;
/*0673*/ for ( ; length > 0; length--, data++) {
/*0674*/ crc ^= *data;
/*0675*/ for (j = 8; j > 0; --j) {
/*0676*/ crc = (crc & 1) ? ((crc >> 1) ^ 0xedb88320) : (crc >> 1);
/*0677*/ }
/*0678*/ }
/*0679*/ return ~crc;
/*0680*/}
/*0681*/
/*0682*//*
/*0683./ * Callback passed to inflate, to read the next byte of data.
/*0684./ */
/*0685*/static int
/*0686*/jar_getByte(void* p) {
/*0687*/#if JAR_FILES_USE_STDIO
/*0688*/ return getc((FILE*)p);
/*0689*/#else
/*0690*/ return *(*(unsigned char **)p)++;
/*0691*/#endif
/*0692*/}
/*0693*/
/*0694*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -