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/bin/gui/about.rb
CHANGED
|
@@ -1,46 +1,36 @@
|
|
|
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 General Public License for more details.
|
|
20
|
-
|
|
21
|
-
You should have received a copy of the GNU General Public License
|
|
22
|
-
along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
|
|
3
|
+
This file is part of PDF Walker, a graphical PDF file browser
|
|
4
|
+
Copyright (C) 2016 Guillaume Delugré.
|
|
5
|
+
|
|
6
|
+
PDF Walker is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU 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
|
+
PDF Walker 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 General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License
|
|
17
|
+
along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
|
|
23
18
|
|
|
24
19
|
=end
|
|
25
20
|
|
|
26
21
|
module PDFWalker
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
})
|
|
41
|
-
|
|
23
|
+
class Walker < Window
|
|
24
|
+
|
|
25
|
+
def about
|
|
26
|
+
AboutDialog.show(self,
|
|
27
|
+
name: "PDF Walker",
|
|
28
|
+
program_name: "PDF Walker",
|
|
29
|
+
version: Origami::VERSION,
|
|
30
|
+
copyright: "Copyright (C) 2016\nGuillaume Delugré",
|
|
31
|
+
comments: "A graphical PDF parser front-end",
|
|
32
|
+
license: File.read(File.join(__dir__, "COPYING"))
|
|
33
|
+
)
|
|
34
|
+
end
|
|
42
35
|
end
|
|
43
|
-
|
|
44
|
-
end
|
|
45
|
-
|
|
46
36
|
end
|
data/bin/gui/config.rb
CHANGED
|
@@ -1,128 +1,119 @@
|
|
|
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 General Public License for more details.
|
|
20
|
-
|
|
21
|
-
You should have received a copy of the GNU General Public License
|
|
22
|
-
along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
|
|
3
|
+
This file is part of PDF Walker, a graphical PDF file browser
|
|
4
|
+
Copyright (C) 2016 Guillaume Delugré.
|
|
5
|
+
|
|
6
|
+
PDF Walker is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU 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
|
+
PDF Walker 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 General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License
|
|
17
|
+
along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
|
|
23
18
|
|
|
24
19
|
=end
|
|
25
20
|
|
|
21
|
+
require 'origami'
|
|
26
22
|
require 'yaml'
|
|
27
23
|
|
|
28
24
|
module PDFWalker
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
@conf[cat][key] = value unless @conf[cat].include?(key)
|
|
121
|
-
end
|
|
25
|
+
|
|
26
|
+
class Walker < Window
|
|
27
|
+
|
|
28
|
+
class Config
|
|
29
|
+
DEFAULT_CONFIG_FILE = "#{File.expand_path("~")}/.pdfwalker.conf.yml"
|
|
30
|
+
DEFAULT_CONFIG =
|
|
31
|
+
{
|
|
32
|
+
"Debug" =>
|
|
33
|
+
{
|
|
34
|
+
"Profiling" => false,
|
|
35
|
+
"ProfilingOutputDir" => "prof",
|
|
36
|
+
"Verbosity" => Origami::Parser::VERBOSE_TRACE,
|
|
37
|
+
"IgnoreFileHeader" => true
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
"UI" =>
|
|
41
|
+
{
|
|
42
|
+
"LastOpenedDocuments" => []
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
NLOG_RECENT_FILES = 5
|
|
46
|
+
|
|
47
|
+
def initialize(configfile = DEFAULT_CONFIG_FILE)
|
|
48
|
+
begin
|
|
49
|
+
@conf = YAML.load(File.open(configfile)) or DEFAULT_CONFIG
|
|
50
|
+
rescue
|
|
51
|
+
ensure
|
|
52
|
+
@filename = configfile
|
|
53
|
+
set_missing_values
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def last_opened_file(filepath)
|
|
58
|
+
@conf["UI"]['LastOpenedDocuments'].push(filepath).uniq!
|
|
59
|
+
@conf["UI"]['LastOpenedDocuments'].delete_at(0) while @conf["UI"]['LastOpenedDocuments'].size > NLOG_RECENT_FILES
|
|
60
|
+
|
|
61
|
+
save
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def recent_files(n = NLOG_RECENT_FILES)
|
|
65
|
+
@conf["UI"]['LastOpenedDocuments'].last(n).reverse
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def set_profiling(bool)
|
|
69
|
+
@conf["Debug"]['Profiling'] = bool
|
|
70
|
+
save
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def profile?
|
|
74
|
+
@conf["Debug"]['Profiling']
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def profile_output_dir
|
|
78
|
+
@conf["Debug"]['ProfilingOutputDir']
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def set_ignore_header(bool)
|
|
82
|
+
@conf["Debug"]['IgnoreFileHeader'] = bool
|
|
83
|
+
save
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def ignore_header?
|
|
87
|
+
@conf["Debug"]['IgnoreFileHeader']
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def set_verbosity(level)
|
|
91
|
+
@conf["Debug"]['Verbosity'] = level
|
|
92
|
+
save
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def verbosity
|
|
96
|
+
@conf["Debug"]['Verbosity']
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def save
|
|
100
|
+
File.open(@filename, "w").write(@conf.to_yaml)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
|
|
105
|
+
def set_missing_values
|
|
106
|
+
@conf ||= {}
|
|
107
|
+
|
|
108
|
+
DEFAULT_CONFIG.each_key do |cat|
|
|
109
|
+
@conf[cat] = {} unless @conf.include?(cat)
|
|
110
|
+
|
|
111
|
+
DEFAULT_CONFIG[cat].each_pair do |key, value|
|
|
112
|
+
@conf[cat][key] = value unless @conf[cat].include?(key)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
122
116
|
end
|
|
123
|
-
|
|
117
|
+
|
|
124
118
|
end
|
|
125
|
-
|
|
126
|
-
end
|
|
127
|
-
|
|
128
119
|
end
|
data/bin/gui/file.rb
CHANGED
|
@@ -1,385 +1,436 @@
|
|
|
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 General Public License for more details.
|
|
20
|
-
|
|
21
|
-
You should have received a copy of the GNU General Public License
|
|
22
|
-
along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
|
|
3
|
+
This file is part of PDF Walker, a graphical PDF file browser
|
|
4
|
+
Copyright (C) 2016 Guillaume Delugré.
|
|
5
|
+
|
|
6
|
+
PDF Walker is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU 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
|
+
PDF Walker 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 General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License
|
|
17
|
+
along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
|
|
23
18
|
|
|
24
19
|
=end
|
|
25
20
|
|
|
26
21
|
require 'origami'
|
|
27
|
-
include Origami
|
|
28
22
|
|
|
29
23
|
module PDFWalker
|
|
30
24
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
attr_reader :explore_history
|
|
35
|
-
|
|
36
|
-
def close
|
|
37
|
-
|
|
38
|
-
@opened = nil
|
|
39
|
-
@filename = ''
|
|
40
|
-
@explorer_history.clear
|
|
41
|
-
|
|
42
|
-
@treeview.clear
|
|
43
|
-
@objectview.clear
|
|
44
|
-
@hexview.clear
|
|
45
|
-
|
|
46
|
-
[
|
|
47
|
-
@file_menu_close, @file_menu_saveas, @file_menu_serialize, @file_menu_refresh,
|
|
48
|
-
@document_menu_search,
|
|
49
|
-
@document_menu_gotocatalog, @document_menu_gotopage, @document_menu_gotorev, @document_menu_gotoobj,
|
|
50
|
-
@document_menu_properties, @document_menu_sign, @document_menu_ur
|
|
51
|
-
].each do |menu|
|
|
52
|
-
menu.sensitive = false
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
@statusbar.pop(@main_context)
|
|
56
|
-
|
|
57
|
-
GC.start
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def open(filename = nil)
|
|
61
|
-
|
|
62
|
-
dialog = Gtk::FileChooserDialog.new("Open PDF File",
|
|
63
|
-
self,
|
|
64
|
-
FileChooser::ACTION_OPEN,
|
|
65
|
-
nil,
|
|
66
|
-
[Stock::CANCEL, Dialog::RESPONSE_CANCEL],
|
|
67
|
-
[Stock::OPEN, Dialog::RESPONSE_ACCEPT])
|
|
68
|
-
|
|
69
|
-
last_file = @config.recent_files.first
|
|
70
|
-
unless last_file.nil?
|
|
71
|
-
last_folder = last_file[0..last_file.size - File.basename(last_file).size - 1]
|
|
72
|
-
dialog.set_current_folder(last_folder) if File.directory?(last_folder)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
dialog.filter = FileFilter.new.add_pattern("*.acrodata").add_pattern("*.pdf").add_pattern("*.fdf")
|
|
76
|
-
|
|
77
|
-
if filename or dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
|
78
|
-
|
|
79
|
-
create_progressbar
|
|
80
|
-
|
|
81
|
-
filename ||= dialog.filename
|
|
82
|
-
dialog.destroy
|
|
83
|
-
|
|
84
|
-
begin
|
|
85
|
-
|
|
86
|
-
if @help_menu_profile.active?
|
|
87
|
-
require 'ruby-prof'
|
|
88
|
-
RubyProf.start
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
target = parsefile(filename)
|
|
92
|
-
|
|
93
|
-
if @help_menu_profile.active?
|
|
94
|
-
result = RubyProf.stop
|
|
95
|
-
txtprinter = RubyProf::FlatPrinter.new(result)
|
|
96
|
-
htmlprinter = RubyProf::GraphHtmlPrinter.new(result)
|
|
97
|
-
txtprinter.print(File.new("#{@config.profile_output_dir}/#{File.basename(filename)}.log", "w"))
|
|
98
|
-
htmlprinter.print(File.new("#{@config.profile_output_dir}/#{File.basename(filename)}.log.html", "w"))
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
if target
|
|
102
|
-
close if @opened
|
|
103
|
-
@opened = target
|
|
104
|
-
@filename = filename
|
|
105
|
-
|
|
106
|
-
@config.last_opened_file(filename)
|
|
107
|
-
@config.save
|
|
108
|
-
update_recent_menu
|
|
109
|
-
|
|
110
|
-
@last_search_result = []
|
|
111
|
-
@last_search =
|
|
112
|
-
{
|
|
113
|
-
:expr => "",
|
|
114
|
-
:regexp => false,
|
|
115
|
-
:type => :body
|
|
116
|
-
}
|
|
25
|
+
class Walker < Window
|
|
26
|
+
attr_reader :opened
|
|
27
|
+
attr_reader :explore_history
|
|
117
28
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
@file_menu_close, @file_menu_saveas, @file_menu_serialize, @file_menu_refresh,
|
|
122
|
-
@document_menu_search,
|
|
123
|
-
@document_menu_gotocatalog, @document_menu_gotopage, @document_menu_gotorev, @document_menu_gotoobj,
|
|
124
|
-
@document_menu_properties, @document_menu_sign, @document_menu_ur
|
|
125
|
-
].each do |menu|
|
|
126
|
-
menu.sensitive = true
|
|
127
|
-
end
|
|
128
|
-
|
|
29
|
+
def close
|
|
30
|
+
@opened = nil
|
|
31
|
+
@filename = ''
|
|
129
32
|
@explorer_history.clear
|
|
130
|
-
|
|
131
|
-
@
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
revmenu = Menu.new
|
|
145
|
-
@document_menu_gotorev.remove_submenu
|
|
146
|
-
rev_index = 1
|
|
147
|
-
@opened.revisions.each do |rev|
|
|
148
|
-
revmenu.append(item = MenuItem.new(rev_index.to_s).show)
|
|
149
|
-
item.signal_connect("activate") do @treeview.goto(rev) end
|
|
150
|
-
rev_index = rev_index + 1
|
|
151
|
-
end
|
|
152
|
-
@document_menu_gotorev.set_submenu(revmenu)
|
|
153
|
-
|
|
154
|
-
goto_catalog
|
|
33
|
+
|
|
34
|
+
@treeview.clear
|
|
35
|
+
@objectview.clear
|
|
36
|
+
@hexview.clear
|
|
37
|
+
|
|
38
|
+
# disable all menus.
|
|
39
|
+
[
|
|
40
|
+
@file_menu_close, @file_menu_saveas, @file_menu_serialize, @file_menu_refresh,
|
|
41
|
+
@document_menu_search,
|
|
42
|
+
@document_menu_gotocatalog, @document_menu_gotodocinfo, @document_menu_gotometadata,
|
|
43
|
+
@document_menu_gotopage, @document_menu_gotofield, @document_menu_gotorev, @document_menu_gotoobj,
|
|
44
|
+
@document_menu_properties, @document_menu_sign, @document_menu_ur
|
|
45
|
+
].each do |menu|
|
|
46
|
+
menu.sensitive = false
|
|
155
47
|
end
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
48
|
+
|
|
49
|
+
@statusbar.pop(@main_context)
|
|
50
|
+
|
|
51
|
+
GC.start
|
|
160
52
|
end
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
53
|
+
|
|
54
|
+
def open(filename = nil)
|
|
55
|
+
dialog = Gtk::FileChooserDialog.new("Open PDF File",
|
|
56
|
+
self,
|
|
57
|
+
FileChooser::ACTION_OPEN,
|
|
58
|
+
nil,
|
|
59
|
+
[Stock::CANCEL, Dialog::RESPONSE_CANCEL],
|
|
60
|
+
[Stock::OPEN, Dialog::RESPONSE_ACCEPT])
|
|
61
|
+
|
|
62
|
+
last_file = @config.recent_files.first
|
|
63
|
+
unless last_file.nil?
|
|
64
|
+
last_folder = File.dirname(last_file)
|
|
65
|
+
dialog.set_current_folder(last_folder) if File.directory?(last_folder)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
dialog.filter = FileFilter.new.add_pattern("*.acrodata").add_pattern("*.pdf").add_pattern("*.fdf")
|
|
69
|
+
|
|
70
|
+
if filename.nil? and dialog.run != Gtk::Dialog::RESPONSE_ACCEPT
|
|
71
|
+
dialog.destroy
|
|
72
|
+
return
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
create_progressbar
|
|
76
|
+
|
|
77
|
+
filename ||= dialog.filename
|
|
78
|
+
dialog.destroy
|
|
79
|
+
|
|
80
|
+
begin
|
|
81
|
+
if @help_menu_profile.active?
|
|
82
|
+
require 'ruby-prof'
|
|
83
|
+
RubyProf.start
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
target = parse_file(filename)
|
|
87
|
+
|
|
88
|
+
if @help_menu_profile.active?
|
|
89
|
+
result = RubyProf.stop
|
|
90
|
+
multiprinter = RubyProf::MultiPrinter.new(result)
|
|
91
|
+
|
|
92
|
+
Dir.mkdir(@config.profile_output_dir) unless Dir.exists?(@config.profile_output_dir)
|
|
93
|
+
|
|
94
|
+
multiprinter.print(path: @config.profile_output_dir, profile: File.basename(filename))
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
if target
|
|
98
|
+
close if @opened
|
|
99
|
+
@opened = target
|
|
100
|
+
@filename = filename
|
|
101
|
+
|
|
102
|
+
@config.last_opened_file(filename)
|
|
103
|
+
@config.save
|
|
104
|
+
update_recent_menu
|
|
105
|
+
|
|
106
|
+
@last_search_result = []
|
|
107
|
+
@last_search =
|
|
108
|
+
{
|
|
109
|
+
:expr => "",
|
|
110
|
+
:regexp => false,
|
|
111
|
+
:type => :body
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
self.reload
|
|
115
|
+
|
|
116
|
+
# Enable basic file menus.
|
|
117
|
+
[
|
|
118
|
+
@file_menu_close, @file_menu_refresh,
|
|
119
|
+
].each do |menu|
|
|
120
|
+
menu.sensitive = true
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
@explorer_history.clear
|
|
124
|
+
|
|
125
|
+
@statusbar.push(@main_context, "Viewing #{filename}")
|
|
126
|
+
|
|
127
|
+
if @opened.is_a?(Origami::PDF)
|
|
128
|
+
|
|
129
|
+
# Enable save and document menu.
|
|
130
|
+
[
|
|
131
|
+
@file_menu_saveas, @file_menu_serialize,
|
|
132
|
+
@document_menu_search,
|
|
133
|
+
@document_menu_gotocatalog, @document_menu_gotopage, @document_menu_gotorev, @document_menu_gotoobj,
|
|
134
|
+
@document_menu_properties, @document_menu_sign, @document_menu_ur
|
|
135
|
+
].each do |menu|
|
|
136
|
+
menu.sensitive = true
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
@document_menu_gotodocinfo.sensitive = true if @opened.document_info?
|
|
140
|
+
@document_menu_gotometadata.sensitive = true if @opened.metadata?
|
|
141
|
+
@document_menu_gotofield.sensitive = true if @opened.form?
|
|
142
|
+
|
|
143
|
+
page_menu = Menu.new
|
|
144
|
+
@document_menu_gotopage.remove_submenu
|
|
145
|
+
@opened.each_page.with_index(1) do |page, index|
|
|
146
|
+
page_menu.append(item = MenuItem.new(index.to_s).show)
|
|
147
|
+
item.signal_connect("activate") do @treeview.goto(page) end
|
|
148
|
+
end
|
|
149
|
+
@document_menu_gotopage.set_submenu(page_menu)
|
|
150
|
+
|
|
151
|
+
field_menu = Menu.new
|
|
152
|
+
@document_menu_gotofield.remove_submenu
|
|
153
|
+
@opened.each_field do |field|
|
|
154
|
+
field_name = field.T || "<unnamed field>"
|
|
155
|
+
field_menu.append(item = MenuItem.new(field_name).show)
|
|
156
|
+
item.signal_connect("activate") do @treeview.goto(field) end
|
|
157
|
+
end
|
|
158
|
+
@document_menu_gotofield.set_submenu(field_menu)
|
|
159
|
+
|
|
160
|
+
rev_menu = Menu.new
|
|
161
|
+
@document_menu_gotorev.remove_submenu
|
|
162
|
+
rev_index = 1
|
|
163
|
+
@opened.revisions.each do |rev|
|
|
164
|
+
rev_menu.append(item = MenuItem.new(rev_index.to_s).show)
|
|
165
|
+
item.signal_connect("activate") do @treeview.goto(rev) end
|
|
166
|
+
rev_index = rev_index + 1
|
|
167
|
+
end
|
|
168
|
+
@document_menu_gotorev.set_submenu(rev_menu)
|
|
169
|
+
|
|
170
|
+
goto_catalog
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
rescue
|
|
175
|
+
error("Error while parsing file.\n#{$!} (#{$!.class})\n" + $!.backtrace.join("\n"))
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
close_progressbar
|
|
179
|
+
self.activate_focus
|
|
205
180
|
end
|
|
206
181
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
dialog = Gtk::FileChooserDialog.new("Save dump file",
|
|
216
|
-
self,
|
|
217
|
-
Gtk::FileChooser::ACTION_SAVE,
|
|
218
|
-
nil,
|
|
219
|
-
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
|
220
|
-
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT]
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
dialog.do_overwrite_confirmation = true
|
|
224
|
-
dialog.current_folder = "#{Dir.pwd}/dumps"
|
|
225
|
-
dialog.current_name = "#{File.basename(@filename)}.dmp.gz"
|
|
226
|
-
dialog.filter = FileFilter.new.add_pattern("*.gz")
|
|
227
|
-
|
|
228
|
-
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
|
229
|
-
@opened.serialize(dialog.filename)
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
dialog.destroy
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
def save_data(caption, data, filename = "")
|
|
236
|
-
|
|
237
|
-
dialog = Gtk::FileChooserDialog.new(caption,
|
|
238
|
-
self,
|
|
239
|
-
Gtk::FileChooser::ACTION_SAVE,
|
|
240
|
-
nil,
|
|
241
|
-
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
|
242
|
-
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT]
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
dialog.do_overwrite_confirmation = true
|
|
246
|
-
dialog.current_name = File.basename(filename)
|
|
247
|
-
dialog.filter = FileFilter.new.add_pattern("*.*")
|
|
248
|
-
|
|
249
|
-
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
|
250
|
-
fd = File.open(dialog.filename, "w").binmode
|
|
251
|
-
fd << data
|
|
252
|
-
fd.close
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
dialog.destroy
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
def save
|
|
259
|
-
|
|
260
|
-
dialog = Gtk::FileChooserDialog.new("Save PDF file",
|
|
261
|
-
self,
|
|
262
|
-
Gtk::FileChooser::ACTION_SAVE,
|
|
263
|
-
nil,
|
|
264
|
-
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
|
265
|
-
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT]
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
dialog.filter = FileFilter.new.add_pattern("*.acrodata").add_pattern("*.pdf").add_pattern("*.fdf")
|
|
269
|
-
|
|
270
|
-
folder = @filename[0..@filename.size - File.basename(@filename).size - 1]
|
|
271
|
-
dialog.set_current_folder(folder)
|
|
272
|
-
|
|
273
|
-
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
|
274
|
-
@opened.save(dialog.filename)
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
dialog.destroy
|
|
278
|
-
end
|
|
182
|
+
def deserialize
|
|
183
|
+
dialog = Gtk::FileChooserDialog.new("Open dump file",
|
|
184
|
+
self,
|
|
185
|
+
FileChooser::ACTION_OPEN,
|
|
186
|
+
nil,
|
|
187
|
+
[Stock::CANCEL, Dialog::RESPONSE_CANCEL],
|
|
188
|
+
[Stock::OPEN, Dialog::RESPONSE_ACCEPT]
|
|
189
|
+
)
|
|
279
190
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
dialog = Gtk::FileChooserDialog.new("Save GraphML file",
|
|
305
|
-
self,
|
|
306
|
-
Gtk::FileChooser::ACTION_SAVE,
|
|
307
|
-
nil,
|
|
308
|
-
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
|
309
|
-
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT]
|
|
310
|
-
)
|
|
311
|
-
|
|
312
|
-
dialog.filter = FileFilter.new.add_pattern("*.graphml")
|
|
313
|
-
|
|
314
|
-
folder = @filename[0..@filename.size - File.basename(@filename).size - 1]
|
|
315
|
-
dialog.set_current_folder(folder)
|
|
316
|
-
|
|
317
|
-
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
|
318
|
-
@opened.export_to_graphml(dialog.filename)
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
dialog.destroy
|
|
322
|
-
end
|
|
191
|
+
dialog.current_folder = File.join(Dir.pwd, "dumps")
|
|
192
|
+
dialog.filter = FileFilter.new.add_pattern("*.gz")
|
|
193
|
+
|
|
194
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
|
195
|
+
close if @opened
|
|
196
|
+
filename = dialog.filename
|
|
197
|
+
|
|
198
|
+
begin
|
|
199
|
+
@opened = Origami::PDF.deserialize(filename)
|
|
200
|
+
self.reload
|
|
201
|
+
|
|
202
|
+
[
|
|
203
|
+
@file_menu_close, @file_menu_saveas, @file_menu_serialize, @file_menu_refresh,
|
|
204
|
+
@document_menu_search,
|
|
205
|
+
@document_menu_gotocatalog, @document_menu_gotopage, @document_menu_gotorev, @document_menu_gotoobj,
|
|
206
|
+
@document_menu_properties, @document_menu_sign, @document_menu_ur
|
|
207
|
+
].each do |menu|
|
|
208
|
+
menu.sensitive = true
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
@document_menu_gotodocinfo.sensitive = true if @opened.document_info?
|
|
212
|
+
@document_menu_gotometadata.sensitive = true if @opened.metadata?
|
|
213
|
+
@document_menu_gotofield.sensitive = true if @opened.form?
|
|
323
214
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
passwd = ""
|
|
334
|
-
|
|
335
|
-
dialog = Gtk::Dialog.new(
|
|
336
|
-
"This document is encrypted",
|
|
337
|
-
nil,
|
|
338
|
-
Gtk::Dialog::MODAL,
|
|
339
|
-
[ Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK ],
|
|
340
|
-
[ Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL ]
|
|
341
|
-
)
|
|
342
|
-
|
|
343
|
-
dialog.set_default_response(Gtk::Dialog::RESPONSE_OK)
|
|
344
|
-
|
|
345
|
-
label = Gtk::Label.new("Please enter password:")
|
|
346
|
-
entry = Gtk::Entry.new
|
|
347
|
-
entry.signal_connect('activate') {
|
|
348
|
-
dialog.response(Gtk::Dialog::RESPONSE_OK)
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
dialog.vbox.add(label)
|
|
352
|
-
dialog.vbox.add(entry)
|
|
353
|
-
dialog.show_all
|
|
354
|
-
|
|
355
|
-
dialog.run do |response|
|
|
356
|
-
if response == Gtk::Dialog::RESPONSE_OK
|
|
357
|
-
passwd = entry.text
|
|
358
|
-
end
|
|
215
|
+
@explorer_history.clear
|
|
216
|
+
|
|
217
|
+
@statusbar.push(@main_context, "Viewing dump of #{filename}")
|
|
218
|
+
rescue
|
|
219
|
+
error("This file cannot be loaded.\n#{$!} (#{$!.class})")
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
dialog.destroy
|
|
359
224
|
end
|
|
360
|
-
|
|
361
|
-
dialog.destroy
|
|
362
|
-
|
|
363
|
-
return passwd
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
PDF.read(filename,
|
|
367
|
-
:verbosity => Parser::VERBOSE_INSANE,
|
|
368
|
-
:ignoreerrors => false,
|
|
369
|
-
:callback => update_bar,
|
|
370
|
-
:prompt_password => prompt_passwd
|
|
371
|
-
)
|
|
372
|
-
end
|
|
373
|
-
|
|
374
|
-
def create_progressbar
|
|
375
|
-
@progresswin = Dialog.new("Parsing file...", self, Dialog::MODAL)
|
|
376
|
-
@progresswin.vbox.add(@progressbar = ProgressBar.new.set_pulse_step(0.05))
|
|
377
|
-
@progresswin.show_all
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
def close_progressbar
|
|
381
|
-
@progresswin.close
|
|
382
|
-
end
|
|
383
|
-
end
|
|
384
225
|
|
|
226
|
+
def serialize
|
|
227
|
+
dialog = Gtk::FileChooserDialog.new("Save dump file",
|
|
228
|
+
self,
|
|
229
|
+
Gtk::FileChooser::ACTION_SAVE,
|
|
230
|
+
nil,
|
|
231
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
|
232
|
+
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT]
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
dialog.do_overwrite_confirmation = true
|
|
236
|
+
dialog.current_folder = File.join(Dir.pwd, "dumps")
|
|
237
|
+
dialog.current_name = "#{File.basename(@filename)}.dmp.gz"
|
|
238
|
+
dialog.filter = FileFilter.new.add_pattern("*.gz")
|
|
239
|
+
|
|
240
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
|
241
|
+
begin
|
|
242
|
+
@opened.serialize(dialog.filename)
|
|
243
|
+
rescue
|
|
244
|
+
error("Error: #{$!.message}")
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
dialog.destroy
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def save_data(caption, data, filename = "")
|
|
252
|
+
dialog = Gtk::FileChooserDialog.new(caption,
|
|
253
|
+
self,
|
|
254
|
+
Gtk::FileChooser::ACTION_SAVE,
|
|
255
|
+
nil,
|
|
256
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
|
257
|
+
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT]
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
dialog.do_overwrite_confirmation = true
|
|
261
|
+
dialog.current_name = File.basename(filename)
|
|
262
|
+
dialog.filter = FileFilter.new.add_pattern("*.*")
|
|
263
|
+
|
|
264
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
|
265
|
+
begin
|
|
266
|
+
File.binwrite(dialog.filename, data)
|
|
267
|
+
rescue
|
|
268
|
+
error("Error: #{$!.message}")
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
dialog.destroy
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def save
|
|
276
|
+
dialog = Gtk::FileChooserDialog.new("Save PDF file",
|
|
277
|
+
self,
|
|
278
|
+
Gtk::FileChooser::ACTION_SAVE,
|
|
279
|
+
nil,
|
|
280
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
|
281
|
+
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT]
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
dialog.filter = FileFilter.new.add_pattern("*.acrodata").add_pattern("*.pdf").add_pattern("*.fdf")
|
|
285
|
+
|
|
286
|
+
folder = File.dirname(@filename)
|
|
287
|
+
dialog.set_current_folder(folder)
|
|
288
|
+
|
|
289
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
|
290
|
+
begin
|
|
291
|
+
@opened.save(dialog.filename)
|
|
292
|
+
rescue
|
|
293
|
+
error("#{$!.class}: #{$!.message}\n#{$!.backtrace.join($/)}")
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
dialog.destroy
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def save_dot
|
|
301
|
+
dialog = Gtk::FileChooserDialog.new("Save dot file",
|
|
302
|
+
self,
|
|
303
|
+
Gtk::FileChooser::ACTION_SAVE,
|
|
304
|
+
nil,
|
|
305
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
|
306
|
+
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT]
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
dialog.filter = FileFilter.new.add_pattern("*.dot")
|
|
310
|
+
|
|
311
|
+
folder = File.dirname(@filename)
|
|
312
|
+
dialog.set_current_folder(folder)
|
|
313
|
+
|
|
314
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
|
315
|
+
begin
|
|
316
|
+
@opened.export_to_graph(dialog.filename)
|
|
317
|
+
rescue
|
|
318
|
+
error("Error: #{$!.message}")
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
dialog.destroy
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def save_graphml
|
|
326
|
+
dialog = Gtk::FileChooserDialog.new("Save GraphML file",
|
|
327
|
+
self,
|
|
328
|
+
Gtk::FileChooser::ACTION_SAVE,
|
|
329
|
+
nil,
|
|
330
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
|
331
|
+
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT]
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
dialog.filter = FileFilter.new.add_pattern("*.graphml")
|
|
335
|
+
|
|
336
|
+
folder = File.dirname(@filename)
|
|
337
|
+
dialog.set_current_folder(folder)
|
|
338
|
+
|
|
339
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
|
340
|
+
begin
|
|
341
|
+
@opened.export_to_graphml(dialog.filename)
|
|
342
|
+
rescue
|
|
343
|
+
error("Error: #{$!.message}")
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
dialog.destroy
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
private
|
|
351
|
+
|
|
352
|
+
def parse_file(path)
|
|
353
|
+
update_bar = lambda { |obj|
|
|
354
|
+
@progressbar.pulse if @progressbar
|
|
355
|
+
Gtk.main_iteration while Gtk.events_pending?
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
prompt_passwd = lambda {
|
|
359
|
+
passwd = ""
|
|
360
|
+
|
|
361
|
+
dialog = Gtk::Dialog.new(
|
|
362
|
+
"This document is encrypted",
|
|
363
|
+
nil,
|
|
364
|
+
Gtk::Dialog::MODAL,
|
|
365
|
+
[ Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK ],
|
|
366
|
+
[ Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL ]
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
dialog.set_default_response(Gtk::Dialog::RESPONSE_OK)
|
|
370
|
+
|
|
371
|
+
label = Gtk::Label.new("Please enter password:")
|
|
372
|
+
entry = Gtk::Entry.new
|
|
373
|
+
entry.signal_connect('activate') {
|
|
374
|
+
dialog.response(Gtk::Dialog::RESPONSE_OK)
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
dialog.vbox.add(label)
|
|
378
|
+
dialog.vbox.add(entry)
|
|
379
|
+
dialog.show_all
|
|
380
|
+
|
|
381
|
+
dialog.run do |response|
|
|
382
|
+
if response == Gtk::Dialog::RESPONSE_OK
|
|
383
|
+
passwd = entry.text
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
dialog.destroy
|
|
388
|
+
return passwd
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
#
|
|
392
|
+
# Try to detect the file type of the document.
|
|
393
|
+
# Fallback to PDF if none is found.
|
|
394
|
+
#
|
|
395
|
+
file_type = detect_file_type(path)
|
|
396
|
+
if file_type.nil?
|
|
397
|
+
file_type = Origami::PDF
|
|
398
|
+
force_mode = true
|
|
399
|
+
else
|
|
400
|
+
force_mode = false
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
file_type.read(path,
|
|
404
|
+
verbosity: Origami::Parser::VERBOSE_TRACE,
|
|
405
|
+
ignore_errors: false,
|
|
406
|
+
callback: update_bar,
|
|
407
|
+
prompt_password: prompt_passwd,
|
|
408
|
+
force: force_mode
|
|
409
|
+
)
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
def detect_file_type(path)
|
|
413
|
+
supported_types = [ Origami::PDF, Origami::FDF, Origami::PPKLite ]
|
|
414
|
+
|
|
415
|
+
File.open(path, 'rb') do |file|
|
|
416
|
+
data = file.read(128)
|
|
417
|
+
|
|
418
|
+
supported_types.each do |type|
|
|
419
|
+
return type if data.match(type::Header::MAGIC)
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
nil
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def create_progressbar
|
|
427
|
+
@progresswin = Dialog.new("Parsing file...", self, Dialog::MODAL)
|
|
428
|
+
@progresswin.vbox.add(@progressbar = ProgressBar.new.set_pulse_step(0.05))
|
|
429
|
+
@progresswin.show_all
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def close_progressbar
|
|
433
|
+
@progresswin.close
|
|
434
|
+
end
|
|
435
|
+
end
|
|
385
436
|
end
|