mms2r 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +54 -0
  3. data/README.txt +81 -0
  4. data/Rakefile +30 -0
  5. data/conf/mms2r_cingularmedia_transform.yml +6 -0
  6. data/conf/mms2r_sprintmedia_ignore.yml +10 -0
  7. data/conf/mms2r_tmobilemedia_ignore.yml +17 -0
  8. data/conf/mms2r_verizonmedia_ignore.yml +3 -0
  9. data/lib/mms2r.rb +3 -0
  10. data/lib/mms2r/cingular_media.rb +11 -0
  11. data/lib/mms2r/media.rb +345 -0
  12. data/lib/mms2r/mmode_media.rb +13 -0
  13. data/lib/mms2r/sprint_media.rb +50 -0
  14. data/lib/mms2r/tmobile_media.rb +11 -0
  15. data/lib/mms2r/verizon_media.rb +11 -0
  16. data/lib/mms2r/version.rb +12 -0
  17. data/lib/vendor/text/format.rb +1466 -0
  18. data/lib/vendor/tmail.rb +3 -0
  19. data/lib/vendor/tmail/address.rb +242 -0
  20. data/lib/vendor/tmail/attachments.rb +39 -0
  21. data/lib/vendor/tmail/base64.rb +71 -0
  22. data/lib/vendor/tmail/config.rb +69 -0
  23. data/lib/vendor/tmail/encode.rb +467 -0
  24. data/lib/vendor/tmail/facade.rb +552 -0
  25. data/lib/vendor/tmail/header.rb +914 -0
  26. data/lib/vendor/tmail/info.rb +35 -0
  27. data/lib/vendor/tmail/loader.rb +1 -0
  28. data/lib/vendor/tmail/mail.rb +447 -0
  29. data/lib/vendor/tmail/mailbox.rb +433 -0
  30. data/lib/vendor/tmail/mbox.rb +1 -0
  31. data/lib/vendor/tmail/net.rb +280 -0
  32. data/lib/vendor/tmail/obsolete.rb +135 -0
  33. data/lib/vendor/tmail/parser.rb +1522 -0
  34. data/lib/vendor/tmail/port.rb +377 -0
  35. data/lib/vendor/tmail/quoting.rb +131 -0
  36. data/lib/vendor/tmail/scanner.rb +41 -0
  37. data/lib/vendor/tmail/scanner_r.rb +263 -0
  38. data/lib/vendor/tmail/stringio.rb +277 -0
  39. data/lib/vendor/tmail/tmail.rb +1 -0
  40. data/lib/vendor/tmail/utils.rb +238 -0
  41. data/test/files/dot.jpg +0 -0
  42. data/test/files/sprint-image-01.mail +195 -0
  43. data/test/files/sprint-text-01.mail +8 -0
  44. data/test/files/sprint-video-01.mail +195 -0
  45. data/test/files/sprint.mov +0 -0
  46. data/test/files/verizon-image-01.mail +815 -0
  47. data/test/files/verizon-text-01.mail +11 -0
  48. data/test/files/verizon-video-01.mail +336 -0
  49. data/test/test_mms2r_cingular.rb +52 -0
  50. data/test/test_mms2r_media.rb +311 -0
  51. data/test/test_mms2r_mmode.rb +52 -0
  52. data/test/test_mms2r_sprint.rb +154 -0
  53. data/test/test_mms2r_tmobile.rb +169 -0
  54. data/test/test_mms2r_verizon.rb +74 -0
  55. metadata +130 -0
