Module: Rfc2047

Defined in:
lib/rfc_2047.rb

Overview

Copyright © 2020 Jian Weihang <[email protected]> frozen_string_literal: true

Constant Summary collapse

TOKEN =
/[\041\043-\047\052\053\055\060-\071\101-\132\134\136\137\141-\176]+/.freeze
ENCODED_TEXT =
/[\041-\076\100-\176]*/.freeze
ENCODED_WORD =
/=\?(?<charset>#{TOKEN})\?(?<encoding>[QBqb])\?(?<encoded_text>#{ENCODED_TEXT})\?=/.freeze
ENCODED_WORD_SEQUENCE =
/#{ENCODED_WORD}(?:\s*#{ENCODED_WORD})*/.freeze

Class Method Summary collapse

Class Method Details

.decode(input) ⇒ Object

example

Rfc2047.decode '=?UTF-8?B?5Yu/5Lul5oOh5bCP6ICM54K65LmL77yM5Yu/5Lul5ZaE5bCP6ICM5LiN54K6?= =?UTF-8?B?44CC?='
# => "勿以惡小而為之,勿以善小而不為。"


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/rfc_2047.rb', line 36

def decode(input)
  return input unless input.match?(ENCODED_WORD)

  input.gsub(ENCODED_WORD_SEQUENCE) do |match|
    result = +''
    match.scan(ENCODED_WORD) { result << decode_word($&) }
    if result.encoding == Encoding::UTF_7
      result.replace(
        decode_utf7(result.force_encoding(Encoding::BINARY))
      ).force_encoding(Encoding::UTF_8)
    else
      result.encode!(Encoding::UTF_8)
    end
    result
  end
end

.encode(input, encoding: :B) ⇒ Object

example:

Rfc2047.encode('己所不欲,勿施於人。')
# => "=?UTF-8?B?5bex5omA5LiN5qyy77yM5Yu/5pa95pa85Lq644CC?="


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rfc_2047.rb', line 15

def encode(input, encoding: :B)
  return input if input.ascii_only?

  case encoding
  when :B
    size = 45
    chunks = Array.new(((input.bytesize + size - 1) / size)) { input.byteslice(_1 * size, size) }
    chunks.map! { "=?#{input.encoding}?B?#{[_1].pack('m0')}?=" }.join(' ')
  when :Q
    [input]
      .pack('M').each_line
      .map { "=?#{input.encoding}?Q?#{_1.chomp!.gsub(' ', '_')}?=" }
      .join(' ')
  else raise ":encoding should be either :B or :Q, got #{encoding}"
  end
end