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: /["'()]/


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

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"


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
765
# File 'lib/hermeneutics/escape.rb', line 731

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.



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

def encode str
  std.encode str
end

.encode_whole(str) ⇒ Object

:call-seq:

encode_whole( str)   -> str

Use the standard content encoding.



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

def encode_whole str
  std.encode_whole str
end

.lexer(str) ⇒ Object



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

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)


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

def needs? str
  std.needs? str
end

.stdObject

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



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

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

Instance Method Details

#decode(str) ⇒ Object



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

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."


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
624
# File 'lib/hermeneutics/escape.rb', line 599

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?="


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

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)


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

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