示例#1
0
nsresult nsZipHeader::WriteCDSHeader(nsIOutputStream *aStream)
{
    NS_ASSERTION(mInited, "Not initalised");

    PRUint8 buf[ZIP_CDS_HEADER_SIZE];
    PRUint32 pos = 0;
    WRITE32(buf, &pos, ZIP_CDS_HEADER_SIGNATURE);
    WRITE16(buf, &pos, mVersionMade);
    WRITE16(buf, &pos, mVersionNeeded);
    WRITE16(buf, &pos, mFlags);
    WRITE16(buf, &pos, mMethod);
    WRITE16(buf, &pos, mTime);
    WRITE16(buf, &pos, mDate);
    WRITE32(buf, &pos, mCRC);
    WRITE32(buf, &pos, mCSize);
    WRITE32(buf, &pos, mUSize);
    WRITE16(buf, &pos, mName.Length());
    WRITE16(buf, &pos, mFieldLength);
    WRITE16(buf, &pos, mComment.Length());
    WRITE16(buf, &pos, mDisk);
    WRITE16(buf, &pos, mIAttr);
    WRITE32(buf, &pos, mEAttr);
    WRITE32(buf, &pos, mOffset);

    nsresult rv = ZW_WriteData(aStream, (const char *)buf, pos);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = ZW_WriteData(aStream, mName.get(), mName.Length());
    NS_ENSURE_SUCCESS(rv, rv);
    if (mExtraField) {
        rv = ZW_WriteData(aStream, (const char *)mExtraField.get(), mFieldLength);
        NS_ENSURE_SUCCESS(rv, rv);
    }
    return ZW_WriteData(aStream, mComment.get(), mComment.Length());
}
示例#2
0
nsresult nsZipHeader::WriteFileHeader(nsIOutputStream *aStream)
{
    NS_ASSERTION(mInited, "Not initalised");

    PRUint8 buf[ZIP_FILE_HEADER_SIZE];
    PRUint32 pos = 0;
    WRITE32(buf, &pos, ZIP_FILE_HEADER_SIGNATURE);
    WRITE16(buf, &pos, mVersionNeeded);
    WRITE16(buf, &pos, mFlags);
    WRITE16(buf, &pos, mMethod);
    WRITE16(buf, &pos, mTime);
    WRITE16(buf, &pos, mDate);
    WRITE32(buf, &pos, mCRC);
    WRITE32(buf, &pos, mCSize);
    WRITE32(buf, &pos, mUSize);
    WRITE16(buf, &pos, mName.Length());
    WRITE16(buf, &pos, mLocalFieldLength);

    nsresult rv = ZW_WriteData(aStream, (const char *)buf, pos);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = ZW_WriteData(aStream, mName.get(), mName.Length());
    NS_ENSURE_SUCCESS(rv, rv);

    if (mLocalFieldLength)
    {
      rv = ZW_WriteData(aStream, (const char *)mLocalExtraField.get(), mLocalFieldLength);
      NS_ENSURE_SUCCESS(rv, rv);
    }

    return NS_OK;
}
示例#3
0
/* void close (); */
NS_IMETHODIMP nsZipWriter::Close()
{
    if (!mStream)
        return NS_ERROR_NOT_INITIALIZED;
    if (mInQueue)
        return NS_ERROR_IN_PROGRESS;

    if (mCDSDirty) {
        PRUint32 size = 0;
        for (PRInt32 i = 0; i < mHeaders.Count(); i++) {
            nsresult rv = mHeaders[i]->WriteCDSHeader(mStream);
            if (NS_FAILED(rv)) {
                Cleanup();
                return rv;
            }
            size += mHeaders[i]->GetCDSHeaderLength();
        }

        char buf[ZIP_EOCDR_HEADER_SIZE];
        PRUint32 pos = 0;
        WRITE32(buf, &pos, ZIP_EOCDR_HEADER_SIGNATURE);
        WRITE16(buf, &pos, 0);
        WRITE16(buf, &pos, 0);
        WRITE16(buf, &pos, mHeaders.Count());
        WRITE16(buf, &pos, mHeaders.Count());
        WRITE32(buf, &pos, size);
        WRITE32(buf, &pos, mCDSOffset);
        WRITE16(buf, &pos, mComment.Length());

        nsresult rv = ZW_WriteData(mStream, buf, pos);
        if (NS_FAILED(rv)) {
            Cleanup();
            return rv;
        }

        rv = ZW_WriteData(mStream, mComment.get(), mComment.Length());
        if (NS_FAILED(rv)) {
            Cleanup();
            return rv;
        }

        nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mStream);
        rv = seekable->SetEOF();
        if (NS_FAILED(rv)) {
            Cleanup();
            return rv;
        }
    }

    nsresult rv = mStream->Close();
    mStream = nsnull;
    mHeaders.Clear();
    mEntryHash.Clear();
    mQueue.Clear();

    return rv;
}
示例#4
0
/*
 * Make all stored(uncompressed) files align to given alignment size.
 */
