001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hslf;
019:
020: import java.io.FileNotFoundException;
021:
022: import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
023: import org.apache.poi.hslf.record.CurrentUserAtom;
024: import org.apache.poi.hslf.record.DocumentEncryptionAtom;
025: import org.apache.poi.hslf.record.PersistPtrHolder;
026: import org.apache.poi.hslf.record.Record;
027: import org.apache.poi.hslf.record.UserEditAtom;
028: import org.apache.poi.poifs.filesystem.POIFSFileSystem;
029: import org.apache.poi.poifs.filesystem.DocumentEntry;
030: import org.apache.poi.poifs.filesystem.DocumentInputStream;
031: import org.apache.poi.util.LittleEndian;
032:
033: /**
034: * This class provides helper functions for determining if a
035: * PowerPoint document is Encrypted.
036: * In future, it may also provide Encryption and Decryption
037: * functions, but first we'd need to figure out how
038: * PowerPoint encryption is really done!
039: *
040: * @author Nick Burch
041: */
042:
043: public class EncryptedSlideShow {
044: /**
045: * Check to see if a HSLFSlideShow represents an encrypted
046: * PowerPoint document, or not
047: * @param hss The HSLFSlideShow to check
048: * @return true if encrypted, otherwise false
049: */
050: public static boolean checkIfEncrypted(HSLFSlideShow hss) {
051: // Easy way to check - contains a stream
052: // "EncryptedSummary"
053: POIFSFileSystem fs = hss.getPOIFSFileSystem();
054: try {
055: fs.getRoot().getEntry("EncryptedSummary");
056: return true;
057: } catch (FileNotFoundException fnfe) {
058: // Doesn't have encrypted properties
059: }
060:
061: // If they encrypted the document but not the properties,
062: // it's harder.
063: // We need to see what the last record pointed to by the
064: // first PersistPrtHolder is - if it's a
065: // DocumentEncryptionAtom, then the file's Encrypted
066: DocumentEncryptionAtom dea = fetchDocumentEncryptionAtom(hss);
067: if (dea != null) {
068: return true;
069: }
070: return false;
071: }
072:
073: /**
074: * Return the DocumentEncryptionAtom for a HSLFSlideShow, or
075: * null if there isn't one.
076: * @return a DocumentEncryptionAtom, or null if there isn't one
077: */
078: public static DocumentEncryptionAtom fetchDocumentEncryptionAtom(
079: HSLFSlideShow hss) {
080: // Will be the last Record pointed to by the
081: // first PersistPrtHolder, if there is one
082:
083: CurrentUserAtom cua = hss.getCurrentUserAtom();
084: if (cua.getCurrentEditOffset() != 0) {
085: // Check it's not past the end of the file
086: if (cua.getCurrentEditOffset() > hss.getUnderlyingBytes().length) {
087: throw new CorruptPowerPointFileException(
088: "The CurrentUserAtom claims that the offset of last edit details are past the end of the file");
089: }
090:
091: // Grab the details of the UserEditAtom there
092: // If the record's messed up, we could AIOOB
093: Record r = null;
094: try {
095: r = Record.buildRecordAtOffset(
096: hss.getUnderlyingBytes(), (int) cua
097: .getCurrentEditOffset());
098: } catch (ArrayIndexOutOfBoundsException e) {
099: }
100: if (r == null) {
101: return null;
102: }
103: if (!(r instanceof UserEditAtom)) {
104: return null;
105: }
106: UserEditAtom uea = (UserEditAtom) r;
107:
108: // Now get the PersistPtrHolder
109: Record r2 = Record.buildRecordAtOffset(hss
110: .getUnderlyingBytes(), uea
111: .getPersistPointersOffset());
112: if (!(r2 instanceof PersistPtrHolder)) {
113: return null;
114: }
115: PersistPtrHolder pph = (PersistPtrHolder) r2;
116:
117: // Now get the last record
118: int[] slideIds = pph.getKnownSlideIDs();
119: int maxSlideId = -1;
120: for (int i = 0; i < slideIds.length; i++) {
121: if (slideIds[i] > maxSlideId) {
122: maxSlideId = slideIds[i];
123: }
124: }
125: if (maxSlideId == -1) {
126: return null;
127: }
128:
129: int offset = ((Integer) pph.getSlideLocationsLookup().get(
130: new Integer(maxSlideId))).intValue();
131: Record r3 = Record.buildRecordAtOffset(hss
132: .getUnderlyingBytes(), offset);
133:
134: // If we have a DocumentEncryptionAtom, it'll be this one
135: if (r3 instanceof DocumentEncryptionAtom) {
136: return (DocumentEncryptionAtom) r3;
137: }
138: }
139:
140: return null;
141: }
142: }
|