
/* ====================================================================
   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.record;

import static org.apache.poi.hslf.usermodel.HSLFSlideShow.PP95_DOCUMENT;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
import org.apache.poi.hslf.exceptions.OldPowerPointFormatException;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.StringUtil;

/**
 * This is a special kind of Atom, because it doesn't live inside the
 *  PowerPoint document. Instead, it lives in a separate stream in the
 *  document. As such, it has to be treated specially
 */
public class CurrentUserAtom
{
	private static final POILogger LOG = POILogFactory.getLogger(CurrentUserAtom.class);
	//arbitrarily selected; may need to increase
	private static final int MAX_RECORD_LENGTH = 1_000_000;

	/** Standard Atom header */
	private static final byte[] atomHeader = new byte[] { 0, 0, -10, 15 };
	/** The PowerPoint magic number for a non-encrypted file */
	private static final byte[] headerToken = new byte[] { 95, -64, -111, -29 };
	/** The PowerPoint magic number for an encrypted file */
	private static final byte[] encHeaderToken = new byte[] { -33, -60, -47, -13 };
	// The Powerpoint 97 version, major and minor numbers
	// byte[] ppt97FileVer = new byte[] { 8, 00, -13, 03, 03, 00 };

	/** The version, major and minor numbers */
	private int docFinalVersion;
	private byte docMajorNo;
	private byte docMinorNo;

	/** The Offset into the file for the current edit */
    private long currentEditOffset;
	/** The Username of the last person to edit the file */
	private String lastEditUser;
	/** The document release version. Almost always 8 */
	private long releaseVersion;

	/** Only correct after reading in or writing out */
	private byte[] _contents;

	/** Flag for encryption state of the whole file */
	private boolean isEncrypted;


	/* ********************* getter/setter follows *********************** */

	public int  getDocFinalVersion() { return docFinalVersion; }
	public byte getDocMajorNo()       { return docMajorNo; }
	public byte getDocMinorNo()       { return docMinorNo; }

	public long getReleaseVersion()  { return releaseVersion; }
	public void setReleaseVersion(long rv) { releaseVersion = rv; }

	/** Points to the UserEditAtom */
	public long getCurrentEditOffset() { return currentEditOffset; }
	public void setCurrentEditOffset(long id ) { currentEditOffset = id; }

	public String getLastEditUsername() { return lastEditUser; }
	public void setLastEditUsername(String u) { lastEditUser = u; }

	public boolean isEncrypted() { return isEncrypted; }
	public void setEncrypted(boolean isEncrypted) { this.isEncrypted = isEncrypted; }


	/* ********************* real code follows *************************** */

	/**
	 * Create a new Current User Atom
	 */
	public CurrentUserAtom() {
		_contents = new byte[0];

		// Initialise to empty
		docFinalVersion = 0x03f4;
		docMajorNo = 3;
		docMinorNo = 0;
		releaseVersion = 8;
		currentEditOffset = 0;
		lastEditUser = "Apache POI";
		isEncrypted = false;
	}


	/**
	 * Find the Current User in the filesystem, and create from that
	 */
	public CurrentUserAtom(DirectoryNode dir) throws IOException {
		// Decide how big it is
		DocumentEntry docProps =
			(DocumentEntry)dir.getEntry("Current User");

		// If it's clearly junk, bail out
		if(docProps.getSize() > 131072) {
			throw new CorruptPowerPointFileException("The Current User stream is implausably long. It's normally 28-200 bytes long, but was " + docProps.getSize() + " bytes");
		}

		// Grab the contents
		try (InputStream in = dir.createDocumentInputStream("Current User")) {
			_contents = IOUtils.toByteArray(in, docProps.getSize(), MAX_RECORD_LENGTH);
		}

		// See how long it is. If it's under 28 bytes long, we can't
		//  read it
		if(_contents.length < 28) {
		    boolean isPP95 = dir.hasEntry(PP95_DOCUMENT);
		    // PPT95 has 4 byte size, then data
			if (!isPP95 && _contents.length >= 4) {
				int size = LittleEndian.getInt(_contents);
				isPP95 = (size + 4 == _contents.length);
			}

			if (isPP95) {
			    throw new OldPowerPointFormatException("Based on the Current User stream, you seem to have supplied a PowerPoint95 file, which isn't supported");
			} else {
			    throw new CorruptPowerPointFileException("The Current User stream must be at least 28 bytes long, but was only " + _contents.length);
			}
		}

		// Set everything up
		init();
	}

