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

de.intarsys.pdf.crypt.SystemSecurityHandler Maven / Gradle / Ivy

/*
 * Copyright (c) 2007, intarsys consulting GmbH
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * - Neither the name of intarsys nor the names of its contributors may be used
 *   to endorse or promote products derived from this software without specific
 *   prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package de.intarsys.pdf.crypt;

import de.intarsys.pdf.cos.COSArray;
import de.intarsys.pdf.cos.COSCompositeObject;
import de.intarsys.pdf.cos.COSDictionary;
import de.intarsys.pdf.cos.COSInteger;
import de.intarsys.pdf.cos.COSNumber;
import de.intarsys.pdf.cos.COSStream;
import de.intarsys.pdf.cos.COSTrailer;
import de.intarsys.pdf.st.EnumWriteMode;
import de.intarsys.pdf.st.STDocument;
import de.intarsys.pdf.st.STStreamXRefSection;

/**
 * An abstract superclass for implementing the PDF security process.
 * 
 */
abstract public class SystemSecurityHandler implements ISystemSecurityHandler {

	public static final int DEFAULT_LENGTH = 40;

	static public SystemSecurityHandler createFromSt(STDocument doc)
			throws COSSecurityException {
		SystemSecurityHandler systemSecurityHandler = null;
		COSDictionary dict = doc.cosGetTrailer().get(COSTrailer.DK_Encrypt)
				.asDictionary();
		if (dict != null) {
			int version = 0;
			COSNumber cosVersion = dict.get(COSEncryption.DK_V).asNumber();
			if (cosVersion != null) {
				version = cosVersion.intValue();
			}
			if (version == 0) {
				systemSecurityHandler = new SystemSecurityHandlerV0(dict);
			} else if (version == 1) {
				systemSecurityHandler = new SystemSecurityHandlerV1(dict);
			} else if (version == 2) {
				systemSecurityHandler = new SystemSecurityHandlerV2(dict);
			} else if (version == 3) {
				systemSecurityHandler = new SystemSecurityHandlerV3(dict);
			} else if (version == 4) {
				systemSecurityHandler = new SystemSecurityHandlerV4(dict);
			} else {
				throw new COSSecurityException("unsupported security version "
						+ version);
			}
			systemSecurityHandler.initialize(doc);
		}
		return systemSecurityHandler;
	}

	static public SystemSecurityHandler createNewV1() {
		COSDictionary dict = COSDictionary.create();
		dict.beIndirect();
		SystemSecurityHandler result = new SystemSecurityHandlerV1(dict);
		result.initializeFromScratch();
		return result;
	}

	static public SystemSecurityHandler createNewV2() {
		COSDictionary dict = COSDictionary.create();
		dict.beIndirect();
		SystemSecurityHandler result = new SystemSecurityHandlerV2(dict);
		result.initializeFromScratch();
		return result;
	}

	static public SystemSecurityHandler createNewV4() {
		COSDictionary dict = COSDictionary.create();
		dict.beIndirect();
		SystemSecurityHandler result = new SystemSecurityHandlerV4(dict);
		result.initializeFromScratch();
		return result;
	}

	final private COSDictionary cosEncryption;

	private COSArray currentCosIDs;

	final private COSEncryption encryption;

	private COSDictionary currentCosTrailer;

	private COSDictionary currentCosEncryption;

	private ISecurityHandler securityHandler;

	private STDocument stDoc;

	private COSCompositeObject[] contextStack = new COSCompositeObject[5];

	private short stackPtr = -1;

	private boolean enabled = true;

	protected SystemSecurityHandler(COSDictionary dict) {
		this.cosEncryption = dict;
		this.currentCosEncryption = cosEncryption;
		this.encryption = (COSEncryption) COSEncryption.META
				.createFromCos(dict);
	}

	public void attach(STDocument stDoc) throws COSSecurityException {
		this.stDoc = stDoc;
		currentCosTrailer = stDoc.cosGetTrailer();
		currentCosIDs = currentCosTrailer.get(COSTrailer.DK_ID).asArray();
		currentCosTrailer.put(COSTrailer.DK_Encrypt, cosGetEncryption());
		if (getSecurityHandler() != null) {
			getSecurityHandler().attach(stDoc);
		}
		forceFullWrite();
	}

