protected List parseAllBlocks()

in src/main/java/org/apache/commons/imaging/formats/jpeg/iptc/IptcParser.java [107:199]


    protected List<IptcBlock> parseAllBlocks(final byte[] bytes, final boolean strict) throws ImagingException, IOException {
        final List<IptcBlock> blocks = new ArrayList<>();

        try (InputStream bis = new ByteArrayInputStream(bytes)) {

            // Note that these are unsigned quantities. Name is always an even
            // number of bytes (including the 1st byte, which is the size.)

            final byte[] idString = BinaryFunctions.readBytes("", bis, JpegConstants.PHOTOSHOP_IDENTIFICATION_STRING.size(),
                    "App13 Segment missing identification string");
            if (!JpegConstants.PHOTOSHOP_IDENTIFICATION_STRING.equals(idString)) {
                throw new ImagingException("Not a Photoshop App13 Segment");
            }

            // int index = PHOTOSHOP_IDENTIFICATION_STRING.length;

            while (true) {
                final int imageResourceBlockSignature;
                try {
                    imageResourceBlockSignature = BinaryFunctions.read4Bytes("", bis, "Image Resource Block missing identification string", APP13_BYTE_ORDER);
                } catch (final IOException ioEx) {
                    break;
                }
                if (imageResourceBlockSignature != JpegConstants.CONST_8BIM) {
                    throw new ImagingException("Invalid Image Resource Block Signature");
                }

                final int blockType = BinaryFunctions.read2Bytes("", bis, "Image Resource Block missing type", APP13_BYTE_ORDER);
                Debug.debug("blockType: " + blockType + " (0x" + Integer.toHexString(blockType) + ")");

                // skip blocks that the photoshop spec recommends to, see IMAGING-246
                if (PHOTOSHOP_IGNORED_BLOCK_TYPE.contains(blockType)) {
                    Debug.debug("Skipping blockType: " + blockType + " (0x" + Integer.toHexString(blockType) + ")");
                    // if there is still data in this block, before the next image resource block
                    // (8BIM), then we must consume these bytes to leave a pointer ready to read
                    // the next block
                    BinaryFunctions.searchQuad(JpegConstants.CONST_8BIM, bis);
                    continue;
                }

                final int blockNameLength = BinaryFunctions.readByte("Name length", bis, "Image Resource Block missing name length");
                if (blockNameLength > 0) {
                    Debug.debug("blockNameLength: " + blockNameLength + " (0x" + Integer.toHexString(blockNameLength) + ")");
                }
                final byte[] blockNameBytes;
                if (blockNameLength == 0) {
                    BinaryFunctions.readByte("Block name bytes", bis, "Image Resource Block has invalid name");
                    blockNameBytes = ImagingConstants.EMPTY_BYTE_ARRAY;
                } else {
                    try {
                        blockNameBytes = BinaryFunctions.readBytes("", bis, blockNameLength, "Invalid Image Resource Block name");
                    } catch (final IOException ioEx) {
                        if (strict) {
                            throw ioEx;
                        }
                        break;
                    }

                    if (blockNameLength % 2 == 0) {
                        BinaryFunctions.readByte("Padding byte", bis, "Image Resource Block missing padding byte");
                    }
                }

                final int blockSize = BinaryFunctions.read4Bytes("", bis, "Image Resource Block missing size", APP13_BYTE_ORDER);
                Debug.debug("blockSize: " + blockSize + " (0x" + Integer.toHexString(blockSize) + ")");

                /*
                 * doesn't catch cases where blocksize is invalid but is still less than bytes.length but will at least prevent OutOfMemory errors
                 */
                if (blockSize > bytes.length) {
                    throw new ImagingException("Invalid Block Size : " + blockSize + " > " + bytes.length);
                }

                final byte[] blockData;
                try {
                    blockData = BinaryFunctions.readBytes("", bis, blockSize, "Invalid Image Resource Block data");
                } catch (final IOException ioEx) {
                    if (strict) {
                        throw ioEx;
                    }
                    break;
                }

                blocks.add(new IptcBlock(blockType, blockNameBytes, blockData));

                if (blockSize % 2 != 0) {
                    BinaryFunctions.readByte("Padding byte", bis, "Image Resource Block missing padding byte");
                }
            }

            return blocks;
        }
    }