1#!/usr/bin/env ruby
2#
3# Copyright (C) 2017 Denver Gingerich <denver@ossguy.com>
4#
5# This file is part of sgx-catapult.
6#
7# sgx-catapult is free software: you can redistribute it and/or modify it under
8# the terms of the GNU Affero General Public License as published by the Free
9# Software Foundation, either version 3 of the License, or (at your option) any
10# later version.
11#
12# sgx-catapult is distributed in the hope that it will be useful, but WITHOUT
13# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
15# details.
16#
17# You should have received a copy of the GNU Affero General Public License along
18# with sgx-catapult. If not, see <http://www.gnu.org/licenses/>.
19
20require 'blather/client/dsl'
21
22if ARGV.size != 4 then
23 puts "Usage: sgx-catapult.rb <component_jid> <component_password> " +
24 "<server_hostname> <server_port>"
25 exit 0
26end
27
28module SGXcatapult
29 extend Blather::DSL
30
31 def self.run
32 client.run
33 end
34
35 setup ARGV[0], ARGV[1], ARGV[2], ARGV[3]
36
37 message :chat?, :body do |m|
38 begin
39 puts "#{m.from.to_s} -> #{m.to.to_s} #{m.body}"
40 msg = Blather::Stanza::Message.new(m.from, 'thx for "' +
41 m.body + '"')
42 msg.from = m.to
43 write_to_stream msg
44 rescue => e
45 # TODO: do something better with this info
46 say m.from, e.inspect
47 end
48 end
49
50 iq '/iq/ns:query', :ns =>
51 'http://jabber.org/protocol/disco#items' do |i, xpath_result|
52
53 puts "IQ: #{i.inspect}"
54
55 msg = Blather::Stanza::Iq::DiscoItems.new
56 msg.id = i.id
57 msg.to = i.from
58 msg.type = 'result'
59
60 puts "RESPONSE0: #{msg.inspect}"
61 write_to_stream msg
62 puts "SENT"
63 end
64
65 iq '/iq/ns:query', :ns =>
66 'http://jabber.org/protocol/disco#info' do |i, xpath_result|
67
68 puts "IQ: #{i.inspect}"
69
70 msg = Blather::Stanza::Iq::DiscoInfo.new
71 msg.id = i.id
72 msg.to = i.from
73 msg.type = 'result'
74
75 msg.identities = [{:name =>
76 'Soprani.ca Gateway to XMPP - Catapult',
77 :type => 'sms-ctplt', :category => 'gateway'}]
78 msg.features = ["jabber:iq:register",
79 "jabber:iq:gateway", "jabber:iq:private",
80 "http://jabber.org/protocol/disco#info",
81 "http://jabber.org/protocol/commands",
82 "http://jabber.org/protocol/muc"]
83 puts "RESPONSE1: #{msg.inspect}"
84 write_to_stream msg
85 puts "SENT"
86 end
87
88 iq '/iq/ns:query', :ns => 'jabber:iq:register' do |i, qn|
89 puts "IQ: #{i.inspect}"
90
91 if i.type == :set
92 xn = qn.children.find { |v| v.element_name == "x" }
93
94 if xn.nil?
95 puts "id: " + qn.children.find {
96 |v| v.element_name == "nick" }
97 puts "token: " + qn.children.find {
98 |v| v.element_name == "username" }
99 puts "secret: " + qn.children.find {
100 |v| v.element_name == "password" }
101 puts "phone num: " + qn.children.find {
102 |v| v.element_name == "phone" }
103 next
104 end
105
106 for field in xn.children
107 if field.element_name == "field"
108 val = field.children.find { |v|
109 v.element_name == "value" }
110
111 case field['var']
112 when 'nick'
113 puts "id: " + val.text
114 when 'username'
115 puts "token: " + val.text
116 when 'password'
117 puts "secret: " + val.text
118 when 'phone'
119 puts "phone num: " + val.text
120 when 'FORM_TYPE'
121 puts "FORM_TYPE: " + val.text
122 else
123 # TODO: error
124 puts "weird var: " +field['var']
125 end
126 end
127 end
128
129 # success (for now)
130 msg = Blather::Stanza::Iq.new
131 msg.id = i.id
132 msg.to = i.from
133 msg.type = 'result'
134
135 puts "RESPONSE3: #{msg.inspect}"
136 write_to_stream msg
137 puts "SENT"
138
139 elsif i.type == :get
140 orig = Blather::Stanza::Iq.new
141 orig.id = i.id
142 orig.to = i.from
143 orig.type = 'result'
144
145 msg = Nokogiri::XML::Node.new 'query',orig.document
146 msg['xmlns'] = 'jabber:iq:register'
147 n1 = Nokogiri::XML::Node.new 'instructions',msg.document
148 n1.content= "Enter the information from your Account " +
149 "page as well as the Phone Number\nin your " +
150 "account you want to use (ie. '+12345678901')" +
151 ".\nUser Id is nick, API Token is username, " +
152 "API Secret is password, Phone Number is phone"+
153 ".\n\nThe source code for this gateway is at " +
154 "https://github.com/ossguy/sgx-catapult ." +
155 "\nCopyright (C) 2017 Denver Gingerich, " +
156 "licensed under AGPLv3+."
157 n2 = Nokogiri::XML::Node.new 'nick',msg.document
158 n3 = Nokogiri::XML::Node.new 'username',msg.document
159 n4 = Nokogiri::XML::Node.new 'password',msg.document
160 n5 = Nokogiri::XML::Node.new 'phone',msg.document
161 msg.add_child(n1)
162 msg.add_child(n2)
163 msg.add_child(n3)
164 msg.add_child(n4)
165 msg.add_child(n5)
166
167 x = Nokogiri::XML::Node.new 'x',orig.document
168 x['xmlns'] = 'jabber:x:data'
169 x['type'] = 'form'
170 msg.add_child(x)
171
172 title = Nokogiri::XML::Node.new 'title',orig.document
173 title.content= 'Register for ' +
174 'Soprani.ca Gateway to XMPP - Catapult'
175 x.add_child(title)
176
177 instr = Nokogiri::XML::Node.new 'instructions',
178 orig.document
179 instr.content= "Enter the details from your Account " +
180 "page as well as the Phone Number\nin your " +
181 "account you want to use (ie. '+12345678901')" +
182 ".\n\nThe source code for this gateway is at " +
183 "https://github.com/ossguy/sgx-catapult ." +
184 "\nCopyright (C) 2017 Denver Gingerich, " +
185 "licensed under AGPLv3+."
186 x.add_child(instr)
187
188 f1 = Nokogiri::XML::Node.new 'field',orig.document
189 f1['type'] = 'hidden'
190 f1['var'] = 'FORM_TYPE'
191 v1 = Nokogiri::XML::Node.new 'value',orig.document
192 v1.content= 'jabber:iq:register'
193 f1.add_child(v1)
194 x.add_child(f1)
195
196 f2 = Nokogiri::XML::Node.new 'field',orig.document
197 f2['type'] = 'text-single'
198 f2['label'] = 'User Id'
199 f2['var'] = 'nick'
200 v2 = Nokogiri::XML::Node.new 'required',orig.document
201 f2.add_child(v2)
202 x.add_child(f2)
203
204 f3 = Nokogiri::XML::Node.new 'field',orig.document
205 f3['type'] = 'text-single'
206 f3['label'] = 'API Token'
207 f3['var'] = 'username'
208 v3 = Nokogiri::XML::Node.new 'required',orig.document
209 f3.add_child(v3)
210 x.add_child(f3)
211
212 f4 = Nokogiri::XML::Node.new 'field',orig.document
213 f4['type'] = 'text-private'
214 f4['label'] = 'API Secret'
215 f4['var'] = 'password'
216 v4 = Nokogiri::XML::Node.new 'required',orig.document
217 f4.add_child(v4)
218 x.add_child(f4)
219
220 f5 = Nokogiri::XML::Node.new 'field',orig.document
221 f5['type'] = 'text-single'
222 f5['label'] = 'Phone Number'
223 f5['var'] = 'phone'
224 v5 = Nokogiri::XML::Node.new 'required',orig.document
225 f5.add_child(v5)
226 x.add_child(f5)
227
228 orig.add_child(msg)
229 puts "RESPONSE2: #{orig.inspect}"
230 write_to_stream orig
231 puts "SENT"
232 end
233 end
234
235 subscription(:request?) do |s|
236 # TODO: fix these - they don't actual work; write does not exist
237 #write(s.approve!)
238 #write(s.request!)
239 end
240end
241
242[:INT, :TERM].each do |sig|
243 trap(sig) {
244 puts 'Shutting down gateway...'
245 SGXcatapult.shutdown
246 puts 'Gateway has terminated.'
247
248 EM.stop
249 }
250end
251
252EM.run do
253 SGXcatapult.run
254end