mms2r 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/Manifest.txt +54 -0
- data/README.txt +81 -0
- data/Rakefile +30 -0
- data/conf/mms2r_cingularmedia_transform.yml +6 -0
- data/conf/mms2r_sprintmedia_ignore.yml +10 -0
- data/conf/mms2r_tmobilemedia_ignore.yml +17 -0
- data/conf/mms2r_verizonmedia_ignore.yml +3 -0
- data/lib/mms2r.rb +3 -0
- data/lib/mms2r/cingular_media.rb +11 -0
- data/lib/mms2r/media.rb +345 -0
- data/lib/mms2r/mmode_media.rb +13 -0
- data/lib/mms2r/sprint_media.rb +50 -0
- data/lib/mms2r/tmobile_media.rb +11 -0
- data/lib/mms2r/verizon_media.rb +11 -0
- data/lib/mms2r/version.rb +12 -0
- data/lib/vendor/text/format.rb +1466 -0
- data/lib/vendor/tmail.rb +3 -0
- data/lib/vendor/tmail/address.rb +242 -0
- data/lib/vendor/tmail/attachments.rb +39 -0
- data/lib/vendor/tmail/base64.rb +71 -0
- data/lib/vendor/tmail/config.rb +69 -0
- data/lib/vendor/tmail/encode.rb +467 -0
- data/lib/vendor/tmail/facade.rb +552 -0
- data/lib/vendor/tmail/header.rb +914 -0
- data/lib/vendor/tmail/info.rb +35 -0
- data/lib/vendor/tmail/loader.rb +1 -0
- data/lib/vendor/tmail/mail.rb +447 -0
- data/lib/vendor/tmail/mailbox.rb +433 -0
- data/lib/vendor/tmail/mbox.rb +1 -0
- data/lib/vendor/tmail/net.rb +280 -0
- data/lib/vendor/tmail/obsolete.rb +135 -0
- data/lib/vendor/tmail/parser.rb +1522 -0
- data/lib/vendor/tmail/port.rb +377 -0
- data/lib/vendor/tmail/quoting.rb +131 -0
- data/lib/vendor/tmail/scanner.rb +41 -0
- data/lib/vendor/tmail/scanner_r.rb +263 -0
- data/lib/vendor/tmail/stringio.rb +277 -0
- data/lib/vendor/tmail/tmail.rb +1 -0
- data/lib/vendor/tmail/utils.rb +238 -0
- data/test/files/dot.jpg +0 -0
- data/test/files/sprint-image-01.mail +195 -0
- data/test/files/sprint-text-01.mail +8 -0
- data/test/files/sprint-video-01.mail +195 -0
- data/test/files/sprint.mov +0 -0
- data/test/files/verizon-image-01.mail +815 -0
- data/test/files/verizon-text-01.mail +11 -0
- data/test/files/verizon-video-01.mail +336 -0
- data/test/test_mms2r_cingular.rb +52 -0
- data/test/test_mms2r_media.rb +311 -0
- data/test/test_mms2r_mmode.rb +52 -0
- data/test/test_mms2r_sprint.rb +154 -0
- data/test/test_mms2r_tmobile.rb +169 -0
- data/test/test_mms2r_verizon.rb +74 -0
- metadata +130 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
#
|
2
|
+
# scanner.rb
|
3
|
+
#
|
4
|
+
#--
|
5
|
+
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
8
|
+
# a copy of this software and associated documentation files (the
|
9
|
+
# "Software"), to deal in the Software without restriction, including
|
10
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
11
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
12
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
13
|
+
# the following conditions:
|
14
|
+
#
|
15
|
+
# The above copyright notice and this permission notice shall be
|
16
|
+
# included in all copies or substantial portions of the Software.
|
17
|
+
#
|
18
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
20
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
21
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
22
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
23
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
24
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
#
|
26
|
+
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
27
|
+
# with permission of Minero Aoki.
|
28
|
+
#++
|
29
|
+
|
30
|
+
require 'tmail/utils'
|
31
|
+
|
32
|
+
module TMail
|
33
|
+
require 'tmail/scanner_r.rb'
|
34
|
+
begin
|
35
|
+
raise LoadError, 'Turn off Ruby extention by user choice' if ENV['NORUBYEXT']
|
36
|
+
require 'tmail/scanner_c.so'
|
37
|
+
Scanner = Scanner_C
|
38
|
+
rescue LoadError
|
39
|
+
Scanner = Scanner_R
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,263 @@
|
|
1
|
+
#
|
2
|
+
# scanner_r.rb
|
3
|
+
#
|
4
|
+
#--
|
5
|
+
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
8
|
+
# a copy of this software and associated documentation files (the
|
9
|
+
# "Software"), to deal in the Software without restriction, including
|
10
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
11
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
12
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
13
|
+
# the following conditions:
|
14
|
+
#
|
15
|
+
# The above copyright notice and this permission notice shall be
|
16
|
+
# included in all copies or substantial portions of the Software.
|
17
|
+
#
|
18
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
20
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
21
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
22
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
23
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
24
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
#
|
26
|
+
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
27
|
+
# with permission of Minero Aoki.
|
28
|
+
#++
|
29
|
+
|
30
|
+
require 'tmail/config'
|
31
|
+
|
32
|
+
|
33
|
+
module TMail
|
34
|
+
|
35
|
+
class Scanner_R
|
36
|
+
|
37
|
+
Version = '0.10.7'
|
38
|
+
Version.freeze
|
39
|
+
|
40
|
+
MIME_HEADERS = {
|
41
|
+
:CTYPE => true,
|
42
|
+
:CENCODING => true,
|
43
|
+
:CDISPOSITION => true
|
44
|
+
}
|
45
|
+
|
46
|
+
alnum = 'a-zA-Z0-9'
|
47
|
+
atomsyms = %q[ _#!$%&`'*+-{|}~^@/=? ].strip
|
48
|
+
tokensyms = %q[ _#!$%&`'*+-{|}~^@. ].strip
|
49
|
+
|
50
|
+
atomchars = alnum + Regexp.quote(atomsyms)
|
51
|
+
tokenchars = alnum + Regexp.quote(tokensyms)
|
52
|
+
iso2022str = '\e(?!\(B)..(?:[^\e]+|\e(?!\(B)..)*\e\(B'
|
53
|
+
|
54
|
+
eucstr = '(?:[\xa1-\xfe][\xa1-\xfe])+'
|
55
|
+
sjisstr = '(?:[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc])+'
|
56
|
+
utf8str = '(?:[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf])+'
|
57
|
+
|
58
|
+
quoted_with_iso2022 = /\A(?:[^\\\e"]+|#{iso2022str})+/n
|
59
|
+
domlit_with_iso2022 = /\A(?:[^\\\e\]]+|#{iso2022str})+/n
|
60
|
+
comment_with_iso2022 = /\A(?:[^\\\e()]+|#{iso2022str})+/n
|
61
|
+
|
62
|
+
quoted_without_iso2022 = /\A[^\\"]+/n
|
63
|
+
domlit_without_iso2022 = /\A[^\\\]]+/n
|
64
|
+
comment_without_iso2022 = /\A[^\\()]+/n
|
65
|
+
|
66
|
+
PATTERN_TABLE = {}
|
67
|
+
PATTERN_TABLE['EUC'] =
|
68
|
+
[
|
69
|
+
/\A(?:[#{atomchars}]+|#{iso2022str}|#{eucstr})+/n,
|
70
|
+
/\A(?:[#{tokenchars}]+|#{iso2022str}|#{eucstr})+/n,
|
71
|
+
quoted_with_iso2022,
|
72
|
+
domlit_with_iso2022,
|
73
|
+
comment_with_iso2022
|
74
|
+
]
|
75
|
+
PATTERN_TABLE['SJIS'] =
|
76
|
+
[
|
77
|
+
/\A(?:[#{atomchars}]+|#{iso2022str}|#{sjisstr})+/n,
|
78
|
+
/\A(?:[#{tokenchars}]+|#{iso2022str}|#{sjisstr})+/n,
|
79
|
+
quoted_with_iso2022,
|
80
|
+
domlit_with_iso2022,
|
81
|
+
comment_with_iso2022
|
82
|
+
]
|
83
|
+
PATTERN_TABLE['UTF8'] =
|
84
|
+
[
|
85
|
+
/\A(?:[#{atomchars}]+|#{utf8str})+/n,
|
86
|
+
/\A(?:[#{tokenchars}]+|#{utf8str})+/n,
|
87
|
+
quoted_without_iso2022,
|
88
|
+
domlit_without_iso2022,
|
89
|
+
comment_without_iso2022
|
90
|
+
]
|
91
|
+
PATTERN_TABLE['NONE'] =
|
92
|
+
[
|
93
|
+
/\A[#{atomchars}]+/n,
|
94
|
+
/\A[#{tokenchars}]+/n,
|
95
|
+
quoted_without_iso2022,
|
96
|
+
domlit_without_iso2022,
|
97
|
+
comment_without_iso2022
|
98
|
+
]
|
99
|
+
|
100
|
+
|
101
|
+
def initialize( str, scantype, comments )
|
102
|
+
init_scanner str
|
103
|
+
@comments = comments || []
|
104
|
+
@debug = false
|
105
|
+
|
106
|
+
# fix scanner mode
|
107
|
+
@received = (scantype == :RECEIVED)
|
108
|
+
@is_mime_header = MIME_HEADERS[scantype]
|
109
|
+
|
110
|
+
atom, token, @quoted_re, @domlit_re, @comment_re = PATTERN_TABLE[$KCODE]
|
111
|
+
@word_re = (MIME_HEADERS[scantype] ? token : atom)
|
112
|
+
end
|
113
|
+
|
114
|
+
attr_accessor :debug
|
115
|
+
|
116
|
+
def scan( &block )
|
117
|
+
if @debug
|
118
|
+
scan_main do |arr|
|
119
|
+
s, v = arr
|
120
|
+
printf "%7d %-10s %s\n",
|
121
|
+
rest_size(),
|
122
|
+
s.respond_to?(:id2name) ? s.id2name : s.inspect,
|
123
|
+
v.inspect
|
124
|
+
yield arr
|
125
|
+
end
|
126
|
+
else
|
127
|
+
scan_main(&block)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
RECV_TOKEN = {
|
134
|
+
'from' => :FROM,
|
135
|
+
'by' => :BY,
|
136
|
+
'via' => :VIA,
|
137
|
+
'with' => :WITH,
|
138
|
+
'id' => :ID,
|
139
|
+
'for' => :FOR
|
140
|
+
}
|
141
|
+
|
142
|
+
def scan_main
|
143
|
+
until eof?
|
144
|
+
if skip(/\A[\n\r\t ]+/n) # LWSP
|
145
|
+
break if eof?
|
146
|
+
end
|
147
|
+
|
148
|
+
if s = readstr(@word_re)
|
149
|
+
if @is_mime_header
|
150
|
+
yield :TOKEN, s
|
151
|
+
else
|
152
|
+
# atom
|
153
|
+
if /\A\d+\z/ === s
|
154
|
+
yield :DIGIT, s
|
155
|
+
elsif @received
|
156
|
+
yield RECV_TOKEN[s.downcase] || :ATOM, s
|
157
|
+
else
|
158
|
+
yield :ATOM, s
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
elsif skip(/\A"/)
|
163
|
+
yield :QUOTED, scan_quoted_word()
|
164
|
+
|
165
|
+
elsif skip(/\A\[/)
|
166
|
+
yield :DOMLIT, scan_domain_literal()
|
167
|
+
|
168
|
+
elsif skip(/\A\(/)
|
169
|
+
@comments.push scan_comment()
|
170
|
+
|
171
|
+
else
|
172
|
+
c = readchar()
|
173
|
+
yield c, c
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
yield false, '$'
|
178
|
+
end
|
179
|
+
|
180
|
+
def scan_quoted_word
|
181
|
+
scan_qstr(@quoted_re, /\A"/, 'quoted-word')
|
182
|
+
end
|
183
|
+
|
184
|
+
def scan_domain_literal
|
185
|
+
'[' + scan_qstr(@domlit_re, /\A\]/, 'domain-literal') + ']'
|
186
|
+
end
|
187
|
+
|
188
|
+
def scan_qstr( pattern, terminal, type )
|
189
|
+
result = ''
|
190
|
+
until eof?
|
191
|
+
if s = readstr(pattern) then result << s
|
192
|
+
elsif skip(terminal) then return result
|
193
|
+
elsif skip(/\A\\/) then result << readchar()
|
194
|
+
else
|
195
|
+
raise "TMail FATAL: not match in #{type}"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
scan_error! "found unterminated #{type}"
|
199
|
+
end
|
200
|
+
|
201
|
+
def scan_comment
|
202
|
+
result = ''
|
203
|
+
nest = 1
|
204
|
+
content = @comment_re
|
205
|
+
|
206
|
+
until eof?
|
207
|
+
if s = readstr(content) then result << s
|
208
|
+
elsif skip(/\A\)/) then nest -= 1
|
209
|
+
return result if nest == 0
|
210
|
+
result << ')'
|
211
|
+
elsif skip(/\A\(/) then nest += 1
|
212
|
+
result << '('
|
213
|
+
elsif skip(/\A\\/) then result << readchar()
|
214
|
+
else
|
215
|
+
raise 'TMail FATAL: not match in comment'
|
216
|
+
end
|
217
|
+
end
|
218
|
+
scan_error! 'found unterminated comment'
|
219
|
+
end
|
220
|
+
|
221
|
+
# string scanner
|
222
|
+
|
223
|
+
def init_scanner( str )
|
224
|
+
@src = str
|
225
|
+
end
|
226
|
+
|
227
|
+
def eof?
|
228
|
+
@src.empty?
|
229
|
+
end
|
230
|
+
|
231
|
+
def rest_size
|
232
|
+
@src.size
|
233
|
+
end
|
234
|
+
|
235
|
+
def readstr( re )
|
236
|
+
if m = re.match(@src)
|
237
|
+
@src = m.post_match
|
238
|
+
m[0]
|
239
|
+
else
|
240
|
+
nil
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def readchar
|
245
|
+
readstr(/\A./)
|
246
|
+
end
|
247
|
+
|
248
|
+
def skip( re )
|
249
|
+
if m = re.match(@src)
|
250
|
+
@src = m.post_match
|
251
|
+
true
|
252
|
+
else
|
253
|
+
false
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def scan_error!( msg )
|
258
|
+
raise SyntaxError, msg
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
|
263
|
+
end # module TMail
|
@@ -0,0 +1,277 @@
|
|
1
|
+
#
|
2
|
+
# stringio.rb
|
3
|
+
#
|
4
|
+
#--
|
5
|
+
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
8
|
+
# a copy of this software and associated documentation files (the
|
9
|
+
# "Software"), to deal in the Software without restriction, including
|
10
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
11
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
12
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
13
|
+
# the following conditions:
|
14
|
+
#
|
15
|
+
# The above copyright notice and this permission notice shall be
|
16
|
+
# included in all copies or substantial portions of the Software.
|
17
|
+
#
|
18
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
19
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
20
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
21
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
22
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
23
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
24
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
#
|
26
|
+
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
27
|
+
# with permission of Minero Aoki.
|
28
|
+
#++
|
29
|
+
|
30
|
+
class StringInput#:nodoc:
|
31
|
+
|
32
|
+
include Enumerable
|
33
|
+
|
34
|
+
class << self
|
35
|
+
|
36
|
+
def new( str )
|
37
|
+
if block_given?
|
38
|
+
begin
|
39
|
+
f = super
|
40
|
+
yield f
|
41
|
+
ensure
|
42
|
+
f.close if f
|
43
|
+
end
|
44
|
+
else
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
alias open new
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize( str )
|
54
|
+
@src = str
|
55
|
+
@pos = 0
|
56
|
+
@closed = false
|
57
|
+
@lineno = 0
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :lineno
|
61
|
+
|
62
|
+
def string
|
63
|
+
@src
|
64
|
+
end
|
65
|
+
|
66
|
+
def inspect
|
67
|
+
"#<#{self.class}:#{@closed ? 'closed' : 'open'},src=#{@src[0,30].inspect}>"
|
68
|
+
end
|
69
|
+
|
70
|
+
def close
|
71
|
+
stream_check!
|
72
|
+
@pos = nil
|
73
|
+
@closed = true
|
74
|
+
end
|
75
|
+
|
76
|
+
def closed?
|
77
|
+
@closed
|
78
|
+
end
|
79
|
+
|
80
|
+
def pos
|
81
|
+
stream_check!
|
82
|
+
[@pos, @src.size].min
|
83
|
+
end
|
84
|
+
|
85
|
+
alias tell pos
|
86
|
+
|
87
|
+
def seek( offset, whence = IO::SEEK_SET )
|
88
|
+
stream_check!
|
89
|
+
case whence
|
90
|
+
when IO::SEEK_SET
|
91
|
+
@pos = offset
|
92
|
+
when IO::SEEK_CUR
|
93
|
+
@pos += offset
|
94
|
+
when IO::SEEK_END
|
95
|
+
@pos = @src.size - offset
|
96
|
+
else
|
97
|
+
raise ArgumentError, "unknown seek flag: #{whence}"
|
98
|
+
end
|
99
|
+
@pos = 0 if @pos < 0
|
100
|
+
@pos = [@pos, @src.size + 1].min
|
101
|
+
offset
|
102
|
+
end
|
103
|
+
|
104
|
+
def rewind
|
105
|
+
stream_check!
|
106
|
+
@pos = 0
|
107
|
+
end
|
108
|
+
|
109
|
+
def eof?
|
110
|
+
stream_check!
|
111
|
+
@pos > @src.size
|
112
|
+
end
|
113
|
+
|
114
|
+
def each( &block )
|
115
|
+
stream_check!
|
116
|
+
begin
|
117
|
+
@src.each(&block)
|
118
|
+
ensure
|
119
|
+
@pos = 0
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def gets
|
124
|
+
stream_check!
|
125
|
+
if idx = @src.index(?\n, @pos)
|
126
|
+
idx += 1 # "\n".size
|
127
|
+
line = @src[ @pos ... idx ]
|
128
|
+
@pos = idx
|
129
|
+
@pos += 1 if @pos == @src.size
|
130
|
+
else
|
131
|
+
line = @src[ @pos .. -1 ]
|
132
|
+
@pos = @src.size + 1
|
133
|
+
end
|
134
|
+
@lineno += 1
|
135
|
+
|
136
|
+
line
|
137
|
+
end
|
138
|
+
|
139
|
+
def getc
|
140
|
+
stream_check!
|
141
|
+
ch = @src[@pos]
|
142
|
+
@pos += 1
|
143
|
+
@pos += 1 if @pos == @src.size
|
144
|
+
ch
|
145
|
+
end
|
146
|
+
|
147
|
+
def read( len = nil )
|
148
|
+
stream_check!
|
149
|
+
return read_all unless len
|
150
|
+
str = @src[@pos, len]
|
151
|
+
@pos += len
|
152
|
+
@pos += 1 if @pos == @src.size
|
153
|
+
str
|
154
|
+
end
|
155
|
+
|
156
|
+
alias sysread read
|
157
|
+
|
158
|
+
def read_all
|
159
|
+
stream_check!
|
160
|
+
return nil if eof?
|
161
|
+
rest = @src[@pos ... @src.size]
|
162
|
+
@pos = @src.size + 1
|
163
|
+
rest
|
164
|
+
end
|
165
|
+
|
166
|
+
def stream_check!
|
167
|
+
@closed and raise IOError, 'closed stream'
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
class StringOutput#:nodoc:
|
174
|
+
|
175
|
+
class << self
|
176
|
+
|
177
|
+
def new( str = '' )
|
178
|
+
if block_given?
|
179
|
+
begin
|
180
|
+
f = super
|
181
|
+
yield f
|
182
|
+
ensure
|
183
|
+
f.close if f
|
184
|
+
end
|
185
|
+
else
|
186
|
+
super
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
alias open new
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
def initialize( str = '' )
|
195
|
+
@dest = str
|
196
|
+
@closed = false
|
197
|
+
end
|
198
|
+
|
199
|
+
def close
|
200
|
+
@closed = true
|
201
|
+
end
|
202
|
+
|
203
|
+
def closed?
|
204
|
+
@closed
|
205
|
+
end
|
206
|
+
|
207
|
+
def string
|
208
|
+
@dest
|
209
|
+
end
|
210
|
+
|
211
|
+
alias value string
|
212
|
+
alias to_str string
|
213
|
+
|
214
|
+
def size
|
215
|
+
@dest.size
|
216
|
+
end
|
217
|
+
|
218
|
+
alias pos size
|
219
|
+
|
220
|
+
def inspect
|
221
|
+
"#<#{self.class}:#{@dest ? 'open' : 'closed'},#{id}>"
|
222
|
+
end
|
223
|
+
|
224
|
+
def print( *args )
|
225
|
+
stream_check!
|
226
|
+
raise ArgumentError, 'wrong # of argument (0 for >1)' if args.empty?
|
227
|
+
args.each do |s|
|
228
|
+
raise ArgumentError, 'nil not allowed' if s.nil?
|
229
|
+
@dest << s.to_s
|
230
|
+
end
|
231
|
+
nil
|
232
|
+
end
|
233
|
+
|
234
|
+
def puts( *args )
|
235
|
+
stream_check!
|
236
|
+
args.each do |str|
|
237
|
+
@dest << (s = str.to_s)
|
238
|
+
@dest << "\n" unless s[-1] == ?\n
|
239
|
+
end
|
240
|
+
@dest << "\n" if args.empty?
|
241
|
+
nil
|
242
|
+
end
|
243
|
+
|
244
|
+
def putc( ch )
|
245
|
+
stream_check!
|
246
|
+
@dest << ch.chr
|
247
|
+
nil
|
248
|
+
end
|
249
|
+
|
250
|
+
def printf( *args )
|
251
|
+
stream_check!
|
252
|
+
@dest << sprintf(*args)
|
253
|
+
nil
|
254
|
+
end
|
255
|
+
|
256
|
+
def write( str )
|
257
|
+
stream_check!
|
258
|
+
s = str.to_s
|
259
|
+
@dest << s
|
260
|
+
s.size
|
261
|
+
end
|
262
|
+
|
263
|
+
alias syswrite write
|
264
|
+
|
265
|
+
def <<( str )
|
266
|
+
stream_check!
|
267
|
+
@dest << str.to_s
|
268
|
+
self
|
269
|
+
end
|
270
|
+
|
271
|
+
private
|
272
|
+
|
273
|
+
def stream_check!
|
274
|
+
@closed and raise IOError, 'closed stream'
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|