origami 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. data/COPYING.LESSER +165 -0
  2. data/README +77 -0
  3. data/VERSION +1 -0
  4. data/bin/config/pdfcop.conf.yml +237 -0
  5. data/bin/gui/about.rb +46 -0
  6. data/bin/gui/config.rb +132 -0
  7. data/bin/gui/file.rb +385 -0
  8. data/bin/gui/hexdump.rb +74 -0
  9. data/bin/gui/hexview.rb +91 -0
  10. data/bin/gui/imgview.rb +72 -0
  11. data/bin/gui/menu.rb +392 -0
  12. data/bin/gui/properties.rb +132 -0
  13. data/bin/gui/signing.rb +635 -0
  14. data/bin/gui/textview.rb +107 -0
  15. data/bin/gui/treeview.rb +409 -0
  16. data/bin/gui/walker.rb +282 -0
  17. data/bin/gui/xrefs.rb +79 -0
  18. data/bin/pdf2graph +121 -0
  19. data/bin/pdf2ruby +353 -0
  20. data/bin/pdfcocoon +104 -0
  21. data/bin/pdfcop +455 -0
  22. data/bin/pdfdecompress +104 -0
  23. data/bin/pdfdecrypt +95 -0
  24. data/bin/pdfencrypt +112 -0
  25. data/bin/pdfextract +221 -0
  26. data/bin/pdfmetadata +123 -0
  27. data/bin/pdfsh +13 -0
  28. data/bin/pdfwalker +7 -0
  29. data/bin/shell/.irbrc +104 -0
  30. data/bin/shell/console.rb +136 -0
  31. data/bin/shell/hexdump.rb +83 -0
  32. data/origami.rb +36 -0
  33. data/origami/3d.rb +239 -0
  34. data/origami/acroform.rb +321 -0
  35. data/origami/actions.rb +299 -0
  36. data/origami/adobe/fdf.rb +259 -0
  37. data/origami/adobe/ppklite.rb +489 -0
  38. data/origami/annotations.rb +775 -0
  39. data/origami/array.rb +187 -0
  40. data/origami/boolean.rb +101 -0
  41. data/origami/catalog.rb +486 -0
  42. data/origami/destinations.rb +213 -0
  43. data/origami/dictionary.rb +188 -0
  44. data/origami/docmdp.rb +96 -0
  45. data/origami/encryption.rb +1293 -0
  46. data/origami/export.rb +283 -0
  47. data/origami/file.rb +222 -0
  48. data/origami/filters.rb +250 -0
  49. data/origami/filters/ascii.rb +189 -0
  50. data/origami/filters/ccitt.rb +515 -0
  51. data/origami/filters/crypt.rb +47 -0
  52. data/origami/filters/dct.rb +61 -0
  53. data/origami/filters/flate.rb +112 -0
  54. data/origami/filters/jbig2.rb +63 -0
  55. data/origami/filters/jpx.rb +53 -0
  56. data/origami/filters/lzw.rb +195 -0
  57. data/origami/filters/predictors.rb +276 -0
  58. data/origami/filters/runlength.rb +117 -0
  59. data/origami/font.rb +209 -0
  60. data/origami/functions.rb +93 -0
  61. data/origami/graphics.rb +33 -0
  62. data/origami/graphics/colors.rb +191 -0
  63. data/origami/graphics/instruction.rb +126 -0
  64. data/origami/graphics/path.rb +154 -0
  65. data/origami/graphics/patterns.rb +180 -0
  66. data/origami/graphics/state.rb +164 -0
  67. data/origami/graphics/text.rb +224 -0
  68. data/origami/graphics/xobject.rb +493 -0
  69. data/origami/header.rb +90 -0
  70. data/origami/linearization.rb +318 -0
  71. data/origami/metadata.rb +114 -0
  72. data/origami/name.rb +170 -0
  73. data/origami/null.rb +75 -0
  74. data/origami/numeric.rb +188 -0
  75. data/origami/obfuscation.rb +233 -0
  76. data/origami/object.rb +527 -0
  77. data/origami/outline.rb +59 -0
  78. data/origami/page.rb +559 -0
  79. data/origami/parser.rb +268 -0
  80. data/origami/parsers/fdf.rb +45 -0
  81. data/origami/parsers/pdf.rb +27 -0
  82. data/origami/parsers/pdf/linear.rb +113 -0
  83. data/origami/parsers/ppklite.rb +86 -0
  84. data/origami/pdf.rb +1144 -0
  85. data/origami/reference.rb +113 -0
  86. data/origami/signature.rb +474 -0
  87. data/origami/stream.rb +575 -0
  88. data/origami/string.rb +416 -0
  89. data/origami/trailer.rb +173 -0
  90. data/origami/webcapture.rb +87 -0
  91. data/origami/xfa.rb +3027 -0
  92. data/origami/xreftable.rb +447 -0
  93. data/templates/patterns.rb +66 -0
  94. data/templates/widgets.rb +173 -0
  95. data/templates/xdp.rb +92 -0
  96. data/tests/dataset/test.dummycrt +28 -0
  97. data/tests/dataset/test.dummykey +27 -0
  98. data/tests/tc_actions.rb +32 -0
  99. data/tests/tc_annotations.rb +85 -0
  100. data/tests/tc_pages.rb +37 -0
  101. data/tests/tc_pdfattach.rb +24 -0
  102. data/tests/tc_pdfencrypt.rb +110 -0
  103. data/tests/tc_pdfnew.rb +32 -0
  104. data/tests/tc_pdfparse.rb +98 -0
  105. data/tests/tc_pdfsig.rb +37 -0
  106. data/tests/tc_streams.rb +129 -0
  107. data/tests/ts_pdf.rb +45 -0
  108. metadata +193 -0
