-
-
Save adacosta/199854 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'base64' | |
require 'test/unit' | |
module B64 | |
CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split '' | |
# === Encode Non-MIME | |
# convert string to binary | |
# copy groups of 8 bits to 6 bits | |
# add b64 padding - 0 fill (to 6) the right side of the last bit grouping | |
# add byte padding (1.8 + 1.9 compat) | |
def self.encode64(string="") | |
encoded, buffer = '', string.unpack('B*')[0] | |
buffer.scan(/.{6}/).each { |nib| encoded << CHARS[nib.to_i(2)] } | |
encoded << CHARS[((buffer[-(buffer.size % 6)..-1] << "00000")[/^(.{6})(.+)/,1]).to_i(2)] | |
(string.send((string.respond_to?(:bytesize) ? :bytesize : :size)) % 4).times { encoded << '=' } | |
encoded | |
end | |
# === Decode MIME and non-MIME | |
# iterate string as character array | |
# left pad each 6 bit representation with 0s | |
# lop off trailing 0s (from encoded fill) | |
# covert decoded bits to new character set | |
def self.decode64(string="") | |
decoded = "" | |
string.unpack('C*').each do |char_num| | |
b64_index = CHARS.index(char_num.chr) | |
decoded << "%06d" % b64_index.to_s(2) if b64_index | |
end | |
(decoded.size % 8).times { decoded.chop! } | |
decoded.gsub!(/(.{8})/) { |b| b.to_i(2).chr } | |
end | |
end | |
class TC_B64 < Test::Unit::TestCase | |
LOGIN_STRING = "username:password" | |
STRING = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." | |
PARAGRAPH = %Q[ | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit. | |
Fusce dolor massa, tincidunt eu pulvinar id, congue vel lacus. | |
Ut at nisi volutpat elit consequat facilisis. | |
Nam imperdiet fringilla urna, ut ultricies tellus hendrerit sed. | |
Sed eleifend velit ut enim ultrices tincidunt. | |
Cras non eros augue, non posuere nibh. Vivamus sit amet nisl magna, eu blandit ante. | |
Curabitur nec magna eget nibh porttitor congue vel sed felis. | |
Phasellus vitae consectetur purus. Curabitur luctus tortor ac nisl lobortis imperdiet. | |
Integer eu pharetra mi. Aenean luctus nibh et est iaculis vehicula. | |
Nunc dictum accumsan urna, vitae auctor nisl consequat ut. Donec at tortor dolor, | |
varius placerat libero. Donec consequat pulvinar urna, non posuere libero tempor at. | |
] | |
def test_encode_and_decode | |
assert_equal LOGIN_STRING, B64.decode64(B64.encode64(LOGIN_STRING)) | |
assert_equal STRING, B64.decode64(B64.encode64(STRING)) | |
assert_equal PARAGRAPH, B64.decode64(B64.encode64(PARAGRAPH)) | |
end | |
def test_encode_is_non_mime | |
# \n is a notable MIME marker | |
assert (B64.encode64(PARAGRAPH)[/\n/].nil?) | |
# Base64 encodes mime...verify our output doesn't match | |
assert_not_equal Base64.encode64(PARAGRAPH), B64.encode64(PARAGRAPH) | |
end | |
# NOTE: Depending on byte alignment, codings can be equal. | |
# One example is the included STRING test, where PARAGRAPH wouldn't | |
# show the same result. | |
# assert_equal PARAGRAPH, Base64.decode64(B64.encode64(PARAGRAPH)) #=> true | |
def test_base64_std_lib_fails_decoding_non_mime | |
# Base64 can't decode non-MIME encoded base64 | |
assert_not_equal STRING, Base64.decode64(B64.encode64(STRING)) | |
end | |
def test_can_decode_base64_std_lib | |
# decode works on MIME encoded base64 | |
assert_equal LOGIN_STRING, B64.decode64(Base64.encode64(LOGIN_STRING)) | |
assert_equal STRING, B64.decode64(Base64.encode64(STRING)) | |
assert_equal PARAGRAPH, B64.decode64(Base64.encode64(PARAGRAPH)) | |
end | |
# require "benchmark" | |
# def test_zbenchies | |
# n = 5000 | |
# encoded_login_string = B64.encode64(LOGIN_STRING) | |
# puts "" | |
# Benchmark.bm do |x| | |
# x.report("Base64.encode64") { n.times do; Base64.encode64(LOGIN_STRING); end } | |
# x.report("B64.encode64") { n.times do ; B64.encode64(LOGIN_STRING); end } | |
# x.report("Base64.decode64") { n.times do; Base64.decode64(encoded_login_string); end } | |
# x.report("B64.decode64") { n.times do ; B64.decode64(encoded_login_string); end } | |
# end | |
# end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment