protected List parseAllBlocks()

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


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

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

                final int blockSize = 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 = 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) {
                    readByte("Padding byte", bis, "Image Resource Block missing padding byte");
                }
            }

            return blocks;
        }
    }