
/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */
        


package org.apache.poi.hslf;

import java.io.FileNotFoundException;

import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
import org.apache.poi.hslf.record.CurrentUserAtom;
import org.apache.poi.hslf.record.DocumentEncryptionAtom;
import org.apache.poi.hslf.record.PersistPtrHolder;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.UserEditAtom;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.util.LittleEndian;

/**
 * This class provides helper functions for determining if a
 *  PowerPoint document is Encrypted. 
 * In future, it may also provide Encryption and Decryption
 *  functions, but first we'd need to figure out how 
 *  PowerPoint encryption is really done!
 *
 * @author Nick Burch
 */

public class EncryptedSlideShow
{
	/**
	 * Check to see if a HSLFSlideShow represents an encrypted
	 *  PowerPoint document, or not
	 * @param hss The HSLFSlideShow to check
	 * @return true if encrypted, otherwise false
	 */
	public static boolean checkIfEncrypted(HSLFSlideShow hss) {
		// Easy way to check - contains a stream
		//  "EncryptedSummary"
		try {
			hss.getPOIFSDirectory().getEntry("EncryptedSummary");
			return true;
		} catch(FileNotFoundException fnfe) {
			// Doesn't have encrypted properties
		}
		
		// If they encrypted the document but not the properties,
		//  it's harder.
		// We need to see what the last record pointed to by the
		//  first PersistPrtHolder is - if it's a 
		//  DocumentEncryptionAtom, then the file's Encrypted
		DocumentEncryptionAtom dea = fetchDocumentEncryptionAtom(hss);
		if(dea != null) {
			return true;
		}
		return false;
	}
	
	/**
	 * Return the DocumentEncryptionAtom for a HSLFSlideShow, or
	 *  null if there isn't one.
	 * @return a DocumentEncryptionAtom, or null if there isn't one
	 */
	public static DocumentEncryptionAtom fetchDocumentEncryptionAtom(HSLFSlideShow hss) {
		// Will be the last Record pointed to by the 
		//  first PersistPrtHolder, if there is one
		
		CurrentUserAtom cua = hss.getCurrentUserAtom();
		if(cua.getCurrentEditOffset() != 0) {
			// Check it's not past the end of the file
			if(cua.getCurrentEditOffset() > hss.getUnderlyingBytes().length) {
				throw new CorruptPowerPointFileException("The CurrentUserAtom claims that the offset of last edit details are past the end of the file");
			}
			
			// Grab the details of the UserEditAtom there
			// If the record's messed up, we could AIOOB
			Record r = null;
			try {
				r = Record.buildRecordAtOffset(
						hss.getUnderlyingBytes(),
						(int)cua.getCurrentEditOffset()
				);
			} catch(ArrayIndexOutOfBoundsException e) {}
			if(r == null) { return null; }
			if(! (r instanceof UserEditAtom)) { return null; }
			UserEditAtom uea = (UserEditAtom)r;
			
			// Now get the PersistPtrHolder
			Record r2 = Record.buildRecordAtOffset(
					hss.getUnderlyingBytes(),
					uea.getPersistPointersOffset()
			);
			if(! (r2 instanceof PersistPtrHolder)) { return null; }
			PersistPtrHolder pph = (PersistPtrHolder)r2;
			
			// Now get the last record
			int[] slideIds = pph.getKnownSlideIDs();
			int maxSlideId = -1;
			for(int i=0; i<slideIds.length; i++) {
				if(slideIds[i] > maxSlideId) { maxSlideId = slideIds[i]; }
			}
			if(maxSlideId == -1) { return null; }
			
			int offset = (
					(Integer)pph.getSlideLocationsLookup().get(
							new Integer(maxSlideId)
					) ).intValue();
			Record r3 = Record.buildRecordAtOffset(
					hss.getUnderlyingBytes(),
					offset
			);
			
			// If we have a DocumentEncryptionAtom, it'll be this one
			if(r3 instanceof DocumentEncryptionAtom) {
				return (DocumentEncryptionAtom)r3;
			}
		}
		
		return null;
	}
}
