oxygene 0.1.0 → 0.1.1
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 +6 -0
- data/SECURITY.md +16 -0
- data/lib/oxygene/car_archive.rb +7 -4
- data/lib/oxygene/car_repo.rb +1 -1
- data/lib/oxygene/star_archive.rb +124 -0
- data/lib/oxygene/version.rb +1 -1
- data/lib/oxygene.rb +1 -0
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 330529457cdaebeb17c7cc3f3edf18b93c8e1a5a4a88c79738e8dbab9a0ef12a
|
|
4
|
+
data.tar.gz: d489d30eb02c4c2a4667ec294e6cc13f1961a3ded3ca2e42df6185d77556a516
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f3258bd11dcb7f8fd2ac81e8e602ac848f6dd13e38a1bbe54b0a3e35661eea8b778805443f83decc3941804a9d2ebe55549ae268aaac6030b7e0244a03525c40
|
|
7
|
+
data.tar.gz: de40782159c5cd2febdeaeb876bee0bda1f0ddea0639ebe5f954bc0458d6fc1da2e0788834cee13bb059a3b87011e6258d70c331e0cf889569b62992083cd32d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [0.1.1] - 2026-11-06
|
|
2
|
+
|
|
3
|
+
* added experimental parser for STAR archives (`Oxygene::STARArchive`)
|
|
4
|
+
* some minor optimizations
|
|
5
|
+
* bumped up `cbor` gem dependency to 0.6
|
|
6
|
+
|
|
1
7
|
## [0.1.0] - 2026-08-17
|
|
2
8
|
|
|
3
9
|
* added custom, much faster Base32 encoder/decoder, dropping `base32` gem dependency
|
data/SECURITY.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## How To Report a Vulnerability
|
|
4
|
+
|
|
5
|
+
If you find a potential vulnerability in one of my projects, it's recommended not to report it through a standard publicly-readable issue report, in order to avoid giving possible clues to any potential attackers who could abuse it before it's fixed (see: ["Just a rumour of a bug is enough to find a security exploit these days"](https://anil.recoil.org/notes/rumour-is-the-exploit)).
|
|
6
|
+
|
|
7
|
+
You can use one of these to contact me instead:
|
|
8
|
+
|
|
9
|
+
- [@mackuba.eu](https://bsky.app/profile/did:plc:oio4hkxaop4ao4wz2pp3f4cr) on Bluesky (my DMs should be open, or mention me discretely with a request for contact)
|
|
10
|
+
- [@mackuba@martianbase.net](https://martianbase.net/@mackuba) on Mastodon (my personal instance)
|
|
11
|
+
- email: mackuba `@` protonmail.ch (optionally with [this PGP key](https://mail-api.proton.me/pks/lookup?op=get&search=mackuba@protonmail.ch))
|
|
12
|
+
- ["Report a vulnerability"](https://github.com/mackuba/oxygene/security/advisories/new) form on GitHub
|
|
13
|
+
|
|
14
|
+
I do not check my Twitter/X or LinkedIn accounts regularly.
|
|
15
|
+
|
|
16
|
+
Note: please don't submit AI-reported issues that have not been verified manually :)
|
data/lib/oxygene/car_archive.rb
CHANGED
|
@@ -268,13 +268,16 @@ module Oxygene
|
|
|
268
268
|
|
|
269
269
|
def read_section(buffer)
|
|
270
270
|
len = buffer.read_varint
|
|
271
|
+
raise DecodeError, "Section length is too short: #{len}" if len < 36
|
|
271
272
|
|
|
272
273
|
# TODO: verify content CIDs
|
|
273
|
-
|
|
274
|
-
|
|
274
|
+
cid_data = buffer.read(36)
|
|
275
|
+
body_data = buffer.read(len - 36)
|
|
276
|
+
|
|
277
|
+
unless cid_data&.bytesize == 36 && body_data&.bytesize == len - 36
|
|
278
|
+
raise DecodeError, "Section is truncated"
|
|
279
|
+
end
|
|
275
280
|
|
|
276
|
-
cid_data = section_data.byteslice(0, 36)
|
|
277
|
-
body_data = section_data.byteslice(36..)
|
|
278
281
|
cid_data.prepend(CID::CBOR_TAG_PREFIX)
|
|
279
282
|
cid = CID.new(cid_data, binary: true, cbor_prefix: true, codec: :drisl)
|
|
280
283
|
|
data/lib/oxygene/car_repo.rb
CHANGED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'errors'
|
|
4
|
+
require_relative 'extensions'
|
|
5
|
+
|
|
6
|
+
require 'cbor'
|
|
7
|
+
require 'stringio'
|
|
8
|
+
|
|
9
|
+
module Oxygene
|
|
10
|
+
|
|
11
|
+
#
|
|
12
|
+
# Parser for STAR archives (experimental).
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
class STARArchive
|
|
16
|
+
using Oxygene::Extensions
|
|
17
|
+
|
|
18
|
+
MAGIC_PREFIX = "\x2A\x6C\x01\x00"
|
|
19
|
+
|
|
20
|
+
attr_reader :data_pairs, :data_map, :metadata
|
|
21
|
+
|
|
22
|
+
def initialize(data)
|
|
23
|
+
@buffer = StringIO.new(data)
|
|
24
|
+
@data_pairs = []
|
|
25
|
+
@data_map = {}
|
|
26
|
+
|
|
27
|
+
read_header(@buffer)
|
|
28
|
+
|
|
29
|
+
loop do
|
|
30
|
+
had_data = read_section(@buffer)
|
|
31
|
+
break if !had_data
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
@buffer = nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def inspect
|
|
38
|
+
vars = (instance_variables - [:@data_map]).map { |v|
|
|
39
|
+
"#{v}=#{instance_variable_get(v).inspect}"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
"#<#{self.class}:0x#{object_id} #{vars.join(", ")}>"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def read_header(buffer)
|
|
49
|
+
magic = buffer.read(MAGIC_PREFIX.length)
|
|
50
|
+
raise DecodeError.new("Missing initial magic bytes") unless magic == MAGIC_PREFIX
|
|
51
|
+
|
|
52
|
+
header_len = read_varint(buffer)
|
|
53
|
+
raise DecodeError.new("Header length cannot be 0") if header_len == 0
|
|
54
|
+
|
|
55
|
+
header_data = buffer.read(header_len)
|
|
56
|
+
|
|
57
|
+
unless header_data.length == header_len
|
|
58
|
+
raise DecodeError.new("Header too short: got #{header_data.length} bytes, expected #{header_len}")
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
begin
|
|
62
|
+
metadata = CBOR.decode(header_data)
|
|
63
|
+
rescue StandardError
|
|
64
|
+
raise DecodeError.new("Malformed CBOR data")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
raise DecodeError.new("Metadata object should be a hash") unless metadata.is_a?(Hash)
|
|
68
|
+
|
|
69
|
+
type = metadata['$type']
|
|
70
|
+
raise DecodeError.new("Missing '$type' field") if type.nil?
|
|
71
|
+
raise DecodeError.new("Invalid '$type' field: #{type.inspect}") unless type.is_a?(String)
|
|
72
|
+
|
|
73
|
+
@type = type
|
|
74
|
+
@metadata = metadata
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def read_section(buffer)
|
|
78
|
+
control_byte = buffer.getbyte
|
|
79
|
+
|
|
80
|
+
case control_byte
|
|
81
|
+
when 0
|
|
82
|
+
# end of file
|
|
83
|
+
if @buffer.eof?
|
|
84
|
+
return false
|
|
85
|
+
else
|
|
86
|
+
raise DecodeError, "Unexpected content after end of file marker"
|
|
87
|
+
end
|
|
88
|
+
when 1
|
|
89
|
+
# continue with the next section
|
|
90
|
+
when nil
|
|
91
|
+
raise DecodeError, "Unexpected end of file"
|
|
92
|
+
else
|
|
93
|
+
raise DecodeError, "Unexpected control byte: #{control_byte}"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
k_len = read_varint(buffer)
|
|
97
|
+
raise DecodeError, "Unexpected end of file" if k_len.nil?
|
|
98
|
+
|
|
99
|
+
key = buffer.read(k_len)
|
|
100
|
+
raise DecodeError, "Truncated key data" if key.nil? || key.length != k_len
|
|
101
|
+
|
|
102
|
+
v_len = read_varint(buffer)
|
|
103
|
+
raise DecodeError, "Unexpected end of file" if v_len.nil?
|
|
104
|
+
|
|
105
|
+
value = buffer.read(v_len)
|
|
106
|
+
raise DecodeError, "Truncated value data" if value.nil? || value.length != v_len
|
|
107
|
+
|
|
108
|
+
@data_pairs << [key, value]
|
|
109
|
+
@data_map[key] = value
|
|
110
|
+
|
|
111
|
+
true
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def read_varint(buffer)
|
|
115
|
+
pos_before = buffer.pos
|
|
116
|
+
value = buffer.read_varint
|
|
117
|
+
length = buffer.pos - pos_before
|
|
118
|
+
|
|
119
|
+
raise DecodeError, "Varint length exceeds limit" if length > 9
|
|
120
|
+
|
|
121
|
+
value
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
data/lib/oxygene/version.rb
CHANGED
data/lib/oxygene.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: oxygene
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kuba Suder
|
|
@@ -29,14 +29,14 @@ dependencies:
|
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 0.
|
|
32
|
+
version: 0.6.1
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 0.
|
|
39
|
+
version: 0.6.1
|
|
40
40
|
email:
|
|
41
41
|
- jakub.suder@gmail.com
|
|
42
42
|
executables: []
|
|
@@ -47,6 +47,7 @@ files:
|
|
|
47
47
|
- CHANGELOG.md
|
|
48
48
|
- LICENSE.txt
|
|
49
49
|
- README.md
|
|
50
|
+
- SECURITY.md
|
|
50
51
|
- lib/oxygene.rb
|
|
51
52
|
- lib/oxygene/base32.rb
|
|
52
53
|
- lib/oxygene/car_archive.rb
|
|
@@ -55,6 +56,7 @@ files:
|
|
|
55
56
|
- lib/oxygene/cid.rb
|
|
56
57
|
- lib/oxygene/errors.rb
|
|
57
58
|
- lib/oxygene/extensions.rb
|
|
59
|
+
- lib/oxygene/star_archive.rb
|
|
58
60
|
- lib/oxygene/version.rb
|
|
59
61
|
- sig/oxygene.rbs
|
|
60
62
|
homepage: https://ruby.sdk.blue
|
|
@@ -79,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
79
81
|
- !ruby/object:Gem::Version
|
|
80
82
|
version: '0'
|
|
81
83
|
requirements: []
|
|
82
|
-
rubygems_version:
|
|
84
|
+
rubygems_version: 4.0.23
|
|
83
85
|
specification_version: 4
|
|
84
86
|
summary: Various data decoding primitives for ATProto (CAR, CID, CBOR)
|
|
85
87
|
test_files: []
|