Skip to content

Commit c4aeead

Browse files
author
Andres Canal
committed
added XEP-0030 extensions to create iq for disco#info and disco#items
1 parent c5ab86f commit c4aeead

File tree

6 files changed

+363
-0
lines changed

6 files changed

+363
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//
2+
// XMPPIQ+XEP_0030.h
3+
// XMPPFramework
4+
//
5+
// Created by Andres on 7/07/16.
6+
// Copyright © 2016 Inaka. All rights reserved.
7+
//
8+
9+
#import <XMPPFramework/XMPPFramework.h>
10+
#import "XMPPFramework/XMPPJID.h"
11+
12+
@interface XMPPIQ (XEP_0030)
13+
14+
+ (nonnull XMPPIQ *) discoverItemsAssociatedWithJID:(nonnull XMPPJID *)jid;
15+
+ (nonnull XMPPIQ *) discoverInfoAssociatedWithJID:(nonnull XMPPJID *)jid;
16+
+ (nullable NSArray <NSXMLElement *> *)parseDiscoveredItemsFromIQ:(nonnull XMPPIQ *)iq;
17+
+ (nullable NSArray <NSXMLElement *> *)parseDiscoveredInfoFromIQ:(nonnull XMPPIQ *)iq;
18+
19+
@end
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//
2+
// XMPPIQ+XEP_0030.m
3+
// XMPPFramework
4+
//
5+
// Created by Andres on 7/07/16.
6+
// Copyright © 2016 Inaka. All rights reserved.
7+
//
8+
9+
#import "XMPPIQ+XEP_0030.h"
10+
#import "NSXMLElement+XMPP.h"
11+
#import "XMPPConstants.h"
12+
13+
@implementation XMPPIQ (XEP_0060)
14+
15+
+ (nonnull XMPPIQ *) discoverItemsAssociatedWithJID:(nonnull XMPPJID *)jid {
16+
17+
// <iq type='get'
18+
// from='[email protected]/orchard'
19+
// to='shakespeare.lit'
20+
// id='items1'>
21+
// <query xmlns='http://jabber.org/protocol/disco#items'/> // disco#items
22+
// </iq>
23+
24+
NSString *iqID = [XMPPStream generateUUID];
25+
NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns: XMPPDiscoItemsNamespace];
26+
return [XMPPIQ iqWithType:@"get" to:jid elementID:iqID child:query];
27+
28+
}
29+
30+
+ (nonnull XMPPIQ *) discoverInfoAssociatedWithJID:(nonnull XMPPJID *)jid {
31+
32+
// <iq type='get'
33+
// from='[email protected]/orchard'
34+
// to='shakespeare.lit'
35+
// id='items1'>
36+
// <query xmlns='http://jabber.org/protocol/disco#info'/> // disco#info
37+
// </iq>
38+
39+
NSString *iqID = [XMPPStream generateUUID];
40+
NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns: XMPPDiscoInfoNamespace];
41+
return [XMPPIQ iqWithType:@"get" to:jid elementID:iqID child:query];
42+
43+
}
44+
45+
+ (nullable NSArray <NSXMLElement *> *)parseDiscoveredItemsFromIQ:(nonnull XMPPIQ *)iq {
46+
// <iq xmlns='jabber:client' from='shakespeare.lit'
47+
48+
// id='items1' type='result'>
49+
// <query xmlns='http://jabber.org/protocol/disco#items'>
50+
// <item jid='muc.erlang-solutions.com'/>
51+
// <item jid='muclight.erlang-solutions.com'/>
52+
// <item jid='pubsub.erlang-solutions.com'/>
53+
// <item jid='vjud.erlang-solutions.com'/>
54+
// </query>
55+
// </iq>
56+
57+
NSXMLElement *query = [iq elementForName:@"query" xmlns: XMPPDiscoItemsNamespace];
58+
if(query) {
59+
return [query elementsForName:@"item"];
60+
}
61+
62+
return nil;
63+
}
64+
65+
+ (nullable NSArray <NSXMLElement *> *)parseDiscoveredInfoFromIQ:(nonnull XMPPIQ *)iq {
66+
// <iq xmlns='jabber:client' from='shakespeare.lit'
67+
68+
// id='items1' type='result'>
69+
// <query xmlns='http://jabber.org/protocol/disco#info'>
70+
// <identity category='pubsub' type='pep'/>
71+
// <identity category='server' type='im' name='ejabberd'/>
72+
// <feature var='erlang-solutions.com:xmpp:token-auth:0'/>
73+
// <feature var='http://jabber.org/protocol/disco#info'/>
74+
// <feature var='http://jabber.org/protocol/disco#items'/>
75+
// <feature var='http://jabber.org/protocol/pubsub'/>
76+
// <feature var='urn:xmpp:mam:0'/>
77+
// <feature var='urn:xmpp:mam:1'/>
78+
// </query>
79+
// </iq>
80+
81+
NSXMLElement *query = [iq elementForName:@"query" xmlns: XMPPDiscoInfoNamespace];
82+
if(query) {
83+
return [query children];
84+
}
85+
86+
return nil;
87+
}
88+
89+
@end

