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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d85155d1ce53a32be48e557bd81995deea20b096f0d5ac7797aad798f6527680
4
- data.tar.gz: 70d1b127ab875cc3a7d2f04b922aa48c950cb2db33b46240e35a29080edc5fc8
3
+ metadata.gz: 330529457cdaebeb17c7cc3f3edf18b93c8e1a5a4a88c79738e8dbab9a0ef12a
4
+ data.tar.gz: d489d30eb02c4c2a4667ec294e6cc13f1961a3ded3ca2e42df6185d77556a516
5
5
  SHA512:
6
- metadata.gz: ec92728d10052f07d4fced7e9aa973bb14f655f67fb1f4c1684535b7d4e2dcaac2fda995fa64243253c1ef56e0ee66eb33d1ba66b31fb76c37437beaacf0f85e
7
- data.tar.gz: 133a216c0b0016c18d269355eb5336fcaa754cb30b8fa648786644648f06820ccec4e9608d00f8de57229ea3d493bd10de4bc06368ac901a71c674605d841159
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 :)
@@ -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
- section_data = buffer.read(len)
274
- raise DecodeError.new("Section too short: #{section_data}") unless section_data.length == len
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
 
@@ -102,7 +102,7 @@ module Oxygene
102
102
 
103
103
  (data['e'] || []).each do |e|
104
104
  if previous
105
- key = previous[0...e['p']]
105
+ key = previous.byteslice(0, e['p'])
106
106
  key << e['k']
107
107
  else
108
108
  key = e['k']
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Oxygene
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end
data/lib/oxygene.rb CHANGED
@@ -4,6 +4,7 @@ require_relative 'oxygene/base32'
4
4
  require_relative 'oxygene/car_archive'
5
5
  require_relative 'oxygene/car_repo'
6
6
  require_relative 'oxygene/cid'
7
+ require_relative 'oxygene/star_archive'
7
8
  require_relative 'oxygene/version'
8
9
 
9
10
  #
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.0
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.5.9
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.5.9
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: 3.6.9
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: []