- Update
This commit is contained in:
1 parent
d281d765ea
commit
5b074a5176
1261 files changed
+199158
-7303
No files matched your search
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// Created by Jonathon Staff on 10/11/14.
|
||||
// Copyright (c) 2014 Jonathon Staff. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "XMPPModule.h"
|
||||
|
||||
@class XMPPIDTracker;
|
||||
|
||||
#define _XMPP_REGISTRATION_H
|
||||
|
||||
@interface XMPPRegistration : XMPPModule {
|
||||
XMPPIDTracker *xmppIDTracker;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will attempt to change the current user's password to the new one provided. The
|
||||
* user *MUST* be authenticated for this to work successfully.
|
||||
*
|
||||
* @see passwordChangeSuccessful:
|
||||
* @see passwordChangeFailed:withError:
|
||||
*
|
||||
* @param newPassword The new password for the user
|
||||
*/
|
||||
- (BOOL)changePassword:(NSString *)newPassword;
|
||||
|
||||
/**
|
||||
* This method will attempt to cancel the current user's registration. Later implementations
|
||||
* will provide support for handling authentication challenges by the server. For now,
|
||||
* simply pass a value of 'nil' in for password, or preferably, use the other cancellation
|
||||
* method.
|
||||
*
|
||||
* @see cancelRegistration
|
||||
*/
|
||||
- (BOOL)cancelRegistrationUsingPassword:(NSString *)password;
|
||||
|
||||
/**
|
||||
* This method will attempt to cancel the current user's registration. The user *MUST* be
|
||||
* already authenticated for this to work successfully.
|
||||
*
|
||||
* @see cancelRegistrationSuccessful:
|
||||
* @see cancelRegistrationFailed:withError:
|
||||
*/
|
||||
- (BOOL)cancelRegistration;
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark - XMPPRegistrationDelegate
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@protocol XMPPRegistrationDelegate
|
||||
@optional
|
||||
|
||||
/**
|
||||
* Implement this method when calling [regInstance changePassword:]. It will be invoked
|
||||
* if the request for changing the user's password is successfully executed and receives a
|
||||
* successful response.
|
||||
*
|
||||
* @param sender XMPPRegistration object invoking this delegate method.
|
||||
*/
|
||||
- (void)passwordChangeSuccessful:(XMPPRegistration *)sender;
|
||||
|
||||
/**
|
||||
* Implement this method when calling [regInstance changePassword:]. It will be invoked
|
||||
* if the request for changing the user's password is unsuccessfully executed or receives
|
||||
* an unsuccessful response.
|
||||
*
|
||||
* @param sender XMPPRegistration object invoking this delegate method.
|
||||
* @param error NSError containing more details of the failure.
|
||||
*/
|
||||
- (void)passwordChangeFailed:(XMPPRegistration *)sender withError:(NSError *)error;
|
||||
|
||||
/**
|
||||
* Implement this method when calling [regInstance cancelRegistration] or a variation. It
|
||||
* is invoked if the request for canceling the user's registration is successfully
|
||||
* executed and receives a successful response.
|
||||
*
|
||||
* @param sender XMPPRegistration object invoking this delegate method.
|
||||
*/
|
||||
- (void)cancelRegistrationSuccessful:(XMPPRegistration *)sender;
|
||||
|
||||
/**
|
||||
* Implement this method when calling [regInstance cancelRegistration] or a variation. It
|
||||
* is invoked if the request for canceling the user's registration is unsuccessfully
|
||||
* executed or receives an unsuccessful response.
|
||||
*
|
||||
* @param sender XMPPRegistration object invoking this delegate method.
|
||||
* @param error NSError containing more details of the failure.
|
||||
*/
|
||||
- (void)cancelRegistrationFailed:(XMPPRegistration *)sender withError:(NSError *)error;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,237 @@
|
||||
//
|
||||
// Created by Jonathon Staff on 10/11/14.
|
||||
// Copyright (c) 2014 Jonathon Staff. All rights reserved.
|
||||
//
|
||||
|
||||
#import "XMPPRegistration.h"
|
||||
#import "XMPPStream.h"
|
||||
#import "XMPPIDTracker.h"
|
||||
#import "XMPPIQ.h"
|
||||
#import "NSXMLElement+XMPP.h"
|
||||
|
||||
NSString *const XMPPRegistrationErrorDomain = @"XMPPRegistrationErrorDomain";
|
||||
|
||||
@implementation XMPPRegistration
|
||||
|
||||
- (void)didActivate
|
||||
{
|
||||
xmppIDTracker = [[XMPPIDTracker alloc] initWithStream:xmppStream dispatchQueue:moduleQueue];
|
||||
}
|
||||
|
||||
- (void)willDeactivate
|
||||
{
|
||||
[xmppIDTracker removeAllIDs];
|
||||
xmppIDTracker = nil;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark Public API
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* This method provides functionality of XEP-0077 3.3 User Changes Password.
|
||||
*
|
||||
* @link {http://xmpp.org/extensions/xep-0077.html#usecases-changepw}
|
||||
*
|
||||
* Example 18. Password Change
|
||||
*
|
||||
* <iq type='set' to='shakespeare.lit' id='change1'>
|
||||
* <query xmlns='jabber:iq:register'>
|
||||
* <username>bill</username>
|
||||
* <password>newpass</password>
|
||||
* </query>
|
||||
* </iq>
|
||||
*
|
||||
*/
|
||||
- (BOOL)changePassword:(NSString *)newPassword
|
||||
{
|
||||
if (![xmppStream isAuthenticated])
|
||||
return NO; // You must be authenticated in order to change your password
|
||||
|
||||
dispatch_block_t block = ^{
|
||||
@autoreleasepool {
|
||||
NSString *toStr = xmppStream.myJID.domain;
|
||||
NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"jabber:iq:register"];
|
||||
|
||||
NSXMLElement *username = [NSXMLElement elementWithName:@"username"
|
||||
stringValue:xmppStream.myJID.user];
|
||||
NSXMLElement *password = [NSXMLElement elementWithName:@"password"
|
||||
stringValue:newPassword];
|
||||
[query addChild:username];
|
||||
[query addChild:password];
|
||||
|
||||
XMPPIQ *iq = [XMPPIQ iqWithType:@"set"
|
||||
to:[XMPPJID jidWithString:toStr]
|
||||
elementID:[xmppStream generateUUID]
|
||||
child:query];
|
||||
|
||||
[xmppIDTracker addID:[iq elementID]
|
||||
target:self
|
||||
selector:@selector(handlePasswordChangeQueryIQ:withInfo:)
|
||||
timeout:60];
|
||||
|
||||
[xmppStream sendElement:iq];
|
||||
}
|
||||
};
|
||||
|
||||
if (dispatch_get_specific(moduleQueueTag))
|
||||
block();
|
||||
else
|
||||
dispatch_async(moduleQueue, block);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method provides functionality of XEP-0077 3.2 Entity Cancels an Existing Registration.
|
||||
*
|
||||
* @link {http://xmpp.org/extensions/xep-0077.html#usecases-cancel}
|
||||
*
|
||||
* <iq type='set' from='bill@shakespeare.lit/globe' id='unreg1'>
|
||||
* <query xmlns='jabber:iq:register'>
|
||||
* <remove/>
|
||||
* </query>
|
||||
* </iq>
|
||||
*
|
||||
*/
|
||||
- (BOOL)cancelRegistration
|
||||
{
|
||||
return [self cancelRegistrationUsingPassword:nil];
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as cancelRegistration. Handling authentication challenges is not yet implemented.
|
||||
*/
|
||||
- (BOOL)cancelRegistrationUsingPassword:(NSString *)password
|
||||
{
|
||||
// TODO: Handle the scenario of using password
|
||||
|
||||
dispatch_block_t block = ^{
|
||||
@autoreleasepool {
|
||||
|
||||
NSXMLElement *remove = [NSXMLElement elementWithName:@"remove"];
|
||||
NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"jabber:iq:register"];
|
||||
[query addChild:remove];
|
||||
XMPPIQ *iq = [XMPPIQ iqWithType:@"set"
|
||||
elementID:[xmppStream generateUUID]
|
||||
child:query];
|
||||
|
||||
[xmppIDTracker addElement:iq
|
||||
target:self
|
||||
selector:@selector(handleRegistrationCancelQueryIQ:withInfo:)
|
||||
timeout:60];
|
||||
|
||||
[xmppStream sendElement:iq];
|
||||
}
|
||||
};
|
||||
|
||||
if (dispatch_get_specific(moduleQueueTag))
|
||||
block();
|
||||
else
|
||||
dispatch_async(moduleQueue, block);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark - XMPPIDTracker
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* This method handles the response received (or not received) after calling changePassword.
|
||||
*/
|
||||
- (void)handlePasswordChangeQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info
|
||||
{
|
||||
dispatch_block_t block = ^{
|
||||
@autoreleasepool {
|
||||
NSXMLElement *errorElem = [iq elementForName:@"error"];
|
||||
|
||||
if (errorElem) {
|
||||
NSString *errMsg = [[errorElem children] componentsJoinedByString:@", "];
|
||||
NSInteger errCode = [errorElem attributeIntegerValueForName:@"code"
|
||||
withDefaultValue:-1];
|
||||
NSDictionary *errInfo = @{NSLocalizedDescriptionKey : errMsg};
|
||||
NSError *err = [NSError errorWithDomain:XMPPRegistrationErrorDomain
|
||||
code:errCode
|
||||
userInfo:errInfo];
|
||||
|
||||
[multicastDelegate passwordChangeFailed:self
|
||||
withError:err];
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *type = [iq type];
|
||||
|
||||
if ([type isEqualToString:@"result"]) {
|
||||
[multicastDelegate passwordChangeSuccessful:self];
|
||||
} else {
|
||||
// this should be impossible to reach, but just for safety's sake...
|
||||
[multicastDelegate passwordChangeFailed:self
|
||||
withError:nil];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (dispatch_get_specific(moduleQueueTag))
|
||||
block();
|
||||
else
|
||||
dispatch_async(moduleQueue, block);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method handles the response received (or not received) after calling cancelRegistration.
|
||||
*/
|
||||
- (void)handleRegistrationCancelQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info
|
||||
{
|
||||
dispatch_block_t block = ^{
|
||||
@autoreleasepool {
|
||||
NSXMLElement *errorElem = [iq elementForName:@"error"];
|
||||
|
||||
if (errorElem) {
|
||||
NSString *errMsg = [[errorElem children] componentsJoinedByString:@", "];
|
||||
NSInteger errCode = [errorElem attributeIntegerValueForName:@"code"
|
||||
withDefaultValue:-1];
|
||||
NSDictionary *errInfo = @{NSLocalizedDescriptionKey : errMsg};
|
||||
NSError *err = [NSError errorWithDomain:XMPPRegistrationErrorDomain
|
||||
code:errCode
|
||||
userInfo:errInfo];
|
||||
|
||||
[multicastDelegate cancelRegistrationFailed:self
|
||||
withError:err];
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *type = [iq type];
|
||||
|
||||
if ([type isEqualToString:@"result"]) {
|
||||
[multicastDelegate cancelRegistrationSuccessful:self];
|
||||
} else {
|
||||
// this should be impossible to reach, but just for safety's sake...
|
||||
[multicastDelegate cancelRegistrationFailed:self
|
||||
withError:nil];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (dispatch_get_specific(moduleQueueTag))
|
||||
block();
|
||||
else
|
||||
dispatch_async(moduleQueue, block);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark - XMPPStreamDelegate
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
- (BOOL)xmppStream:(XMPPStream *)stream didReceiveIQ:(XMPPIQ *)iq
|
||||
{
|
||||
NSString *type = [iq type];
|
||||
|
||||
if ([type isEqualToString:@"result"] || [type isEqualToString:@"error"]) {
|
||||
return [xmppIDTracker invokeForElement:iq withObject:iq];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in new issue
Block a user