Пример #1
0
nsresult
nsJARInputStream::InitFile(nsJAR *aJar, nsZipItem *item)
{
    nsresult rv = NS_OK;
    MOZ_ASSERT(aJar, "Argument may not be null");
    MOZ_ASSERT(item, "Argument may not be null");

    // Mark it as closed, in case something fails in initialisation
    mMode = MODE_CLOSED;
    //-- prepare for the compression type
    switch (item->Compression()) {
       case STORED: 
           mMode = MODE_COPY;
           break;

       case DEFLATED:
           rv = gZlibInit(&mZs);
           NS_ENSURE_SUCCESS(rv, rv);
    
           mMode = MODE_INFLATE;
           mInCrc = item->CRC32();
           mOutCrc = crc32(0L, Z_NULL, 0);
           break;

#ifdef MOZ_JAR_BROTLI
       case MOZ_JAR_BROTLI:
           mBrotliState = BrotliCreateState(nullptr, nullptr, nullptr);
           mMode = MODE_BROTLI;
           mInCrc = item->CRC32();
           mOutCrc = crc32(0L, Z_NULL, 0);
           break;
#endif

       default:
           return NS_ERROR_NOT_IMPLEMENTED;
    }
   
    // Must keep handle to filepointer and mmap structure as long as we need access to the mmapped data
    mFd = aJar->mZip->GetFD();
    mZs.next_in = (Bytef *)aJar->mZip->GetData(item);
    if (!mZs.next_in) {
        nsZipArchive::sFileCorruptedReason = "nsJARInputStream: !mZs.next_in";
        return NS_ERROR_FILE_CORRUPTED;
    }
    mZs.avail_in = item->Size();
    mOutSize = item->RealSize();
    mZs.total_out = 0;
    return NS_OK;
}
Пример #2
0
nsresult
nsJARInputStream::InitFile(nsZipArchive* aZip, nsZipItem *item, PRFileDesc *fd)
{
    nsresult rv;

    // Keep the file handle, even on failure
    mFd = fd;
      
    NS_ENSURE_ARG_POINTER(aZip);
    NS_ENSURE_ARG_POINTER(item);
    NS_ENSURE_ARG_POINTER(fd);

    // Mark it as closed, in case something fails in initialisation
    mClosed = PR_TRUE;

    // Keep the important bits of nsZipItem only
    mInSize = item->size;
 
    //-- prepare for the compression type
    switch (item->compression) {
       case STORED: 
           break;

       case DEFLATED:
           mInflate = (InflateStruct *) PR_Malloc(sizeof(InflateStruct));
           NS_ENSURE_TRUE(mInflate, NS_ERROR_OUT_OF_MEMORY);
    
           rv = gZlibInit(&(mInflate->mZs));
           NS_ENSURE_SUCCESS(rv, NS_ERROR_OUT_OF_MEMORY);
    
           mInflate->mOutSize = item->realsize;
           mInflate->mInCrc = item->crc32;
           mInflate->mOutCrc = crc32(0L, Z_NULL, 0);
           break;

       default:
           return NS_ERROR_NOT_IMPLEMENTED;
    }
   
    //-- Set filepointer to start of item
    rv = aZip->SeekToItem(item, mFd);
    NS_ENSURE_SUCCESS(rv, NS_ERROR_FILE_CORRUPTED);
        
    // Open for reading
    mClosed = PR_FALSE;
    mCurPos = 0;
    return NS_OK;
}
Пример #3
0
//---------------------------------------------
// nsZipArchive::InflateItem
//---------------------------------------------
nsresult nsZipArchive::InflateItem(const nsZipItem* aItem, PRFileDesc* outFD)
/*
 * This function inflates an archive item to disk, to the
 * file specified by outFD. If outFD is zero, the extracted data is
 * not written, only checked for CRC, so this is in effect same as 'Test'.
 */
{
  PR_ASSERT(aItem);

  //-- allocate deflation buffers
  Bytef inbuf[ZIP_BUFLEN];
  Bytef outbuf[ZIP_BUFLEN];

  //-- set up the inflate
  z_stream    zs;
  nsresult status = gZlibInit(&zs);
  if (status != ZIP_OK)
    return ZIP_ERR_GENERAL;

  //-- inflate loop
  zs.next_out = outbuf;
  zs.avail_out = ZIP_BUFLEN;

  PRUint32  size = aItem->size;
  PRUint32  outpos = 0;
  PRUint32  crc = crc32(0L, Z_NULL, 0);
  int       zerr = Z_OK;
  while (zerr == Z_OK)
  {
    PRBool      bRead = PR_FALSE;
    PRBool      bWrote= PR_FALSE;

    if (zs.avail_in == 0 && zs.total_in < size)
    {
      //-- no data to inflate yet still more in file:
      //-- read another chunk of compressed data
      PRUint32 chunk = (size-zs.total_in < ZIP_BUFLEN) ? size-zs.total_in : ZIP_BUFLEN;

      if (PR_Read(mFd, inbuf, chunk) != (READTYPE)chunk)
      {
        //-- unexpected end of data
        status = ZIP_ERR_CORRUPT;
        break;
      }

      zs.next_in  = inbuf;
      zs.avail_in = chunk;
      bRead       = PR_TRUE;
    }

    if (zs.avail_out == 0)
    {
      //-- write inflated buffer to disk and make space
      if (outFD && PR_Write(outFD, outbuf, ZIP_BUFLEN) < ZIP_BUFLEN)
      {
        //-- Couldn't write all the data (disk full?)
        status = ZIP_ERR_DISK;
        break;
      }

      outpos = zs.total_out;
      zs.next_out  = outbuf;
      zs.avail_out = ZIP_BUFLEN;
      bWrote       = PR_TRUE;
    }

    if(bRead || bWrote)
    {
      Bytef* old_next_out = zs.next_out;

      zerr = inflate(&zs, Z_PARTIAL_FLUSH);

      //-- incrementally update crc32
      crc = crc32(crc, (const unsigned char*)old_next_out, zs.next_out - old_next_out);
    }
    else
      zerr = Z_STREAM_END;

#if defined STANDALONE && defined XP_WIN
    ProcessWindowsMessages();
#endif
  } // while

  //-- verify crc32
  if ((status == ZIP_OK) && (crc != aItem->crc32))
  {
      status = ZIP_ERR_CORRUPT;
      goto cleanup;
  }

  //-- write last inflated bit to disk
  if (zerr == Z_STREAM_END && outpos < zs.total_out)
  {
    PRUint32 chunk = zs.total_out - outpos;
    if (outFD && PR_Write(outFD, outbuf, chunk) < (READTYPE)chunk)
      status = ZIP_ERR_DISK;
  }

  //-- convert zlib error to return value
  if (status == ZIP_OK && zerr != Z_OK && zerr != Z_STREAM_END)
  {
    status = (zerr == Z_MEM_ERROR) ? ZIP_ERR_MEMORY : ZIP_ERR_CORRUPT;
  }

  //-- if found no errors make sure we've converted the whole thing

  // Allow for reading less than the total size if it appears we've
  // reached the end of the stream without error. It appears Celtx
  // can produce a .celtx file where an entry appears to be padded
  // with unnecessary data (size is 316752 bytes, but inflation
  // stops at 316749 bytes). It's still an error if we read more than
  // intended, or if the output doesn't match the expected size.
  PR_ASSERT(status != ZIP_OK || zs.total_in == aItem->size ||
    (zerr == Z_STREAM_END && zs.total_in < aItem->size));
  PR_ASSERT(status != ZIP_OK || zs.total_out == aItem->realsize);

cleanup:
  //-- free zlib internal state
  inflateEnd(&zs);

  return status;
}