All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jpedal.io.types.General Maven / Gradle / Ivy

/*
 * ===========================================
 * Java Pdf Extraction Decoding Access Library
 * ===========================================
 *
 * Project Info:  http://www.idrsolutions.com
 * Help section for developers at http://www.idrsolutions.com/support/
 *
 * (C) Copyright 1997-2017 IDRsolutions and Contributors.
 *
 * This file is part of JPedal/JPDF2HTML5
 *
     This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


 *
 * ---------------
 * General.java
 * ---------------
 */

package org.jpedal.io.types;

import static org.jpedal.io.ObjectDecoder.debugFastCode;
import static org.jpedal.io.ObjectDecoder.padding;

import org.jpedal.io.PdfFileReader;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.utils.LogWriter;


/**
 * @author markee
 */
public class General {

    public static int readGeneral(final PdfObject pdfObject, int i, final byte[] raw, final int PDFkeyInt, final PdfFileReader objectReader) {

        //if we only need top level do not read whole tree
        final boolean ignoreRecursion = pdfObject.ignoreRecursion();

        if (debugFastCode) {
            System.out.println(padding + "general case " + i);
        }

        //see if number or ref
        int jj = i;
        int j = i + 1;
        byte[] data = raw;
        int typeFound = 0;
        boolean isNumber = true, isRef = false, isString = false;

        String objRef = pdfObject.getObjectRefAsString();

        while (true) {

            if (data[j] == 'R' && !isString) {

                isRef = true;
                final int end = j;
                j = i;
                i = end;

                final int ref;
                final int generation;

                //allow for [ref] at top level (may be followed by gap
                while (data[j] == 91 || data[j] == 32 || data[j] == 13 || data[j] == 10) {
                    j++;
                }
                final int[] values = StreamReaderUtils.readRefFromStream(data, j);
                // get object ref

                final int refStart = j;
                ref = values[0];
                generation = values[1];
                j = values[2];

                if (data[j] != 82)  //we are expecting R to end ref
                {
                    throw new RuntimeException("ref=" + ref + " gen=" + ref + " 1. Unexpected value " + data[j] + " in file - please send to IDRsolutions for analysis char=" + (char) data[j]);
                }

                objRef = new String(data, refStart, 1 + j - refStart);

                //read the Dictionary data
                //boolean setting=debugFastCode;
                data = objectReader.readObjectAsByteArray(pdfObject, objectReader.isCompressed(ref, generation), ref, generation);

                //allow for data in Linear object not yet loaded
                if (data == null) {
                    pdfObject.setFullyResolved(false);

                    if (debugFastCode) {
                        System.out.println(padding + "Data not yet loaded");
                    }

                    i = raw.length;
                    break;
                }

                //find first valid char to see if String
                int firstChar = 0;

                //some data actually starts << and not 10 0 obj so allow for this
                if (data != null && data.length > 2 && data[0] == '<' && data[1] == '<') {
                    //check for already at <<

                } else {
                    firstChar = findFirstChar(data, firstChar);
                }

                //stop string with R failing in loop
                isString = data[firstChar] == '(';

                jj = skipStartObj(data);

                j = jj;

                if (debugFastCode) {
                    System.out.println(j + " >>" + new String(data) + "<' || data[j] == '/') {
                typeFound = 1;
                break;
            } else if (data[j] == 32 || data[j] == 10 || data[j] == 13 || data[j] == 9) {
            } else if ((data[j] >= '0' && data[j] <= '9') || data[j] == '.') { //assume and disprove
            } else {
                isNumber = false;
            }
            if (data[j] != '[') {
                j++;
            }
            if (j == data.length) {
                break;
            }
        }

        jj = StreamReaderUtils.skipSpaces(data, jj);

        if (typeFound == 4) { //direct ref done above
        } else if (data[jj] == '/' && getKeyCount(jj, data) == 0) {
            jj = Name.setNameStringValue(pdfObject, jj, data, PDFkeyInt, objectReader);
        } else if (data[jj] == '(') {
            jj = TextStream.readTextStream(pdfObject, jj, data, PDFkeyInt, objectReader);
        } else if (data[jj] == '[') {

            final ArrayDecoder objDecoder = ArrayFactory.getDecoder(objectReader, jj, PdfDictionary.VALUE_IS_STRING_ARRAY, data);
            jj = objDecoder.readArray(pdfObject, PDFkeyInt);

        } else if (typeFound == 0) {
            try {
                jj = Dictionary.readDictionaryFromRefOrDirect(pdfObject, objRef, jj, data, PDFkeyInt, objectReader);

            } catch (final Exception e) {
                LogWriter.writeLog("Exception: " + e.getMessage());
            }
        } else if (isNumber) {
            jj = NumberValue.setNumberValue(pdfObject, jj, data, PDFkeyInt, objectReader);
        } else if (typeFound == 1) {
            jj = Name.setNameStringValue(pdfObject, jj, data, PDFkeyInt, objectReader);
        } else if (debugFastCode) {
            System.out.println(padding + "Not read");
        }

        if (!isRef) {
            i = jj;
        }

        return i;
    }

    private static int findFirstChar(final byte[] newData, int firstChar) {

        final int newLength = newData.length - 3;
        for (int aa = 3; aa < newLength; aa++) {   //skip past 13 0 obj bit at start if present
            if (newData[aa - 2] == 'o' && newData[aa - 1] == 'b' && newData[aa] == 'j') {
                firstChar = aa + 1;

                firstChar = StreamReaderUtils.skipSpaces(newData, firstChar);

                aa = newLength; //exit loop
            } else if (newData[aa] > 47 && newData[aa] < 58) { //number
            } else if (newData[aa] == 'o' || newData[aa] == 'b' || newData[aa] == 'j' || newData[aa] == 'R' || newData[aa] == 32 || newData[aa] == 10 || newData[aa] == 13) { //allowed char
            } else { //not expected so reset and quit
                aa = newLength;
                firstChar = 0;
            }
        }
        return firstChar;
    }

    private static int skipStartObj(final byte[] data) {

        int jj = 3;

        if (data.length <= 3) {
            jj = 0;
        } else {
            while (true) {
                if (data[jj - 2] == 'o' && data[jj - 1] == 'b' && data[jj] == 'j') {
                    break;
                }

                jj++;

                if (jj == data.length) {
                    jj = 0;
                    break;
                }
            }
        }
        if (data[jj] != '[' && data[jj] != '(' && data[jj] != '<') //do not roll on if text string
        {
            jj++;
        }

        jj = StreamReaderUtils.skipSpaces(data, jj);

        return jj;
    }

    private static int getKeyCount(final int jj, final byte[] data) {
        //check if name by counting /
        int count = 0;
        for (int aa = jj + 1; aa < data.length; aa++) {
            if (data[aa] == '/') {
                count++;
            }
        }
        return count;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy