binascii 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f3e19a8aa182b270cc304d659d9ad8d8decea96ec2e1bec4fd4cdcd81f9af34f
4
+ data.tar.gz: cd5d28e6e1bae4c736edbba2ba85ccdb9eea43c1e7255cc78c403007da8ea355
5
+ SHA512:
6
+ metadata.gz: deeb040eb021c8fb261d03146fbfea27103317b978b040826d28f3b39e9ed976bf1dd038489c4b27183c416239c11c15ba7a405985a5a0c0a2e478662f7b2528
7
+ data.tar.gz: 62cbff23f40de4a92434259d074b60198b4f2dd80f97554b741b737e26ee1211a527776ec13c711e34cb6a689450a86927a05701b0f09d058f10e6e86e90ff97
@@ -0,0 +1,2 @@
1
+ ## 1.0.0
2
+ * Birthday!
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem 'benchmark-ips'
7
+ gem 'pry-byebug'
8
+ gem 'ruby-prof'
9
+ gem 'rake'
10
+ end
11
+
12
+ group :test do
13
+ gem 'rspec'
14
+ end
@@ -0,0 +1,92 @@
1
+ ## binascii [![Build Status](https://secure.travis-ci.org/camertron/binascii.png?branch=master)](http://travis-ci.org/camertron/binascii)
2
+
3
+ A Ruby version of Python's binascii module.
4
+
5
+ ## Installation
6
+
7
+ `gem install binascii`
8
+
9
+ ## Usage
10
+
11
+ ```ruby
12
+ require 'binascii'
13
+ ```
14
+
15
+ ### Base64
16
+
17
+ Encodes and decodes text in the base64 format. This differs from Ruby's built-in base64 encoding mechanism in that it removes line breaks from the result and provides the option to append a newline character at the end.
18
+
19
+ ```ruby
20
+ Binascii.b2a_base64('abc') # => "YWJj\n"
21
+ Binascii.b2a_base64('abc', newline: false) # => "YWJj"
22
+
23
+ Binascii.a2b_base64('YWJj') # => "abc"
24
+ Binascii.a2b_base64("YWJj\n") # => "abc"
25
+ ```
26
+
27
+ ### CRC32
28
+
29
+ This is simply a wrapper around the CRC32 functionality present in Ruby's `Zlib` module.
30
+
31
+ ```ruby
32
+ Binascii.crc32('abc') # => 891568578
33
+ ```
34
+
35
+ ### Hexlify
36
+
37
+ Outputs each byte of the input data as two hexadecimal characters. Produces a string that contains twice as many bytes as the input data.
38
+
39
+ ```ruby
40
+ # aliased as .hexlify
41
+ Binascii.b2a_hex('jkl') # => "6a6b6c"
42
+
43
+ # aliased as .unhexlify
44
+ Binascii.a2b_hex('6a6b6c') # => "jkl"
45
+ ```
46
+
47
+ ### HQX and Run-length Encoding
48
+
49
+ Encodes and decodes bytes in the HQX format. HQX is (apparently) often combined with RLE, or run-length encoding.
50
+
51
+ ```ruby
52
+ rle = Binascii.rlecode_hqx('aaaaabbbbbb') # => "a\x90\x05b\x90\x06"
53
+ hqx = Binascii.b2a_hqx(rle) # => # => "BC!&BT!'"
54
+
55
+ Binascii.rledecode_hqx(Binascii.a2b_hqx(hqx).first) # => "aaaaabbbbbb"
56
+ ```
57
+
58
+ `.a2b_hqx` returns an array with two elements. The first is the decoded result, and the second is an integer containing either 1 or 0. 1 indicates decoding was stopped because of the presence of a stop character (ASCII code 58, i.e. a colon, ':'), 0 means no stop character was found.
59
+
60
+ ### Quoted-printable
61
+
62
+ Encodes and decodes bytes in the quoted-printable format.
63
+
64
+ ```ruby
65
+ Binascii.b2a_qp("some \x12 \x14 data") # => "some =12 =14 data"
66
+ Binascii.a2b_qp('some =12 =14 data') # => "some \x12 \x14 data"
67
+ ```
68
+
69
+ ### Unix-to-unix
70
+
71
+ Encodes and decodes bytes in the unix-to-unix format.
72
+
73
+ ```ruby
74
+ Binascii.b2a_uu("abc\n") # => "$86)C\"@ \n"
75
+ Binascii.a2b_uu("$86)C\"@ \n") # => "abc\n"
76
+ ```
77
+
78
+ ## Running Benchmarks
79
+
80
+ Benchmarks are provided for most of Binascii's functionality in the bench/ directory. Run each benchmark directly, i.e. `bundle exec ruby bench/hqx_bench.rb`. Binascii's algorithms are compared to native Ruby versions when they are available. However it should be noted that, with the exception of CRC32, all algorithms implemented by this library will not produce exactly the same output as their Ruby counterparts as they accept generally more options and therefore produce more customizable output. It should also be noted that the Ruby equivalents are all implemented in C and will therefore be much faster in most cases.
81
+
82
+ ## Running Tests
83
+
84
+ `bundle exec rspec` should do the trick :)
85
+
86
+ ## License
87
+
88
+ Licensed under the MIT license. See LICENSE for details.
89
+
90
+ ## Authors
91
+
92
+ * Cameron C. Dutro: http://github.com/camertron
@@ -0,0 +1,13 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'rubygems/package_task'
3
+
4
+ require 'binascii'
5
+
6
+ Bundler::GemHelper.install_tasks
7
+
8
+ task default: :spec
9
+
10
+ desc 'Run specs'
11
+ RSpec::Core::RakeTask.new do |t|
12
+ t.pattern = './spec/**/*_spec.rb'
13
+ end
@@ -0,0 +1,18 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+ require 'binascii/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'binascii'
6
+ s.version = ::Binascii::VERSION
7
+ s.authors = ['Cameron Dutro']
8
+ s.email = ['camertron@gmail.com']
9
+ s.homepage = 'https://github.com/camertron/binascii'
10
+ s.license = 'MIT'
11
+ s.description = s.summary = "A Ruby version of Python's binascii module"
12
+
13
+ s.platform = Gem::Platform::RUBY
14
+ s.has_rdoc = true
15
+
16
+ s.require_path = 'lib'
17
+ s.files = Dir['{lib,spec}/**/*', 'Gemfile', 'CHANGELOG.md', 'README.md', 'Rakefile', 'binascii.gemspec']
18
+ end
@@ -0,0 +1,17 @@
1
+ require 'binascii/qp'
2
+ require 'binascii/uu'
3
+ require 'binascii/base64'
4
+ require 'binascii/hqx'
5
+ require 'binascii/crc32'
6
+ require 'binascii/hex'
7
+
8
+ module Binascii
9
+ include Qp
10
+ include Uu
11
+ include Base64
12
+ include Hqx
13
+ include Crc32
14
+ include Hex
15
+
16
+ extend Binascii
17
+ end
@@ -0,0 +1,13 @@
1
+ module Binascii
2
+ module Base64
3
+ def a2b_base64(string)
4
+ string.unpack('m').first
5
+ end
6
+
7
+ def b2a_base64(data, newline: true)
8
+ result = [data].pack('m').gsub!("\n", '')
9
+ result << "\n" if newline
10
+ result
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'zlib'
4
+
5
+ module Binascii
6
+ module Crc32
7
+ def crc32(data, crc = 0)
8
+ Zlib.crc32(data, crc)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Binascii
4
+ module Hex
5
+ A2B_LO = (('0'..'9').to_a + ('a'..'z').to_a + ('A'..'Z').to_a)
6
+ .each_with_object({}).with_index { |(chr, ret), idx| ret[chr.ord] = idx }
7
+ .freeze
8
+
9
+ A2B_HI = A2B_LO
10
+ .each_with_object({}) { |(ord, idx), ret| ret[ord] = idx + (0xF * idx) }
11
+ .freeze
12
+
13
+ B2A = (0...256).each_with_object({}) do |b, ret|
14
+ ret[b] = b.to_s(16).rjust(2, '0')
15
+ end.freeze
16
+
17
+ def b2a_hex(data)
18
+ String.new('', encoding: 'ASCII-8BIT').tap do |result|
19
+ data.each_byte do |byte|
20
+ result << B2A[byte]
21
+ end
22
+ end
23
+ end
24
+
25
+ alias_method :hexlify, :b2a_hex
26
+
27
+ def a2b_hex(data)
28
+ String.new('', encoding: 'ASCII-8BIT').tap do |result|
29
+ len = data.bytesize
30
+ pos = 0
31
+
32
+ while pos < len
33
+ result << (A2B_HI[data.getbyte(pos)] | A2B_LO[data.getbyte(pos + 1)])
34
+ pos += 2
35
+ end
36
+ end
37
+ end
38
+
39
+ alias_method :unhexlify, :a2b_hex
40
+ end
41
+ end
@@ -0,0 +1,226 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Binascii
4
+ module Hqx
5
+ class DecodeError < ::StandardError
6
+ end
7
+
8
+ A2B_TABLE = [
9
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
10
+ :fail, :fail, :skip, :fail, :fail, :skip, :fail, :fail,
11
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
12
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
13
+ :fail, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
14
+ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, :fail, :fail,
15
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, :fail,
16
+ 0x14, 0x15, :done, :fail, :fail, :fail, :fail, :fail,
17
+ 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
18
+ 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, :fail,
19
+ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, :fail,
20
+ 0x2C, 0x2D, 0x2E, 0x2F, :fail, :fail, :fail, :fail,
21
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, :fail,
22
+ 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, :fail, :fail,
23
+ 0x3D, 0x3E, 0x3F, :fail, :fail, :fail, :fail, :fail,
24
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
25
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
26
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
27
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
28
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
29
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
30
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
31
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
32
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
33
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
34
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
35
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
36
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
37
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
38
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
39
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail,
40
+ :fail, :fail, :fail, :fail, :fail, :fail, :fail, :fail
41
+ ].freeze
42
+
43
+ B2A_TABLE = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"
44
+ .bytes
45
+ .freeze
46
+
47
+ RLE_RUN_CHAR = 0x90
48
+
49
+ CRC_TABLE = [
50
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
51
+ 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
52
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
53
+ 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
54
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
55
+ 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
56
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
57
+ 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
58
+ 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
59
+ 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
60
+ 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
61
+ 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
62
+ 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
63
+ 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
64
+ 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
65
+ 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
66
+ 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
67
+ 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
68
+ 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
69
+ 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
70
+ 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
71
+ 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
72
+ 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
73
+ 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
74
+ 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
75
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
76
+ 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
77
+ 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
78
+ 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
79
+ 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
80
+ 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
81
+ 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
82
+ ].freeze
83
+
84
+ def a2b_hqx(str)
85
+ result = String.new('', encoding: 'ASCII-8BIT')
86
+ bits = 0
87
+ buffer = 0
88
+ pos = 0
89
+ done = 0
90
+
91
+ str.each_byte do |byte|
92
+ ch = A2B_TABLE[byte]
93
+
94
+ if ch == :fail
95
+ raise DecodeError, "Illegal character at position #{pos}"
96
+ elsif ch == :done
97
+ done = 1
98
+ break
99
+ end
100
+
101
+ buffer = (buffer << 6) | ch
102
+ bits += 6
103
+
104
+ if bits >= 8
105
+ bits -= 8
106
+ result << ((buffer >> bits) & 0xFF)
107
+ buffer &= ((1 << bits) - 1)
108
+ end
109
+
110
+ pos += 1
111
+ end
112
+
113
+ if bits > 0 && done == 0
114
+ raise DecodeError, 'String has incomplete number of bytes'
115
+ end
116
+
117
+ [result, done]
118
+ end
119
+
120
+ def b2a_hqx(data)
121
+ String.new('', encoding: 'ASCII-8BIT').tap do |result|
122
+ bits = 0
123
+ buffer = 0
124
+
125
+ data.each_byte do |byte|
126
+ buffer = (buffer << 8) | byte
127
+ bits += 8
128
+
129
+ while bits >= 6
130
+ ch = (buffer >> (bits - 6)) & 0x3F
131
+ result << B2A_TABLE[ch]
132
+ bits -= 6
133
+ end
134
+ end
135
+
136
+ if bits > 0
137
+ buffer <<= (6 - bits)
138
+ result << B2A_TABLE[buffer & 0x3F]
139
+ end
140
+ end
141
+ end
142
+
143
+ def rlecode_hqx(data)
144
+ String.new('', encoding: 'ASCII-8BIT').tap do |result|
145
+ len = data.bytesize
146
+ pos = 0
147
+
148
+ while pos < len
149
+ byte = data.getbyte(pos)
150
+
151
+ if byte == RLE_RUN_CHAR
152
+ result << RLE_RUN_CHAR
153
+ result << 0
154
+ else
155
+ count = 0
156
+ (len - pos).times do |i|
157
+ break if count >= 255
158
+ break if data.getbyte(pos + i) != byte
159
+ count += 1
160
+ end
161
+
162
+ result << byte
163
+
164
+ if count > 3
165
+ result << RLE_RUN_CHAR
166
+ result << count
167
+ pos += count - 1
168
+ end
169
+ end
170
+
171
+ pos += 1
172
+ end
173
+ end
174
+ end
175
+
176
+ def rledecode_hqx(data)
177
+ String.new('', encoding: 'ASCII-8BIT').tap do |result|
178
+ len = data.bytesize
179
+ last_byte = data.getbyte(0)
180
+
181
+ if last_byte == RLE_RUN_CHAR
182
+ raise DecodeError, 'Orphaned RLE code at start'
183
+ end
184
+
185
+ result << last_byte
186
+ pos = 1
187
+
188
+ while pos < len
189
+ byte = data.getbyte(pos)
190
+
191
+ if byte == RLE_RUN_CHAR
192
+ count = data.getbyte(pos + 1)
193
+
194
+ if count == 0
195
+ # indicates an escaped RLE_RUN_CHAR, so output it
196
+ result << RLE_RUN_CHAR
197
+ else
198
+ # one less than count because we have already outputted the
199
+ # character once during the previous iteration
200
+ result << (last_byte.chr * (count - 1))
201
+ end
202
+
203
+ # skip count
204
+ pos += 1
205
+ else
206
+ result << byte
207
+ end
208
+
209
+ last_byte = byte
210
+ pos += 1
211
+ end
212
+ end
213
+ end
214
+
215
+ def crc_hqx(data, crc = 0)
216
+ crc &= 0xFFFF
217
+ len = data.bytesize
218
+
219
+ data.each_byte do |byte|
220
+ crc = ((crc << 8) & 0xFF00) ^ CRC_TABLE[(crc >> 8) ^ byte]
221
+ end
222
+
223
+ crc
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'binascii/utils'
4
+
5
+ module Binascii
6
+ module Qp
7
+ LINE_MAX = 76
8
+
9
+ def a2b_qp(str, header: false)
10
+ return '' if str == '='
11
+ str = Utils.render_string(str) if str.index("\r")
12
+ first_byte = str.getbyte(0)
13
+
14
+ str = if first_byte == 95 || first_byte == 61
15
+ str
16
+ else
17
+ idx = str.index("\n")
18
+ idx ? str[(idx + 1)..-1] : ''
19
+ end
20
+
21
+ str = str.unpack('M').first
22
+
23
+ str.gsub!('==', '=')
24
+ str.gsub!('_', ' ') if header
25
+
26
+ str
27
+ end
28
+
29
+ def b2a_qp(data, header: false, quote_tabs: false, is_text: true)
30
+ @byte_cache ||= {}
31
+
32
+ String.new.tap do |result|
33
+ data_size = data.bytesize
34
+ line_len = 0
35
+ cr_lf = false
36
+
37
+ # This code is obtusely procedural for performance reasons.
38
+ # The python C version isn't much better.
39
+ Utils.each_byte_quad(data) do |leading, byte, trailing1, trailing2|
40
+ repl = nil
41
+ repl_size = 1
42
+
43
+ if byte == 13 # linefeed, \r
44
+ if is_text
45
+ repl = byte
46
+ else
47
+ repl = '=0D'
48
+ end
49
+ elsif byte == 10 # carriage return, \n
50
+ if is_text
51
+ cr_lf = true if leading == 13
52
+
53
+ if cr_lf && leading != 13
54
+ repl = "\r\n"
55
+ repl_size = 2
56
+ else
57
+ repl = byte
58
+ end
59
+ else
60
+ repl = '=0A'
61
+ end
62
+ elsif byte == 95 # underscore
63
+ repl = header ? '=5F' : '_'
64
+ repl_size = repl.bytesize
65
+ elsif byte == 32 # space
66
+ if (!trailing1 || trailing1 == 10 || (trailing1 == 13 && trailing2 == 10) || quote_tabs) && is_text
67
+ repl = "=20"
68
+ repl_size = 3
69
+ else
70
+ repl = header ? '_' : ' '
71
+ end
72
+ elsif byte == 9 # tab
73
+ if (!trailing1 || trailing1 == 10 || (trailing1 == 13 && trailing2 == 10) || quote_tabs) && is_text
74
+ repl = "=09"
75
+ repl_size = 3
76
+ else
77
+ repl = "\t"
78
+ end
79
+ elsif byte == 46 # period
80
+ # I don't understand these rules, but whatever
81
+ if line_len == 0 && (!trailing1 || trailing1 == 10 || trailing1 == 13 || trailing1 == 0)
82
+ repl = '=2E'
83
+ repl_size = 3
84
+ else
85
+ repl = '.'
86
+ end
87
+ elsif (byte >= 33 && byte <= 126) && byte != 61 # all printable ascii characters except '='
88
+ repl = byte
89
+ else
90
+ repl = (@byte_cache[byte] ||= "=#{byte.to_s(16).rjust(2, '0').upcase}")
91
+ repl_size = 3
92
+ end
93
+
94
+ if (line_len + repl_size) > LINE_MAX - 1
95
+ line_len = 0
96
+ result << "=\r\n"
97
+ result << repl
98
+ else
99
+ result << repl
100
+ end
101
+
102
+ line_len += repl_size
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,54 @@
1
+ module Binascii
2
+ module Utils
3
+ class << self
4
+ def each_byte_quad(data, &block)
5
+ data.force_encoding('ASCII-8BIT')
6
+ yield [nil, data.getbyte(0), data.getbyte(1), data.getbyte(2)]
7
+ return if data.bytesize == 1
8
+
9
+ data.each_byte.each_cons(4, &block)
10
+
11
+ if data.bytesize > 2
12
+ yield [data.getbyte(-3), data.getbyte(-2), data.getbyte(-1), nil]
13
+ end
14
+
15
+ yield [data.getbyte(-2), data.getbyte(-1), nil, nil]
16
+ end
17
+
18
+ def each_byte_pair(data, &block)
19
+ data.force_encoding('ASCII-8BIT')
20
+ data.each_byte.each_cons(2, &block)
21
+ yield [data.getbyte(-1), nil]
22
+ end
23
+
24
+ def render_string(data)
25
+ read_pos = 0
26
+ write_pos = 0
27
+ line_start_pos = 0
28
+ result = ''
29
+
30
+ each_byte_pair(data) do |current, trailing|
31
+ if current == 13
32
+ if trailing != 10
33
+ write_pos = line_start_pos
34
+ next
35
+ end
36
+ elsif current == 10
37
+ line_start_pos = read_pos
38
+ end
39
+
40
+ if write_pos >= result.bytesize
41
+ result << current
42
+ else
43
+ result.setbyte(write_pos, current)
44
+ end
45
+
46
+ read_pos += 1
47
+ write_pos += 1
48
+ end
49
+
50
+ result
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Binascii
4
+ module Uu
5
+ def b2a_uu(data, backtick: false)
6
+ if data.bytesize == 0
7
+ backtick ? "`\n" : " \n"
8
+ else
9
+ result = [data].pack('u')
10
+ backtick ? result : result.gsub!('`', ' ')
11
+ end
12
+ end
13
+
14
+ def a2b_uu(str)
15
+ str.force_encoding('ASCII-8BIT')
16
+ len = (str.getbyte(0) - 32) & 077
17
+ str.unpack('u').first.rjust(len, "\0")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module Binascii
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Binascii do
4
+ describe '#crc32' do
5
+ it do
6
+ crc = described_class.crc32("Test the CRC-32 of")
7
+ crc = described_class.crc32(" this string.", crc)
8
+ expect(crc).to eq(1571220330)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Binascii do
4
+ let(:s) { "{s\005\000\000\000worldi\002\000\000\000s\005\000\000\000helloi\001\000\000\0000" }
5
+ let(:t) { described_class.b2a_hex(s) }
6
+ let(:u) { described_class.a2b_hex(t) }
7
+
8
+ it do
9
+ expect(s).to eq(u)
10
+ end
11
+
12
+ describe '#b2a_hex' do
13
+ it do
14
+ expect(described_class.b2a_hex(s)).to eq(t)
15
+ end
16
+ end
17
+
18
+ describe '#a2b_hex' do
19
+ it do
20
+ expect(described_class.a2b_hex(t)).to eq(u)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Binascii do
4
+ def ascii8(str)
5
+ str.force_encoding('ASCII-8BIT')
6
+ end
7
+
8
+ describe 'rle' do
9
+ it do
10
+ data = ('a' * 100) + 'b' + ('c' * 300)
11
+ encoded = described_class.rlecode_hqx(data)
12
+ expect(encoded).to eq(ascii8("a\x90dbc\x90\xffc\x90-"))
13
+ decoded = described_class.rledecode_hqx(encoded)
14
+ expect(decoded).to eq(data)
15
+ end
16
+ end
17
+
18
+ describe 'hqx' do
19
+ it do
20
+ data = "The quick brown fox jumps over the lazy dog.\r\n" +
21
+ (0...256).to_a.pack('C*') +
22
+ "\r\nHello world.\n"
23
+
24
+ rle = described_class.rlecode_hqx(data)
25
+ a = described_class.b2a_hqx(rle)
26
+
27
+ b, _ = described_class.a2b_hqx(a)
28
+ res = described_class.rledecode_hqx(b)
29
+ expect(res).to eq(data)
30
+ end
31
+ end
32
+
33
+ describe '#crc_hqx' do
34
+ it do
35
+ crc = described_class.crc_hqx('Test the CRC-32 of', 0)
36
+ crc = described_class.crc_hqx(" this string.", crc)
37
+ expect(crc).to eq(14290)
38
+
39
+ [0, 1, 0x1234, 0x12345, 0x12345678, -1].each do |crc|
40
+ expect(described_class.crc_hqx('', crc)).to eq(crc & 0xffff)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,268 @@
1
+ require 'spec_helper'
2
+
3
+ describe Binascii do
4
+ def ascii8(str)
5
+ str.force_encoding('ASCII-8BIT')
6
+ end
7
+
8
+ describe '#a2b_qp' do
9
+ def a2b_qp(str, options = {})
10
+ described_class.a2b_qp(str, **options)
11
+ end
12
+
13
+ it do
14
+ expect(a2b_qp('=')).to eq('')
15
+ end
16
+
17
+ it do
18
+ expect(a2b_qp('= ')).to eq('= ')
19
+ end
20
+
21
+ it do
22
+ expect(a2b_qp('==')).to eq('=')
23
+ end
24
+
25
+ it do
26
+ expect(a2b_qp("=\nAB")).to eq('AB')
27
+ end
28
+
29
+ it do
30
+ expect(a2b_qp("=\r\nAB")).to eq('AB')
31
+ end
32
+
33
+ it do
34
+ expect(a2b_qp("=\rAB")).to eq('')
35
+ end
36
+
37
+ it do
38
+ expect(a2b_qp("=\rAB\nCD")).to eq('CD')
39
+ end
40
+
41
+ it do
42
+ expect(a2b_qp('=AB')).to eq(ascii8("\xab"))
43
+ end
44
+
45
+ it do
46
+ expect(a2b_qp('=ab')).to eq(ascii8("\xab"))
47
+ end
48
+
49
+ it do
50
+ expect(a2b_qp('=AX')).to eq('=AX')
51
+ end
52
+
53
+ it do
54
+ expect(a2b_qp('=XA')).to eq('=XA')
55
+ end
56
+
57
+ it do
58
+ expect(a2b_qp('=A')).to eq('=A')
59
+ end
60
+
61
+ it do
62
+ expect(a2b_qp('_')).to eq('_')
63
+ end
64
+
65
+ it do
66
+ expect(a2b_qp('_', header: true)).to eq(' ')
67
+ end
68
+
69
+ # @TODO
70
+ # self.assertRaises(TypeError, b2a_qp, foo="bar")
71
+
72
+ it do
73
+ expect(a2b_qp("=00\r\n=00")).to eq("\x00\r\n\x00")
74
+ end
75
+ end
76
+
77
+ describe '#b2a_qp' do
78
+ def b2a_qp(str, options = {})
79
+ described_class.b2a_qp(str, **options)
80
+ end
81
+
82
+ it do
83
+ expect(b2a_qp("\xff\r\n\xff\n\xff")).to eq("=FF\r\n=FF\r\n=FF")
84
+ end
85
+
86
+ it do
87
+ expect(b2a_qp(('0' * 75) + "\xff\r\n\xff\r\n\xff")).to eq(
88
+ ('0' * 75) + "=\r\n=FF\r\n=FF\r\n=FF"
89
+ )
90
+ end
91
+
92
+ it do
93
+ expect(b2a_qp("\x7f")).to eq('=7F')
94
+ end
95
+
96
+ it do
97
+ expect(b2a_qp('=')).to eq('=3D')
98
+ end
99
+
100
+ it do
101
+ expect(b2a_qp('_')).to eq('_')
102
+ end
103
+
104
+ it do
105
+ expect(b2a_qp('_', header: true)).to eq('=5F')
106
+ end
107
+
108
+ it do
109
+ expect(b2a_qp('x y', header: true)).to eq('x_y')
110
+ end
111
+
112
+ it do
113
+ expect(b2a_qp('x ', header: true)).to eq('x=20')
114
+ end
115
+
116
+ it do
117
+ expect(b2a_qp('x y', header: true, quote_tabs: true)).to eq('x=20y')
118
+ end
119
+
120
+ it do
121
+ expect(b2a_qp("x\ty", header: true)).to eq("x\ty")
122
+ end
123
+
124
+ it do
125
+ expect(b2a_qp(' ')).to eq('=20')
126
+ end
127
+
128
+ it do
129
+ expect(b2a_qp("\t")).to eq('=09')
130
+ end
131
+
132
+ it do
133
+ expect(b2a_qp(' x')).to eq(' x')
134
+ end
135
+
136
+ it do
137
+ expect(b2a_qp("\tx")).to eq("\tx")
138
+ end
139
+
140
+ it do
141
+ expect(b2a_qp(" ")).to eq("=20")
142
+ end
143
+
144
+ it do
145
+ expect(b2a_qp("\t")).to eq("=09")
146
+ end
147
+
148
+ it do
149
+ expect(b2a_qp("\0")).to eq("=00")
150
+ end
151
+
152
+ it do
153
+ expect(b2a_qp("\0\n")).to eq("=00\n")
154
+ end
155
+
156
+ it do
157
+ expect(b2a_qp("\0\n", quote_tabs: true)).to eq("=00\n")
158
+ end
159
+
160
+ it do
161
+ expect(b2a_qp("x y\tz")).to eq("x y\tz")
162
+ end
163
+
164
+ it do
165
+ expect(b2a_qp("x y\tz", quote_tabs: true)).to eq('x=20y=09z')
166
+ end
167
+
168
+ it do
169
+ expect(b2a_qp("x y\tz", is_text: false)).to eq("x y\tz")
170
+ end
171
+
172
+ it do
173
+ expect(b2a_qp("x \ny\t\n")).to eq("x=20\ny=09\n")
174
+ end
175
+
176
+ it do
177
+ expect(b2a_qp("x \ny\t\n", quote_tabs: true)).to eq("x=20\ny=09\n")
178
+ end
179
+
180
+ it do
181
+ expect(b2a_qp("x \ny\t\n", is_text: false)).to eq("x =0Ay\t=0A")
182
+ end
183
+
184
+ it do
185
+ expect(b2a_qp("x \ry\t\r")).to eq("x \ry\t\r")
186
+ end
187
+
188
+ it do
189
+ expect(b2a_qp("x \ry\t\r", quote_tabs: true)).to eq("x=20\ry=09\r")
190
+ end
191
+
192
+ it do
193
+ expect(b2a_qp("x \ry\t\r", is_text: false)).to eq("x =0Dy\t=0D")
194
+ end
195
+
196
+ it do
197
+ expect(b2a_qp("x \r\ny\t\r\n")).to eq("x=20\r\ny=09\r\n")
198
+ end
199
+
200
+ it do
201
+ expect(b2a_qp("x \r\ny\t\r\n", quote_tabs: true)).to eq("x=20\r\ny=09\r\n")
202
+ end
203
+
204
+ it do
205
+ expect(b2a_qp("x \r\ny\t\r\n", is_text: false)).to eq("x =0D=0Ay\t=0D=0A")
206
+ end
207
+
208
+ it do
209
+ expect(b2a_qp("x \r")).to eq("x \r")
210
+ end
211
+
212
+ it do
213
+ expect(b2a_qp("x\t\r")).to eq("x\t\r")
214
+ end
215
+
216
+ it do
217
+ expect(b2a_qp("x \r", quote_tabs: true)).to eq("x=20\r")
218
+ end
219
+
220
+ it do
221
+ expect(b2a_qp("x\t\r", quote_tabs: true)).to eq("x=09\r")
222
+ end
223
+
224
+ it do
225
+ expect(b2a_qp("x \r", is_text: false)).to eq('x =0D')
226
+ end
227
+
228
+ it do
229
+ expect(b2a_qp("x\t\r", is_text: false)).to eq("x\t=0D")
230
+ end
231
+
232
+ it do
233
+ expect(b2a_qp('.')).to eq('=2E')
234
+ end
235
+
236
+ it do
237
+ expect(b2a_qp(".\n")).to eq("=2E\n")
238
+ end
239
+
240
+ it do
241
+ expect(b2a_qp(".\r")).to eq("=2E\r")
242
+ end
243
+
244
+ it do
245
+ expect(b2a_qp(".\0")).to eq('=2E=00')
246
+ end
247
+
248
+ it do
249
+ expect(b2a_qp("a.\n")).to eq("a.\n")
250
+ end
251
+
252
+ it do
253
+ french = "J'interdis aux marchands de vanter trop leur marchandises. "\
254
+ "Car ils se font vite pédagogues et t'enseignent comme but ce qui n'est "\
255
+ "par essence qu'un moyen, et te trompant ainsi sur la route à suivre les "\
256
+ "voilà bientôt qui te dégradent, car si leur musique est vulgaire ils te "\
257
+ "fabriquent pour te la vendre une âme vulgaire."
258
+
259
+ expect(b2a_qp(french)).to eq(<<~END.gsub(/\r?\n/, "\r\n").strip)
260
+ J'interdis aux marchands de vanter trop leur marchandises. Car ils se font =
261
+ vite p=C3=A9dagogues et t'enseignent comme but ce qui n'est par essence qu'=
262
+ un moyen, et te trompant ainsi sur la route =C3=A0 suivre les voil=C3=A0 bi=
263
+ ent=C3=B4t qui te d=C3=A9gradent, car si leur musique est vulgaire ils te f=
264
+ abriquent pour te la vendre une =C3=A2me vulgaire.
265
+ END
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,9 @@
1
+ $:.push(File.dirname(__FILE__))
2
+
3
+ require 'rspec'
4
+ require 'binascii'
5
+ require 'pry-byebug'
6
+
7
+ RSpec.configure do |config|
8
+ # configure me here
9
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe Binascii do
4
+ def ascii8(str)
5
+ str.force_encoding('ASCII-8BIT')
6
+ end
7
+
8
+ describe '#a2b_uu' do
9
+ def a2b_uu(str)
10
+ described_class.a2b_uu(str)
11
+ end
12
+
13
+ it do
14
+ expect(a2b_uu("\x7f")).to eq(ascii8("\x00") * 31)
15
+ end
16
+
17
+ it do
18
+ expect(a2b_uu("\x80")).to eq(ascii8("\x00") * 32)
19
+ end
20
+
21
+ it do
22
+ expect(a2b_uu("\xff")).to eq(ascii8("\x00") * 31)
23
+ end
24
+
25
+ it do
26
+ expect(a2b_uu(" \n")).to eq('')
27
+ end
28
+
29
+ it do
30
+ expect(a2b_uu("`\n")).to eq('')
31
+ end
32
+
33
+ it do
34
+ expect(a2b_uu("$`$-A=```\n")).to eq(a2b_uu("$ $-A= \n"))
35
+ end
36
+ end
37
+
38
+ describe '#b2a_uu' do
39
+ def b2a_uu(str, options = {})
40
+ described_class.b2a_uu(str, **options)
41
+ end
42
+
43
+ it do
44
+ expect(b2a_uu('x')).to eq("!> \n")
45
+ end
46
+
47
+ it do
48
+ expect(b2a_uu('')).to eq(" \n")
49
+ end
50
+
51
+ it do
52
+ expect(b2a_uu('', backtick: true)).to eq("`\n")
53
+ end
54
+
55
+ it do
56
+ expect(b2a_uu("\x00Cat")).to eq("$ $-A= \n")
57
+ end
58
+
59
+ it do
60
+ expect(b2a_uu("\x00Cat", backtick: true)).to eq("$`$-A=```\n")
61
+ end
62
+ end
63
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: binascii
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Cameron Dutro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-04-16 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A Ruby version of Python's binascii module
14
+ email:
15
+ - camertron@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - CHANGELOG.md
21
+ - Gemfile
22
+ - README.md
23
+ - Rakefile
24
+ - binascii.gemspec
25
+ - lib/binascii.rb
26
+ - lib/binascii/base64.rb
27
+ - lib/binascii/crc32.rb
28
+ - lib/binascii/hex.rb
29
+ - lib/binascii/hqx.rb
30
+ - lib/binascii/qp.rb
31
+ - lib/binascii/utils.rb
32
+ - lib/binascii/uu.rb
33
+ - lib/binascii/version.rb
34
+ - spec/crc32_spec.rb
35
+ - spec/hex_spec.rb
36
+ - spec/hqx_spec.rb
37
+ - spec/qp_spec.rb
38
+ - spec/spec_helper.rb
39
+ - spec/uu_spec.rb
40
+ homepage: https://github.com/camertron/binascii
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 2.7.6
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: A Ruby version of Python's binascii module
64
+ test_files: []