Froze rails gems
[depot.git] / vendor / rails / actionmailer / lib / action_mailer / vendor / tmail-1.2.3 / tmail / scanner_r.rb
diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/scanner_r.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/scanner_r.rb
new file mode 100644 (file)
index 0000000..f207550
--- /dev/null
@@ -0,0 +1,261 @@
+# scanner_r.rb
+#
+#--
+# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
+# with permission of Minero Aoki.
+#++
+#:stopdoc:
+require 'tmail/config'
+
+module TMail
+
+  class TMailScanner
+
+    Version = '1.2.3'
+    Version.freeze
+
+    MIME_HEADERS = {
+      :CTYPE        => true,
+      :CENCODING    => true,
+      :CDISPOSITION => true
+    }
+
+    alnum      = 'a-zA-Z0-9'
+    atomsyms   = %q[  _#!$%&`'*+-{|}~^/=?  ].strip
+    tokensyms  = %q[  _#!$%&`'*+-{|}~^@.    ].strip
+    atomchars  = alnum + Regexp.quote(atomsyms)
+    tokenchars = alnum + Regexp.quote(tokensyms)
+    iso2022str = '\e(?!\(B)..(?:[^\e]+|\e(?!\(B)..)*\e\(B'
+
+    eucstr  = "(?:[\xa1-\xfe][\xa1-\xfe])+"
+    sjisstr = "(?:[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc])+"
+    utf8str = "(?:[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf])+"
+
+    quoted_with_iso2022  = /\A(?:[^\\\e"]+|#{iso2022str})+/n
+    domlit_with_iso2022  = /\A(?:[^\\\e\]]+|#{iso2022str})+/n
+    comment_with_iso2022 = /\A(?:[^\\\e()]+|#{iso2022str})+/n
+
+    quoted_without_iso2022  = /\A[^\\"]+/n
+    domlit_without_iso2022  = /\A[^\\\]]+/n
+    comment_without_iso2022 = /\A[^\\()]+/n
+
+    PATTERN_TABLE = {}
+    PATTERN_TABLE['EUC'] =
+      [
+        /\A(?:[#{atomchars}]+|#{iso2022str}|#{eucstr})+/n,
+        /\A(?:[#{tokenchars}]+|#{iso2022str}|#{eucstr})+/n,
+        quoted_with_iso2022,
+        domlit_with_iso2022,
+        comment_with_iso2022
+      ]
+    PATTERN_TABLE['SJIS'] =
+      [
+        /\A(?:[#{atomchars}]+|#{iso2022str}|#{sjisstr})+/n,
+        /\A(?:[#{tokenchars}]+|#{iso2022str}|#{sjisstr})+/n,
+        quoted_with_iso2022,
+        domlit_with_iso2022,
+        comment_with_iso2022
+      ]
+    PATTERN_TABLE['UTF8'] =
+      [
+        /\A(?:[#{atomchars}]+|#{utf8str})+/n,
+        /\A(?:[#{tokenchars}]+|#{utf8str})+/n,
+        quoted_without_iso2022,
+        domlit_without_iso2022,
+        comment_without_iso2022
+      ]
+    PATTERN_TABLE['NONE'] =
+      [
+        /\A[#{atomchars}]+/n,
+        /\A[#{tokenchars}]+/n,
+        quoted_without_iso2022,
+        domlit_without_iso2022,
+        comment_without_iso2022
+      ]
+
+
+    def initialize( str, scantype, comments )
+      init_scanner str
+      @comments = comments || []
+      @debug    = false
+
+      # fix scanner mode
+      @received  = (scantype == :RECEIVED)
+      @is_mime_header = MIME_HEADERS[scantype]
+
+      atom, token, @quoted_re, @domlit_re, @comment_re = PATTERN_TABLE[TMail.KCODE]
+      @word_re = (MIME_HEADERS[scantype] ? token : atom)
+    end
+
+    attr_accessor :debug
+
+    def scan( &block )
+      if @debug
+        scan_main do |arr|
+          s, v = arr
+          printf "%7d %-10s %s\n",
+                 rest_size(),
+                 s.respond_to?(:id2name) ? s.id2name : s.inspect,
+                 v.inspect
+          yield arr
+        end
+      else
+        scan_main(&block)
+      end
+    end
+
+    private
+
+    RECV_TOKEN = {
+      'from' => :FROM,
+      'by'   => :BY,
+      'via'  => :VIA,
+      'with' => :WITH,
+      'id'   => :ID,
+      'for'  => :FOR
+    }
+
+    def scan_main
+      until eof?
+        if skip(/\A[\n\r\t ]+/n)   # LWSP
+          break if eof?
+        end
+
+        if s = readstr(@word_re)
+          if @is_mime_header
+            yield [:TOKEN, s]
+          else
+            # atom
+            if /\A\d+\z/ === s
+              yield [:DIGIT, s]
+            elsif @received
+              yield [RECV_TOKEN[s.downcase] || :ATOM, s]
+            else
+              yield [:ATOM, s]
+            end
+          end
+
+        elsif skip(/\A"/)
+          yield [:QUOTED, scan_quoted_word()]
+
+        elsif skip(/\A\[/)
+          yield [:DOMLIT, scan_domain_literal()]
+
+        elsif skip(/\A\(/)
+          @comments.push scan_comment()
+
+        else
+          c = readchar()
+          yield [c, c]
+        end
+      end
+
+      yield [false, '$']
+    end
+
+    def scan_quoted_word
+      scan_qstr(@quoted_re, /\A"/, 'quoted-word')
+    end
+
+    def scan_domain_literal
+      '[' + scan_qstr(@domlit_re, /\A\]/, 'domain-literal') + ']'
+    end
+
+    def scan_qstr( pattern, terminal, type )
+      result = ''
+      until eof?
+        if    s = readstr(pattern) then result << s
+        elsif skip(terminal)       then return result
+        elsif skip(/\A\\/)         then result << readchar()
+        else
+          raise "TMail FATAL: not match in #{type}"
+        end
+      end
+      scan_error! "found unterminated #{type}"
+    end
+
+    def scan_comment
+      result = ''
+      nest = 1
+      content = @comment_re
+
+      until eof?
+        if s = readstr(content) then result << s
+        elsif skip(/\A\)/)      then nest -= 1
+                                     return result if nest == 0
+                                     result << ')'
+        elsif skip(/\A\(/)      then nest += 1
+                                     result << '('
+        elsif skip(/\A\\/)      then result << readchar()
+        else
+          raise 'TMail FATAL: not match in comment'
+        end
+      end
+      scan_error! 'found unterminated comment'
+    end
+
+    # string scanner
+
+    def init_scanner( str )
+      @src = str
+    end
+
+    def eof?
+      @src.empty?
+    end
+
+    def rest_size
+      @src.size
+    end
+
+    def readstr( re )
+      if m = re.match(@src)
+        @src = m.post_match
+        m[0]
+      else
+        nil
+      end
+    end
+
+    def readchar
+      readstr(/\A./)
+    end
+
+    def skip( re )
+      if m = re.match(@src)
+        @src = m.post_match
+        true
+      else
+        false
+      end
+    end
+
+    def scan_error!( msg )
+      raise SyntaxError, msg
+    end
+
+  end
+
+end   # module TMail
+#:startdoc:
\ No newline at end of file