Class: Hermeneutics::HeaderExt

Inherits:
Object
  • Object
show all
Defined in:
lib/hermeneutics/escape.rb

Overview

Header field contents (RFC 2047) encoding

Examples

HeaderExt.encode "Jörg Müller"
                              #=> "=?utf-8?Q?J=C3=B6rg_M=C3=BCller?="
HeaderExt.decode "=?UTF-8?Q?J=C3=B6rg_M=C3=BCller?="
                              #=> "Jörg Müller"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params = nil) ⇒ HeaderExt

:call-seq:

new( [ parameters] )    -> con

Creates a HeaderExt converter.

See the encode method for an explanation of the parameters.

Examples

con = HeaderExt.new
con = HeaderExt.new base64: true, limit: 32, lower: true
con = HeaderExt.new mask: /["'()]/


540
541
542
543
544
545
546
547
548
549
# File 'lib/hermeneutics/escape.rb', line 540

def initialize params = nil
  if params then
    @base64 = params.delete :base64
    @limit  = params.delete :limit
    @lower  = params.delete :lower
    @mask   = params.delete :mask
    params.empty? or
      raise ArgumentError, "invalid parameter: #{params.keys.first}."
  end
end

Class Method Details

.decode(str) ⇒ Object

:call-seq:

decode( str)     -> str

Remove header field style escapes.

HeaderExt.decode "=?UTF-8?Q?J=C3=B6rg_M=C3=BCller?="
                              #=> "Jörg Müller"


730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
# File 'lib/hermeneutics/escape.rb', line 730

def decode str
  r, e = [], []
  v, l = nil, nil
  lexer str do |type,piece|
    case type
      when :decoded then
        e.push piece.encoding
        if l == :space and (v == :decoded or not v) then
          r.pop
        elsif l == :plain then
          r.push SPACE
        end
      when :space then
        nil
      when :plain then
        if l == :decoded then
          r.push SPACE
        end
    end
    r.push piece
    v, l = l, type
  end
  if l == :space and v == :decoded then
    r.pop
  end
  e.uniq!
  begin
    r.join
  rescue EncodingError
    raise if e.empty?
    f = e.shift
    r.each { |x| x.encode! f }
    retry
  end
end

.encode(str) ⇒ Object

:call-seq:

encode( str)   -> str

Use the standard content encoding.



709
710
711
# File 'lib/hermeneutics/escape.rb', line 709

def encode str
  std.encode str
end

.encode_whole(str) ⇒ Object

:call-seq:

encode_whole( str)   -> str

Use the standard content encoding.



718
719
720
# File 'lib/hermeneutics/escape.rb', line 718

def encode_whole str
  std.encode_whole str
end

.lexer(str) ⇒ Object



766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
# File 'lib/hermeneutics/escape.rb', line 766

def lexer str
  while str do
    str =~ /(\s+)|\B=\?(\S*?)\?([QB])\?(\S*?)\?=\B/i
    if $1 then
      yield :plain, $` unless $`.empty?
      yield :space, $&
    elsif $2 then
      yield :plain, $` unless $`.empty?
      d = unmask $2, $3, $4
      yield :decoded, d
    else
      yield :plain, str
    end
    str = $'.notempty?
  end
end

.needs?(str) ⇒ Boolean

:call-seq:

needs? str  -> true or false

Use the standard content encoding.

Returns:

  • (Boolean)


700
701
702
# File 'lib/hermeneutics/escape.rb', line 700

def needs? str
  std.needs? str
end

.stdObject

The standard header content encoding has a word break limit of 64.



691
692
693
# File 'lib/hermeneutics/escape.rb', line 691

def std
  @std ||= new limit: 64
end

Instance Method Details

#decode(str) ⇒ Object



683
684
685
# File 'lib/hermeneutics/escape.rb', line 683

def decode str
  self.class.decode str
end

#encode(str) ⇒ Object

:call-seq:

encode( str)   -> str

Create a header field style encoded string. The following parameters will be evaluated:

:base64    # build ?B? instead of ?Q?
:limit     # break words longer than this
:lower     # build lower case ?b? and ?q?
:mask      # a regular expression detecting characters to mask

The result will not contain any 8-bit characters. The encoding will be kept although it won’t have a meaning.

The parameter :mask will have no influence on the masking itself but will guarantee characters to be masked.

Examples

yodel = "Holleri du dödl di, diri diri dudl dö."

con = HeaderExt.new
con.encode yodel
  #=> "Holleri du =?UTF-8?Q?d=C3=B6dl?= di, diri diri dudl =?UTF-8?Q?d=C3=B6=2E?="

yodel.encode! "iso8859-1"
con.encode yodel
  #=> "Holleri du =?ISO8859-1?Q?d=F6dl?= di, diri diri dudl =?ISO8859-1?Q?d=F6=2E?="

e = ""
e.encode! "utf-8"      ; con.encode e      #=> "=?UTF-8?Q?=E2=82=AC?="
e.encode! "iso8859-15" ; con.encode e      #=> "=?ISO8859-15?Q?=A4?="
e.encode! "ms-ansi"    ; con.encode e      #=> "=?MS-ANSI?Q?=80?="

con = HeaderExt.new mask: /["'()]/
con.encode "'Stop!' said Fred."
  #=> "=?UTF-8?Q?=27Stop=21=27?= said Fred."


598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
# File 'lib/hermeneutics/escape.rb', line 598

def encode str
  do_encoding str do
    # I don't like this kind of programming style but it seems to work. BS
    r, enc = "", ""
    while str =~ /\S+/ do
      if needs? $& then
        (enc.notempty? || r) << $`
        enc << $&
      else
        if not enc.empty? then
          r << (mask enc)
          enc.clear
        end
        r << $` << $&
      end
      str = $'
    end
    if not enc.empty? then
      enc << str
      r << (mask enc)
    else
      r << str
    end
    r
  end
end

#encode_whole(str) ⇒ Object

:call-seq:

encode_whole( str)   -> str

The unlike encode the whole string as one piece will be encoded.

yodel = "Holleri du dödl di, diri diri dudl dö."
HeaderExt.encode_whole yodel
  #=> "=?UTF-8?Q?Holleri_du_d=C3=B6dl_di,_diri_diri_dudl_d=C3=B6=2E?="


634
635
636
637
638
# File 'lib/hermeneutics/escape.rb', line 634

def encode_whole str
  do_encoding str do
    mask str
  end
end

#needs?(str) ⇒ Boolean

:call-seq:

needs? str  -> true or false

Check whether a string needs encoding.

Returns:

  • (Boolean)


556
557
558
# File 'lib/hermeneutics/escape.rb', line 556

def needs? str
  (not str.ascii_only? or str =~ @mask) and true or false
end