From 2a51c8682d44ee71a3c0411e2e30ef8ff29d6f67 Mon Sep 17 00:00:00 2001 From: Rick Olson Date: Tue, 6 Nov 2007 14:24:32 +0000 Subject: [PATCH] Update TMail to v1.1.0. Use an updated version of TMail if available. [mikel] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8084 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionmailer/CHANGELOG | 2 + actionmailer/lib/action_mailer.rb | 11 +- .../lib/action_mailer/vendor/tmail.rb | 3 +- .../lib/action_mailer/vendor/tmail/Makefile | 19 + .../lib/action_mailer/vendor/tmail/address.rb | 9 +- .../action_mailer/vendor/tmail/attachments.rb | 6 + .../lib/action_mailer/vendor/tmail/base64.rb | 8 +- .../lib/action_mailer/vendor/tmail/compat.rb | 39 ++ .../lib/action_mailer/vendor/tmail/config.rb | 8 +- .../vendor/tmail/core_extensions.rb | 67 +++ .../lib/action_mailer/vendor/tmail/encode.rb | 32 +- .../lib/action_mailer/vendor/tmail/header.rb | 29 +- .../action_mailer/vendor/tmail/interface.rb | 540 ++++++++++++++++++ .../lib/action_mailer/vendor/tmail/mail.rb | 25 +- .../lib/action_mailer/vendor/tmail/mailbox.rb | 8 +- .../lib/action_mailer/vendor/tmail/net.rb | 8 +- .../action_mailer/vendor/tmail/obsolete.rb | 8 +- .../lib/action_mailer/vendor/tmail/parser.rb | 515 ++++++++--------- .../lib/action_mailer/vendor/tmail/parser.y | 381 ++++++++++++ .../lib/action_mailer/vendor/tmail/port.rb | 8 +- .../lib/action_mailer/vendor/tmail/quoting.rb | 5 + .../lib/action_mailer/vendor/tmail/scanner.rb | 8 +- .../action_mailer/vendor/tmail/stringio.rb | 10 +- .../lib/action_mailer/vendor/tmail/utils.rb | 57 +- .../lib/action_mailer/vendor/tmail/version.rb | 38 ++ ...il_with_invalid_characters_in_content_type | 104 ++++ 26 files changed, 1610 insertions(+), 338 deletions(-) create mode 100644 actionmailer/lib/action_mailer/vendor/tmail/Makefile create mode 100644 actionmailer/lib/action_mailer/vendor/tmail/compat.rb create mode 100644 actionmailer/lib/action_mailer/vendor/tmail/core_extensions.rb create mode 100644 actionmailer/lib/action_mailer/vendor/tmail/interface.rb create mode 100644 actionmailer/lib/action_mailer/vendor/tmail/parser.y create mode 100644 actionmailer/lib/action_mailer/vendor/tmail/version.rb create mode 100644 actionmailer/test/fixtures/raw_email_with_invalid_characters_in_content_type diff --git a/actionmailer/CHANGELOG b/actionmailer/CHANGELOG index b4122e7072..2e4f5cfe33 100644 --- a/actionmailer/CHANGELOG +++ b/actionmailer/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Update TMail to v1.1.0. Use an updated version of TMail if available. [mikel] + * Introduce a new base test class for testing Mailers. ActionMailer::TestCase [Koz] * Fix silent failure of rxml templates. #9879 [jstewart] diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb index 4b3d5f35c1..28fe5b3cf7 100755 --- a/actionmailer/lib/action_mailer.rb +++ b/actionmailer/lib/action_mailer.rb @@ -31,14 +31,23 @@ unless defined?(ActionController) end end +# attempt to load the TMail gem +begin + require 'rubygems' + gem 'TMail', '> 1.1.0' + require 'tmail' +rescue Gem::LoadError + # no gem, fall back to vendor copy +end + $:.unshift(File.dirname(__FILE__) + "/action_mailer/vendor/") +require 'tmail' require 'action_mailer/base' require 'action_mailer/helpers' require 'action_mailer/mail_helper' require 'action_mailer/quoting' require 'action_mailer/test_helper' -require 'tmail' require 'net/smtp' ActionMailer::Base.class_eval do diff --git a/actionmailer/lib/action_mailer/vendor/tmail.rb b/actionmailer/lib/action_mailer/vendor/tmail.rb index 8cea88d3ed..7de185019b 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail.rb @@ -1,3 +1,4 @@ -require 'tmail/info' +require 'tmail/version' require 'tmail/mail' require 'tmail/mailbox' +require 'tmail/core_extensions' diff --git a/actionmailer/lib/action_mailer/vendor/tmail/Makefile b/actionmailer/lib/action_mailer/vendor/tmail/Makefile new file mode 100644 index 0000000000..346353b83f --- /dev/null +++ b/actionmailer/lib/action_mailer/vendor/tmail/Makefile @@ -0,0 +1,19 @@ +# +# lib/tmail/Makefile +# + +debug: + rm -f parser.rb + make parser.rb DEBUG=true + +parser.rb: parser.y + if [ "$(DEBUG)" = true ]; then \ + racc -v -g -o$@ parser.y ;\ + else \ + racc -E -o$@ parser.y ;\ + fi + +clean: + rm -f parser.rb parser.output + +distclean: clean diff --git a/actionmailer/lib/action_mailer/vendor/tmail/address.rb b/actionmailer/lib/action_mailer/vendor/tmail/address.rb index 235ec7618b..224ed7090e 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/address.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/address.rb @@ -1,5 +1,8 @@ -# -# address.rb +=begin rdoc + += Address handling class + +=end # #-- # Copyright (c) 1998-2003 Minero Aoki @@ -51,6 +54,7 @@ module TMail raise SyntaxError, 'empty word in domain' if s.empty? end end + @local = local @domain = domain @name = nil @@ -96,7 +100,6 @@ module TMail alias address spec - def ==( other ) other.respond_to? :spec and self.spec == other.spec end diff --git a/actionmailer/lib/action_mailer/vendor/tmail/attachments.rb b/actionmailer/lib/action_mailer/vendor/tmail/attachments.rb index 7961b03ac5..a8b8017cf9 100644 --- a/actionmailer/lib/action_mailer/vendor/tmail/attachments.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/attachments.rb @@ -1,3 +1,9 @@ +=begin rdoc + += Attachment handling class + +=end + require 'stringio' module TMail diff --git a/actionmailer/lib/action_mailer/vendor/tmail/base64.rb b/actionmailer/lib/action_mailer/vendor/tmail/base64.rb index 5713827521..41189f8c34 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/base64.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/base64.rb @@ -1,6 +1,8 @@ -# -# base64.rb -# +=begin rdoc + += Base64 handling class + +=end #-- # Copyright (c) 1998-2003 Minero Aoki # diff --git a/actionmailer/lib/action_mailer/vendor/tmail/compat.rb b/actionmailer/lib/action_mailer/vendor/tmail/compat.rb new file mode 100644 index 0000000000..9d2aa83798 --- /dev/null +++ b/actionmailer/lib/action_mailer/vendor/tmail/compat.rb @@ -0,0 +1,39 @@ +unless Enumerable.method_defined?(:map) + module Enumerable + alias map collect + end +end + +unless Enumerable.method_defined?(:select) + module Enumerable + alias select find_all + end +end + +unless Enumerable.method_defined?(:reject) + module Enumerable + def reject + result = [] + each do |i| + result.push i unless yield(i) + end + result + end + end +end + +unless Enumerable.method_defined?(:sort_by) + module Enumerable + def sort_by + map {|i| [yield(i), i] }.sort.map {|val, i| i } + end + end +end + +unless File.respond_to?(:read) + def File.read(fname) + File.open(fname) {|f| + return f.read + } + end +end diff --git a/actionmailer/lib/action_mailer/vendor/tmail/config.rb b/actionmailer/lib/action_mailer/vendor/tmail/config.rb index b075299be1..4b253d2b2a 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/config.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/config.rb @@ -1,6 +1,8 @@ -# -# config.rb -# +=begin rdoc + += Configuration Class + +=end #-- # Copyright (c) 1998-2003 Minero Aoki # diff --git a/actionmailer/lib/action_mailer/vendor/tmail/core_extensions.rb b/actionmailer/lib/action_mailer/vendor/tmail/core_extensions.rb new file mode 100644 index 0000000000..cc24e97778 --- /dev/null +++ b/actionmailer/lib/action_mailer/vendor/tmail/core_extensions.rb @@ -0,0 +1,67 @@ +=begin rdoc + += Ruby on Rails Core Extensions + +provides .blank? + +=end +unless Object.respond_to?(:blank?) #:nodoc: + # Check first to see if we are in a Rails environment, no need to + # define these methods if we are + class Object + # An object is blank if it's nil, empty, or a whitespace string. + # For example, "", " ", nil, [], and {} are blank. + # + # This simplifies + # if !address.nil? && !address.empty? + # to + # if !address.blank? + def blank? + if respond_to?(:empty?) && respond_to?(:strip) + empty? or strip.empty? + elsif respond_to?(:empty?) + empty? + else + !self + end + end + end + + class NilClass #:nodoc: + def blank? + true + end + end + + class FalseClass #:nodoc: + def blank? + true + end + end + + class TrueClass #:nodoc: + def blank? + false + end + end + + class Array #:nodoc: + alias_method :blank?, :empty? + end + + class Hash #:nodoc: + alias_method :blank?, :empty? + end + + class String #:nodoc: + def blank? + empty? || strip.empty? + end + end + + class Numeric #:nodoc: + def blank? + false + end + end +end \ No newline at end of file diff --git a/actionmailer/lib/action_mailer/vendor/tmail/encode.rb b/actionmailer/lib/action_mailer/vendor/tmail/encode.rb index 91bd289c5b..0721a25490 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/encode.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/encode.rb @@ -1,6 +1,8 @@ -# -# encode.rb -# +=begin rdoc + += Text Encoding class + +=end #-- # Copyright (c) 1998-2003 Minero Aoki # @@ -50,23 +52,25 @@ module TMail end end module_function :create_dest - + def encoded( eol = "\r\n", charset = 'j', dest = nil ) accept_strategy Encoder, eol, charset, dest end - + def decoded( eol = "\n", charset = 'e', dest = nil ) + # Turn the E-Mail into a string and return it with all + # encoded characters decoded. alias for to_s accept_strategy Decoder, eol, charset, dest end - + alias to_s decoded - + def accept_strategy( klass, eol, charset, dest = nil ) dest ||= '' - accept klass.new(create_dest(dest), charset, eol) + accept klass.new( create_dest(dest), charset, eol ) dest end - + end @@ -141,6 +145,7 @@ module TMail end def kv_pair( k, v ) + v = dquote(v) unless token_safe?(v) @f << k << '=' << v end @@ -190,9 +195,18 @@ module TMail @f = StrategyInterface.create_dest(dest) @opt = OPTIONS[$KCODE] @eol = eol + @preserve_quotes = true reset end + def preserve_quotes=( bool ) + @preserve_quotes + end + + def preserve_quotes + @preserve_quotes + end + def normalize_encoding( str ) if @opt then NKF.nkf(@opt, str) diff --git a/actionmailer/lib/action_mailer/vendor/tmail/header.rb b/actionmailer/lib/action_mailer/vendor/tmail/header.rb index be97803def..41c371f37f 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/header.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/header.rb @@ -1,5 +1,10 @@ -# -# header.rb +=begin rdoc + += Header handling class + +=end +# RFC #822 ftp://ftp.isi.edu/in-notes/rfc822.txt +# # #-- # Copyright (c) 1998-2003 Minero Aoki @@ -76,6 +81,7 @@ module TMail @illegal = false @parsed = false + if intern @parsed = true parse_init @@ -129,7 +135,7 @@ module TMail include StrategyInterface - def accept( strategy, dummy1 = nil, dummy2 = nil ) + def accept( strategy ) ensure_parsed do_accept strategy strategy.terminate @@ -207,6 +213,7 @@ module TMail end def do_parse + quote_boundary obj = Parser.parse(self.class::PARSE_TYPE, @body, @comments) set obj if obj end @@ -739,12 +746,17 @@ module TMail def params ensure_parsed + unless @params.blank? + @params.each do |k, v| + @params[k] = unquote(v) + end + end @params end def []( key ) ensure_parsed - @params and @params[key] + @params and unquote(@params[key]) end def []=( key, val ) @@ -835,12 +847,17 @@ module TMail def params ensure_parsed + unless @params.blank? + @params.each do |k, v| + @params[k] = unquote(v) + end + end @params end def []( key ) ensure_parsed - @params and @params[key] + @params and unquote(@params[key]) end def []=( key, val ) @@ -867,7 +884,7 @@ module TMail @params.each do |k,v| strategy.meta ';' strategy.space - strategy.kv_pair k, v + strategy.kv_pair k, unquote(v) end end diff --git a/actionmailer/lib/action_mailer/vendor/tmail/interface.rb b/actionmailer/lib/action_mailer/vendor/tmail/interface.rb new file mode 100644 index 0000000000..957e899734 --- /dev/null +++ b/actionmailer/lib/action_mailer/vendor/tmail/interface.rb @@ -0,0 +1,540 @@ +=begin rdoc + += Facade.rb Provides an interface to the TMail object + +=end +#-- +# Copyright (c) 1998-2003 Minero Aoki +# +# 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. +#++ + +require 'tmail/utils' + +module TMail + + class Mail + + def header_string( name, default = nil ) + h = @header[name.downcase] or return default + h.to_s + end + + ### + ### attributes + ### + + include TextUtils + + def set_string_array_attr( key, strs ) + strs.flatten! + if strs.empty? + @header.delete key.downcase + else + store key, strs.join(', ') + end + strs + end + private :set_string_array_attr + + def set_string_attr( key, str ) + if str + store key, str + else + @header.delete key.downcase + end + str + end + private :set_string_attr + + def set_addrfield( name, arg ) + if arg + h = HeaderField.internal_new(name, @config) + h.addrs.replace [arg].flatten + @header[name] = h + else + @header.delete name + end + arg + end + private :set_addrfield + + def addrs2specs( addrs ) + return nil unless addrs + list = addrs.map {|addr| + if addr.address_group? + then addr.map {|a| a.spec } + else addr.spec + end + }.flatten + return nil if list.empty? + list + end + private :addrs2specs + + # + # date time + # + + def date( default = nil ) + if h = @header['date'] + h.date + else + default + end + end + + def date=( time ) + if time + store 'Date', time2str(time) + else + @header.delete 'date' + end + time + end + + def strftime( fmt, default = nil ) + if t = date + t.strftime(fmt) + else + default + end + end + + # + # destination + # + + def to_addrs( default = nil ) + if h = @header['to'] + h.addrs + else + default + end + end + + def cc_addrs( default = nil ) + if h = @header['cc'] + h.addrs + else + default + end + end + + def bcc_addrs( default = nil ) + if h = @header['bcc'] + h.addrs + else + default + end + end + + def to_addrs=( arg ) + set_addrfield 'to', arg + end + + def cc_addrs=( arg ) + set_addrfield 'cc', arg + end + + def bcc_addrs=( arg ) + set_addrfield 'bcc', arg + end + + def to( default = nil ) + addrs2specs(to_addrs(nil)) || default + end + + def cc( default = nil ) + addrs2specs(cc_addrs(nil)) || default + end + + def bcc( default = nil ) + addrs2specs(bcc_addrs(nil)) || default + end + + def to=( *strs ) + set_string_array_attr 'To', strs + end + + def cc=( *strs ) + set_string_array_attr 'Cc', strs + end + + def bcc=( *strs ) + set_string_array_attr 'Bcc', strs + end + + # + # originator + # + + def from_addrs( default = nil ) + if h = @header['from'] + h.addrs + else + default + end + end + + def from_addrs=( arg ) + set_addrfield 'from', arg + end + + def from( default = nil ) + addrs2specs(from_addrs(nil)) || default + end + + def from=( *strs ) + set_string_array_attr 'From', strs + end + + def friendly_from( default = nil ) + h = @header['from'] + a, = h.addrs + return default unless a + return a.phrase if a.phrase + return h.comments.join(' ') unless h.comments.empty? + a.spec + end + + + def reply_to_addrs( default = nil ) + if h = @header['reply-to'] + h.addrs + else + default + end + end + + def reply_to_addrs=( arg ) + set_addrfield 'reply-to', arg + end + + def reply_to( default = nil ) + addrs2specs(reply_to_addrs(nil)) || default + end + + def reply_to=( *strs ) + set_string_array_attr 'Reply-To', strs + end + + + def sender_addr( default = nil ) + f = @header['sender'] or return default + f.addr or return default + end + + def sender_addr=( addr ) + if addr + h = HeaderField.internal_new('sender', @config) + h.addr = addr + @header['sender'] = h + else + @header.delete 'sender' + end + addr + end + + def sender( default ) + f = @header['sender'] or return default + a = f.addr or return default + a.spec + end + + def sender=( str ) + set_string_attr 'Sender', str + end + + + # + # subject + # + + def subject( default = nil ) + if h = @header['subject'] + h.body + else + default + end + end + alias quoted_subject subject + + def subject=( str ) + set_string_attr 'Subject', str + end + + # + # identity & threading + # + + def message_id( default = nil ) + if h = @header['message-id'] + h.id || default + else + default + end + end + + def message_id=( str ) + set_string_attr 'Message-Id', str + end + + def in_reply_to( default = nil ) + if h = @header['in-reply-to'] + h.ids + else + default + end + end + + def in_reply_to=( *idstrs ) + set_string_array_attr 'In-Reply-To', idstrs + end + + def references( default = nil ) + if h = @header['references'] + h.refs + else + default + end + end + + def references=( *strs ) + set_string_array_attr 'References', strs + end + + # + # MIME headers + # + + def mime_version( default = nil ) + if h = @header['mime-version'] + h.version || default + else + default + end + end + + def mime_version=( m, opt = nil ) + if opt + if h = @header['mime-version'] + h.major = m + h.minor = opt + else + store 'Mime-Version', "#{m}.#{opt}" + end + else + store 'Mime-Version', m + end + m + end + + def content_type( default = nil ) + if h = @header['content-type'] + h.content_type || default + else + default + end + end + + def main_type( default = nil ) + if h = @header['content-type'] + h.main_type || default + else + default + end + end + + def sub_type( default = nil ) + if h = @header['content-type'] + h.sub_type || default + else + default + end + end + + def set_content_type( str, sub = nil, param = nil ) + if sub + main, sub = str, sub + else + main, sub = str.split(%r, 2) + raise ArgumentError, "sub type missing: #{str.inspect}" unless sub + end + if h = @header['content-type'] + h.main_type = main + h.sub_type = sub + h.params.clear + else + store 'Content-Type', "#{main}/#{sub}" + end + @header['content-type'].params.replace param if param + str + end + + alias content_type= set_content_type + + def type_param( name, default = nil ) + if h = @header['content-type'] + h[name] || default + else + default + end + end + + def charset( default = nil ) + if h = @header['content-type'] + h['charset'] or default + else + default + end + end + + def charset=( str ) + if str + if h = @header[ 'content-type' ] + h['charset'] = str + else + store 'Content-Type', "text/plain; charset=#{str}" + end + end + str + end + + def transfer_encoding( default = nil ) + if h = @header['content-transfer-encoding'] + h.encoding || default + else + default + end + end + + def transfer_encoding=( str ) + set_string_attr 'Content-Transfer-Encoding', str + end + + alias encoding transfer_encoding + alias encoding= transfer_encoding= + alias content_transfer_encoding transfer_encoding + alias content_transfer_encoding= transfer_encoding= + + def disposition( default = nil ) + if h = @header['content-disposition'] + h.disposition || default + else + default + end + end + + alias content_disposition disposition + + def set_disposition( str, params = nil ) + if h = @header['content-disposition'] + h.disposition = str + h.params.clear + else + store('Content-Disposition', str) + h = @header['content-disposition'] + end + h.params.replace params if params + end + + alias disposition= set_disposition + alias set_content_disposition set_disposition + alias content_disposition= set_disposition + + def disposition_param( name, default = nil ) + if h = @header['content-disposition'] + h[name] || default + else + default + end + end + + ### + ### utils + ### + + def create_reply + mail = TMail::Mail.parse('') + mail.subject = 'Re: ' + subject('').sub(/\A(?:\[[^\]]+\])?(?:\s*Re:)*\s*/i, '') + mail.to_addrs = reply_addresses([]) + mail.in_reply_to = [message_id(nil)].compact + mail.references = references([]) + [message_id(nil)].compact + mail.mime_version = '1.0' + mail + end + + def base64_encode + store 'Content-Transfer-Encoding', 'Base64' + self.body = Base64.folding_encode(self.body) + end + + def base64_decode + if /base64/i === self.transfer_encoding('') + store 'Content-Transfer-Encoding', '8bit' + self.body = Base64.decode(self.body, @config.strict_base64decode?) + end + end + + def destinations( default = nil ) + ret = [] + %w( to cc bcc ).each do |nm| + if h = @header[nm] + h.addrs.each {|i| ret.push i.address } + end + end + ret.empty? ? default : ret + end + + def each_destination( &block ) + destinations([]).each do |i| + if Address === i + yield i + else + i.each(&block) + end + end + end + + alias each_dest each_destination + + def reply_addresses( default = nil ) + reply_to_addrs(nil) or from_addrs(nil) or default + end + + def error_reply_addresses( default = nil ) + if s = sender(nil) + [s] + else + from_addrs(default) + end + end + + def multipart? + main_type('').downcase == 'multipart' + end + + end # class Mail + +end # module TMail diff --git a/actionmailer/lib/action_mailer/vendor/tmail/mail.rb b/actionmailer/lib/action_mailer/vendor/tmail/mail.rb index e11fa0f0f8..d10275b734 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/mail.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/mail.rb @@ -1,6 +1,8 @@ -# -# mail.rb -# +=begin rdoc + += Mail class + +=end #-- # Copyright (c) 1998-2003 Minero Aoki # @@ -27,7 +29,7 @@ # with permission of Minero Aoki. #++ -require 'tmail/facade' +require 'tmail/interface' require 'tmail/encode' require 'tmail/header' require 'tmail/port' @@ -37,7 +39,6 @@ require 'tmail/attachments' require 'tmail/quoting' require 'socket' - module TMail class Mail @@ -53,6 +54,7 @@ module TMail def parse( str ) new(StringPort.new(str)) end + end def initialize( port = nil, conf = DEFAULT_CONFIG ) @@ -355,6 +357,19 @@ module TMail end def body=( str ) + # Sets the body of the email to a new (encoded) string. + # + # We also reparses the email if the body is ever reassigned, this is a performance hit, however when + # you assign the body, you usually want to be able to make sure that you can access the attachments etc. + # + # Usage: + # + # mail.body = "Hello, this is\nthe body text" + # # => "Hello, this is\nthe body" + # mail.body + # # => "Hello, this is\nthe body" + @body_parsed = false + parse_body(StringInput.new(str)) parse_body @body_port.wopen {|f| f.write str } str diff --git a/actionmailer/lib/action_mailer/vendor/tmail/mailbox.rb b/actionmailer/lib/action_mailer/vendor/tmail/mailbox.rb index d85915ed5a..bb7a460e1a 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/mailbox.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/mailbox.rb @@ -1,6 +1,8 @@ -# -# mailbox.rb -# +=begin rdoc + += Mailbox and Mbox interaction class + +=end #-- # Copyright (c) 1998-2003 Minero Aoki # diff --git a/actionmailer/lib/action_mailer/vendor/tmail/net.rb b/actionmailer/lib/action_mailer/vendor/tmail/net.rb index f96cf64c45..50b1dd95be 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/net.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/net.rb @@ -1,6 +1,8 @@ -# -# net.rb -# +=begin rdoc + += Net provides SMTP wrapping + +=end #-- # Copyright (c) 1998-2003 Minero Aoki # diff --git a/actionmailer/lib/action_mailer/vendor/tmail/obsolete.rb b/actionmailer/lib/action_mailer/vendor/tmail/obsolete.rb index f98be74775..b871510b82 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/obsolete.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/obsolete.rb @@ -1,6 +1,8 @@ -# -# obsolete.rb -# +=begin rdoc + += Obsolete methods that are depriciated + +=end #-- # Copyright (c) 1998-2003 Minero Aoki # diff --git a/actionmailer/lib/action_mailer/vendor/tmail/parser.rb b/actionmailer/lib/action_mailer/vendor/tmail/parser.rb index 825eca920d..5deb0ff655 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/parser.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/parser.rb @@ -1,38 +1,32 @@ -# # DO NOT MODIFY!!!! -# This file is automatically generated by racc 1.4.3 +# This file is automatically generated by racc 1.4.5 # from racc grammer file "parser.y". # # # parser.rb: generated by racc (runtime embedded) # - -###### racc/parser.rb - +###### racc/parser.rb begin unless $".index 'racc/parser.rb' $".push 'racc/parser.rb' -self.class.module_eval <<'..end /home/aamine/lib/ruby/racc/parser.rb modeval..idb76f2e220d', '/home/aamine/lib/ruby/racc/parser.rb', 1 +self.class.module_eval <<'..end racc/parser.rb modeval..id8076474214', 'racc/parser.rb', 1 # -# parser.rb +# $Id: parser.rb,v 1.7 2005/11/20 17:31:32 aamine Exp $ # -# Copyright (c) 1999-2003 Minero Aoki +# Copyright (c) 1999-2005 Minero Aoki # -# This program is free software. -# You can distribute/modify this program under the same terms of ruby. +# This program is free software. +# You can distribute/modify this program under the same terms of ruby. # -# As a special exception, when this code is copied by Racc -# into a Racc output file, you may use that output file -# without restriction. -# -# $Id: parser.rb,v 1.1.1.1 2004/10/14 11:59:58 webster132 Exp $ +# As a special exception, when this code is copied by Racc +# into a Racc output file, you may use that output file +# without restriction. # -unless defined? NotImplementedError +unless defined?(NotImplementedError) NotImplementedError = NotImplementError end - module Racc class ParseError < StandardError; end end @@ -40,24 +34,23 @@ unless defined?(::ParseError) ParseError = Racc::ParseError end - module Racc - unless defined? Racc_No_Extentions + unless defined?(Racc_No_Extentions) Racc_No_Extentions = false end class Parser - Racc_Runtime_Version = '1.4.3' - Racc_Runtime_Revision = '$Revision: 1.1.1.1 $'.split(/\s+/)[1] + Racc_Runtime_Version = '1.4.5' + Racc_Runtime_Revision = '$Revision: 1.7 $'.split[1] - Racc_Runtime_Core_Version_R = '1.4.3' - Racc_Runtime_Core_Revision_R = '$Revision: 1.1.1.1 $'.split(/\s+/)[1] + Racc_Runtime_Core_Version_R = '1.4.5' + Racc_Runtime_Core_Revision_R = '$Revision: 1.7 $'.split[1] begin require 'racc/cparse' # Racc_Runtime_Core_Version_C = (defined in extention) - Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split(/\s+/)[2] + Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split[2] unless new.respond_to?(:_racc_do_parse_c, true) raise LoadError, 'old cparse.so' end @@ -78,7 +71,7 @@ module Racc Racc_Runtime_Type = 'ruby' end - def self.racc_runtime_type + def Parser.racc_runtime_type Racc_Runtime_Type end @@ -86,9 +79,9 @@ module Racc def _racc_setup @yydebug = false unless self.class::Racc_debug_parser - @yydebug = false unless defined? @yydebug + @yydebug = false unless defined?(@yydebug) if @yydebug - @racc_debug_out = $stderr unless defined? @racc_debug_out + @racc_debug_out = $stderr unless defined?(@racc_debug_out) @racc_debug_out ||= $stderr end arg = self.class::Racc_arg @@ -110,20 +103,19 @@ module Racc @racc_error_status = 0 end - ### ### do_parse ### def do_parse - __send__ Racc_Main_Parsing_Routine, _racc_setup(), false + __send__(Racc_Main_Parsing_Routine, _racc_setup(), false) end def next_token raise NotImplementedError, "#{self.class}\#next_token is not defined" end - def _racc_do_parse_rb( arg, in_debug ) + def _racc_do_parse_rb(arg, in_debug) action_table, action_check, action_default, action_pointer, goto_table, goto_check, goto_default, goto_pointer, nt_base, reduce_table, token_table, shift_n, @@ -134,47 +126,45 @@ module Racc nerr = 0 catch(:racc_end_parse) { - while true - if i = action_pointer[@racc_state[-1]] - if @racc_read_next - if @racc_t != 0 # not EOF - tok, @racc_val = next_token() - unless tok # EOF - @racc_t = 0 - else - @racc_t = (token_table[tok] or 1) # error token - end - racc_read_token(@racc_t, tok, @racc_val) if @yydebug - @racc_read_next = false + while true + if i = action_pointer[@racc_state[-1]] + if @racc_read_next + if @racc_t != 0 # not EOF + tok, @racc_val = next_token() + unless tok # EOF + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1) # error token end + racc_read_token(@racc_t, tok, @racc_val) if @yydebug + @racc_read_next = false end - i += @racc_t - if i >= 0 and - act = action_table[i] and - action_check[i] == @racc_state[-1] - ; - else - act = action_default[@racc_state[-1]] - end - else + end + i += @racc_t + unless i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] act = action_default[@racc_state[-1]] end - while act = _racc_evalact(act, arg) - end + else + act = action_default[@racc_state[-1]] end + while act = _racc_evalact(act, arg) + ; + end + end } end - ### ### yyparse ### - def yyparse( recv, mid ) - __send__ Racc_YY_Parse_Method, recv, mid, _racc_setup(), true + def yyparse(recv, mid) + __send__(Racc_YY_Parse_Method, recv, mid, _racc_setup(), true) end - def _racc_yyparse_rb( recv, mid, arg, c_debug ) + def _racc_yyparse_rb(recv, mid, arg, c_debug) action_table, action_check, action_default, action_pointer, goto_table, goto_check, goto_default, goto_pointer, nt_base, reduce_table, token_table, shift_n, @@ -186,15 +176,13 @@ module Racc i = nil nerr = 0 - catch(:racc_end_parse) { until i = action_pointer[@racc_state[-1]] while act = _racc_evalact(action_default[@racc_state[-1]], arg) + ; end end - recv.__send__(mid) do |tok, val| -# $stderr.puts "rd: tok=#{tok}, val=#{val}" unless tok @racc_t = 0 else @@ -204,67 +192,53 @@ module Racc @racc_read_next = false i += @racc_t - if i >= 0 and - act = action_table[i] and - action_check[i] == @racc_state[-1] - ; -# $stderr.puts "01: act=#{act}" - else + unless i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] act = action_default[@racc_state[-1]] -# $stderr.puts "02: act=#{act}" -# $stderr.puts "curstate=#{@racc_state[-1]}" end - while act = _racc_evalact(act, arg) + ; end while not (i = action_pointer[@racc_state[-1]]) or not @racc_read_next or @racc_t == 0 # $ - if i and i += @racc_t and - i >= 0 and - act = action_table[i] and - action_check[i] == @racc_state[-1] - ; -# $stderr.puts "03: act=#{act}" - else -# $stderr.puts "04: act=#{act}" + unless i and i += @racc_t and + i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] act = action_default[@racc_state[-1]] end - while act = _racc_evalact(act, arg) + ; end end end } end - ### ### common ### - def _racc_evalact( act, arg ) -# $stderr.puts "ea: act=#{act}" + def _racc_evalact(act, arg) action_table, action_check, action_default, action_pointer, goto_table, goto_check, goto_default, goto_pointer, nt_base, reduce_table, token_table, shift_n, reduce_n, use_result, * = arg -nerr = 0 # tmp + nerr = 0 # tmp if act > 0 and act < shift_n # # shift # - if @racc_error_status > 0 @racc_error_status -= 1 unless @racc_t == 1 # error token end - @racc_vstack.push @racc_val @racc_state.push act @racc_read_next = true - if @yydebug @racc_tstack.push @racc_t racc_shift @racc_t, @racc_tstack, @racc_vstack @@ -274,10 +248,9 @@ nerr = 0 # tmp # # reduce # - code = catch(:racc_jump) { - @racc_state.push _racc_do_reduce(arg, act) - false + @racc_state.push _racc_do_reduce(arg, act) + false } if code case code @@ -287,7 +260,7 @@ nerr = 0 # tmp when 2 # yyaccept return shift_n else - raise RuntimeError, '[Racc Bug] unknown jump code' + raise '[Racc Bug] unknown jump code' end end @@ -295,7 +268,6 @@ nerr = 0 # tmp # # accept # - racc_accept if @yydebug throw :racc_end_parse, @racc_vstack[0] @@ -303,7 +275,6 @@ nerr = 0 # tmp # # error # - case @racc_error_status when 0 unless arg[21] # user_yyerror @@ -318,7 +289,6 @@ nerr = 0 # tmp end @racc_user_yyerror = false @racc_error_status = 3 - while true if i = action_pointer[@racc_state[-1]] i += 1 # error token @@ -328,8 +298,7 @@ nerr = 0 # tmp break end end - - throw :racc_end_parse, nil if @racc_state.size < 2 + throw :racc_end_parse, nil if @racc_state.size <= 1 @racc_state.pop @racc_vstack.pop if @yydebug @@ -337,11 +306,10 @@ nerr = 0 # tmp racc_e_pop @racc_state, @racc_tstack, @racc_vstack end end - return act else - raise RuntimeError, "[Racc Bug] unknown action #{act.inspect}" + raise "[Racc Bug] unknown action #{act.inspect}" end racc_next_state(@racc_state[-1], @racc_state) if @yydebug @@ -349,7 +317,7 @@ nerr = 0 # tmp nil end - def _racc_do_reduce( arg, act ) + def _racc_do_reduce(arg, act) action_table, action_check, action_default, action_pointer, goto_table, goto_check, goto_default, goto_pointer, nt_base, reduce_table, token_table, shift_n, @@ -390,7 +358,7 @@ nerr = 0 # tmp goto_default[k1] end - def on_error( t, val, vstack ) + def on_error(t, val, vstack) raise ParseError, sprintf("\nparse error on value %s (%s)", val.inspect, token_to_str(t) || '?') end @@ -407,23 +375,24 @@ nerr = 0 # tmp @racc_error_status = 0 end - + # # for debugging output + # - def racc_read_token( t, tok, val ) + def racc_read_token(t, tok, val) @racc_debug_out.print 'read ' @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') ' @racc_debug_out.puts val.inspect @racc_debug_out.puts end - def racc_shift( tok, tstack, vstack ) + def racc_shift(tok, tstack, vstack) @racc_debug_out.puts "shift #{racc_token2str tok}" racc_print_stacks tstack, vstack @racc_debug_out.puts end - def racc_reduce( toks, sim, tstack, vstack ) + def racc_reduce(toks, sim, tstack, vstack) out = @racc_debug_out out.print 'reduce ' if toks.empty? @@ -442,20 +411,20 @@ nerr = 0 # tmp @racc_debug_out.puts end - def racc_e_pop( state, tstack, vstack ) + def racc_e_pop(state, tstack, vstack) @racc_debug_out.puts 'error recovering mode: pop token' racc_print_states state racc_print_stacks tstack, vstack @racc_debug_out.puts end - def racc_next_state( curstate, state ) + def racc_next_state(curstate, state) @racc_debug_out.puts "goto #{curstate}" racc_print_states state @racc_debug_out.puts end - def racc_print_stacks( t, v ) + def racc_print_stacks(t, v) out = @racc_debug_out out.print ' [' t.each_index do |i| @@ -464,57 +433,39 @@ nerr = 0 # tmp out.puts ' ]' end - def racc_print_states( s ) + def racc_print_states(s) out = @racc_debug_out out.print ' [' s.each {|st| out.print ' ', st } out.puts ' ]' end - def racc_token2str( tok ) + def racc_token2str(tok) self.class::Racc_token_to_s_table[tok] or - raise RuntimeError, "[Racc Bug] can't convert token #{tok} to string" + raise "[Racc Bug] can't convert token #{tok} to string" end - def token_to_str( t ) + def token_to_str(t) self.class::Racc_token_to_s_table[t] end end end -..end /home/aamine/lib/ruby/racc/parser.rb modeval..idb76f2e220d -end # end of racc/parser.rb +..end racc/parser.rb modeval..id8076474214 +end +###### racc/parser.rb end # # parser.rb # -#-- -# Copyright (c) 1998-2003 Minero Aoki +# Copyright (c) 1998-2007 Minero Aoki # -# 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: +# This program is free software. +# You can distribute/modify this program under the terms of +# the GNU Lesser General Public License version 2.1. # -# 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. -#++ require 'tmail/scanner' require 'tmail/utils' @@ -524,7 +475,7 @@ module TMail class Parser < Racc::Parser -module_eval <<'..end parser.y modeval..id43721faf1c', 'parser.y', 331 +module_eval <<'..end parser.y modeval..id7b0b3dccb7', 'parser.y', 340 include TextUtils @@ -567,9 +518,9 @@ module_eval <<'..end parser.y modeval..id43721faf1c', 'parser.y', 331 raise SyntaxError, "parse error on token #{racc_token2str t}" end -..end parser.y modeval..id43721faf1c +..end parser.y modeval..id7b0b3dccb7 -##### racc 1.4.3 generates ### +##### racc 1.4.5 generates ### racc_reduce_table = [ 0, 0, :racc_error, @@ -669,10 +620,9 @@ racc_reduce_table = [ 3, 43, :_reduce_94, 0, 80, :_reduce_95, 5, 80, :_reduce_96, - 1, 82, :_reduce_none, - 1, 82, :_reduce_none, - 1, 44, :_reduce_99, - 3, 45, :_reduce_100, + 5, 80, :_reduce_97, + 1, 44, :_reduce_98, + 3, 45, :_reduce_99, 0, 81, :_reduce_none, 1, 81, :_reduce_none, 1, 78, :_reduce_none, @@ -683,15 +633,15 @@ racc_reduce_table = [ 1, 78, :_reduce_none, 1, 78, :_reduce_none ] -racc_reduce_n = 110 +racc_reduce_n = 109 -racc_shift_n = 168 +racc_shift_n = 167 racc_action_table = [ - -70, -69, 23, 25, 146, 147, 29, 31, 105, 106, + -70, -69, 23, 25, 145, 146, 29, 31, 105, 106, 16, 17, 20, 22, 136, 27, -70, -69, 32, 101, - -70, -69, 154, 100, 113, 115, -70, -69, -70, 109, - 75, 23, 25, 101, 155, 29, 31, 142, 143, 16, + -70, -69, 153, 100, 113, 115, -70, -69, -70, 109, + 75, 23, 25, 101, 154, 29, 31, 142, 143, 16, 17, 20, 22, 107, 27, 23, 25, 32, 98, 29, 31, 96, 94, 16, 17, 20, 22, 78, 27, 23, 25, 32, 112, 29, 31, 74, 91, 16, 17, 20, @@ -703,11 +653,11 @@ racc_action_table = [ 78, 29, 31, 133, 78, 16, 17, 20, 22, 77, 23, 25, 75, 32, 29, 31, 65, 62, 16, 17, 20, 22, 139, 23, 25, 101, 32, 29, 31, 60, - 100, 16, 17, 20, 22, 44, 27, 101, 148, 32, - 23, 25, 120, 149, 29, 31, 152, 153, 16, 17, - 20, 22, 42, 27, 157, 159, 32, 23, 25, 120, - 40, 29, 31, 15, 164, 16, 17, 20, 22, 40, - 27, 23, 25, 32, 68, 29, 31, 166, 167, 16, + 100, 16, 17, 20, 22, 44, 27, 101, 147, 32, + 23, 25, 120, 148, 29, 31, 151, 152, 16, 17, + 20, 22, 42, 27, 156, 158, 32, 23, 25, 120, + 40, 29, 31, 15, 163, 16, 17, 20, 22, 40, + 27, 23, 25, 32, 68, 29, 31, 165, 166, 16, 17, 20, 22, nil, 27, 23, 25, 32, nil, 29, 31, 74, nil, 16, 17, 20, 22, nil, 23, 25, nil, 32, 29, 31, nil, nil, 16, 17, 20, 22, @@ -735,9 +685,9 @@ racc_action_check = [ 68, 68, 68, 68, 126, 68, 75, 28, 68, 67, 75, 28, 143, 66, 86, 86, 75, 28, 75, 75, 28, 3, 3, 86, 143, 3, 3, 134, 134, 3, - 3, 3, 3, 73, 3, 152, 152, 3, 62, 152, - 152, 60, 56, 152, 152, 152, 152, 51, 152, 52, - 52, 152, 80, 52, 52, 52, 50, 52, 52, 52, + 3, 3, 3, 73, 3, 151, 151, 3, 62, 151, + 151, 60, 56, 151, 151, 151, 151, 51, 151, 52, + 52, 151, 80, 52, 52, 52, 50, 52, 52, 52, 52, 45, 89, 52, 42, 52, 71, 71, 41, 96, 71, 71, 97, 98, 71, 71, 71, 71, 100, 7, 7, 101, 71, 7, 7, 102, 104, 7, 7, 7, @@ -748,13 +698,13 @@ racc_action_check = [ 10, 10, 130, 2, 2, 131, 10, 2, 2, 11, 135, 2, 2, 2, 2, 6, 2, 138, 139, 2, 90, 90, 90, 140, 90, 90, 141, 142, 90, 90, - 90, 90, 5, 90, 148, 151, 90, 127, 127, 127, - 4, 127, 127, 1, 157, 127, 127, 127, 127, 159, - 127, 26, 26, 127, 26, 26, 26, 163, 164, 26, + 90, 90, 5, 90, 147, 150, 90, 127, 127, 127, + 4, 127, 127, 1, 156, 127, 127, 127, 127, 158, + 127, 26, 26, 127, 26, 26, 26, 162, 163, 26, 26, 26, 26, nil, 26, 27, 27, 26, nil, 27, - 27, 27, nil, 27, 27, 27, 27, nil, 155, 155, - nil, 27, 155, 155, nil, nil, 155, 155, 155, 155, - nil, 122, 122, nil, 155, 122, 122, nil, nil, 122, + 27, 27, nil, 27, 27, 27, 27, nil, 154, 154, + nil, 27, 154, 154, nil, nil, 154, 154, 154, 154, + nil, 122, 122, nil, 154, 122, 122, nil, nil, 122, 122, 122, 122, nil, 76, 76, nil, 122, 76, 76, nil, nil, 76, 76, 76, 76, nil, 38, 38, nil, 76, 38, 38, nil, nil, 38, 38, 38, 38, nil, @@ -788,78 +738,78 @@ racc_action_pointer = [ nil, 80, 96, 344, 296, nil, nil, 108, nil, nil, nil, 98, 217, nil, nil, nil, -19, 163, nil, 380, 128, 116, nil, nil, 14, 124, -26, nil, 128, 141, - 148, 141, 152, 7, nil, nil, nil, nil, 160, nil, - nil, 149, 31, nil, nil, 204, nil, 167, nil, 174, - nil, nil, nil, 169, 184, nil, nil, nil ] + 148, 141, 152, 7, nil, nil, nil, 160, nil, nil, + 149, 31, nil, nil, 204, nil, 167, nil, 174, nil, + nil, nil, 169, 184, nil, nil, nil ] racc_action_default = [ - -110, -110, -110, -110, -14, -110, -20, -110, -110, -110, - -110, -110, -110, -110, -10, -95, -106, -107, -77, -44, - -108, -11, -109, -79, -43, -103, -110, -110, -60, -104, - -55, -105, -78, -68, -54, -71, -45, -12, -110, -1, - -110, -110, -110, -2, -110, -22, -51, -48, -50, -3, - -40, -41, -110, -46, -4, -86, -5, -88, -6, -90, - -110, -7, -95, -8, -9, -99, -101, -61, -59, -56, - -69, -110, -110, -110, -110, -75, -110, -110, -57, -15, - -110, 168, -73, -80, -82, -21, -24, -81, -110, -27, - -110, -83, -47, -89, -110, -91, -110, -101, -110, -100, - -102, -75, -58, -52, -110, -110, -64, -63, -65, -76, - -72, -67, -110, -110, -110, -26, -23, -110, -29, -49, - -84, -42, -87, -92, -94, -95, -110, -110, -62, -110, - -110, -25, -74, -28, -31, -101, -110, -53, -66, -110, - -110, -34, -110, -110, -93, -96, -98, -97, -110, -18, - -13, -38, -110, -30, -33, -110, -32, -16, -19, -14, - -35, -36, -37, -110, -110, -39, -85, -17 ] + -109, -109, -109, -109, -14, -109, -20, -109, -109, -109, + -109, -109, -109, -109, -10, -95, -105, -106, -77, -44, + -107, -11, -108, -79, -43, -102, -109, -109, -60, -103, + -55, -104, -78, -68, -54, -71, -45, -12, -109, -1, + -109, -109, -109, -2, -109, -22, -51, -48, -50, -3, + -40, -41, -109, -46, -4, -86, -5, -88, -6, -90, + -109, -7, -95, -8, -9, -98, -100, -61, -59, -56, + -69, -109, -109, -109, -109, -75, -109, -109, -57, -15, + -109, 167, -73, -80, -82, -21, -24, -81, -109, -27, + -109, -83, -47, -89, -109, -91, -109, -100, -109, -99, + -101, -75, -58, -52, -109, -109, -64, -63, -65, -76, + -72, -67, -109, -109, -109, -26, -23, -109, -29, -49, + -84, -42, -87, -92, -94, -95, -109, -109, -62, -109, + -109, -25, -74, -28, -31, -100, -109, -53, -66, -109, + -109, -34, -109, -109, -93, -96, -97, -109, -18, -13, + -38, -109, -30, -33, -109, -32, -16, -19, -14, -35, + -36, -37, -109, -109, -39, -85, -17 ] racc_goto_table = [ - 39, 67, 70, 73, 24, 37, 69, 66, 36, 38, - 57, 59, 55, 67, 108, 83, 90, 111, 69, 99, - 85, 49, 53, 76, 158, 134, 141, 70, 73, 151, - 118, 89, 45, 156, 160, 150, 140, 21, 14, 19, - 119, 102, 64, 63, 61, 83, 70, 104, 83, 58, - 124, 132, 56, 131, 97, 54, 93, 43, 5, 83, - 95, 145, 76, nil, 116, 76, nil, nil, 127, 138, - 103, nil, nil, nil, 38, nil, nil, 110, nil, nil, - nil, nil, nil, nil, 83, 83, nil, nil, 144, nil, - nil, nil, nil, nil, nil, 57, 121, 122, nil, nil, - 83, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, 135, nil, nil, - nil, nil, nil, 93, nil, nil, nil, 70, 162, 137, - 70, 163, 161, 38, nil, nil, nil, nil, nil, nil, + 39, 67, 70, 73, 38, 66, 69, 24, 37, 57, + 59, 36, 55, 67, 99, 90, 85, 157, 69, 108, + 83, 134, 111, 76, 49, 53, 141, 70, 73, 150, + 118, 89, 45, 155, 159, 149, 140, 21, 14, 19, + 119, 102, 64, 63, 61, 124, 70, 104, 58, 132, + 83, 56, 97, 83, 54, 93, 43, 5, 131, 95, + 116, nil, 76, nil, 83, 76, nil, 127, nil, 38, + nil, nil, nil, 103, 138, nil, 110, nil, nil, nil, + nil, nil, nil, 144, nil, nil, nil, nil, nil, 83, + 83, nil, nil, nil, 57, nil, nil, 122, nil, 121, + nil, nil, nil, nil, nil, 83, nil, nil, nil, nil, + nil, nil, nil, nil, nil, 135, nil, nil, nil, nil, + nil, nil, 93, nil, nil, nil, 70, 161, 38, 70, + 162, 160, 137, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, 165 ] + nil, nil, nil, nil, 164 ] racc_goto_check = [ - 2, 37, 37, 29, 13, 13, 28, 46, 31, 36, - 41, 41, 45, 37, 25, 44, 32, 25, 28, 47, - 24, 4, 4, 42, 23, 20, 21, 37, 29, 22, + 2, 37, 37, 29, 36, 46, 28, 13, 13, 41, + 41, 31, 45, 37, 47, 32, 24, 23, 28, 25, + 44, 20, 25, 42, 4, 4, 21, 37, 29, 22, 19, 18, 17, 26, 27, 16, 15, 12, 11, 33, - 34, 35, 10, 9, 8, 44, 37, 29, 44, 7, - 47, 43, 6, 25, 46, 5, 41, 3, 1, 44, - 41, 48, 42, nil, 24, 42, nil, nil, 32, 25, - 13, nil, nil, nil, 36, nil, nil, 41, nil, nil, - nil, nil, nil, nil, 44, 44, nil, nil, 47, nil, - nil, nil, nil, nil, nil, 41, 31, 45, nil, nil, - 44, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, 46, nil, nil, - nil, nil, nil, 41, nil, nil, nil, 37, 29, 13, - 37, 29, 28, 36, nil, nil, nil, nil, nil, nil, + 34, 35, 10, 9, 8, 47, 37, 29, 7, 43, + 44, 6, 46, 44, 5, 41, 3, 1, 25, 41, + 24, nil, 42, nil, 44, 42, nil, 32, nil, 36, + nil, nil, nil, 13, 25, nil, 41, nil, nil, nil, + nil, nil, nil, 47, nil, nil, nil, nil, nil, 44, + 44, nil, nil, nil, 41, nil, nil, 45, nil, 31, + nil, nil, nil, nil, nil, 44, nil, nil, nil, nil, + nil, nil, nil, nil, nil, 46, nil, nil, nil, nil, + nil, nil, 41, nil, nil, nil, 37, 29, 36, 37, + 29, 28, 13, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, 2 ] + nil, nil, nil, nil, 2 ] racc_goto_pointer = [ - nil, 58, -4, 51, 14, 47, 43, 39, 33, 31, - 29, 37, 35, 2, nil, -94, -105, 26, -14, -59, - -93, -108, -112, -127, -24, -60, -110, -118, -20, -24, - nil, 6, -34, 37, -50, -27, 6, -25, nil, nil, - nil, 1, -5, -63, -29, 3, -8, -47, -75 ] + nil, 57, -4, 50, 17, 46, 42, 38, 33, 31, + 29, 37, 35, 5, nil, -94, -105, 26, -14, -59, + -97, -108, -112, -133, -28, -55, -110, -117, -20, -24, + nil, 9, -35, 37, -50, -27, 1, -25, nil, nil, + nil, 0, -5, -65, -24, 3, -10, -52 ] racc_goto_default = [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 48, 41, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 86, nil, nil, 30, 34, 50, 51, nil, 46, 47, nil, 26, 28, 71, 72, - 33, 35, 114, 82, 18, nil, nil, nil, nil ] + 33, 35, 114, 82, 18, nil, nil, nil ] racc_token_table = { false => 0, @@ -999,8 +949,7 @@ Racc_token_to_s_table = [ 'atom', 'phrase', 'params', -'opt_semicolon', -'value'] +'opt_semicolon'] Racc_debug_parser = false @@ -1080,7 +1029,7 @@ module_eval <<'.,.,', 'parser.y', 27 end .,., -module_eval <<'.,.,', 'parser.y', 33 +module_eval <<'.,.,', 'parser.y', 36 def _reduce_13( val, _values) t = Time.gm(val[3].to_i, val[2], val[1].to_i, 0, 0, 0) (t + val[4] - val[5]).localtime @@ -1091,14 +1040,14 @@ module_eval <<'.,.,', 'parser.y', 33 # reduce 15 omitted -module_eval <<'.,.,', 'parser.y', 42 +module_eval <<'.,.,', 'parser.y', 45 def _reduce_16( val, _values) (val[0].to_i * 60 * 60) + (val[2].to_i * 60) end .,., -module_eval <<'.,.,', 'parser.y', 47 +module_eval <<'.,.,', 'parser.y', 51 def _reduce_17( val, _values) (val[0].to_i * 60 * 60) + (val[2].to_i * 60) + @@ -1106,13 +1055,13 @@ module_eval <<'.,.,', 'parser.y', 47 end .,., -module_eval <<'.,.,', 'parser.y', 54 +module_eval <<'.,.,', 'parser.y', 56 def _reduce_18( val, _values) timezone_string_to_unixtime(val[0]) end .,., -module_eval <<'.,.,', 'parser.y', 59 +module_eval <<'.,.,', 'parser.y', 61 def _reduce_19( val, _values) val end @@ -1120,7 +1069,7 @@ module_eval <<'.,.,', 'parser.y', 59 # reduce 20 omitted -module_eval <<'.,.,', 'parser.y', 65 +module_eval <<'.,.,', 'parser.y', 67 def _reduce_21( val, _values) val[1] end @@ -1128,25 +1077,25 @@ module_eval <<'.,.,', 'parser.y', 65 # reduce 22 omitted -module_eval <<'.,.,', 'parser.y', 71 +module_eval <<'.,.,', 'parser.y', 73 def _reduce_23( val, _values) val[1] end .,., -module_eval <<'.,.,', 'parser.y', 77 +module_eval <<'.,.,', 'parser.y', 79 def _reduce_24( val, _values) join_domain(val[0]) end .,., -module_eval <<'.,.,', 'parser.y', 81 +module_eval <<'.,.,', 'parser.y', 83 def _reduce_25( val, _values) join_domain(val[2]) end .,., -module_eval <<'.,.,', 'parser.y', 85 +module_eval <<'.,.,', 'parser.y', 87 def _reduce_26( val, _values) join_domain(val[0]) end @@ -1154,19 +1103,19 @@ module_eval <<'.,.,', 'parser.y', 85 # reduce 27 omitted -module_eval <<'.,.,', 'parser.y', 91 +module_eval <<'.,.,', 'parser.y', 93 def _reduce_28( val, _values) val[1] end .,., -module_eval <<'.,.,', 'parser.y', 96 +module_eval <<'.,.,', 'parser.y', 98 def _reduce_29( val, _values) [] end .,., -module_eval <<'.,.,', 'parser.y', 100 +module_eval <<'.,.,', 'parser.y', 103 def _reduce_30( val, _values) val[0].push val[2] val[0] @@ -1175,13 +1124,13 @@ module_eval <<'.,.,', 'parser.y', 100 # reduce 31 omitted -module_eval <<'.,.,', 'parser.y', 107 +module_eval <<'.,.,', 'parser.y', 109 def _reduce_32( val, _values) val[1] end .,., -module_eval <<'.,.,', 'parser.y', 111 +module_eval <<'.,.,', 'parser.y', 113 def _reduce_33( val, _values) val[1] end @@ -1189,19 +1138,19 @@ module_eval <<'.,.,', 'parser.y', 111 # reduce 34 omitted -module_eval <<'.,.,', 'parser.y', 117 +module_eval <<'.,.,', 'parser.y', 119 def _reduce_35( val, _values) val[1] end .,., -module_eval <<'.,.,', 'parser.y', 123 +module_eval <<'.,.,', 'parser.y', 125 def _reduce_36( val, _values) val[0].spec end .,., -module_eval <<'.,.,', 'parser.y', 127 +module_eval <<'.,.,', 'parser.y', 129 def _reduce_37( val, _values) val[0].spec end @@ -1209,7 +1158,7 @@ module_eval <<'.,.,', 'parser.y', 127 # reduce 38 omitted -module_eval <<'.,.,', 'parser.y', 134 +module_eval <<'.,.,', 'parser.y', 136 def _reduce_39( val, _values) val[1] end @@ -1235,15 +1184,16 @@ module_eval <<'.,.,', 'parser.y', 146 end .,., -module_eval <<'.,.,', 'parser.y', 148 +module_eval <<'.,.,', 'parser.y', 152 def _reduce_48( val, _values) - val + val end .,., -module_eval <<'.,.,', 'parser.y', 149 +module_eval <<'.,.,', 'parser.y', 157 def _reduce_49( val, _values) - val[0].push val[2]; val[0] + val[0].push val[2] + val[0] end .,., @@ -1251,13 +1201,13 @@ module_eval <<'.,.,', 'parser.y', 149 # reduce 51 omitted -module_eval <<'.,.,', 'parser.y', 156 +module_eval <<'.,.,', 'parser.y', 165 def _reduce_52( val, _values) val end .,., -module_eval <<'.,.,', 'parser.y', 160 +module_eval <<'.,.,', 'parser.y', 170 def _reduce_53( val, _values) val[0].push val[2] val[0] @@ -1268,7 +1218,7 @@ module_eval <<'.,.,', 'parser.y', 160 # reduce 55 omitted -module_eval <<'.,.,', 'parser.y', 168 +module_eval <<'.,.,', 'parser.y', 178 def _reduce_56( val, _values) val[1].phrase = Decoder.decode(val[0]) val[1] @@ -1277,38 +1227,38 @@ module_eval <<'.,.,', 'parser.y', 168 # reduce 57 omitted -module_eval <<'.,.,', 'parser.y', 176 +module_eval <<'.,.,', 'parser.y', 185 def _reduce_58( val, _values) AddressGroup.new(val[0], val[2]) end .,., -module_eval <<'.,.,', 'parser.y', 178 +module_eval <<'.,.,', 'parser.y', 185 def _reduce_59( val, _values) AddressGroup.new(val[0], []) end .,., -module_eval <<'.,.,', 'parser.y', 181 +module_eval <<'.,.,', 'parser.y', 188 def _reduce_60( val, _values) val[0].join('.') end .,., -module_eval <<'.,.,', 'parser.y', 182 +module_eval <<'.,.,', 'parser.y', 189 def _reduce_61( val, _values) val[0] << ' ' << val[1].join('.') end .,., -module_eval <<'.,.,', 'parser.y', 186 +module_eval <<'.,.,', 'parser.y', 196 def _reduce_62( val, _values) val[2].routes.replace val[1] val[2] end .,., -module_eval <<'.,.,', 'parser.y', 191 +module_eval <<'.,.,', 'parser.y', 200 def _reduce_63( val, _values) val[1] end @@ -1316,25 +1266,25 @@ module_eval <<'.,.,', 'parser.y', 191 # reduce 64 omitted -module_eval <<'.,.,', 'parser.y', 196 +module_eval <<'.,.,', 'parser.y', 203 def _reduce_65( val, _values) [ val[1].join('.') ] end .,., -module_eval <<'.,.,', 'parser.y', 197 +module_eval <<'.,.,', 'parser.y', 204 def _reduce_66( val, _values) val[0].push val[3].join('.'); val[0] end .,., -module_eval <<'.,.,', 'parser.y', 199 +module_eval <<'.,.,', 'parser.y', 206 def _reduce_67( val, _values) Address.new( val[0], val[2] ) end .,., -module_eval <<'.,.,', 'parser.y', 200 +module_eval <<'.,.,', 'parser.y', 207 def _reduce_68( val, _values) Address.new( val[0], nil ) end @@ -1342,19 +1292,19 @@ module_eval <<'.,.,', 'parser.y', 200 # reduce 69 omitted -module_eval <<'.,.,', 'parser.y', 203 +module_eval <<'.,.,', 'parser.y', 210 def _reduce_70( val, _values) val[0].push ''; val[0] end .,., -module_eval <<'.,.,', 'parser.y', 206 +module_eval <<'.,.,', 'parser.y', 213 def _reduce_71( val, _values) val end .,., -module_eval <<'.,.,', 'parser.y', 209 +module_eval <<'.,.,', 'parser.y', 222 def _reduce_72( val, _values) val[1].times do val[0].push '' @@ -1364,13 +1314,13 @@ module_eval <<'.,.,', 'parser.y', 209 end .,., -module_eval <<'.,.,', 'parser.y', 217 +module_eval <<'.,.,', 'parser.y', 224 def _reduce_73( val, _values) val end .,., -module_eval <<'.,.,', 'parser.y', 220 +module_eval <<'.,.,', 'parser.y', 233 def _reduce_74( val, _values) val[1].times do val[0].push '' @@ -1380,13 +1330,13 @@ module_eval <<'.,.,', 'parser.y', 220 end .,., -module_eval <<'.,.,', 'parser.y', 227 +module_eval <<'.,.,', 'parser.y', 234 def _reduce_75( val, _values) 0 end .,., -module_eval <<'.,.,', 'parser.y', 228 +module_eval <<'.,.,', 'parser.y', 235 def _reduce_76( val, _values) 1 end @@ -1408,20 +1358,20 @@ module_eval <<'.,.,', 'parser.y', 228 # reduce 84 omitted -module_eval <<'.,.,', 'parser.y', 243 +module_eval <<'.,.,', 'parser.y', 253 def _reduce_85( val, _values) val[1] = val[1].spec val.join('') end .,., -module_eval <<'.,.,', 'parser.y', 247 +module_eval <<'.,.,', 'parser.y', 254 def _reduce_86( val, _values) val end .,., -module_eval <<'.,.,', 'parser.y', 248 +module_eval <<'.,.,', 'parser.y', 255 def _reduce_87( val, _values) val[0].push val[2]; val[0] end @@ -1429,72 +1379,77 @@ module_eval <<'.,.,', 'parser.y', 248 # reduce 88 omitted -module_eval <<'.,.,', 'parser.y', 251 +module_eval <<'.,.,', 'parser.y', 258 def _reduce_89( val, _values) val[0] << ' ' << val[1] end .,., -module_eval <<'.,.,', 'parser.y', 255 +module_eval <<'.,.,', 'parser.y', 265 def _reduce_90( val, _values) val.push nil val end .,., -module_eval <<'.,.,', 'parser.y', 260 +module_eval <<'.,.,', 'parser.y', 269 def _reduce_91( val, _values) val end .,., -module_eval <<'.,.,', 'parser.y', 265 +module_eval <<'.,.,', 'parser.y', 274 def _reduce_92( val, _values) [ val[0].to_i, val[2].to_i ] end .,., -module_eval <<'.,.,', 'parser.y', 270 +module_eval <<'.,.,', 'parser.y', 279 def _reduce_93( val, _values) [ val[0].downcase, val[2].downcase, decode_params(val[3]) ] end .,., -module_eval <<'.,.,', 'parser.y', 274 +module_eval <<'.,.,', 'parser.y', 283 def _reduce_94( val, _values) [ val[0].downcase, nil, decode_params(val[1]) ] end .,., -module_eval <<'.,.,', 'parser.y', 279 +module_eval <<'.,.,', 'parser.y', 288 def _reduce_95( val, _values) {} end .,., -module_eval <<'.,.,', 'parser.y', 283 +module_eval <<'.,.,', 'parser.y', 293 def _reduce_96( val, _values) + val[0][ val[2].downcase ] = ('"' + val[4].to_s + '"') + val[0] + end +.,., + +module_eval <<'.,.,', 'parser.y', 298 + def _reduce_97( val, _values) val[0][ val[2].downcase ] = val[4] val[0] end .,., - # reduce 97 omitted - - # reduce 98 omitted - -module_eval <<'.,.,', 'parser.y', 292 - def _reduce_99( val, _values) +module_eval <<'.,.,', 'parser.y', 303 + def _reduce_98( val, _values) val[0].downcase end .,., -module_eval <<'.,.,', 'parser.y', 297 - def _reduce_100( val, _values) +module_eval <<'.,.,', 'parser.y', 308 + def _reduce_99( val, _values) [ val[0].downcase, decode_params(val[1]) ] end .,., + # reduce 100 omitted + # reduce 101 omitted # reduce 102 omitted @@ -1511,8 +1466,6 @@ module_eval <<'.,.,', 'parser.y', 297 # reduce 108 omitted - # reduce 109 omitted - def _reduce_none( val, _values) val[0] end diff --git a/actionmailer/lib/action_mailer/vendor/tmail/parser.y b/actionmailer/lib/action_mailer/vendor/tmail/parser.y new file mode 100644 index 0000000000..77a1457794 --- /dev/null +++ b/actionmailer/lib/action_mailer/vendor/tmail/parser.y @@ -0,0 +1,381 @@ +# +# parser.y +# +# Copyright (c) 1998-2007 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the terms of +# the GNU Lesser General Public License version 2.1. +# + +class TMail::Parser + + options no_result_var + +rule + + content : DATETIME datetime { val[1] } + | RECEIVED received { val[1] } + | MADDRESS addrs_TOP { val[1] } + | RETPATH retpath { val[1] } + | KEYWORDS keys { val[1] } + | ENCRYPTED enc { val[1] } + | MIMEVERSION version { val[1] } + | CTYPE ctype { val[1] } + | CENCODING cencode { val[1] } + | CDISPOSITION cdisp { val[1] } + | ADDRESS addr_TOP { val[1] } + | MAILBOX mbox { val[1] } + + datetime : day DIGIT ATOM DIGIT hour zone + # 0 1 2 3 4 5 + # date month year + { + t = Time.gm(val[3].to_i, val[2], val[1].to_i, 0, 0, 0) + (t + val[4] - val[5]).localtime + } + + day : /* none */ + | ATOM ',' + + hour : DIGIT ':' DIGIT + { + (val[0].to_i * 60 * 60) + + (val[2].to_i * 60) + } + | DIGIT ':' DIGIT ':' DIGIT + { + (val[0].to_i * 60 * 60) + + (val[2].to_i * 60) + + (val[4].to_i) + } + + zone : ATOM + { + timezone_string_to_unixtime(val[0]) + } + + received : from by via with id for received_datetime + { + val + } + + from : /* none */ + | FROM received_domain + { + val[1] + } + + by : /* none */ + | BY received_domain + { + val[1] + } + + received_domain + : domain + { + join_domain(val[0]) + } + | domain '@' domain + { + join_domain(val[2]) + } + | domain DOMLIT + { + join_domain(val[0]) + } + + via : /* none */ + | VIA ATOM + { + val[1] + } + + with : /* none */ + { + [] + } + | with WITH ATOM + { + val[0].push val[2] + val[0] + } + + id : /* none */ + | ID msgid + { + val[1] + } + | ID ATOM + { + val[1] + } + + for : /* none */ + | FOR received_addrspec + { + val[1] + } + + received_addrspec + : routeaddr + { + val[0].spec + } + | spec + { + val[0].spec + } + + received_datetime + : /* none */ + | ';' datetime + { + val[1] + } + + addrs_TOP : addrs + | group_bare + | addrs commas group_bare + + addr_TOP : mbox + | group + | group_bare + + retpath : addrs_TOP + | '<' '>' { [ Address.new(nil, nil) ] } + + addrs : addr + { + val + } + | addrs commas addr + { + val[0].push val[2] + val[0] + } + + addr : mbox + | group + + mboxes : mbox + { + val + } + | mboxes commas mbox + { + val[0].push val[2] + val[0] + } + + mbox : spec + | routeaddr + | addr_phrase routeaddr + { + val[1].phrase = Decoder.decode(val[0]) + val[1] + } + + group : group_bare ';' + + group_bare: addr_phrase ':' mboxes + { + AddressGroup.new(val[0], val[2]) + } + | addr_phrase ':' { AddressGroup.new(val[0], []) } + + addr_phrase + : local_head { val[0].join('.') } + | addr_phrase local_head { val[0] << ' ' << val[1].join('.') } + + routeaddr : '<' routes spec '>' + { + val[2].routes.replace val[1] + val[2] + } + | '<' spec '>' + { + val[1] + } + + routes : at_domains ':' + + at_domains: '@' domain { [ val[1].join('.') ] } + | at_domains ',' '@' domain { val[0].push val[3].join('.'); val[0] } + + spec : local '@' domain { Address.new( val[0], val[2] ) } + | local { Address.new( val[0], nil ) } + + local: local_head + | local_head '.' { val[0].push ''; val[0] } + + local_head: word + { val } + | local_head dots word + { + val[1].times do + val[0].push '' + end + val[0].push val[2] + val[0] + } + + domain : domword + { val } + | domain dots domword + { + val[1].times do + val[0].push '' + end + val[0].push val[2] + val[0] + } + + dots : '.' { 0 } + | '.' '.' { 1 } + + word : atom + | QUOTED + | DIGIT + + domword : atom + | DOMLIT + | DIGIT + + commas : ',' + | commas ',' + + msgid : '<' spec '>' + { + val[1] = val[1].spec + val.join('') + } + + keys : phrase { val } + | keys ',' phrase { val[0].push val[2]; val[0] } + + phrase : word + | phrase word { val[0] << ' ' << val[1] } + + enc : word + { + val.push nil + val + } + | word word + { + val + } + + version : DIGIT '.' DIGIT + { + [ val[0].to_i, val[2].to_i ] + } + + ctype : TOKEN '/' TOKEN params opt_semicolon + { + [ val[0].downcase, val[2].downcase, decode_params(val[3]) ] + } + | TOKEN params opt_semicolon + { + [ val[0].downcase, nil, decode_params(val[1]) ] + } + + params : /* none */ + { + {} + } + | params ';' TOKEN '=' QUOTED + { + val[0][ val[2].downcase ] = ('"' + val[4].to_s + '"') + val[0] + } + | params ';' TOKEN '=' TOKEN + { + val[0][ val[2].downcase ] = val[4] + val[0] + } + + cencode : TOKEN + { + val[0].downcase + } + + cdisp : TOKEN params opt_semicolon + { + [ val[0].downcase, decode_params(val[1]) ] + } + + opt_semicolon + : + | ';' + + atom : ATOM + | FROM + | BY + | VIA + | WITH + | ID + | FOR + +end + + +---- header +# +# parser.rb +# +# Copyright (c) 1998-2007 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the terms of +# the GNU Lesser General Public License version 2.1. +# + +require 'tmail/scanner' +require 'tmail/utils' + +---- inner + + include TextUtils + + def self.parse( ident, str, cmt = nil ) + new.parse(ident, str, cmt) + end + + MAILP_DEBUG = false + + def initialize + self.debug = MAILP_DEBUG + end + + def debug=( flag ) + @yydebug = flag && Racc_debug_parser + @scanner_debug = flag + end + + def debug + @yydebug + end + + def parse( ident, str, comments = nil ) + @scanner = Scanner.new(str, ident, comments) + @scanner.debug = @scanner_debug + @first = [ident, ident] + result = yyparse(self, :parse_in) + comments.map! {|c| to_kcode(c) } if comments + result + end + + private + + def parse_in( &block ) + yield @first + @scanner.scan(&block) + end + + def on_error( t, val, vstack ) + raise SyntaxError, "parse error on token #{racc_token2str t}" + end + diff --git a/actionmailer/lib/action_mailer/vendor/tmail/port.rb b/actionmailer/lib/action_mailer/vendor/tmail/port.rb index f973c05b3e..445f0e632b 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/port.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/port.rb @@ -1,6 +1,8 @@ -# -# port.rb -# +=begin rdoc + += Port class + +=end #-- # Copyright (c) 1998-2003 Minero Aoki # diff --git a/actionmailer/lib/action_mailer/vendor/tmail/quoting.rb b/actionmailer/lib/action_mailer/vendor/tmail/quoting.rb index f27234fcfe..0b2d11c3f0 100644 --- a/actionmailer/lib/action_mailer/vendor/tmail/quoting.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/quoting.rb @@ -1,3 +1,8 @@ +=begin rdoc + += Quoting methods + +=end module TMail class Mail def subject(to_charset = 'utf-8') diff --git a/actionmailer/lib/action_mailer/vendor/tmail/scanner.rb b/actionmailer/lib/action_mailer/vendor/tmail/scanner.rb index 839dd79303..9216b430fa 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/scanner.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/scanner.rb @@ -1,6 +1,8 @@ -# -# scanner.rb -# +=begin rdoc + += Scanner for TMail + +=end #-- # Copyright (c) 1998-2003 Minero Aoki # diff --git a/actionmailer/lib/action_mailer/vendor/tmail/stringio.rb b/actionmailer/lib/action_mailer/vendor/tmail/stringio.rb index 532be3db8c..3817850f63 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/stringio.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/stringio.rb @@ -1,6 +1,8 @@ -# -# stringio.rb -# +=begin rdoc + += String handling class + +=end #-- # Copyright (c) 1998-2003 Minero Aoki # @@ -218,7 +220,7 @@ class StringOutput#:nodoc: alias pos size def inspect - "#<#{self.class}:#{@dest ? 'open' : 'closed'},#{id}>" + "#<#{self.class}:#{@dest ? 'open' : 'closed'},#{object_id}>" end def print( *args ) diff --git a/actionmailer/lib/action_mailer/vendor/tmail/utils.rb b/actionmailer/lib/action_mailer/vendor/tmail/utils.rb index 852acd7576..016330ffd5 100755 --- a/actionmailer/lib/action_mailer/vendor/tmail/utils.rb +++ b/actionmailer/lib/action_mailer/vendor/tmail/utils.rb @@ -1,6 +1,8 @@ -# -# utils.rb -# +=begin rdoc + += General Purpose TMail Utilities + +=end #-- # Copyright (c) 1998-2003 Minero Aoki # @@ -52,9 +54,9 @@ module TMail @uniq = 0 - module TextUtils - + # Defines characters per RFC that are OK for TOKENs, ATOMs, PHRASEs and CONTROL characters. + aspecial = '()<>[]:;.\\,"' tspecial = '()<>[];:\\,"/?=' lwsp = " \t\r\n" @@ -66,31 +68,50 @@ module TMail CONTROL_CHAR = /[#{control}]/n def atom_safe?( str ) + # Returns true if the string supplied is free from characters not allowed as an ATOM not ATOM_UNSAFE === str end def quote_atom( str ) + # If the string supplied has ATOM unsafe characters in it, will return the string quoted + # in double quotes, otherwise returns the string unmodified (ATOM_UNSAFE === str) ? dquote(str) : str end def quote_phrase( str ) + # If the string supplied has PHRASE unsafe characters in it, will return the string quoted + # in double quotes, otherwise returns the string unmodified (PHRASE_UNSAFE === str) ? dquote(str) : str end def token_safe?( str ) + # Returns true if the string supplied is free from characters not allowed as a TOKEN not TOKEN_UNSAFE === str end def quote_token( str ) + # If the string supplied has TOKEN unsafe characters in it, will return the string quoted + # in double quotes, otherwise returns the string unmodified (TOKEN_UNSAFE === str) ? dquote(str) : str end def dquote( str ) - '"' + str.gsub(/["\\]/n) {|s| '\\' + s } + '"' + # Wraps supplied string in double quotes unless it is already wrapped + # Returns double quoted string + unless str =~ /^".*?"$/ + '"' + str.gsub(/["\\]/n) {|s| '\\' + s } + '"' + else + str + end end private :dquote - + def unquote( str ) + # Unwraps supplied string from inside double quotes + # Returns unquoted string + str =~ /^"(.*?)"$/ ? $1 : str + end + def join_domain( arr ) arr.map {|i| if /\A\[.*\]\z/ === i @@ -149,6 +170,7 @@ module TMail } def timezone_string_to_unixtime( str ) + # Takes a time zone string from an EMail and converts it to Unix Time (seconds) if m = /([\+\-])(\d\d?)(\d\d)/.match(str) sec = (m[2].to_i * 60 + m[3].to_i) * 60 m[1] == '-' ? -sec : sec @@ -233,6 +255,27 @@ module TMail end end + def quote_boundary + # Make sure the Content-Type boundary= parameter is quoted if it contains illegal characters + # (to ensure any special characters in the boundary text are escaped from the parser + # (such as = in MS Outlook's boundary text)) + if @body =~ /^(.*)boundary=(.*)$/m + preamble = $1 + remainder = $2 + if remainder =~ /;/ + remainder =~ /^(.*)(;.*)$/m + boundary_text = $1 + post = $2.chomp + else + boundary_text = remainder.chomp + end + if boundary_text =~ /[\/\?\=]/ + boundary_text = "\"#{boundary_text}\"" unless boundary_text =~ /^".*?"$/ + @body = "#{preamble}boundary=#{boundary_text}#{post}" + end + end + end + end end diff --git a/actionmailer/lib/action_mailer/vendor/tmail/version.rb b/actionmailer/lib/action_mailer/vendor/tmail/version.rb new file mode 100644 index 0000000000..175ea92538 --- /dev/null +++ b/actionmailer/lib/action_mailer/vendor/tmail/version.rb @@ -0,0 +1,38 @@ +# +# version.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki +# +# 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. +#++ + +module TMail #:nodoc: + module VERSION #:nodoc: + MAJOR = 1 + MINOR = 1 + TINY = 0 + + STRING = [MAJOR, MINOR, TINY].join('.') + end +end diff --git a/actionmailer/test/fixtures/raw_email_with_invalid_characters_in_content_type b/actionmailer/test/fixtures/raw_email_with_invalid_characters_in_content_type new file mode 100644 index 0000000000..a8ff7ed4cb --- /dev/null +++ b/actionmailer/test/fixtures/raw_email_with_invalid_characters_in_content_type @@ -0,0 +1,104 @@ +Return-Path: +Received: from some.isp.com by baci with ESMTP id 632BD5758 for ; Sun, 21 Oct 2007 19:38:21 +1000 +Date: Sun, 21 Oct 2007 19:38:13 +1000 +From: Mikel Lindsaar +Reply-To: Mikel Lindsaar +To: mikel.lindsaar@baci +Message-Id: <009601c813c6$19df3510$0437d30a@mikel091a> +Subject: Testing outlook +Mime-Version: 1.0 +Content-Type: multipart/alternative; boundary=----=_NextPart_000_0093_01C81419.EB75E850 +Delivered-To: mikel.lindsaar@baci +X-Mimeole: Produced By Microsoft MimeOLE V6.00.2900.3138 +X-Msmail-Priority: Normal + +This is a multi-part message in MIME format. + + +------=_NextPart_000_0093_01C81419.EB75E850 +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: Quoted-printable + +Hello +This is an outlook test + +So there. + +Me. + +------=_NextPart_000_0093_01C81419.EB75E850 +Content-Type: text/html; charset=iso-8859-1 +Content-Transfer-Encoding: Quoted-printable + + + + + + + + +
Hello
+
This is an outlook=20 +test
+
 
