rubrik 1.0.0 → 1.1.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/README.md +1 -0
- data/lib/rubrik/document/serialize_object.rb +39 -2
- data/lib/rubrik/document.rb +39 -6
- data/lib/rubrik/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1092e4bfdff7f05272eab8cf226a09b54737f368c24e883370002a399036ce4a
|
|
4
|
+
data.tar.gz: 818072d3ea9003599a9ec5fb49af2df99f3f43045e9aa6a81a1e62e8f2c11fd3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 173091b0ab44b398a10260e267de6ff92fe8083d2668dabe86e79bdb93547151ad9b73e08296c955e3e604ebba4b1f9f74fc44ae91ef661839883cd96f71fe9d
|
|
7
|
+
data.tar.gz: 60a0c1647190a473703ac1ae1cf1e5d407bc59e4f599b1de6d3111c3dd7105fa8077ec7955fed5df1c5c088dc9a515e7b5b3bd1987a0d42dc2835f5ca8585313
|
data/README.md
CHANGED
|
@@ -22,6 +22,7 @@ This gem is under development and may be subjected to breaking changes.
|
|
|
22
22
|
|
|
23
23
|
### PDF Features
|
|
24
24
|
- [x] Modify PDFs with incremental updates (doesn't modify the documents, only append signature appearance)
|
|
25
|
+
- [ ] Encryption Support
|
|
25
26
|
- [ ] Signature appearance (stamp)
|
|
26
27
|
- [ ] External (offline) signatures
|
|
27
28
|
|
|
@@ -15,14 +15,14 @@ module Rubrik
|
|
|
15
15
|
serialized_objs = obj.flatten.map { |e| SerializeObject[e] }
|
|
16
16
|
"<<#{serialized_objs.join(" ")}>>"
|
|
17
17
|
when Symbol
|
|
18
|
-
|
|
18
|
+
serialize_symbol(obj)
|
|
19
19
|
when Array
|
|
20
20
|
serialized_objs = obj.map { |e| SerializeObject[e] }
|
|
21
21
|
"[#{serialized_objs.join(" ")}]"
|
|
22
22
|
when PDF::Reader::Reference
|
|
23
23
|
"#{obj.id} #{obj.gen} R"
|
|
24
24
|
when String
|
|
25
|
-
|
|
25
|
+
serialize_string(obj)
|
|
26
26
|
when TrueClass
|
|
27
27
|
"true"
|
|
28
28
|
when FalseClass
|
|
@@ -48,6 +48,43 @@ module Rubrik
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
alias call []
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
STRING_ESCAPE_MAP = {
|
|
55
|
+
"\n" => "\\\n",
|
|
56
|
+
"\r" => "\\\r",
|
|
57
|
+
"\t" => "\\\t",
|
|
58
|
+
"\b" => "\\\b",
|
|
59
|
+
"\f" => "\\\f",
|
|
60
|
+
"\\" => "\\\\",
|
|
61
|
+
"(" => "\\(",
|
|
62
|
+
")" => "\\)"
|
|
63
|
+
}.freeze
|
|
64
|
+
|
|
65
|
+
sig {params(string: String).returns(String)}
|
|
66
|
+
def serialize_string(string)
|
|
67
|
+
"(#{string.gsub(/[\n\r\t\b\f\\()]/n, STRING_ESCAPE_MAP)})"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
DELIMITERS = "()<>[]{}/%".bytes.freeze
|
|
71
|
+
REGULAR_CHARACTERS =
|
|
72
|
+
"!\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~".bytes.freeze
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
NAME_ESCAPE_CHARACTERS = (0..255).to_a - REGULAR_CHARACTERS + DELIMITERS + "#".bytes
|
|
76
|
+
NAME_ESCAPE_CHARACTERS.freeze
|
|
77
|
+
|
|
78
|
+
NAME_ESCAPE_MAP = NAME_ESCAPE_CHARACTERS.each_with_object({}) do |char, escape_map|
|
|
79
|
+
escape_map[char.chr] = "##{char.to_s(16).rjust(2, "0")}"
|
|
80
|
+
end.freeze
|
|
81
|
+
|
|
82
|
+
NAME_ESCAPE_REGEX = /[#{Regexp.escape(NAME_ESCAPE_CHARACTERS.map(&:chr).join)}]/
|
|
83
|
+
|
|
84
|
+
sig {params(symbol: Symbol).returns(String)}
|
|
85
|
+
def serialize_symbol(symbol)
|
|
86
|
+
"/#{symbol.to_s.b.gsub(NAME_ESCAPE_REGEX, NAME_ESCAPE_MAP)}"
|
|
87
|
+
end
|
|
51
88
|
end
|
|
52
89
|
end
|
|
53
90
|
end
|
data/lib/rubrik/document.rb
CHANGED
|
@@ -76,12 +76,30 @@ module Rubrik
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
first_page = objects.fetch(first_page_reference)
|
|
80
|
+
annots = first_page[:Annots]
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
if annots.is_a?(PDF::Reader::Reference)
|
|
83
|
+
new_annots = objects.fetch(annots).dup
|
|
84
|
+
new_annots << signature_field_id
|
|
83
85
|
|
|
84
|
-
|
|
86
|
+
modified_objects << {id: annots, value: new_annots}
|
|
87
|
+
else
|
|
88
|
+
new_first_page = first_page.dup
|
|
89
|
+
(new_first_page[:Annots] ||= []) << signature_field_id
|
|
90
|
+
|
|
91
|
+
modified_objects << {id: first_page_reference, value: new_first_page}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
fields_entry = interactive_form[:Fields]
|
|
95
|
+
if fields_entry.is_a?(PDF::Reader::Reference)
|
|
96
|
+
new_fields_array = objects.fetch(fields_entry).dup
|
|
97
|
+
new_fields_array << signature_field_id
|
|
98
|
+
|
|
99
|
+
modified_objects << {id: fields_entry, value: new_fields_array}
|
|
100
|
+
else
|
|
101
|
+
(interactive_form[:Fields] ||= []) << signature_field_id
|
|
102
|
+
end
|
|
85
103
|
|
|
86
104
|
signature_value_id
|
|
87
105
|
end
|
|
@@ -108,11 +126,22 @@ module Rubrik
|
|
|
108
126
|
root_ref = objects.trailer[:Root]
|
|
109
127
|
root = T.let(objects.fetch(root_ref), T::Hash[Symbol, T.untyped])
|
|
110
128
|
|
|
111
|
-
|
|
129
|
+
interactive_form_value = root[:AcroForm]
|
|
130
|
+
case interactive_form_value
|
|
131
|
+
when PDF::Reader::Reference
|
|
112
132
|
form_id = root[:AcroForm]
|
|
113
133
|
|
|
114
134
|
modified_objects << {id: form_id, value: objects.fetch(form_id).dup}
|
|
115
|
-
|
|
135
|
+
when Hash
|
|
136
|
+
interactive_form_id = assign_new_object_id!
|
|
137
|
+
|
|
138
|
+
modified_objects << {id: interactive_form_id, value: interactive_form_value.dup}
|
|
139
|
+
|
|
140
|
+
new_root = root.dup
|
|
141
|
+
new_root[:AcroForm] = interactive_form_id
|
|
142
|
+
|
|
143
|
+
modified_objects << {id: root_ref, value: new_root}
|
|
144
|
+
when NilClass
|
|
116
145
|
interactive_form_id = assign_new_object_id!
|
|
117
146
|
modified_objects << {id: interactive_form_id, value: {Fields: []}}
|
|
118
147
|
|
|
@@ -121,6 +150,10 @@ module Rubrik
|
|
|
121
150
|
updated_root[:AcroForm] = interactive_form_id
|
|
122
151
|
|
|
123
152
|
modified_objects << {id: root_ref, value: updated_root}
|
|
153
|
+
else
|
|
154
|
+
raise Error.new(
|
|
155
|
+
"Expected dictionary, reference or nil but got " \
|
|
156
|
+
"#{interactive_form_value.class} on AcroForm entry.")
|
|
124
157
|
end
|
|
125
158
|
|
|
126
159
|
interactive_form[:SigFlags] = 3 # dont modify, append only
|
data/lib/rubrik/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubrik
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tomás Coêlho
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-
|
|
11
|
+
date: 2023-12-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: pdf-reader
|