I am working on the chat application. I want to block friend. I am using XEP-0016 extensions of xmpp framework.
Here is my code..
- (void)setupXMPPPrivacy
{
NSLog((#"%s [Line %d] "), __PRETTY_FUNCTION__, __LINE__);
//Init XMPPPrivacy List
//xmppPrivacy = [[XMPPPrivacy alloc] init];
xmppPrivacy = [[XMPPPrivacy alloc] initWithDispatchQueue:dispatch_get_main_queue()];
//Activate xmpp modules
[xmppPrivacy activate:xmppStream];
//Delegate XMPPPrivacy
[xmppPrivacy addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
- (void)privacyBlock:(XMPPJID *)jid
{
NSXMLElement *privacyElement = [XMPPPrivacy privacyItemWithType:#"jid" value:jid.bare action:#"deny" order:1];
[XMPPPrivacy blockIQs:privacyElement];
[XMPPPrivacy blockMessages:privacyElement];
[XMPPPrivacy blockPresenceIn:privacyElement];
[XMPPPrivacy blockPresenceOut:privacyElement];
NSLog(#"-------> PRIVACY ELEMENT: %#", privacyElement);
NSArray *arrayPrivacy = [[NSArray alloc] initWithObjects:privacyElement, nil];
[xmppPrivacy setListWithName:#"public" items:arrayPrivacy];
}
But, this is not working. What am I doing wrong?
Help please. Thanks.
I had the same trouble. First problem was UUID generator, it returned nil. But in iOS 5 added NSUUID class. So using [[NSUUID UUID] UUIDString] I solved this problem. Second problem was my big mistake. I initialized xmmpStram and did request to block, but opening stream takes some time.So, I requested before opening a stream.
Related
Trying to create a very simple proof of concept iOS xmpp app with the robbiehanson xmpp frame work, just need to be able to send and receive messages and roster data. I can authenticate and send messages successfully, but when users attempt to respond to my messages I do not receive them. I have implemented the didReceiveMessage delegate method as follows:
-(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
NSLog(#"incoming message: %#", message);
}
but I never receive this log. If I log in with the existing web app or android app that communicates with this xmpp server I receive these messages, so I'm inclined to believe they are formatted properly. Is there a module I need to add to the XMPPStream for receiving messages? I'm setting up the stream like this (some of the string values have been changed for security and what not):
stream = [[XMPPStream alloc] init];
stream.enableBackgroundingOnSocket = YES;
stream.hostName = #"hostname.com";
stream.hostPort = 5222;
XMPPRosterCoreDataStorage* xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] initWithInMemoryStore];
XMPPRoster* xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterStorage];
xmppRoster.autoFetchRoster = YES;
xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = YES;
[stream addDelegate:self delegateQueue:dispatch_get_main_queue()];
XMPPJID* jid = [XMPPJID jidWithUser:#"username" domain:#"domain.com" resource:#"iOS"];
[stream setMyJID:jid];
[xmppRoster activate:stream];
[stream connectWithTimeout:XMPPStreamTimeoutNone error:&error]
and then in the xmppStreamDidConnect method I do this to authenticate
NSString *myPassword = #"password";
NSError *error = nil;
[stream authenticateWithPassword:myPassword error:&error]
When I am sending a message out I use this snippet:
MPPJID* recipient = [XMPPJID jidWithString:#"user#domain.com"];
XMPPMessage* message = [[XMPPMessage alloc] initWithType:#"chat" to:recipient];
[message addBody:#"hello world"];
[stream sendElement: message];
I'm thinking there is something simple I am missing that someone who has used this before will be able to point out to me right away. I'm ready to supply other info if necessary for solving this issue.
I simply needed to broadcast my presence, then I was able to receive messages.
I added these lines to the streamDidAuthenticate method
XMPPPresence *presence = [XMPPPresence presence];
[sender sendElement:presence];
In my delegate.m
- (void)setupStream
{
NSAssert(xmppStream == nil, #"Method setupStream invoked multiple times");
customCertEvaluation = YES;
// allowSelfSignedCertificates = YES;
// allowSSLHostNameMismatch = NO; // Setup xmpp stream
//
// The XMPPStream is the base class for all activity.
// Everything else plugs into the xmppStream, such as modules/extensions and delegates.
xmppStream = [[XMPPStream alloc] init];
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
#if !TARGET_IPHONE_SIMULATOR
{
// Want xmpp to run in the background?
//
// P.S. - The simulator doesn't support backgrounding yet.
// When you try to set the associated property on the simulator, it simply fails.
// And when you background an app on the simulator,
// it just queues network traffic til the app is foregrounded again.
// We are patiently waiting for a fix from Apple.
// If you do enableBackgroundingOnSocket on the simulator,
// you will simply see an error message from the xmpp stack when it fails to set the property.
xmppStream.enableBackgroundingOnSocket = YES;
}
#endif
// Setup reconnect
//
// The XMPPReconnect module monitors for "accidental disconnections" and
// automatically reconnects the stream for you.
// There's a bunch more information in the XMPPReconnect header file.
xmppReconnect = [[XMPPReconnect alloc] init];
// XMPPAutoPing *xmppAutoPing = [[XMPPAutoPing alloc] initWithDispatchQueue:dispatch_get_main_queue()];
//xmppAutoPing.pingInterval = 25.f; // default is 60
//xmppAutoPing.pingTimeout = 10.f; // default is 10
//[xmppAutoPing addDelegate:self delegateQueue:dispatch_get_main_queue()];
//[xmppAutoPing activate:self.xmppStream];
// Setup roster
//
// The XMPPRoster handles the xmpp protocol stuff related to the roster.
// The storage for the roster is abstracted.
// So you can use any storage mechanism you want.
// You can store it all in memory, or use core data and store it on disk, or use core data with an in-memory store,
// or setup your own using raw SQLite, or create your own storage mechanism.
// You can do it however you like! It's your application.
// But you do need to provide the roster with some storage facility.
xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] initWithInMemoryStore];
xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterStorage];
xmppRoster.autoFetchRoster = YES;
xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = YES;
// Setup vCard support
//
// The vCard Avatar module works in conjuction with the standard vCard Temp module to download user avatars.
// The XMPPRoster will automatically integrate with XMPPvCardAvatarModule to cache roster photos in the roster.
xmppvCardStorage = [XMPPvCardCoreDataStorage sharedInstance];
xmppvCardTempModule = [[XMPPvCardTempModule alloc] initWithvCardStorage:xmppvCardStorage];
xmppvCardAvatarModule = [[XMPPvCardAvatarModule alloc] initWithvCardTempModule:xmppvCardTempModule];
// Setup capabilities
//
// The XMPPCapabilities module handles all the complex hashing of the caps protocol (XEP-0115).
// Basically, when other clients broadcast their presence on the network
// they include information about what capabilities their client supports (audio, video, file transfer, etc).
// But as you can imagine, this list starts to get pretty big.
// This is where the hashing stuff comes into play.
// Most people running the same version of the same client are going to have the same list of capabilities.
// So the protocol defines a standardized way to hash the list of capabilities.
// Clients then broadcast the tiny hash instead of the big list.
// The XMPPCapabilities protocol automatically handles figuring out what these hashes mean,
// and also persistently storing the hashes so lookups aren't needed in the future.
//
// Similarly to the roster, the storage of the module is abstracted.
// You are strongly encouraged to persist caps information across sessions.
//
// The XMPPCapabilitiesCoreDataStorage is an ideal solution.
// It can also be shared amongst multiple streams to further reduce hash lookups.
xmppCapabilitiesStorage = [XMPPCapabilitiesCoreDataStorage sharedInstance];
xmppCapabilities = [[XMPPCapabilities alloc] initWithCapabilitiesStorage:xmppCapabilitiesStorage];
xmppCapabilities.autoFetchHashedCapabilities = YES;
xmppCapabilities.autoFetchNonHashedCapabilities = NO;
// Activate xmpp modules
[xmppReconnect activate:xmppStream];
[xmppRoster activate:xmppStream];
[xmppvCardTempModule activate:xmppStream];
[xmppvCardAvatarModule activate:xmppStream];
[xmppCapabilities activate:xmppStream];
// Add ourself as a delegate to anything we may be interested in
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
// Optional:
//
// Replace me with the proper domain and port.
// The example below is setup for a typical google talk account.
//
// If you don't supply a hostName, then it will be automatically resolved using the JID (below).
// For example, if you supply a JID like 'user#quack.com/rsrc'
// then the xmpp framework will follow the xmpp specification, and do a SRV lookup for quack.com.
//
// If you don't specify a hostPort, then the default (5222) will be used.
[xmppStream setHostName:#"10.10.1.77"];
[xmppStream setHostPort:5222];
// You may need to alter these settings depending on the server you're connecting to
// allowSelfSignedCertificates = YES;
// allowSSLHostNameMismatch = NO;
customCertEvaluation = YES;
}
and also
- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
{
DDLogVerbose(#"%#: %#", THIS_FILE, THIS_METHOD);
NSString *expectedCertName = [xmppStream.myJID domain];
if (expectedCertName)
{
[settings setObject:expectedCertName forKey:(NSString *)kCFStreamSSLPeerName];
}
if (customCertEvaluation)
[settings setObject:#(YES) forKey:GCDAsyncSocketManuallyEvaluateTrust];
}
- (void)xmppStream:(XMPPStream *)sender didReceiveTrust:(SecTrustRef)trust
completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler
{
/*DDLogVerbose(#"%#: %#", THIS_FILE, THIS_METHOD);
// The delegate method should likely have code similar to this,
// but will presumably perform some extra security code stuff.
// For example, allowing a specific self-signed certificate that is known to the app.
allowSelfSignedCertificates = YES;
allowSSLHostNameMismatch = NO;
dispatch_queue_t bgQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(bgQueue, ^{
SecTrustResultType result = kSecTrustResultDeny;
OSStatus status = SecTrustEvaluate(trust, &result);
if (status == noErr && (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified)) {
completionHandler(YES);
}
else {
completionHandler(NO);
}
});
*/
completionHandler(YES);
}
I have done everything that was suggested in code but still connecting to server using SSL port gives error
2014-07-18 18:08:14:724 iPhoneXMPP[20593:60b] iPhoneXMPPAppDelegate: xmppStream:socketDidConnect:
2014-07-18 18:08:14:724 iPhoneXMPP[20593:60b] iPhoneXMPPAppDelegate: xmppStream:socketDidConnect:
2014-07-18 18:08:14:925 iPhoneXMPP[20593:60b] iPhoneXMPPAppDelegate: xmppStreamDidDisconnect:withError:
2014-07-18 18:08:14.925 iPhoneXMPP[20593:60b] Unable to connect to server
2014-07-18 18:08:14:926 iPhoneXMPP[20593:60b] Unable to connect to server. Check xmppStream.hostName
How am i supposed to solve to this error; Connection to normal port is fine though.Connection to SSL port is the only problem.
I finally can use SSL in 5223 port. I have to force use startTLS on didConnectToHost on XMPPStream.m. I don't know why isSecure always says NO.
Use the following method to enable the SSL/TLS. However this method is not defined theXMPPStream.h class, you need to define it here and access it from appdelegate or inside setupsteam method.
-(void)setIsSecure:(BOOL)flag
My app displays a short list of tweets based on a given TV hashtag with the additional ability to post a tweet.
But now twitter has gone oauth for all requests, my tweet list doesnt appear as it was using the old search.atom API.
Therefore, how do I access the search api and pass in OAuth credentials using Sharekit so user authenticates just the once for viewing tweets and posting between sessions.
I have tried using SHKRequest, hoping, that as ShareKit has already authorised it will pass this information through; with no joy, is there some other way of doing this or am I just using it badly/wrong.
request = [[[SHKRequest alloc] initWithURL:[NSURL URLWithString:#"https://api.twitter.com/1.1/search/tweets.json?q=twitter&result_type=recent"]
delegate:self
isFinishedSelector:#selector(sendFinishedSearch:)
params:nil
method:#"GET"
autostart:YES] autorelease];
I do need to maintain compatibility with 4.3 API so I cant just use iOS5 Twitter API.
Disclaimer: I am inheriting project from someone so my XCode/ObjC knowledge is being learnt whilst I modify project (I come from C/C++ background), so please ignore my ignorance.
ShareKit contains an SHKTwitter class. It is a subclass of SHKOAuthSharer. As such, you can ask it to perform authorisations / refreshes and get the resulting token.
Create an instance of SHKTwitter and register as it's delegate. Implement the - (void)sharerAuthDidFinish:(SHKSharer *)sharer success:(BOOL)success delegate method. Then call tokenRequest. When the delegate method is called, if success is YES you can get the accessToken.
SHKTwitter *twitter = [[SHKTwitter alloc] init];
twitter.shareDelegate = self;
[twitter tokenRequest];
- (void)sharerAuthDidFinish:(SHKSharer *)sharer success:(BOOL)success
{
SHKTwitter *twitter = (SHKTwitter *)sharer;
if (twitter.accessToken != nil) {
NSLog(#"session: %#, %#", twitterSharer.accessToken.key, twitterSharer.accessToken.secret);
} else {
[twitter tokenAccess];
}
}
IN SHKOAuthSharer.m class You will get access Token in method:
- (void)tokenAccessTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data
{
if (SHKDebugShowLogs) // check so we don't have to alloc the string with the data if we aren't logging
SHKLog(#"tokenAccessTicket Response Body: %#", [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);
///[[SHKActivityIndicator currentIndicator] hide];
if (ticket.didSucceed)
{
NSString *responseBody = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
//piyush Added
NSArray *strArray = [responseBody componentsSeparatedByString:#"="];
[[NSUserDefaults standardUserDefaults]setObject:[strArray objectAtIndex:([strArray count]-1)] forKey:#"TwitterUsername"];
**self.accessToken** = [[OAToken alloc] initWithHTTPResponseBody:responseBody];
[responseBody release];
[self storeAccessToken];
//[self tryPendingAction];
[[NSNotificationCenter defaultCenter] postNotificationName:#"TwitterDidLogin" object:nil];
}
else
// TODO - better error handling here
[self tokenAccessTicket:ticket didFailWithError:[SHK error:SHKLocalizedString(#"There was a problem requesting access from %#", [self sharerTitle])]];
}
I am using Robbiehanson's iOS XMPPFramework. I am trying to create a MUC room and invite a user to the group chat room but it is not working.
I am using the following code:
XMPPRoom *room = [[XMPPRoom alloc] initWithRoomName:#"user101#conference.jabber.org/room" nickName:#"room"];
[room createOrJoinRoom];
[room sendInstantRoomConfig];
[room setInvitedUser:#"ABC#jabber.org"];
[room activate:[self xmppStream]];
[room inviteUser:jid1 withMessage:#"hello please join."];
[room sendMessage:#"HELLO"];
The user ABC#jabber.org should receive the invite message but nothing is happening.
Any help will be appreciated. :)
After exploring various solutions, I've decided to compile and share my implementation here:
Create an XMPP Room:
XMPPRoomMemoryStorage *roomStorage = [[XMPPRoomMemoryStorage alloc] init];
/**
* Remember to add 'conference' in your JID like this:
* e.g. uniqueRoomJID#conference.yourserverdomain
*/
XMPPJID *roomJID = [XMPPJID jidWithString:#"chat#conference.shakespeare"];
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:roomStorage
jid:roomJID
dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:[self appDelegate].xmppStream];
[xmppRoom addDelegate:self
delegateQueue:dispatch_get_main_queue()];
[xmppRoom joinRoomUsingNickname:[self appDelegate].xmppStream.myJID.user
history:nil
password:nil];
Check if room is successfully created in this delegate:
- (void)xmppRoomDidCreate:(XMPPRoom *)sender
Check if you've joined the room in this delegate:
- (void)xmppRoomDidJoin:(XMPPRoom *)sender
After room is created, fetch room configuration form:
- (void)xmppRoomDidJoin:(XMPPRoom *)sender {
[sender fetchConfigurationForm];
}
Configure your room
/**
* Necessary to prevent this message:
* "This room is locked from entry until configuration is confirmed."
*/
- (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"];
// Make Room Persistent
if ([var isEqualToString:#"muc#roomconfig_persistentroom"]) {
[field removeChildAtIndex:0];
[field addChild:[NSXMLElement elementWithName:#"value" stringValue:#"1"]];
}
}
[sender configureRoomUsingOptions:newConfig];
}
References: XEP-0045: Multi-User Chat, Implement Group Chat
Invite users
- (void)xmppRoomDidJoin:(XMPPRoom *)sender
{
/**
* You can read from an array containing participants in a for-loop
* and send multiple invites in the same way here
*/
[sender inviteUser:[XMPPJID jidWithString:#"keithoys"] withMessage:#"Greetings!"];
}
There, you've created a XMPP multi-user/group chat room, and invited a user. :)
I have the feeling that the first thing to do after alloc-init is to attach it to your xmppStream, so it can use xmppStream to send/receive messages.
More exactly:
XMPPRoom *room = [[XMPPRoom alloc] initWithRoomName:#"user101#conference.jabber.org/room" nickName:#"room"];
[room activate:[self xmppStream]];
//other things (create/config/...)
Check the latest XMPPMUCLight & XMPPRoomLight its similar to Whatsapp and other today's trends social app rooms that don't get destroyed or members kicked when offline or no one in room.
Refer this documentation & mod from MongooseIM
I am creating a chat application using XMPP Framework in iPhone. I wish to know the process for sending and receiving messages. Can anyone give me a solution for this?
Thanks in advance.
Download XMPPFramework and unzip it. There are several folders inside. Open the 'Xcode' folder > open 'iPhoneXMPP' folder > click on 'iPhoneXMPP.xcodeproj' > run it. It asks login credential first. Upon successful login, it will show your buddy list. It works fine for gmail. There is one call back method which is called for every incoming message:
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
user = [xmppRosterStorage userForJID:[message from] xmppStream:sender managedObjectContext:[self managedObjectContext_roster]];
if ([message isChatMessageWithBody])
{
NSString *body = [[message elementForName:#"body"] stringValue];
NSString *from = [[message attributeForName:#"from"] stringValue];
NSMutableDictionary *m = [[NSMutableDictionary alloc] init];
[m setObject:body forKey:#"msg"];
[m setObject:from forKey:#"sender"];
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
{
NSLog(#"Applications are in active state");
//send the above dictionary where ever you want
}
else
{
NSLog(#"Applications are in Inactive state");
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertAction = #"Ok";
localNotification.applicationIconBadgeNumber=count;
localNotification.alertBody =[NSString stringWithFormat:#"From:"%#\n\n%#",from,body];
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
//send the above dictionary where ever you want
}
}
}
For sending message we have to write our own method where ever you want:
-(void)sendMessage
{
NSString *messageStr =messageField.text;
if([messageStr length] > 0)
{
NSLog(#"Message sending fron Gmail");
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
[body setStringValue:messageStr];
NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"to" stringValue:#"destination address"];
[message addChild:body];
NSLog(#"message1%#",message);
[[self appDelegate].xmppSream sendElement:message];
}
}
For Sending the message in groups/Room below is the snippet
XMPPMessage *message = [XMPPMessage message];
[message addBody:#"123"];
[self.currentRoom sendMessage:message1];
Where self.currentRoom is XMPPRoom
If you are sending message from Room/Group then use this code for sending messages.
[xmppRoom sendMessage:#"Hi All"];
Don't need to send the messages through xmppStream. This Single line of code works perfectly for me.
Quick google search reveals many XMPP libraries, either C/C++ or ObjC. Perhaps http://code.google.com/p/xmppframework/ would be a good starting point, though I haven't tried it personally.
Here is a solution to send message via XMPPFramework in Swift 3
let user = XMPPJID(string: "user#jabjab.de")
let msg = XMPPMessage(type: "chat", to: user)
msg?.addBody("Message to send")
self.xmppStream.send(msg)