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

org.jpedal.io.NameLookup 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
 *
 @LICENSE@
 *
 * ---------------
 * NameLookup.java
 * ---------------
 */
package org.jpedal.io;

import java.util.HashMap;
import java.util.Iterator;

import org.jpedal.objects.Javascript;
import org.jpedal.objects.raw.*;
import org.jpedal.utils.StringUtils;

/**
 * convert names to refs
 */
public class NameLookup extends HashMap {

    private final PdfFileReader objectReader;

    private final HashMap embeddedFiles = new HashMap();

    /**
     * @param objectReader
     */
    public NameLookup(final PdfFileReader objectReader) {

        this.objectReader = objectReader;

    }

    /**
     * read any names
     *
     * @param nameObject
     * @param javascript
     * @param isKid
     */
    public void readNames(final PdfObject nameObject, final Javascript javascript, final boolean isKid) {

        final PdfKeyPairsIterator keyPairs = nameObject.getKeyPairsIterator();

        if (keyPairs.getTokenCount() > 0) {

            while (keyPairs.hasMorePairs()) {
                this.put(keyPairs.getNextKeyAsString(), keyPairs.getNextValueAsString());
                keyPairs.nextPair();
            }
        } else {
            readNamesObject(nameObject, javascript, isKid);
        }
    }

    /**
     * read any names
     *
     * @param nameObject
     * @param javascript
     * @param isKid
     */
    private void readNamesObject(final PdfObject nameObject, final Javascript javascript, final boolean isKid) {


        final ObjectDecoder objectDecoder = new ObjectDecoder(objectReader);
        objectDecoder.checkResolved(nameObject);

        final int[] nameLists = {PdfDictionary.Dests, PdfDictionary.EmbeddedFiles, PdfDictionary.JavaScript, PdfDictionary.XFAImages};
        int count = nameLists.length;
        if (isKid) {
            count = 1;
        }

        PdfObject pdfObj;
        PdfArrayIterator namesArray;

        String name, value;

        for (int ii = 0; ii < count; ii++) {

            if (isKid) {
                pdfObj = nameObject;
            } else {
                pdfObj = nameObject.getDictionary(nameLists[ii]);
            }

            if (pdfObj == null) {
                continue;
            }

            //any kids
            final byte[][] kidList = pdfObj.getKeyArray(PdfDictionary.Kids);
            if (kidList != null) {
                final int kidCount = kidList.length;

                /* allow for empty value and put next pages in the queue */
                if (kidCount > 0) {

                    for (final byte[] aKidList : kidList) {

                        final String nextValue = new String(aKidList);

                        final PdfObject nextObject = new NamesObject(nextValue);

                        if (aKidList[0] == '<') {
                            nextObject.setStatus(PdfObject.UNDECODED_DIRECT);
                        } else {
                            nextObject.setStatus(PdfObject.UNDECODED_REF);
                        }
                        nextObject.setUnresolvedData(aKidList, nameLists[ii]);

                        nextObject.ignoreRecursion(false);

                        objectDecoder.checkResolved(nextObject);

                        readNames(nextObject, javascript, true);
                    }
                }
            }

            //get any names object
            namesArray = pdfObj.getMixedArray(PdfDictionary.Names);

            //read all the values
            if (namesArray != null && namesArray.getTokenCount() > 0) {
                while (namesArray.hasMoreTokens()) {

                    if (nameLists[ii] == PdfDictionary.EmbeddedFiles) {
                        name = StringUtils.getTextString(namesArray.getNextValueAsByte(true), false);
                    } else {
                        name = namesArray.getNextValueAsString(true);
                    }
                    //fix for baseline_screens/11jun/Bundy_vs_F_Kruger_Sons_Bundy_v_F_Kruger!~!2200.pdf
                    //as code assumes paired values and not in this file (List a list)
                    if (!namesArray.hasMoreTokens()) {
                        continue;
                    }

                    value = namesArray.getNextValueAsString(true);

                    switch (nameLists[ii]) {

                        case PdfDictionary.EmbeddedFiles:

                            embeddedFiles.put(name, value);

                            break;

                        //if Javascript, get full value and store, otherwise just get name
                        case PdfDictionary.JavaScript:
                            setJavaScriptName(value, objectDecoder, javascript, name);
                            break;

                        case PdfDictionary.XFAImages:
                            setXFAImage(value, objectDecoder, name);
                            break;

                        default: //just store
                            this.put(name, value);
                    }
                }
            }
        }
    }