	public void authenticate() throws COSSecurityException {
		securityHandler.authenticate();
	}

	public COSDictionary cosGetEncryption() {
		return cosEncryption;
	}

	public void detach(STDocument stDoc) throws COSSecurityException {
		if (getSecurityHandler() != null) {
			getSecurityHandler().detach(stDoc);
		}
		stDoc.cosGetTrailer().remove(COSTrailer.DK_Encrypt);
		forceFullWrite();
		// don't eliminate back reference
	}

	protected void forceFullWrite() {
		if (stGetDoc() == null) {
			return;
		}
		stGetDoc().setWriteModeHint(EnumWriteMode.FULL);
	}

	public COSCompositeObject getContextObject() {
		if (stackPtr < 0) {
			return null;
		}
		return contextStack[stackPtr];
	}

	public COSEncryption getEncryption() {
		return encryption;
	}

	public int getLength() {
		COSEncryption encryption = getEncryption();
		return encryption.getFieldInt(COSEncryption.DK_Length, DEFAULT_LENGTH);
	}

	public ISecurityHandler getSecurityHandler() {
		return securityHandler;
	}

	abstract public int getVersion();

	public void initialize(STDocument doc) throws COSSecurityException {
		this.stDoc = doc;
		initializeFromSt();
	}

	protected void initializeFromScratch() {
		COSEncryption encryption = getEncryption();
		encryption.cosSetField(COSEncryption.DK_V, COSInteger
				.create(getVersion()));
	}

	protected void initializeFromSt() throws COSSecurityException {
		COSEncryption encryption = getEncryption();
		securityHandler = SecurityHandlerFactory.get().getSecurityHandler(
				encryption);
		securityHandler.initialize(stGetDoc());
	}

	protected boolean isEnabled() {
		return enabled;
	}

	public COSCompositeObject popContextObject() {
		COSCompositeObject contextObject = contextStack[stackPtr--];
		// enable encryption when no longer in encryption dict of file id's
		if (contextObject == currentCosEncryption
				|| contextObject == currentCosIDs) {
			enabled = true;
		}
		if (contextObject instanceof COSStream) {
			COSDictionary dict = contextObject.asStream().getDict();
			if (dict != null
					&& dict.get(STStreamXRefSection.DK_Type).equals(
							STStreamXRefSection.CN_Type_XRef)) {
				// /XRef streams are not encrypted
				enabled = true;
			}
		}
		return contextObject;
	}

	public void pushContextObject(COSCompositeObject contextObject) {
		stackPtr++;
		if (stackPtr >= contextStack.length) {
			COSCompositeObject[] tempStack = new COSCompositeObject[contextStack.length + 5];
			System
					.arraycopy(contextStack, 0, tempStack, 0,
							contextStack.length);
			contextStack = tempStack;
		}
		contextStack[stackPtr] = contextObject;
		// do not encrypt within encryption dict and file id's
		if (contextObject == currentCosEncryption
				|| contextObject == currentCosIDs) {
			enabled = false;
		}
		if (contextObject instanceof COSStream) {
			COSDictionary dict = contextObject.asStream().getDict();
			if (dict != null
					&& dict.get(STStreamXRefSection.DK_Type).equals(
							STStreamXRefSection.CN_Type_XRef)) {
				// /XRef streams are not encrypted
				enabled = false;
			}
		}
	}

	public void setLength(int length) {
		COSEncryption encryption = getEncryption();
		encryption.setFieldInt(COSEncryption.DK_Length, length);
	}

	public void setSecurityHandler(ISecurityHandler pSecurityHandler)
			throws COSSecurityException {
		if (securityHandler != null) {
			securityHandler.detach(stGetDoc());
		}
		securityHandler = pSecurityHandler;
		if (securityHandler != null) {
			securityHandler.attach(stGetDoc());
		}
	}

	public STDocument stGetDoc() {
		return stDoc;
	}

	public void updateTrailer(COSDictionary trailer) {
		this.currentCosTrailer = trailer;
		this.currentCosIDs = currentCosTrailer.get(COSTrailer.DK_ID).asArray();
		this.currentCosEncryption = trailer.get(COSTrailer.DK_Encrypt)
				.asDictionary();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy