pdf_oxide 0.3.55-aarch64-linux
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 +7 -0
- data/Gemfile +16 -0
- data/LICENSE +176 -0
- data/LICENSE-APACHE +176 -0
- data/LICENSE-MIT +25 -0
- data/README.md +122 -0
- data/ext/pdf_oxide/libpdf_oxide.so +0 -0
- data/lib/pdf_oxide/auto_extractor.rb +157 -0
- data/lib/pdf_oxide/document_editor.rb +235 -0
- data/lib/pdf_oxide/errors.rb +58 -0
- data/lib/pdf_oxide/ffi/bindings.rb +1694 -0
- data/lib/pdf_oxide/ffi/library.rb +98 -0
- data/lib/pdf_oxide/ffi/string_marshaller.rb +45 -0
- data/lib/pdf_oxide/markdown_converter.rb +52 -0
- data/lib/pdf_oxide/pdf.rb +218 -0
- data/lib/pdf_oxide/pdf_document.rb +411 -0
- data/lib/pdf_oxide/pdf_page.rb +71 -0
- data/lib/pdf_oxide/pdf_policy.rb +64 -0
- data/lib/pdf_oxide/pdf_signer.rb +155 -0
- data/lib/pdf_oxide/pdf_validator.rb +97 -0
- data/lib/pdf_oxide/version.rb +5 -0
- data/lib/pdf_oxide.rb +60 -0
- metadata +198 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PdfOxide
|
|
4
|
+
# PDF/A · PDF/X · PDF/UA compliance validation (v0.3.50).
|
|
5
|
+
#
|
|
6
|
+
# Mirrors `fyi.oxide.pdf.PdfValidator`. Stateless façade.
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# PdfOxide::PdfDocument.open('compliant.pdf') do |doc|
|
|
10
|
+
# puts PdfOxide::PdfValidator.pdf_a?(doc, level: :a1b)
|
|
11
|
+
# end
|
|
12
|
+
module PdfValidator
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
# PDF/A level → cdylib wire-format integer.
|
|
16
|
+
#
|
|
17
|
+
# Matches `src/ffi.rs:1225` (`0=A1b 1=A1a 2=A2b 3=A2a 4=A2u 5=A3b
|
|
18
|
+
# 6=A3a 7=A3u`). Every binding (Java, Ruby, PHP, C#, Go) sends the
|
|
19
|
+
# SAME integer for the same PDF/A level — the "B before A"
|
|
20
|
+
# intra-level order is the cdylib's contract, not a Ruby choice.
|
|
21
|
+
PDF_A_LEVELS = { a1b: 0, a1a: 1, a2b: 2, a2a: 3, a2u: 4, a3b: 5, a3a: 6, a3u: 7 }.freeze
|
|
22
|
+
|
|
23
|
+
# PDF/UA level → cdylib wire-format integer.
|
|
24
|
+
#
|
|
25
|
+
# Matches `src/ffi.rs:5538` (`level == 2 → UA-2, else UA-1`).
|
|
26
|
+
# 1-indexed, not 0-indexed; mirrors the C# `PdfUaLevel` enum.
|
|
27
|
+
PDF_UA_LEVELS = { ua1: 1, ua2: 2 }.freeze
|
|
28
|
+
|
|
29
|
+
# @return [Boolean] PDF/A compliance for `level`.
|
|
30
|
+
def pdf_a?(doc, level: :a1b)
|
|
31
|
+
raise ::PdfOxide::ArgumentError, 'doc cannot be nil' if doc.nil?
|
|
32
|
+
|
|
33
|
+
ordinal = PDF_A_LEVELS.fetch(level) do
|
|
34
|
+
raise ::PdfOxide::ArgumentError, "unknown PDF/A level: #{level.inspect}"
|
|
35
|
+
end
|
|
36
|
+
# If the native symbol is absent (older cdylib), surface a clean
|
|
37
|
+
# "unavailable" verdict instead of reading an uninitialised err
|
|
38
|
+
# buffer and raising a spurious ComplianceError.
|
|
39
|
+
return false unless Bindings.respond_to?(:pdf_validate_pdf_a_level)
|
|
40
|
+
|
|
41
|
+
err = ::FFI::MemoryPointer.new(:int32)
|
|
42
|
+
result_ptr = Bindings.pdf_validate_pdf_a_level(doc.handle, ordinal, err)
|
|
43
|
+
code = err.read_int32
|
|
44
|
+
raise ComplianceError, "pdf_validate_pdf_a_level failed (#{code})" if code != 0
|
|
45
|
+
|
|
46
|
+
compliance_verdict(result_ptr, :pdf_pdf_a_is_compliant, :pdf_pdf_a_results_free)
|
|
47
|
+
rescue ::FFI::NotFoundError
|
|
48
|
+
false
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @return [Boolean] PDF/UA compliance for `level`.
|
|
52
|
+
def pdf_ua?(doc, level: :ua1)
|
|
53
|
+
raise ::PdfOxide::ArgumentError, 'doc cannot be nil' if doc.nil?
|
|
54
|
+
|
|
55
|
+
ordinal = PDF_UA_LEVELS.fetch(level) do
|
|
56
|
+
raise ::PdfOxide::ArgumentError, "unknown PDF/UA level: #{level.inspect}"
|
|
57
|
+
end
|
|
58
|
+
err = ::FFI::MemoryPointer.new(:int32)
|
|
59
|
+
result_ptr = Bindings.pdf_validate_pdf_ua(doc.handle, ordinal, err)
|
|
60
|
+
code = err.read_int32
|
|
61
|
+
raise ComplianceError, "pdf_validate_pdf_ua failed (#{code})" if code != 0
|
|
62
|
+
|
|
63
|
+
compliance_verdict(result_ptr, :pdf_pdf_ua_is_accessible, :pdf_pdf_ua_results_free)
|
|
64
|
+
rescue ::FFI::NotFoundError
|
|
65
|
+
false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @return [Hash] simplified PDF/A validation result: { compliant:, violations: }.
|
|
69
|
+
def validate_pdf_a(doc, level: :a1b)
|
|
70
|
+
{ compliant: pdf_a?(doc, level: level), violations: [] }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# @return [Hash] simplified PDF/UA validation result.
|
|
74
|
+
def validate_pdf_ua(doc, level: :ua1)
|
|
75
|
+
{ compliant: pdf_ua?(doc, level: level), violations: [] }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# The accessor symbols (pdf_pdf_a_is_compliant, pdf_pdf_x_is_compliant,
|
|
79
|
+
# pdf_pdf_ua_is_accessible) all take (results, int32_t *error_code).
|
|
80
|
+
# Pre-v0.3.55 Ruby bound them with just (results) — register garbage
|
|
81
|
+
# was used as the err pointer and the cdylib wrote through it,
|
|
82
|
+
# producing the same flaky segfault class as the search-result
|
|
83
|
+
# accessors (#547). Both args are passed here so the new 2-arg
|
|
84
|
+
# binding is honoured.
|
|
85
|
+
def self.compliance_verdict(result_ptr, accessor_sym, free_sym)
|
|
86
|
+
return false if result_ptr.nil? || result_ptr.null?
|
|
87
|
+
|
|
88
|
+
err = ::FFI::MemoryPointer.new(:int32)
|
|
89
|
+
begin
|
|
90
|
+
Bindings.send(accessor_sym, result_ptr, err)
|
|
91
|
+
ensure
|
|
92
|
+
Bindings.send(free_sym, result_ptr) if Bindings.respond_to?(free_sym)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
private_class_method :compliance_verdict
|
|
96
|
+
end
|
|
97
|
+
end
|
data/lib/pdf_oxide.rb
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Ruby bindings for pdf_oxide — high-performance PDF processing.
|
|
4
|
+
#
|
|
5
|
+
# Idiomatic 9-class API mirroring the Java binding's shape at
|
|
6
|
+
# `fyi.oxide.pdf.*`. All native calls route through the FFI layer
|
|
7
|
+
# at `PdfOxide::FFI::Bindings`; UTF-8 marshalling is via
|
|
8
|
+
# `PdfOxide::FFI::StringMarshaller`.
|
|
9
|
+
#
|
|
10
|
+
# Public surface:
|
|
11
|
+
# - {PdfOxide::PdfDocument} — read-only entry point.
|
|
12
|
+
# - {PdfOxide::PdfPage} — per-page view.
|
|
13
|
+
# - {PdfOxide::Pdf} — create + transform (markdown/html/text → PDF).
|
|
14
|
+
# - {PdfOxide::DocumentEditor} — write-side: form-fill, redaction, save.
|
|
15
|
+
# - {PdfOxide::AutoExtractor} — typed-reason auto-extraction (#519).
|
|
16
|
+
# - {PdfOxide::MarkdownConverter} — PDF → Markdown / HTML.
|
|
17
|
+
# - {PdfOxide::PdfValidator} — PDF/A · PDF/UA compliance.
|
|
18
|
+
# - {PdfOxide::PdfSigner} — PAdES B/T/LT/LTA signing.
|
|
19
|
+
# - {PdfOxide::PdfPolicy} — process-global crypto-governance.
|
|
20
|
+
|
|
21
|
+
require 'ffi'
|
|
22
|
+
|
|
23
|
+
require_relative 'pdf_oxide/version'
|
|
24
|
+
require_relative 'pdf_oxide/errors'
|
|
25
|
+
require_relative 'pdf_oxide/ffi/library'
|
|
26
|
+
require_relative 'pdf_oxide/ffi/bindings'
|
|
27
|
+
require_relative 'pdf_oxide/ffi/string_marshaller'
|
|
28
|
+
|
|
29
|
+
module PdfOxide
|
|
30
|
+
# Convenience constants reaching into the FFI sub-module. Keeps
|
|
31
|
+
# downstream callers free of the `PdfOxide::FFI::` prefix when
|
|
32
|
+
# accessing the binding layer; matches the Java binding's flat shape.
|
|
33
|
+
Bindings = FFI::Bindings
|
|
34
|
+
StringMarshaller = FFI::StringMarshaller
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
require_relative 'pdf_oxide/pdf_page'
|
|
38
|
+
require_relative 'pdf_oxide/markdown_converter'
|
|
39
|
+
require_relative 'pdf_oxide/auto_extractor'
|
|
40
|
+
require_relative 'pdf_oxide/pdf_document'
|
|
41
|
+
require_relative 'pdf_oxide/pdf'
|
|
42
|
+
require_relative 'pdf_oxide/document_editor'
|
|
43
|
+
require_relative 'pdf_oxide/pdf_signer'
|
|
44
|
+
require_relative 'pdf_oxide/pdf_validator'
|
|
45
|
+
require_relative 'pdf_oxide/pdf_policy'
|
|
46
|
+
|
|
47
|
+
module PdfOxide
|
|
48
|
+
class << self
|
|
49
|
+
# Open a PDF for reading.
|
|
50
|
+
# @return [PdfDocument]
|
|
51
|
+
def open(source, password: nil, &block)
|
|
52
|
+
PdfDocument.open(source, password: password, &block)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @return [String] library version.
|
|
56
|
+
def version
|
|
57
|
+
VERSION
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: pdf_oxide
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.3.55
|
|
5
|
+
platform: aarch64-linux
|
|
6
|
+
authors:
|
|
7
|
+
- PDF Oxide Contributors
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-05-25 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: ffi
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.16'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.16'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: bundler
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '2.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '2.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '13.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '13.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rspec
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.12'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3.12'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rubocop
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '1.86'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '1.86'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rubocop-rspec
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '2.20'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '2.20'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: simplecov-lcov
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0.8'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0.8'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: yard
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0.9'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0.9'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: simplecov
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0.22'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - "~>"
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0.22'
|
|
139
|
+
description: Idiomatic Ruby bindings for PDF Oxide. Process, analyze, and generate
|
|
140
|
+
PDFs through the libpdf_oxide cdylib used by the Python, Java, Node, Go, and C#
|
|
141
|
+
bindings.
|
|
142
|
+
email:
|
|
143
|
+
- support@pdf-oxide.dev
|
|
144
|
+
executables: []
|
|
145
|
+
extensions: []
|
|
146
|
+
extra_rdoc_files: []
|
|
147
|
+
files:
|
|
148
|
+
- Gemfile
|
|
149
|
+
- LICENSE
|
|
150
|
+
- LICENSE-APACHE
|
|
151
|
+
- LICENSE-MIT
|
|
152
|
+
- README.md
|
|
153
|
+
- ext/pdf_oxide/libpdf_oxide.so
|
|
154
|
+
- lib/pdf_oxide.rb
|
|
155
|
+
- lib/pdf_oxide/auto_extractor.rb
|
|
156
|
+
- lib/pdf_oxide/document_editor.rb
|
|
157
|
+
- lib/pdf_oxide/errors.rb
|
|
158
|
+
- lib/pdf_oxide/ffi/bindings.rb
|
|
159
|
+
- lib/pdf_oxide/ffi/library.rb
|
|
160
|
+
- lib/pdf_oxide/ffi/string_marshaller.rb
|
|
161
|
+
- lib/pdf_oxide/markdown_converter.rb
|
|
162
|
+
- lib/pdf_oxide/pdf.rb
|
|
163
|
+
- lib/pdf_oxide/pdf_document.rb
|
|
164
|
+
- lib/pdf_oxide/pdf_page.rb
|
|
165
|
+
- lib/pdf_oxide/pdf_policy.rb
|
|
166
|
+
- lib/pdf_oxide/pdf_signer.rb
|
|
167
|
+
- lib/pdf_oxide/pdf_validator.rb
|
|
168
|
+
- lib/pdf_oxide/version.rb
|
|
169
|
+
homepage: https://github.com/yfedoseev/pdf_oxide
|
|
170
|
+
licenses:
|
|
171
|
+
- MIT
|
|
172
|
+
- Apache-2.0
|
|
173
|
+
metadata:
|
|
174
|
+
homepage_uri: https://github.com/yfedoseev/pdf_oxide
|
|
175
|
+
source_code_uri: https://github.com/yfedoseev/pdf_oxide
|
|
176
|
+
bug_tracker_uri: https://github.com/yfedoseev/pdf_oxide/issues
|
|
177
|
+
documentation_uri: https://rubydoc.info/gems/pdf_oxide
|
|
178
|
+
changelog_uri: https://github.com/yfedoseev/pdf_oxide/blob/main/CHANGELOG.md
|
|
179
|
+
post_install_message:
|
|
180
|
+
rdoc_options: []
|
|
181
|
+
require_paths:
|
|
182
|
+
- lib
|
|
183
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
184
|
+
requirements:
|
|
185
|
+
- - ">="
|
|
186
|
+
- !ruby/object:Gem::Version
|
|
187
|
+
version: 3.1.0
|
|
188
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
189
|
+
requirements:
|
|
190
|
+
- - ">="
|
|
191
|
+
- !ruby/object:Gem::Version
|
|
192
|
+
version: '0'
|
|
193
|
+
requirements: []
|
|
194
|
+
rubygems_version: 3.5.22
|
|
195
|
+
signing_key:
|
|
196
|
+
specification_version: 4
|
|
197
|
+
summary: Ruby bindings for PDF Oxide - high-performance PDF processing
|
|
198
|
+
test_files: []
|