flyerhzm-rfetion 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +26 -0
- data/Rakefile +11 -0
- data/VERSION +1 -0
- data/lib/rfetion/fetion.rb +216 -0
- data/lib/rfetion.rb +8 -0
- metadata +58 -0
data/README.textile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
h1. rfetion
|
2
|
+
|
3
|
+
rfetion is a ruby gem for China Mobile fetion service that you can send SMS free.
|
4
|
+
|
5
|
+
**************************************************************************
|
6
|
+
|
7
|
+
h2. Install
|
8
|
+
|
9
|
+
<pre><code>
|
10
|
+
gem sources -a http://gems.github.com
|
11
|
+
gem install flyerhzm-rfetion
|
12
|
+
</code></pre>
|
13
|
+
|
14
|
+
**************************************************************************
|
15
|
+
|
16
|
+
h2. Usage
|
17
|
+
|
18
|
+
send sms to yourself
|
19
|
+
<pre><code>
|
20
|
+
Fetion.send_sms_to_self(mobile_no, password, content)
|
21
|
+
</code></pre>
|
22
|
+
|
23
|
+
send sms to friends
|
24
|
+
<pre><code>
|
25
|
+
Fetion.send_sms_to_friends(mobile_no, password, friend_mobile_no or array of friends_mobile_no, content)
|
26
|
+
</code></pre>
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'jeweler'
|
2
|
+
|
3
|
+
Jeweler::Tasks.new do |gemspec|
|
4
|
+
gemspec.name = 'rfetion'
|
5
|
+
gemspec.summary = 'rfetion is a ruby gem for China Mobile fetion service that you can send SMS free.'
|
6
|
+
gemspec.description = 'rfetion is a ruby gem for China Mobile fetion service that you can send SMS free.'
|
7
|
+
gemspec.email = 'flyerhzm@gmail.com'
|
8
|
+
gemspec.homepage = ''
|
9
|
+
gemspec.authors = ['Richard Huang']
|
10
|
+
gemspec.files.exclude '.gitignore'
|
11
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,216 @@
|
|
1
|
+
class FetionException < Exception
|
2
|
+
end
|
3
|
+
|
4
|
+
class Fetion
|
5
|
+
attr_accessor :mobile_no, :password
|
6
|
+
attr_reader :uri, :contacts
|
7
|
+
|
8
|
+
FETION_URL = 'http://221.130.44.194/ht/sd.aspx'
|
9
|
+
FETION_LOGIN_URL = 'https://nav.fetion.com.cn/ssiportal/SSIAppSignIn.aspx'
|
10
|
+
FETION_CONFIG_URL = 'http://nav.fetion.com.cn/nav/getsystemconfig.aspx'
|
11
|
+
FETION_SIPP = 'SIPP'
|
12
|
+
GUID = UUID.new.generate
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@next_call = 0
|
16
|
+
@seq = 0
|
17
|
+
@buddies = []
|
18
|
+
@contacts = []
|
19
|
+
@logger = Logger.new(STDOUT)
|
20
|
+
@logger.level = Logger::INFO
|
21
|
+
end
|
22
|
+
|
23
|
+
def logger_level=(level)
|
24
|
+
@logger.level = level
|
25
|
+
end
|
26
|
+
|
27
|
+
def Fetion.send_sms_to_self(mobile_no, password, content)
|
28
|
+
fetion = Fetion.new
|
29
|
+
fetion.mobile_no = mobile_no
|
30
|
+
fetion.password = password
|
31
|
+
fetion.login
|
32
|
+
fetion.register
|
33
|
+
fetion.send_sms(fetion.uri, content)
|
34
|
+
end
|
35
|
+
|
36
|
+
def Fetion.send_sms_to_friends(mobile_no, password, friend_mobiles, content)
|
37
|
+
friend_mobiles = Array(friend_mobiles)
|
38
|
+
fetion = Fetion.new
|
39
|
+
fetion.mobile_no = mobile_no
|
40
|
+
fetion.password = password
|
41
|
+
fetion.login
|
42
|
+
fetion.register
|
43
|
+
fetion.get_buddy_list
|
44
|
+
fetion.get_contacts_info
|
45
|
+
fetion.contacts.each do |contact|
|
46
|
+
if friend_mobiles.include? contact[:mobile_no].to_i
|
47
|
+
fetion.send_sms(contact[:sip], content)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def login
|
53
|
+
@logger.info "fetion login"
|
54
|
+
uri = URI.parse(FETION_LOGIN_URL + "?mobileno=#{@mobile_no}&pwd=#{@password}")
|
55
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
56
|
+
http.use_ssl = true
|
57
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
58
|
+
headers = {'Content-Type' => 'application/oct-stream', 'Pragma' => "xz4BBcV#{GUID}", 'User-Agent' => 'IIC2.0/PC 3.2.0540'}
|
59
|
+
response = http.request_get(uri.request_uri, headers)
|
60
|
+
|
61
|
+
raise FetionException.new('Fetion Error: Login failed.') unless response.is_a? Net::HTTPSuccess
|
62
|
+
raise FetionException.new('Fetion Error: No ssic found in cookie.') unless response['set-cookie'] =~ /ssic=(.*);/
|
63
|
+
|
64
|
+
@ssic = $1
|
65
|
+
doc = REXML::Document.new(response.body)
|
66
|
+
results = doc.root
|
67
|
+
@status_code = results.attributes["status-code"]
|
68
|
+
user = results.children.first
|
69
|
+
@user_status = user.attributes['user-status']
|
70
|
+
@uri = user.attributes['uri']
|
71
|
+
@mobile_no = user.attributes['mobile-no']
|
72
|
+
@user_id = user.attributes['user-id']
|
73
|
+
if @uri =~ /sip:(\d+)@(.+);/
|
74
|
+
@sid = $1
|
75
|
+
@domain = $2
|
76
|
+
end
|
77
|
+
@logger.debug "ssic: " + @ssic
|
78
|
+
@logger.debug "status_code: " + @status_code
|
79
|
+
@logger.debug "user_status: " + @user_status
|
80
|
+
@logger.debug "uri: " + @uri
|
81
|
+
@logger.debug "mobile_no: " + @mobile_no
|
82
|
+
@logger.debug "user_id: " + @user_id
|
83
|
+
@logger.debug "sid: " + @sid
|
84
|
+
@logger.debug "domain: " + @domain
|
85
|
+
@logger.info "fetion login success"
|
86
|
+
end
|
87
|
+
|
88
|
+
def register
|
89
|
+
@logger.info "fetion http register"
|
90
|
+
arg = '<args><device type="PC" version="44" client-version="3.2.0540" /><caps value="simple-im;im-session;temp-group;personal-group" /><events value="contact;permission;system-message;personal-group" /><user-info attributes="all" /><presence><basic value="400" desc="" /></presence></args>'
|
91
|
+
|
92
|
+
call = next_call
|
93
|
+
curl_exec(next_url, @ssic, FETION_SIPP)
|
94
|
+
|
95
|
+
msg = sip_create("R fetion.com.cn SIP-C/2.0", {'F' => @sid, 'I' => call, 'Q' => '1 R'}, arg) + FETION_SIPP
|
96
|
+
curl_exec(next_url('i'), @ssic, msg)
|
97
|
+
|
98
|
+
response = curl_exec(next_url, @ssic, FETION_SIPP)
|
99
|
+
raise FetionException.new("Fetion Error: no nonce found") unless response.body =~ /nonce="(\w+)"/
|
100
|
+
|
101
|
+
@nonce = $1
|
102
|
+
@salt = "777A6D03"
|
103
|
+
@cnonce = calc_cnonce
|
104
|
+
@response = calc_response
|
105
|
+
|
106
|
+
@logger.debug "nonce: #{@nonce}"
|
107
|
+
@logger.debug "salt: #{@salt}"
|
108
|
+
@logger.debug "cnonce: #{@cnonce}"
|
109
|
+
@logger.debug "response: #{@response}"
|
110
|
+
|
111
|
+
msg = sip_create('R fetion.com.cn SIP-C/2.0', {'F' => @sid, 'I' => call, 'Q' => '2 R', 'A' => "Digest algorithm=\"SHA1-sess\",response=\"#{@response}\",cnonce=\"#{@cnonce}\",salt=\"#{@salt}\""}, arg) + FETION_SIPP
|
112
|
+
curl_exec(next_url, @ssic, msg)
|
113
|
+
response = curl_exec(next_url, @ssic, FETION_SIPP)
|
114
|
+
|
115
|
+
@logger.info "fetion http register success"
|
116
|
+
response.is_a? Net::HTTPSuccess
|
117
|
+
end
|
118
|
+
|
119
|
+
def get_buddy_list
|
120
|
+
@logger.info "fetion get buddy list"
|
121
|
+
arg = '<args><contacts><buddy-lists /><buddies attributes="all" /><mobile-buddies attributes="all" /><chat-friends /><blacklist /></contacts></args>'
|
122
|
+
msg = sip_create('S fetion.com.cn SIP-C/2.0', {'F' => @sid, 'I' => next_call, 'Q' => '1 S', 'N' => 'GetContactList'}, arg) + FETION_SIPP
|
123
|
+
curl_exec(next_url, @ssic, msg)
|
124
|
+
response = curl_exec(next_url, @ssic, FETION_SIPP)
|
125
|
+
raise FetionException.new("Fetion Error: No buddy list found") unless response.body =~ /.*?\r\n\r\n(.*)#{FETION_SIPP}\s*$/i
|
126
|
+
|
127
|
+
response.body.scan(/uri="([^"]+)"/).each do |buddy|
|
128
|
+
@buddies << {:uri => buddy[0]}
|
129
|
+
end
|
130
|
+
@logger.debug @buddies.inspect
|
131
|
+
@logger.info "fetion get buddy list success"
|
132
|
+
end
|
133
|
+
|
134
|
+
def get_contacts_info
|
135
|
+
@logger.info "fetion get contacts info"
|
136
|
+
arg = '<args><contacts attributes="all">'
|
137
|
+
@buddies.each do |buddy|
|
138
|
+
arg += "<contact uri=\"#{buddy[:uri]}\" />"
|
139
|
+
end
|
140
|
+
arg += '</contacts></args>'
|
141
|
+
|
142
|
+
msg = sip_create('S fetion.com.cn SIP-C/2.0', {'F' => @sid, 'I' => next_call, 'Q' => '1 S', 'N' => 'GetContactsInfo'}, arg) + FETION_SIPP
|
143
|
+
curl_exec(next_url, @ssic, msg)
|
144
|
+
response = curl_exec(next_url, @ssic, FETION_SIPP)
|
145
|
+
response.body.scan(/uri="([^"]+)".*?mobile-no="([^"]+)"/).each do |contact|
|
146
|
+
@contacts << {:sip => contact[0], :mobile_no => contact[1]}
|
147
|
+
end
|
148
|
+
@logger.debug @contacts.inspect
|
149
|
+
@logger.info "fetion get contacts info success"
|
150
|
+
end
|
151
|
+
|
152
|
+
def send_sms(to, content)
|
153
|
+
@logger.info "fetion send sms to #{to}"
|
154
|
+
msg = sip_create('M fetion.com.cn SIP-C/2.0', {'F' => @sid, 'I' => next_call, 'Q' => '1 M', 'T' => to, 'N' => 'SendSMS'}, content) + FETION_SIPP
|
155
|
+
curl_exec(next_url, @ssic, msg)
|
156
|
+
|
157
|
+
response = curl_exec(next_url, @ssic, FETION_SIPP)
|
158
|
+
@logger.info "fetion send sms to #{to} success"
|
159
|
+
response.is_a? Net::HTTPSuccess
|
160
|
+
end
|
161
|
+
|
162
|
+
def curl_exec(url, ssic, body)
|
163
|
+
@logger.debug "fetion curl exec"
|
164
|
+
@logger.debug "url: #{url}"
|
165
|
+
@logger.debug "ssic: #{ssic}"
|
166
|
+
@logger.debug "body: #{body}"
|
167
|
+
uri = URI.parse(url)
|
168
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
169
|
+
headers = {'Content-Type' => 'application/oct-stream', 'Pragma' => "xz4BBcV#{GUID}", 'User-Agent' => 'IIC2.0/PC 3.2.0540', 'Cookie' => "ssic=#{@ssic}"}
|
170
|
+
response = http.request_post(uri.request_uri, body, headers)
|
171
|
+
|
172
|
+
@logger.debug "response: #{response.inspect}"
|
173
|
+
@logger.debug "response body: #{response.body}"
|
174
|
+
@logger.debug "fetion curl exec complete"
|
175
|
+
response
|
176
|
+
end
|
177
|
+
|
178
|
+
def sip_create(invite, fields, arg)
|
179
|
+
sip = invite + "\r\n"
|
180
|
+
fields.each {|k, v| sip += "#{k}: #{v}\r\n"}
|
181
|
+
sip += "L: #{arg.size}\r\n\r\n#{arg}"
|
182
|
+
@logger.debug "sip message: #{sip}"
|
183
|
+
sip
|
184
|
+
end
|
185
|
+
|
186
|
+
def calc_response
|
187
|
+
str = [hash_password[8..-1]].pack("H*")
|
188
|
+
key = Digest::SHA1.digest("#{@sid}:#{@domain}:#{str}")
|
189
|
+
|
190
|
+
h1 = Digest::MD5.hexdigest("#{key}:#{@nonce}:#{@cnonce}").upcase
|
191
|
+
h2 = Digest::MD5.hexdigest("REGISTER:#{@sid}").upcase
|
192
|
+
|
193
|
+
Digest::MD5.hexdigest("#{h1}:#{@nonce}:#{h2}").upcase
|
194
|
+
end
|
195
|
+
|
196
|
+
def calc_cnonce
|
197
|
+
Digest::MD5.hexdigest(UUID.new.generate).upcase
|
198
|
+
end
|
199
|
+
|
200
|
+
def hash_password
|
201
|
+
salt = "#{0x77.chr}#{0x7A.chr}#{0x6D.chr}#{0x03.chr}"
|
202
|
+
src = salt + Digest::SHA1.digest(@password)
|
203
|
+
'777A6D03' + Digest::SHA1.hexdigest(src).upcase
|
204
|
+
end
|
205
|
+
|
206
|
+
def next_url(t = 's')
|
207
|
+
@seq += 1
|
208
|
+
FETION_URL + "?t=#{t}&i=#{@seq}"
|
209
|
+
end
|
210
|
+
|
211
|
+
def next_call
|
212
|
+
@next_call += 1
|
213
|
+
@next_call
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
data/lib/rfetion.rb
ADDED
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: flyerhzm-rfetion
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Richard Huang
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-09-17 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: rfetion is a ruby gem for China Mobile fetion service that you can send SMS free.
|
17
|
+
email: flyerhzm@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.textile
|
24
|
+
files:
|
25
|
+
- README.textile
|
26
|
+
- Rakefile
|
27
|
+
- VERSION
|
28
|
+
- lib/rfetion.rb
|
29
|
+
- lib/rfetion/fetion.rb
|
30
|
+
has_rdoc: false
|
31
|
+
homepage: ""
|
32
|
+
licenses:
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options:
|
35
|
+
- --charset=UTF-8
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: "0"
|
43
|
+
version:
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
requirements: []
|
51
|
+
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 1.3.5
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: rfetion is a ruby gem for China Mobile fetion service that you can send SMS free.
|
57
|
+
test_files: []
|
58
|
+
|