    private void setXFAImage(final String value, final ObjectDecoder objectDecoder, final String name) {

        final PdfObject XFAImagesObj = new XObject(value);
        XFAImagesObj.decompressStreamWhenRead();
        final byte[] xfaData = StringUtils.toBytes(value);
        if (xfaData[0] == '<') {
            XFAImagesObj.setStatus(PdfObject.UNDECODED_DIRECT);
        } else {
            XFAImagesObj.setStatus(PdfObject.UNDECODED_REF);
        }

        if (value.contains(" ") || value.contains("<")) {

            //must be done AFTER setStatus()
            XFAImagesObj.setUnresolvedData(xfaData, PdfDictionary.XObject);
            objectDecoder.checkResolved(XFAImagesObj);

            final byte[] decodedImageData = objectReader.readStream(XFAImagesObj, true, true, false, false, false, null);

            this.put(name, decodedImageData);
        }
    }

    static void setJavaScriptName(final String value, final ObjectDecoder objectDecoder, final Javascript javascript, final String name) {
        final String JSstring;

        final PdfObject javascriptObj = new NamesObject(value);
        final byte[] jsData = StringUtils.toBytes(value);
        if (jsData[0] == '<') {
            javascriptObj.setStatus(PdfObject.UNDECODED_DIRECT);
        } else {
            javascriptObj.setStatus(PdfObject.UNDECODED_REF);
        }

        if (value.contains(" ") || value.contains("<")) {
            //must be done AFTER setStatus()
            javascriptObj.setUnresolvedData(jsData, PdfDictionary.JS);
            objectDecoder.checkResolved(javascriptObj);


            final PdfObject JS = javascriptObj.getDictionary(PdfDictionary.JS);
            if (JS != null) { //in stream
                JSstring = new String(JS.getDecodedStream());
            } else { //can also be text
                JSstring = javascriptObj.getTextStreamValue((PdfDictionary.JS));
            }
        } else {
            JSstring = value;
        }

        if (JSstring != null) {
            //store
            javascript.setCode(name, JSstring);
        }
    }

    /**
     * used to parser on demand if needed and return as key pair of name, PdfObject
     *
     * @return
     */
    public Object[] getEmbeddedFiles() {

        final Object[] returnValues = new Object[embeddedFiles.keySet().size() * 2];
        int ptr = 0;

        String name, value;
        final Iterator embeddedFileNames = embeddedFiles.keySet().iterator();

        final ObjectDecoder objectDecoder = new ObjectDecoder(objectReader);

        while (embeddedFileNames.hasNext()) {
            name = embeddedFileNames.next();
            returnValues[ptr++] = name;
            value = embeddedFiles.get(name);

            final PdfObject embeddedObj = new FSObject(value);
            final byte[] jsData = StringUtils.toBytes(value);
            if (jsData[0] == '<') {
                embeddedObj.setStatus(PdfObject.UNDECODED_DIRECT);
            } else {
                embeddedObj.setStatus(PdfObject.UNDECODED_REF);
            }

            if (value.contains(" ") || value.contains("<")) {
                //must be done AFTER setStatus()
                embeddedObj.setUnresolvedData(jsData, PdfDictionary.JS);
                objectDecoder.checkResolved(embeddedObj);


                returnValues[ptr++] = embeddedObj;
            } else {
                returnValues[ptr++] = null;
            }
        }
        return returnValues;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy