Search in sources :

Example 1 with PositionDependentRecord

use of org.apache.poi.hslf.record.PositionDependentRecord in project poi by apache.

the class HSLFSlideShowEncrypted method normalizeRecords.

/**
     * remove duplicated UserEditAtoms and merge PersistPtrHolder.
     * Before this method is called, make sure that the offsets are correct,
     * i.e. call {@link HSLFSlideShowImpl#updateAndWriteDependantRecords(OutputStream, Map)}
     */
protected static Record[] normalizeRecords(Record[] records) {
    // http://msdn.microsoft.com/en-us/library/office/gg615594(v=office.14).aspx
    // repeated slideIds can be overwritten, i.e. ignored
    UserEditAtom uea = null;
    PersistPtrHolder pph = null;
    TreeMap<Integer, Integer> slideLocations = new TreeMap<Integer, Integer>();
    TreeMap<Integer, Record> recordMap = new TreeMap<Integer, Record>();
    List<Integer> obsoleteOffsets = new ArrayList<Integer>();
    int duplicatedCount = 0;
    for (Record r : records) {
        assert (r instanceof PositionDependentRecord);
        PositionDependentRecord pdr = (PositionDependentRecord) r;
        if (pdr instanceof UserEditAtom) {
            uea = (UserEditAtom) pdr;
            continue;
        }
        if (pdr instanceof PersistPtrHolder) {
            if (pph != null) {
                duplicatedCount++;
            }
            pph = (PersistPtrHolder) pdr;
            for (Map.Entry<Integer, Integer> me : pph.getSlideLocationsLookup().entrySet()) {
                Integer oldOffset = slideLocations.put(me.getKey(), me.getValue());
                if (oldOffset != null) {
                    obsoleteOffsets.add(oldOffset);
                }
            }
            continue;
        }
        recordMap.put(pdr.getLastOnDiskOffset(), r);
    }
    if (uea == null || pph == null || uea.getPersistPointersOffset() != pph.getLastOnDiskOffset()) {
        throw new EncryptedDocumentException("UserEditAtom and PersistPtrHolder must exist and their offset need to match.");
    }
    recordMap.put(pph.getLastOnDiskOffset(), pph);
    recordMap.put(uea.getLastOnDiskOffset(), uea);
    if (duplicatedCount == 0 && obsoleteOffsets.isEmpty()) {
        return records;
    }
    uea.setLastUserEditAtomOffset(0);
    pph.clear();
    for (Map.Entry<Integer, Integer> me : slideLocations.entrySet()) {
        pph.addSlideLookup(me.getKey(), me.getValue());
    }
    for (Integer oldOffset : obsoleteOffsets) {
        recordMap.remove(oldOffset);
    }
    return recordMap.values().toArray(new Record[recordMap.size()]);
}
Also used : EncryptedDocumentException(org.apache.poi.EncryptedDocumentException) PersistPtrHolder(org.apache.poi.hslf.record.PersistPtrHolder) ArrayList(java.util.ArrayList) TreeMap(java.util.TreeMap) PositionDependentRecord(org.apache.poi.hslf.record.PositionDependentRecord) Record(org.apache.poi.hslf.record.Record) PositionDependentRecord(org.apache.poi.hslf.record.PositionDependentRecord) UserEditAtom(org.apache.poi.hslf.record.UserEditAtom) Map(java.util.Map) NavigableMap(java.util.NavigableMap) TreeMap(java.util.TreeMap)

Example 2 with PositionDependentRecord

use of org.apache.poi.hslf.record.PositionDependentRecord in project poi by apache.

the class HSLFSlideShowImpl method updateAndWriteDependantRecords.

/**
     * This is a helper functions, which is needed for adding new position dependent records
     * or finally write the slideshow to a file.
     *
     * @param os                 the stream to write to, if null only the references are updated
     * @param interestingRecords a map of interesting records (PersistPtrHolder and UserEditAtom)
     *                           referenced by their RecordType. Only the very last of each type will be saved to the map.
     *                           May be null, if not needed.
     * @throws IOException
     */
public void updateAndWriteDependantRecords(OutputStream os, Map<RecordTypes, PositionDependentRecord> interestingRecords) throws IOException {
    // For position dependent records, hold where they were and now are
    // As we go along, update, and hand over, to any Position Dependent
    //  records we happen across
    Map<Integer, Integer> oldToNewPositions = new HashMap<Integer, Integer>();
    // First pass - figure out where all the position dependent
    //   records are going to end up, in the new scheme
    // (Annoyingly, some powerpoint files have PersistPtrHolders
    //  that reference slides after the PersistPtrHolder)
    UserEditAtom usr = null;
    PersistPtrHolder ptr = null;
    CountingOS cos = new CountingOS();
    for (Record record : _records) {
        // all top level records are position dependent
        assert (record instanceof PositionDependentRecord);
        PositionDependentRecord pdr = (PositionDependentRecord) record;
        int oldPos = pdr.getLastOnDiskOffset();
        int newPos = cos.size();
        pdr.setLastOnDiskOffset(newPos);
        if (oldPos != UNSET_OFFSET) {
            // new records don't need a mapping, as they aren't in a relation yet
            oldToNewPositions.put(oldPos, newPos);
        }
        // Grab interesting records as they come past
        // this will only save the very last record of each type
        RecordTypes saveme = null;
        int recordType = (int) record.getRecordType();
        if (recordType == RecordTypes.PersistPtrIncrementalBlock.typeID) {
            saveme = RecordTypes.PersistPtrIncrementalBlock;
            ptr = (PersistPtrHolder) pdr;
        } else if (recordType == RecordTypes.UserEditAtom.typeID) {
            saveme = RecordTypes.UserEditAtom;
            usr = (UserEditAtom) pdr;
        }
        if (interestingRecords != null && saveme != null) {
            interestingRecords.put(saveme, pdr);
        }
        // Dummy write out, so the position winds on properly
        record.writeOut(cos);
    }
    cos.close();
    if (usr == null || ptr == null) {
        throw new HSLFException("UserEditAtom or PersistPtr can't be determined.");
    }
    Map<Integer, Integer> persistIds = new HashMap<Integer, Integer>();
    for (Map.Entry<Integer, Integer> entry : ptr.getSlideLocationsLookup().entrySet()) {
        persistIds.put(oldToNewPositions.get(entry.getValue()), entry.getKey());
    }
    HSLFSlideShowEncrypted encData = new HSLFSlideShowEncrypted(getDocumentEncryptionAtom());
    for (Record record : _records) {
        assert (record instanceof PositionDependentRecord);
        // We've already figured out their new location, and
        // told them that
        // Tell them of the positions of the other records though
        PositionDependentRecord pdr = (PositionDependentRecord) record;
        Integer persistId = persistIds.get(pdr.getLastOnDiskOffset());
        if (persistId == null) {
            persistId = 0;
        }
        // For now, we're only handling PositionDependentRecord's that
        // happen at the top level.
        // In future, we'll need the handle them everywhere, but that's
        // a bit trickier
        pdr.updateOtherRecordReferences(oldToNewPositions);
        // Whatever happens, write out that record tree
        if (os != null) {
            record.writeOut(encData.encryptRecord(os, persistId, record));
        }
    }
    encData.close();
    // Update and write out the Current User atom
    int oldLastUserEditAtomPos = (int) currentUser.getCurrentEditOffset();
    Integer newLastUserEditAtomPos = oldToNewPositions.get(oldLastUserEditAtomPos);
    if (newLastUserEditAtomPos == null || usr.getLastOnDiskOffset() != newLastUserEditAtomPos) {
        throw new HSLFException("Couldn't find the new location of the last UserEditAtom that used to be at " + oldLastUserEditAtomPos);
    }
    currentUser.setCurrentEditOffset(usr.getLastOnDiskOffset());
}
Also used : HSLFException(org.apache.poi.hslf.exceptions.HSLFException) HashMap(java.util.HashMap) PersistPtrHolder(org.apache.poi.hslf.record.PersistPtrHolder) PositionDependentRecord(org.apache.poi.hslf.record.PositionDependentRecord) Record(org.apache.poi.hslf.record.Record) PositionDependentRecord(org.apache.poi.hslf.record.PositionDependentRecord) PersistRecord(org.apache.poi.hslf.record.PersistRecord) UserEditAtom(org.apache.poi.hslf.record.UserEditAtom) HashMap(java.util.HashMap) Map(java.util.Map) NavigableMap(java.util.NavigableMap) TreeMap(java.util.TreeMap) RecordTypes(org.apache.poi.hslf.record.RecordTypes)

Example 3 with PositionDependentRecord

use of org.apache.poi.hslf.record.PositionDependentRecord in project poi by apache.

the class UserEditAndPersistListing method main.

