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.
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