001 package railo.runtime.text.pdf; 002 003 import java.io.ByteArrayInputStream; 004 import java.io.File; 005 import java.io.IOException; 006 import java.util.HashMap; 007 import java.util.HashSet; 008 import java.util.Iterator; 009 import java.util.Map; 010 import java.util.Set; 011 012 import org.pdfbox.exceptions.CryptographyException; 013 import org.pdfbox.exceptions.InvalidPasswordException; 014 import org.pdfbox.pdmodel.PDDocument; 015 016 import railo.commons.io.IOUtil; 017 import railo.commons.io.res.Resource; 018 import railo.commons.io.res.type.file.FileResource; 019 import railo.commons.lang.StringUtil; 020 import railo.runtime.PageContext; 021 import railo.runtime.dump.DumpData; 022 import railo.runtime.dump.DumpProperties; 023 import railo.runtime.dump.DumpTable; 024 import railo.runtime.exp.ApplicationException; 025 import railo.runtime.exp.PageException; 026 import railo.runtime.exp.PageRuntimeException; 027 import railo.runtime.op.Caster; 028 import railo.runtime.type.Collection; 029 import railo.runtime.type.Struct; 030 import railo.runtime.type.StructImpl; 031 import railo.runtime.type.dt.DateTime; 032 import railo.runtime.type.util.StructSupport; 033 034 import com.lowagie.text.pdf.PdfReader; 035 import com.lowagie.text.pdf.PdfWriter; 036 037 public class PDFDocument extends StructSupport implements Struct { 038 039 private byte[] barr; 040 private String password; 041 private Resource resource; 042 private Set<Integer> pages; 043 044 public PDFDocument(byte[] barr, String password) { 045 this.barr=barr; 046 this.password=password; 047 } 048 049 public PDFDocument(Resource resource, String password) { 050 this.resource=resource; 051 this.password=password; 052 } 053 054 public PDFDocument(byte[] barr, Resource resource, String password) { 055 this.resource=resource; 056 this.barr=barr; 057 this.password=password; 058 } 059 060 061 @Override 062 public void clear() { 063 getInfo().clear(); 064 } 065 066 067 @Override 068 public boolean containsKey(Key key) { 069 return getInfo().containsKey(key); 070 } 071 072 @Override 073 public Collection duplicate(boolean deepCopy) { 074 PDFDocument duplicate=new PDFDocument(barr,resource,password); 075 return duplicate; 076 } 077 078 079 @Override 080 public Object get(Key key) throws PageException { 081 return getInfo().get(key); 082 } 083 084 @Override 085 public Object get(Key key, Object defaultValue) { 086 return getInfo().get(key, defaultValue); 087 } 088 089 @Override 090 public Key[] keys() { 091 return getInfo().keys(); 092 } 093 094 @Override 095 public Object remove(Key key) throws PageException { 096 return getInfo().remove(key); 097 } 098 099 @Override 100 public Object removeEL(Key key) { 101 return getInfo().removeEL(key); 102 } 103 104 @Override 105 public Object set(Key key, Object value) throws PageException { 106 return getInfo().set(key, value); 107 } 108 109 @Override 110 public Object setEL(Key key, Object value) { 111 return getInfo().setEL(key, value); 112 } 113 114 @Override 115 public int size() { 116 return getInfo().size(); 117 } 118 119 @Override 120 public DumpData toDumpData(PageContext pageContext, int maxlevel,DumpProperties properties) { 121 122 DumpData dd = getInfo().toDumpData(pageContext, maxlevel,properties); 123 if(dd instanceof DumpTable)((DumpTable)dd).setTitle("Struct (PDFDocument)"); 124 return dd; 125 } 126 127 @Override 128 public Iterator<Collection.Key> keyIterator() { 129 return getInfo().keyIterator(); 130 } 131 132 @Override 133 public Iterator<String> keysAsStringIterator() { 134 return getInfo().keysAsStringIterator(); 135 } 136 137 @Override 138 public Iterator<Entry<Key, Object>> entryIterator() { 139 return getInfo().entryIterator(); 140 } 141 142 @Override 143 public Iterator<Object> valueIterator() { 144 return getInfo().valueIterator(); 145 } 146 147 @Override 148 public boolean castToBooleanValue() throws PageException { 149 return getInfo().castToBooleanValue(); 150 } 151 152 @Override 153 public Boolean castToBoolean(Boolean defaultValue) { 154 return getInfo().castToBoolean(defaultValue); 155 } 156 157 @Override 158 public DateTime castToDateTime() throws PageException { 159 return getInfo().castToDateTime(); 160 } 161 162 @Override 163 public DateTime castToDateTime(DateTime defaultValue) { 164 return getInfo().castToDateTime(defaultValue); 165 } 166 167 @Override 168 public double castToDoubleValue() throws PageException { 169 return getInfo().castToDoubleValue(); 170 } 171 172 @Override 173 public double castToDoubleValue(double defaultValue) { 174 return getInfo().castToDoubleValue(defaultValue); 175 } 176 177 @Override 178 public String castToString() throws PageException { 179 return getInfo().castToString(); 180 } 181 @Override 182 public String castToString(String defaultValue) { 183 return getInfo().castToString(defaultValue); 184 } 185 186 @Override 187 public int compareTo(String str) throws PageException { 188 return getInfo().compareTo(str); 189 } 190 191 @Override 192 public int compareTo(boolean b) throws PageException { 193 return getInfo().compareTo(b); 194 } 195 196 @Override 197 public int compareTo(double d) throws PageException { 198 return getInfo().compareTo(d); 199 } 200 201 @Override 202 public int compareTo(DateTime dt) throws PageException { 203 return getInfo().compareTo(dt); 204 } 205 /////////////////////////////////////////////// 206 207 public PdfReader getPdfReader() throws ApplicationException { 208 try { 209 if(barr!=null) { 210 if(password!=null)return new PdfReader(barr,password.getBytes()); 211 return new PdfReader(barr); 212 } 213 if(password!=null)return new PdfReader(IOUtil.toBytes(resource),password.getBytes()); 214 return new PdfReader(IOUtil.toBytes(resource)); 215 } 216 catch(IOException ioe) { 217 throw new ApplicationException("can not load file ["+resource+"]",ioe.getMessage()); 218 } 219 } 220 221 private String getFilePath() { 222 if(resource==null) return ""; 223 return resource.getAbsolutePath(); 224 } 225 226 public Struct getInfo() { 227 228 PdfReader pr=null; 229 try { 230 pr=getPdfReader(); 231 //PdfDictionary catalog = pr.getCatalog(); 232 int permissions = pr.getPermissions(); 233 boolean encrypted=pr.isEncrypted(); 234 235 Struct info=new StructImpl(); 236 info.setEL("FilePath", getFilePath()); 237 238 // access 239 info.setEL("ChangingDocument", allowed(encrypted,permissions,PdfWriter.ALLOW_MODIFY_CONTENTS)); 240 info.setEL("Commenting", allowed(encrypted,permissions,PdfWriter.ALLOW_MODIFY_ANNOTATIONS)); 241 info.setEL("ContentExtraction", allowed(encrypted,permissions,PdfWriter.ALLOW_SCREENREADERS)); 242 info.setEL("CopyContent", allowed(encrypted,permissions,PdfWriter.ALLOW_COPY)); 243 info.setEL("DocumentAssembly", allowed(encrypted,permissions,PdfWriter.ALLOW_ASSEMBLY+PdfWriter.ALLOW_MODIFY_CONTENTS)); 244 info.setEL("FillingForm", allowed(encrypted,permissions,PdfWriter.ALLOW_FILL_IN+PdfWriter.ALLOW_MODIFY_ANNOTATIONS)); 245 info.setEL("Printing", allowed(encrypted,permissions,PdfWriter.ALLOW_PRINTING)); 246 info.setEL("Secure", ""); 247 info.setEL("Signing", allowed(encrypted,permissions,PdfWriter.ALLOW_MODIFY_ANNOTATIONS+PdfWriter.ALLOW_MODIFY_CONTENTS+PdfWriter.ALLOW_FILL_IN)); 248 249 info.setEL("Encryption", encrypted?"Password Security":"No Security");// MUST 250 info.setEL("TotalPages", Caster.toDouble(pr.getNumberOfPages())); 251 info.setEL("Version", "1."+pr.getPdfVersion()); 252 info.setEL("permissions", ""+permissions); 253 info.setEL("permiss", ""+PdfWriter.ALLOW_FILL_IN); 254 255 info.setEL("Application", ""); 256 info.setEL("Author", ""); 257 info.setEL("CenterWindowOnScreen", ""); 258 info.setEL("Created", ""); 259 info.setEL("FitToWindow", ""); 260 info.setEL("HideMenubar", ""); 261 info.setEL("HideToolbar", ""); 262 info.setEL("HideWindowUI", ""); 263 info.setEL("Keywords", ""); 264 info.setEL("Language", ""); 265 info.setEL("Modified", ""); 266 info.setEL("PageLayout", ""); 267 info.setEL("Producer", ""); 268 info.setEL("Properties", ""); 269 info.setEL("ShowDocumentsOption", ""); 270 info.setEL("ShowWindowsOption", ""); 271 info.setEL("Subject", ""); 272 info.setEL("Title", ""); 273 info.setEL("Trapped", ""); 274 275 // info 276 HashMap imap = pr.getInfo(); 277 Iterator it = imap.entrySet().iterator(); 278 Map.Entry entry; 279 while(it.hasNext()) { 280 entry=(Entry) it.next(); 281 info.setEL(Caster.toString(entry.getKey(),null), entry.getValue()); 282 } 283 return info; 284 } 285 catch(PageException pe) { 286 throw new PageRuntimeException(pe); 287 } 288 finally { 289 if(pr!=null)pr.close(); 290 } 291 } 292 293 294 295 296 private static Object allowed(boolean encrypted, int permissions, int permission) { 297 return (!encrypted || (permissions&permission)>0)?"Allowed":"Not Allowed"; 298 } 299 300 301 302 public void setPages(String strPages) throws PageException { 303 if(StringUtil.isEmpty(strPages))return; 304 if(pages==null) 305 pages=new HashSet<Integer>(); 306 PDFUtil.parsePageDefinition(pages,strPages); 307 } 308 309 public Set<Integer> getPages() { 310 //if(pages==null)pages=new HashSet(); 311 return pages; 312 } 313 314 public Resource getResource() { 315 return resource; 316 } 317 public byte[] getRaw() throws IOException { 318 if(barr!=null)return barr; 319 return IOUtil.toBytes(resource); 320 } 321 322 @Override 323 public boolean containsValue(Object value) { 324 return getInfo().containsValue(value); 325 } 326 327 @Override 328 public java.util.Collection values() { 329 return getInfo().values(); 330 } 331 332 public PDDocument toPDDocument() throws CryptographyException, InvalidPasswordException, IOException { 333 PDDocument doc; 334 if(barr!=null) 335 doc= PDDocument.load(new ByteArrayInputStream(barr,0,barr.length)); 336 else if(resource instanceof FileResource) 337 doc= PDDocument.load((File)resource); 338 else 339 doc= PDDocument.load(new ByteArrayInputStream(IOUtil.toBytes(resource),0,barr.length)); 340 341 if(password!=null)doc.decrypt(password); 342 343 344 return doc; 345 346 } 347 348 }