/*
 * 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.
 */

/* $Id$ */

package org.apache.fop.pdf;

// Java
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

/**
 * class representing a /Filter /Standard object.
 *
 */
public class PDFEncryptionJCE extends PDFObject implements PDFEncryption {

    private class EncryptionFilter extends PDFFilter {
        private PDFEncryptionJCE encryption;
        private int number;
        private int generation;

        /**
         * The constructor for the internal PDFEncryptionJCE filter
         * @param encryption The encryption object to use
         * @param number The number of the object to be encrypted
         * @param generation The generation of the object to be encrypted
         */
        public EncryptionFilter(PDFEncryptionJCE encryption,
                                int number, int generation) {
            super();
            this.encryption = encryption;
            this.number  = number;
            this.generation = generation;
            log.debug("new encryption filter for number "
                + number + " and generation " + generation);
        }

        /**
         * Return a PDF string representation of the filter. In this
         * case no filter name is passed.
         * @return The filter name, blank in this case
         */
        public String getName() {
            return "";
        }

        /**
         * Return a parameter dictionary for this filter, or null
         * @return The parameter dictionary. In this case, null.
         */
        public PDFObject getDecodeParms() {
            return null;
        }

        /**
         * Encode the given data with the filter
         * @param data The data to be encrypted
         * @return The encrypted data
         */
        public byte[] encode(byte[] data) {
            return encryption.encryptData(data, number, generation);
        }

        /**
         * {@inheritDoc}
         */
        public void encode(InputStream in, OutputStream out, int length)
                                                        throws IOException {
            byte[] buffer = new byte[length];
            in.read(buffer);
            buffer = encode(buffer);
            out.write(buffer);
        }

        /**
         * {@inheritDoc}
         */
        public OutputStream applyFilter(OutputStream out) throws IOException {
            return new CipherOutputStream(out,
                    encryption.initCipher(number, generation));
        }

    }

    private static final char [] PAD
                             = {0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
                                0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
                                0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
                                0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A};

    /** Value of PRINT permission */
    public static final int PERMISSION_PRINT            =  4;
    /** Value of content editting permission */
    public static final int PERMISSION_EDIT_CONTENT     =  8;
    /** Value of content extraction permission */
    public static final int PERMISSION_COPY_CONTENT     = 16;
    /** Value of annotation editting permission */
    public static final int PERMISSION_EDIT_ANNOTATIONS = 32;

    // Encryption tools
    private MessageDigest digest = null;
    //private Cipher cipher = null;
    private Random random = new Random();
    // Control attributes
    private PDFEncryptionParams params;
    // Output attributes
    private byte[] fileID = null;
    private byte[] encryptionKey = null;
    private String dictionary = null;

    /**
     * Create a /Filter /Standard object.
     *
     * @param objnum the object's number
     */
    public PDFEncryptionJCE(int objnum) {
        /* generic creation of object */
        super();
        setObjectNumber(objnum);
        try {
            digest = MessageDigest.getInstance("MD5");
            //cipher = Cipher.getInstance("RC4");
        } catch (NoSuchAlgorithmException e) {
            throw new UnsupportedOperationException(e.getMessage());
        /*} catch (NoSuchPaddingException e) {
            throw new UnsupportedOperationException(e.getMessage());*/
        }
    }

    /**
     * Local factory method.
     * @param objnum PDF object number for the encryption object
     * @param params PDF encryption parameters
     * @return PDFEncryption the newly created PDFEncryption object
     */
    public static PDFEncryption make(int objnum, PDFEncryptionParams params) {
        PDFEncryptionJCE impl = new PDFEncryptionJCE(objnum);
        impl.setParams(params);
        impl.init();
        return impl;
    }


    /**
     * Returns the encryption parameters.
     * @return the encryption parameters
     */
    public PDFEncryptionParams getParams() {
        return this.params;
    }

    /**
     * Sets the encryption parameters.
     * @param params The parameterss to set
     */
    public void setParams(PDFEncryptionParams params) {
        this.params = params;
    }

    // Internal procedures

    private byte[] prepPassword(String password) {
        byte[] obuffer = new byte[32];
        byte[] pbuffer = password.getBytes();

        int i = 0;
        int j = 0;

        while (i < obuffer.length && i < pbuffer.length) {
            obuffer[i] = pbuffer[i];
            i++;
        }
        while (i < obuffer.length) {
            obuffer[i++] = (byte) PAD[j++];
        }

        return obuffer;
    }

    /**
     * Returns the document file ID
     * @return The file ID
     */
    public byte[] getFileID() {
        if (fileID == null) {
            fileID = new byte[16];
            random.nextBytes(fileID);
        }

        return fileID;
    }

    /**
     * This method returns the indexed file ID
     * @param index The index to access the file ID
     * @return The file ID
     */
    public String getFileID(int index) {
        if (index == 1) {
            return PDFText.toHex(getFileID());
        }

        byte[] id = new byte[16];
        random.nextBytes(id);
        return PDFText.toHex(id);
    }

    private byte[] encryptWithKey(byte[] data, byte[] key) {
        try {
            final Cipher c = initCipher(key);
            return c.doFinal(data);
        } catch (IllegalBlockSizeException e) {
            throw new IllegalStateException(e.getMessage());
        } catch (BadPaddingException e) {
            throw new IllegalStateException(e.getMessage());
        }
    }

    private Cipher initCipher(byte[] key) {
        try {
            Cipher c = Cipher.getInstance("RC4");
            SecretKeySpec keyspec = new SecretKeySpec(key, "RC4");
            c.init(Cipher.ENCRYPT_MODE, keyspec);
            return c;
        } catch (InvalidKeyException e) {
            throw new IllegalStateException(e.getMessage());
        } catch (NoSuchAlgorithmException e) {
            throw new UnsupportedOperationException(e.getMessage());
        } catch (NoSuchPaddingException e) {
            throw new UnsupportedOperationException(e.getMessage());
        }
    }

    private Cipher initCipher(int number, int generation) {
        byte[] hash = calcHash(number, generation);
        int size = hash.length;
        hash = digest.digest(hash);
        byte[] key = calcKey(hash, size);
        return initCipher(key);
    }

    private byte[] encryptWithHash(byte[] data, byte[] hash, int size) {
        hash = digest.digest(hash);

        byte[] key = calcKey(hash, size);

        return encryptWithKey(data, key);
    }

    private byte[] calcKey(byte[] hash, int size) {
        byte[] key = new byte[size];

        for (int i = 0; i < size; i++) {
            key[i] = hash[i];
        }
        return key;
    }

    /**
     * This method initializes the encryption algorithms and values
     */
    public void init() {
        // Generate the owner value
        byte[] oValue;
        if (params.getOwnerPassword().length() > 0) {
            oValue = encryptWithHash(
                    prepPassword(params.getUserPassword()),
                    prepPassword(params.getOwnerPassword()), 5);
        } else {
            oValue = encryptWithHash(
                    prepPassword(params.getUserPassword()),
                    prepPassword(params.getUserPassword()), 5);
        }

        // Generate permissions value
        int permissions = -4;

        if (!params.isAllowPrint()) {
            permissions -= PERMISSION_PRINT;
        }
        if (!params.isAllowCopyContent()) {
            permissions -= PERMISSION_COPY_CONTENT;
        }
        if (!params.isAllowEditContent()) {
            permissions -= PERMISSION_EDIT_CONTENT;
        }
        if (!params.isAllowEditAnnotations()) {
            permissions -= PERMISSION_EDIT_ANNOTATIONS;
        }

        // Create the encrption key
        digest.update(prepPassword(params.getUserPassword()));
        digest.update(oValue);
        digest.update((byte) (permissions >>> 0));
        digest.update((byte) (permissions >>> 8));
        digest.update((byte) (permissions >>> 16));
        digest.update((byte) (permissions >>> 24));
        digest.update(getFileID());

        byte [] hash = digest.digest();
        this.encryptionKey = new byte[5];

        for (int i = 0; i < 5; i++) {
            this.encryptionKey[i] = hash[i];
        }

        // Create the user value
        byte[] uValue = encryptWithKey(prepPassword(""), this.encryptionKey);

        // Create the dictionary
        this.dictionary = getObjectID()
                        + "<< /Filter /Standard\n"
                        + "/V 1\n"
                        + "/R 2\n"
                        + "/Length 40\n"
                        + "/P "  + permissions + "\n"
                        + "/O " + PDFText.toHex(oValue) + "\n"
                        + "/U " + PDFText.toHex(uValue) + "\n"
                        + ">>\n"
                        + "endobj\n";
    }

    /**
     * This method encrypts the passed data using the generated keys.
     * @param data The data to be encrypted
     * @param number The block number
     * @param generation The block generation
     * @return The encrypted data
     */
    public byte[] encryptData(byte[] data, int number, int generation) {
        if (this.encryptionKey == null) {
            throw new IllegalStateException("PDF Encryption has not been initialized");
        }
        byte[] hash = calcHash(number, generation);
        return encryptWithHash(data, hash, hash.length);
    }

    /** {@inheritDoc} */
    public byte[] encrypt(byte[] data, PDFObject refObj) {
        PDFObject o = refObj;
        while (o != null && !o.hasObjectNumber()) {
            o = o.getParent();
        }
        if (o == null) {
            throw new IllegalStateException("No object number could be obtained for a PDF object");
        }
        return encryptData(data, o.getObjectNumber(), o.getGeneration());
    }

    private byte[] calcHash(int number, int generation) {
        byte[] hash = new byte[this.encryptionKey.length + 5];

        int i = 0;
        while (i < this.encryptionKey.length) {
            hash[i] = this.encryptionKey[i]; i++;
        }

        hash[i++] = (byte) (number >>> 0);
        hash[i++] = (byte) (number >>> 8);
        hash[i++] = (byte) (number >>> 16);
        hash[i++] = (byte) (generation >>> 0);
        hash[i++] = (byte) (generation >>> 8);
        return hash;
    }

    /**
     * Creates PDFFilter for the encryption object
     * @param number The object number
     * @param generation The objects generation
     * @return The resulting filter
     */
    public PDFFilter makeFilter(int number, int generation) {
        return new EncryptionFilter(this, number, generation);
    }

    /**
     * Adds a PDFFilter to the PDFStream object
     * @param stream the stream to add an encryption filter to
     */
    public void applyFilter(AbstractPDFStream stream) {
        stream.getFilterList().addFilter(
                this.makeFilter(stream.getObjectNumber(), stream.getGeneration()));
    }

    /**
     * Represent the object in PDF
     *
     * @return the PDF
     */
    public byte[] toPDF() {
        if (this.dictionary == null) {
            throw new IllegalStateException("PDF Encryption has not been initialized");
        }

        return encode(this.dictionary);
    }

    /**
     * {@inheritDoc}
     */
    public String getTrailerEntry() {
        return "/Encrypt " + getObjectNumber() + " "
                    + getGeneration() + " R\n"
                    + "/ID[" + getFileID(1) + getFileID(2) + "]\n";
    }
}