public static void main(String[] args) throws IOException {
    if (args.length < 1) {
        System.err.println("Need to give a filename");
        System.exit(1);
    }
    // Create the slideshow object, for normal working with
    HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]);
    fileContents = ss.getUnderlyingBytes();
    System.out.println("");
    // Find any persist ones first
    int pos = 0;
    for (Record r : ss.getRecords()) {
        if (r.getRecordType() == 6001l) {
            // PersistPtrFullBlock
            System.out.println("Found PersistPtrFullBlock at " + pos + " (" + Integer.toHexString(pos) + ")");
        }
        if (r.getRecordType() == 6002l) {
            // PersistPtrIncrementalBlock
            System.out.println("Found PersistPtrIncrementalBlock at " + pos + " (" + Integer.toHexString(pos) + ")");
            PersistPtrHolder pph = (PersistPtrHolder) r;
            // Check the sheet offsets
            Map<Integer, Integer> sheetOffsets = pph.getSlideLocationsLookup();
            for (int id : pph.getKnownSlideIDs()) {
                Integer offset = sheetOffsets.get(id);
                System.out.println("  Knows about sheet " + id);
                System.out.println("    That sheet lives at " + offset);
                Record atPos = findRecordAtPos(offset.intValue());
                System.out.println("    The record at that pos is of type " + atPos.getRecordType());
                System.out.println("    The record at that pos has class " + atPos.getClass().getName());
                if (!(atPos instanceof PositionDependentRecord)) {
                    System.out.println("    ** The record class isn't position aware! **");
                }
            }
        }
        // Increase the position by the on disk size
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        r.writeOut(baos);
        pos += baos.size();
    }
    System.out.println("");
    pos = 0;
    // Now look for UserEditAtoms
    for (Record r : ss.getRecords()) {
        if (r instanceof UserEditAtom) {
            UserEditAtom uea = (UserEditAtom) r;
            System.out.println("Found UserEditAtom at " + pos + " (" + Integer.toHexString(pos) + ")");
            System.out.println("  lastUserEditAtomOffset = " + uea.getLastUserEditAtomOffset());
            System.out.println("  persistPointersOffset  = " + uea.getPersistPointersOffset());
            System.out.println("  docPersistRef          = " + uea.getDocPersistRef());
            System.out.println("  maxPersistWritten      = " + uea.getMaxPersistWritten());
        }
        // Increase the position by the on disk size
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        r.writeOut(baos);
        pos += baos.size();
    }
    System.out.println("");
    // Query the CurrentUserAtom
    CurrentUserAtom cua = ss.getCurrentUserAtom();
    System.out.println("Checking Current User Atom");
    System.out.println("  Thinks the CurrentEditOffset is " + cua.getCurrentEditOffset());
    System.out.println("");
    ss.close();
}
Also used : PositionDependentRecord(org.apache.poi.hslf.record.PositionDependentRecord) PersistPtrHolder(org.apache.poi.hslf.record.PersistPtrHolder) Record(org.apache.poi.hslf.record.Record) PositionDependentRecord(org.apache.poi.hslf.record.PositionDependentRecord) ByteArrayOutputStream(java.io.ByteArrayOutputStream) UserEditAtom(org.apache.poi.hslf.record.UserEditAtom) CurrentUserAtom(org.apache.poi.hslf.record.CurrentUserAtom) HSLFSlideShowImpl(org.apache.poi.hslf.usermodel.HSLFSlideShowImpl)

Example 4 with PositionDependentRecord

use of org.apache.poi.hslf.record.PositionDependentRecord in project poi by apache.

the class SlideIdListing method main.

