iOS XMPP framework get all registered users - objective-c

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

Related

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.

Create chatroom with XMPP framework and Ejabberd in iOS

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?

uisearchbar in grouped section uitable

I've pieced together several tutorials to create a grouped table with sections and I'm now trying to get a uisearchbar to work. the problem I'm having is how to search within the grouped sections.
I've read the similar questions this post suggested but can't
This is the code to create the grouped sections
#import "Job.h" // A model for the data
#import "Address.h" // Another model for the data
- (void)viewDidLoad
{
[super viewDidLoad];
self.theTable.delegate = self;
self.theTable.dataSource =self;
_searchBar.delegate = (id)self;
FMDBDataAccess *db = [[FMDBDataAccess alloc] init];
jobs = [[NSMutableArray alloc] init];
jobs = [db getJobs:1];
_sections = [[NSMutableDictionary alloc] init];
NSMutableArray *jobsTempArray = [db getJobsAsDictionary:1];
BOOL found;
// Loop through the books and create our keys
for (NSDictionary *book in jobsTempArray)
{
NSString *cLong = [book objectForKey:#"addrAddress"];
NSString *c = [cLong substringToIndex:1];
found = NO;
for (NSString *str in [_sections allKeys])
{
if ([str isEqualToString:c])
{
found = YES;
}
}
if (!found)
{
[_sections setValue:[[NSMutableArray alloc] init] forKey:c];
}
}
// Loop again and sort the books into their respective keys
for (NSDictionary *book in jobsTempArray)
{
[[_sections objectForKey:[[book objectForKey:#"addrAddress"] substringToIndex:1]] addObject:book];
}
// Sort each section array
for (NSString *key in [_sections allKeys])
{
[[_sections objectForKey:key] sortUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"addrAddress" ascending:YES]]];
}
}
And this is the code that searches
-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text
{
if(text.length == 0)
{
_isFiltered = FALSE;
}
else
{
_isFiltered = true;
_filteredjobs = [[NSMutableArray alloc] init];
//for (Job* book in jobs)
//for (Job* book in [_sections allKeys])
//for (NSString *food in [_sections allKeys])
for (NSDictionary* book in [_sections allKeys])
{
NSString *addrStr = [book objectForKey:#"addrAddress"];
NSString *postStr = [book objectForKey:#"addrPostcode"];
//NSRange nameRange = [book.jobAddress rangeOfString:text options:NSCaseInsensitiveSearch];
NSRange nameRange = [addrStr rangeOfString:text options:NSCaseInsensitiveSearch];
//NSRange descriptionRange = [book.jobPostcode rangeOfString:text options:NSCaseInsensitiveSearch];
NSRange descriptionRange = [postStr rangeOfString:text options:NSCaseInsensitiveSearch];
if(nameRange.location != NSNotFound || descriptionRange.location != NSNotFound)
{
[_filteredjobs addObject:book];
}
}
}
[self.theTable reloadData];
}
I've got as far as realising I need to change for (Job* food in jobs) to for (NSDictionary* book in [_sections allKeys]) but I'm stuck how to search within [_sections allKeys]
Specifically this line
NSRange nameRange = [addrStr rangeOfString:text options:NSCaseInsensitiveSearch];
which crashes with
-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x692e200
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]:
unrecognized selector sent to instance 0x692e200':
Any ideas? PS Treat me as a noob, I'll need some code as well as explanation - I'm still learning obj-c
Check the Link.It shows the UISearchBar With Grouped Section Tableview.Its a simple Tutorial..Hope its useful for you
I found the answer in
UISearchBar - search a NSDictionary of Arrays of Objects and reading up on allkeys.
Basically loop through the grouped NSDictionary and extract the NSArrays, then loop through again searching...
-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text
{
if(text.length == 0)
{
_isFiltered = FALSE;
}
else
{
_isFiltered = true;
_filteredjobs = [[NSMutableArray alloc] init];
NSString *currentLetter = [[NSString alloc] init];
for (int i=0; i<[_sections count]; i++)
{
currentLetter = [[_sections allKeys] objectAtIndex:i];
NSArray *jobsForKey = [ [NSArray alloc] initWithArray:[_sections objectForKey:[[_sections allKeys] objectAtIndex:i]] ];
for (int j=0; j<[jobsForKey count]; j++)
{
NSDictionary *book = [jobsForKey objectAtIndex:j];
NSRange titleResultsRange = [[book objectForKey:#"addrAddress"] rangeOfString:text options:NSCaseInsensitiveSearch];
if(titleResultsRange.location != NSNotFound)
{
[_filteredjobs addObject:book];
}
}
}
}
[self.theTable reloadData];
}

assign value from NSDictionary to NSManagedObject

My app requires to get data from a .Net WCF service when the device is connected to WiFi.If there's a new row added on the server,it should add it to its CoreData database. I am using a NSDictionary for comparing the local objects with the remote objects. The code is:
-(void)handleGetAllCategories:(id)value
{
if([value isKindOfClass:[NSError class]])
{
NSLog(#"This is an error %#",value);
return;
}
if([value isKindOfClass:[SoapFault class]])
{
NSLog(#"this is a soap fault %#",value);
return;
}
NSMutableArray *result = (NSMutableArray*)value;
NSMutableArray *remoteObj = [[NSMutableArray alloc]init];
for (int i = 0; i < [result count]; i++)
{
EDVCategory *catObj = [[EDVCategory alloc]init];
catObj = [result objectAtIndex:i];
[remoteObj addObject:catObj];
}
NSArray *remoteIDs = [remoteObj valueForKey:#"categoryId"];
NSFetchRequest *request = [[[NSFetchRequest alloc] init]autorelease];
request.predicate = [NSPredicate predicateWithFormat:#"categoryId IN %#", remoteIDs];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Categories" inManagedObjectContext:__managedObjectContext];
[request setEntity:entity];
NSMutableArray *results = [[NSMutableArray alloc]initWithArray:[__managedObjectContext executeFetchRequest:request error:nil]];
NSArray *existingIDs = [results valueForKey:#"categoryId"];
NSDictionary *existingObjects = [NSDictionary dictionaryWithObjects:results forKeys:existingIDs];
for (NSDictionary *remoteObjectDic in remoteObj)
{
Categories *existingObject = [existingObjects objectForKey:[remoteObjectDic valueForKey:#"categoryId"]];
if (existingObject)
{
NSLog(#"object exists");
}
else
{
NSLog(#"create new local object");
// Categories *newCategory;
// newCategory = [NSEntityDescription insertNewObjectForEntityForName:#"Categories" inManagedObjectContext:__managedObjectContext];
// [newCategory setCategoryId:[NSNumber numberWithInt:[[remoteObjectDic objectForKey:#"categoryId"]intValue]]];
// [newCategory setCategoryName:[remoteObjectDic objectForKey:#"categoryName"]];
// [newCategory setDocCount:[NSNumber numberWithInt:[[remoteObjectDic objectForKey:#"docCount"]intValue]]];
// [newCategory setCategoryType:[NSNumber numberWithInt:[[remoteObjectDic objectForKey:#"categoryType"]intValue]]];
// [newCategory setSubCategoryId:[NSNumber numberWithInt:[[remoteObjectDic objectForKey:#"subCategoryId"]intValue]]];
// [__managedObjectContext insertObject:newCategory];
}
}
[my_table reloadData];
}
The problem is,I am not able to extract values from the remote object and assign it to the NSManagedObject.I have commented the code which (according to me) should save the values in new object to the managed object. Can someone please help me achieve this?
Thanks
Here is an example of a save I did in a recent project. I have somethings in wrappers so fetching a managed object and saving look a little weird on my end. Really the only major difference I see is the act of saving. Are you saving the new NSManagedObject elsewhere in the code?
dict = (NSDictionary*)data;
#try {
if (dict) {
CaretakerInfo* info = [GenericDataService makeObjectWithEntityName:NSStringFromClass([CaretakerInfo class])];
[info setName:[dict valueForKey:#"name"]];
[info setImageURL:[dict valueForKey:#"photo"]];
[info setCaretakerID:[dict valueForKey:#"id"]];
[GenericDataService save];
}
else {
theError = [Error createErrorMessage:#"No Data" Code:-42];
}
}
#catch (NSException *exception) {
//return an error if an exception
theError = [Error createErrorMessage:#"Exception Thrown While Parsing" Code:-42];
}
If not it should looks something like this...
NSError *error = nil;
[context save:&error];
If you have anymore information about what's happening when you extract or assigning data that would be helpful (error/warning/log messages).

Why are there no times in any of my GDataEntryCalendarEvent?

I am using a GDataServiceGoogleCalendar to anonymously fetch a GDataFeedCalendarEvent from a public url. But I am absolutely unable to retrieve times from any of the resulting GDataEntryCalendarEvent objects. I can read the title, so I believe the API works, but somehow the times arrays are lost somewhere.
The service is instantiated as follows:
- (GDataServiceGoogleCalendar *)calendarService {
static GDataServiceGoogleCalendar* service = nil;
if (!service) {
service = [[GDataServiceGoogleCalendar alloc] init];
[service setShouldCacheResponseData:YES];
[service setServiceShouldFollowNextLinks:YES];
[service setIsServiceRetryEnabled:YES];
}
return service;
}
This is the code where the data is retrieved:
for (GDataEntryCalendarEvent *event in eventEntries) {
NSString *title = [[event title] stringValue];
GDataDateTime *startTime = nil;
GDataDateTime *endTime = nil;
NSArray *times = [event times];
GDataWhen *when = nil;
if ([times count] > 0) {
when = [times objectAtIndex:0];
startTime = [when startTime];
endTime = [when endTime];
}
}
What is wrong with my code or the way I connect? The sample app retrieves the dates successfully.
I am sorry but I can not answer what is wrong with your code. I had problems with the date of the events, and that was my solution that works great for me:
Hope it will help you:
NSArray *events = [feed entries];
[events enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
GDataEntryEvent *entry = [events objectAtIndex:idx];
for (NSUInteger i=0; i<[[entry times] count]; i++) {
NSDate * startDate = [[[[entry times] objectAtIndex:i] startTime] date];
NSDate * endDate = [[[[entry times] objectAtIndex:i] endTime] date];
}
}];
There might be a better way but this works.
The Google API requires the use of an actual identified user even to access the public data.
So no access to most API call s is granted until an authenticated user account is being used.