origami 1.2.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -0
  3. data/README.md +112 -0
  4. data/bin/config/pdfcop.conf.yml +232 -233
  5. data/bin/gui/about.rb +27 -37
  6. data/bin/gui/config.rb +108 -117
  7. data/bin/gui/file.rb +416 -365
  8. data/bin/gui/gtkhex.rb +1138 -1153
  9. data/bin/gui/hexview.rb +55 -57
  10. data/bin/gui/imgview.rb +48 -51
  11. data/bin/gui/menu.rb +388 -386
  12. data/bin/gui/properties.rb +114 -130
  13. data/bin/gui/signing.rb +571 -617
  14. data/bin/gui/textview.rb +77 -95
  15. data/bin/gui/treeview.rb +382 -387
  16. data/bin/gui/walker.rb +227 -232
  17. data/bin/gui/xrefs.rb +56 -60
  18. data/bin/pdf2pdfa +53 -57
  19. data/bin/pdf2ruby +212 -228
  20. data/bin/pdfcop +338 -348
  21. data/bin/pdfdecompress +58 -65
  22. data/bin/pdfdecrypt +56 -60
  23. data/bin/pdfencrypt +75 -80
  24. data/bin/pdfexplode +185 -182
  25. data/bin/pdfextract +201 -218
  26. data/bin/pdfmetadata +83 -82
  27. data/bin/pdfsh +4 -5
  28. data/bin/pdfwalker +1 -2
  29. data/bin/shell/.irbrc +45 -82
  30. data/bin/shell/console.rb +105 -130
  31. data/bin/shell/hexdump.rb +40 -64
  32. data/examples/README.md +34 -0
  33. data/examples/attachments/attachment.rb +38 -0
  34. data/examples/attachments/nested_document.rb +51 -0
  35. data/examples/encryption/encryption.rb +28 -0
  36. data/{samples/actions/triggerevents/trigger.rb → examples/events/events.rb} +13 -16
  37. data/examples/flash/flash.rb +37 -0
  38. data/{samples → examples}/flash/helloworld.swf +0 -0
  39. data/examples/forms/javascript.rb +54 -0
  40. data/examples/forms/xfa.rb +115 -0
  41. data/examples/javascript/hello_world.rb +22 -0
  42. data/examples/javascript/js_emulation.rb +54 -0
  43. data/examples/loop/goto.rb +32 -0
  44. data/examples/loop/named.rb +33 -0
  45. data/examples/signature/signature.rb +65 -0
  46. data/examples/uri/javascript.rb +56 -0
  47. data/examples/uri/open-uri.rb +21 -0
  48. data/examples/uri/submitform.rb +47 -0
  49. data/lib/origami.rb +29 -42
  50. data/lib/origami/3d.rb +350 -225
  51. data/lib/origami/acroform.rb +262 -288
  52. data/lib/origami/actions.rb +268 -288
  53. data/lib/origami/annotations.rb +697 -722
  54. data/lib/origami/array.rb +258 -184
  55. data/lib/origami/boolean.rb +74 -84
  56. data/lib/origami/catalog.rb +397 -434
  57. data/lib/origami/collections.rb +144 -0
  58. data/lib/origami/destinations.rb +233 -194
  59. data/lib/origami/dictionary.rb +253 -232
  60. data/lib/origami/encryption.rb +1274 -1243
  61. data/lib/origami/export.rb +232 -268
  62. data/lib/origami/extensions/fdf.rb +307 -220
  63. data/lib/origami/extensions/ppklite.rb +368 -435
  64. data/lib/origami/filespec.rb +197 -0
  65. data/lib/origami/filters.rb +301 -295
  66. data/lib/origami/filters/ascii.rb +177 -180
  67. data/lib/origami/filters/ccitt.rb +528 -535
  68. data/lib/origami/filters/crypt.rb +26 -35
  69. data/lib/origami/filters/dct.rb +46 -52
  70. data/lib/origami/filters/flate.rb +95 -94
  71. data/lib/origami/filters/jbig2.rb +49 -55
  72. data/lib/origami/filters/jpx.rb +38 -44
  73. data/lib/origami/filters/lzw.rb +189 -183
  74. data/lib/origami/filters/predictors.rb +221 -235
  75. data/lib/origami/filters/runlength.rb +103 -104
  76. data/lib/origami/font.rb +173 -186
  77. data/lib/origami/functions.rb +67 -81
  78. data/lib/origami/graphics.rb +25 -21
  79. data/lib/origami/graphics/colors.rb +178 -187
  80. data/lib/origami/graphics/instruction.rb +79 -85
  81. data/lib/origami/graphics/path.rb +142 -148
  82. data/lib/origami/graphics/patterns.rb +160 -167
  83. data/lib/origami/graphics/render.rb +43 -50
  84. data/lib/origami/graphics/state.rb +138 -153
  85. data/lib/origami/graphics/text.rb +188 -205
  86. data/lib/origami/graphics/xobject.rb +819 -815
  87. data/lib/origami/header.rb +63 -78
  88. data/lib/origami/javascript.rb +596 -597
  89. data/lib/origami/linearization.rb +285 -290
  90. data/lib/origami/metadata.rb +139 -148
  91. data/lib/origami/name.rb +112 -148
  92. data/lib/origami/null.rb +53 -62
  93. data/lib/origami/numeric.rb +162 -175
  94. data/lib/origami/obfuscation.rb +186 -174
  95. data/lib/origami/object.rb +593 -573
  96. data/lib/origami/outline.rb +42 -47
  97. data/lib/origami/outputintents.rb +73 -82
  98. data/lib/origami/page.rb +703 -592
  99. data/lib/origami/parser.rb +238 -290
  100. data/lib/origami/parsers/fdf.rb +41 -33
  101. data/lib/origami/parsers/pdf.rb +75 -95
  102. data/lib/origami/parsers/pdf/lazy.rb +137 -0
  103. data/lib/origami/parsers/pdf/linear.rb +64 -66
  104. data/lib/origami/parsers/ppklite.rb +34 -70
  105. data/lib/origami/pdf.rb +1030 -1005
  106. data/lib/origami/reference.rb +102 -102
  107. data/lib/origami/signature.rb +591 -609
  108. data/lib/origami/stream.rb +668 -551
  109. data/lib/origami/string.rb +397 -373
  110. data/lib/origami/template/patterns.rb +56 -0
  111. data/lib/origami/template/widgets.rb +151 -0
  112. data/lib/origami/trailer.rb +144 -158
  113. data/lib/origami/tree.rb +62 -0
  114. data/lib/origami/version.rb +23 -0
  115. data/lib/origami/webcapture.rb +88 -79
  116. data/lib/origami/xfa.rb +2863 -2882
  117. data/lib/origami/xreftable.rb +472 -384
  118. data/test/dataset/calc.pdf +85 -0
  119. data/test/dataset/crypto.pdf +82 -0
  120. data/test/dataset/empty.pdf +49 -0
  121. data/test/test_actions.rb +27 -0
  122. data/test/test_annotations.rb +90 -0
  123. data/test/test_pages.rb +31 -0
  124. data/test/test_pdf.rb +16 -0
  125. data/test/test_pdf_attachment.rb +34 -0
  126. data/test/test_pdf_create.rb +24 -0
  127. data/test/test_pdf_encrypt.rb +95 -0
  128. data/test/test_pdf_parse.rb +96 -0
  129. data/test/test_pdf_sign.rb +58 -0
  130. data/test/test_streams.rb +182 -0
  131. data/test/test_xrefs.rb +67 -0
  132. metadata +88 -58
  133. data/README +0 -67
  134. data/bin/pdf2graph +0 -121
  135. data/bin/pdfcocoon +0 -104
  136. data/lib/origami/file.rb +0 -233
  137. data/samples/README.txt +0 -45
  138. data/samples/actions/launch/calc.rb +0 -87
  139. data/samples/actions/launch/winparams.rb +0 -22
  140. data/samples/actions/loop/loopgoto.rb +0 -24
  141. data/samples/actions/loop/loopnamed.rb +0 -21
  142. data/samples/actions/named/named.rb +0 -31
  143. data/samples/actions/samba/smbrelay.rb +0 -26
  144. data/samples/actions/webbug/submitform.js +0 -26
  145. data/samples/actions/webbug/webbug-browser.rb +0 -68
  146. data/samples/actions/webbug/webbug-js.rb +0 -67
  147. data/samples/actions/webbug/webbug-reader.rb +0 -90
  148. data/samples/attachments/attach.rb +0 -40
  149. data/samples/attachments/attached.txt +0 -1
  150. data/samples/crypto/crypto.rb +0 -28
  151. data/samples/digsig/signed.rb +0 -46
  152. data/samples/exploits/cve-2008-2992-utilprintf.rb +0 -87
  153. data/samples/exploits/cve-2009-0927-geticon.rb +0 -65
  154. data/samples/exploits/exploit_customdictopen.rb +0 -55
  155. data/samples/exploits/getannots.rb +0 -69
  156. data/samples/flash/flash.rb +0 -31
  157. data/samples/javascript/attached.txt +0 -1
  158. data/samples/javascript/js.rb +0 -52
  159. data/templates/patterns.rb +0 -66
  160. data/templates/widgets.rb +0 -173
  161. data/templates/xdp.rb +0 -92
  162. data/test/ts_pdf.rb +0 -50
