binascii 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +14 -0
- data/README.md +92 -0
- data/Rakefile +13 -0
- data/binascii.gemspec +18 -0
- data/lib/binascii.rb +17 -0
- data/lib/binascii/base64.rb +13 -0
- data/lib/binascii/crc32.rb +11 -0
- data/lib/binascii/hex.rb +41 -0
- data/lib/binascii/hqx.rb +226 -0
- data/lib/binascii/qp.rb +107 -0
- data/lib/binascii/utils.rb +54 -0
- data/lib/binascii/uu.rb +20 -0
- data/lib/binascii/version.rb +3 -0
- data/spec/crc32_spec.rb +11 -0
- data/spec/hex_spec.rb +23 -0
- data/spec/hqx_spec.rb +44 -0
- data/spec/qp_spec.rb +268 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/uu_spec.rb +63 -0
- metadata +64 -0
checksums.yaml
ADDED
@@ -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
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -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
|
data/Rakefile
ADDED
data/binascii.gemspec
ADDED
@@ -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
|
data/lib/binascii.rb
ADDED
@@ -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
|
data/lib/binascii/hex.rb
ADDED
@@ -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
|
data/lib/binascii/hqx.rb
ADDED
@@ -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
|
data/lib/binascii/qp.rb
ADDED
@@ -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
|
data/lib/binascii/uu.rb
ADDED
@@ -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
|
data/spec/crc32_spec.rb
ADDED
data/spec/hex_spec.rb
ADDED
@@ -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
|
data/spec/hqx_spec.rb
ADDED
@@ -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
|
data/spec/qp_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
data/spec/uu_spec.rb
ADDED
@@ -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: []
|