Skip to content

Commit 1cea842

Browse files
committed
Added XMPPRegistration to handle XEP-0077
1 parent acab932 commit 1cea842

File tree

2 files changed

+233
-0
lines changed

2 files changed

+233
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// Created by Jonathon Staff on 10/11/14.
3+
// Copyright (c) 2014 Jonathon Staff. All rights reserved.
4+
//
5+
6+
#import <Foundation/Foundation.h>
7+
#import "XMPPModule.h"
8+
9+
@class XMPPIDTracker;
10+
11+
#define _XMPP_REGISTRATION_H
12+
13+
@interface XMPPRegistration : XMPPModule
14+
{
15+
XMPPIDTracker *xmppIDTracker;
16+
}
17+
18+
- (BOOL)changePassword:(NSString *)newPassword;
19+
- (BOOL)cancelRegistrationUsingPassword:(NSString *)password;
20+
21+
@end
22+
23+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
24+
#pragma mark - XMPPRegistrationDelegate
25+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26+
27+
@protocol XMPPRegistrationDelegate
28+
@optional
29+
30+
- (void)passwordChangeSuccessful:(XMPPRegistration *)sender;
31+
- (void)passwordChangeFailed:(XMPPRegistration *)sender withError:(NSError *)error;
32+
33+
- (void)cancelRegistrationSuccessful:(XMPPRegistration *)sender;
34+
- (void)cancelRegistrationFailed:(XMPPRegistration *)sender withError:(NSError *)error;
35+
36+
@end
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
//
2+
// Created by Jonathon Staff on 10/11/14.
3+
// Copyright (c) 2014 Jonathon Staff. All rights reserved.
4+
//
5+
6+
#import "XMPPRegistration.h"
7+
#import "XMPPStream.h"
8+
#import "XMPPIDTracker.h"
9+
#import "XMPPIQ.h"
10+
#import "NSXMLElement+XMPP.h"
11+
12+
NSString *const XMPPRegistrationErrorDomain = @"XMPPRegistrationErrorDomain";
13+
14+
@implementation XMPPRegistration
15+
16+
- (void)didActivate
17+
{
18+
xmppIDTracker = [[XMPPIDTracker alloc] initWithStream:xmppStream dispatchQueue:moduleQueue];
19+
}
20+
21+
- (void)willDeactivate
22+
{
23+
[xmppIDTracker removeAllIDs];
24+
xmppIDTracker = nil;
25+
}
26+
27+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28+
#pragma mark Public API
29+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30+
31+
- (BOOL)changePassword:(NSString *)newPassword
32+
{
33+
if (![xmppStream isAuthenticated])
34+
return NO; // You must be authenticated in order to change your password
35+
36+
dispatch_block_t block = ^{
37+
@autoreleasepool {
38+
NSString *toStr = xmppStream.myJID.domain;
39+
NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"jabber:iq:register"];
40+
41+
NSXMLElement *username = [NSXMLElement elementWithName:@"username"
42+
stringValue:xmppStream.myJID.user];
43+
NSXMLElement *password = [NSXMLElement elementWithName:@"password"
44+
stringValue:newPassword];
45+
[query addChild:username];
46+
[query addChild:password];
47+
48+
XMPPIQ *iq = [XMPPIQ iqWithType:@"set"
49+
to:[XMPPJID jidWithString:toStr]
50+
elementID:[xmppStream generateUUID]
51+
child:query];
52+
53+
[xmppIDTracker addID:[iq elementID]
54+
target:self
55+
selector:@selector(handlePasswordChangeQueryIQ:withInfo:)
56+
timeout:60];
57+
58+
[xmppStream sendElement:iq];
59+
}
60+
};
61+
62+
if (dispatch_get_specific(moduleQueueTag))
63+
block();
64+
else
65+
dispatch_async(moduleQueue, block);
66+
67+
return YES;
68+
}
69+
70+
- (BOOL)cancelRegistrationUsingPassword:(NSString *)password
71+
{
72+
// TODO: Handle the scenario of using password
73+
74+
dispatch_block_t block = ^{
75+
@autoreleasepool {
76+
77+
NSXMLElement *remove = [NSXMLElement elementWithName:@"remove"];
78+
NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"jabber:iq:register"];
79+
[query addChild:remove];
80+
XMPPIQ *iq = [XMPPIQ iqWithType:@"set"
81+
elementID:[xmppStream generateUUID]
82+
child:query];
83+
84+
[xmppIDTracker addElement:iq
85+
target:self
86+
selector:@selector(handleRegistrationCancelQueryIQ:withInfo:)
87+
timeout:60];
88+
89+
[xmppStream sendElement:iq];
90+
}
91+
};
92+
93+
if (dispatch_get_specific(moduleQueueTag))
94+
block();
95+
else
96+
dispatch_async(moduleQueue, block);
97+
98+
return YES;
99+
}
100+
101+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
102+
#pragma mark - XMPPIDTracker
103+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104+
105+
- (void)handlePasswordChangeQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info
106+
{
107+
dispatch_block_t block = ^{
108+
@autoreleasepool {
109+
NSXMLElement *errorElem = [iq elementForName:@"error"];
110+
111+
if (errorElem) {
112+
NSString *errMsg = [[errorElem children] componentsJoinedByString:@", "];
113+
NSInteger errCode = [errorElem attributeIntegerValueForName:@"code"
114+
withDefaultValue:-1];
115+
NSDictionary *errInfo = @{NSLocalizedDescriptionKey : errMsg};
116+
NSError *err = [NSError errorWithDomain:XMPPRegistrationErrorDomain
117+
code:errCode
118+
userInfo:errInfo];
119+
120+
[multicastDelegate passwordChangeFailed:self
121+
withError:err];
122+
return;
123+
}
124+
125+
NSString *type = [iq type];
126+
127+
if ([type isEqualToString:@"result"] && iq.childCount == 0) {
128+
[multicastDelegate passwordChangeSuccessful:self];
129+
} else {
130+
// this should be impossible to reach, but just for safety's sake...
131+
[multicastDelegate passwordChangeFailed:self
132+
withError:nil];
133+
}
134+
}
135+
};
136+
137+
if (dispatch_get_specific(moduleQueueTag))
138+
block();
139+
else
140+
dispatch_async(moduleQueue, block);
141+
}
142+
143+
- (void)handleRegistrationCancelQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info
144+
{
145+
dispatch_block_t block = ^{
146+
@autoreleasepool {
147+
NSXMLElement *errorElem = [iq elementForName:@"error"];
148+
149+
if (errorElem) {
150+
NSString *errMsg = [[errorElem children] componentsJoinedByString:@", "];
151+
NSInteger errCode = [errorElem attributeIntegerValueForName:@"code"
152+
withDefaultValue:-1];
153+
NSDictionary *errInfo = @{NSLocalizedDescriptionKey : errMsg};
154+
NSError *err = [NSError errorWithDomain:XMPPRegistrationErrorDomain
155+
code:errCode
156+
userInfo:errInfo];
157+
158+
[multicastDelegate cancelRegistrationFailed:self
159+
withError:err];
160+
return;
161+
}
162+
163+
NSString *type = [iq type];
164+
165+
if ([type isEqualToString:@"result"] && iq.childCount == 0) {
166+
[multicastDelegate cancelRegistrationSuccessful:self];
167+
} else {
168+
// this should be impossible to reach, but just for safety's sake...
169+
[multicastDelegate cancelRegistrationFailed:self
170+
withError:nil];
171+
}
172+
}
173+
};
174+
175+
if (dispatch_get_specific(moduleQueueTag))
176+
block();
177+
else
178+
dispatch_async(moduleQueue, block);
179+
}
180+
181+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
182+
#pragma mark - XMPPStreamDelegate
183+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
184+
185+
- (BOOL)xmppStream:(XMPPStream *)stream didReceiveIQ:(XMPPIQ *)iq
186+
{
187+
NSString *type = [iq type];
188+
189+
if ([type isEqualToString:@"result"] || [type isEqualToString:@"error"]) {
190+
NSLog(@"invoking with iq: %@", iq);
191+
return [xmppIDTracker invokeForElement:iq withObject:iq];
192+
}
193+
194+
return NO;
195+
}
196+
197+
@end

0 commit comments

Comments
 (0)