Ejemplo n.º 1
0
    void PngChunk::decode(Image* pImage,
                          const  byte* pData,
                          long   size)
    {
        assert(pImage != 0);
        assert(pData != 0);

        // look for a tEXt chunk
        long index = 8;
        index += getLong(&pData[index], bigEndian) + PNG_CHUNK_HEADER_SIZE;

        while(index < size-PNG_CHUNK_HEADER_SIZE)
        {
            while (index < size-PNG_CHUNK_HEADER_SIZE &&
                   strncmp((char*)PNG_CHUNK_TYPE(pData, index), "tEXt", 4) &&
                   strncmp((char*)PNG_CHUNK_TYPE(pData, index), "zTXt", 4) &&
                   strncmp((char*)PNG_CHUNK_TYPE(pData, index), "iTXt", 4))
            {
                if (!strncmp((char*)PNG_CHUNK_TYPE(pData, index), "IEND", 4))
                    throw Error(14);

                index += getLong(&pData[index], bigEndian) + PNG_CHUNK_HEADER_SIZE;
            }

            if (index < size-PNG_CHUNK_HEADER_SIZE)
            {
                // we found a tEXt, zTXt, or iTXt field

                // get the key, it's a null terminated string at the chunk start
                const byte *key = &PNG_CHUNK_DATA(pData, index, 0);

                int keysize=0;
                for ( ; key[keysize] != 0 ; keysize++)
                {
                    // look if we reached the end of the file (it might be corrupted)
                    if (8+index+keysize >= size)
                        throw Error(14);
                }

                DataBuf arr = parsePngChunk(pData, size, index, keysize);

#ifdef DEBUG
                std::cerr << "Exiv2::PngChunk::decode: Found PNG chunk: " 
                          << std::string((const char*)key) << " :: "
                          << std::string((const char*)arr.pData_, 32) << "\n";
#endif

                parseChunkContent(pImage, key, arr);

                index += getLong(&pData[index], bigEndian) + PNG_CHUNK_HEADER_SIZE;
            }
        }

    } // PngChunk::decode
Ejemplo n.º 2
0
    DataBuf PngChunk::parsePngChunk(const byte* pData, long size, long& index, int keysize)
    {
        DataBuf arr;

        if(!strncmp((char*)PNG_CHUNK_TYPE(pData, index), "zTXt", 4))
        {
            // Extract a deflate compressed Latin-1 text chunk

#ifdef DEBUG
            std::cerr << "Exiv2::PngChunk::parsePngChunk: We found a zTXt field\n";
#endif
            // we get the compression method after the key
            const byte* compressionMethod = &PNG_CHUNK_DATA(pData, index, keysize+1);
            if ( *compressionMethod != 0x00 )
            {
                // then it isn't zlib compressed and we are sunk
#ifdef DEBUG
                std::cerr << "Exiv2::PngChunk::parsePngChunk: Non-standard zTXt compression method.\n";
#endif
                throw Error(14);
            }

            // compressed string after the compression technique spec
            const byte* compressedText      = &PNG_CHUNK_DATA(pData, index, keysize+2);
            unsigned int compressedTextSize = getLong(&pData[index], bigEndian)-keysize-2;

            // security check, also considering overflow wraparound from the addition --
            // we may endup with a /smaller/ index if we wrap all the way around
            long firstIndex       = (long)(compressedText - pData);
            long onePastLastIndex = firstIndex + compressedTextSize;
            if ( onePastLastIndex > size || onePastLastIndex <= firstIndex)
                throw Error(14);

            zlibUncompress(compressedText, compressedTextSize, arr);
        }
        else if (!strncmp((char*)PNG_CHUNK_TYPE(pData, index), "tEXt", 4))
        {
            // Extract a non-compressed Latin-1 text chunk
#ifdef DEBUG
            std::cerr << "Exiv2::PngChunk::parsePngChunk: We found a tEXt field\n";
#endif
            // the text comes after the key, but isn't null terminated
            const byte* text = &PNG_CHUNK_DATA(pData, index, keysize+1);
            long textsize    = getLong(&pData[index], bigEndian)-keysize-1;

            // security check, also considering overflow wraparound from the addition --
            // we may endup with a /smaller/ index if we wrap all the way around
            long firstIndex       = (long)(text - pData);
            long onePastLastIndex = firstIndex + textsize;

            if ( onePastLastIndex > size || onePastLastIndex <= firstIndex)
                throw Error(14);

            arr.alloc(textsize);
            arr = DataBuf(text, textsize);
        }
        else if(!strncmp((char*)PNG_CHUNK_TYPE(pData, index), "iTXt", 4))
        {
            // Extract a deflate compressed or uncompressed UTF-8 text chunk

            // we get the compression flag after the key
            const byte* compressionFlag = &PNG_CHUNK_DATA(pData, index, keysize+1);
            // we get the compression method after the compression flag
            const byte* compressionMethod = &PNG_CHUNK_DATA(pData, index, keysize+1);
            // language description string after the compression technique spec
            const byte* languageText      = &PNG_CHUNK_DATA(pData, index, keysize+1);
            unsigned int languageTextSize = getLong(&pData[index], bigEndian)-keysize-1;
            // translated keyword string after the language description
            const byte* translatedKeyText      = &PNG_CHUNK_DATA(pData, index, keysize+1);
            unsigned int translatedKeyTextSize = getLong(&pData[index], bigEndian)-keysize-1;

            if ( *compressionFlag == 0x00 )
            {
                // then it's an uncompressed iTXt chunk
#ifdef DEBUG
                std::cerr << "Exiv2::PngChunk::parsePngChunk: We found an uncompressed iTXt field\n";
#endif

                // the text comes after the translated keyword, but isn't null terminated
                const byte* text = &PNG_CHUNK_DATA(pData, index, keysize+1);
                long textsize    = getLong(&pData[index], bigEndian)-keysize-1;

                // security check, also considering overflow wraparound from the addition --
                // we may endup with a /smaller/ index if we wrap all the way around
                long firstIndex       = (long)(text - pData);
                long onePastLastIndex = firstIndex + textsize;

                if ( onePastLastIndex > size || onePastLastIndex <= firstIndex)
                    throw Error(14);

                arr.alloc(textsize);
                arr = DataBuf(text, textsize);
            }
            else if ( *compressionMethod == 0x00 )
            {
                // then it's a zlib compressed iTXt chunk
#ifdef DEBUG
                std::cerr << "Exiv2::PngChunk::parsePngChunk: We found a zlib compressed iTXt field\n";
#endif

                // the compressed text comes after the translated keyword, but isn't null terminated
                const byte* compressedText = &PNG_CHUNK_DATA(pData, index, keysize+1);
                long compressedTextSize    = getLong(&pData[index], bigEndian)-keysize-1;

                // security check, also considering overflow wraparound from the addition --
                // we may endup with a /smaller/ index if we wrap all the way around
                long firstIndex       = (long)(compressedText - pData);
                long onePastLastIndex = firstIndex + compressedTextSize;
                if ( onePastLastIndex > size || onePastLastIndex <= firstIndex)
                    throw Error(14);

                zlibUncompress(compressedText, compressedTextSize, arr);
            }
            else
            {
                // then it isn't zlib compressed and we are sunk
#ifdef DEBUG
                std::cerr << "Exiv2::PngChunk::parsePngChunk: Non-standard iTXt compression method.\n";
#endif
                throw Error(14);
            }
        }
        else
        {
#ifdef DEBUG
            std::cerr << "Exiv2::PngChunk::parsePngChunk: We found a field, not expected though\n";
#endif
            throw Error(14);
        }

    return arr;

    } // PngChunk::parsePngChunk
