origami 1.2.7 → 2.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -0
- data/README.md +112 -0
- data/bin/config/pdfcop.conf.yml +232 -233
- data/bin/gui/about.rb +27 -37
- data/bin/gui/config.rb +108 -117
- data/bin/gui/file.rb +416 -365
- data/bin/gui/gtkhex.rb +1138 -1153
- data/bin/gui/hexview.rb +55 -57
- data/bin/gui/imgview.rb +48 -51
- data/bin/gui/menu.rb +388 -386
- data/bin/gui/properties.rb +114 -130
- data/bin/gui/signing.rb +571 -617
- data/bin/gui/textview.rb +77 -95
- data/bin/gui/treeview.rb +382 -387
- data/bin/gui/walker.rb +227 -232
- data/bin/gui/xrefs.rb +56 -60
- data/bin/pdf2pdfa +53 -57
- data/bin/pdf2ruby +212 -228
- data/bin/pdfcop +338 -348
- data/bin/pdfdecompress +58 -65
- data/bin/pdfdecrypt +56 -60
- data/bin/pdfencrypt +75 -80
- data/bin/pdfexplode +185 -182
- data/bin/pdfextract +201 -218
- data/bin/pdfmetadata +83 -82
- data/bin/pdfsh +4 -5
- data/bin/pdfwalker +1 -2
- data/bin/shell/.irbrc +45 -82
- data/bin/shell/console.rb +105 -130
- data/bin/shell/hexdump.rb +40 -64
- data/examples/README.md +34 -0
- data/examples/attachments/attachment.rb +38 -0
- data/examples/attachments/nested_document.rb +51 -0
- data/examples/encryption/encryption.rb +28 -0
- data/{samples/actions/triggerevents/trigger.rb → examples/events/events.rb} +13 -16
- data/examples/flash/flash.rb +37 -0
- data/{samples → examples}/flash/helloworld.swf +0 -0
- data/examples/forms/javascript.rb +54 -0
- data/examples/forms/xfa.rb +115 -0
- data/examples/javascript/hello_world.rb +22 -0
- data/examples/javascript/js_emulation.rb +54 -0
- data/examples/loop/goto.rb +32 -0
- data/examples/loop/named.rb +33 -0
- data/examples/signature/signature.rb +65 -0
- data/examples/uri/javascript.rb +56 -0
- data/examples/uri/open-uri.rb +21 -0
- data/examples/uri/submitform.rb +47 -0
- data/lib/origami.rb +29 -42
- data/lib/origami/3d.rb +350 -225
- data/lib/origami/acroform.rb +262 -288
- data/lib/origami/actions.rb +268 -288
- data/lib/origami/annotations.rb +697 -722
- data/lib/origami/array.rb +258 -184
- data/lib/origami/boolean.rb +74 -84
- data/lib/origami/catalog.rb +397 -434
- data/lib/origami/collections.rb +144 -0
- data/lib/origami/destinations.rb +233 -194
- data/lib/origami/dictionary.rb +253 -232
- data/lib/origami/encryption.rb +1274 -1243
- data/lib/origami/export.rb +232 -268
- data/lib/origami/extensions/fdf.rb +307 -220
- data/lib/origami/extensions/ppklite.rb +368 -435
- data/lib/origami/filespec.rb +197 -0
- data/lib/origami/filters.rb +301 -295
- data/lib/origami/filters/ascii.rb +177 -180
- data/lib/origami/filters/ccitt.rb +528 -535
- data/lib/origami/filters/crypt.rb +26 -35
- data/lib/origami/filters/dct.rb +46 -52
- data/lib/origami/filters/flate.rb +95 -94
- data/lib/origami/filters/jbig2.rb +49 -55
- data/lib/origami/filters/jpx.rb +38 -44
- data/lib/origami/filters/lzw.rb +189 -183
- data/lib/origami/filters/predictors.rb +221 -235
- data/lib/origami/filters/runlength.rb +103 -104
- data/lib/origami/font.rb +173 -186
- data/lib/origami/functions.rb +67 -81
- data/lib/origami/graphics.rb +25 -21
- data/lib/origami/graphics/colors.rb +178 -187
- data/lib/origami/graphics/instruction.rb +79 -85
- data/lib/origami/graphics/path.rb +142 -148
- data/lib/origami/graphics/patterns.rb +160 -167
- data/lib/origami/graphics/render.rb +43 -50
- data/lib/origami/graphics/state.rb +138 -153
- data/lib/origami/graphics/text.rb +188 -205
- data/lib/origami/graphics/xobject.rb +819 -815
- data/lib/origami/header.rb +63 -78
- data/lib/origami/javascript.rb +596 -597
- data/lib/origami/linearization.rb +285 -290
- data/lib/origami/metadata.rb +139 -148
- data/lib/origami/name.rb +112 -148
- data/lib/origami/null.rb +53 -62
- data/lib/origami/numeric.rb +162 -175
- data/lib/origami/obfuscation.rb +186 -174
- data/lib/origami/object.rb +593 -573
- data/lib/origami/outline.rb +42 -47
- data/lib/origami/outputintents.rb +73 -82
- data/lib/origami/page.rb +703 -592
- data/lib/origami/parser.rb +238 -290
- data/lib/origami/parsers/fdf.rb +41 -33
- data/lib/origami/parsers/pdf.rb +75 -95
- data/lib/origami/parsers/pdf/lazy.rb +137 -0
- data/lib/origami/parsers/pdf/linear.rb +64 -66
- data/lib/origami/parsers/ppklite.rb +34 -70
- data/lib/origami/pdf.rb +1030 -1005
- data/lib/origami/reference.rb +102 -102
- data/lib/origami/signature.rb +591 -609
- data/lib/origami/stream.rb +668 -551
- data/lib/origami/string.rb +397 -373
- data/lib/origami/template/patterns.rb +56 -0
- data/lib/origami/template/widgets.rb +151 -0
- data/lib/origami/trailer.rb +144 -158
- data/lib/origami/tree.rb +62 -0
- data/lib/origami/version.rb +23 -0
- data/lib/origami/webcapture.rb +88 -79
- data/lib/origami/xfa.rb +2863 -2882
- data/lib/origami/xreftable.rb +472 -384
- data/test/dataset/calc.pdf +85 -0
- data/test/dataset/crypto.pdf +82 -0
- data/test/dataset/empty.pdf +49 -0
- data/test/test_actions.rb +27 -0
- data/test/test_annotations.rb +90 -0
- data/test/test_pages.rb +31 -0
- data/test/test_pdf.rb +16 -0
- data/test/test_pdf_attachment.rb +34 -0
- data/test/test_pdf_create.rb +24 -0
- data/test/test_pdf_encrypt.rb +95 -0
- data/test/test_pdf_parse.rb +96 -0
- data/test/test_pdf_sign.rb +58 -0
- data/test/test_streams.rb +182 -0
- data/test/test_xrefs.rb +67 -0
- metadata +88 -58
- data/README +0 -67
- data/bin/pdf2graph +0 -121
- data/bin/pdfcocoon +0 -104
- data/lib/origami/file.rb +0 -233
- data/samples/README.txt +0 -45
- data/samples/actions/launch/calc.rb +0 -87
- data/samples/actions/launch/winparams.rb +0 -22
- data/samples/actions/loop/loopgoto.rb +0 -24
- data/samples/actions/loop/loopnamed.rb +0 -21
- data/samples/actions/named/named.rb +0 -31
- data/samples/actions/samba/smbrelay.rb +0 -26
- data/samples/actions/webbug/submitform.js +0 -26
- data/samples/actions/webbug/webbug-browser.rb +0 -68
- data/samples/actions/webbug/webbug-js.rb +0 -67
- data/samples/actions/webbug/webbug-reader.rb +0 -90
- data/samples/attachments/attach.rb +0 -40
- data/samples/attachments/attached.txt +0 -1
- data/samples/crypto/crypto.rb +0 -28
- data/samples/digsig/signed.rb +0 -46
- data/samples/exploits/cve-2008-2992-utilprintf.rb +0 -87
- data/samples/exploits/cve-2009-0927-geticon.rb +0 -65
- data/samples/exploits/exploit_customdictopen.rb +0 -55
- data/samples/exploits/getannots.rb +0 -69
- data/samples/flash/flash.rb +0 -31
- data/samples/javascript/attached.txt +0 -1
- data/samples/javascript/js.rb +0 -52
- data/templates/patterns.rb +0 -66
- data/templates/widgets.rb +0 -173
- data/templates/xdp.rb +0 -92
- data/test/ts_pdf.rb +0 -50
data/lib/origami/export.rb
CHANGED
|
@@ -1,283 +1,247 @@
|
|
|
1
1
|
=begin
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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/>.
|
|
3
|
+
This file is part of Origami, PDF manipulation framework for Ruby
|
|
4
|
+
Copyright (C) 2016 Guillaume Delugré.
|
|
5
|
+
|
|
6
|
+
Origami is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU Lesser General Public License as published by
|
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
Origami is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU Lesser General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU Lesser General Public License
|
|
17
|
+
along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
|
23
18
|
|
|
24
19
|
=end
|
|
25
20
|
|
|
26
21
|
module Origami
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
|
23
|
+
class PDF
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Exports the document to a dot Graphiz file.
|
|
27
|
+
# _filename_:: The path where to save the file.
|
|
28
|
+
#
|
|
29
|
+
def export_to_graph(path)
|
|
30
|
+
|
|
31
|
+
appearance = -> (object) do
|
|
32
|
+
label = object.type.to_s
|
|
33
|
+
case object
|
|
34
|
+
when Catalog
|
|
35
|
+
fontcolor = "red"
|
|
36
|
+
color = "mistyrose"
|
|
37
|
+
shape = "ellipse"
|
|
38
|
+
when Name, Number
|
|
39
|
+
label = object.value
|
|
40
|
+
fontcolor = "brown"
|
|
41
|
+
color = "lightgoldenrodyellow"
|
|
42
|
+
shape = "polygon"
|
|
43
|
+
when String
|
|
44
|
+
label = object.value if (object.ascii_only? and object.length <= 50)
|
|
45
|
+
fontcolor = "red"
|
|
46
|
+
color = "white"
|
|
47
|
+
shape = "polygon"
|
|
48
|
+
when Array
|
|
49
|
+
fontcolor = "darkgreen"
|
|
50
|
+
color = "lightcyan"
|
|
51
|
+
shape = "ellipse"
|
|
52
|
+
else
|
|
53
|
+
fontcolor = "blue"
|
|
54
|
+
color = "aliceblue"
|
|
55
|
+
shape = "ellipse"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
{ label: label, fontcolor: fontcolor, color: color, shape: shape }
|
|
200
59
|
end
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
60
|
+
|
|
61
|
+
add_edges = -> (fd, object) do
|
|
62
|
+
if object.is_a?(Array) or object.is_a?(ObjectStream)
|
|
63
|
+
object.each do |subobj|
|
|
64
|
+
fd << "\t#{object.object_id} -> #{subobj.solve.object_id}\n"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
elsif object.is_a?(Dictionary)
|
|
68
|
+
object.each_pair do |name, subobj|
|
|
69
|
+
fd << "\t#{object.object_id} -> #{subobj.solve.object_id} "
|
|
70
|
+
fd << "[label=\"#{name.value}\",fontsize=9];\n"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if object.is_a?(Stream)
|
|
75
|
+
object.dictionary.each_pair do |key, value|
|
|
76
|
+
fd << "\t#{object.object_id} -> #{value.solve.object_id} "
|
|
77
|
+
fd << "[label=\"#{key.value}\",fontsize=9];\n"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
graph_name = "PDF" if graph_name.nil? or graph_name.empty?
|
|
83
|
+
fd = File.open(path, "w")
|
|
84
|
+
|
|
85
|
+
begin
|
|
86
|
+
fd << "digraph #{graph_name} {\n\n"
|
|
87
|
+
|
|
88
|
+
objects = self.objects(include_keys: false).find_all{ |obj| not obj.is_a?(Reference) }
|
|
89
|
+
|
|
90
|
+
objects.each do |object|
|
|
91
|
+
attr = appearance[object]
|
|
92
|
+
|
|
93
|
+
fd << "\t#{object.object_id} "
|
|
94
|
+
fd << "[label=\"#{attr[:label]}\",shape=#{attr[:shape]},color=#{attr[:color]},style=filled,fontcolor=#{attr[:fontcolor]},fontsize=16];\n"
|
|
95
|
+
|
|
96
|
+
if object.is_a?(Stream)
|
|
97
|
+
object.dictionary.each do |value|
|
|
98
|
+
unless value.is_a?(Reference)
|
|
99
|
+
attr = appearance[value]
|
|
100
|
+
fd << "\t#{value.object_id} "
|
|
101
|
+
fd << "[label=\"#{attr[:label]}\",shape=#{attr[:shape]},color=#{attr[:color]},style=filled,fontcolor=#{attr[:fontcolor]},fontsize=16];\n"
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
add_edges.call(fd, object)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
fd << "\n}"
|
|
110
|
+
ensure
|
|
111
|
+
fd.close
|
|
212
112
|
end
|
|
213
|
-
}
|
|
214
|
-
|
|
215
113
|
end
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
114
|
+
|
|
115
|
+
#
|
|
116
|
+
# Exports the document to a GraphML file.
|
|
117
|
+
# _filename_:: The path where to save the file.
|
|
118
|
+
#
|
|
119
|
+
def export_to_graphml(path)
|
|
120
|
+
require 'rexml/document'
|
|
121
|
+
|
|
122
|
+
declare_node = -> (id, attr) do
|
|
123
|
+
<<-XML
|
|
124
|
+
<node id="#{id}">
|
|
125
|
+
<data key="d0">
|
|
126
|
+
<y:ShapeNode>
|
|
127
|
+
<y:NodeLabel>#{attr[:label]}</y:NodeLabel>
|
|
128
|
+
</y:ShapeNode>
|
|
129
|
+
</data>
|
|
130
|
+
</node>
|
|
131
|
+
XML
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
declare_edge = -> (id, src, dest, label = nil) do
|
|
135
|
+
<<-XML
|
|
136
|
+
<edge id="#{id}" source="#{src}" target="#{dest}">
|
|
137
|
+
<data key="d1">
|
|
138
|
+
<y:PolyLineEdge>
|
|
139
|
+
<y:LineStyle type="line" width="1.0" color="#000000"/>
|
|
140
|
+
<y:Arrows source="none" target="standard"/>
|
|
141
|
+
<y:EdgeLabel>#{label.to_s}</y:EdgeLabel>
|
|
142
|
+
</y:PolyLineEdge>
|
|
143
|
+
</data>
|
|
144
|
+
</edge>
|
|
145
|
+
XML
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
appearance = -> (object) do
|
|
149
|
+
label = object.type.to_s
|
|
150
|
+
case object
|
|
151
|
+
when Catalog
|
|
152
|
+
fontcolor = "red"
|
|
153
|
+
color = "mistyrose"
|
|
154
|
+
shape = "doublecircle"
|
|
155
|
+
when Name, Number
|
|
156
|
+
label = object.value
|
|
157
|
+
fontcolor = "orange"
|
|
158
|
+
color = "lightgoldenrodyellow"
|
|
159
|
+
shape = "polygon"
|
|
160
|
+
when String
|
|
161
|
+
label = object.value if (object.ascii_only? and object.length <= 50)
|
|
162
|
+
fontcolor = "red"
|
|
163
|
+
color = "white"
|
|
164
|
+
shape = "polygon"
|
|
165
|
+
when Array
|
|
166
|
+
fontcolor = "green"
|
|
167
|
+
color = "lightcyan"
|
|
168
|
+
shape = "ellipse"
|
|
169
|
+
else
|
|
170
|
+
fontcolor = "blue"
|
|
171
|
+
color = "aliceblue"
|
|
172
|
+
shape = "ellipse"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
{ label: label, fontcolor: fontcolor, color: color, shape: shape }
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
add_edges = -> (xml, object, id) do
|
|
179
|
+
if object.is_a?(Array) or object.is_a?(ObjectStream)
|
|
180
|
+
object.each do |subobj|
|
|
181
|
+
xml << declare_edge["e#{id}", "n#{object.object_id}", "n#{subobj.solve.object_id}"]
|
|
182
|
+
id = id + 1
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
elsif object.is_a?(Dictionary)
|
|
186
|
+
object.each_pair do |name, subobj|
|
|
187
|
+
xml << declare_edge["e#{id}", "n#{object.object_id}", "n#{subobj.solve.object_id}",
|
|
188
|
+
name.value]
|
|
189
|
+
id = id + 1
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
if object.is_a?(Stream)
|
|
194
|
+
object.dictionary.each_pair do |key, value|
|
|
195
|
+
xml << declare_edge["e#{id}", "n#{object.object_id}", "n#{value.object_id}", key.value]
|
|
196
|
+
id = id + 1
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
id
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
graph_name = "PDF" if graph_name.nil? or graph_name.empty?
|
|
204
|
+
|
|
205
|
+
edge_nb = 1
|
|
206
|
+
xml = <<-XML
|
|
207
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
208
|
+
<graphml xmlns="http://graphml.graphdrawing.org/xmlns/graphml"
|
|
209
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
210
|
+
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns/graphml
|
|
211
|
+
http://www.yworks.com/xml/schema/graphml/1.0/ygraphml.xsd"
|
|
212
|
+
xmlns:y="http://www.yworks.com/xml/graphml">
|
|
213
|
+
<key id="d0" for="node" yfiles.type="nodegraphics"/>
|
|
214
|
+
<key id="d1" for="edge" yfiles.type="edgegraphics"/>
|
|
215
|
+
<graph id="#{graph_name}" edgedefault="directed">
|
|
216
|
+
XML
|
|
217
|
+
|
|
218
|
+
objects = self.objects(include_keys: false).find_all{ |obj| not obj.is_a?(Reference) }
|
|
219
|
+
|
|
220
|
+
objects.each do |object|
|
|
221
|
+
xml << declare_node["n#{object.object_id}", appearance[object]]
|
|
222
|
+
|
|
223
|
+
if object.is_a?(Stream)
|
|
224
|
+
object.dictionary.each do |value|
|
|
225
|
+
unless value.is_a?(Reference)
|
|
226
|
+
xml << declare_node[value.object_id, appearance[value]]
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
edge_nb = add_edges[xml, object, edge_nb]
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
xml << '</graph>' << "\n"
|
|
235
|
+
xml << '</graphml>'
|
|
236
|
+
|
|
237
|
+
doc = REXML::Document.new(xml)
|
|
238
|
+
formatter = REXML::Formatters::Pretty.new(4)
|
|
239
|
+
formatter.compact = true
|
|
240
|
+
|
|
241
|
+
File.open(path, "w") do |fd|
|
|
242
|
+
formatter.write(doc, fd)
|
|
226
243
|
end
|
|
227
|
-
}
|
|
228
|
-
|
|
229
244
|
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
245
|
end
|
|
280
246
|
|
|
281
|
-
end
|
|
282
|
-
|
|
283
247
|
end
|