private boolean readDirectory()

in src/main/java/org/apache/commons/imaging/formats/tiff/TiffReader.java [269:413]


    private boolean readDirectory(final ByteSource byteSource, final long directoryOffset, final int dirType, final FormatCompliance formatCompliance,
            final Listener listener, final boolean ignoreNextDirectory, final List<Number> visited) throws ImagingException, IOException {

        if (visited.contains(directoryOffset)) {
            return false;
        }
        visited.add(directoryOffset);

        try (InputStream is = byteSource.getInputStream()) {
            if (directoryOffset >= byteSource.size()) {
                return true;
            }

            BinaryFunctions.skipBytes(is, directoryOffset);

            final List<TiffField> fields = new ArrayList<>();

            final long entryCount;
            try {
                if (standardTiff) {
                    entryCount = BinaryFunctions.read2Bytes("DirectoryEntryCount", is, "Not a Valid TIFF File", getByteOrder());
                } else {
                    entryCount = BinaryFunctions.read8Bytes("DirectoryEntryCount", is, "Not a Valid TIFF File", getByteOrder());
                }
            } catch (final IOException e) {
                if (strict) {
                    throw e;
                }
                return true;
            }

            for (int i = 0; i < entryCount; i++) {
                final int tag = BinaryFunctions.read2Bytes("Tag", is, "Not a Valid TIFF File", getByteOrder());
                final int type = BinaryFunctions.read2Bytes("Type", is, "Not a Valid TIFF File", getByteOrder());
                final long count;
                final byte[] offsetBytes;
                final long offset;
                if (standardTiff) {
                    count = 0xFFFFffffL & BinaryFunctions.read4Bytes("Count", is, "Not a Valid TIFF File", getByteOrder());
                    offsetBytes = BinaryFunctions.readBytes("Offset", is, 4, "Not a Valid TIFF File");
                    offset = 0xFFFFffffL & ByteConversions.toInt(offsetBytes, getByteOrder());
                } else {
                    count = BinaryFunctions.read8Bytes("Count", is, "Not a Valid TIFF File", getByteOrder());
                    offsetBytes = BinaryFunctions.readBytes("Offset", is, 8, "Not a Valid TIFF File");
                    offset = ByteConversions.toLong(offsetBytes, getByteOrder());
                }

                if (tag == 0) {
                    // skip invalid fields.
                    // These are seen very rarely, but can have invalid value
                    // lengths,
                    // which can cause OOM problems.
                    continue;
                }

                final AbstractFieldType abstractFieldType;
                try {
                    abstractFieldType = AbstractFieldType.getFieldType(type);
                } catch (final ImagingException imageReadEx) {
                    // skip over unknown fields types, since we
                    // can't calculate their size without
                    // knowing their type
                    continue;
                }
                final long valueLength = count * abstractFieldType.getSize();
                final byte[] value;
                if (valueLength > entryMaxValueLength) {
                    if (offset < 0 || offset + valueLength > byteSource.size()) {
                        if (strict) {
                            throw new IOException("Attempt to read byte range starting from " + offset + " " + "of length " + valueLength + " "
                                    + "which is outside the file's size of " + byteSource.size());
                        }
                        // corrupt field, ignore it
                        continue;
                    }
                    value = byteSource.getByteArray(offset, (int) valueLength);
                } else {
                    value = offsetBytes;
                }

                final TiffField field = new TiffField(tag, dirType, abstractFieldType, count, offset, value, getByteOrder(), i);

                fields.add(field);

                if (!listener.addField(field)) {
                    return true;
                }
            }

            final long nextDirectoryOffset = 0xFFFFffffL & BinaryFunctions.read4Bytes("nextDirectoryOffset", is, "Not a Valid TIFF File", getByteOrder());

            final TiffDirectory directory = new TiffDirectory(dirType, fields, directoryOffset, nextDirectoryOffset, getByteOrder());

            if (listener.readImageData()) {
                if (directory.hasTiffImageData()) {
                    final AbstractTiffImageData rawImageData = getTiffRawImageData(byteSource, directory);
                    directory.setTiffImageData(rawImageData);
                }
                if (directory.hasJpegImageData()) {
                    final JpegImageData rawJpegImageData = getJpegRawImageData(byteSource, directory);
                    directory.setJpegImageData(rawJpegImageData);
                }
            }

            if (!listener.addDirectory(directory)) {
                return true;
            }

            if (listener.readOffsetDirectories()) {
                final TagInfoDirectory[] offsetFields = { ExifTagConstants.EXIF_TAG_EXIF_OFFSET, ExifTagConstants.EXIF_TAG_GPSINFO,
                        ExifTagConstants.EXIF_TAG_INTEROP_OFFSET };
                final int[] directoryTypes = { TiffDirectoryConstants.DIRECTORY_TYPE_EXIF, TiffDirectoryConstants.DIRECTORY_TYPE_GPS,
                        TiffDirectoryConstants.DIRECTORY_TYPE_INTEROPERABILITY };
                for (int i = 0; i < offsetFields.length; i++) {
                    final TagInfoDirectory offsetField = offsetFields[i];
                    final TiffField field = directory.findField(offsetField);
                    if (field != null) {
                        final long subDirectoryOffset;
                        final int subDirectoryType;
                        boolean subDirectoryRead = false;
                        try {
                            subDirectoryOffset = directory.getFieldValue(offsetField);
                            subDirectoryType = directoryTypes[i];
                            subDirectoryRead = readDirectory(byteSource, subDirectoryOffset, subDirectoryType, formatCompliance, listener, true, visited);

                        } catch (final ImagingException imageReadException) {
                            if (strict) {
                                throw imageReadException;
                            }
                        }
                        if (!subDirectoryRead) {
                            fields.remove(field);
                        }
                    }
                }
            }

            if (!ignoreNextDirectory && directory.getNextDirectoryOffset() > 0) {
                // Debug.debug("next dir", directory.nextDirectoryOffset );
                readDirectory(byteSource, directory.getNextDirectoryOffset(), dirType + 1, formatCompliance, listener, visited);
            }

            return true;
        }
    }