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


549
550
551
552
553
554
555
556
557
558
# File 'lib/hermeneutics/escape.rb', line 549

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"


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
766
767
768
769
770
771
772
773
# File 'lib/hermeneutics/escape.rb', line 739

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.



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

def encode str
  std.encode str
end

.encode_whole(str) ⇒ Object

:call-seq:

encode_whole( str)   -> str

Use the standard content encoding.



727
728
729
# File 'lib/hermeneutics/escape.rb', line 727

def encode_whole str
  std.encode_whole str
end

.lexer(str) ⇒ Object



775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
# File 'lib/hermeneutics/escape.rb', line 775

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)


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

def needs? str
  std.needs? str
end

.stdObject

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



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

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

Instance Method Details

#decode(str) ⇒ Object



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

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


607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
# File 'lib/hermeneutics/escape.rb', line 607

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


643
644
645
646
647
# File 'lib/hermeneutics/escape.rb', line 643

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)


565
566
567
# File 'lib/hermeneutics/escape.rb', line 565

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