@@ -1,25 +1,20 @@
1
1
  =begin
2
2
 
3
- = File
4
- properties.rb
5
-
6
- = Info
7
- This file is part of PDF Walker, a graphical PDF file browser
8
- Copyright (C) 2010 Guillaume Delugré <guillaume AT security-labs DOT org>
9
- All right reserved.
10
-
11
- PDF Walker is free software: you can redistribute it and/or modify
12
- it under the terms of the GNU 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
- PDF Walker 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 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
 
@@ -27,118 +22,107 @@ require 'digest/md5'
27
22
 
28
23
  module PDFWalker
29
24
 
30
- class Walker < Window
31
-
32
- def display_file_properties
33
- if @opened
34
- prop = Properties.new(self, @opened)
35
- end
36
- end
37
-
38
- class Properties < Dialog
39
-
40
- @@acrobat_versions =
41
- {
42
- 1.0 => "1.x",
43
- 1.1 => "2.x",
44
- 1.2 => "3.x",
45
- 1.3 => "4.x",
46
- 1.4 => "5.x",
47
- 1.5 => "6.x",
48
- 1.6 => "7.x",
49
- 1.7 => "8.x / 9.x / 10.x"
50
- }
51
-
52
- def initialize(parent, pdf)
53
- super("Document properties", parent, Dialog::MODAL, [Stock::CLOSE, Dialog::RESPONSE_NONE])
54
-
55
- docframe = Frame.new(" File properties ")
56
- stat = File.stat(parent.filename)
57
-
58
- if RUBY_VERSION < '1.9'
59
- require 'iconv'
60
- i = Iconv.new("UTF-8//IGNORE//TRANSLIT", "ISO-8859-1")
61
-
62
- creation_date = i.iconv(stat.ctime.to_s)
63
- last_modified = i.iconv(stat.mtime.to_s)
64
- fd = File.open(parent.filename, 'rb')
65
- md5sum = Digest::MD5.hexdigest(fd.read)
66
- fd.close
67
- i.close
68
- else
69
- creation_date = stat.ctime.to_s.encode("utf-8", :invalid => :replace, :undef => :replace)
70
- last_modified = stat.mtime.to_s.encode("utf-8", :invalid => :replace, :undef => :replace)
71
- md5sum = Digest::MD5.hexdigest(File.binread(parent.filename))
72
- end
73
-
74
- labels =
75
- [
76
- [ "Filename:", parent.filename ],
77
- [ "File size:", "#{File.size(parent.filename)} bytes" ],
78
- [ "MD5:", md5sum ],
79
- [ "Read-only:", "#{not stat.writable?}" ],
80
- [ "Creation date:", creation_date ],
81
- [ "Last modified:", last_modified ]
82
- ]
83
-
84
- doctable = Table.new(labels.size + 1, 3)
85
-
86
- row = 0
87
- labels.each do |name, value|
88
-
89
- doctable.attach(Label.new(name).set_alignment(1,0), 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
90
- doctable.attach(Label.new(value).set_alignment(0,0), 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
91
-
92
- row = row.succ
25
+ class Walker < Window
26
+
27
+ def display_file_properties
28
+ Properties.new(self, @opened) if @opened
93
29
  end
94
-
95
- docframe.border_width = 5
96
- docframe.shadow_type = Gtk::SHADOW_IN
97
- docframe.add(doctable)
98
-
99
- pdfframe = Frame.new(" PDF properties ")
100
-
101
- labels =
102
- [
103
- [ "Version:", "#{pdf.header.to_f} (Acrobat #{ if pdf.header.to_f >= 1.0 and pdf.header.to_f <= 1.7 then @@acrobat_versions[pdf.header.to_f] else "unknown version" end})" ],
104
- [ "Number of revisions:", "#{pdf.revisions.size}" ],
105
- [ "Number of indirect objects:", "#{pdf.indirect_objects.size}" ],
106
- [ "Number of pages:", "#{pdf.pages.size}" ],
107
- [ "Is linearized:", "#{pdf.is_linearized?}" ],
108
- [ "Is encrypted:", "#{pdf.is_encrypted?}" ],
109
- [ "Is signed:", "#{pdf.is_signed?}" ],
110
- [ "Has usage rights:", "#{pdf.has_usage_rights?}"],
111
- [ "Contains Acroform:", "#{pdf.has_form?}" ],
112
- #[ "Contains XFA forms:", "#{pdf.has_xfa_forms?}" ]
113
- [ "Has document information:", "#{pdf.has_document_info?}" ],
114
- [ "Has metadata:", "#{pdf.has_metadata?}" ]
115
- ]
116
-
117
- pdftable = Table.new(labels.size + 1, 3)
118
-
119
- row = 0
120
- labels.each do |name, value|
121
-
122
- pdftable.attach(Label.new(name).set_alignment(1,0), 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK, 4, 4)
123
- pdftable.attach(Label.new(value).set_alignment(0,0), 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
124
-
125
- row = row.succ
30
+
31
+ class Properties < Dialog
32
+
33
+ @@acrobat_versions =
34
+ {
35
+ 1.0 => "1.x",
36
+ 1.1 => "2.x",
37
+ 1.2 => "3.x",
38
+ 1.3 => "4.x",
39
+ 1.4 => "5.x",
40
+ 1.5 => "6.x",
41
+ 1.6 => "7.x",
42
+ 1.7 => "8.x / 9.x / 10.x"
43
+ }
44
+
45
+ def initialize(parent, pdf)
46
+ super("Document properties", parent, Dialog::MODAL, [Stock::CLOSE, Dialog::RESPONSE_NONE])
47
+
48
+ docframe = Frame.new(" File properties ")
49
+ stat = File.stat(parent.filename)
50
+
51
+ creation_date = stat.ctime.to_s.encode("utf-8", :invalid => :replace, :undef => :replace)
52
+ last_modified = stat.mtime.to_s.encode("utf-8", :invalid => :replace, :undef => :replace)
53
+ md5sum = Digest::MD5.hexdigest(File.binread(parent.filename))
54
+
55
+ labels =
56
+ [
57
+ [ "Filename:", parent.filename ],
58
+ [ "File size:", "#{File.size(parent.filename)} bytes" ],
59
+ [ "MD5:", md5sum ],
60
+ [ "Read-only:", "#{not stat.writable?}" ],
61
+ [ "Creation date:", creation_date ],
62
+ [ "Last modified:", last_modified ]
63
+ ]
64
+
65
+ doctable = Table.new(labels.size + 1, 3)
66
+
67
+ row = 0
68
+ labels.each do |name, value|
69
+ doctable.attach(Label.new(name).set_alignment(1,0), 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
70
+ doctable.attach(Label.new(value).set_alignment(0,0), 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
71
+
72
+ row = row.succ
73
+ end
74
+
75
+ docframe.border_width = 5
76
+ docframe.shadow_type = Gtk::SHADOW_IN
77
+ docframe.add(doctable)
78
+
79
+ pdfframe = Frame.new(" PDF properties ")
80
+
81
+ pdf_version = pdf.header.to_f
82
+ if pdf_version >= 1.0 and pdf_version <= 1.7
83
+ acrobat_version = @@acrobat_versions[pdf_version]
84
+ else
85
+ acrobat_version = "unknown version"
86
+ end
87
+
88
+ labels =
89
+ [
90
+ [ "Version:", "#{pdf_version} (Acrobat #{acrobat_version})" ],
91
+ [ "Number of revisions:", "#{pdf.revisions.size}" ],
92
+ [ "Number of indirect objects:", "#{pdf.indirect_objects.size}" ],
93
+ [ "Number of pages:", "#{pdf.pages.count}" ],
94
+ [ "Linearized:", pdf.linearized? ? 'yes' : 'no' ],
95
+ [ "Encrypted:", pdf.encrypted? ? 'yes' : 'no' ],
96
+ [ "Signed:", pdf.signed? ? 'yes' : 'no' ],
97
+ [ "Has usage rights:", pdf.usage_rights? ? 'yes' : 'no' ],
98
+ [ "Form:", pdf.form? ? 'yes' : 'no' ],
99
+ [ "XFA form:", pdf.xfa_form? ? 'yes' : 'no' ],
100
+ [ "Document information:", pdf.document_info? ? 'yes' : 'no' ],
101
+ [ "Metadata:", pdf.metadata? ? 'yes' : 'no' ]
102
+ ]
103
+
104
+ pdftable = Table.new(labels.size + 1, 3)
105
+
106
+ row = 0
107
+ labels.each do |name, value|
108
+ pdftable.attach(Label.new(name).set_alignment(1,0), 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK, 4, 4)
109
+ pdftable.attach(Label.new(value).set_alignment(0,0), 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
110
+
111
+ row = row.succ
112
+ end
113
+
114
+ pdfframe.border_width = 5
115
+ pdfframe.shadow_type = Gtk::SHADOW_IN
116
+ pdfframe.add(pdftable)
117
+
118
+ vbox.add(docframe)
119
+ vbox.add(pdfframe)
120
+
121
+ signal_connect('response') { destroy }
122
+
123
+ show_all
124
+ end
126
125
  end
127
-
128
- pdfframe.border_width = 5
129
- pdfframe.shadow_type = Gtk::SHADOW_IN
130
- pdfframe.add(pdftable)
131
-
132
- vbox.add(docframe)
133
- vbox.add(pdfframe)
134
-
135
- signal_connect('response') { destroy }
136
-
137
- show_all
138
- end
139
-
140
126
  end
141
-
142
- end
143
127
 
144
128
  end
@@ -1,635 +1,589 @@
1
1
  =begin
2
2
 
3
- = File
4
- signing.rb
5
-
6
- = Info
7
- This file is part of PDF Walker, a graphical PDF file browser
8
- Copyright (C) 2010 Guillaume Delugré <guillaume AT security-labs DOT org>
9
- All right reserved.
10
-
11
- PDF Walker is free software: you can redistribute it and/or modify
12
- it under the terms of the GNU 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
- PDF Walker 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 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
- class Walker < Window
29
-
30
- def display_signing_wizard
31
-
32
- if @opened
33
- SignWizard.new(self, @opened)
34
- end
35
-
36
- end
37
-
38
- def display_usage_rights_wizard
39
-
40
- if @opened
41
- UsageRightsWizard.new(self, @opened)
42
- end
43
-
44
- end
45
-
46
- class UsageRightsWizard < Assistant
47
-
48
- def initialize(parent, pdf)
49
-
50
- super()
51
-
52
- @parent = parent
53
-
54
- @pkey, @cert = nil, nil
55
-
56
- create_intro_page
57
- create_rights_selection_page
58
- create_termination_page
59
-
60
- signal_connect('delete_event') { self.destroy }
61
- signal_connect('cancel') { self.destroy }
62
- signal_connect('close') { self.destroy }
63
-
64
- signal_connect('apply') {
65
-
66
- rights = []
67
-
68
- rights << UsageRights::Rights::DOCUMENT_FULLSAVE if @document_fullsave.active?
69
-
70
- rights << UsageRights::Rights::ANNOTS_CREATE if @annots_create.active?
71
- rights << UsageRights::Rights::ANNOTS_DELETE if @annots_delete.active?
72
- rights << UsageRights::Rights::ANNOTS_MODIFY if @annots_modify.active?
73
- rights << UsageRights::Rights::ANNOTS_COPY if @annots_copy.active?
74
- rights << UsageRights::Rights::ANNOTS_IMPORT if @annots_import.active?
75
- rights << UsageRights::Rights::ANNOTS_EXPORT if @annots_export.active?
76
- rights << UsageRights::Rights::ANNOTS_ONLINE if @annots_online.active?
77
- rights << UsageRights::Rights::ANNOTS_SUMMARYVIEW if @annots_sumview.active?
78
-
79
- rights << UsageRights::Rights::FORM_FILLIN if @form_fillin.active?
80
- rights << UsageRights::Rights::FORM_IMPORT if @form_import.active?
81
- rights << UsageRights::Rights::FORM_EXPORT if @form_export.active?
82
- rights << UsageRights::Rights::FORM_SUBMITSTANDALONE if @form_submit.active?
83
- rights << UsageRights::Rights::FORM_SPAWNTEMPLATE if @form_spawntemplate.active?
84
- rights << UsageRights::Rights::FORM_BARCODEPLAINTEXT if @form_barcode.active?
85
- rights << UsageRights::Rights::FORM_ONLINE if @form_online.active?
86
-
87
- rights << UsageRights::Rights::SIGNATURE_MODIFY if @signature_modify.active?
88
-
89
- rights << UsageRights::Rights::EF_CREATE if @ef_create.active?
90
- rights << UsageRights::Rights::EF_DELETE if @ef_delete.active?
91
- rights << UsageRights::Rights::EF_MODIFY if @ef_modify.active?
92
- rights << UsageRights::Rights::EF_IMPORT if @ef_import.active?
93
-
94
- begin
95
- pdf.enable_usage_rights(*rights)
96
-
97
- set_page_title(@lastpage, "Usage Rights have been enabled")
98
- @msg_status.text = "Usage Rights have been enabled for the current document.\n You should consider saving it now."
99
-
100
- @parent.reload
101
- rescue Exception => e
102
- puts e
103
- puts e.backtrace
104
-
105
- set_page_title(@lastpage, "Usage Rights have not been enabled")
106
- @msg_status.text = "An error occured during the signature process."
107
- end
108
- }
109
-
110
- show_all
111
-
112
- end
113
-
114
- private
115
-
116
- def create_intro_page
117
-
118
- intro = <<INTRO
119
- You are about to enable Usage Rights for the current PDF document.
120
- To enable these features, you need to have an Adobe public/private key pair in your possession.
121
-
122
- Make sure you have adobe.crt and adobe.key located in the current directory.
123
- INTRO
124
-
125
- vbox = VBox.new(false, 5)
126
- vbox.set_border_width(5)
127
-
128
- lbl = Label.new(intro).set_justify(Gtk::JUSTIFY_LEFT).set_wrap(true)
129
-
130
- vbox.pack_start(lbl, true, true, 0)
131
-
132
- append_page(vbox)
133
- set_page_title(vbox, "Usage Rights Wizard")
134
- set_page_type(vbox, Assistant::PAGE_INTRO)
135
- set_page_complete(vbox, true)
136
-
137
- end
138
-
139
- def create_rights_selection_page
140
-
141
- vbox = VBox.new(false, 5)
142
-
143
- docframe = Frame.new(" Document ")
144
- docframe.border_width = 5
145
- docframe.shadow_type = Gtk::SHADOW_IN
146
-
147
- doctable = Table.new(1, 2)
148
- doctable.attach(@document_fullsave = CheckButton.new("Full Save").set_active(true), 0, 1, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
149
- docframe.add(doctable)
150
-
151
- annotsframe = Frame.new(" Annotations ")
152
- annotsframe.border_width = 5
153
- annotsframe.shadow_type = Gtk::SHADOW_IN
154
-
155
- annotstable = Table.new(4,2)
156
- annots =
157
- [
158
- [ @annots_create = CheckButton.new("Create").set_active(true), @annots_import = CheckButton.new("Import").set_active(true) ],
159
- [ @annots_delete = CheckButton.new("Delete").set_active(true), @annots_export = CheckButton.new("Export").set_active(true) ],
160
- [ @annots_modify = CheckButton.new("Modify").set_active(true), @annots_online = CheckButton.new("Online").set_active(true) ],
161
- [ @annots_copy = CheckButton.new("Copy").set_active(true), @annots_sumview = CheckButton.new("Summary View").set_active(true) ]
162
- ]
163
-
164
- tt = Tooltips.new.enable
165
- tt.set_tip(@annots_create, "test", "")
166
-
167
- row = 0
168
- annots.each do |col1, col2|
169
-
170
- annotstable.attach(col1, 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
171
- annotstable.attach(col2, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
172
-
173
- row = row.succ
174
- end
175
-
176
- annotsframe.add(annotstable)
177
-
178
- formframe = Frame.new(" Forms ")
179
- formframe.border_width = 5
180
- formframe.shadow_type = Gtk::SHADOW_IN
181
-
182
- formtable = Table.new(4,2)
183
- forms =
184
- [
185
- [ @form_fillin = CheckButton.new("Fill in").set_active(true), @form_spawntemplate = CheckButton.new("Spawn template").set_active(true) ],
186
- [ @form_import = CheckButton.new("Import").set_active(true), @form_barcode = CheckButton.new("Barcode plaintext").set_active(true) ],
187
- [ @form_export = CheckButton.new("Export").set_active(true), @form_online = CheckButton.new("Online").set_active(true) ],
188
- [ @form_submit = CheckButton.new("Submit stand-alone").set_active(true), nil ]
189
- ]
190
-
191
- row = 0
192
- forms.each do |col1, col2|
193
-
194
- formtable.attach(col1, 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
195
- formtable.attach(col2, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
196
-
197
- row = row.succ
198
- end
199
-
200
- formframe.add(formtable)
201
-
202
- signatureframe = Frame.new(" Signature ")
203
- signatureframe.border_width = 5
204
- signatureframe.shadow_type = Gtk::SHADOW_IN
205
-
206
- signaturetable = Table.new(1, 2)
207
- signaturetable.attach(@signature_modify = CheckButton.new("Modify").set_active(true), 0, 1, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
208
- signatureframe.add(signaturetable)
209
-
210
- efframe = Frame.new(" Embedded files ")
211
- efframe.border_width = 5
212
- efframe.shadow_type = Gtk::SHADOW_IN
213
-
214
- eftable = Table.new(2,2)
215
- efitems =
216
- [
217
- [ @ef_create = CheckButton.new("Create").set_active(true), @ef_modify = CheckButton.new("Modify").set_active(true) ],
218
- [ @ef_delete = CheckButton.new("Delete").set_active(true), @ef_import = CheckButton.new("Import").set_active(true) ]
219
- ]
220
-
221
- row = 0
222
- efitems.each do |col1, col2|
223
-
224
- eftable.attach(col1, 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
225
- eftable.attach(col2, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
226
-
227
- row = row.succ
23
+ class Walker < Window
24
+
25
+ def display_signing_wizard
26
+ SignWizard.new(self, @opened) if @opened
228
27
  end
229
-
230
- efframe.add(eftable)
231
-
232
- vbox.add(docframe)
233
- vbox.add(annotsframe)
234
- vbox.add(formframe)
235
- vbox.add(signatureframe)
236
- vbox.add(efframe)
237
-
238
- append_page(vbox)
239
- set_page_title(vbox, "Select Usage Rights to enable")
240
- set_page_type(vbox, Assistant::PAGE_CONFIRM)
241
- set_page_complete(vbox, true)
242
-
243
- end
244
-
245
- def create_termination_page
246
-
247
- @lastpage = VBox.new(false, 5)
248
-
249
- @msg_status = Label.new
250
- @lastpage.pack_start(@msg_status, true, true, 0)
251
-
252
- append_page(@lastpage)
253
- set_page_title(@lastpage, "Usage Rights have not been enabled")
254
- set_page_type(@lastpage, Assistant::PAGE_SUMMARY)
255
-
256
- end
257
-
258
- end
259
-
260
- class SignWizard < Assistant
261
-
262
- INTRO_PAGE = 0
263
- KEY_SELECT_PAGE = 1
264
- PKCS12_IMPORT_PAGE = 2
265
- KEYPAIR_IMPORT_PAGE = 3
266
- SIGNATURE_INFO_PAGE = 4
267
- SIGNATURE_RESULT_PAGE = 5
268
-
269
- def initialize(parent, pdf)
270
-
271
- super()
272
-
273
- @parent = parent
274
-
275
- @pkey, @cert, @ca = nil, nil, []
276
-
277
- create_intro_page
278
- create_key_selection_page
279
- create_pkcs12_import_page
280
- create_keypair_import_page
281
- create_signature_info_page
282
- create_termination_page
283
-
284
- set_forward_page_func { |current_page|
285
- case current_page
286
- when KEY_SELECT_PAGE
287
- if @p12button.active? then PKCS12_IMPORT_PAGE else KEYPAIR_IMPORT_PAGE end
288
-
289
- when PKCS12_IMPORT_PAGE, KEYPAIR_IMPORT_PAGE
290
- SIGNATURE_INFO_PAGE
291
-
292
- else current_page.succ
293
- end
294
- }
295
-
296
- signal_connect('delete_event') { self.destroy }
297
- signal_connect('cancel') { self.destroy }
298
- signal_connect('close') { self.destroy }
299
-
300
- signal_connect('apply') {
301
-
302
- location = @location.text.empty? ? nil : @location.text
303
- contact = @email.text.empty? ? nil : @email.text
304
- reason = @reason.text.empty? ? nil : @reason.text
305
-
306
- begin
307
- pdf.sign(@cert, @pkey, @ca, nil, location, contact, reason)
308
-
309
- set_page_title(@lastpage, "Document has been signed")
310
- @msg_status.text = "The document has been signed.\n You should consider saving it now."
311
-
312
- @parent.reload
313
- rescue Exception => e
314
- puts e
315
- puts e.backtrace
316
-
317
- set_page_title(@lastpage, "Document has not been signed")
318
- @msg_status.text = "An error occured during the signature process."
319
- end
320
- }
321
-
322
- show_all
323
-
324
- end
325
-
326
- private
327
-
328
- def create_intro_page
329
-
330
- intro = <<INTRO
331
- You are about to sign the current PDF document.
332
- Once the document will be signed, no further modification will be allowed.
333
-
334
- The signature process is based on assymetric cryptography, so you will basically need a public/private RSA key pair (between 1024 and 4096 bits).
335
- INTRO
336
-
337
- vbox = VBox.new(false, 5)
338
- vbox.set_border_width(5)
339
-
340
- lbl = Label.new(intro).set_justify(Gtk::JUSTIFY_LEFT).set_wrap(true)
341
-
342
- vbox.pack_start(lbl, true, true, 0)
343
-
344
- append_page(vbox)
345
- set_page_title(vbox, "Signature Wizard")
346
- set_page_type(vbox, Assistant::PAGE_INTRO)
347
- set_page_complete(vbox, true)
348
-
349
- end
350
-
351
- def create_key_selection_page
352
-
353
- vbox = VBox.new(false, 5)
354
-
355
- @p12button = RadioButton.new("Import keys from a PKCS12 container")
356
- @rawbutton = RadioButton.new(@p12button, "Import keys from separate PEM/DER encoded files")
357
-
358
- vbox.pack_start(@p12button, true, true, 0)
359
- vbox.pack_start(@rawbutton, true, true, 0)
360
-
361
- append_page(vbox)
362
- set_page_title(vbox, "Choose a key importation method")
363
- set_page_type(vbox, Assistant::PAGE_CONTENT)
364
- set_page_complete(vbox, true)
365
-
366
- end
367
-
368
- def create_pkcs12_import_page
369
-
370
- def get_passwd
371
-
372
- dialog = Dialog.new("Enter passphrase",
373
- @parent,
374
- Dialog::MODAL,
375
- [Stock::OK, Dialog::RESPONSE_OK]
376
- )
377
-
378
- pwd_entry = Entry.new.set_visibility(false).show
379
-
380
- dialog.vbox.pack_start(pwd_entry, true, true, 0)
381
-
382
- pwd = (dialog.run == Dialog::RESPONSE_OK) ? pwd_entry.text : ""
383
-
384
- dialog.destroy
385
-
386
- return pwd
387
-
28
+
29
+ def display_usage_rights_wizard
30
+ UsageRightsWizard.new(self, @opened) if @opened
388
31
  end
389
-
390
- def open_file_dialog(page)
391
-
392
- dialog = FileChooserDialog.new("Open PKCS12 container",
393
- @parent,
394
- FileChooser::ACTION_OPEN,
395
- nil,
396
- [Stock::CANCEL, Dialog::RESPONSE_CANCEL],
397
- [Stock::OPEN, Dialog::RESPONSE_ACCEPT])
398
- filter = FileFilter.new
399
- filter.add_pattern("*.pfx")
400
- filter.add_pattern("*.p12")
401
-
402
- dialog.filter = filter
403
-
404
- if dialog.run == Dialog::RESPONSE_ACCEPT
405
-
406
- begin
407
- p12 = OpenSSL::PKCS12::PKCS12.new(File.open(dialog.filename, 'r').binmode.read, get_passwd)
408
-
409
- if not p12.key.is_a?(OpenSSL::PKey::RSA) then raise TypeError end
410
- if not p12.certificate.is_a?(OpenSSL::X509::Certificate) then raise TypeError end
411
-
412
- @pkey = p12.key
413
- @cert = p12.certificate
414
- @ca = p12.ca_certs
415
-
416
- @p12filename.set_text(dialog.filename)
417
- set_page_complete(page, true)
418
-
419
- rescue Exception => e
420
- puts e.backtrace
421
- error = MessageDialog.new(@parent,
422
- Dialog::MODAL,
423
- Gtk::MessageDialog::ERROR,
424
- Gtk::MessageDialog::BUTTONS_CLOSE,
425
- "Error loading file '#{File.basename(dialog.filename)}'")
426
- error.run
427
- error.destroy
428
-
429
- @pkey, @cert, @ca = nil, nil, []
430
- @p12filename.text = ""
431
- set_page_complete(page, false)
432
-
32
+
33
+ module SignatureDialogs
34
+ private
35
+
36
+ def open_private_key_dialog(page)
37
+ dialog = FileChooserDialog.new("Choose a private RSA key",
38
+ @parent,
39
+ FileChooser::ACTION_OPEN,
40
+ nil,
41
+ [Stock::CANCEL, Dialog::RESPONSE_CANCEL],
42
+ [Stock::OPEN, Dialog::RESPONSE_ACCEPT])
43
+
44
+ filter = FileFilter.new
45
+ filter.add_pattern("*.key")
46
+ filter.add_pattern("*.pem")
47
+ filter.add_pattern("*.der")
48
+
49
+ dialog.set_filter(filter)
50
+
51
+ if dialog.run == Dialog::RESPONSE_ACCEPT
52
+ begin
53
+ @pkey = OpenSSL::PKey::RSA.new(File.binread(dialog.filename))
54
+
55
+ @pkeyfilename.set_text(dialog.filename)
56
+ set_page_complete(page, true) if @cert
57
+ rescue
58
+ @parent.error("Error loading file '#{File.basename(dialog.filename)}'")
59
+
60
+ @pkey = nil
61
+ @pkeyfilename.text = ""
62
+ set_page_complete(page, false)
63
+ ensure
64
+ @ca = [] # Shall be added to the GUI
65
+ end
66
+ end
67
+
68
+ dialog.destroy
433
69
  end
434
-
435
- end
436
-
437
- dialog.destroy
438
-
439
- end
440
-
441
- vbox = VBox.new(false, 5)
442
-
443
- hbox = HBox.new(false, 5)
444
- vbox.pack_start(hbox, true, false, 10)
445
-
446
- @p12filename = Entry.new.set_editable(false).set_sensitive(false)
447
- choosebtn = Button.new(Gtk::Stock::OPEN)
448
-
449
- choosebtn.signal_connect('clicked') { open_file_dialog(vbox) }
450
-
451
- hbox.pack_start(@p12filename, true, true, 5)
452
- hbox.pack_start(choosebtn, false, false, 5)
453
-
454
- append_page(vbox)
455
- set_page_title(vbox, "Import a PKCS12 container")
456
- set_page_type(vbox, Assistant::PAGE_CONTENT)
457
-
458
- end
459
-
460
- def create_keypair_import_page
461
-
462
- def open_pkey_dialog(page)
463
-
464
- dialog = FileChooserDialog.new("Choose a private RSA key",
465
- @parent,
466
- FileChooser::ACTION_OPEN,
467
- nil,
468
- [Stock::CANCEL, Dialog::RESPONSE_CANCEL],
469
- [Stock::OPEN, Dialog::RESPONSE_ACCEPT])
470
- filter = FileFilter.new
471
- filter.add_pattern("*.key")
472
- filter.add_pattern("*.pem")
473
- filter.add_pattern("*.der")
474
-
475
- dialog.set_filter(filter)
476
-
477
- if dialog.run == Dialog::RESPONSE_ACCEPT
478
-
479
- begin
480
- @pkey = OpenSSL::PKey::RSA.new(File.open(dialog.filename, 'r').binmode.read)
481
-
482
- @pkeyfilename.set_text(dialog.filename)
483
- if @cert then set_page_complete(page, true) end
484
-
485
- rescue Exception => e
486
- puts e.backtrace
487
- error = MessageDialog.new(@parent,
488
- Dialog::MODAL,
489
- Gtk::MessageDialog::ERROR,
490
- Gtk::MessageDialog::BUTTONS_CLOSE,
491
- "Error loading file '#{File.basename(dialog.filename)}'")
492
- error.run
493
- error.destroy
494
-
495
- @pkey = nil
496
- @pkeyfilename.text = ""
497
- set_page_complete(page, false)
498
-
499
- ensure
500
- @ca = [] # Shall be added to the GUI
70
+
71
+ def open_certificate_dialog(page)
72
+ dialog = FileChooserDialog.new("Choose a x509 certificate",
73
+ @parent,
74
+ FileChooser::ACTION_OPEN,
75
+ nil,
76
+ [Stock::CANCEL, Dialog::RESPONSE_CANCEL],
77
+ [Stock::OPEN, Dialog::RESPONSE_ACCEPT])
78
+ filter = FileFilter.new
79
+ filter.add_pattern("*.crt")
80
+ filter.add_pattern("*.cer")
81
+ filter.add_pattern("*.pem")
82
+ filter.add_pattern("*.der")
83
+
84
+ dialog.set_filter(filter)
85
+
86
+ if dialog.run == Dialog::RESPONSE_ACCEPT
87
+ begin
88
+ @cert = OpenSSL::X509::Certificate.new(File.binread(dialog.filename))
89
+
90
+ @certfilename.set_text(dialog.filename)
91
+ if @pkey then set_page_complete(page, true) end
92
+
93
+ rescue
94
+ @parent.error("Error loading file '#{File.basename(dialog.filename)}'")
95
+
96
+ @cert = nil
97
+ @certfilename.text = ""
98
+ set_page_complete(page, false)
99
+ ensure
100
+ @ca = [] # Shall be added to the GUI
101
+ end
102
+ end
103
+
104
+ dialog.destroy
501
105
  end
502
-
503
- end
504
-
505
- dialog.destroy
506
-
507
- end
508
-
509
- def open_cert_dialog(page)
510
-
511
- dialog = FileChooserDialog.new("Choose a private RSA key",
512
- @parent,
513
- FileChooser::ACTION_OPEN,
514
- nil,
515
- [Stock::CANCEL, Dialog::RESPONSE_CANCEL],
516
- [Stock::OPEN, Dialog::RESPONSE_ACCEPT])
517
- filter = FileFilter.new
518
- filter.add_pattern("*.crt")
519
- filter.add_pattern("*.cer")
520
- filter.add_pattern("*.pem")
521
- filter.add_pattern("*.der")
522
-
523
- dialog.set_filter(filter)
524
-
525
- if dialog.run == Dialog::RESPONSE_ACCEPT
526
-
527
- begin
528
- @cert = OpenSSL::X509::Certificate.new(File.open(dialog.filename, 'r').binmode.read)
529
-
530
- @certfilename.set_text(dialog.filename)
531
- if @pkey then set_page_complete(page, true) end
532
-
533
- rescue Exception => e
534
- puts e.backtrace
535
- error = MessageDialog.new(@parent,
536
- Dialog::MODAL,
537
- Gtk::MessageDialog::ERROR,
538
- Gtk::MessageDialog::BUTTONS_CLOSE,
539
- "Error loading file '#{File.basename(dialog.filename)}'")
540
- error.run
541
- error.destroy
542
-
543
- @cert = nil
544
- @certfilename.text = ""
545
- set_page_complete(page, false)
546
-
547
- ensure
548
- @ca = [] # Shall be added to the GUI
106
+
107
+ def open_pkcs12_file_dialog(page)
108
+
109
+ get_passwd = -> () do
110
+ dialog = Dialog.new("Enter passphrase",
111
+ @parent,
112
+ Dialog::MODAL,
113
+ [Stock::OK, Dialog::RESPONSE_OK]
114
+ )
115
+
116
+ pwd_entry = Entry.new.set_visibility(false).show
117
+ dialog.vbox.pack_start(pwd_entry, true, true, 0)
118
+
119
+ pwd = (dialog.run == Dialog::RESPONSE_OK) ? pwd_entry.text : ""
120
+
121
+ dialog.destroy
122
+ return pwd
123
+ end
124
+
125
+ dialog = FileChooserDialog.new("Open PKCS12 container",
126
+ @parent,
127
+ FileChooser::ACTION_OPEN,
128
+ nil,
129
+ [Stock::CANCEL, Dialog::RESPONSE_CANCEL],
130
+ [Stock::OPEN, Dialog::RESPONSE_ACCEPT])
131
+ filter = FileFilter.new
132
+ filter.add_pattern("*.pfx")
133
+ filter.add_pattern("*.p12")
134
+
135
+ dialog.filter = filter
136
+
137
+ if dialog.run == Dialog::RESPONSE_ACCEPT
138
+ begin
139
+ p12 = OpenSSL::PKCS12::PKCS12.new(File.binread(dialog.filename), get_passwd)
140
+
141
+ raise TypeError, "PKCS12 does not contain a RSA key" unless p12.key.is_a?(OpenSSL::PKey::RSA)
142
+ raise TypeError, "PKCS12 does not contain a x509 certificate" unless p12.certificate.is_a?(OpenSSL::X509::Certificate)
143
+
144
+ @pkey = p12.key
145
+ @cert = p12.certificate
146
+ @ca = p12.ca_certs
147
+
148
+ @p12filename.set_text(dialog.filename)
149
+ set_page_complete(page, true)
150
+ rescue
151
+ @parent.error("Error loading file '#{File.basename(dialog.filename)}'")
152
+
153
+ @pkey, @cert, @ca = nil, nil, []
154
+ @p12filename.text = ""
155
+ set_page_complete(page, false)
156
+
157
+ end
158
+ end
159
+
160
+ dialog.destroy
549
161
  end
550
-
551
- end
552
-
553
- dialog.destroy
554
-
555
162
  end
556
-
557
- labels =
558
- [
559
- [ "Private RSA key:", @pkeyfilename = Entry.new, pkeychoosebtn = Button.new(Gtk::Stock::OPEN) ],
560
- [ "Public certificate:", @certfilename = Entry.new, certchoosebtn = Button.new(Gtk::Stock::OPEN) ]
561
- ]
562
-
563
- row = 0
564
- table = Table.new(2, 3)
565
- labels.each do |lbl, entry, btn|
566
-
567
- entry.editable = entry.sensitive = false
568
-
569
- table.attach(Label.new(lbl).set_alignment(1,0), 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
570
- table.attach(entry, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
571
- table.attach(btn, 2, 3, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
572
-
573
- row = row.succ
163
+
164
+ class UsageRightsWizard < Assistant
165
+ include SignatureDialogs
166
+
167
+ def initialize(parent, pdf)
168
+ super()
169
+
170
+ @parent = parent
171
+ @pkey, @cert = nil, nil
172
+
173
+ create_intro_page
174
+ create_keypair_import_page
175
+ create_rights_selection_page
176
+ create_termination_page
177
+
178
+ signal_connect('delete_event') { self.destroy }
179
+ signal_connect('cancel') { self.destroy }
180
+ signal_connect('close') { self.destroy }
181
+
182
+ signal_connect('apply') {
183
+ rights = []
184
+
185
+ rights << Origami::UsageRights::Rights::DOCUMENT_FULLSAVE if @document_fullsave.active?
186
+
187
+ rights << Origami::UsageRights::Rights::ANNOTS_CREATE if @annots_create.active?
188
+ rights << Origami::UsageRights::Rights::ANNOTS_DELETE if @annots_delete.active?
189
+ rights << Origami::UsageRights::Rights::ANNOTS_MODIFY if @annots_modify.active?
190
+ rights << Origami::UsageRights::Rights::ANNOTS_COPY if @annots_copy.active?
191
+ rights << Origami::UsageRights::Rights::ANNOTS_IMPORT if @annots_import.active?
192
+ rights << Origami::UsageRights::Rights::ANNOTS_EXPORT if @annots_export.active?
193
+ rights << Origami::UsageRights::Rights::ANNOTS_ONLINE if @annots_online.active?
194
+ rights << Origami::UsageRights::Rights::ANNOTS_SUMMARYVIEW if @annots_sumview.active?
195
+
196
+ rights << Origami::UsageRights::Rights::FORM_FILLIN if @form_fillin.active?
197
+ rights << Origami::UsageRights::Rights::FORM_IMPORT if @form_import.active?
198
+ rights << Origami::UsageRights::Rights::FORM_EXPORT if @form_export.active?
199
+ rights << Origami::UsageRights::Rights::FORM_SUBMITSTANDALONE if @form_submit.active?
200
+ rights << Origami::UsageRights::Rights::FORM_SPAWNTEMPLATE if @form_spawntemplate.active?
201
+ rights << Origami::UsageRights::Rights::FORM_BARCODEPLAINTEXT if @form_barcode.active?
202
+ rights << Origami::UsageRights::Rights::FORM_ONLINE if @form_online.active?
203
+
204
+ rights << Origami::UsageRights::Rights::SIGNATURE_MODIFY if @signature_modify.active?
205
+
206
+ rights << Origami::UsageRights::Rights::EF_CREATE if @ef_create.active?
207
+ rights << Origami::UsageRights::Rights::EF_DELETE if @ef_delete.active?
208
+ rights << Origami::UsageRights::Rights::EF_MODIFY if @ef_modify.active?
209
+ rights << Origami::UsageRights::Rights::EF_IMPORT if @ef_import.active?
210
+
211
+ begin
212
+ pdf.enable_usage_rights(@cert, @pkey, *rights)
213
+
214
+ set_page_title(@lastpage, "Usage Rights have been enabled")
215
+ @msg_status.text = "Usage Rights have been enabled for the current document.\n You should consider saving it now."
216
+
217
+ @parent.reload
218
+ rescue
219
+ @parent.error("#{$!}: #{$!.backtrace.join($/)}")
220
+
221
+ set_page_title(@lastpage, "Usage Rights have not been enabled")
222
+ @msg_status.text = "An error occured during the signature process."
223
+ end
224
+ }
225
+
226
+ set_modal(true)
227
+
228
+ show_all
229
+ end
230
+
231
+ private
232
+
233
+ def create_intro_page
234
+ intro = <<-INTRO
235
+ You are about to enable Usage Rights for the current PDF document.
236
+ To enable these features, you need to have an Adobe public/private key pair in your possession.
237
+
238
+ Make sure you have adobe.crt and adobe.key located in the current directory.
239
+ INTRO
240
+
241
+ vbox = VBox.new(false, 5)
242
+ vbox.set_border_width(5)
243
+
244
+ lbl = Label.new(intro).set_justify(Gtk::JUSTIFY_LEFT).set_wrap(true)
245
+
246
+ vbox.pack_start(lbl, true, true, 0)
247
+
248
+ append_page(vbox)
249
+ set_page_title(vbox, "Usage Rights Wizard")
250
+ set_page_type(vbox, Assistant::PAGE_INTRO)
251
+ set_page_complete(vbox, true)
252
+ end
253
+
254
+ def create_keypair_import_page
255
+
256
+ labels =
257
+ [
258
+ [ "Private RSA key:", @pkeyfilename = Entry.new, pkeychoosebtn = Button.new(Gtk::Stock::OPEN) ],
259
+ [ "Public certificate:", @certfilename = Entry.new, certchoosebtn = Button.new(Gtk::Stock::OPEN) ]
260
+ ]
261
+
262
+ row = 0
263
+ table = Table.new(2, 3)
264
+ labels.each do |lbl, entry, btn|
265
+ entry.editable = entry.sensitive = false
266
+
267
+ table.attach(Label.new(lbl).set_alignment(1,0), 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
268
+ table.attach(entry, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
269
+ table.attach(btn, 2, 3, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
270
+
271
+ row = row.succ
272
+ end
273
+
274
+ pkeychoosebtn.signal_connect('clicked') { open_private_key_dialog(table) }
275
+ certchoosebtn.signal_connect('clicked') { open_certificate_dialog(table) }
276
+
277
+ append_page(table)
278
+ set_page_title(table, "Import a public/private key pair")
279
+ set_page_type(table, Assistant::PAGE_CONTENT)
280
+ end
281
+
282
+ def create_rights_selection_page
283
+ vbox = VBox.new(false, 5)
284
+
285
+ docframe = Frame.new(" Document ")
286
+ docframe.border_width = 5
287
+ docframe.shadow_type = Gtk::SHADOW_IN
288
+
289
+ doctable = Table.new(1, 2)
290
+ doctable.attach(@document_fullsave = CheckButton.new("Full Save").set_active(true), 0, 1, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
291
+ docframe.add(doctable)
292
+
293
+ annotsframe = Frame.new(" Annotations ")
294
+ annotsframe.border_width = 5
295
+ annotsframe.shadow_type = Gtk::SHADOW_IN
296
+
297
+ annotstable = Table.new(4,2)
298
+ annots =
299
+ [
300
+ [ @annots_create = CheckButton.new("Create").set_active(true), @annots_import = CheckButton.new("Import").set_active(true) ],
301
+ [ @annots_delete = CheckButton.new("Delete").set_active(true), @annots_export = CheckButton.new("Export").set_active(true) ],
302
+ [ @annots_modify = CheckButton.new("Modify").set_active(true), @annots_online = CheckButton.new("Online").set_active(true) ],
303
+ [ @annots_copy = CheckButton.new("Copy").set_active(true), @annots_sumview = CheckButton.new("Summary View").set_active(true) ]
304
+ ]
305
+
306
+ row = 0
307
+ annots.each do |col1, col2|
308
+ annotstable.attach(col1, 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
309
+ annotstable.attach(col2, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
310
+
311
+ row = row.succ
312
+ end
313
+
314
+ annotsframe.add(annotstable)
315
+
316
+ formframe = Frame.new(" Forms ")
317
+ formframe.border_width = 5
318
+ formframe.shadow_type = Gtk::SHADOW_IN
319
+
320
+ formtable = Table.new(4,2)
321
+ forms =
322
+ [
323
+ [ @form_fillin = CheckButton.new("Fill in").set_active(true), @form_spawntemplate = CheckButton.new("Spawn template").set_active(true) ],
324
+ [ @form_import = CheckButton.new("Import").set_active(true), @form_barcode = CheckButton.new("Barcode plaintext").set_active(true) ],
325
+ [ @form_export = CheckButton.new("Export").set_active(true), @form_online = CheckButton.new("Online").set_active(true) ],
326
+ [ @form_submit = CheckButton.new("Submit stand-alone").set_active(true), nil ]
327
+ ]
328
+
329
+ row = 0
330
+ forms.each do |col1, col2|
331
+ formtable.attach(col1, 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
332
+ formtable.attach(col2, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4) unless col2.nil?
333
+
334
+ row = row.succ
335
+ end
336
+
337
+ formframe.add(formtable)
338
+
339
+ signatureframe = Frame.new(" Signature ")
340
+ signatureframe.border_width = 5
341
+ signatureframe.shadow_type = Gtk::SHADOW_IN
342
+
343
+ signaturetable = Table.new(1, 2)
344
+ signaturetable.attach(@signature_modify = CheckButton.new("Modify").set_active(true), 0, 1, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
345
+ signatureframe.add(signaturetable)
346
+
347
+ efframe = Frame.new(" Embedded files ")
348
+ efframe.border_width = 5
349
+ efframe.shadow_type = Gtk::SHADOW_IN
350
+
351
+ eftable = Table.new(2,2)
352
+ efitems =
353
+ [
354
+ [ @ef_create = CheckButton.new("Create").set_active(true), @ef_modify = CheckButton.new("Modify").set_active(true) ],
355
+ [ @ef_delete = CheckButton.new("Delete").set_active(true), @ef_import = CheckButton.new("Import").set_active(true) ]
356
+ ]
357
+
358
+ row = 0
359
+ efitems.each do |col1, col2|
360
+ eftable.attach(col1, 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
361
+ eftable.attach(col2, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
362
+
363
+ row = row.succ
364
+ end
365
+
366
+ efframe.add(eftable)
367
+
368
+ vbox.add(docframe)
369
+ vbox.add(annotsframe)
370
+ vbox.add(formframe)
371
+ vbox.add(signatureframe)
372
+ vbox.add(efframe)
373
+
374
+ append_page(vbox)
375
+ set_page_title(vbox, "Select Usage Rights to enable")
376
+ set_page_type(vbox, Assistant::PAGE_CONFIRM)
377
+ set_page_complete(vbox, true)
378
+ end
379
+
380
+ def create_termination_page
381
+ @lastpage = VBox.new(false, 5)
382
+
383
+ @msg_status = Label.new
384
+ @lastpage.pack_start(@msg_status, true, true, 0)
385
+
386
+ append_page(@lastpage)
387
+ set_page_title(@lastpage, "Usage Rights have not been enabled")
388
+ set_page_type(@lastpage, Assistant::PAGE_SUMMARY)
389
+ end
574
390
  end
575
-
576
- pkeychoosebtn.signal_connect('clicked') { open_pkey_dialog(table) }
577
- certchoosebtn.signal_connect('clicked') { open_cert_dialog(table) }
578
-
579
- append_page(table)
580
- set_page_title(table, "Import a public/private key pair")
581
- set_page_type(table, Assistant::PAGE_CONTENT)
582
-
583
- end
584
-
585
- def create_signature_info_page
586
-
587
- vbox = VBox.new(false, 5)
588
-
589
- lbl = Label.new("Here are a few optional information you can add with your signature.")
590
- vbox.pack_start(lbl, true, true, 0)
591
-
592
- labels =
593
- [
594
- [ "Location:", @location = Entry.new ],
595
- [ "Contact:", @email = Entry.new ],
596
- [ "Reason:", @reason = Entry.new ]
597
- ]
598
-
599
- row = 0
600
- table = Table.new(4, 3)
601
- labels.each do |label|
602
-
603
- table.attach(Label.new(label[0]).set_alignment(1,0), 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
604
- table.attach(label[1], 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
605
-
606
- row = row.succ
391
+
392
+ class SignWizard < Assistant
393
+ include SignatureDialogs
394
+
395
+ INTRO_PAGE = 0
396
+ KEY_SELECT_PAGE = 1
397
+ PKCS12_IMPORT_PAGE = 2
398
+ KEYPAIR_IMPORT_PAGE = 3
399
+ SIGNATURE_INFO_PAGE = 4
400
+ SIGNATURE_RESULT_PAGE = 5
401
+
402
+ def initialize(parent, pdf)
403
+ super()
404
+
405
+ @parent = parent
406
+
407
+ @pkey, @cert, @ca = nil, nil, []
408
+
409
+ create_intro_page
410
+ create_key_selection_page
411
+ create_pkcs12_import_page
412
+ create_keypair_import_page
413
+ create_signature_info_page
414
+ create_termination_page
415
+
416
+ set_forward_page_func { |current_page|
417
+ case current_page
418
+ when KEY_SELECT_PAGE
419
+ if @p12button.active? then PKCS12_IMPORT_PAGE else KEYPAIR_IMPORT_PAGE end
420
+
421
+ when PKCS12_IMPORT_PAGE, KEYPAIR_IMPORT_PAGE
422
+ SIGNATURE_INFO_PAGE
423
+
424
+ else current_page.succ
425
+ end
426
+ }
427
+
428
+ signal_connect('delete_event') { self.destroy }
429
+ signal_connect('cancel') { self.destroy }
430
+ signal_connect('close') { self.destroy }
431
+
432
+ signal_connect('apply') {
433
+ location = @location.text.empty? ? nil : @location.text
434
+ contact = @email.text.empty? ? nil : @email.text
435
+ reason = @reason.text.empty? ? nil : @reason.text
436
+
437
+ begin
438
+ pdf.sign(@cert, @pkey,
439
+ ca: @ca,
440
+ location: location,
441
+ contact: contact,
442
+ reason: reason)
443
+
444
+ set_page_title(@lastpage, "Document has been signed")
445
+ @msg_status.text = "The document has been signed.\n You should consider saving it now."
446
+
447
+ @parent.reload
448
+ rescue
449
+ @parent.error("#{$!}: #{$!.backtrace.join($/)}")
450
+
451
+ set_page_title(@lastpage, "Document has not been signed")
452
+ @msg_status.text = "An error occured during the signature process."
453
+ end
454
+ }
455
+
456
+ set_modal(true)
457
+
458
+ show_all
459
+ end
460
+
461
+ private
462
+
463
+ def create_intro_page
464
+ intro = <<-INTRO
465
+ You are about to sign the current PDF document.
466
+ Once the document will be signed, no further modification will be allowed.
467
+
468
+ The signature process is based on assymetric cryptography, so you will basically need a public/private RSA key pair (between 1024 and 4096 bits).
469
+ INTRO
470
+
471
+ vbox = VBox.new(false, 5)
472
+ vbox.set_border_width(5)
473
+
474
+ lbl = Label.new(intro).set_justify(Gtk::JUSTIFY_LEFT).set_wrap(true)
475
+
476
+ vbox.pack_start(lbl, true, true, 0)
477
+
478
+ append_page(vbox)
479
+ set_page_title(vbox, "Signature Wizard")
480
+ set_page_type(vbox, Assistant::PAGE_INTRO)
481
+ set_page_complete(vbox, true)
482
+ end
483
+
484
+ def create_key_selection_page
485
+ vbox = VBox.new(false, 5)
486
+
487
+ @rawbutton = RadioButton.new("Import keys from separate PEM/DER encoded files")
488
+ @p12button = RadioButton.new(@rawbutton, "Import keys from a PKCS12 container")
489
+
490
+ vbox.pack_start(@rawbutton, true, true, 0)
491
+ vbox.pack_start(@p12button, true, true, 0)
492
+
493
+ append_page(vbox)
494
+ set_page_title(vbox, "Choose a key importation method")
495
+ set_page_type(vbox, Assistant::PAGE_CONTENT)
496
+ set_page_complete(vbox, true)
497
+ end
498
+
499
+ def create_pkcs12_import_page
500
+ vbox = VBox.new(false, 5)
501
+
502
+ hbox = HBox.new(false, 5)
503
+ vbox.pack_start(hbox, true, false, 10)
504
+
505
+ @p12filename = Entry.new.set_editable(false).set_sensitive(false)
506
+ choosebtn = Button.new(Gtk::Stock::OPEN)
507
+
508
+ choosebtn.signal_connect('clicked') { open_pkcs12_file_dialog(vbox) }
509
+
510
+ hbox.pack_start(@p12filename, true, true, 5)
511
+ hbox.pack_start(choosebtn, false, false, 5)
512
+
513
+ append_page(vbox)
514
+ set_page_title(vbox, "Import a PKCS12 container")
515
+ set_page_type(vbox, Assistant::PAGE_CONTENT)
516
+ end
517
+
518
+ def create_keypair_import_page
519
+
520
+ labels =
521
+ [
522
+ [ "Private RSA key:", @pkeyfilename = Entry.new, pkeychoosebtn = Button.new(Gtk::Stock::OPEN) ],
523
+ [ "Public certificate:", @certfilename = Entry.new, certchoosebtn = Button.new(Gtk::Stock::OPEN) ]
524
+ ]
525
+
526
+ row = 0
527
+ table = Table.new(2, 3)
528
+ labels.each do |lbl, entry, btn|
529
+ entry.editable = entry.sensitive = false
530
+
531
+ table.attach(Label.new(lbl).set_alignment(1,0), 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
532
+ table.attach(entry, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
533
+ table.attach(btn, 2, 3, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
534
+
535
+ row = row.succ
536
+ end
537
+
538
+ pkeychoosebtn.signal_connect('clicked') { open_private_key_dialog(table) }
539
+ certchoosebtn.signal_connect('clicked') { open_certificate_dialog(table) }
540
+
541
+ append_page(table)
542
+ set_page_title(table, "Import a public/private key pair")
543
+ set_page_type(table, Assistant::PAGE_CONTENT)
544
+ end
545
+
546
+ def create_signature_info_page
547
+ vbox = VBox.new(false, 5)
548
+
549
+ lbl = Label.new("Here are a few optional information you can add with your signature.")
550
+ vbox.pack_start(lbl, true, true, 0)
551
+
552
+ labels =
553
+ [
554
+ [ "Location:", @location = Entry.new ],
555
+ [ "Contact:", @email = Entry.new ],
556
+ [ "Reason:", @reason = Entry.new ]
557
+ ]
558
+
559
+ row = 0
560
+ table = Table.new(4, 3)
561
+ labels.each do |label|
562
+ table.attach(Label.new(label[0]).set_alignment(1,0), 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
563
+ table.attach(label[1], 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4)
564
+
565
+ row = row.succ
566
+ end
567
+
568
+ vbox.pack_start(table, true, true, 0)
569
+
570
+ append_page(vbox)
571
+ set_page_title(vbox, "Fill in signature details")
572
+ set_page_type(vbox, Assistant::PAGE_CONFIRM)
573
+ set_page_complete(vbox, true)
574
+ end
575
+
576
+ def create_termination_page
577
+ @lastpage = VBox.new(false, 5)
578
+
579
+ @msg_status = Label.new
580
+ @lastpage.pack_start(@msg_status, true, true, 0)
581
+
582
+ append_page(@lastpage)
583
+ set_page_title(@lastpage, "Document has not been signed")
584
+ set_page_type(@lastpage, Assistant::PAGE_SUMMARY)
585
+ end
607
586
  end
608
-
609
- vbox.pack_start(table, true, true, 0)
610
-
611
- append_page(vbox)
612
- set_page_title(vbox, "Fill in signature details")
613
- set_page_type(vbox, Assistant::PAGE_CONFIRM)
614
- set_page_complete(vbox, true)
615
-
616
- end
617
-
618
- def create_termination_page
619
-
620
- @lastpage = VBox.new(false, 5)
621
-
622
- @msg_status = Label.new
623
- @lastpage.pack_start(@msg_status, true, true, 0)
624
-
625
- append_page(@lastpage)
626
- set_page_title(@lastpage, "Document has not been signed")
627
- set_page_type(@lastpage, Assistant::PAGE_SUMMARY)
628
-
629
- end
630
-
631
587
  end
632
-
633
- end
634
588
 
635
589
  end