Ejemplo n.º 3
0
    void PngChunk::decode(Image*      pImage,
                          const byte* pData,
                          long        size,
                          int*        outWidth,
                          int*        outHeight)
    {
        assert(pImage != 0);
        assert(pData != 0);
        assert(outWidth != 0);
        assert(outHeight != 0);

        long index = 8;

        // extract width and height from IHDR chunk, which *must* be the first chunk in the PNG file
        if (strncmp((const char *)PNG_CHUNK_TYPE(pData, index), "IHDR", 4) == 0)
        {
            *outWidth = getLong((const byte*)&PNG_CHUNK_DATA(pData, index, 0), bigEndian);
            *outHeight = getLong((const byte*)&PNG_CHUNK_DATA(pData, index, 4), bigEndian);
        }

        // look for a tEXt chunk
        index += chunkLength(pData, index) + PNG_CHUNK_HEADER_SIZE;

        while(index < size-PNG_CHUNK_HEADER_SIZE)
        {
            while (index < size-PNG_CHUNK_HEADER_SIZE &&
                   strncmp((char*)PNG_CHUNK_TYPE(pData, index), "tEXt", 4) &&
                   strncmp((char*)PNG_CHUNK_TYPE(pData, index), "zTXt", 4) &&
                   strncmp((char*)PNG_CHUNK_TYPE(pData, index), "iTXt", 4))
            {
                if (!strncmp((char*)PNG_CHUNK_TYPE(pData, index), "IEND", 4))
                    throw Error(14);

                index += chunkLength(pData, index) + PNG_CHUNK_HEADER_SIZE;
            }

            if (index < size-PNG_CHUNK_HEADER_SIZE)
            {
                // we found a tEXt, zTXt, or iTXt field

                // get the key, it's a null terminated string at the chunk start
                const byte *key = &PNG_CHUNK_DATA(pData, index, 0);

                int keysize=0;
                for ( ; key[keysize] != 0 ; keysize++)
                {
                    // look if we reached the end of the file (it might be corrupted)
                    if (8+index+keysize >= size)
                        throw Error(14);
                }

                DataBuf arr = parsePngChunk(pData, size, index, keysize);

#ifdef DEBUG
                std::cerr << "Exiv2::PngChunk::decode: Found PNG chunk: " 
                          << std::string((const char*)key) << " :: "
                          << std::string((const char*)arr.pData_, 32) << "\n";
#endif

                parseChunkContent(pImage, key, arr);

                index += chunkLength(pData, index) + PNG_CHUNK_HEADER_SIZE;
            }
        }

    } // PngChunk::decode