Create chatroom with XMPP framework and Ejabberd in iOS - objective-c

Basically I'm trying to create a chatroom with all registered users on my domain using a ejabberd server. So a user can see all other online registered users on that domain when he enters the chatroom.
Until now I've only been able to make all the users 'friends / buddies' visible and deliver a notification when a friend goes online or offline with the help of the XMPP framework:
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {
// a buddy went offline/online
NSString *presenceType = [presence type]; // online/offline
NSString *myUsername = [[sender myJID] user];
NSString *presenceFromUser = [[presence from] user];
if (![presenceFromUser isEqualToString:myUsername]) {
if ([presenceType isEqualToString:#"available"]) {
[_chatDelegate newBuddyOnline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"chat.denederlandsewateren.nl"]];
} else if ([presenceType isEqualToString:#"unavailable"]) {
[_chatDelegate buddyWentOffline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"chat.denederlandsewateren.nl"]];
}
}
}
I'm able to get a list with all online registered users but I don't know how to notify the user when somebody goes online or offline.
- (void)getAllRegisteredUsers {
xmppRosterMemStorage = [[XMPPRosterMemoryStorage alloc] init];
xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterMemStorage
dispatchQueue:dispatch_get_main_queue()];
[xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = false;
xmppRoster.autoFetchRoster = true;
[xmppRoster activate:xmppStream];
[xmppRoster fetchRoster];
NSError *error = [[NSError alloc] init];
NSXMLElement *query = [[NSXMLElement alloc] initWithXMLString:#"<query xmlns='http://jabber.org/protocol/disco#items' node='all users'/>"
error:&error];
XMPPIQ *iq = [XMPPIQ iqWithType:#"get"
to:[XMPPJID jidWithString:#"chat.denederlandsewateren.nl"]
elementID:[xmppStream generateUUID] child:query];
[xmppStream sendElement:iq];
}
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
NSXMLElement *queryElement = [iq elementForName: #"query" xmlns:
#"http://jabber.org/protocol/disco#items"];
if (queryElement) {
NSArray *itemElements = [queryElement elementsForName: #"item"];
NSMutableArray *mArray = [[NSMutableArray alloc] init];
for (int i=0; i<[itemElements count]; i++) {
NSString *jid=[[[itemElements objectAtIndex:i] attributeForName:#"jid"] stringValue];
[mArray addObject:jid];
[xmppRoster addUser:[XMPPJID jidWithString:jid] withNickname:[[jid componentsSeparatedByString:#"#"] objectAtIndex:0]];
}
}
How can I create a chatroom where the user can see all online registered users on one domain using a Ejabberd server and the XMPP framework?

Related

CODE UPDATE: AWS Cognito user identitiy pool authorization? Objective -C

So I have been trying to figure this out and the documentation just isn't clear enough.
I am trying to use AWS cognito user pools and federated identity pools.
Online they say you can connect the two then authenticate users via your user pools to gain credentials from your identity pool. Right now I have them connected and it's showing up as an authorization method but I am unable to figure out what to do in objective-c to get it to work. I can only get unauthorized users into my Federated identity pool not authorized users.
I also have everything working on the user pools (creating and authenticating users) So it's just getting them into the Federated identity pool for permissions.
Could someone post a code example in objective-c on how to do it? Or walk me through the logical steps on how to do it?
I've been looking at these links:
http://mobile.awsblog.com/post/TxGNH1AUKDRZDH/Announcing-Your-User-Pools-in-Amazon-Cognito
How to combine Cognito User Pools with external providers like Facebook?
and just about every other aws link
An Update to the question here is some code:
I am able to sign up and verify a user however it does not register on the console in the user federated identity pool only unauthenticated. Is it a problem with my AWSServiceConfiguration? (Etc)
This is the sign up method we use to create a user
RCT_EXPORT_METHOD(submitUser: (NSString*) email and:
(NSString*) gender and:
(NSString*) name and:
(NSString*) nickname and:
(NSString*) picture and:
(NSString*) phone_number and:
(NSString*) preferred_username and:
(NSString*) hashedPass and:
(RCTResponseSenderBlock)callback){
AWSCognitoIdentityUserPool *pool = [AWSCognitoIdentityUserPool CognitoIdentityUserPoolForKey:#"UserPool"];
NSMutableArray * attributes = [NSMutableArray new];
AWSCognitoIdentityUserAttributeType * userEmail = [AWSCognitoIdentityUserAttributeType new];
userEmail.name = #"email";
userEmail.value = email;
AWSCognitoIdentityUserAttributeType * userGender = [AWSCognitoIdentityUserAttributeType new];
userGender.name = #"gender";
userGender.value = gender;
AWSCognitoIdentityUserAttributeType * userName = [AWSCognitoIdentityUserAttributeType new];
userName.name = #"name";
userName.value = name;
AWSCognitoIdentityUserAttributeType * userNickname = [AWSCognitoIdentityUserAttributeType new];
userNickname.name = #"nickname";
userNickname.value = nickname;
AWSCognitoIdentityUserAttributeType * userPicture = [AWSCognitoIdentityUserAttributeType new];
userPicture.name = #"picture";
userPicture.value = picture;
AWSCognitoIdentityUserAttributeType * userPhone = [AWSCognitoIdentityUserAttributeType new];
userPhone.name = #"phone_number";
userPhone.value = phone_number;
AWSCognitoIdentityUserAttributeType * userPreferredUsername = [AWSCognitoIdentityUserAttributeType new];
userPreferredUsername.name = #"preferred_username";
userPreferredUsername.value = preferred_username;
[attributes addObject:userEmail];
[attributes addObject:userGender];
[attributes addObject:userName];
[attributes addObject:userNickname];
[attributes addObject:userPicture];
[attributes addObject:userPhone];
[attributes addObject:userPreferredUsername];
NSMutableString *str = [NSMutableString string];
[str appendString:name];
[str appendString:name];
NSString *immutableString = str; // Change later to unique identifier
[[pool signUp:immutableString password:hashedPass userAttributes:attributes validationData:nil]
continueWithBlock:^id(AWSTask<AWSCognitoIdentityUser*> *task) {
if (task.error) {
RCTLog(#"Error: %#", task.error);
}
if (task.exception) {
RCTLog(#"Exception: %#", task.exception);
}
if (task.result) {
RCTLog(#"Successfully registered user: %#",task.result);
}
callback(#[[NSNull null],#NO]);
return nil;
}];
}
Verify User with emailed code method
RCT_EXPORT_METHOD(verifyUser:(nonnull NSString *)userName and:
(nonnull NSString *)code and:
(RCTResponseSenderBlock)callback) {
AWSCognitoIdentityUserPool *pool = [AWSCognitoIdentityUserPool CognitoIdentityUserPoolForKey:#"UserPool"];
AWSCognitoIdentityUser * user = [pool getUser:userName];
[[user confirmSignUp:code] continueWithBlock:^id(AWSTask<AWSCognitoIdentityProviderConfirmSignUpResponse*> *task) {
bool pass = NO;
if(task.error){
RCTLog(#"Error: %#", task.error);
}
else if(task.exception){
RCTLog(#"Exception: %#", task.exception);
}
else{
RCTLog(#"Successfully confirmed user: %#",user.username); pass = YES;
}
// Return TRUE If Succead
if(pass){
callback(#[[NSNull null],#YES]);
}
else{
callback(#[[NSNull null],#NO]);
}
return nil;
}];
}
In Appdelegate.m
AWSServiceConfiguration *serviceConfiguration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:nil];
AWSCognitoIdentityUserPoolConfiguration *configuration = [[AWSCognitoIdentityUserPoolConfiguration alloc]
initWithClientId:#"clientidhere"
clientSecret:#"clientsecrethere"
poolId:#"poolidhere"];
[AWSCognitoIdentityUserPool registerCognitoIdentityUserPoolWithConfiguration:serviceConfiguration userPoolConfiguration:configuration forKey:#"UserPool"];
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
initWithRegionType:AWSRegionUSEast1
identityPoolId:#"identitypoolIDhere"];
AWSServiceConfiguration *config = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = config;
[AWSSQS registerSQSWithConfiguration:config forKey:#"USWest2SQS"]; // Needed for sqs work throughout the app
I solved this issue by providing a CustomIdentityProvider
#interface CustomIdentityProvider : NSObject <AWSIdentityProviderManager>
#property (nonatomic, retain) NSDictionary *tokens;
- (AWSTask *) logins;
#end
#implementation CustomIdentityProvider
- (AWSTask *) logins {
AWSTask *task = nil;
if (nil != self.tokens) {
return [AWSTask taskWithResult:self.tokens];
}
return task;
}
#end
When you create your AWSCognitoCredentialsProvider you need to assign the identityProviderManager
self.identityProviderManager = [[CustomIdentityProvider alloc] init];
self.credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
initWithRegionType:AWSRegionUSEast1
identityPoolId:self.identityPoolId
identityProviderManager:self.identityProviderManager];
Once you have this set up, you need to populate the tokens NSDictionary. This is done after calling getSession and obtaining your AWSCognitoIdentityUserSession.
AWSCognitoIdentityUserSession *session; // Obtained from getSession
NSString *userPoolName = [NSString stringWithFormat:#"cognito-idp.us-east-1.amazonaws.com/%#", self.poolId];
NSDictionary *dict = #{userPoolName : session.idToken.tokenString};
self.customIdentityProvider.tokens = dict;
Assuming that you are generating your AWSAPIGatewayClient code via the SDKGeneration feature within API Gateway, you should be all set up for making your API Gateway calls as an authenticated user.
(PS. Don't forget to configure your Federated Identity to set your IAMS role for your Authenticated users to allow execute-api:Invoke.)

Create Chat room with XMPPFramework openfire

I'm working on a chat App where I have to add group chat
functionality using XMPP Framework . I'm able to setup
peer-to-peer chatting. But when it comes to group chat ,I'm unable
to create a chat room. I know, this question has been asked many
times before, but I could not find any solution from that answers.
Here's my code for creating and configuring a chat room.
- (void)createChatRoom:(NSString *) newRoomName
{
NSString *jid=[NSString stringWithFormat:#"%##%#",newRoomName,kGroupChatDomain];
XMPPRoomMemoryStorage * _roomMemory = [[XMPPRoomMemoryStorage alloc]init];
XMPPJID * roomJID = [XMPPJID jidWithString:jid];
_xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:_roomMemory
jid:roomJID
dispatchQueue:dispatch_get_main_queue()];
NSString *nickName=[NSString stringWithFormat:#"%#chatRoom",newRoomName];
[_xmppRoom joinRoomUsingNickname:nickName
history:nil
password:nil];
[_xmppRoom activate:[AppDel xmppStream]];
[_xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[_xmppRoom fetchConfigurationForm];
}
- (void)xmppRoomDidCreate:(XMPPRoom *)sender{
NSLog(#"didCreateChat Room method called");
}
- (void)xmppRoomDidJoin:(XMPPRoom *)sender{
NSLog(#"xmppRoomDidJoin method called ");
}
- (void)xmppRoom:(XMPPRoom *)sender didFetchConfigurationForm:(NSXMLElement *)configForm{
NSXMLElement *newConfig = [configForm copy];
NSArray* fields = [newConfig elementsForName:#"field"];
for (NSXMLElement *field in fields) {
NSString *var = [field attributeStringValueForName:#"var"];
if ([var isEqualToString:#"muc#roomconfig_persistentroom"]) {
[field removeChildAtIndex:0];
[field addChild:[NSXMLElement elementWithName:#"value" stringValue:#"1"]];
}
}
[sender configureRoomUsingOptions:newConfig];
}
Above is the code to create and configure the chat room. Before
calling this code, I'm connecting XMPP in viewDidLoad method. But
I'm unable to create a chat room. Code is not calling XMPPRoom
Delegate methods (xmppRoomDidCreate, xmppRoomDidJoin) I don't know
where I'm doing wrong, please correct me if there's any mistake in my
code. I could not even find any error in openfire logs. Please help me
resolving the issue. Any help will be appreciated.
Create room and if room already created you can easily join existing group using this code
- (void)createOrEnterRoom:(NSString *)groupName
{
BOOL flag=valueExistInGroup(groupName);
if (flag==TRUE) {
savevalueInGroup(groupName);
XMPPRoomMemoryStorage *roomStorage = [[XMPPRoomMemoryStorage alloc] init];
XMPPJID *roomJID = [XMPPJID jidWithString:[NSString stringWithFormat:#"%##conference.your_server_name",groupName]];
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:roomStorage
jid:roomJID
dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];
[xmppRoom addDelegate:self
delegateQueue:dispatch_get_main_queue()];
[xmppRoom joinRoomUsingNickname:xmppStream.myJID.user
history:nil
password:nil];
}
else
{
NSString *strJid=[AppSetting getUserId];
strJid=[strJid stringByAppendingFormat:#"#your_server_name"];
_xmppRoomStorage = [XMPPRoomHybridStorage sharedInstance];
XMPPJID *roomJid = [XMPPJID jidWithString:[NSString stringWithFormat:#"%##conference.52.10.97.23",groupName]];
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:_xmppRoomStorage jid:roomJid];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];
NSXMLElement *history = [NSXMLElement elementWithName:#"history"];
[history addAttributeWithName:#"maxstanzas" stringValue:#"10"];
[xmppRoom joinRoomUsingNickname:strJid history:nil];
}
}
- (void)xmppRoomDidJoin:(XMPPRoom *)sender{
[sender fetchConfigurationForm];
}
- (void)fetchConfigurationForm
{
dispatch_block_t block = ^{ #autoreleasepool {
XMPPLogTrace();
// <iq type='get'
// id='config1'
// to='coven#chat.shakespeare.lit'>
// <query xmlns='http://jabber.org/protocol/muc#owner'/>
// </iq>
NSString *fetchID = [xmppStream generateUUID];
NSXMLElement *query = [NSXMLElement elementWithName:#"query" xmlns:XMPPMUCOwnerNamespace];
XMPPIQ *iq = [XMPPIQ iqWithType:#"get" to:roomJID elementID:fetchID child:query];
[xmppStream sendElement:iq];
[responseTracker addID:fetchID
target:self
selector:#selector(handleConfigurationFormResponse:withInfo:)
timeout:60.0];
}};
if (dispatch_get_specific(moduleQueueTag))
block();
else
dispatch_async(moduleQueue, block);
}

MCOIMAPIdleOperation Issue

I am totally new in IOS Development, And I am making a app using MailCore2 api.
Company has told me to use MCOIMApIdleOperation to get the emails from Gmail Server.
I have google all the way to find out solution about this but it is not worth it.
Here is detail about the Problem,
First I want to load the emails from the INBOX folder through MCOIMAPIdleOperation.Below is my code for fetching emails.
- (void)viewDidLoad{
[super viewDidLoad];
//Do any additional setup after loading the view from its nib.
//Made connection with Gmail Imap Server
NSUserDefaults *defaules = [NSUserDefaults standardUserDefaults];
NSString *emailid = [defaules objectForKey:#"emailid" ];
NSString *password = [defaules objectForKey:#"password" ];
session = [[MCOIMAPSession alloc] init];
session.hostname = #"imap.gmail.com";
session.port = 993;
session.username = emailid;
session.password = password;
session.connectionType = MCOConnectionTypeTLS;
idle=[session idleOperationWithFolder:#"INBOX" lastKnownUID:0];
[idle start:^(NSError *err){
MCOIMAPMessagesRequestKind requestKind = (MCOIMAPMessagesRequestKind)
(MCOIMAPMessagesRequestKindHeaders | MCOIMAPMessagesRequestKindStructure |MCOIMAPMessagesRequestKindInternalDate | MCOIMAPMessagesRequestKindHeaderSubject |MCOIMAPMessagesRequestKindFlags);
MCOIMAPFolderInfoOperation *inboxFolderInfo = [session folderInfoOperation:Folder];
NSLog(#"statrt1");
[inboxFolderInfo start:^(NSError *error, MCOIMAPFolderInfo *info)
{
NSLog(#"start2");
BOOL totalNumberOfMessagesDidChange =
self.totalNumberOfInboxMessages != [info messageCount];
self.totalNumberOfInboxMessages = [info messageCount];
NSUInteger numberOfMessagesToLoad =MIN(self.totalNumberOfInboxMessages, nMessages);
if (numberOfMessagesToLoad == 0)
{
self.isLoading = NO;
return;
}
// If total number of messages did not change since last fetch,
// assume nothing was deleted since our last fetch and just
// fetch what we don't have
MCORange fetchRange;
if (!totalNumberOfMessagesDidChange && msgbody.count)
{
numberOfMessagesToLoad -= msgbody.count;
fetchRange = MCORangeMake(self.totalNumberOfInboxMessages -msgbody.count -(numberOfMessagesToLoad - 1),(numberOfMessagesToLoad - 1));
}
// Else just fetch the last N messages
else
{
fetchRange =MCORangeMake(self.totalNumberOfInboxMessages -(numberOfMessagesToLoad - 1),(numberOfMessagesToLoad - 1));
}
MCOIMAPFetchMessagesOperation *imapMessagesFetchOp =[session fetchMessagesByNumberOperationWithFolder:Folder requestKind:requestKind numbers:
[MCOIndexSet indexSetWithRange:fetchRange]];
[imapMessagesFetchOp start:^(NSError *error, NSArray *messages, MCOIndexSet *vanishedMessages)
{
NSSortDescriptor *sort =[NSSortDescriptor sortDescriptorWithKey:#"header.date" ascending:NO];
NSMutableArray *combinedMessages = [NSMutableArray arrayWithArray:messages];
[combinedMessages removeAllObjects];
[combinedMessages addObjectsFromArray:messages];
msgbody=[combinedMessages sortedArrayUsingDescriptors:#[sort]];
[uitable reloadData];
}];
}];
}];
}
By Above code mails are fetched successfully.Problem is when new mail is arrive above code is not running again.what to do so that i can get the new mails when they arrive..
Please help me to solve this issue.

iOS XMPP framework get all registered users

In my chat application I want to get all online registered users. So everybody and not only people in my roster which is achieved with this code:
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {
// a buddy went offline/online
NSString *presenceType = [presence type]; // online/offline
NSString *myUsername = [[sender myJID] user];
NSString *presenceFromUser = [[presence from] user];
if (![presenceFromUser isEqualToString:myUsername]) {
if ([presenceType isEqualToString:#"available"]) {
[_chatDelegate newBuddyOnline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"chat.denederlandsewateren.nl"]];
} else if ([presenceType isEqualToString:#"unavailable"]) {
[_chatDelegate buddyWentOffline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"chat.denederlandsewateren.nl"]];
}
}
}
With this code the users only sees other users who are 'friends' but I need all users registered on this particular domain. Is this possible with ejabberd?
- (void)getAllRegisteredUsers {
NSError *error = [[NSError alloc] init];
NSXMLElement *query = [[NSXMLElement alloc] initWithXMLString:#"<query xmlns='http://jabber.org/protocol/disco#items' node='all users'/>"
error:&error];
XMPPIQ *iq = [XMPPIQ iqWithType:#"get"
to:[XMPPJID jidWithString:#"DOMAIN"]
elementID:[xmppStream generateUUID] child:query];
[xmppStream sendElement:iq];
}
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
NSXMLElement *queryElement = [iq elementForName: #"query" xmlns: #"http://jabber.org/protocol/disco#items"];
if (queryElement) {
NSArray *itemElements = [queryElement elementsForName: #"item"];
NSMutableArray *mArray = [[NSMutableArray alloc] init];
for (int i=0; i<[itemElements count]; i++) {
NSString *jid=[[[itemElements objectAtIndex:i] attributeForName:#"jid"] stringValue];
[mArray addObject:jid];
}
}
I had the same issue, I got queryElement as nil as well. I've changed the response code to see the XML like this:
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
//DDLogVerbose(#"%#: %# - %#", THIS_FILE, THIS_METHOD, [iq elementID]);
//NSXMLElement *queryElement = [iq elementForName:#"query" xmlns: #"http://jabber.org/protocol/disco#items"];
NSXMLElement *queryElement = [iq elementForName:#"query" xmlns: #"jabber:iq:roster"];
NSLog(#"IQ: %#",iq);
if (queryElement) {
NSArray *itemElements = [queryElement elementsForName: #"item"];
NSMutableArray *mArray = [[NSMutableArray alloc] init];
for (int i=0; i<[itemElements count]; i++) {
NSString *jid=[[[itemElements objectAtIndex:i] attributeForName:#"jid"] stringValue];
NSLog(#"%#",jid);
[mArray addObject:jid];
}
}
return NO;
}
As you may see what I've changed is the xmlns: from this xmlns: #"http://jabber.org/protocol/disco#items" to this xmlns: #"jabber:iq:roster" and that gave me the list of users.
I'm using ejabberd, not sure if this works for all the others XMPP servers.
Also I've found that this gave me the list of the "buddy" users, looks like if you want "all" users you need to make the query as an admin user. Please check this link for more information about it: https://www.ejabberd.im/node/3420
After googling, You can not get all user easily, You must need to create Shared Roster Groups by follow step in the Example 1: everybody can see everybody else after done this you will get all the online users in the below delegate methods.
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence

Is there quick way to check user access using ALAssetsLibrary?

I think this is a really bad way to check user access to the resources.
Is there better way to get user access?
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// create library
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
accessGiven = YES;
return ;
};
void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) {
accessGiven = NO;
return;
};
// create 2 blocks
NSURL *url = [[NSURL alloc] initWithString:#" "];
[library assetForURL:url resultBlock:resultblock failureBlock:assetGroupEnumberatorFailure];
// use empty url to check acces..
[library release];
iOS 6.0 has better way to do that.
[ALAssetsLibrary authorizationStatus];
Method Description
Authorization Status Enum