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 + -
显示快捷键?