imprimatur 0.4.0-aarch64-linux-gnu → 0.5.0-aarch64-linux-gnu
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 +7 -0
- data/README.md +7 -0
- data/lib/imprimatur/4.0/imprimatur_native.so +0 -0
- data/lib/imprimatur/reader.rb +48 -11
- data/lib/imprimatur/spreadsheet.rb +1 -1
- data/lib/imprimatur/version.rb +1 -1
- data/lib/imprimatur.rb +2 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5a6d6451a7a370921f43b37e27a8edb7d886a4923981afd28a256b424b85234e
|
|
4
|
+
data.tar.gz: e74c978a45ce43cc0856b186b71f38d3204aea8cb71c4f0ed5d961bd4f0dc874
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bf5c3cc806be6379e109c335d65e4b1f84662cbdcb569db4ae0e9fd0e028d4185cf0f9f0b4cd7cc37ac00cc8a313878aaddaee276898b5835e4365f25fe0dfb4
|
|
7
|
+
data.tar.gz: 0ac1716d1208f48001683efafd3bba638ddc134ff1d67c545a7ad123f99213ee9ff83a96eb7603ca3f3f64ba1cdb8a14507128f530adf21c3e6a5ab989ebca95
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.0](https://github.com/seuros/imprimatur/compare/v0.4.0...v0.5.0) (2026-10-18)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* a binary String is always a document's bytes, a path must name a regular file, and reads stop at max_bytes ([3484a64](https://github.com/seuros/imprimatur/commit/3484a64b791beb2e9f90cd485441fae255e223f0))
|
|
9
|
+
|
|
3
10
|
## [0.4.0](https://github.com/seuros/imprimatur/compare/v0.3.0...v0.4.0) (2026-10-18)
|
|
4
11
|
|
|
5
12
|
|
data/README.md
CHANGED
|
@@ -318,6 +318,13 @@ fibers keep running, and `Timeout` or `Thread#raise` cancels it.
|
|
|
318
318
|
`Imprimatur::PasswordRequired` and `Imprimatur::UnsupportedDocument` (legacy
|
|
319
319
|
`.doc`, `.xlsb`, presentations) are the other errors to expect.
|
|
320
320
|
|
|
321
|
+
A binary String is always the document's bytes, never a path: an upload
|
|
322
|
+
holding `/etc/passwd` or `/dev/zero` is refused as `UnsupportedDocument`,
|
|
323
|
+
not read from the server. A path (a `Pathname`, or a String that is not
|
|
324
|
+
binary and has no document signature) must name a regular file; devices,
|
|
325
|
+
pipes and directories are refused. An IO or a path is read no further than
|
|
326
|
+
`max_bytes:`, so an endless stream or a huge file stops there.
|
|
327
|
+
|
|
321
328
|
### Structure and images
|
|
322
329
|
|
|
323
330
|
Markdown is one rendering of what a read finds. `Imprimatur.content` gives
|
|
Binary file
|
data/lib/imprimatur/reader.rb
CHANGED
|
@@ -12,22 +12,29 @@ module Imprimatur
|
|
|
12
12
|
# Documents in: Markdown, their structure, their images. See
|
|
13
13
|
# {Imprimatur.markdown}, {Imprimatur.content} and {Imprimatur.images}.
|
|
14
14
|
module Reader
|
|
15
|
-
# File signatures a document's bytes start with; a String that
|
|
16
|
-
# with neither is taken for a path.
|
|
15
|
+
# File signatures a document's bytes start with; a String that is not
|
|
16
|
+
# binary and starts with neither is taken for a path.
|
|
17
17
|
SIGNATURES = ["%PDF-".b, "PK\x03\x04".b, "PK\x05\x06".b, "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1".b].freeze
|
|
18
18
|
private_constant :SIGNATURES
|
|
19
19
|
|
|
20
|
+
# The largest document read in unless told, as the native core's own limit.
|
|
21
|
+
MAX_BYTES = 512 * 1024 * 1024
|
|
22
|
+
private_constant :MAX_BYTES
|
|
23
|
+
|
|
20
24
|
# @see Imprimatur.markdown
|
|
21
|
-
def self.markdown(document,
|
|
25
|
+
def self.markdown(document, max_bytes: nil, **)
|
|
26
|
+
Native.markdown(read(document, max_bytes), *limits(max_bytes:, **))
|
|
27
|
+
end
|
|
22
28
|
|
|
23
29
|
# @see Imprimatur.content
|
|
24
|
-
def self.content(document, styles: false, **)
|
|
25
|
-
|
|
30
|
+
def self.content(document, styles: false, max_bytes: nil, **)
|
|
31
|
+
bytes = read(document, max_bytes)
|
|
32
|
+
JSON.parse(Native.content(bytes, *limits(max_bytes:, **), styles ? true : false), symbolize_names: true)
|
|
26
33
|
end
|
|
27
34
|
|
|
28
35
|
# @see Imprimatur.images
|
|
29
|
-
def self.images(document, **)
|
|
30
|
-
Native.images(read(document), *limits(**)).map do |data, description|
|
|
36
|
+
def self.images(document, max_bytes: nil, **)
|
|
37
|
+
Native.images(read(document, max_bytes), *limits(max_bytes:, **)).map do |data, description|
|
|
31
38
|
found = JSON.parse(description, symbolize_names: true)
|
|
32
39
|
Image.new(data:, **Image.members.drop(1).to_h { [it, found[it]] })
|
|
33
40
|
end
|
|
@@ -38,22 +45,52 @@ module Imprimatur
|
|
|
38
45
|
[max_bytes, max_inflated, timeout && Float(timeout)]
|
|
39
46
|
end
|
|
40
47
|
|
|
48
|
+
# A path or an IO is read no further than +max_bytes+ (one byte past it
|
|
49
|
+
# tells it is passed): an endless stream or a huge file stops there.
|
|
50
|
+
#
|
|
41
51
|
# @api private
|
|
42
|
-
def self.read(document)
|
|
52
|
+
def self.read(document, max_bytes = nil)
|
|
53
|
+
limit = max_bytes.is_a?(Integer) && max_bytes >= 0 ? max_bytes : MAX_BYTES
|
|
43
54
|
case document
|
|
44
|
-
when Pathname then
|
|
45
|
-
when String then bytes?(document) ? document :
|
|
55
|
+
when Pathname then file(document, limit)
|
|
56
|
+
when String then bytes?(document) ? document : file(document, limit)
|
|
46
57
|
else
|
|
47
58
|
raise TypeError, "expected a path, bytes or an IO, not #{document.class}" unless document.respond_to?(:read)
|
|
48
59
|
|
|
49
|
-
document.read.to_s.b
|
|
60
|
+
within(document.read(limit + 1).to_s.b, limit)
|
|
50
61
|
end
|
|
51
62
|
end
|
|
52
63
|
|
|
64
|
+
# A binary String (what +File.binread+, a binary IO or a download give)
|
|
65
|
+
# is bytes, whatever it holds: uploaded bytes never name a file to read.
|
|
66
|
+
#
|
|
53
67
|
# @api private
|
|
54
68
|
def self.bytes?(string)
|
|
69
|
+
return true if string.encoding == Encoding::BINARY
|
|
70
|
+
|
|
55
71
|
head = string.byteslice(0, 1024).b
|
|
56
72
|
SIGNATURES.any? { head.start_with?(it) } || head.include?("%PDF-") || head.include?("\0")
|
|
57
73
|
end
|
|
74
|
+
|
|
75
|
+
# A regular file's bytes. Opened without blocking and checked through
|
|
76
|
+
# the open file, so a pipe cannot hang the read, a device such as
|
|
77
|
+
# +/dev/zero+ is refused, and the file cannot be swapped in between.
|
|
78
|
+
#
|
|
79
|
+
# @api private
|
|
80
|
+
def self.file(path, limit)
|
|
81
|
+
File.open(path, File::RDONLY | File::NONBLOCK | File::BINARY) do |io|
|
|
82
|
+
stat = io.stat
|
|
83
|
+
raise UnsupportedDocument, "cannot read this document: #{path} is not a regular file" unless stat.file?
|
|
84
|
+
|
|
85
|
+
within(stat.size > limit ? '' : io.read(limit + 1).to_s, limit, stat.size)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# @api private
|
|
90
|
+
def self.within(bytes, limit, size = bytes.bytesize)
|
|
91
|
+
raise LimitExceeded, 'the document exceeds the input size limit' if [size, bytes.bytesize].max > limit
|
|
92
|
+
|
|
93
|
+
bytes
|
|
94
|
+
end
|
|
58
95
|
end
|
|
59
96
|
end
|
|
@@ -123,7 +123,7 @@ module Imprimatur
|
|
|
123
123
|
# @raise [UnsupportedDocument] a PDF, a Word document or another format
|
|
124
124
|
# @raise [Imprimatur::Error] a damaged workbook, or past a limit
|
|
125
125
|
def self.open(document, styles: false, **limits)
|
|
126
|
-
new(Native.sheets(Reader.read(document), *Reader.limits(**limits), styles ? true : false))
|
|
126
|
+
new(Native.sheets(Reader.read(document, limits[:max_bytes]), *Reader.limits(**limits), styles ? true : false))
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
# @return [Array<Sheet>] in the workbook's order, hidden ones included
|
data/lib/imprimatur/version.rb
CHANGED
data/lib/imprimatur.rb
CHANGED
|
@@ -66,7 +66,8 @@ module Imprimatur
|
|
|
66
66
|
# Imprimatur.markdown(File.open('sales.xlsx'))
|
|
67
67
|
#
|
|
68
68
|
# @param document [String, Pathname, #read] a path, the document's bytes
|
|
69
|
-
# (
|
|
69
|
+
# (a binary String always is; another String only with a document's
|
|
70
|
+
# signature), or an IO. A path must name a regular file.
|
|
70
71
|
# @param timeout [Numeric, nil] seconds the read may take (60), +nil+ for none
|
|
71
72
|
# @param max_bytes [Integer, nil] the largest document accepted (512 MiB)
|
|
72
73
|
# @param max_inflated [Integer, nil] decompressed bytes allowed in all (1 GiB)
|