NS_IMETHODIMP nsZipWriter::AlignStoredFiles(uint16_t aAlignSize)
{
    nsresult rv;

    // Check for range and power of 2.
    if (aAlignSize < 2 || aAlignSize > 32768 ||
        (aAlignSize & (aAlignSize - 1)) != 0) {
        return NS_ERROR_INVALID_ARG;
    }

    for (int i = 0; i < mHeaders.Count(); i++) {
        nsZipHeader *header = mHeaders[i];

        // Check whether this entry is file and compression method is stored.
        bool isdir;
        rv = header->GetIsDirectory(&isdir);
        if (NS_FAILED(rv)) {
            return rv;
        }
        if (isdir || header->mMethod != 0) {
            continue;
        }
        // Pad extra field to align data starting position to specified size.
        uint32_t old_len = header->mLocalFieldLength;
        rv = header->PadExtraField(header->mOffset, aAlignSize);
        if (NS_FAILED(rv)) {
            continue;
        }
        // No padding means data already aligned.
        uint32_t shift = header->mLocalFieldLength - old_len;
        if (shift == 0) {
            continue;
        }

        // Flush any remaining data before we start.
        rv = mStream->Flush();
        if (NS_FAILED(rv)) {
            return rv;
        }

        // Open zip file for reading.
        nsCOMPtr<nsIInputStream> inputStream;
        rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), mFile);
        if (NS_FAILED(rv)) {
            return rv;
        }

        nsCOMPtr<nsISeekableStream> in_seekable = do_QueryInterface(inputStream);
        nsCOMPtr<nsISeekableStream> out_seekable = do_QueryInterface(mStream);

        uint32_t data_offset = header->mOffset + header->GetFileHeaderLength() - shift;
        uint32_t count = mCDSOffset - data_offset;
        uint32_t read;
        char buf[4096];

        // Shift data to aligned postion.
        while (count > 0) {
            read = std::min(count, (uint32_t) sizeof(buf));

            rv = in_seekable->Seek(nsISeekableStream::NS_SEEK_SET,
                                   data_offset + count - read);
            if (NS_FAILED(rv)) {
                break;
             }

            rv = inputStream->Read(buf, read, &read);
            if (NS_FAILED(rv)) {
                break;
            }

            rv = out_seekable->Seek(nsISeekableStream::NS_SEEK_SET,
                                    data_offset + count - read + shift);
            if (NS_FAILED(rv)) {
                break;
             }

            rv = ZW_WriteData(mStream, buf, read);
            if (NS_FAILED(rv)) {
                break;
            }

            count -= read;
        }
        inputStream->Close();
        if (NS_FAILED(rv)) {
            Cleanup();
            return rv;
        }

        // Update current header
        rv = out_seekable->Seek(nsISeekableStream::NS_SEEK_SET,
                                header->mOffset);
        if (NS_FAILED(rv)) {
            Cleanup();
            return rv;
        }
        rv = header->WriteFileHeader(mStream);
        if (NS_FAILED(rv)) {
            Cleanup();
            return rv;
        }

        // Update offset of all other headers
        int pos = i + 1;
        while (pos < mHeaders.Count()) {
            mHeaders[pos]->mOffset += shift;
            pos++;
        }
        mCDSOffset += shift;
        rv = SeekCDS();
        if (NS_FAILED(rv)) {
            return rv;
        }
        mCDSDirty = true;
    }

    return NS_OK;
}
示例#5
0
NS_IMETHODIMP nsZipWriter::Close()
{
    if (!mStream)
        return NS_ERROR_NOT_INITIALIZED;
    if (mInQueue)
        return NS_ERROR_IN_PROGRESS;

    if (mCDSDirty) {
        uint32_t size = 0;
        for (int32_t i = 0; i < mHeaders.Count(); i++) {
            nsresult rv = mHeaders[i]->WriteCDSHeader(mStream);
            if (NS_FAILED(rv)) {
                Cleanup();
                return rv;
            }
            size += mHeaders[i]->GetCDSHeaderLength();
        }

        uint8_t buf[ZIP_EOCDR_HEADER_SIZE];
        uint32_t pos = 0;
        WRITE32(buf, &pos, ZIP_EOCDR_HEADER_SIGNATURE);
        WRITE16(buf, &pos, 0);
        WRITE16(buf, &pos, 0);
        WRITE16(buf, &pos, mHeaders.Count());
        WRITE16(buf, &pos, mHeaders.Count());
        WRITE32(buf, &pos, size);
        WRITE32(buf, &pos, mCDSOffset);
        WRITE16(buf, &pos, mComment.Length());

        nsresult rv = ZW_WriteData(mStream, (const char *)buf, pos);
        if (NS_FAILED(rv)) {
            Cleanup();
            return rv;
        }

        rv = ZW_WriteData(mStream, mComment.get(), mComment.Length());
        if (NS_FAILED(rv)) {
            Cleanup();
            return rv;
        }

        nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mStream);
        rv = seekable->SetEOF();
        if (NS_FAILED(rv)) {
            Cleanup();
            return rv;
        }

        // Go back and rewrite the file headers
        for (int32_t i = 0; i < mHeaders.Count(); i++) {
            nsZipHeader *header = mHeaders[i];
            if (!header->mWriteOnClose)
              continue;

            rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, header->mOffset);
            if (NS_FAILED(rv)) {
               Cleanup();
               return rv;
            }
            rv = header->WriteFileHeader(mStream);
            if (NS_FAILED(rv)) {
               Cleanup();
               return rv;
            }
        }
    }

    nsresult rv = mStream->Close();
    mStream = nullptr;
    mHeaders.Clear();
    mEntryHash.Clear();
    mQueue.Clear();

    return rv;
}
示例#6
0
NS_IMETHODIMP nsZipWriter::RemoveEntry(const nsACString & aZipEntry,
                                       bool aQueue)
{
    if (!mStream)
        return NS_ERROR_NOT_INITIALIZED;

    if (aQueue) {
        nsZipQueueItem item;
        item.mOperation = OPERATION_REMOVE;
        item.mZipEntry = aZipEntry;
        if (!mQueue.AppendElement(item))
            return NS_ERROR_OUT_OF_MEMORY;
        return NS_OK;
    }

    if (mInQueue)
        return NS_ERROR_IN_PROGRESS;

    int32_t pos;
    if (mEntryHash.Get(aZipEntry, &pos)) {
        // Flush any remaining data before we seek.
        nsresult rv = mStream->Flush();
        NS_ENSURE_SUCCESS(rv, rv);
        if (pos < mHeaders.Count() - 1) {
            // This is not the last entry, pull back the data.
            nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mStream);
            rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
                                mHeaders[pos]->mOffset);
            NS_ENSURE_SUCCESS(rv, rv);

            nsCOMPtr<nsIInputStream> inputStream;
            rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream),
                                            mFile);
            NS_ENSURE_SUCCESS(rv, rv);
            seekable = do_QueryInterface(inputStream);
            rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
                                mHeaders[pos + 1]->mOffset);
            if (NS_FAILED(rv)) {
                inputStream->Close();
                return rv;
            }

            uint32_t count = mCDSOffset - mHeaders[pos + 1]->mOffset;
            uint32_t read = 0;
            char buf[4096];
            while (count > 0) {
                read = std::min(count, (uint32_t) sizeof(buf));

                rv = inputStream->Read(buf, read, &read);
                if (NS_FAILED(rv)) {
                    inputStream->Close();
                    Cleanup();
                    return rv;
                }

                rv = ZW_WriteData(mStream, buf, read);
                if (NS_FAILED(rv)) {
                    inputStream->Close();
                    Cleanup();
                    return rv;
                }

                count -= read;
            }
            inputStream->Close();

            // Rewrite header offsets and update hash
            uint32_t shift = (mHeaders[pos + 1]->mOffset -
                              mHeaders[pos]->mOffset);
            mCDSOffset -= shift;
            int32_t pos2 = pos + 1;
            while (pos2 < mHeaders.Count()) {
                mEntryHash.Put(mHeaders[pos2]->mName, pos2-1);
                mHeaders[pos2]->mOffset -= shift;
                pos2++;
            }
        }
        else {
            // Remove the last entry is just a case of moving the CDS
            mCDSOffset = mHeaders[pos]->mOffset;
            rv = SeekCDS();
            NS_ENSURE_SUCCESS(rv, rv);
        }

        mEntryHash.Remove(mHeaders[pos]->mName);
        mHeaders.RemoveObjectAt(pos);
        mCDSDirty = true;

        return NS_OK;
    }

    return NS_ERROR_FILE_NOT_FOUND;
}