~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/quoting.rb

  • Committer: Richard Lee (Canonical)
  • Date: 2010-10-15 15:17:58 UTC
  • mfrom: (190.1.3 use-case-mapper)
  • Revision ID: richard.lee@canonical.com-20101015151758-wcvmfxrexsongf9d
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
=begin rdoc
2
 
 
3
 
= Quoting methods
4
 
 
5
 
=end
6
 
module TMail
7
 
  class Mail
8
 
    def subject(to_charset = 'utf-8')
9
 
      Unquoter.unquote_and_convert_to(quoted_subject, to_charset)
10
 
    end
11
 
 
12
 
    def unquoted_body(to_charset = 'utf-8')
13
 
      from_charset = sub_header("content-type", "charset")
14
 
      case (content_transfer_encoding || "7bit").downcase
15
 
        when "quoted-printable"
16
 
          # the default charset is set to iso-8859-1 instead of 'us-ascii'.
17
 
          # This is needed as many mailer do not set the charset but send in ISO. This is only used if no charset is set.
18
 
          if !from_charset.blank? && from_charset.downcase == 'us-ascii'
19
 
            from_charset = 'iso-8859-1'
20
 
          end
21
 
 
22
 
          Unquoter.unquote_quoted_printable_and_convert_to(quoted_body,
23
 
            to_charset, from_charset, true)
24
 
        when "base64"
25
 
          Unquoter.unquote_base64_and_convert_to(quoted_body, to_charset,
26
 
            from_charset)
27
 
        when "7bit", "8bit"
28
 
          Unquoter.convert_to(quoted_body, to_charset, from_charset)
29
 
        when "binary"
30
 
          quoted_body
31
 
        else
32
 
          quoted_body
33
 
      end
34
 
    end
35
 
 
36
 
    def body(to_charset = 'utf-8', &block)
37
 
      attachment_presenter = block || Proc.new { |file_name| "Attachment: #{file_name}\n" }
38
 
 
39
 
      if multipart?
40
 
        parts.collect { |part|
41
 
          header = part["content-type"]
42
 
 
43
 
          if part.multipart?
44
 
            part.body(to_charset, &attachment_presenter)
45
 
          elsif header.nil?
46
 
            ""
47
 
          elsif !attachment?(part)
48
 
            part.unquoted_body(to_charset)
49
 
          else
50
 
            attachment_presenter.call(header["name"] || "(unnamed)")
51
 
          end
52
 
        }.join
53
 
      else
54
 
        unquoted_body(to_charset)
55
 
      end
56
 
    end
57
 
  end
58
 
 
59
 
  class Unquoter
60
 
    class << self
61
 
      def unquote_and_convert_to(text, to_charset, from_charset = "iso-8859-1", preserve_underscores=false)
62
 
        return "" if text.nil?
63
 
        text.gsub(/(.*?)(?:(?:=\?(.*?)\?(.)\?(.*?)\?=)|$)/) do
64
 
          before = $1
65
 
          from_charset = $2
66
 
          quoting_method = $3
67
 
          text = $4
68
 
 
69
 
          before = convert_to(before, to_charset, from_charset) if before.length > 0
70
 
          before + case quoting_method
71
 
              when "q", "Q" then
72
 
                unquote_quoted_printable_and_convert_to(text, to_charset, from_charset, preserve_underscores)
73
 
              when "b", "B" then
74
 
                unquote_base64_and_convert_to(text, to_charset, from_charset)
75
 
              when nil then
76
 
                # will be nil at the end of the string, due to the nature of
77
 
                # the regex used.
78
 
                ""
79
 
              else
80
 
                raise "unknown quoting method #{quoting_method.inspect}"
81
 
            end
82
 
        end
83
 
      end
84
 
 
85
 
      def unquote_quoted_printable_and_convert_to(text, to, from, preserve_underscores=false)
86
 
        text = text.gsub(/_/, " ") unless preserve_underscores
87
 
        text = text.gsub(/\r\n|\r/, "\n") # normalize newlines
88
 
        convert_to(text.unpack("M*").first, to, from)
89
 
      end
90
 
 
91
 
      def unquote_base64_and_convert_to(text, to, from)
92
 
        convert_to(Base64.decode(text), to, from)
93
 
      end
94
 
 
95
 
      begin
96
 
        require 'iconv'
97
 
        def convert_to(text, to, from)
98
 
          return text unless to && from
99
 
          text ? Iconv.iconv(to, from, text).first : ""
100
 
        rescue Iconv::IllegalSequence, Iconv::InvalidEncoding, Errno::EINVAL
101
 
          # the 'from' parameter specifies a charset other than what the text
102
 
          # actually is...not much we can do in this case but just return the
103
 
          # unconverted text.
104
 
          #
105
 
          # Ditto if either parameter represents an unknown charset, like
106
 
          # X-UNKNOWN.
107
 
          text
108
 
        end
109
 
      rescue LoadError
110
 
        # Not providing quoting support
111
 
        def convert_to(text, to, from)
112
 
          warn "Action Mailer: iconv not loaded; ignoring conversion from #{from} to #{to} (#{__FILE__}:#{__LINE__})"
113
 
          text
114
 
        end
115
 
      end
116
 
    end
117
 
  end
118
 
end