@@ -0,0 +1,35 @@
1
+ #
2
+ # info.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
+ module TMail
31
+
32
+ Version = '0.10.7'
33
+ Copyright = 'Copyright (c) 1998-2002 Minero Aoki'
34
+
35
+ end
@@ -0,0 +1 @@
1
+ require 'tmail/mailbox'
@@ -0,0 +1,447 @@
1
+ #
2
+ # mail.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/facade'
31
+ require 'tmail/encode'
32
+ require 'tmail/header'
33
+ require 'tmail/port'
34
+ require 'tmail/config'
35
+ require 'tmail/utils'
36
+ require 'tmail/attachments'
37
+ require 'tmail/quoting'
38
+ require 'socket'
39
+
40
+
41
+ module TMail
42
+
43
+ class Mail
44
+
45
+ class << self
46
+ def load( fname )
47
+ new(FilePort.new(fname))
48
+ end
49
+
50
+ alias load_from load
51
+ alias loadfrom load
52
+
53
+ def parse( str )
54
+ new(StringPort.new(str))
55
+ end
56
+ end
57
+
58
+ def initialize( port = nil, conf = DEFAULT_CONFIG )
59
+ @port = port || StringPort.new
60
+ @config = Config.to_config(conf)
61
+
62
+ @header = {}
63
+ @body_port = nil
64
+ @body_parsed = false
65
+ @epilogue = ''
66
+ @parts = []
67
+
68
+ @port.ropen {|f|
69
+ parse_header f
70
+ parse_body f unless @port.reproducible?
71
+ }
72
+ end
73
+
74
+ attr_reader :port
75
+
76
+ def inspect
77
+ "\#<#{self.class} port=#{@port.inspect} bodyport=#{@body_port.inspect}>"
78
+ end
79
+
80
+ #
81
+ # to_s interfaces
82
+ #
83
+
84
+ public
85
+
86
+ include StrategyInterface
87
+
88
+ def write_back( eol = "\n", charset = 'e' )
89
+ parse_body
90
+ @port.wopen {|stream| encoded eol, charset, stream }
91
+ end
92
+
93
+ def accept( strategy )
94
+ with_multipart_encoding(strategy) {
95
+ ordered_each do |name, field|
96
+ next if field.empty?
97
+ strategy.header_name canonical(name)
98
+ field.accept strategy
99
+ strategy.puts
100
+ end
101
+ strategy.puts
102
+ body_port().ropen {|r|
103
+ strategy.write r.read
104
+ }
105
+ }
106
+ end
107
+
108
+ private
109
+
110
+ def canonical( name )
111
+ name.split(/-/).map {|s| s.capitalize }.join('-')
112
+ end
113
+
114
+ def with_multipart_encoding( strategy )
115
+ if parts().empty? # DO NOT USE @parts
116
+ yield
117
+
118
+ else
119
+ bound = ::TMail.new_boundary
120
+ if @header.key? 'content-type'
121
+ @header['content-type'].params['boundary'] = bound
122
+ else
123
+ store 'Content-Type', %<multipart/mixed; boundary="#{bound}">
124
+ end
125
+
126
+ yield
127
+
128
+ parts().each do |tm|
129
+ strategy.puts
130
+ strategy.puts '--' + bound
131
+ tm.accept strategy
132
+ end
133
+ strategy.puts
134
+ strategy.puts '--' + bound + '--'
135
+ strategy.write epilogue()
136
+ end
137
+ end
138
+
139
+ ###
140
+ ### header
141
+ ###
142
+
143
+ public
144
+
145
+ ALLOW_MULTIPLE = {
146
+ 'received' => true,
147
+ 'resent-date' => true,
148
+ 'resent-from' => true,
149
+ 'resent-sender' => true,
150
+ 'resent-to' => true,
151
+ 'resent-cc' => true,
152
+ 'resent-bcc' => true,
153
+ 'resent-message-id' => true,
154
+ 'comments' => true,
155
+ 'keywords' => true
156
+ }
157
+ USE_ARRAY = ALLOW_MULTIPLE
158
+
159
+ def header
160
+ @header.dup
161
+ end
162
+
163
+ def []( key )
164
+ @header[key.downcase]
165
+ end
166
+
167
+ def sub_header(key, param)
168
+ (hdr = self[key]) ? hdr[param] : nil
169
+ end
170
+
171
+ alias fetch []
172
+
173
+ def []=( key, val )
174
+ dkey = key.downcase
175
+
176
+ if val.nil?
177
+ @header.delete dkey
178
+ return nil
179
+ end
180
+
181
+ case val
182
+ when String
183
+ header = new_hf(key, val)
184
+ when HeaderField
185
+ ;
186
+ when Array
187
+ ALLOW_MULTIPLE.include? dkey or
188
+ raise ArgumentError, "#{key}: Header must not be multiple"
189
+ @header[dkey] = val
190
+ return val
191
+ else
192
+ header = new_hf(key, val.to_s)
193
+ end
194
+ if ALLOW_MULTIPLE.include? dkey
195
+ (@header[dkey] ||= []).push header
196
+ else
197
+ @header[dkey] = header
198
+ end
199
+
200
+ val
201
+ end
202
+
203
+ alias store []=
204
+
205
+ def each_header
206
+ @header.each do |key, val|
207
+ [val].flatten.each {|v| yield key, v }
208
+ end
209
+ end
210
+
211
+ alias each_pair each_header
212
+
213
+ def each_header_name( &block )
214
+ @header.each_key(&block)
215
+ end
216
+
217
+ alias each_key each_header_name
218
+
219
+ def each_field( &block )
220
+ @header.values.flatten.each(&block)
221
+ end
222
+
223
+ alias each_value each_field
224
+
225
+ FIELD_ORDER = %w(
226
+ return-path received
227
+ resent-date resent-from resent-sender resent-to
228
+ resent-cc resent-bcc resent-message-id
229
+ date from sender reply-to to cc bcc
230
+ message-id in-reply-to references
231
+ subject comments keywords
232
+ mime-version content-type content-transfer-encoding
233
+ content-disposition content-description
234
+ )
235
+
236
+ def ordered_each
237
+ list = @header.keys
238
+ FIELD_ORDER.each do |name|
239
+ if list.delete(name)
240
+ [@header[name]].flatten.each {|v| yield name, v }
241
+ end
242
+ end
243
+ list.each do |name|
244
+ [@header[name]].flatten.each {|v| yield name, v }
245
+ end
246
+ end
247
+
248
+ def clear
249
+ @header.clear
250
+ end
251
+
252
+ def delete( key )
253
+ @header.delete key.downcase
254
+ end
255
+
256
+ def delete_if
257
+ @header.delete_if do |key,val|
258
+ if Array === val
259
+ val.delete_if {|v| yield key, v }
260
+ val.empty?
261
+ else
262
+ yield key, val
263
+ end
264
+ end
265
+ end
266
+
267
+ def keys
268
+ @header.keys
269
+ end
270
+
271
+ def key?( key )
272
+ @header.key? key.downcase
273
+ end
274
+
275
+ def values_at( *args )
276
+ args.map {|k| @header[k.downcase] }.flatten
277
+ end
278
+
279
+ alias indexes values_at
280
+ alias indices values_at
281
+
282
+ private
283
+
284
+ def parse_header( f )
285
+ name = field = nil
286
+ unixfrom = nil
287
+
288
+ while line = f.gets
289
+ case line
290
+ when /\A[ \t]/ # continue from prev line
291
+ raise SyntaxError, 'mail is began by space' unless field
292
+ field << ' ' << line.strip
293
+
294
+ when /\A([^\: \t]+):\s*/ # new header line
295
+ add_hf name, field if field
296
+ name = $1
297
+ field = $' #.strip
298
+
299
+ when /\A\-*\s*\z/ # end of header
300
+ add_hf name, field if field
301
+ name = field = nil
302
+ break
303
+
304
+ when /\AFrom (\S+)/
305
+ unixfrom = $1
306
+
307
+ when /^charset=.*/
308
+
309
+ else
310
+ raise SyntaxError, "wrong mail header: '#{line.inspect}'"
311
+ end
312
+ end
313
+ add_hf name, field if name
314
+
315
+ if unixfrom
316
+ add_hf 'Return-Path', "<#{unixfrom}>" unless @header['return-path']
317
+ end
318
+ end
319
+
320
+ def add_hf( name, field )
321
+ key = name.downcase
322
+ field = new_hf(name, field)
323
+
324
+ if ALLOW_MULTIPLE.include? key
325
+ (@header[key] ||= []).push field
326
+ else
327
+ @header[key] = field
328
+ end
329
+ end
330
+
331
+ def new_hf( name, field )
332
+ HeaderField.new(name, field, @config)
333
+ end
334
+
335
+ ###
336
+ ### body
337
+ ###
338
+
339
+ public
340
+
341
+ def body_port
342
+ parse_body
343
+ @body_port
344
+ end
345
+
346
+ def each( &block )
347
+ body_port().ropen {|f| f.each(&block) }
348
+ end
349
+
350
+ def quoted_body
351
+ parse_body
352
+ @body_port.ropen {|f|
353
+ return f.read
354
+ }
355
+ end
356
+
357
+ def body=( str )
358
+ parse_body
359
+ @body_port.wopen {|f| f.write str }
360
+ str
361
+ end
362
+
363
+ alias preamble body
364
+ alias preamble= body=
365
+
366
+ def epilogue
367
+ parse_body
368
+ @epilogue.dup
369
+ end
370
+
371
+ def epilogue=( str )
372
+ parse_body
373
+ @epilogue = str
374
+ str
375
+ end
376
+
377
+ def parts
378
+ parse_body
379
+ @parts
380
+ end
381
+
382
+ def each_part( &block )
383
+ parts().each(&block)
384
+ end
385
+
386
+ private
387
+
388
+ def parse_body( f = nil )
389
+ return if @body_parsed
390
+ if f
391
+ parse_body_0 f
392
+ else
393
+ @port.ropen {|f|
394
+ skip_header f
395
+ parse_body_0 f
396
+ }
397
+ end
398
+ @body_parsed = true
399
+ end
400
+
401
+ def skip_header( f )
402
+ while line = f.gets
403
+ return if /\A[\r\n]*\z/ === line
404
+ end
405
+ end
406
+
407
+ def parse_body_0( f )
408
+ if multipart?
409
+ read_multipart f
410
+ else
411
+ @body_port = @config.new_body_port(self)
412
+ @body_port.wopen {|w|
413
+ w.write f.read
414
+ }
415
+ end
416
+ end
417
+
418
+ def read_multipart( src )
419
+ bound = @header['content-type'].params['boundary']
420
+ is_sep = /\A--#{Regexp.quote bound}(?:--)?[ \t]*(?:\n|\r\n|\r)/
421
+ lastbound = "--#{bound}--"
422
+
423
+ ports = [ @config.new_preamble_port(self) ]
424
+ begin
425
+ f = ports.last.wopen
426
+ while line = src.gets
427
+ if is_sep === line
428
+ f.close
429
+ break if line.strip == lastbound
430
+ ports.push @config.new_part_port(self)
431
+ f = ports.last.wopen
432
+ else
433
+ f << line
434
+ end
435
+ end
436
+ @epilogue = (src.read || '')
437
+ ensure
438
+ f.close if f and not f.closed?
439
+ end
440
+
441
+ @body_port = ports.shift
442
+ @parts = ports.map {|p| self.class.new(p, @config) }
443
+ end
444
+
445
+ end # class Mail
446
+
447
+ end # module TMail