+
So there.
+
 
+
Me.
+ + +------=_NextPart_000_0093_01C81419.EB75E850-- + + +Return-Path: +Received: from some.isp.com by baci with ESMTP id 632BD5758 for ; Sun, 21 Oct 2007 19:38:21 +1000 +Date: Sun, 21 Oct 2007 19:38:13 +1000 +From: Mikel Lindsaar +Reply-To: Mikel Lindsaar +To: mikel.lindsaar@baci +Message-Id: <009601c813c6$19df3510$0437d30a@mikel091a> +Subject: Testing outlook +Mime-Version: 1.0 +Content-Type: multipart/alternative; boundary=----=_NextPart_000_0093_01C81419.EB75E850 +Delivered-To: mikel.lindsaar@baci +X-Mimeole: Produced By Microsoft MimeOLE V6.00.2900.3138 +X-Msmail-Priority: Normal + +This is a multi-part message in MIME format. + + +------=_NextPart_000_0093_01C81419.EB75E850 +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: Quoted-printable + +Hello +This is an outlook test + +So there. + +Me. + +------=_NextPart_000_0093_01C81419.EB75E850 +Content-Type: text/html; charset=iso-8859-1 +Content-Transfer-Encoding: Quoted-printable + + + + + + + + +
Hello
+
This is an outlook=20 +test
+
 
+
So there.
+
 
+
Me.
+ + +------=_NextPart_000_0093_01C81419.EB75E850-- + +