vines 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +1 -1
- data/Rakefile +10 -10
- data/conf/certs/ca-bundle.crt +112 -378
- data/conf/config.rb +18 -9
- data/lib/vines.rb +8 -1
- data/lib/vines/command/cert.rb +2 -1
- data/lib/vines/command/init.rb +11 -0
- data/lib/vines/command/ldap.rb +6 -3
- data/lib/vines/command/schema.rb +1 -1
- data/lib/vines/config.rb +57 -146
- data/lib/vines/config/host.rb +85 -0
- data/lib/vines/config/port.rb +111 -0
- data/lib/vines/contact.rb +1 -1
- data/lib/vines/jid.rb +26 -4
- data/lib/vines/kit.rb +6 -0
- data/lib/vines/log.rb +24 -0
- data/lib/vines/router.rb +70 -38
- data/lib/vines/stanza.rb +45 -8
- data/lib/vines/stanza/iq.rb +3 -3
- data/lib/vines/stanza/iq/disco_info.rb +5 -1
- data/lib/vines/stanza/iq/disco_items.rb +3 -0
- data/lib/vines/stanza/iq/private_storage.rb +9 -5
- data/lib/vines/stanza/iq/roster.rb +11 -12
- data/lib/vines/stanza/iq/vcard.rb +4 -4
- data/lib/vines/stanza/iq/version.rb +25 -0
- data/lib/vines/stanza/message.rb +4 -5
- data/lib/vines/stanza/presence.rb +20 -18
- data/lib/vines/stanza/presence/probe.rb +3 -4
- data/lib/vines/stanza/presence/subscribe.rb +4 -3
- data/lib/vines/stanza/presence/subscribed.rb +6 -5
- data/lib/vines/stanza/presence/unsubscribe.rb +4 -4
- data/lib/vines/stanza/presence/unsubscribed.rb +4 -3
- data/lib/vines/storage/couchdb.rb +3 -3
- data/lib/vines/storage/ldap.rb +19 -8
- data/lib/vines/storage/local.rb +23 -12
- data/lib/vines/storage/redis.rb +3 -3
- data/lib/vines/storage/sql.rb +5 -5
- data/lib/vines/stream.rb +40 -6
- data/lib/vines/stream/client.rb +5 -6
- data/lib/vines/stream/client/auth.rb +3 -2
- data/lib/vines/stream/client/bind.rb +2 -2
- data/lib/vines/stream/client/bind_restart.rb +1 -2
- data/lib/vines/stream/client/ready.rb +2 -0
- data/lib/vines/stream/client/session.rb +13 -4
- data/lib/vines/stream/client/tls.rb +1 -0
- data/lib/vines/stream/component.rb +6 -5
- data/lib/vines/stream/component/ready.rb +5 -6
- data/lib/vines/stream/http.rb +10 -4
- data/lib/vines/stream/http/request.rb +23 -2
- data/lib/vines/stream/server.rb +13 -11
- data/lib/vines/stream/server/outbound/auth_result.rb +1 -0
- data/lib/vines/stream/server/outbound/tls_result.rb +1 -0
- data/lib/vines/stream/server/ready.rb +2 -2
- data/lib/vines/user.rb +2 -1
- data/lib/vines/version.rb +1 -1
- data/test/config/host_test.rb +292 -0
- data/test/config_test.rb +244 -103
- data/test/contact_test.rb +7 -1
- data/test/jid_test.rb +48 -0
- data/test/router_test.rb +16 -47
- data/test/stanza/iq/disco_info_test.rb +76 -0
- data/test/stanza/iq/disco_items_test.rb +47 -0
- data/test/stanza/iq/private_storage_test.rb +33 -10
- data/test/stanza/iq/roster_test.rb +15 -5
- data/test/stanza/iq/vcard_test.rb +8 -25
- data/test/stanza/iq/version_test.rb +62 -0
- data/test/stanza/iq_test.rb +13 -10
- data/test/stanza/message_test.rb +16 -24
- data/test/stanza/presence/probe_test.rb +52 -0
- data/test/stanza/presence/subscribe_test.rb +1 -5
- data/test/stanza_test.rb +77 -0
- data/test/stream/client/auth_test.rb +1 -0
- data/test/stream/client/ready_test.rb +2 -0
- data/test/stream/client/session_test.rb +7 -2
- data/test/stream/component/ready_test.rb +19 -36
- data/test/stream/http/request_test.rb +22 -2
- data/test/stream/server/ready_test.rb +14 -21
- data/web/404.html +9 -3
- data/web/chat/index.html +2 -2
- data/web/chat/javascripts/app.js +1 -1
- data/web/chat/stylesheets/chat.css +4 -9
- data/web/lib/coffeescripts/layout.coffee +2 -2
- data/web/{chat → lib}/coffeescripts/logout.coffee +0 -0
- data/web/lib/coffeescripts/notification.coffee +14 -0
- data/web/lib/coffeescripts/session.coffee +28 -24
- data/web/lib/coffeescripts/transfer.coffee +37 -34
- data/web/lib/javascripts/base.js +8 -8
- data/web/lib/javascripts/icons.js +3 -0
- data/web/lib/javascripts/jquery.js +4 -18
- data/web/lib/javascripts/layout.js +2 -2
- data/web/{chat → lib}/javascripts/logout.js +0 -0
- data/web/lib/javascripts/notification.js +26 -0
- data/web/lib/javascripts/session.js +20 -16
- data/web/lib/javascripts/transfer.js +45 -55
- data/web/lib/stylesheets/base.css +45 -9
- metadata +31 -15
data/lib/vines/stanza/iq.rb
CHANGED
@@ -33,11 +33,11 @@ module Vines
|
|
33
33
|
private
|
34
34
|
|
35
35
|
def route_iq
|
36
|
-
to =
|
37
|
-
return false if to.
|
36
|
+
to = validate_to
|
37
|
+
return false if to.nil? || to.to_s == stream.domain
|
38
38
|
self['from'] = stream.user.jid.to_s
|
39
39
|
if local?
|
40
|
-
|
40
|
+
stream.available_resources(to).each do |recipient|
|
41
41
|
recipient.write(@node)
|
42
42
|
end
|
43
43
|
else
|
@@ -13,9 +13,13 @@ module Vines
|
|
13
13
|
result = to_result.tap do |el|
|
14
14
|
el << el.document.create_element('query') do |query|
|
15
15
|
query.default_namespace = NS
|
16
|
+
query << el.document.create_element('identity', 'category' => 'server', 'type' => 'im')
|
17
|
+
query << el.document.create_element('feature', 'var' => NAMESPACES[:disco_info])
|
18
|
+
query << el.document.create_element('feature', 'var' => NAMESPACES[:disco_items])
|
16
19
|
query << el.document.create_element('feature', 'var' => NAMESPACES[:ping])
|
17
20
|
query << el.document.create_element('feature', 'var' => NAMESPACES[:vcard])
|
18
|
-
|
21
|
+
query << el.document.create_element('feature', 'var' => NAMESPACES[:version])
|
22
|
+
if stream.config.private_storage?(stream.domain)
|
19
23
|
query << el.document.create_element('feature', 'var' => NAMESPACES[:storage])
|
20
24
|
end
|
21
25
|
end
|
@@ -13,6 +13,9 @@ module Vines
|
|
13
13
|
result = to_result.tap do |el|
|
14
14
|
el << el.document.create_element('query') do |query|
|
15
15
|
query.default_namespace = NS
|
16
|
+
stream.config.vhosts[stream.domain].components.keys.sort.each do |domain|
|
17
|
+
query << el.document.create_element('item', 'jid' => domain)
|
18
|
+
end
|
16
19
|
end
|
17
20
|
end
|
18
21
|
stream.write(result)
|
@@ -12,10 +12,8 @@ module Vines
|
|
12
12
|
register "/iq[@id and (@type='get' or @type='set')]/ns:query", 'ns' => NS
|
13
13
|
|
14
14
|
def process
|
15
|
-
unless stream.private_storage?
|
16
|
-
raise StanzaErrors::ServiceUnavailable.new(self, 'cancel')
|
17
|
-
end
|
18
15
|
validate_to_address
|
16
|
+
validate_storage_enabled
|
19
17
|
validate_children_size
|
20
18
|
validate_namespaces
|
21
19
|
get? ? retrieve_fragment : update_fragment
|
@@ -64,12 +62,18 @@ module Vines
|
|
64
62
|
end
|
65
63
|
|
66
64
|
def validate_to_address
|
67
|
-
to =
|
68
|
-
unless to.
|
65
|
+
to = validate_to
|
66
|
+
unless to.nil? || to == stream.user.jid.bare
|
69
67
|
raise StanzaErrors::Forbidden.new(self, 'cancel')
|
70
68
|
end
|
71
69
|
end
|
72
70
|
|
71
|
+
def validate_storage_enabled
|
72
|
+
unless stream.config.private_storage?(stream.domain)
|
73
|
+
raise StanzaErrors::ServiceUnavailable.new(self, 'cancel')
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
73
77
|
def validate_namespaces
|
74
78
|
elements.first.elements.each do |node|
|
75
79
|
if node.namespace.nil? || NAMESPACES.values.include?(node.namespace.href)
|
@@ -9,6 +9,7 @@ module Vines
|
|
9
9
|
register "/iq[@id and (@type='get' or @type='set')]/ns:query", 'ns' => NS
|
10
10
|
|
11
11
|
def process
|
12
|
+
validate_to_address
|
12
13
|
get? ? roster_query : update_roster
|
13
14
|
end
|
14
15
|
|
@@ -26,8 +27,8 @@ module Vines
|
|
26
27
|
# Roster sets must have no 'to' address or be addressed to the same
|
27
28
|
# JID that sent the stanza. RFC 6121 sections 2.1.5 and 2.3.3.
|
28
29
|
def validate_to_address
|
29
|
-
to =
|
30
|
-
unless to.
|
30
|
+
to = validate_to
|
31
|
+
unless to.nil? || to.bare == stream.user.jid.bare
|
31
32
|
raise StanzaErrors::Forbidden.new(self, 'auth')
|
32
33
|
end
|
33
34
|
end
|
@@ -35,14 +36,12 @@ module Vines
|
|
35
36
|
# Add, update, or delete the roster item contained in the iq set
|
36
37
|
# stanza received from the client. RFC 6121 sections 2.3, 2.4, 2.5.
|
37
38
|
def update_roster
|
38
|
-
validate_to_address
|
39
|
-
|
40
39
|
items = self.xpath('ns:query/ns:item', 'ns' => NS)
|
41
40
|
raise StanzaErrors::BadRequest.new(self, 'modify') if items.size != 1
|
42
41
|
item = items.first
|
43
42
|
|
44
|
-
jid = (item['jid']
|
45
|
-
raise StanzaErrors::BadRequest.new(self, 'modify')
|
43
|
+
jid = JID.new(item['jid']) rescue (raise StanzaErrors::JidMalformed.new(self, 'modify'))
|
44
|
+
raise StanzaErrors::BadRequest.new(self, 'modify') if jid.empty? || !jid.bare?
|
46
45
|
|
47
46
|
if item['subscription'] == 'remove'
|
48
47
|
remove_contact(jid)
|
@@ -75,7 +74,7 @@ module Vines
|
|
75
74
|
def remove_contact(jid)
|
76
75
|
contact = stream.user.contact(jid)
|
77
76
|
raise StanzaErrors::ItemNotFound.new(self, 'modify') unless contact
|
78
|
-
if
|
77
|
+
if local_jid?(contact.jid)
|
79
78
|
user = storage(contact.jid.domain).find_user(contact.jid)
|
80
79
|
end
|
81
80
|
|
@@ -94,10 +93,10 @@ module Vines
|
|
94
93
|
:jid => contact.jid,
|
95
94
|
:subscription => 'remove'))
|
96
95
|
|
97
|
-
if
|
96
|
+
if local_jid?(contact.jid)
|
98
97
|
send_unavailable(stream.user.jid, contact.jid) if contact.subscribed_from?
|
99
98
|
send_unsubscribe(contact)
|
100
|
-
if user.contact(stream.user.jid)
|
99
|
+
if user && user.contact(stream.user.jid)
|
101
100
|
push_roster_updates(contact.jid, user.contact(stream.user.jid))
|
102
101
|
end
|
103
102
|
else
|
@@ -112,8 +111,8 @@ module Vines
|
|
112
111
|
presence(contact.jid, type) if contact.send("subscribed_#{meth}?")
|
113
112
|
end.compact
|
114
113
|
|
115
|
-
if
|
116
|
-
|
114
|
+
if local_jid?(contact.jid)
|
115
|
+
stream.interested_resources(contact.jid).each do |recipient|
|
117
116
|
presence.each {|el| recipient.write(el) }
|
118
117
|
end
|
119
118
|
else
|
@@ -133,7 +132,7 @@ module Vines
|
|
133
132
|
# Send an iq set stanza to the user's interested resources, letting them
|
134
133
|
# know their roster has been updated.
|
135
134
|
def push_roster_updates(to, contact)
|
136
|
-
|
135
|
+
stream.interested_resources(to).each do |recipient|
|
137
136
|
contact.send_roster_push(recipient)
|
138
137
|
end
|
139
138
|
end
|
@@ -20,8 +20,8 @@ module Vines
|
|
20
20
|
private
|
21
21
|
|
22
22
|
def vcard_query
|
23
|
-
|
24
|
-
jid =
|
23
|
+
to = validate_to
|
24
|
+
jid = to ? to.bare : stream.user.jid.bare
|
25
25
|
card = storage.find_vcard(jid)
|
26
26
|
|
27
27
|
raise StanzaErrors::ItemNotFound.new(self, 'cancel') unless card
|
@@ -38,8 +38,8 @@ module Vines
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def vcard_update
|
41
|
-
to =
|
42
|
-
unless to.
|
41
|
+
to = validate_to
|
42
|
+
unless to.nil? || to == stream.user.jid.bare
|
43
43
|
raise StanzaErrors::Forbidden.new(self, 'auth')
|
44
44
|
end
|
45
45
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Vines
|
4
|
+
class Stanza
|
5
|
+
class Iq
|
6
|
+
class Version < Query
|
7
|
+
NS = NAMESPACES[:version]
|
8
|
+
|
9
|
+
register "/iq[@id and @type='get']/ns:query", 'ns' => NS
|
10
|
+
|
11
|
+
def process
|
12
|
+
return if route_iq
|
13
|
+
result = to_result.tap do |node|
|
14
|
+
node << node.document.create_element('query') do |query|
|
15
|
+
query.default_namespace = NS
|
16
|
+
query << node.document.create_element('name', 'Vines')
|
17
|
+
query << node.document.create_element('version', VERSION)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
stream.write(result)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/vines/stanza/message.rb
CHANGED
@@ -5,8 +5,8 @@ module Vines
|
|
5
5
|
class Message < Stanza
|
6
6
|
register "/message"
|
7
7
|
|
8
|
-
TYPE,
|
9
|
-
VALID_TYPES
|
8
|
+
TYPE, FROM = %w[type from].map {|s| s.freeze }
|
9
|
+
VALID_TYPES = %w[chat error groupchat headline normal].freeze
|
10
10
|
|
11
11
|
VALID_TYPES.each do |type|
|
12
12
|
define_method "#{type}?" do
|
@@ -20,9 +20,8 @@ module Vines
|
|
20
20
|
end
|
21
21
|
|
22
22
|
if local?
|
23
|
-
to =
|
24
|
-
|
25
|
-
recipients = router.connected_resources(to)
|
23
|
+
to = validate_to || stream.user.jid.bare
|
24
|
+
recipients = stream.connected_resources(to)
|
26
25
|
if recipients.empty?
|
27
26
|
if user = storage(to.domain).find_user(to)
|
28
27
|
# TODO Implement offline messaging storage
|
@@ -14,7 +14,7 @@ module Vines
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def process
|
17
|
-
stream.last_broadcast_presence = @node.clone unless
|
17
|
+
stream.last_broadcast_presence = @node.clone unless validate_to
|
18
18
|
unless self['type'].nil?
|
19
19
|
raise StanzaErrors::BadRequest.new(self, 'modify')
|
20
20
|
end
|
@@ -23,26 +23,28 @@ module Vines
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def outbound?
|
26
|
-
|
26
|
+
!inbound?
|
27
27
|
end
|
28
28
|
|
29
29
|
def inbound?
|
30
|
-
stream.class == Vines::Stream::Server
|
30
|
+
stream.class == Vines::Stream::Server ||
|
31
|
+
stream.class == Vines::Stream::Component
|
31
32
|
end
|
32
33
|
|
33
34
|
def outbound_broadcast_presence
|
34
35
|
self['from'] = stream.user.jid.to_s
|
35
|
-
to
|
36
|
-
|
36
|
+
to = validate_to
|
37
|
+
type = (self['type'] || '').strip
|
38
|
+
initial = to.nil? && type.empty? && !stream.available?
|
37
39
|
|
38
|
-
recipients = if to.
|
40
|
+
recipients = if to.nil?
|
39
41
|
stream.available_subscribers
|
40
42
|
else
|
41
|
-
stream.user.subscribed_from?(to) ?
|
43
|
+
stream.user.subscribed_from?(to) ? stream.available_resources(to) : []
|
42
44
|
end
|
43
45
|
|
44
46
|
broadcast(recipients)
|
45
|
-
broadcast(
|
47
|
+
broadcast(stream.available_resources(stream.user.jid))
|
46
48
|
|
47
49
|
if initial
|
48
50
|
stream.available_subscribed_to_resources.each do |recipient|
|
@@ -53,6 +55,9 @@ module Vines
|
|
53
55
|
stream.write(el)
|
54
56
|
end
|
55
57
|
end
|
58
|
+
stream.remote_subscribed_to_contacts.each do |contact|
|
59
|
+
send_probe(contact.jid.bare)
|
60
|
+
end
|
56
61
|
stream.available!
|
57
62
|
end
|
58
63
|
|
@@ -60,12 +65,11 @@ module Vines
|
|
60
65
|
node = @node.clone
|
61
66
|
node['to'] = contact.jid.bare.to_s
|
62
67
|
router.route(node) rescue nil # ignore RemoteServerNotFound
|
63
|
-
send_probe(contact.jid.bare) if initial
|
64
68
|
end
|
65
69
|
end
|
66
70
|
|
67
71
|
def inbound_broadcast_presence
|
68
|
-
broadcast(
|
72
|
+
broadcast(stream.available_resources(validate_to))
|
69
73
|
end
|
70
74
|
|
71
75
|
private
|
@@ -78,7 +82,7 @@ module Vines
|
|
78
82
|
'id' => Kit.uuid,
|
79
83
|
'to' => to.bare.to_s,
|
80
84
|
'type' => 'probe')
|
81
|
-
router.route(probe)
|
85
|
+
router.route(probe) rescue nil # ignore RemoteServerNotFound
|
82
86
|
end
|
83
87
|
|
84
88
|
def auto_reply_to_subscription_request(from, type)
|
@@ -96,13 +100,11 @@ module Vines
|
|
96
100
|
# resource part from it so it's a bare jid. Return the bare JID object
|
97
101
|
# that was stamped.
|
98
102
|
def stamp_to
|
99
|
-
to =
|
100
|
-
raise StanzaErrors::BadRequest.new(self, 'modify')
|
101
|
-
to
|
102
|
-
|
103
|
-
|
104
|
-
self['to'] = to.to_s
|
105
|
-
to
|
103
|
+
to = validate_to
|
104
|
+
raise StanzaErrors::BadRequest.new(self, 'modify') unless to
|
105
|
+
to.bare.tap do |bare|
|
106
|
+
self['to'] = bare.to_s
|
107
|
+
end
|
106
108
|
end
|
107
109
|
end
|
108
110
|
end
|
@@ -16,15 +16,14 @@ module Vines
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def process_inbound
|
19
|
-
to =
|
20
|
-
raise StanzaErrors::BadRequest.new(self, 'modify')
|
21
|
-
to = JID.new(to)
|
19
|
+
to = validate_to
|
20
|
+
raise StanzaErrors::BadRequest.new(self, 'modify') unless to
|
22
21
|
|
23
22
|
user = storage(to.domain).find_user(to)
|
24
23
|
unless user && user.subscribed_from?(stream.user.jid)
|
25
24
|
auto_reply_to_subscription_request(to.bare, 'unsubscribed')
|
26
25
|
else
|
27
|
-
|
26
|
+
stream.available_resources(to).each do |recipient|
|
28
27
|
el = recipient.last_broadcast_presence.clone
|
29
28
|
el['from'] = recipient.user.jid.to_s
|
30
29
|
el['to'] = stream.user.jid.to_s
|
@@ -13,14 +13,15 @@ module Vines
|
|
13
13
|
def process_outbound
|
14
14
|
self['from'] = stream.user.jid.bare.to_s
|
15
15
|
to = stamp_to
|
16
|
-
local? ? process_inbound : route
|
17
16
|
|
18
17
|
stream.user.request_subscription(to)
|
19
18
|
storage.save_user(stream.user)
|
20
19
|
stream.update_user_streams(stream.user)
|
21
20
|
|
21
|
+
local? ? process_inbound : route
|
22
|
+
|
22
23
|
contact = stream.user.contact(to)
|
23
|
-
|
24
|
+
stream.interested_resources(stream.user.jid).each do |recipient|
|
24
25
|
contact.send_roster_push(recipient)
|
25
26
|
end
|
26
27
|
end
|
@@ -35,7 +36,7 @@ module Vines
|
|
35
36
|
elsif contact.subscribed_from?(stream.user.jid)
|
36
37
|
auto_reply_to_subscription_request(to, 'subscribed')
|
37
38
|
else
|
38
|
-
recipients =
|
39
|
+
recipients = stream.available_resources(to)
|
39
40
|
if recipients.empty?
|
40
41
|
# TODO store subscription request per RFC 6121 3.1.3 #4
|
41
42
|
else
|
@@ -13,18 +13,19 @@ module Vines
|
|
13
13
|
def process_outbound
|
14
14
|
self['from'] = stream.user.jid.bare.to_s
|
15
15
|
to = stamp_to
|
16
|
-
local? ? process_inbound : route
|
17
16
|
|
18
17
|
stream.user.add_subscription_from(to)
|
19
18
|
storage.save_user(stream.user)
|
20
19
|
stream.update_user_streams(stream.user)
|
21
20
|
|
21
|
+
local? ? process_inbound : route
|
22
|
+
|
22
23
|
contact = stream.user.contact(to)
|
23
|
-
|
24
|
+
stream.interested_resources(stream.user.jid).each do |recipient|
|
24
25
|
contact.send_roster_push(recipient)
|
25
26
|
end
|
26
27
|
|
27
|
-
presences =
|
28
|
+
presences = stream.available_resources(stream.user.jid).map do |c|
|
28
29
|
c.last_broadcast_presence.clone.tap do |node|
|
29
30
|
node['from'] = c.user.jid.to_s
|
30
31
|
node['id'] = Kit.uuid
|
@@ -33,7 +34,7 @@ module Vines
|
|
33
34
|
end
|
34
35
|
|
35
36
|
if local?
|
36
|
-
|
37
|
+
stream.available_resources(to).each do |recipient|
|
37
38
|
presences.each {|el| recipient.write(el) }
|
38
39
|
end
|
39
40
|
else
|
@@ -52,7 +53,7 @@ module Vines
|
|
52
53
|
storage(to.domain).save_user(user)
|
53
54
|
stream.update_user_streams(user)
|
54
55
|
|
55
|
-
|
56
|
+
stream.interested_resources(to).each do |recipient|
|
56
57
|
recipient.write(@node)
|
57
58
|
contact.send_roster_push(recipient)
|
58
59
|
end
|
@@ -15,14 +15,14 @@ module Vines
|
|
15
15
|
to = stamp_to
|
16
16
|
|
17
17
|
return unless stream.user.subscribed_to?(to)
|
18
|
-
local? ? process_inbound : route
|
19
|
-
|
20
18
|
stream.user.remove_subscription_to(to)
|
21
19
|
storage.save_user(stream.user)
|
22
20
|
stream.update_user_streams(stream.user)
|
23
21
|
|
22
|
+
local? ? process_inbound : route
|
23
|
+
|
24
24
|
contact = stream.user.contact(to)
|
25
|
-
|
25
|
+
stream.interested_resources(stream.user.jid).each do |recipient|
|
26
26
|
contact.send_roster_push(recipient)
|
27
27
|
end
|
28
28
|
end
|
@@ -38,7 +38,7 @@ module Vines
|
|
38
38
|
storage(to.domain).save_user(user)
|
39
39
|
stream.update_user_streams(user)
|
40
40
|
|
41
|
-
|
41
|
+
stream.interested_resources(to).each do |recipient|
|
42
42
|
recipient.write(@node)
|
43
43
|
contact.send_roster_push(recipient)
|
44
44
|
end
|
@@ -16,14 +16,15 @@ module Vines
|
|
16
16
|
|
17
17
|
return unless stream.user.subscribed_from?(to)
|
18
18
|
send_unavailable(stream.user.jid, to)
|
19
|
-
local? ? process_inbound : route
|
20
19
|
|
21
20
|
stream.user.remove_subscription_from(to)
|
22
21
|
storage.save_user(stream.user)
|
23
22
|
stream.update_user_streams(stream.user)
|
24
23
|
|
24
|
+
local? ? process_inbound : route
|
25
|
+
|
25
26
|
contact = stream.user.contact(to)
|
26
|
-
|
27
|
+
stream.interested_resources(stream.user.jid).each do |recipient|
|
27
28
|
contact.send_roster_push(recipient)
|
28
29
|
end
|
29
30
|
end
|
@@ -39,7 +40,7 @@ module Vines
|
|
39
40
|
storage(to.domain).save_user(user)
|
40
41
|
stream.update_user_streams(user)
|
41
42
|
|
42
|
-
|
43
|
+
stream.interested_resources(to).each do |recipient|
|
43
44
|
recipient.write(@node)
|
44
45
|
contact.send_roster_push(recipient)
|
45
46
|
end
|