package railo.runtime.text.pdf;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.pdfbox.exceptions.CryptographyException;
import org.pdfbox.exceptions.InvalidPasswordException;
import org.pdfbox.pdmodel.PDDocument;
import railo.commons.io.IOUtil;
import railo.commons.io.res.Resource;
import railo.commons.io.res.type.file.FileResource;
import railo.commons.lang.StringUtil;
import railo.runtime.PageContext;
import railo.runtime.dump.DumpData;
import railo.runtime.dump.DumpProperties;
import railo.runtime.dump.DumpTable;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.PageException;
import railo.runtime.exp.PageRuntimeException;
import railo.runtime.op.Caster;
import railo.runtime.type.Collection;
import railo.runtime.type.Struct;
import railo.runtime.type.StructImpl;
import railo.runtime.type.dt.DateTime;
import railo.runtime.type.util.StructSupport;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfWriter;
public class PDFDocument extends StructSupport implements Struct {
private byte[] barr;
private String password;
private Resource resource;
private Set<Integer> pages;
public PDFDocument(byte[] barr, String password) {
this.barr=barr;
this.password=password;
}
public PDFDocument(Resource resource, String password) {
this.resource=resource;
this.password=password;
}
public PDFDocument(byte[] barr, Resource resource, String password) {
this.resource=resource;
this.barr=barr;
this.password=password;
}
@Override
public void clear() {
getInfo().clear();
}
@Override
public boolean containsKey(Key key) {
return getInfo().containsKey(key);
}
@Override
public Collection duplicate(boolean deepCopy) {
PDFDocument duplicate=new PDFDocument(barr,resource,password);
return duplicate;
}
@Override
public Object get(Key key) throws PageException {
return getInfo().get(key);
}
@Override
public Object get(Key key, Object defaultValue) {
return getInfo().get(key, defaultValue);
}
@Override
public Key[] keys() {
return getInfo().keys();
}
@Override
public Object remove(Key key) throws PageException {
return getInfo().remove(key);
}
@Override
public Object removeEL(Key key) {
return getInfo().removeEL(key);
}
@Override
public Object set(Key key, Object value) throws PageException {
return getInfo().set(key, value);
}
@Override
public Object setEL(Key key, Object value) {
return getInfo().setEL(key, value);
}
@Override
public int size() {
return getInfo().size();
}
@Override
public DumpData toDumpData(PageContext pageContext, int maxlevel,DumpProperties properties) {
DumpData dd = getInfo().toDumpData(pageContext, maxlevel,properties);
if(dd instanceof DumpTable)((DumpTable)dd).setTitle("Struct (PDFDocument)");
return dd;
}
@Override
public Iterator<Collection.Key> keyIterator() {
return getInfo().keyIterator();
}
@Override
public Iterator<String> keysAsStringIterator() {
return getInfo().keysAsStringIterator();
}
@Override
public Iterator<Entry<Key, Object>> entryIterator() {
return getInfo().entryIterator();
}
@Override
public Iterator<Object> valueIterator() {
return getInfo().valueIterator();
}
@Override
public boolean castToBooleanValue() throws PageException {
return getInfo().castToBooleanValue();
}
@Override
public Boolean castToBoolean(Boolean defaultValue) {
return getInfo().castToBoolean(defaultValue);
}
@Override
public DateTime castToDateTime() throws PageException {
return getInfo().castToDateTime();
}
@Override
public DateTime castToDateTime(DateTime defaultValue) {
return getInfo().castToDateTime(defaultValue);
}
@Override
public double castToDoubleValue() throws PageException {
return getInfo().castToDoubleValue();
}
@Override
public double castToDoubleValue(double defaultValue) {
return getInfo().castToDoubleValue(defaultValue);
}
@Override
public String castToString() throws PageException {
return getInfo().castToString();
}
@Override
public String castToString(String defaultValue) {
return getInfo().castToString(defaultValue);
}
@Override
public int compareTo(String str) throws PageException {
return getInfo().compareTo(str);
}
@Override
public int compareTo(boolean b) throws PageException {
return getInfo().compareTo(b);
}
@Override
public int compareTo(double d) throws PageException {
return getInfo().compareTo(d);
}
@Override
public int compareTo(DateTime dt) throws PageException {
return getInfo().compareTo(dt);
}
///////////////////////////////////////////////
public PdfReader getPdfReader() throws ApplicationException {
try {
if(barr!=null) {
if(password!=null)return new PdfReader(barr,password.getBytes());
return new PdfReader(barr);
}
if(password!=null)return new PdfReader(IOUtil.toBytes(resource),password.getBytes());
return new PdfReader(IOUtil.toBytes(resource));
}
catch(IOException ioe) {
throw new ApplicationException("can not load file ["+resource+"]",ioe.getMessage());
}
}
private String getFilePath() {
if(resource==null) return "";
return resource.getAbsolutePath();
}
public Struct getInfo() {
PdfReader pr=null;
try {
pr=getPdfReader();
//PdfDictionary catalog = pr.getCatalog();
int permissions = pr.getPermissions();
boolean encrypted=pr.isEncrypted();
Struct info=new StructImpl();
info.setEL("FilePath", getFilePath());
// access
info.setEL("ChangingDocument", allowed(encrypted,permissions,PdfWriter.ALLOW_MODIFY_CONTENTS));
info.setEL("Commenting", allowed(encrypted,permissions,PdfWriter.ALLOW_MODIFY_ANNOTATIONS));
info.setEL("ContentExtraction", allowed(encrypted,permissions,PdfWriter.ALLOW_SCREENREADERS));
info.setEL("CopyContent", allowed(encrypted,permissions,PdfWriter.ALLOW_COPY));
info.setEL("DocumentAssembly", allowed(encrypted,permissions,PdfWriter.ALLOW_ASSEMBLY+PdfWriter.ALLOW_MODIFY_CONTENTS));
info.setEL("FillingForm", allowed(encrypted,permissions,PdfWriter.ALLOW_FILL_IN+PdfWriter.ALLOW_MODIFY_ANNOTATIONS));
info.setEL("Printing", allowed(encrypted,permissions,PdfWriter.ALLOW_PRINTING));
info.setEL("Secure", "");
info.setEL("Signing", allowed(encrypted,permissions,PdfWriter.ALLOW_MODIFY_ANNOTATIONS+PdfWriter.ALLOW_MODIFY_CONTENTS+PdfWriter.ALLOW_FILL_IN));
info.setEL("Encryption", encrypted?"Password Security":"No Security");// MUST
info.setEL("TotalPages", Caster.toDouble(pr.getNumberOfPages()));
info.setEL("Version", "1."+pr.getPdfVersion());
info.setEL("permissions", ""+permissions);
info.setEL("permiss", ""+PdfWriter.ALLOW_FILL_IN);
info.setEL("Application", "");
info.setEL("Author", "");
info.setEL("CenterWindowOnScreen", "");
info.setEL("Created", "");
info.setEL("FitToWindow", "");
info.setEL("HideMenubar", "");
info.setEL("HideToolbar", "");
info.setEL("HideWindowUI", "");
info.setEL("Keywords", "");
info.setEL("Language", "");
info.setEL("Modified", "");
info.setEL("PageLayout", "");
info.setEL("Producer", "");
info.setEL("Properties", "");
info.setEL("ShowDocumentsOption", "");
info.setEL("ShowWindowsOption", "");
info.setEL("Subject", "");
info.setEL("Title", "");
info.setEL("Trapped", "");
// info
HashMap imap = pr.getInfo();
Iterator it = imap.entrySet().iterator();
Map.Entry entry;
while(it.hasNext()) {
entry=(Entry) it.next();
info.setEL(Caster.toString(entry.getKey(),null), entry.getValue());
}
return info;
}
catch(PageException pe) {
throw new PageRuntimeException(pe);
}
finally {
if(pr!=null)pr.close();
}
}
private static Object allowed(boolean encrypted, int permissions, int permission) {
return (!encrypted || (permissions&permission)>0)?"Allowed":"Not Allowed";
}
public void setPages(String strPages) throws PageException {
if(StringUtil.isEmpty(strPages))return;
if(pages==null)
pages=new HashSet<Integer>();
PDFUtil.parsePageDefinition(pages,strPages);
}
public Set<Integer> getPages() {
//if(pages==null)pages=new HashSet();
return pages;
}
public Resource getResource() {
return resource;
}
public byte[] getRaw() throws IOException {
if(barr!=null)return barr;
return IOUtil.toBytes(resource);
}
@Override
public boolean containsValue(Object value) {
return getInfo().containsValue(value);
}
@Override
public java.util.Collection values() {
return getInfo().values();
}
public PDDocument toPDDocument() throws CryptographyException, InvalidPasswordException, IOException {
PDDocument doc;
if(barr!=null)
doc= PDDocument.load(new ByteArrayInputStream(barr,0,barr.length));
else if(resource instanceof FileResource)
doc= PDDocument.load((File)resource);
else
doc= PDDocument.load(new ByteArrayInputStream(IOUtil.toBytes(resource),0,barr.length));
if(password!=null)doc.decrypt(password);
return doc;
}
}