jarfile.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,150 行 · 第 1/2 页
C
1,150 行
static int jar_extract_manifests (JAR *jar, jarArch format, JAR_FILE fp) { int status; if (format != jarArchZip && format != jarArchTar) return JAR_ERR_CORRUPT; if ((status = jar_extract_mf (jar, format, fp, "mf")) < 0) return status; if ((status = jar_extract_mf (jar, format, fp, "sf")) < 0) return status; if ((status = jar_extract_mf (jar, format, fp, "rsa")) < 0) return status; if ((status = jar_extract_mf (jar, format, fp, "dsa")) < 0) return status; return 0; }/* * j a r _ e x t r a c t _ m f * * Extracts manifest files based on an extension, which * should be .MF, .SF, .RSA, etc. Order of the files is now no * longer important when zipping jar files. * */static int jar_extract_mf (JAR *jar, jarArch format, JAR_FILE fp, char *ext) { JAR_Item *it; JAR_Physical *phy; ZZLink *link; ZZList *list; char *fn, *e; char ZHUGEP *manifest; long length; int status, ret = 0, num; list = jar->phy; if (ZZ_ListEmpty (list)) return JAR_ERR_PNF; for (link = ZZ_ListHead (list); !ZZ_ListIterDone (list, link); link = link->next) { it = link->thing; if (it->type == jarTypePhy && !PORT_Strncmp (it->pathname, "META-INF", 8)) { phy = (JAR_Physical *) it->data; if (PORT_Strlen (it->pathname) < 8) continue; fn = it->pathname + 8; if (*fn == '/' || *fn == '\\') fn++; if (*fn == 0) { /* just a directory entry */ continue; } /* skip to extension */ for (e = fn; *e && *e != '.'; e++) /* yip */ ; /* and skip dot */ if (*e == '.') e++; if (PORT_Strcasecmp (ext, e)) { /* not the right extension */ continue; } if (phy->length == 0) { /* manifest files cannot be zero length! */ return JAR_ERR_CORRUPT; } /* Read in the manifest and parse it */ /* FIX? Does this break on win16 for very very large manifest files? */#ifdef XP_WIN16 PORT_Assert( phy->length+1 < 0xFFFF );#endif manifest = (char ZHUGEP *) PORT_ZAlloc (phy->length + 1); if (manifest) { JAR_FSEEK (fp, phy->offset, (PRSeekWhence)0); num = JAR_FREAD (fp, manifest, phy->length); if (num != phy->length) { /* corrupt archive file */ return JAR_ERR_CORRUPT; } if (phy->compression == 8) { length = phy->length; status = jar_inflate_memory ((unsigned int) phy->compression, &length, phy->uncompressed_length, &manifest); if (status < 0) return status; } else if (phy->compression) { /* unsupported compression method */ return JAR_ERR_CORRUPT; } else length = phy->length; status = JAR_parse_manifest (jar, manifest, length, it->pathname, "url"); PORT_Free (manifest); if (status < 0 && ret == 0) ret = status; } else return JAR_ERR_MEMORY; } else if (it->type == jarTypePhy) { /* ordinary file */ } } return ret; }/* * j a r _ g e n _ i n d e x * * Generate an index for the various types of * known archive files. Right now .ZIP and .TAR * */static int jar_gen_index (JAR *jar, jarArch format, JAR_FILE fp) { int result = JAR_ERR_CORRUPT; JAR_FSEEK (fp, 0, (PRSeekWhence)0); switch (format) { case jarArchZip: result = jar_listzip (jar, fp); break; case jarArchTar: result = jar_listtar (jar, fp); break; } JAR_FSEEK (fp, 0, (PRSeekWhence)0); return result; }/* * j a r _ l i s t z i p * * List the physical contents of a Phil Katz * style .ZIP file into the JAR linked list. * */static int jar_listzip (JAR *jar, JAR_FILE fp) { int err = 0; long pos = 0L; char filename [JAR_SIZE]; char date [9], time [9]; char sig [4]; unsigned int compression; unsigned int filename_len, extra_len; struct ZipLocal *Local; struct ZipCentral *Central; struct ZipEnd *End; /* phy things */ ZZLink *ent; JAR_Item *it; JAR_Physical *phy; Local = (struct ZipLocal *) PORT_ZAlloc (30); Central = (struct ZipCentral *) PORT_ZAlloc (46); End = (struct ZipEnd *) PORT_ZAlloc (22); if (!Local || !Central || !End) { /* out of memory */ err = JAR_ERR_MEMORY; goto loser; } while (1) { JAR_FSEEK (fp, pos, (PRSeekWhence)0); if (JAR_FREAD (fp, (char *) sig, 4) != 4) { /* zip file ends prematurely */ err = JAR_ERR_CORRUPT; goto loser; } JAR_FSEEK (fp, pos, (PRSeekWhence)0); if (xtolong ((unsigned char *)sig) == LSIG) { JAR_FREAD (fp, (char *) Local, 30); filename_len = xtoint ((unsigned char *) Local->filename_len); extra_len = xtoint ((unsigned char *) Local->extrafield_len); if (filename_len >= JAR_SIZE) { /* corrupt zip file */ err = JAR_ERR_CORRUPT; goto loser; } if (JAR_FREAD (fp, filename, filename_len) != filename_len) { /* truncated archive file */ err = JAR_ERR_CORRUPT; goto loser; } filename [filename_len] = 0; /* Add this to our jar chain */ phy = (JAR_Physical *) PORT_ZAlloc (sizeof (JAR_Physical)); if (phy == NULL) { err = JAR_ERR_MEMORY; goto loser; } /* We will index any file that comes our way, but when it comes to actually extraction, compression must be 0 or 8 */ compression = xtoint ((unsigned char *) Local->method); phy->compression = compression >= 0 && compression <= 255 ? compression : 222; phy->offset = pos + 30 + filename_len + extra_len; phy->length = xtolong ((unsigned char *) Local->size); phy->uncompressed_length = xtolong((unsigned char *) Local->orglen); dosdate (date, Local->date); dostime (time, Local->time); it = (JAR_Item*)PORT_ZAlloc (sizeof (JAR_Item)); if (it == NULL) { err = JAR_ERR_MEMORY; goto loser; } it->pathname = PORT_Strdup (filename); it->type = jarTypePhy; it->data = (unsigned char *) phy; it->size = sizeof (JAR_Physical); ent = ZZ_NewLink (it); if (ent == NULL) { err = JAR_ERR_MEMORY; goto loser; } ZZ_AppendLink (jar->phy, ent); pos = phy->offset + phy->length; } else if (xtolong ( (unsigned char *)sig) == CSIG) { if (JAR_FREAD (fp, (char *) Central, 46) != 46) { /* apparently truncated archive */ err = JAR_ERR_CORRUPT; goto loser; }#ifdef XP_UNIX /* with unix we need to locate any bits from the protection mask in the external attributes. */ { unsigned int attr; /* determined empirically */ attr = Central->external_attributes [2]; if (attr) { /* we have to read the filename, again */ filename_len = xtoint ((unsigned char *) Central->filename_len); if (filename_len >= JAR_SIZE) { /* corrupt in central directory */ err = JAR_ERR_CORRUPT; goto loser; } if (JAR_FREAD (fp, filename, filename_len) != filename_len) { /* truncated in central directory */ err = JAR_ERR_CORRUPT; goto loser; } filename [filename_len] = 0; /* look up this name again */ phy = jar_get_physical (jar, filename); if (phy) { /* always allow access by self */ phy->mode = 0400 | attr; } } }#endif pos += 46 + xtoint ( (unsigned char *)Central->filename_len) + xtoint ( (unsigned char *)Central->commentfield_len) + xtoint ( (unsigned char *)Central->extrafield_len); } else if (xtolong ( (unsigned char *)sig) == ESIG) { if (JAR_FREAD (fp, (char *) End, 22) != 22) { err = JAR_ERR_CORRUPT; goto loser; } else break; } else { /* garbage in archive */ err = JAR_ERR_CORRUPT; goto loser; } }loser: if (Local) PORT_Free (Local); if (Central) PORT_Free (Central); if (End) PORT_Free (End); return err; }/* * j a r _ l i s t t a r * * List the physical contents of a Unix * .tar file into the JAR linked list. * */static int jar_listtar (JAR *jar, JAR_FILE fp) { long pos = 0L; long sz, mode; time_t when; union TarEntry tarball; char *s; /* phy things */ ZZLink *ent; JAR_Item *it; JAR_Physical *phy; while (1) { JAR_FSEEK (fp, pos, (PRSeekWhence)0); if (JAR_FREAD (fp, (char *) &tarball, 512) < 512) break; if (!*tarball.val.filename) break; when = atoo (tarball.val.time); sz = atoo (tarball.val.size); mode = atoo (tarball.val.mode); /* Tag the end of filename */ s = tarball.val.filename; while (*s && *s != ' ') s++; *s = 0; /* Add to our linked list */ phy = (JAR_Physical *) PORT_ZAlloc (sizeof (JAR_Physical)); if (phy == NULL) return JAR_ERR_MEMORY; phy->compression = 0; phy->offset = pos + 512; phy->length = sz; ADDITEM (jar->phy, jarTypePhy, tarball.val.filename, phy, sizeof (JAR_Physical)); /* Advance to next file entry */ sz += 511; sz = (sz / 512) * 512; pos += sz + 512; } return 0; }/* * d o s d a t e * * Not used right now, but keep it in here because * it will be needed. * */static int dosdate (char *date, char *s) { int num = xtoint ( (unsigned char *)s); PR_snprintf (date, 9, "%02d-%02d-%02d", ((num >> 5) & 0x0F), (num & 0x1F), ((num >> 9) + 80)); return 0; }/* * d o s t i m e * * Not used right now, but keep it in here because * it will be needed. * */static int dostime (char *time, char *s) { int num = xtoint ( (unsigned char *)s); PR_snprintf (time, 6, "%02d:%02d", ((num >> 11) & 0x1F), ((num >> 5) & 0x3F)); return 0; }/* * x t o i n t * * Converts a two byte ugly endianed integer * to our platform's integer. * */static unsigned int xtoint (unsigned char *ii) { return (int) (ii [0]) | ((int) ii [1] << 8); }/* * x t o l o n g * * Converts a four byte ugly endianed integer * to our platform's integer. * */static unsigned long xtolong (unsigned char *ll) { unsigned long ret; ret = ( (((unsigned long) ll [0]) << 0) | (((unsigned long) ll [1]) << 8) | (((unsigned long) ll [2]) << 16) | (((unsigned long) ll [3]) << 24) ); return ret; }/* * a t o o * * Ascii octal to decimal. * Used for integer encoding inside tar files. * */static long atoo (char *s) { long num = 0L; while (*s == ' ') s++; while (*s >= '0' && *s <= '7') { num <<= 3; num += *s++ - '0'; } return num; }/* * g u e s s _ j a r * * Try to guess what kind of JAR file this is. * Maybe tar, maybe zip. Look in the file for magic * or at its filename. * */static int jar_guess_jar (char *filename, JAR_FILE fp) { char *ext; ext = filename + PORT_Strlen (filename) - 4; if (!PORT_Strcmp (ext, ".tar")) return jarArchTar; return jarArchZip; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?