	/**
	 * Actually do the creation from a block of bytes
	 */
	private void init() {
		// First up is the size, in 4 bytes, which is fixed
		// Then is the header

	    isEncrypted = (LittleEndian.getInt(encHeaderToken) == LittleEndian.getInt(_contents,12));

		// Grab the edit offset
		currentEditOffset = LittleEndian.getUInt(_contents,16);

		// Grab the versions
		docFinalVersion = LittleEndian.getUShort(_contents,22);
		docMajorNo = _contents[24];
		docMinorNo = _contents[25];

		// Get the username length
		long usernameLen = LittleEndian.getUShort(_contents,20);
		if(usernameLen > 512) {
			// Handle the case of it being garbage
			LOG.log(POILogger.WARN, "Warning - invalid username length ", usernameLen, " found, treating as if there was no username set");
			usernameLen = 0;
		}

		// Now we know the length of the username,
		//  use this to grab the revision
		if(_contents.length >= 28+(int)usernameLen + 4) {
			releaseVersion = LittleEndian.getUInt(_contents,28+(int)usernameLen);
		} else {
			// No revision given, as not enough data. Odd
			releaseVersion = 0;
		}

		// Grab the unicode username, if stored
		int start = 28+(int)usernameLen+4;

		if(_contents.length >= start+2*usernameLen) {
			lastEditUser = StringUtil.getFromUnicodeLE(_contents, start, (int)usernameLen);
		} else {
			// Fake from the 8 bit version
			lastEditUser = StringUtil.getFromCompressedUnicode(_contents, 28, (int)usernameLen);
		}
	}


	/**
	 * Writes ourselves back out
	 */
	public void writeOut(OutputStream out) throws IOException {
		// Decide on the size
		//  8 = atom header
		//  20 = up to name
		//  4 = revision
		//  3 * len = ascii + unicode
		int size = 8 + 20 + 4 + (3 * lastEditUser.length());
		_contents = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);

		// First we have a 8 byte atom header
		System.arraycopy(atomHeader,0,_contents,0,4);
		// Size is 20+user len + revision len(4)
		int atomSize = 20+4+lastEditUser.length();
		LittleEndian.putInt(_contents,4,atomSize);

		// Now we have the size of the details, which is 20
		LittleEndian.putInt(_contents,8,20);

		// Now the ppt un-encrypted header token (4 bytes)
		System.arraycopy((isEncrypted ? encHeaderToken : headerToken),0,_contents,12,4);

		// Now the current edit offset
		LittleEndian.putInt(_contents,16,(int)currentEditOffset);

		// The username gets stored twice, once as US
		//  ascii, and again as unicode laster on
		byte[] asciiUN = IOUtils.safelyAllocate(lastEditUser.length(), MAX_RECORD_LENGTH);
		StringUtil.putCompressedUnicode(lastEditUser,asciiUN,0);

		// Now we're able to do the length of the last edited user
		LittleEndian.putShort(_contents,20,(short)asciiUN.length);

		// Now the file versions, 2+1+1
		LittleEndian.putShort(_contents,22,(short)docFinalVersion);
		_contents[24] = docMajorNo;
		_contents[25] = docMinorNo;

		// 2 bytes blank
		_contents[26] = 0;
		_contents[27] = 0;

		// At this point we have the username as us ascii
		System.arraycopy(asciiUN,0,_contents,28,asciiUN.length);

		// 4 byte release version
		LittleEndian.putInt(_contents,28+asciiUN.length,(int)releaseVersion);

		// username in unicode
		byte [] ucUN = IOUtils.safelyAllocate(lastEditUser.length() * 2L, MAX_RECORD_LENGTH);
		StringUtil.putUnicodeLE(lastEditUser,ucUN,0);
		System.arraycopy(ucUN,0,_contents,28+asciiUN.length+4,ucUN.length);

		// Write out
		out.write(_contents);
	}

	/**
	 * Writes ourselves back out to a filesystem
	 */
	public void writeToFS(POIFSFileSystem fs) throws IOException {
		// Grab contents
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		writeOut(baos);
		ByteArrayInputStream bais =
			new ByteArrayInputStream(baos.toByteArray());

		// Write out
		fs.createOrUpdateDocument(bais,"Current User");
	}
}
