/* * Copyright (C) 2012 Armin Häberling * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> */ package com.aha.pdftools; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import com.aha.pdftools.model.PdfFile; import com.aha.pdftools.model.PdfPages; import com.aha.pdftools.model.PdfPermissions; import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.pdf.PdfCopy; import com.itextpdf.text.pdf.PdfEncryption; import com.itextpdf.text.pdf.PdfImportedPage; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfStamper; public final class PdfPermissionManager { public static final String PDF_EXTENSION = ".pdf"; //$NON-NLS-1$ public static final String PASSWORD = "changeit"; //$NON-NLS-1$ private PdfPermissionManager() { } public static int getPermissions(PdfReader reader) { int permissions; if (!reader.isEncrypted()) { permissions = 0xFFFFFFFF; } else { permissions = reader.getPermissions(); } return permissions; } private static void changePermissions(PdfReader reader, OutputStream os, PdfPermissions permissions, String password) throws DocumentException, IOException { unlockReader(reader); PdfStamper stp = new PdfStamper(reader, os, '\0'); int perms = permissions.getPermissionFlags(); stp.setEncryption(null, password.getBytes("UTF-8"), perms, PdfEncryption.STANDARD_ENCRYPTION_40); stp.close(); } public static void unlockReader(PdfReader reader) { try { Class<? extends PdfReader> readerClass = reader.getClass(); Field pwField = readerClass.getDeclaredField("ownerPasswordUsed"); //$NON-NLS-1$ pwField.setAccessible(true); pwField.set(reader, Boolean.TRUE); } catch (Exception e) { throw new RuntimeException(e); } } public static void processFile(File inputFile, File output, PdfPermissions permissions, String password) throws IOException, DocumentException { if (permissions instanceof PdfFile && ((PdfFile) permissions).isAllowAll()) { ArrayList<File> inputFiles = new ArrayList<File>(); inputFiles.add(inputFile); merge(output, inputFiles, new NullProgressDisplay()); return; } boolean createTempFile = inputFile.equals(output); File outputFile = createTempFile ? FileUtils.createTempFile(output.getAbsolutePath(), PDF_EXTENSION) : output; PdfReader reader = new PdfReader(inputFile.getAbsolutePath()); FileOutputStream fout = new FileOutputStream(outputFile); changePermissions(reader, fout, permissions, password); if (createTempFile) { FileUtils.moveFile(outputFile, output); } } public static void merge(File output, List<File> inputFiles, ProgressDisplay progress) throws IOException, DocumentException { progress.startTask(Messages.getString("PdfPermissionManager.Combine"), inputFiles.size(), true); //$NON-NLS-1$ FileOutputStream outputStream = null; PdfCopy copy = null; int pageCount = 0; try { Document document = new Document(); outputStream = new FileOutputStream(output); copy = new PdfCopy(document, outputStream); document.open(); int n = 0; for (File file : inputFiles) { if (progress.isCanceled()) { break; } progress.setNote(file.getName()); FileInputStream inputStream = null; PdfReader reader = null; try { inputStream = new FileInputStream(file); reader = new PdfReader(inputStream); unlockReader(reader); for (int i = 1; i <= reader.getNumberOfPages(); i++) { if (progress.isCanceled()) { break; } document.newPage(); pageCount++; // import the page from source pdf PdfImportedPage page = copy.getImportedPage(reader, i); copy.addPage(page); } } finally { if (reader != null) { reader.close(); } if (inputStream != null) { inputStream.close(); } progress.setProgress(++n); } } outputStream.flush(); document.close(); } finally { progress.endTask(); // check if any page was written. if (copy != null && pageCount > 0) { copy.close(); } if (outputStream != null) { outputStream.close(); } } } public static void mergePages(File output, List<PdfPages> pages, ProgressDisplay progress) throws IOException, DocumentException { int totalPageCount = 0; for (PdfPages pdfPages : pages) { totalPageCount += pdfPages.getPageCount(); } progress.startTask(Messages.getString("PdfPermissionManager.Combine"), totalPageCount, true); //$NON-NLS-1$ FileOutputStream outputStream = null; PdfCopy copy = null; int pageCount = 0; try { Document document = new Document(); outputStream = new FileOutputStream(output); copy = new PdfCopy(document, outputStream); document.open(); for (PdfPages pdfPages : pages) { if (progress.isCanceled()) { break; } progress.setNote(pdfPages.getName()); FileInputStream inputStream = null; PdfReader reader = null; try { inputStream = new FileInputStream(pdfPages.getSourceFile()); reader = new PdfReader(inputStream); unlockReader(reader); for (int pageNumber : pdfPages.getPages()) { if (progress.isCanceled()) { break; } document.newPage(); pageCount++; // import the page from source pdf PdfImportedPage page = copy.getImportedPage(reader, pageNumber); copy.addPage(page); progress.setProgress(pageCount); } } finally { if (reader != null) { reader.close(); } if (inputStream != null) { inputStream.close(); } } } outputStream.flush(); document.close(); } finally { progress.endTask(); // check if any page was written. if (copy != null && pageCount > 0) { copy.close(); } if (outputStream != null) { outputStream.close(); } } } }