XMPPFramework.podspec

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,12 @@ s.source = { :git => 'https://github.com/robbiehanson/XMPPFramework.git', :branc
351351
ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}"
352352
end
353353

354+
s.subspec 'XEP-0030' do |ss|
355+
ss.source_files = 'Extensions/XEP-0030/*.{h,m}'
356+
ss.dependency 'XMPPFramework/Core'
357+
ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}"
358+
end
359+
354360
s.subspec 'All' do |ss|
355361
ss.dependency 'XMPPFramework/Core'
356362
ss.dependency 'XMPPFramework/BandwidthMonitor'
@@ -400,5 +406,6 @@ s.source = { :git => 'https://github.com/robbiehanson/XMPPFramework.git', :branc
400406
ss.dependency 'XMPPFramework/XEP-0363'
401407
ss.dependency 'XMPPFramework/XEP-0313'
402408
ss.dependency 'XMPPFramework/XMPPMUCLight'
409+
ss.dependency 'XMPPFramework/XEP-0030'
403410
end
404411
end
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
//
2+
// XMPP0030Tests.m
3+
// XMPPFrameworkTests
4+
//
5+
// Created by Andres Canal on 7/7/16.
6+
//
7+
//
8+
9+
#import <XCTest/XCTest.h>
10+
#import "XMPPFramework/XMPPIQ+XEP_0030.h"
11+
12+
@interface XMPP0030Tests : XCTestCase
13+
14+
@end
15+
16+
@implementation XMPP0030Tests
17+
18+
- (void)testIQDiscoItem {
19+
20+
XMPPJID *jid = [XMPPJID jidWithString:@"[email protected]"];
21+
XMPPIQ *discoItemsIQ = [XMPPIQ discoverItemsAssociatedWithJID:jid];
22+
23+
NSXMLElement *queryElement = [discoItemsIQ elementForName:@"query"];
24+
XCTAssertEqualObjects(queryElement.xmlns, @"http://jabber.org/protocol/disco#items");
25+
26+
XCTAssertEqualObjects(discoItemsIQ.to, jid);
27+
XCTAssertEqualObjects(discoItemsIQ.type, @"get");
28+
}
29+
30+
- (void)testParsingDiscoItemsResponse {
31+
32+
// <iq xmlns='jabber:client' from='shakespeare.lit'
33+
// to='@shakespeare.lit'
34+
// id='items1' type='result'>
35+
// <query xmlns='http://jabber.org/protocol/disco#items'>
36+
// <item jid='muc.erlang-solutions.com'/>
37+
// <item jid='muclight.erlang-solutions.com'/>
38+
// <item jid='pubsub.erlang-solutions.com'/>
39+
// <item jid='vjud.erlang-solutions.com'/>
40+
// </query>
41+
// </iq>
42+
43+
NSMutableString *s = [NSMutableString string];
44+
[s appendString: @"<iq xmlns='jabber:client' from='shakespeare.lit'"];
45+
[s appendString: @" to='@shakespeare.lit'"];
46+
[s appendString: @" id='items1' type='result'>"];
47+
[s appendString: @" <query xmlns='http://jabber.org/protocol/disco#items'>"];
48+
[s appendString: @" <item jid='muc.erlang-solutions.com'/>"];
49+
[s appendString: @" <item jid='muclight.erlang-solutions.com'/>"];
50+
[s appendString: @" <item jid='pubsub.erlang-solutions.com'/>"];
51+
[s appendString: @" <item jid='vjud.erlang-solutions.com'/>"];
52+
[s appendString: @" </query>"];
53+
[s appendString: @"</iq>"];
54+
55+
NSError *error;
56+
NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:s options:0 error:&error];
57+
XMPPIQ *iq = [XMPPIQ iqFromElement:[doc rootElement]];
58+
59+
NSArray *parsedItems = [XMPPIQ parseDiscoveredItemsFromIQ:iq];
60+
XCTAssertEqualObjects([((NSXMLElement *)parsedItems[0]) attributeForName:@"jid"].stringValue, @"muc.erlang-solutions.com");
61+
XCTAssertEqualObjects([((NSXMLElement *)parsedItems[1]) attributeForName:@"jid"].stringValue, @"muclight.erlang-solutions.com");
62+
XCTAssertEqualObjects([((NSXMLElement *)parsedItems[2]) attributeForName:@"jid"].stringValue, @"pubsub.erlang-solutions.com");
63+
XCTAssertEqualObjects([((NSXMLElement *)parsedItems[3]) attributeForName:@"jid"].stringValue, @"vjud.erlang-solutions.com");
64+
}
65+
66+
- (void)testParsingDiscoItemsWithNoItems {
67+
68+
// <iq xmlns='jabber:client' from='shakespeare.lit'
69+
// to='@shakespeare.lit'
70+
// id='items1' type='result'>
71+
// <query xmlns='http://jabber.org/protocol/disco#items'>
72+
// </query>
73+
// </iq>
74+
75+
NSMutableString *s = [NSMutableString string];
76+
[s appendString: @"<iq xmlns='jabber:client' from='shakespeare.lit'"];
77+
[s appendString: @" to='@shakespeare.lit'"];
78+
[s appendString: @" id='items1' type='result'>"];
79+
[s appendString: @" <query xmlns='http://jabber.org/protocol/disco#items'>"];
80+
[s appendString: @" </query>"];
81+
[s appendString: @"</iq>"];
82+
83+
NSError *error;
84+
NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:s options:0 error:&error];
85+
XMPPIQ *iq = [XMPPIQ iqFromElement:[doc rootElement]];
86+
87+
NSArray *parsedItems = [XMPPIQ parseDiscoveredItemsFromIQ:iq];
88+
XCTAssertNotNil(parsedItems);
89+
}
90+
91+
- (void)testParsingDiscoItemsWithWrongIQ {
92+
93+
// <iq xmlns='jabber:client' from='shakespeare.lit'
94+
// to='@shakespeare.lit'
95+
// id='items1' type='result'>
96+
// <query xmlns='http://jabber.org/protocol/disco#items'>
97+
// </query>
98+
// </iq>
99+
100+
NSMutableString *s = [NSMutableString string];
101+
[s appendString: @"<iq xmlns='jabber:client' from='shakespeare.lit'"];
102+
[s appendString: @" to='@shakespeare.lit'"];
103+
[s appendString: @" id='items1' type='result'>"];
104+
[s appendString: @" <query xmlns='anotherxmlns'>"];
105+
[s appendString: @" </query>"];
106+
[s appendString: @"</iq>"];
107+
108+
NSError *error;
109+
NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:s options:0 error:&error];
110+
XMPPIQ *iq = [XMPPIQ iqFromElement:[doc rootElement]];
111+
112+
NSArray *parsedItems = [XMPPIQ parseDiscoveredItemsFromIQ:iq];
113+
XCTAssertNil(parsedItems);
114+
}
115+
116+
- (void)testIQDiscoInfo {
117+
118+
XMPPJID *jid = [XMPPJID jidWithString:@"[email protected]"];
119+
XMPPIQ *discoItemsIQ = [XMPPIQ discoverInfoAssociatedWithJID:jid];
120+
121+
NSXMLElement *queryElement = [discoItemsIQ elementForName:@"query"];
122+
XCTAssertEqualObjects(queryElement.xmlns, @"http://jabber.org/protocol/disco#info");
123+
124+
XCTAssertEqualObjects(discoItemsIQ.to, jid);
125+
XCTAssertEqualObjects(discoItemsIQ.type, @"get");
126+
}
127+
128+
- (void)testParsingDiscoInfoResponse {
129+
130+
// <iq xmlns='jabber:client' from='erlang-solutions.com' to='[email protected]/Andress-MacBook-Pro' id='items1' type='result'>
131+
// <query xmlns='http://jabber.org/protocol/disco#info'>
132+
// <identity category='pubsub' type='pep'/>
133+
// <identity category='server' type='im' name='ejabberd'/>
134+
// <feature var='erlang-solutions.com:xmpp:token-auth:0'/>
135+
// <feature var='urn:xmpp:mam:0'/>
136+
// <feature var='urn:xmpp:mam:1'/>
137+
// </query>
138+
// </iq>
139+
140+
NSMutableString *s = [NSMutableString string];
141+
[s appendString:@"<iq xmlns='jabber:client' id='items1' type='result'>"];
142+
[s appendString:@" <query xmlns='http://jabber.org/protocol/disco#info'>"];
143+
[s appendString:@" <identity category='pubsub' type='pep'/>"];
144+
[s appendString:@" <identity category='server' type='im' name='ejabberd'/>"];
145+
[s appendString:@" <feature var='urn:xmpp:mam:0'/>"];
146+
[s appendString:@" <feature var='urn:xmpp:mam:1'/>"];
147+
[s appendString:@" </query>"];
148+
[s appendString:@"</iq>"];
149+
150+
NSError *error;
151+
NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:s options:0 error:&error];
152+
XMPPIQ *iq = [XMPPIQ iqFromElement:[doc rootElement]];
153+
154+
NSArray *parsedItems = [XMPPIQ parseDiscoveredInfoFromIQ:iq];
155+
XCTAssertEqual(parsedItems.count, 4);
156+
}
157+
158+
- (void)testParsingDiscoInfoWithNoFeatures {
159+
160+
// <iq xmlns='jabber:client' from='shakespeare.lit'
161+
// to='@shakespeare.lit'
162+
// id='items1' type='result'>
163+
// <query xmlns='http://jabber.org/protocol/disco#items'>
164+
// </query>
165+
// </iq>
166+
167+
NSMutableString *s = [NSMutableString string];
168+
[s appendString: @"<iq xmlns='jabber:client' from='shakespeare.lit'"];
169+
[s appendString: @" to='@shakespeare.lit'"];
170+
[s appendString: @" id='items1' type='result'>"];
171+
[s appendString: @" <query xmlns='http://jabber.org/protocol/disco#info'>"];
172+
[s appendString: @" </query>"];
173+
[s appendString: @"</iq>"];
174+
175+
NSError *error;
176+
NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:s options:0 error:&error];
177+
XMPPIQ *iq = [XMPPIQ iqFromElement:[doc rootElement]];
178+
179+
NSArray *parsedItems = [XMPPIQ parseDiscoveredInfoFromIQ:iq];
180+
XCTAssertNotNil(parsedItems);
181+
}
182+
183+
- (void)testParsingDiscoInfoWithWrongIQ {
184+
185+
// <iq xmlns='jabber:client' from='shakespeare.lit'
186+
// to='@shakespeare.lit'
187+
// id='items1' type='result'>
188+
// <query xmlns='http://jabber.org/protocol/disco#items'>
189+
// </query>
190+
// </iq>
191+
192+
NSMutableString *s = [NSMutableString string];
193+
[s appendString: @"<iq xmlns='jabber:client' from='shakespeare.lit'"];
194+
[s appendString: @" to='@shakespeare.lit'"];
195+
[s appendString: @" id='items1' type='result'>"];
196+
[s appendString: @" <query xmlns='anotherxmlns'>"];
197+
[s appendString: @" </query>"];
198+
[s appendString: @"</iq>"];
199+
200+
NSError *error;
201+
NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:s options:0 error:&error];
202+
XMPPIQ *iq = [XMPPIQ iqFromElement:[doc rootElement]];
203+
204+
NSArray *parsedItems = [XMPPIQ parseDiscoveredItemsFromIQ:iq];
205+
XCTAssertNil(parsedItems);
206+
}
207+
208+
@end

0 commit comments

Comments
 (0)