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,283 @@
1
+ =begin
2
+
3
+ = File
4
+ export.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
+ # Exports the document to a dot Graphiz file.
32
+ # _filename_:: The path where to save the file.
33
+ #
34
+ def export_to_graph(filename)
35
+
36
+ def appearance(object) #:nodoc:
37
+
38
+ label = object.type.to_s
39
+ case object
40
+ when Catalog
41
+ fontcolor = "red"
42
+ color = "mistyrose"
43
+ shape = "ellipse"
44
+ when Name, Number
45
+ label = object.value
46
+ fontcolor = "brown"
47
+ color = "lightgoldenrodyellow"
48
+ shape = "polygon"
49
+ when String
50
+ label = object.value unless (object.is_binary_data? or object.length > 50)
51
+ fontcolor = "red"
52
+ color = "white"
53
+ shape = "polygon"
54
+ when Array
55
+ fontcolor = "darkgreen"
56
+ color = "lightcyan"
57
+ shape = "ellipse"
58
+ else
59
+ fontcolor = "blue"
60
+ color = "aliceblue"
61
+ shape = "ellipse"
62
+ end
63
+
64
+ { :label => label, :fontcolor => fontcolor, :color => color, :shape => shape }
65
+ end
66
+
67
+ def add_edges(pdf, fd, object) #:nodoc:
68
+
69
+ if object.is_a?(Array) or object.is_a?(ObjectStream)
70
+
71
+ object.each { |subobj|
72
+ subobj = subobj.solve if subobj.is_a?(Reference)
73
+ fd << "\t#{object.object_id} -> #{subobj.object_id}\n" unless subobj.nil?
74
+ }
75
+
76
+ elsif object.is_a?(Dictionary)
77
+
78
+ object.each_pair { |name, subobj|
79
+ subobj = subobj.solve if subobj.is_a?(Reference)
80
+ fd << "\t#{object.object_id} -> #{subobj.object_id} [label=\"#{name.value}\",fontsize=9];\n" unless subobj.nil?
81
+ }
82
+
83
+ end
84
+
85
+ if object.is_a?(Stream)
86
+
87
+ object.dictionary.each_pair { |key, value|
88
+ value = value.solve if value.is_a?(Reference)
89
+ fd << "\t#{object.object_id} -> #{value.object_id} [label=\"#{key.value}\",fontsize=9];\n" unless value.nil?
90
+ }
91
+
92
+ end
93
+
94
+ end
95
+
96
+ graphname = "PDF" if graphname.nil? or graphname.empty?
97
+ fd = File.open(filename, "w")
98
+
99
+ begin
100
+ fd << "digraph #{graphname} {\n\n"
101
+
102
+ objects = self.objects(:include_keys => false).find_all{ |obj| not obj.is_a?(Reference) }
103
+
104
+ objects.each { |object|
105
+ attr = appearance(object)
106
+
107
+ fd << "\t#{object.object_id} [label=\"#{attr[:label]}\",shape=#{attr[:shape]},color=#{attr[:color]},style=filled,fontcolor=#{attr[:fontcolor]},fontsize=16];\n"
108
+
109
+ if object.is_a?(Stream)
110
+
111
+ object.dictionary.each { |value|
112
+ unless value.is_a?(Reference)
113
+ attr = appearance(value)
114
+ fd << "\t#{value.object_id} [label=\"#{attr[:label]}\",shape=#{attr[:shape]},color=#{attr[:color]},style=filled,fontcolor=#{attr[:fontcolor]},fontsize=16];\n"
115
+ end
116
+ }
117
+
118
+ end
119
+
120
+ add_edges(self, fd, object)
121
+ }
122
+ fd << "\n}"
123
+ ensure
124
+ fd.close
125
+ end
126
+
127
+ end
128
+
129
+ #
130
+ # Exports the document to a GraphML file.
131
+ # _filename_:: The path where to save the file.
132
+ #
133
+ def export_to_graphml(filename)
134
+
135
+ def declare_node(id, attr) #:nodoc:
136
+ " <node id=\"#{id}\">\n" <<
137
+ " <data key=\"d0\">\n" <<
138
+ " <y:ShapeNode>\n" <<
139
+ " <y:NodeLabel>#{attr[:label]}</y:NodeLabel>\n" <<
140
+ #~ " <y:Shape type=\"#{attr[:shape]}\"/>\n" <<
141
+ " </y:ShapeNode>\n" <<
142
+ " </data>\n" <<
143
+ " </node>\n"
144
+ end
145
+
146
+ def declare_edge(id, src, dest, label = nil) #:nodoc:
147
+ " <edge id=\"#{id}\" source=\"#{src}\" target=\"#{dest}\">\n" <<
148
+ " <data key=\"d1\">\n" <<
149
+ " <y:PolyLineEdge>\n" <<
150
+ " <y:LineStyle type=\"line\" width=\"1.0\" color=\"#000000\"/>\n" <<
151
+ " <y:Arrows source=\"none\" target=\"standard\"/>\n" <<
152
+ " <y:EdgeLabel>#{label.to_s}</y:EdgeLabel>\n" <<
153
+ " </y:PolyLineEdge>\n" <<
154
+ " </data>\n" <<
155
+ " </edge>\n"
156
+ end
157
+
158
+ def appearance(object) #:nodoc:
159
+
160
+ label = object.type.to_s
161
+ case object
162
+ when Catalog
163
+ fontcolor = "red"
164
+ color = "mistyrose"
165
+ shape = "doublecircle"
166
+ when Name, Number
167
+ label = object.value
168
+ fontcolor = "orange"
169
+ color = "lightgoldenrodyellow"
170
+ shape = "polygon"
171
+ when String
172
+ label = object.value unless (object.is_binary_data? or object.length > 50)
173
+ fontcolor = "red"
174
+ color = "white"
175
+ shape = "polygon"
176
+ when Array
177
+ fontcolor = "green"
178
+ color = "lightcyan"
179
+ shape = "ellipse"
180
+ else
181
+ fontcolor = "blue"
182
+ color = "aliceblue"
183
+ shape = "ellipse"
184
+ end
185
+
186
+ { :label => label, :fontcolor => fontcolor, :color => color, :shape => shape }
187
+ end
188
+
189
+ def add_edges(pdf, fd, object, id) #:nodoc:
190
+
191
+ if object.is_a?(Array) or object.is_a?(ObjectStream)
192
+
193
+ object.each { |subobj|
194
+
195
+ subobj = subobj.solve if subobj.is_a?(Reference)
196
+
197
+ unless subobj.nil?
198
+ fd << declare_edge("e#{id}", "n#{object.object_id}", "n#{subobj.object_id}")
199
+ id = id + 1
200
+ end
201
+ }
202
+
203
+ elsif object.is_a?(Dictionary)
204
+
205
+ object.each_pair { |name, subobj|
206
+
207
+ subobj = subobj.solve if subobj.is_a?(Reference)
208
+
209
+ unless subobj.nil?
210
+ fd << declare_edge("e#{id}", "n#{object.object_id}", "n#{subobj.object_id}", name.value)
211
+ id = id + 1
212
+ end
213
+ }
214
+
215
+ end
216
+
217
+ if object.is_a?(Stream)
218
+
219
+ object.dictionary.each_pair { |key, value|
220
+
221
+ value = value.solve if value.is_a?(Reference)
222
+
223
+ unless value.nil?
224
+ fd << declare_edge("e#{id}", "n#{object.object_id}", "n#{value.object_id}", key.value)
225
+ id = id + 1
226
+ end
227
+ }
228
+
229
+ end
230
+
231
+ id
232
+ end
233
+
234
+ @@edge_nb = 1
235
+
236
+ graphname = "PDF" if graphname.nil? or graphname.empty?
237
+
238
+ fd = File.open(filename, "w")
239
+
240
+ edge_nb = 1
241
+ begin
242
+
243
+ fd << '<?xml version="1.0" encoding="UTF-8"?>' << "\n"
244
+ fd << '<graphml xmlns="http://graphml.graphdrawing.org/xmlns/graphml"' << "\n"
245
+ fd << ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' << "\n"
246
+ fd << ' xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns/graphml ' << "\n"
247
+ fd << ' http://www.yworks.com/xml/schema/graphml/1.0/ygraphml.xsd"' << "\n"
248
+ fd << ' xmlns:y="http://www.yworks.com/xml/graphml">' << "\n"
249
+ fd << '<key id="d0" for="node" yfiles.type="nodegraphics"/>' << "\n"
250
+ fd << '<key id="d1" for="edge" yfiles.type="edgegraphics"/>' << "\n"
251
+ fd << "<graph id=\"#{graphname}\" edgedefault=\"directed\">\n"
252
+
253
+ objects = self.objects(:include_keys => false).find_all{ |obj| not obj.is_a?(Reference) }
254
+
255
+ objects.each { |object|
256
+
257
+ fd << declare_node("n#{object.object_id}", appearance(object))
258
+
259
+ if object.is_a?(Stream)
260
+
261
+ object.dictionary.each { |value|
262
+
263
+ unless value.is_a?(Reference)
264
+ fd << declare_node(value.object_id, appearance(value))
265
+ end
266
+ }
267
+ end
268
+
269
+ edge_nb = add_edges(self, fd, object, edge_nb)
270
+ }
271
+
272
+ fd << '</graph>' << "\n"
273
+ fd << '</graphml>'
274
+
275
+ ensure
276
+ fd.close
277
+ end
278
+
279
+ end
280
+
281
+ end
282
+
283
+ end
@@ -0,0 +1,222 @@
1
+ =begin
2
+
3
+ = File
4
+ file.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
+ # Attachs an embedded file to the PDF.
32
+ # _path_:: The path to the file to attach.
33
+ # _options_:: A set of options to configure the attachment.
34
+ #
35
+ def attach_file(path, options = {})
36
+
37
+ #
38
+ # Default options.
39
+ #
40
+ params =
41
+ {
42
+ :Register => true, # Shall the file be registered in the name directory ?
43
+ :EmbeddedName => nil, # The inner filename of the attachment.
44
+ :Filter => :FlateDecode # The stream filter used to store data.
45
+ }.update(options)
46
+
47
+ if path.respond_to?(:read)
48
+ fd = path
49
+ params[:EmbeddedName] ||= ''
50
+ else
51
+ fd = File.open(path, 'r').binmode
52
+ params[:EmbeddedName] ||= File.basename(path)
53
+ end
54
+
55
+ fstream = EmbeddedFileStream.new
56
+ fstream.data = fd.read
57
+ fstream.setFilter(params[:Filter])
58
+
59
+ name = params[:EmbeddedName]
60
+ fspec = FileSpec.new.setType(:Filespec).setF(name.dup).setEF(
61
+ FileSpec.new(:F => fstream)
62
+ )
63
+
64
+ register(
65
+ Names::Root::EMBEDDEDFILES,
66
+ name.dup,
67
+ fspec
68
+ ) if params[:Register] == true
69
+
70
+ fd.close
71
+
72
+ fspec
73
+ end
74
+
75
+ #
76
+ # Lookup embedded file in the embedded files name directory.
77
+ #
78
+ def get_embedded_file_by_name(name)
79
+ resolve_name Names::Root::EMBEDDEDFILES, name
80
+ end
81
+
82
+ #
83
+ # Calls block for each named embedded file.
84
+ #
85
+ def each_named_embedded_file(&b)
86
+ each_name(Names::Root::EMBEDDEDFILES, &b)
87
+ end
88
+ end
89
+
90
+ #
91
+ # Class used to convert system-dependent pathes into PDF pathes.
92
+ # PDF path specification offers a single form for representing file pathes over operating systems.
93
+ #
94
+ class Filename
95
+
96
+ class << self
97
+
98
+ #
99
+ # Converts UNIX file path into PDF file path.
100
+ #
101
+ def Unix(file)
102
+ ByteString.new(file)
103
+ end
104
+
105
+ #
106
+ # Converts MacOS file path into PDF file path.
107
+ #
108
+ def Mac(file)
109
+ ByteString.new("/" + file.gsub(":", "/"))
110
+ end
111
+
112
+ #
113
+ # Converts Windows file path into PDF file path.
114
+ #
115
+ def DOS(file)
116
+ path = ""
117
+ # Absolute vs relative path
118
+ if file.include? ":"
119
+ path << "/"
120
+ file.sub!(":","")
121
+ end
122
+
123
+ file.gsub!("\\", "/")
124
+ ByteString.new(path + file)
125
+ end
126
+
127
+ end
128
+
129
+ end
130
+
131
+
132
+ #
133
+ # Class representing a file specification.
134
+ # File specifications can be used to reference external files, as well as embedded files and URIs.
135
+ #
136
+ class FileSpec < Dictionary
137
+
138
+ include StandardObject
139
+
140
+ field :Type, :Type => Name, :Default => :FileSpec
141
+ field :FS, :Type => Name, :Default => :URL
142
+ field :F, :Type => [ ByteString, Stream ]
143
+ field :UF, :Type => String
144
+ field :DOS, :Type => ByteString
145
+ field :Mac, :Type => ByteString
146
+ field :Unix, :Type => ByteString
147
+ field :ID, :Type => Array
148
+ field :V, :Type => Boolean, :Default => false, :Version => "1.2"
149
+ field :EF, :Type => Dictionary, :Version => "1.3"
150
+ field :RF, :Type => Dictionary, :Version => "1.3"
151
+ field :Desc, :Type => ByteString, :Version => "1.6"
152
+ field :CI, :Type => Dictionary, :Version => "1.7"
153
+ field :Thumb, :Type => Stream, :Version => "1.7", :ExtensionLevel => 3
154
+
155
+ end
156
+
157
+ #
158
+ # Class representing a Uniform Resource Locator (URL)
159
+ #
160
+ class URL < FileSpec
161
+
162
+ field :Type, :Type => Name, :Default => :URL, :Required => true
163
+
164
+ def initialize(url)
165
+ super(:F => url)
166
+ end
167
+ end
168
+
169
+ #
170
+ # A class representing a file outside the current PDF file.
171
+ #
172
+ class ExternalFile < FileSpec
173
+
174
+ field :Type, :Type => Name, :Default => :FileSpec, :Required => true
175
+
176
+ #
177
+ # Creates a new external file specification.
178
+ # _dos_:: The Windows path to this file.
179
+ # _mac_:: The MacOS path to this file.
180
+ # _unix_:: The UNIX path to this file.
181
+ #
182
+ def initialize(dos, mac = "", unix = "")
183
+
184
+ if not mac.empty? or not unix.empty?
185
+ super(:DOS => Filename.DOS(dos), :Mac => Filename.Mac(mac), :Unix => Filename.Unix(unix))
186
+ else
187
+ super(:F => dos)
188
+ end
189
+
190
+ end
191
+
192
+ end
193
+
194
+ #
195
+ # Class representing the data of an embedded file.
196
+ #
197
+ class EmbeddedFileStream < Stream
198
+
199
+ include StandardObject
200
+
201
+ field :Type, :Type => Name, :Default => :EmbeddedFile
202
+ field :Subtype, :Type => Name
203
+ field :Params, :Type => Dictionary
204
+
205
+ end
206
+
207
+ #
208
+ # Class representing parameters for a EmbeddedFileStream.
209
+ #
210
+ class EmbeddedFileParameters < Dictionary
211
+
212
+ include StandardObject
213
+
214
+ field :Size, :Type => Integer
215
+ field :CreationDate, :Type => ByteString
216
+ field :ModDate, :Type => ByteString
217
+ field :Mac, :Type => Dictionary
218
+ field :Checksum, :Type => String
219
+
220
+ end
221
+
222
+ end