001/*
002 * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Thibaud Arguillere
018 *     Miguel Nixo
019 */
020package org.nuxeo.ecm.platform.pdf.operations;
021
022import org.apache.commons.lang.StringUtils;
023import org.nuxeo.ecm.automation.core.Constants;
024import org.nuxeo.ecm.automation.core.annotations.Operation;
025import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
026import org.nuxeo.ecm.automation.core.annotations.Param;
027import org.nuxeo.ecm.automation.core.util.BlobList;
028import org.nuxeo.ecm.core.api.Blob;
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.core.api.DocumentModelList;
031import org.nuxeo.ecm.platform.pdf.PDFEncryption;
032
033import java.util.stream.Collectors;
034
035/**
036 * Encrypts the PDF to "readonly" for users. Read only means they can read, copy, and print. They can't assemble,
037 * modify, modify annotations, ...
038 *
039 * @since 8.10
040 */
041@Operation(id = PDFEncryptReadOnlyOperation.ID, category = Constants.CAT_CONVERSION, label = "PDF: Encrypt Read Only",
042    description = "Encrypts the PDF, returning a copy. User can read, print and copy but cannot modify. " +
043        "originalOwnerPwd is used if the PDF was originally encrypted. If ownerPwd is empty, use originalOwnerPwd to " +
044        "encrypt. If no keyLength is provided, use 128. If the operation is ran on Document(s), xpath lets you " +
045        "specificy where to get the blob from (default: file:content).")
046public class PDFEncryptReadOnlyOperation {
047
048    public static final String ID = "PDF.EncryptReadOnly";
049
050    @Param(name = "originalOwnerPwd", required = false)
051    protected String originalOwnerPwd;
052
053    @Param(name = "ownerPwd", required = false)
054    protected String ownerPwd;
055
056    @Param(name = "userPwd", required = false)
057    protected String userPwd;
058
059    @Param(name = "keyLength", required = false, widget = Constants.W_OPTION, values = { "40", "128" })
060    protected String keyLength = "128";
061
062    @Param(name = "xpath", required = false, values = { "file:content" })
063    protected String xpath = "file:content";
064
065    @OperationMethod
066    public Blob run(Blob inBlob) {
067        PDFEncryption pdfe = new PDFEncryption(inBlob);
068        pdfe.setKeyLength(Integer.parseInt(keyLength));
069        pdfe.setOriginalOwnerPwd(originalOwnerPwd);
070        pdfe.setOwnerPwd(ownerPwd);
071        pdfe.setUserPwd(userPwd);
072        Blob result = pdfe.encryptReadOnly();
073        return result;
074    }
075
076    @OperationMethod
077    public BlobList run(BlobList inBlobs) {
078        return inBlobs.stream().map(this::run).collect(Collectors.toCollection(BlobList::new));
079    }
080
081    @OperationMethod
082    public Blob run(DocumentModel inDoc) {
083        if (StringUtils.isBlank(xpath)) {
084            xpath = "file:content";
085        }
086        Blob result = null;
087        Blob content;
088        content = (Blob) inDoc.getPropertyValue(xpath);
089        if (content != null) {
090            result = this.run(content);
091        }
092        return result;
093    }
094
095    @OperationMethod
096    public BlobList run(DocumentModelList inDocs) {
097        if (StringUtils.isBlank(xpath)) {
098            xpath = "file:content";
099        }
100        return inDocs.stream().map(this::run).collect(Collectors.toCollection(BlobList::new));
101    }
102
103}