@@ -0,0 +1,299 @@
1
+ =begin
2
+
3
+ = File
4
+ actions.rb
5
+
6
+ = Info
7
+ This file is part of Origami, PDF manipulation framework for Ruby
8
+ Copyright (C) 2010 Guillaume Delugr� <guillaume@security-labs.org>
9
+ All right reserved.
10
+
11
+ Origami is free software: you can redistribute it and/or modify
12
+ it under the terms of the GNU Lesser General Public License as published by
13
+ the Free Software Foundation, either version 3 of the License, or
14
+ (at your option) any later version.
15
+
16
+ Origami is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU Lesser General Public License for more details.
20
+
21
+ You should have received a copy of the GNU Lesser General Public License
22
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
23
+
24
+ =end
25
+
26
+ module Origami
27
+
28
+ class PDF
29
+
30
+ #
31
+ # Lookup script in the scripts name directory.
32
+ #
33
+ def get_script_by_name(name)
34
+ resolve_name Names::Root::JAVASCRIPT, name
35
+ end
36
+
37
+ #
38
+ # Calls block for each named JavaScript script.
39
+ #
40
+ def each_named_script(&b)
41
+ each_name(Names::Root::JAVASCRIPT, &b)
42
+ end
43
+ end
44
+
45
+ #
46
+ # Class representing an action to launch in a PDF.
47
+ #
48
+ class Action < Dictionary
49
+
50
+ include StandardObject
51
+
52
+ field :Type, :Type => Name, :Default => :Action
53
+ field :S, :Type => Name, :Required => true
54
+ field :Next, :Type => [ Array, Dictionary ], :Version => "1.2"
55
+
56
+ #
57
+ # Class representing a action going to a destination in the current document.
58
+ #
59
+ class GoTo < Action
60
+
61
+ field :S, :Type => Name, :Default => :GoTo, :Required => true
62
+ field :D, :Type => [ Array, Name, ByteString ], :Required => true
63
+
64
+ #
65
+ # Creates a new GoTo Action.
66
+ # _hash_:: A hash of options to set for this jump.
67
+ #
68
+ def initialize(hash = {})
69
+
70
+ if hash.is_a? Destination
71
+ super(:S => :GoTo, :D => hash)
72
+ else
73
+ super(hash)
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+
80
+ #
81
+ # Class representing an action launching an URL.
82
+ #
83
+ class URI < Action
84
+
85
+ field :S, :Type => Name, :Default => :URI, :Required => true
86
+ field :URI, :Type => ByteString, :Required => true
87
+ field :IsMap, :Type => Boolean, :Default => false
88
+
89
+ #
90
+ # Creates a new URI Action.
91
+ # _uri_:: The URI to launch.
92
+ # _ismap_::
93
+ #
94
+ def initialize(uri, ismap = false)
95
+ super(:URI => uri, :IsMap => ismap)
96
+ end
97
+
98
+ end
99
+
100
+ #
101
+ # Class representing a JavaScript Action.
102
+ #
103
+ class JavaScript < Action
104
+
105
+ field :S, :Type => Name, :Default => :JavaScript, :Required => true
106
+ field :JS, :Type => [ Stream, String ], :Required => true
107
+
108
+ #
109
+ # Creates a new JavaScript Action.
110
+ # _script_:: The script to be executed.
111
+ #
112
+ def initialize(script)
113
+ super(:JS => script)
114
+ end
115
+
116
+ end
117
+
118
+ #
119
+ # Class representing an Action which run a command on the current system.
120
+ #
121
+ class Launch < Action
122
+
123
+ field :S, :Type => Name, :Default => :Launch, :Required => true
124
+ field :F, :Type => [ ByteString, Dictionary ]
125
+ field :Win, :Type => Dictionary
126
+ field :Mac, :Type => Object
127
+ field :Unix, :Type => Object
128
+ field :NewWindow, :Type => Boolean
129
+
130
+ #
131
+ # Dictionary for passing parameter to Windows applications during Launch.
132
+ #
133
+ class WindowsLaunchParams < Dictionary
134
+
135
+ include StandardObject
136
+
137
+ field :F, :Type => ByteString, :Required => true
138
+ field :D, :Type => ByteString
139
+ field :O, :Type => ByteString, :Default => "open"
140
+ field :P, :Type => ByteString
141
+
142
+ end
143
+ end
144
+
145
+ #
146
+ # Class representing a Named Action.
147
+ # Named actions are predefined GoTo actions.
148
+ #
149
+ class Named < Action
150
+
151
+ NEXTPAGE = :NextPage
152
+ PREVPAGE = :PrevPage
153
+ FIRSTPAGE = :FirstPage
154
+ LASTPAGE = :LastPage
155
+ PRINT = :Print
156
+
157
+ field :S, :Type => Name, :Default => :Named, :Required => true
158
+ field :N, :Type => Name, :Required => true
159
+
160
+ def initialize(type)
161
+ super(:N => type)
162
+ end
163
+
164
+ end
165
+
166
+ #
167
+ # Class representing a GoTo Action to an external file.
168
+ #
169
+ class GoToR < Action
170
+
171
+ field :S, :Type => Name, :Default => :GoToR, :Required => true
172
+ field :F, :Type => [ ByteString, Dictionary ], :Required => true
173
+ field :D, :Type => [ Array, Name, ByteString ], :Required => true
174
+ field :NewWindow, :Type => Boolean, :Version => "1.2"
175
+
176
+ #
177
+ # Creates a new GoTo remote Action.
178
+ # _file_:: A FileSpec describing the file.
179
+ # _dest_:: A Destination in the file.
180
+ # _newwindow_:: Specifies whether the file has to be opened in a new window.
181
+ #
182
+ def initialize(file, dest = Destination::GlobalFit.new(0), newwindow = false)
183
+ super(:F => file, :D => dest, :NewWindow => newwindow)
184
+ end
185
+
186
+ end
187
+
188
+ #
189
+ # Class representing a GoTo Action to an embedded pdf file.
190
+ #
191
+ class GoToE < Action
192
+
193
+ field :S, :Type => Name, :Default => :GoToE, :Required => true
194
+ field :F, :Type => [ Dictionary, ByteString ]
195
+ field :D, :Type => [ Array, Name, ByteString ], :Required => true
196
+ field :NewWindow, :Type => Boolean
197
+ field :T, :Type => Dictionary
198
+
199
+ #
200
+ # A class representing a target for a GoToE to an embedded file.
201
+ #
202
+ class EmbeddedTarget < Dictionary
203
+
204
+ include StandardObject
205
+
206
+ module Relationship
207
+ PARENT = :P
208
+ CHILD = :C
209
+ end
210
+
211
+ field :R, :Type => Name, :Required => true
212
+ field :N, :Type => ByteString
213
+ field :P, :Type => [ Integer, ByteString ]
214
+ field :A, :Type => [ Integer, ByteString ]
215
+ field :T, :Type => Dictionary
216
+
217
+ end
218
+
219
+ def initialize(filename, dest, newwindow = false)
220
+ super(:T => EmbeddedTarget.new(:R => :C, :N => filename), :D => dest, :NewWindow => newwindow)
221
+ end
222
+
223
+ end
224
+
225
+ #
226
+ # (PDF 1.2) Send data to a uniform resource locator. p703
227
+ #
228
+ class SubmitForm < Action
229
+
230
+ module Flags
231
+ INCLUDEEXCLUDE = 1 << 0
232
+ INCLUDENOVALUEFIELDS = 1 << 1
233
+ EXPORTFORMAT = 1 << 2
234
+ GETMETHOD = 1 << 3
235
+ SUBMITCOORDINATES = 1 << 4
236
+ XFDF = 1 << 5
237
+ INCLUDEAPPENDSAVES = 1 << 6
238
+ INCLUDEANNOTATIONS = 1 << 7
239
+ SUBMITPDF = 1 << 8
240
+ CANONICALFORMAT = 1 << 9
241
+ EXCLNONUSERANNOTS = 1 << 10
242
+ EXCLFKEY = 1 << 11
243
+ EMBEDFORM = 1 << 12
244
+ end
245
+
246
+ field :S, :Type => Name, :Default => :SubmitForm, :Required => true
247
+ field :F, :Type => Dictionary
248
+ field :Fields, :Type => Array
249
+ field :Flags, :Type => Integer, :Default => 0
250
+
251
+ def initialize(url, fields = [], flags = 0)
252
+ if not url.is_a? FileSpec
253
+ url = FileSpec.new(:FS => :URL, :F => url)
254
+ end
255
+
256
+ super(:F => url, :Fields => fields, :Flags => flags)
257
+ end
258
+
259
+ end
260
+
261
+ class ImportData < Action
262
+
263
+ field :S, :Type => Name, :Default => :ImportData, :Required => true
264
+ field :F, :Type => Dictionary, :Required => true
265
+
266
+ def initialize(file)
267
+ if not file.is_a? FileSpec
268
+ file = FileSpec.new(:FS => :File, :F => file)
269
+ end
270
+
271
+ super(:F => file)
272
+ end
273
+
274
+ end
275
+
276
+ class RichMediaExecute < Action
277
+
278
+ field :S, :Type => Name, :Default => :RichMediaExecute, :Version => "1.7", :ExtensionLevel => 3, :Required => true
279
+ field :TA, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3, :Required => true
280
+ field :TI, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3
281
+ field :CMD, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3, :Required => true
282
+
283
+ class Command < Dictionary
284
+ include StandardObject
285
+
286
+ field :Type, :Type => Name, :Default => :RichMediaCommand, :Version => "1.7", :ExtensionLevel => 3
287
+ field :C, :Type => String, :Version => "1.7", :ExtensionLevel => 3, :Required => true
288
+ field :A, :Type => Object, :Version => "1.7", :ExtensionLevel => 3
289
+ end
290
+
291
+ def initialize(annotation, command, *params)
292
+ super(:TA => annotation, :CMD => Command.new(:C => command, :A => params))
293
+ end
294
+
295
+ end
296
+
297
+ end
298
+
299
+ end
@@ -0,0 +1,259 @@
1
+ =begin
2
+
3
+ = File
4
+ adobe/fdf.rb
5
+
6
+ = Info
7
+ This file is part of Origami, PDF manipulation framework for Ruby
8
+ Copyright (C) 2010 Guillaume Delugr� <guillaume@security-labs.org>
9
+ All right reserved.
10
+
11
+ Origami is free software: you can redistribute it and/or modify
12
+ it under the terms of the GNU Lesser General Public License as published by
13
+ the Free Software Foundation, either version 3 of the License, or
14
+ (at your option) any later version.
15
+
16
+ Origami is distributed in the hope that it will be useful,
17
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ GNU Lesser General Public License for more details.
20
+
21
+ You should have received a copy of the GNU Lesser General Public License
22
+ along with Origami. If not, see <http://www.gnu.org/licenses/>.
23
+
24
+ =end
25
+
26
+ require 'origami/object'
27
+ require 'origami/name'
28
+ require 'origami/dictionary'
29
+ require 'origami/reference'
30
+ require 'origami/boolean'
31
+ require 'origami/numeric'
32
+ require 'origami/string'
33
+ require 'origami/array'
34
+ require 'origami/trailer'
35
+ require 'origami/xreftable'
36
+
37
+ module Origami
38
+
39
+ module Adobe
40
+
41
+ #
42
+ # Class representing an AcroForm Forms Data Format file.
43
+ #
44
+ class FDF
45
+
46
+ class Header
47
+
48
+ MAGIC = /\A%FDF-(\d)\.(\d)/
49
+
50
+ attr_accessor :majorversion, :minorversion
51
+
52
+ #
53
+ # Creates a file header, with the given major and minor versions.
54
+ # _majorversion_:: Major version.
55
+ # _minorversion_:: Minor version.
56
+ #
57
+ def initialize(majorversion = 2, minorversion = 1)
58
+ @majorversion, @minorversion = majorversion, minorversion
59
+ end
60
+
61
+ def self.parse(stream) #:nodoc:
62
+
63
+ if not stream.scan(MAGIC).nil?
64
+ maj = stream[1].to_i
65
+ min = stream[2].to_i
66
+ else
67
+ raise InvalidHeader, "Invalid header format"
68
+ end
69
+
70
+ PPKLite::Header.new(maj,min)
71
+ end
72
+
73
+ def to_s
74
+ "%FDF-#{@majorversion}.#{@minorversion}" + EOL
75
+ end
76
+
77
+ def to_sym #:nodoc:
78
+ "#{@majorversion}.#{@minorversion}".to_sym
79
+ end
80
+
81
+ def to_f #:nodoc:
82
+ to_sym.to_s.to_f
83
+ end
84
+
85
+ end
86
+
87
+ class Revision #:nodoc;
88
+ attr_accessor :pdf
89
+ attr_accessor :body, :xreftable, :trailer
90
+
91
+ def initialize(adbk)
92
+ @pdf = adbk
93
+ @body = {}
94
+ @xreftable = nil
95
+ @trailer = nil
96
+ end
97
+
98
+ def trailer=(trl)
99
+ trl.pdf = @pdf
100
+ @trailer = trl
101
+ end
102
+ end
103
+
104
+ attr_accessor :header, :revisions
105
+
106
+ def initialize #:nodoc:
107
+ @header = FDF::Header.new
108
+ @revisions = [ Revision.new(self) ]
109
+ @revisions.first.trailer = Trailer.new
110
+ end
111
+
112
+ def objects
113
+ def append_subobj(root, objset)
114
+ if objset.find{ |o| o.object_id == root.object_id }.nil?
115
+ objset << root
116
+ if root.is_a?(Array) or root.is_a?(Dictionary)
117
+ root.each { |subobj| append_subobj(subobj, objset) unless subobj.is_a?(Reference) }
118
+ end
119
+ end
120
+ end
121
+
122
+ objset = []
123
+ @revisions.first.body.values.each do |object|
124
+ unless object.is_a?(Reference)
125
+ append_subobj(object, objset)
126
+ end
127
+ end
128
+
129
+ objset
130
+ end
131
+
132
+ def <<(object)
133
+
134
+ object.set_indirect(true)
135
+
136
+ if object.no.zero?
137
+ maxno = 1
138
+ while get_object(maxno) do maxno = maxno.succ end
139
+
140
+ object.generation = 0
141
+ object.no = maxno
142
+ end
143
+
144
+ @revisions.first.body[object.reference] = object
145
+
146
+ object.reference
147
+ end
148
+
149
+ def Catalog
150
+ get_object(@trailer.Root)
151
+ end
152
+
153
+ def save(filename)
154
+
155
+ bin = ""
156
+ bin << @header.to_s
157
+
158
+ lastno, brange = 0, 0
159
+
160
+ xrefs = [ XRef.new(0, XRef::LASTFREE, XRef::FREE) ]
161
+ xrefsection = XRef::Section.new
162
+
163
+ @revisions.first.body.values.sort.each { |obj|
164
+ if (obj.no - lastno).abs > 1
165
+ xrefsection << XRef::Subsection.new(brange, xrefs)
166
+ brange = obj.no
167
+ xrefs.clear
168
+ end
169
+
170
+ xrefs << XRef.new(bin.size, obj.generation, XRef::USED)
171
+ lastno = obj.no
172
+
173
+ bin << obj.to_s
174
+ }
175
+
176
+ xrefsection << XRef::Subsection.new(brange, xrefs)
177
+
178
+ @xreftable = xrefsection
179
+ @trailer ||= Trailer.new
180
+ @trailer.Size = rev.body.size + 1
181
+ @trailer.startxref = bin.size
182
+
183
+ bin << @xreftable.to_s
184
+ bin << @trailer.to_s
185
+
186
+ fd = File.open(filename, "w").binmode
187
+ fd << bin
188
+ fd.close
189
+
190
+ show_entries
191
+ end
192
+ alias saveas save
193
+
194
+ private
195
+
196
+ def rebuildxrefs #:nodoc:
197
+
198
+ startxref = @header.to_s.size
199
+
200
+ @revisions.first.body.values.each { |object|
201
+ startxref += object.to_s.size
202
+ }
203
+
204
+ @xreftable = buildxrefs(@revisions.first.body)
205
+
206
+ @trailer ||= Trailer.new
207
+ @trailer.Size = @revisions.first.body.size + 1
208
+ @trailer.startxref = startxref
209
+
210
+ self
211
+ end
212
+
213
+ def buildxrefs(objects) #:nodoc:
214
+
215
+ lastno = 0
216
+ brange = 0
217
+
218
+ xrefs = [ XRef.new(0, XRef::LASTFREE, XRef::FREE) ]
219
+
220
+ xrefsection = XRef::Section.new
221
+ objects.sort.each { |object|
222
+ if (object.no - lastno).abs > 1
223
+ xrefsection << XRef::Subsection.new(brange, xrefs)
224
+ brange = object.no
225
+ xrefs.clear
226
+ end
227
+
228
+ xrefs << XRef.new(get_object_offset(object.no, object.generation), object.generation, XRef::USED)
229
+
230
+ lastno = object.no
231
+ }
232
+
233
+ xrefsection << XRef::Subsection.new(brange, xrefs)
234
+
235
+ xrefsection
236
+ end
237
+
238
+ def get_object_offset(no,generation) #:nodoc:
239
+
240
+ bodyoffset = @header.to_s.size
241
+
242
+ objectoffset = bodyoffset
243
+
244
+ @revisions.first.body.values.each { |object|
245
+ if object.no == no and object.generation == generation then return objectoffset
246
+ else
247
+ objectoffset += object.to_s.size
248
+ end
249
+ }
250
+
251
+ nil
252
+ end
253
+
254
+ end
255
+
256
+ end
257
+
258
+ end
259
+