public static void main(String[] args) throws IOException {
    if (args.length < 1) {
        System.err.println("Need to give a filename");
        System.exit(1);
    }
    // Create the slideshow object, for normal working with
    HSLFSlideShowImpl hss = new HSLFSlideShowImpl(args[0]);
    HSLFSlideShow ss = new HSLFSlideShow(hss);
    // Grab the base contents
    fileContents = hss.getUnderlyingBytes();
    Record[] records = hss.getRecords();
    Record[] latestRecords = ss.getMostRecentCoreRecords();
    // Grab any records that interest us
    Document document = null;
    for (int i = 0; i < latestRecords.length; i++) {
        if (latestRecords[i] instanceof Document) {
            document = (Document) latestRecords[i];
        }
    }
    System.out.println("");
    // Look for SlidePersistAtoms, and report what they have to
    //  say about possible slide IDs
    SlideListWithText[] slwts = document.getSlideListWithTexts();
    for (int i = 0; i < slwts.length; i++) {
        Record[] cr = slwts[i].getChildRecords();
        for (int j = 0; j < cr.length; j++) {
            if (cr[j] instanceof SlidePersistAtom) {
                SlidePersistAtom spa = (SlidePersistAtom) cr[j];
                System.out.println("SlidePersistAtom knows about slide:");
                System.out.println("\t" + spa.getRefID());
                System.out.println("\t" + spa.getSlideIdentifier());
            }
        }
    }
    System.out.println("");
    // Look for latest core records that are slides or notes
    for (int i = 0; i < latestRecords.length; i++) {
        if (latestRecords[i] instanceof Slide) {
            Slide s = (Slide) latestRecords[i];
            SlideAtom sa = s.getSlideAtom();
            System.out.println("Found the latest version of a slide record:");
            System.out.println("\tCore ID is " + s.getSheetId());
            System.out.println("\t(Core Records count is " + i + ")");
            System.out.println("\tDisk Position is " + s.getLastOnDiskOffset());
            System.out.println("\tMaster ID is " + sa.getMasterID());
            System.out.println("\tNotes ID is " + sa.getNotesID());
        }
    }
    System.out.println("");
    for (int i = 0; i < latestRecords.length; i++) {
        if (latestRecords[i] instanceof Notes) {
            Notes n = (Notes) latestRecords[i];
            NotesAtom na = n.getNotesAtom();
            System.out.println("Found the latest version of a notes record:");
            System.out.println("\tCore ID is " + n.getSheetId());
            System.out.println("\t(Core Records count is " + i + ")");
            System.out.println("\tDisk Position is " + n.getLastOnDiskOffset());
            System.out.println("\tMatching slide is " + na.getSlideID());
        }
    }
    System.out.println("");
    // Find any persist ones first
    int pos = 0;
    for (int i = 0; i < records.length; i++) {
        Record r = records[i];
        if (r.getRecordType() == 6001l) {
            // PersistPtrFullBlock
            System.out.println("Found PersistPtrFullBlock at " + pos + " (" + Integer.toHexString(pos) + ")");
        }
        if (r.getRecordType() == 6002l) {
            // PersistPtrIncrementalBlock
            System.out.println("Found PersistPtrIncrementalBlock at " + pos + " (" + Integer.toHexString(pos) + ")");
            PersistPtrHolder pph = (PersistPtrHolder) r;
            // Check the sheet offsets
            int[] sheetIDs = pph.getKnownSlideIDs();
            Map<Integer, Integer> sheetOffsets = pph.getSlideLocationsLookup();
            for (int j = 0; j < sheetIDs.length; j++) {
                Integer id = sheetIDs[j];
                Integer offset = sheetOffsets.get(id);
                System.out.println("  Knows about sheet " + id);
                System.out.println("    That sheet lives at " + offset);
                Record atPos = findRecordAtPos(offset.intValue());
                System.out.println("    The record at that pos is of type " + atPos.getRecordType());
                System.out.println("    The record at that pos has class " + atPos.getClass().getName());
                if (!(atPos instanceof PositionDependentRecord)) {
                    System.out.println("    ** The record class isn't position aware! **");
                }
            }
        }
        // Increase the position by the on disk size
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        r.writeOut(baos);
        pos += baos.size();
    }
    ss.close();
    System.out.println("");
}
Also used : SlideListWithText(org.apache.poi.hslf.record.SlideListWithText) SlidePersistAtom(org.apache.poi.hslf.record.SlidePersistAtom) PersistPtrHolder(org.apache.poi.hslf.record.PersistPtrHolder) ByteArrayOutputStream(java.io.ByteArrayOutputStream) Document(org.apache.poi.hslf.record.Document) HSLFSlideShow(org.apache.poi.hslf.usermodel.HSLFSlideShow) HSLFSlideShowImpl(org.apache.poi.hslf.usermodel.HSLFSlideShowImpl) NotesAtom(org.apache.poi.hslf.record.NotesAtom) PositionDependentRecord(org.apache.poi.hslf.record.PositionDependentRecord) SlideAtom(org.apache.poi.hslf.record.SlideAtom) Slide(org.apache.poi.hslf.record.Slide) Record(org.apache.poi.hslf.record.Record) PositionDependentRecord(org.apache.poi.hslf.record.PositionDependentRecord) Notes(org.apache.poi.hslf.record.Notes)

Aggregations

PersistPtrHolder (org.apache.poi.hslf.record.PersistPtrHolder)4 PositionDependentRecord (org.apache.poi.hslf.record.PositionDependentRecord)4 Record (org.apache.poi.hslf.record.Record)4 UserEditAtom (org.apache.poi.hslf.record.UserEditAtom)3 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 Map (java.util.Map)2 NavigableMap (java.util.NavigableMap)2 TreeMap (java.util.TreeMap)2 HSLFSlideShowImpl (org.apache.poi.hslf.usermodel.HSLFSlideShowImpl)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 EncryptedDocumentException (org.apache.poi.EncryptedDocumentException)1 HSLFException (org.apache.poi.hslf.exceptions.HSLFException)1 CurrentUserAtom (org.apache.poi.hslf.record.CurrentUserAtom)1 Document (org.apache.poi.hslf.record.Document)1 Notes (org.apache.poi.hslf.record.Notes)1 NotesAtom (org.apache.poi.hslf.record.NotesAtom)1 PersistRecord (org.apache.poi.hslf.record.PersistRecord)1 RecordTypes (org.apache.poi.hslf.record.RecordTypes)1 Slide (org.apache.poi.hslf.record.Slide)1