mms2r 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/History.txt +21 -0
- data/Manifest.txt +3 -0
- data/README.txt +51 -40
- data/Rakefile +4 -4
- data/conf/mms2r_media.yml +18 -11
- data/conf/vzwpix.com.yml +2 -2
- data/init.rb +1 -0
- data/lib/mms2r.rb +10 -3
- data/lib/mms2r/media.rb +141 -87
- data/lib/mms2r/media/sprint.rb +2 -2
- data/lib/tmail_ext.rb +5 -0
- data/mms2r.gemspec +27 -13
- data/test/fixtures/iphone-image-01.mail +62 -0
- data/test/fixtures/vzwpix.com-image-01.mail +50 -0
- data/test/test_mms2r_media.rb +8 -4
- data/test/test_vzwpix_com.rb +31 -7
- metadata +63 -8
data/.gitignore
CHANGED
data/History.txt
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
### 2.3.0 / 2008-08-30 (Snakes 'n' Barrels Greatest Hits)
|
2
|
+
* 5 new features
|
3
|
+
* detect smartphone status/type based on model metadata from jpeg and tiff
|
4
|
+
exif data using exifr gem, access exif data with MMS2R::Media#exif
|
5
|
+
* make MMS2R Rails gem packaging friendly with an init.rb - Scott Taylor,
|
6
|
+
smtlaissezfaire
|
7
|
+
* delegate missing methods to mms2r's tmail object so that mms2r behaves as
|
8
|
+
if it were a tmail object - Sai Emrys, saizai
|
9
|
+
* default_media can return an attachment of application content type -
|
10
|
+
Brendan Lim, brendanlim
|
11
|
+
* MMS2R.parse(raw_mail) convenience class method that parses and returns an
|
12
|
+
mms2r from a mail file - saizai
|
13
|
+
|
14
|
+
* 4 minor enhancements
|
15
|
+
* make examples more 'mail' specific to enforce the fact that an mms is a
|
16
|
+
multipart email - saizai
|
17
|
+
* update for text in vzwpix.com default carrier message
|
18
|
+
* detecting smartphone (blackberries and iphones for now) is more versatile
|
19
|
+
from reading mail headers
|
20
|
+
* expanded filtering of carrier advertising text in mms from smartphones
|
21
|
+
|
1
22
|
### 2.2.0 / 2009-01-04 (Rikki Kixx - owner of a franchise of rehab centers)
|
2
23
|
|
3
24
|
* 3 new features
|
data/Manifest.txt
CHANGED
@@ -40,6 +40,7 @@ conf/waw.plspictures.com.yml
|
|
40
40
|
dev_tools/anonymizer.rb
|
41
41
|
dev_tools/debug_sprint_hpricot_parsing.rb
|
42
42
|
dev_tools/github.rb
|
43
|
+
init.rb
|
43
44
|
lib/mms2r.rb
|
44
45
|
lib/mms2r/media.rb
|
45
46
|
lib/mms2r/media/sprint.rb
|
@@ -74,6 +75,7 @@ test/fixtures/iconv-fr-text-01.mail
|
|
74
75
|
test/fixtures/indosat-image-01.mail
|
75
76
|
test/fixtures/indosat-image-02.mail
|
76
77
|
test/fixtures/info2go-image-01.mail
|
78
|
+
test/fixtures/iphone-image-01.mail
|
77
79
|
test/fixtures/luxgsm-image-01.mail
|
78
80
|
test/fixtures/maroctelecom-france-mms-01.mail
|
79
81
|
test/fixtures/mediamessaging_o2_co_uk-image-01.mail
|
@@ -129,6 +131,7 @@ test/fixtures/vodacom4me-co-za-02.mail
|
|
129
131
|
test/fixtures/vodacom4me-southafrica-mms-01.mail
|
130
132
|
test/fixtures/vodacom4me-southafrica-mms-04.mail
|
131
133
|
test/fixtures/vtext-text-01.mail
|
134
|
+
test/fixtures/vzwpix.com-image-01.mail
|
132
135
|
test/fixtures/waw.plspictures.com-image-01.mail
|
133
136
|
test/test_1nbox_net.rb
|
134
137
|
test/test_bell_canada.rb
|
data/README.txt
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
= mms2r
|
2
2
|
|
3
|
+
http://mms2r.rubyforge.org/
|
3
4
|
by Mike Mondragon
|
4
|
-
http://
|
5
|
-
http://rubyforge.org/tracker/?group_id=3065
|
5
|
+
http://rubyforge.org/tracker/?group_id=3065
|
6
6
|
http://github.com/monde/mms2r/tree/master
|
7
7
|
http://peepcode.com/products/mms2r-pdf
|
8
8
|
|
9
9
|
== DESCRIPTION
|
10
|
-
|
11
|
-
MMS2R is a library that decodes the parts of an MMS message to disk while
|
12
|
-
stripping out advertising injected by the mobile carriers. MMS messages are
|
10
|
+
|
11
|
+
MMS2R is a library that decodes the parts of an MMS message to disk while
|
12
|
+
stripping out advertising injected by the mobile carriers. MMS messages are
|
13
13
|
multipart email and the carriers often inject branding into these messages. Use
|
14
14
|
MMS2R if you want to get at the real user generated content from a MMS without
|
15
15
|
having to deal with the cruft from the carriers.
|
16
16
|
|
17
|
-
If MMS2R is not aware of a particular carrier no extra processing is done to the
|
17
|
+
If MMS2R is not aware of a particular carrier no extra processing is done to the
|
18
18
|
MMS other than decoding and consolidating its media.
|
19
19
|
|
20
|
-
Contact the author to add additional carriers to be processed by the library.
|
20
|
+
Contact the author to add additional carriers to be processed by the library.
|
21
21
|
Suggestions and patches appreciated and welcomed!
|
22
22
|
|
23
23
|
Corpus of carriers currently processed by MMS2R:
|
@@ -25,7 +25,7 @@ Corpus of carriers currently processed by MMS2R:
|
|
25
25
|
* 1nbox/Idea: 1nbox.net
|
26
26
|
* 3 Ireland: mms.3ireland.ie
|
27
27
|
* Alltel: mms.alltel.com
|
28
|
-
* AT&T/Cingular/Legacy: mms.att.net, txt.att.net, mmode.com, mms.mycingular.com,
|
28
|
+
* AT&T/Cingular/Legacy: mms.att.net, txt.att.net, mmode.com, mms.mycingular.com,
|
29
29
|
cingularme.com, mobile.mycingular.com pics.cingularme.com
|
30
30
|
* Bell Canada: txt.bell.ca
|
31
31
|
* Bell South / Suncom: bellsouth.net
|
@@ -50,7 +50,7 @@ Corpus of carriers currently processed by MMS2R:
|
|
50
50
|
* T-Mobile: tmomail.net, mmsreply.t-mobile.co.uk, tmo.blackberry.net
|
51
51
|
* TELUS Corporation (Canada): mms.telusmobility.com, msg.telus.com
|
52
52
|
* UAE MMS: mms.ae
|
53
|
-
* Unicel: unicel.com, info2go.com
|
53
|
+
* Unicel: unicel.com, info2go.com
|
54
54
|
(note: mobile number is tucked away in a text/plain part for unicel.com)
|
55
55
|
* Verizon: vzwpix.com, vtext.com
|
56
56
|
* Virgin Mobile: vmpix.com
|
@@ -59,8 +59,8 @@ Corpus of carriers currently processed by MMS2R:
|
|
59
59
|
|
60
60
|
== FEATURES
|
61
61
|
|
62
|
-
* #default_media and #default_text methods return a File that can be used in
|
63
|
-
attachment_fu
|
62
|
+
* #default_media and #default_text methods return a File that can be used in
|
63
|
+
attachment_fu
|
64
64
|
* #process supports blocks to for enumerating over the content of the MMS
|
65
65
|
* #process can be made lazy when :process => :lazy is passed to new
|
66
66
|
* logging is enabled when :logger => your_logger is passed to new
|
@@ -79,59 +79,75 @@ http://peepcode.com/products/mms2r-pdf
|
|
79
79
|
require 'tmail'
|
80
80
|
require 'fileutils'
|
81
81
|
|
82
|
-
mail =
|
83
|
-
|
82
|
+
mail = MMS2R.parse mail
|
83
|
+
# mail = MMS2R.parse File.read('some_saved_mail.file')
|
84
84
|
|
85
|
-
puts "
|
85
|
+
puts "mail has default carrier subject" if mail.subject.empty?
|
86
86
|
|
87
87
|
# access the sender's phone number
|
88
|
-
puts "
|
88
|
+
puts "mail was from phone #{mail.number}"
|
89
89
|
|
90
|
-
# most
|
90
|
+
# most mail are either image or video, default_media will return the largest
|
91
91
|
# (non-advertising) video or image found
|
92
|
-
file =
|
93
|
-
puts "
|
92
|
+
file = mail.default_media
|
93
|
+
puts "mail had a media: #{file.inspect}" unless file.nil?
|
94
94
|
|
95
95
|
# finds the largest (non-advertising) text found
|
96
|
-
file =
|
97
|
-
puts "
|
96
|
+
file = mail.default_text
|
97
|
+
puts "mail had some text: #{file.inspect}" unless file.nil?
|
98
98
|
|
99
|
-
#
|
99
|
+
# mail.media is a hash that is indexed by mime-type.
|
100
100
|
# The mime-type key returns an array of filepaths
|
101
|
-
# to media that were extract from the
|
101
|
+
# to media that were extract from the mail and
|
102
102
|
# are of that type
|
103
|
-
|
104
|
-
|
103
|
+
mail.media['image/jpeg'].each {|f| puts "#{f}"}
|
104
|
+
mail.media['text/plain'].each {|f| puts "#{f}"}
|
105
105
|
|
106
|
-
# print the text (assumes
|
107
|
-
text = IO.readlines(
|
106
|
+
# print the text (assumes mail had text)
|
107
|
+
text = IO.readlines(mail.media['text/plain'].first).join
|
108
108
|
puts text
|
109
109
|
|
110
|
-
# save the image (assumes
|
111
|
-
FileUtils.cp
|
110
|
+
# save the image (assumes mail had a jpeg)
|
111
|
+
FileUtils.cp mail.media['image/jpeg'].first, '/some/where/useful', :verbose => true
|
112
|
+
|
113
|
+
puts "does the mail have quicktime video? #{!mail.media['video/quicktime'].nil?}"
|
114
|
+
|
115
|
+
puts "plus run anything that TMail provides, e.g. #{mail.to.inspect}"
|
116
|
+
|
117
|
+
# check if the mail is from a mobile phone
|
118
|
+
puts "mail is from a mobile phone #{mail.is_mobile?}"
|
112
119
|
|
113
|
-
|
120
|
+
# inspect default media's exif data if exifr gem is installed and default
|
121
|
+
# media is a jpeg or tiff
|
122
|
+
puts "mail is from a mobile phone #{mail.is_mobile?}"
|
123
|
+
puts "mail's default media's exif data is:"
|
124
|
+
puts mms.exif.inspect
|
114
125
|
|
115
126
|
# Block support, process and receive all media types of video.
|
116
|
-
|
127
|
+
mail.process do |media_type, files|
|
117
128
|
# assumes a Clip model that is an AttachmentFu
|
118
129
|
Clip.create(:uploaded_data => files.first, :title => "From phone") if media_type =~ /video/
|
119
130
|
end
|
120
131
|
|
121
132
|
# Another AttachmentFu example, Picture model is an AttachmentFu
|
122
133
|
picture = Picture.new
|
123
|
-
picture.title =
|
124
|
-
picture.uploaded_data =
|
134
|
+
picture.title = mail.subject
|
135
|
+
picture.uploaded_data = mail.default_media
|
125
136
|
picture.save!
|
126
137
|
|
127
138
|
#remove all the media that was put to temporary disk
|
128
|
-
|
139
|
+
mail.purge
|
129
140
|
|
130
141
|
== REQUIREMENTS
|
131
142
|
|
132
143
|
* Hpricot
|
133
144
|
* TMail
|
134
145
|
|
146
|
+
== OPTIONAL
|
147
|
+
|
148
|
+
* exifr - install exifr for exif access on default jpeg or tiff media, and
|
149
|
+
smart phone detection
|
150
|
+
|
135
151
|
== INSTALL
|
136
152
|
|
137
153
|
conventional
|
@@ -146,13 +162,6 @@ github
|
|
146
162
|
git clone git://github.com/monde/mms2r.git
|
147
163
|
svn co svn://rubyforge.org/var/svn/mms2r/trunk mms2r
|
148
164
|
|
149
|
-
== CONTRIBUTE
|
150
|
-
|
151
|
-
If you contribute a patch that is accepted then you'll get developer rights
|
152
|
-
for the project on RubyForge. Please ensure your work includes 100% test
|
153
|
-
converage. The library is ZenTest autotest discovery enabled so running
|
154
|
-
autotest in the root of the project is very helpful during development.
|
155
|
-
|
156
165
|
== AUTHORS
|
157
166
|
|
158
167
|
Copyright (c) 2007-2008 by Mike Mondragon (blog[http://blog.mondragon.cc/])
|
@@ -174,6 +183,8 @@ MMS2R's Flickr page[http://www.flickr.com/photos/8627919@N05/]
|
|
174
183
|
* Matt Conway
|
175
184
|
* Kai Kai
|
176
185
|
* Michael DelGaudio
|
186
|
+
* Sai Emrys (blog[http://saizai.com])
|
187
|
+
* Brendan Lim (github profile[http://github.com/brendanlim])
|
177
188
|
|
178
189
|
== LICENSE
|
179
190
|
|
data/Rakefile
CHANGED
@@ -16,11 +16,11 @@ Hoe.new('mms2r', MMS2R::Media::VERSION) do |p|
|
|
16
16
|
p.author = 'Mike Mondragon'
|
17
17
|
p.email = 'mikemondragon@gmail.com'
|
18
18
|
p.summary = 'Extract user media from MMS (and not carrier cruft)'
|
19
|
-
p.description = p.paragraphs_of('README.txt', 2..
|
19
|
+
p.description = p.paragraphs_of('README.txt', 2..7).join("\n\n")
|
20
20
|
p.url = p.paragraphs_of('README.txt', 1).first.strip
|
21
|
-
p.changes = p.paragraphs_of('History.txt', 0..
|
22
|
-
p.extra_deps << ['hpricot'
|
23
|
-
p.extra_deps << ['tmail'
|
21
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
22
|
+
p.extra_deps << ['hpricot']
|
23
|
+
p.extra_deps << ['tmail']
|
24
24
|
p.clean_globs << 'coverage'
|
25
25
|
end
|
26
26
|
|
data/conf/mms2r_media.yml
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
---
|
2
2
|
ignore:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
text/plain:
|
4
|
+
- /^\(no subject\)$/i
|
5
|
+
- /\ASent via BlackBerry (from|by) .*$/im
|
6
|
+
- /\ASent from my Verizon Wireless BlackBerry$/im
|
7
|
+
- /\ASent from (my|your) iPhone.?$/im
|
8
|
+
- /\ASent on the Sprint.* Now Network.*$/im
|
9
|
+
multipart/mixed:
|
10
|
+
- "/^Attachment: /i"
|
7
11
|
transform:
|
8
12
|
text/plain:
|
9
13
|
- - /\A(.*?)Sent via BlackBerry (from|by) .*$/im
|
@@ -14,11 +18,14 @@ transform:
|
|
14
18
|
- "\1"
|
15
19
|
- - /\A(.*?)\s+image\/jpeg$/im
|
16
20
|
- "\1"
|
21
|
+
- - /\A(.*?)Sent on the Sprint.* Now Network.*$/im
|
22
|
+
- "\1"
|
17
23
|
device_types:
|
18
|
-
headers:
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
-
|
24
|
+
headers:
|
25
|
+
x-mailer:
|
26
|
+
:iphone: !ruby/regexp /iPhone Mail/i
|
27
|
+
:blackberry: !ruby/regexp /Palm webOS/i
|
28
|
+
mime-version:
|
29
|
+
:iphone: !ruby/regexp /iPhone Mail/i
|
30
|
+
x-rim-org-msg-ref-id:
|
31
|
+
:blackberry: !ruby/regexp /.+/
|
data/conf/vzwpix.com.yml
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
---
|
2
2
|
ignore:
|
3
3
|
text/plain:
|
4
|
-
- /\AThis message was sent using
|
4
|
+
- /\AThis message was sent using .* from Verizon Wireless!.*/m
|
5
5
|
transform:
|
6
6
|
text/plain:
|
7
|
-
- - /\A(.+?)\s+This message was sent using
|
7
|
+
- - /\A(.+?)\s+This message was sent using .* from Verizon Wireless!.*/m
|
8
8
|
- "\1"
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/lib/mms2r"
|
data/lib/mms2r.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2007
|
2
|
+
# Copyright (c) 2007-2010 by Mike Mondragon (mikemondragon@gmail.com)
|
3
3
|
#
|
4
4
|
# Please see the LICENSE file for licensing information.
|
5
5
|
#++
|
@@ -39,14 +39,21 @@ module MMS2R
|
|
39
39
|
##
|
40
40
|
# MMS2R library version
|
41
41
|
|
42
|
-
VERSION = '2.
|
42
|
+
VERSION = '2.3.0'
|
43
43
|
|
44
44
|
end
|
45
45
|
|
46
|
+
# Simple convenience function to make it a one-liner:
|
47
|
+
# MMS2R.parse raw_mail or MMS2R.parse File.load(raw_mail)
|
48
|
+
# Combined w/ the method_missing delegation, this should behave as an enhanced TMail object, more or less.
|
49
|
+
def self.parse raw_mail
|
50
|
+
mail = TMail::Mail.parse raw_mail
|
51
|
+
MMS2R::Media.new(mail)
|
52
|
+
end
|
53
|
+
|
46
54
|
end
|
47
55
|
|
48
56
|
require 'rubygems'
|
49
|
-
gem 'tmail', '>= 1.2.3'
|
50
57
|
require 'tmail/mail'
|
51
58
|
require 'fileutils'
|
52
59
|
require 'pathname'
|
data/lib/mms2r/media.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2007
|
2
|
+
# Copyright (c) 2007-2010 by Mike Mondragon (mikemondragon@gmail.com)
|
3
3
|
#
|
4
|
-
# Please see the LICENSE file for licensing information
|
4
|
+
# Please see the LICENSE file for licensing information.
|
5
5
|
#++
|
6
6
|
|
7
7
|
##
|
8
8
|
# = Synopsis
|
9
9
|
#
|
10
|
-
# MMS2R is a library to collect media files from MMS messages. MMS messages
|
11
|
-
# are multipart emails and mobile carriers often inject branding into these
|
12
|
-
# messages. MMS2R strips the advertising from an MMS leaving the actual user
|
10
|
+
# MMS2R is a library to collect media files from MMS messages. MMS messages
|
11
|
+
# are multipart emails and mobile carriers often inject branding into these
|
12
|
+
# messages. MMS2R strips the advertising from an MMS leaving the actual user
|
13
13
|
# generated media.
|
14
14
|
#
|
15
|
-
# The Tracker for MMS2R is located at
|
15
|
+
# The Tracker for MMS2R is located at
|
16
16
|
# http://rubyforge.org/tracker/?group_id=3065
|
17
17
|
# Please submit bugs and feature requests using the Tracker.
|
18
18
|
#
|
19
|
-
# If MMS from a carrier not known by MMS2R is encountered please submit a
|
19
|
+
# If MMS from a carrier not known by MMS2R is encountered please submit a
|
20
20
|
# sample to the author for inclusion in this project.
|
21
21
|
#
|
22
22
|
# == Stand Alone Example
|
@@ -48,31 +48,31 @@
|
|
48
48
|
# == Built In Configuration
|
49
49
|
#
|
50
50
|
# A custom configuration can be created for processing the MMS from carriers
|
51
|
-
# that are not currently known by MMS2R. In the conf/ directory create a
|
52
|
-
# YAML file named by combining the domain name of the MMS sender plus a .yml
|
53
|
-
# extension. For instance the configuration of senders from AT&T's cellular
|
54
|
-
# service with a Sender pattern of 2065551212@mms.att.net have a configuration
|
51
|
+
# that are not currently known by MMS2R. In the conf/ directory create a
|
52
|
+
# YAML file named by combining the domain name of the MMS sender plus a .yml
|
53
|
+
# extension. For instance the configuration of senders from AT&T's cellular
|
54
|
+
# service with a Sender pattern of 2065551212@mms.att.net have a configuration
|
55
55
|
# named conf/mms.att.net.yml
|
56
56
|
#
|
57
57
|
# The YAML configuration contains a Hash with instructions for determining what
|
58
58
|
# is content generated by the user and what is content inserted by the carrier.
|
59
59
|
#
|
60
|
-
# The root hash itself has two hashes under the keys 'ignore' and 'transform',
|
60
|
+
# The root hash itself has two hashes under the keys 'ignore' and 'transform',
|
61
61
|
# and an array under the 'number' key.
|
62
62
|
# Each hash is itself keyed by mime-type. The value pointed to by the mime-type
|
63
|
-
# key is an array. The ignore arrays are first evaluated as a regular expressions
|
63
|
+
# key is an array. The ignore arrays are first evaluated as a regular expressions
|
64
64
|
# and if the evaluation fails as a equality for a string filename. Ignores
|
65
65
|
# work by filename for the multi-part of the MMS that is being inspected. The
|
66
|
-
# array pointed to by the 'number' key represents an alternate mail header where
|
67
|
-
# the sender's number can be found with a regular expression and replacement
|
66
|
+
# array pointed to by the 'number' key represents an alternate mail header where
|
67
|
+
# the sender's number can be found with a regular expression and replacement
|
68
68
|
# value for a gsub eval.
|
69
69
|
#
|
70
70
|
# The transform arrays are themselves an array of two element arrays. The elements
|
71
71
|
# are parameters for gsub and will be evaluated from within the ruby code.
|
72
72
|
#
|
73
|
-
# Ignore instructions are honored first then transform instructions. In the sample,
|
74
|
-
# masthead.jpg is ignored as a regular expression, and spacer.gif is ignored as a
|
75
|
-
# filename comparison. The transform has a match and a replacement, see the gsub
|
73
|
+
# Ignore instructions are honored first then transform instructions. In the sample,
|
74
|
+
# masthead.jpg is ignored as a regular expression, and spacer.gif is ignored as a
|
75
|
+
# filename comparison. The transform has a match and a replacement, see the gsub
|
76
76
|
# documentation for more information about match and replace.
|
77
77
|
#
|
78
78
|
# --
|
@@ -92,9 +92,9 @@
|
|
92
92
|
# - /^([^\s]+)\s.*/
|
93
93
|
# - "\1"
|
94
94
|
#
|
95
|
-
# Carriers often provide their services under many different domain names.
|
96
|
-
# The conf/aliases.yml is a YAML file with a hash that maps alternative or
|
97
|
-
# legacy carrier names to the most common name of their service. For example
|
95
|
+
# Carriers often provide their services under many different domain names.
|
96
|
+
# The conf/aliases.yml is a YAML file with a hash that maps alternative or
|
97
|
+
# legacy carrier names to the most common name of their service. For example
|
98
98
|
# in terms of MMS2R txt.att.net is an alias for mms.att.net. Therefore when
|
99
99
|
# an MMS with a Sender of txt.att.net is processed MMS2R will use the
|
100
100
|
# mms.att.net configuration to process the message.
|
@@ -114,20 +114,26 @@ module MMS2R
|
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
117
|
+
# Pass off everything we don't do to the TMail object
|
118
|
+
# TODO: refactor to explicit addition a la http://blog.jayfields.com/2008/02/ruby-replace-methodmissing-with-dynamic.html
|
119
|
+
def method_missing method, *args, &block
|
120
|
+
mail.send method, *args, &block
|
121
|
+
end
|
122
|
+
|
117
123
|
##
|
118
124
|
# TMail object that the media files were derived from.
|
119
125
|
|
120
126
|
attr_reader :mail
|
121
127
|
|
122
128
|
##
|
123
|
-
# media returns the hash of media. The media hash is keyed by mime-type
|
124
|
-
# such as 'text/plain' and the value mapped to the key is an array of
|
129
|
+
# media returns the hash of media. The media hash is keyed by mime-type
|
130
|
+
# such as 'text/plain' and the value mapped to the key is an array of
|
125
131
|
# media that are of that type.
|
126
132
|
|
127
133
|
attr_reader :media
|
128
134
|
|
129
135
|
##
|
130
|
-
# Carrier is the domain name of the carrier. If the carrier is not known
|
136
|
+
# Carrier is the domain name of the carrier. If the carrier is not known
|
131
137
|
# the carrier will be set to 'mms2r.media'
|
132
138
|
|
133
139
|
attr_reader :carrier
|
@@ -143,14 +149,14 @@ module MMS2R
|
|
143
149
|
MULTIPARTS_TO_SPLIT = [ 'multipart/related', 'multipart/alternative', 'multipart/mixed', 'multipart/appledouble' ]
|
144
150
|
|
145
151
|
##
|
146
|
-
# Factory method that creates MMS2R::Media products based on the domain
|
147
|
-
# name of the carrier from which the MMS originated. mail is a TMail
|
152
|
+
# Factory method that creates MMS2R::Media products based on the domain
|
153
|
+
# name of the carrier from which the MMS originated. mail is a TMail
|
148
154
|
# object.
|
149
155
|
|
150
156
|
def self.create(mail)
|
151
157
|
d = lambda{ ['mms2r.media', MMS2R::Media] } #sets a default to detect
|
152
158
|
from_domain = self.domain(mail)
|
153
|
-
processor = MMS2R::CARRIERS.detect(d) do |domain, klass|
|
159
|
+
processor = MMS2R::CARRIERS.detect(d) do |domain, klass|
|
154
160
|
return klass, domain if from_domain == domain
|
155
161
|
end
|
156
162
|
[MMS2R::Media, from_domain]
|
@@ -158,8 +164,8 @@ module MMS2R
|
|
158
164
|
|
159
165
|
##
|
160
166
|
# Determine if return-path or from is going to be used to desiginate the
|
161
|
-
# origin carrier. If the domain in the From header is listed in
|
162
|
-
# conf/from.yaml then that is the carrier domain. Else if there is a
|
167
|
+
# origin carrier. If the domain in the From header is listed in
|
168
|
+
# conf/from.yaml then that is the carrier domain. Else if there is a
|
163
169
|
# Return-Path header its address's domain is the carrier doamin, else
|
164
170
|
# use From header's address domain.
|
165
171
|
|
@@ -211,7 +217,7 @@ module MMS2R
|
|
211
217
|
log("#{self.class} created", :info)
|
212
218
|
@carrier = opts[:domain]
|
213
219
|
@dir_count = 0
|
214
|
-
@media_dir = File.join(self.tmp_dir(),
|
220
|
+
@media_dir = File.join(self.tmp_dir(),
|
215
221
|
self.safe_message_id(@mail.message_id))
|
216
222
|
@media = {}
|
217
223
|
@was_processed = false
|
@@ -220,7 +226,7 @@ module MMS2R
|
|
220
226
|
@body = nil
|
221
227
|
@default_media = nil
|
222
228
|
@default_text = nil
|
223
|
-
|
229
|
+
|
224
230
|
f = File.join(self.conf_dir(), "aliases.yml")
|
225
231
|
@aliases = YAML::load_file(f) rescue {}
|
226
232
|
|
@@ -234,9 +240,9 @@ module MMS2R
|
|
234
240
|
end
|
235
241
|
|
236
242
|
##
|
237
|
-
# Get the phone number associated with this MMS if it exists. The value
|
238
|
-
# returned is simplistic, it is just the user name of the from address
|
239
|
-
# before the @ symbol. Validation of the number is left to you. Most
|
243
|
+
# Get the phone number associated with this MMS if it exists. The value
|
244
|
+
# returned is simplistic, it is just the user name of the from address
|
245
|
+
# before the @ symbol. Validation of the number is left to you. Most
|
240
246
|
# carriers are using the real phone number as the username.
|
241
247
|
|
242
248
|
def number
|
@@ -268,8 +274,8 @@ module MMS2R
|
|
268
274
|
@subject
|
269
275
|
end
|
270
276
|
|
271
|
-
# Convenience method that returns a string including all the text of the
|
272
|
-
# first text/plain file found. Returns empty string if no body text
|
277
|
+
# Convenience method that returns a string including all the text of the
|
278
|
+
# first text/plain file found. Returns empty string if no body text
|
273
279
|
# is found.
|
274
280
|
|
275
281
|
def body
|
@@ -279,22 +285,22 @@ module MMS2R
|
|
279
285
|
end
|
280
286
|
|
281
287
|
# Returns a File with the most likely candidate for the user-submitted
|
282
|
-
# media. Given that most MMS messages only have one file attached, this
|
283
|
-
# method will try to return that file. Singleton methods are added to
|
284
|
-
# the File object so it can be used in place of a CGI upload (local_path,
|
288
|
+
# media. Given that most MMS messages only have one file attached, this
|
289
|
+
# method will try to return that file. Singleton methods are added to
|
290
|
+
# the File object so it can be used in place of a CGI upload (local_path,
|
285
291
|
# original_filename, size, and content_type) such as in conjunction with
|
286
292
|
# AttachementFu. The largest file found in terms of bytes is returned.
|
287
293
|
#
|
288
294
|
# Returns nil if there are not any video or image Files found.
|
289
295
|
|
290
296
|
def default_media
|
291
|
-
@default_media ||= attachment(['video', 'image', 'text'])
|
297
|
+
@default_media ||= attachment(['video', 'image', 'application', 'text'])
|
292
298
|
end
|
293
299
|
|
294
300
|
# Returns a File with the most likely candidate that is text, or nil
|
295
|
-
# otherwise. It also adds singleton methods to the File object so it can be
|
296
|
-
# used in place of a CGI upload (local_path, original_filename, size, and
|
297
|
-
# content_type) such as in conjunction with AttachmentFu. The largest file
|
301
|
+
# otherwise. It also adds singleton methods to the File object so it can be
|
302
|
+
# used in place of a CGI upload (local_path, original_filename, size, and
|
303
|
+
# content_type) such as in conjunction with AttachmentFu. The largest file
|
298
304
|
# found in terms of bytes is returned.
|
299
305
|
#
|
300
306
|
# Returns nil if there are not any text Files found
|
@@ -305,9 +311,9 @@ module MMS2R
|
|
305
311
|
|
306
312
|
##
|
307
313
|
# process is a template method and collects all the media in a MMS.
|
308
|
-
# Override helper methods to this template to clean out advertising and/or
|
309
|
-
# ignore media that are advertising. This method should not be overridden
|
310
|
-
# unless there is an extreme special case in processing the media of a MMS
|
314
|
+
# Override helper methods to this template to clean out advertising and/or
|
315
|
+
# ignore media that are advertising. This method should not be overridden
|
316
|
+
# unless there is an extreme special case in processing the media of a MMS
|
311
317
|
# (like Sprint)
|
312
318
|
#
|
313
319
|
# Helper methods for the process template:
|
@@ -315,7 +321,7 @@ module MMS2R
|
|
315
321
|
# * process_media -- retrieves media to temporary file, returns path to file.
|
316
322
|
# * transform_text -- called by process_media, strips out advertising.
|
317
323
|
# * temp_file -- creates a temporary filepath based on information from the part.
|
318
|
-
#
|
324
|
+
#
|
319
325
|
# Block support:
|
320
326
|
# Call process() with a block to automatically iterate through media.
|
321
327
|
# For example, to process and receive only media of video type:
|
@@ -329,11 +335,11 @@ module MMS2R
|
|
329
335
|
def process() # :yields: media_type, file
|
330
336
|
unless @was_processed
|
331
337
|
log("#{self.class} processing", :info)
|
332
|
-
|
338
|
+
|
333
339
|
parts = mail.multipart? ? mail.parts : [mail]
|
334
|
-
|
335
|
-
# Double check for multipart/related, if it exists replace it with its
|
336
|
-
# children parts. Do this twice as multipart/alternative can have
|
340
|
+
|
341
|
+
# Double check for multipart/related, if it exists replace it with its
|
342
|
+
# children parts. Do this twice as multipart/alternative can have
|
337
343
|
# children and we want to fold everything down
|
338
344
|
for i in 1..2
|
339
345
|
flat = []
|
@@ -343,10 +349,10 @@ module MMS2R
|
|
343
349
|
else
|
344
350
|
flat << p
|
345
351
|
end
|
346
|
-
end
|
352
|
+
end
|
347
353
|
parts = flat.dup
|
348
|
-
end
|
349
|
-
|
354
|
+
end
|
355
|
+
|
350
356
|
# get to work
|
351
357
|
parts.each do |p|
|
352
358
|
t = p.part_type?
|
@@ -369,8 +375,8 @@ module MMS2R
|
|
369
375
|
end
|
370
376
|
|
371
377
|
##
|
372
|
-
# Helper for process template method to determine if media contained in a
|
373
|
-
# part should be ignored. Producers should override this method to return
|
378
|
+
# Helper for process template method to determine if media contained in a
|
379
|
+
# part should be ignored. Producers should override this method to return
|
374
380
|
# true for media such as images that are advertising, carrier logos, etc.
|
375
381
|
# See the ignore section in the discussion of the built-in configuration.
|
376
382
|
|
@@ -379,18 +385,18 @@ module MMS2R
|
|
379
385
|
ignore = ignores.detect{|test| filename?(part) == test}
|
380
386
|
ignore ||= ignores.detect{|test| filename?(part) =~ eval(test) if test.index('/') == 0 }
|
381
387
|
ignore ||= ignores.detect{|test| part.body.strip =~ eval(test) if test.index('/') == 0 }
|
382
|
-
ignore ||= (part.body.strip.size == 0 ? true : nil)
|
388
|
+
ignore ||= (part.body.strip.size == 0 ? true : nil)
|
383
389
|
ignore.nil? ? false : true
|
384
390
|
end
|
385
391
|
|
386
392
|
##
|
387
|
-
# Helper for process template method to decode the part based on its type
|
388
|
-
# and write its content to a temporary file. Returns path to temporary
|
389
|
-
# file that holds the content. Parts with a main type of text will have
|
393
|
+
# Helper for process template method to decode the part based on its type
|
394
|
+
# and write its content to a temporary file. Returns path to temporary
|
395
|
+
# file that holds the content. Parts with a main type of text will have
|
390
396
|
# their contents transformed with a call to transform_text
|
391
397
|
#
|
392
|
-
# Producers should only override this method if the parts of the MMS need
|
393
|
-
# special treatment besides what is expected for a normal mime part (like
|
398
|
+
# Producers should only override this method if the parts of the MMS need
|
399
|
+
# special treatment besides what is expected for a normal mime part (like
|
394
400
|
# Sprint).
|
395
401
|
#
|
396
402
|
# Returns a tuple of content type, file path
|
@@ -399,7 +405,7 @@ module MMS2R
|
|
399
405
|
# TMail body auto-magically decodes quoted
|
400
406
|
# printable for text/html type.
|
401
407
|
file = temp_file(part)
|
402
|
-
if part.main_type('text') == 'text' ||
|
408
|
+
if part.main_type('text') == 'text' ||
|
403
409
|
part.content_type == 'application/smil'
|
404
410
|
type, content = transform_text_part(part)
|
405
411
|
mode = 'w'
|
@@ -421,11 +427,11 @@ module MMS2R
|
|
421
427
|
|
422
428
|
##
|
423
429
|
# Helper for process_media template method to transform text.
|
424
|
-
# See the transform section in the discussion of the built-in
|
430
|
+
# See the transform section in the discussion of the built-in
|
425
431
|
# configuration.
|
426
432
|
|
427
433
|
def transform_text(type, text, original_nencoding = 'ISO-8859-1')
|
428
|
-
return type, text unless transforms = config['transform'][type]
|
434
|
+
return type, text unless transforms = config['transform'][type]
|
429
435
|
|
430
436
|
#convert to UTF-8
|
431
437
|
begin
|
@@ -441,7 +447,7 @@ module MMS2R
|
|
441
447
|
r = transform.last
|
442
448
|
utf_t = utf_t.gsub(eval(p), r) rescue utf_t
|
443
449
|
end
|
444
|
-
|
450
|
+
|
445
451
|
return type, utf_t
|
446
452
|
end
|
447
453
|
|
@@ -455,12 +461,12 @@ module MMS2R
|
|
455
461
|
end
|
456
462
|
|
457
463
|
##
|
458
|
-
# Helper for process template method to name a temporary filepath based on
|
459
|
-
# information in the part. This version attempts to honor the name of the
|
460
|
-
# media as labeled in the part header and creates a unique temporary
|
464
|
+
# Helper for process template method to name a temporary filepath based on
|
465
|
+
# information in the part. This version attempts to honor the name of the
|
466
|
+
# media as labeled in the part header and creates a unique temporary
|
461
467
|
# directory for writing the file so filename collision does not occur.
|
462
|
-
# Consumers of this method expect the directory structure to the file
|
463
|
-
# exists, if the method is overridden it is mandatory that this behavior is
|
468
|
+
# Consumers of this method expect the directory structure to the file
|
469
|
+
# exists, if the method is overridden it is mandatory that this behavior is
|
464
470
|
# retained.
|
465
471
|
|
466
472
|
def temp_file(part)
|
@@ -469,7 +475,7 @@ module MMS2R
|
|
469
475
|
end
|
470
476
|
|
471
477
|
##
|
472
|
-
# Purges the unique MMS2R::Media.media_dir directory created
|
478
|
+
# Purges the unique MMS2R::Media.media_dir directory created
|
473
479
|
# for this producer and all of the media that it contains.
|
474
480
|
|
475
481
|
def purge()
|
@@ -486,7 +492,7 @@ module MMS2R
|
|
486
492
|
end
|
487
493
|
|
488
494
|
##
|
489
|
-
# Helper to temp_file to create a unique temporary directory that is a
|
495
|
+
# Helper to temp_file to create a unique temporary directory that is a
|
490
496
|
# child of tmp_dir This version is based on the message_id of the mail.
|
491
497
|
|
492
498
|
def msg_tmp_dir()
|
@@ -519,7 +525,7 @@ module MMS2R
|
|
519
525
|
base = File.basename(name, ext)
|
520
526
|
name = "#{base[0, 255 - ext.size]}#{ext}"
|
521
527
|
end
|
522
|
-
|
528
|
+
|
523
529
|
name
|
524
530
|
end
|
525
531
|
|
@@ -528,28 +534,76 @@ module MMS2R
|
|
528
534
|
end
|
529
535
|
|
530
536
|
##
|
531
|
-
# Best guess of the mobile device type. Simple heuristics thus far for
|
532
|
-
# :iphone :blackberry :handset :unknown . Could be expanded for exif
|
537
|
+
# Best guess of the mobile device type. Simple heuristics thus far for
|
538
|
+
# :iphone :blackberry :handset :unknown . Could be expanded for exif
|
533
539
|
# probing or shifting mail header schemes
|
534
540
|
|
535
541
|
def device_type?
|
542
|
+
begin
|
543
|
+
# rely on native exif first with exifr gem if its loaded
|
544
|
+
require 'exifr'
|
545
|
+
file = attachment(['image'])
|
546
|
+
if file
|
547
|
+
original = file.original_filename
|
548
|
+
@exif = case original
|
549
|
+
when /\.jpg$/i
|
550
|
+
EXIFR::JPEG.new(file)
|
551
|
+
when /\.jepg$/i
|
552
|
+
EXIFR::JPEG.new(file)
|
553
|
+
when /\.tif$/i
|
554
|
+
EXIFR::TIFF.new(file)
|
555
|
+
when /\.tiff$/i
|
556
|
+
EXIFR::TIFF.new(file)
|
557
|
+
end
|
558
|
+
if @exif
|
559
|
+
# TODO do something about the assortment of camera models that have
|
560
|
+
# been seen:
|
561
|
+
# 1.3 Megapixel, 2.0 Megapixel, BlackBerry, CU920, G'z One TYPE-S,
|
562
|
+
# Hermes, iPhone, LG8700, LSI_S5K4AAFA, Micron MT9M113 1.3MP YUV,
|
563
|
+
# Motorola Phone, Omni_vision-9650, Pre,
|
564
|
+
# Seoul Electronics & Telecom SIM120B 1.3M, SGH-T729, SGH-T819,
|
565
|
+
# SPH-M540, SPH-M800, SYSTEMLSI S5K4BAFB 2.0 MP, VX-9700
|
566
|
+
case @exif.model
|
567
|
+
when/iPhone/i
|
568
|
+
return :iphone
|
569
|
+
when/BlackBerry/i
|
570
|
+
return :blackberry
|
571
|
+
end
|
572
|
+
end
|
573
|
+
end
|
574
|
+
rescue LoadError => err
|
575
|
+
end
|
576
|
+
|
536
577
|
headers = config['device_types']['headers'] rescue {}
|
537
578
|
headers.keys.each do |header|
|
538
579
|
if mail.header[header.downcase]
|
539
|
-
|
540
|
-
|
580
|
+
# headers[header] refers to a hash of smart phone types with regex values
|
581
|
+
# that if they match the header signals the type should be returned
|
582
|
+
headers[header].each do |type, regex|
|
583
|
+
# HACK to get at the full value of the header before TMail parses according to spec
|
584
|
+
# see @body in and ensure_parsed in lib/tmail/header.rb
|
585
|
+
return type if mail.header[header.downcase].instance_variable_get(:@body) =~ regex
|
586
|
+
end
|
541
587
|
end
|
542
588
|
end
|
543
589
|
|
544
590
|
return :handset if File.exist?(File.join(self.conf_dir,
|
545
591
|
"#{self.aliases[self.carrier] || self.carrier}.yml"))
|
546
|
-
|
592
|
+
|
547
593
|
:unknown
|
548
594
|
end
|
549
595
|
|
596
|
+
##
|
597
|
+
# exif object on default image from exifr gem
|
598
|
+
|
599
|
+
def exif
|
600
|
+
device_type? unless @exif
|
601
|
+
@exif
|
602
|
+
end
|
603
|
+
|
550
604
|
##
|
551
605
|
# The source of the MMS was some sort of mobile or smart phone
|
552
|
-
|
606
|
+
|
553
607
|
def is_mobile?
|
554
608
|
self.device_type? != :unknown
|
555
609
|
end
|
@@ -596,7 +650,7 @@ module MMS2R
|
|
596
650
|
if MMS2R::EXT[content_type]
|
597
651
|
MMS2R::EXT[content_type]
|
598
652
|
elsif content_type
|
599
|
-
content_type.split('/').last
|
653
|
+
content_type.split('/').last
|
600
654
|
end
|
601
655
|
end
|
602
656
|
|
@@ -633,7 +687,7 @@ module MMS2R
|
|
633
687
|
|
634
688
|
##
|
635
689
|
# convenience accessor for self.class.conf_dir
|
636
|
-
|
690
|
+
|
637
691
|
def conf_dir
|
638
692
|
self.class.conf_dir
|
639
693
|
end
|
@@ -654,14 +708,14 @@ module MMS2R
|
|
654
708
|
|
655
709
|
##
|
656
710
|
# convenience accessor for self.class.safe_message_id
|
657
|
-
|
711
|
+
|
658
712
|
def safe_message_id(message_id)
|
659
713
|
self.class.safe_message_id(message_id)
|
660
714
|
end
|
661
715
|
|
662
716
|
##
|
663
717
|
# convenience accessor for self.class.initialize_confg
|
664
|
-
|
718
|
+
|
665
719
|
def initialize_config(config)
|
666
720
|
self.class.initialize_config(config)
|
667
721
|
end
|
@@ -686,13 +740,13 @@ module MMS2R
|
|
686
740
|
|
687
741
|
##
|
688
742
|
# used by #default_media and #text to return the biggest attachment type
|
689
|
-
# listed in the types array
|
743
|
+
# listed in the types array
|
690
744
|
|
691
745
|
def attachment(types)
|
692
746
|
|
693
747
|
# get all the files that are of the major types passed in
|
694
748
|
files = []
|
695
|
-
|
749
|
+
|
696
750
|
types.each do |type|
|
697
751
|
media.keys.find_all{|k| type.include?("/") ? k == type : k.index(type) == 0 }.each do |key|
|
698
752
|
files += media[key]
|
@@ -710,7 +764,7 @@ module MMS2R
|
|
710
764
|
if File.size(f) > size
|
711
765
|
size = File.size(f)
|
712
766
|
file = File.new(f)
|
713
|
-
mime_type = media.detect{|type,files| files.detect{|fl| fl == f}}[0]
|
767
|
+
mime_type = media.detect{|type,files| files.detect{|fl| fl == f}}[0]
|
714
768
|
end
|
715
769
|
end
|
716
770
|
|