Exemplo n.º 1
0
void csArchive::ReadZipEntries (FILE *infile)
{
  size_t cur_offs, new_offs;
  char buff[1024];
  ZIP_central_directory_file_header cdfh;
  ZIP_local_file_header lfh;

  cur_offs = 0;
  while ((fread (buff, 1, sizeof (hdr_local), infile) >= sizeof (hdr_local))
         && (memcmp (buff, hdr_local, sizeof (hdr_local)) == 0)
         && (ReadLFH (lfh, infile)))
  {
    new_offs = cur_offs + sizeof (hdr_local) + ZIP_LOCAL_FILE_HEADER_SIZE +
      lfh.filename_length + lfh.extra_field_length + lfh.csize;
    if ((lfh.filename_length > sizeof (buff))
        || (fread (buff, 1, lfh.filename_length, infile) < lfh.filename_length))
      return;                   /* Broken zipfile? */
    buff[lfh.filename_length] = 0;

    if ((buff[lfh.filename_length - 1] != '/')
        && (buff[lfh.filename_length - 1] != PATH_SEPARATOR))
    {
      /* Partialy convert lfh to cdfh */
      memset (&cdfh, 0, sizeof (cdfh));
      cdfh.version_needed_to_extract[0] = lfh.version_needed_to_extract[0];
      cdfh.version_needed_to_extract[1] = lfh.version_needed_to_extract[1];
      cdfh.general_purpose_bit_flag = lfh.general_purpose_bit_flag;
      cdfh.compression_method = lfh.compression_method;
      cdfh.last_mod_file_time = lfh.last_mod_file_time;
      cdfh.last_mod_file_date = lfh.last_mod_file_date;
      cdfh.crc32 = lfh.crc32;
      cdfh.csize = lfh.csize;
      cdfh.ucsize = lfh.ucsize;
      cdfh.relative_offset_local_header = cur_offs;

      ArchiveEntry *curentry = InsertEntry (buff, cdfh);

      if (!curentry->ReadExtraField (infile, lfh.extra_field_length))
        return;                 /* Broken zipfile */
    } /* endif */
    if (fseek (infile, cur_offs = new_offs, SEEK_SET))
      return;                   /* Broken zipfile */
  } /* endwhile */
}
Exemplo n.º 2
0
void csArchive::ReadZipDirectory (FILE *infile)
{
  ZIP_end_central_dir_record ecdr;
  ZIP_central_directory_file_header cdfh;
  char buff[1024];              /* Read ZIPfile from end in 1K chunks */
  size_t cur_offs, min_offs, central_directory_offset;
  size_t step = ZIP_END_CENTRAL_DIR_RECORD_SIZE + sizeof (hdr_endcentral);

  if (!infile)
    return;                     /* File not open */
  if (fseek (infile, 0, SEEK_END))
    return;                     /* Seek error */
  if ((long) (cur_offs = ftell (infile)) == -1)
    return;                     /* Can't get file position */

  if (cur_offs >= (65535 + ZIP_END_CENTRAL_DIR_RECORD_SIZE + sizeof (hdr_endcentral)))
    min_offs = cur_offs - (65535 + ZIP_END_CENTRAL_DIR_RECORD_SIZE + sizeof (hdr_endcentral));
  else
    min_offs = 0;

  /* Try to find ZIPfile central directory structure */
  /* For this we have to search from end of file the signature "PK" */
  /* after which follows a two-byte END_CENTRAL_SIG */
  while (cur_offs > min_offs)
  {
    UInt search_pos;

    if (cur_offs >= sizeof (buff) - step)
      cur_offs -= sizeof (buff) - step;
    else
      cur_offs = 0;

    fseek (infile, cur_offs, SEEK_SET);
    search_pos = fread (buff, 1, sizeof (buff), infile);
    if (search_pos >= step)
    {
      register char *search_ptr;

      for (search_ptr = &buff[search_pos - step]; search_ptr > buff; search_ptr--)
        if ((*search_ptr == 'P') &&
            (memcmp (search_ptr, hdr_endcentral, sizeof (hdr_endcentral)) == 0))
        {
          /* Central directory structure found */
          central_directory_offset = cur_offs + (ULong) search_ptr - (ULong)buff;
          LoadECDR (ecdr, &search_ptr[sizeof (hdr_endcentral)]);
          if (fseek (infile, central_directory_offset + sizeof (hdr_endcentral) + ZIP_END_CENTRAL_DIR_RECORD_SIZE, SEEK_SET)
           || !ReadArchiveComment (infile, ecdr.zipfile_comment_length)
           || fseek (infile, ecdr.offset_start_central_directory, SEEK_SET))
            goto rebuild_cdr;   /* Broken central directory */

          /* Now read central directory structure */
          for (;;)
          {
            if ((fread (buff, 1, sizeof (hdr_central), infile) < sizeof (hdr_central))
             || (memcmp (buff, hdr_central, sizeof (hdr_central)) != 0))
            {
              if (dir.Length ())
                return;         /* Finished reading central directory */
              else
                goto rebuild_cdr;       /* Broken central directory */
            }
            if ((!ReadCDFH (cdfh, infile))
             || (cdfh.filename_length > sizeof (buff))
             || (fread (buff, 1, cdfh.filename_length, infile) < cdfh.filename_length))
              return;           /* Broken zipfile? */
            buff[cdfh.filename_length] = 0;

            if ((buff[cdfh.filename_length - 1] == PATH_SEPARATOR)
             || (buff[cdfh.filename_length - 1] == PATH_SEPARATOR_2))
            {
              if (fseek (infile, cdfh.extra_field_length + cdfh.file_comment_length, SEEK_CUR))
                return;         /* Broken zipfile? */
              continue;
            } /* endif */

            ArchiveEntry *curentry = InsertEntry (buff, cdfh);
            if (!curentry->ReadExtraField (infile, cdfh.extra_field_length)
             || !curentry->ReadFileComment (infile, cdfh.file_comment_length))
              return;         /* Broken zipfile? */
          } /* endfor */
        } /* endif */
    } /* endif */
  } /* endwhile */

rebuild_cdr:
  /* If we are here, we did not succeeded to read central directory */
  /* If so, we have to rebuild it by reading each ZIPfile member separately */
  if (fseek (infile, 0, SEEK_SET))
    return;
  ReadZipEntries (infile);
}