Wednesday 27 June 2012

XMPP Chat Connection ChatConnection

//
//  ChatConnection.h
//  ChatModule
//
//  Created by Gaurav & Piyush on 27/06/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
// Ref: http://wiki.xmpp.org/web/Programming_XMPP_Clients
//      http://xmpp.org/xmpp-protocols/xmpp-extensions/
//      http://gauravds.blogspot.in/2012/06/nsstring-str-xmlnsjabberclient.html

#import <Foundation/Foundation.h>

#pragma mark - Chat Delegate Protocol
// a protocol
@protocol ChatDelegate <NSObject>

typedef enum ConnectionResponse{
    kConnected,
    kNotConnected
}ConnectionResponse;

@optional
- (void)chatConnectionResponse:(ConnectionResponse)connectionResponse;


typedef enum LoginResponse{
    kLoginSuccess,
    kLoginFail
}LoginResponse;

@optional
- (void)chatLoginResponse:(LoginResponse)loginResponse;


typedef enum MUCResponse{
    kMUCJoinSuccess,
    kMUCJoinFail,
    kMUCLeaveSuccess,
    kMUCLeaveFail,
    kMUCMessageSendSuccess,
    kMUCMessageSendFail
}MUCResponse;

@optional
- (void)chatMUCResponse:(MUCResponse)MUC_Response;

@optional
- (void)chatMUCMessageReceiveResponse:(NSDictionary*)receiveResponse;

@end

#pragma mark - Chat Connection Class
// class declaration
@interface ChatConnection : NSObject <NSStreamDelegate>
{
    NSMutableData *data;
    NSInputStream *inputStream;
    NSOutputStream *outputStream;
    CFReadStreamRef readStream ;
    CFWriteStreamRef writeStream;
}
@property (nonatomic, strong) id<ChatDelegate> delegate;

@property (nonatomic, readonly) BOOL isChatConnectionAvailable;

#pragma mark  connection methods
// --- singleton refernce
+ (ChatConnection*)sharedChatConnection;

// --- some connection methods
- (void)connectToServerUsingStream:(NSString *)urlStr
                            portNo:(uint)portNo;
- (void)disconnect;

- (void)writeToServer:(NSString*)stringXML;

- (void)stream:(NSStream *)stream
   handleEvent:(NSStreamEvent)eventCode;

#pragma mark  login signup chagne password methods
// ---  some user Need methods
- (void)signUpWithUserName:(NSString*)userName
               andPassword:(NSString*)password;

- (void)loginWithUserName:(NSString*)userName
              andPassword:(NSString*)password;

- (void)changePasswordWithUserName:(NSString*)userName
                       andPassword:(NSString*)password;

#pragma mark  Multi User Chat
// --- Multi user Chat methods
- (void)MUC_createOrJoinRoom:(NSString*)chatRoomName
                 andUsername:(NSString*)userName;

- (void)MUC_unlockRoomAndConfig:(NSDictionary*)dict;

- (void)MUC_leaveChatRoomName:(NSString*)chatRoomName
                  andUsername:(NSString*)userName;

- (void)MUC_chatOnChatRoomName:(NSString*)chatRoomName
                    andMessage:(NSString*)messageStr;

#pragma mark  Single User Chat
// --- Single user chat methods
- (void)SUC_chatWithMessage:(NSString*)messageStr 
                     toUser:(NSString*)toUser;

@end
--------------------------------------------------------------------------------------------
//
//  ChatConnection.m
//  ChatModule
//
//  Created by Gaurav & Piyush on 27/06/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "ChatConnection.h"
#import "AppDelegate.h"
#import "XMLReader.h"


#define STREAM_START @"<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
#define STREAM_END   @"</stream:stream>"
#define SERVER_NAME @"openfire"
#define RESOURCE_NAME @"iphone"

// private methods
@interface ChatConnection (privateMethods)

+ (BOOL)isNotNull:(NSString*)aString;

- (void)alertTitle:(NSString*)title withMessage:(NSString*)message;

- (void)alertTitle:(NSString*)title withMessage:(NSString*)message andDelegate:(id)delegateAlert;

- (void)sendPingResponse:(NSDictionary*)dict;

- (void)readServerResponse:(NSData*)dataXML;

- (void)responseLoginHandle:(NSDictionary*)dict;

- (void)responseChangePasswordHandle:(NSDictionary*)dict;

- (void)responseMUCHandle:(NSDictionary*)dict;

@end

// class defination
@implementation ChatConnection

@synthesize delegate;

@synthesize isChatConnectionAvailable;

NSString *usernameStr, *passwordStr;
BOOL isStreamAvailable = NO;
#pragma mark - helper methods
+ (BOOL)isNotNull:(NSString*)aString{
    if ([[aString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:@""]
        || aString == nil || [aString length] == 0 ) {
        return NO;
    }
    return YES;
}

#pragma mark Alert
- (void)alertTitle:(NSString*)title withMessage:(NSString*)message{
    [[[UIAlertView alloc] initWithTitle:title
                                message:message
                               delegate:nil
                      cancelButtonTitle:@"OK"
                      otherButtonTitles: nil] show];
}

- (void)alertTitle:(NSString*)title withMessage:(NSString*)message andDelegate:(id)delegateAlert{
    [[[UIAlertView alloc] initWithTitle:title
                                message:message
                               delegate:delegateAlert
                      cancelButtonTitle:@"OK"
                      otherButtonTitles: nil] show];
}

#pragma mark - Connection Methods

+ (ChatConnection*)sharedChatConnection{
    return (ChatConnection*)[(AppDelegate*)[[UIApplication sharedApplication] delegate] chatConnection];
}

- (void)connectToServerUsingStream:(NSString *)urlStr
                            portNo:(uint)portNo{
   
    NSLog(@"ChatConnection:Method - (void)connectToServerUsingStream:(NSString *)urlStr portNo:(uint)portNo");
   
    CFReadStreamRef readStream1;
    CFWriteStreamRef writeStream1;
    // __bridge used to convert Non ARC class to ARC class typecast
    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)urlStr, portNo, &readStream1, &writeStream1);
   
    assert(urlStr != nil);
    assert( (portNo > 0) && (portNo < 65536) );
   
    // __bridge used to convert Non ARC class to ARC class typecast
    inputStream = (__bridge NSInputStream *)readStream1;
    outputStream = (__bridge NSOutputStream *)writeStream1;
   
    [inputStream setDelegate:self];
    [outputStream setDelegate:self];
   
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
   
    [inputStream open];
    [outputStream open];
   
    if (inputStream && outputStream){
        isChatConnectionAvailable = YES;   
    }

   
    if (delegate && [delegate respondsToSelector:@selector(chatConnectionResponse:)]) {
        [delegate chatConnectionResponse:isChatConnectionAvailable ? kConnected : kNotConnected];
    }
}
- (void)disconnect{
    NSLog(@"ChatConnection:Method - disconnect");
   
    [inputStream close];
    [outputStream close];
    inputStream = nil;
    outputStream = nil;
   
    usernameStr = nil;
   
    if (!inputStream && !outputStream) {
        isChatConnectionAvailable = NO;
    }

   
    if (delegate && [delegate respondsToSelector:@selector(chatConnectionResponse:)]) {
        [delegate chatConnectionResponse:isChatConnectionAvailable ? kConnected : kNotConnected];
    }
}

- (void)writeToServer:(NSString*)stringXML{
    NSLog(@"ChatConnection:Method - (void)writeToServer:(NSString*)stringXML");
   
    NSLog(@"stringXML %@",[XMLReader dictionaryForXMLString:stringXML error:nil]);
   
    if(outputStream) {
        if(![outputStream hasSpaceAvailable]) return;
        NSData *_data=[stringXML dataUsingEncoding:NSUTF8StringEncoding];
        int data_len = [_data length];
        uint8_t *readBytes = (uint8_t *)[_data bytes];
        int byteIndex=0;
        unsigned int len=0;
       
        while (TRUE) {
            len = ((data_len - byteIndex >= 40960) ? 40960 : (data_len-byteIndex));
           
           
            if(len==0)
                break;
            uint8_t buf[len]; (void)memcpy(buf, readBytes, len);
            len = [outputStream write:(const uint8_t *)buf maxLength:len];
            byteIndex += len;
            readBytes += len;
        }
        NSLog(@"ChatConnection: Sent data----------------------%@",stringXML);
    }
   
}

#pragma mark - Server Response Understand (NSStreamDelegate)
- (void)stream:(NSStream *)stream
   handleEvent:(NSStreamEvent)eventCode{
   
    NSLog(@"ChatConnection:Method - (void)stream:(NSStream *)stream"
          "handleEvent:(NSStreamEvent)eventCode");
   
    switch(eventCode) {
        case NSStreamEventHasBytesAvailable:
        {
            if (data == nil) {
                data = [[NSMutableData alloc] init];
            }
            uint8_t buf[1024];
            unsigned int len = 0;
            len = [(NSInputStream *)stream read:buf maxLength:1024];
            if(len) {
                [data appendBytes:(const void *)buf length:len];
                int bytesRead;
                bytesRead += len;
            } else {
                NSLog(@"ChatConnection:No data.");
            }
           
            NSString *str = [[NSString alloc] initWithData:data
                                                  encoding:NSUTF8StringEncoding];
            NSLog(@"ChatConnection response: str :%@",str);
           
            [self readServerResponse:data];
           
            data = nil;
        } break;
        case NSStreamEventErrorOccurred:
        {
            NSLog(@"ChatConnection:An error has occurred on the stream. ");
        }
            break;
           
        case NSStreamEventEndEncountered:
        {
            NSLog(@"ChatConnection:The end of the stream has been reached. ");
        }
            break;
           
        case NSStreamEventNone:
        {
            NSLog(@"ChatConnection:No events occured");
        }
            break;
           
        case NSStreamEventOpenCompleted :
        {
            NSLog(@"ChatConnection:The open has completed successfully. ");
        }
            break;
           
        case NSStreamEventHasSpaceAvailable:
        {
            NSLog(@"ChatConnection:The stream can accept bytes for writing.");
        }
            break;
    }
}

// --- private method
- (void)readServerResponse:(NSData*)dataXML{
    NSLog(@"ChatConnection:Method - (void)readServerResponse:(NSData*)dataXML");
   
   
    XMLReader *reader = [[XMLReader alloc] init];
   
    NSDictionary *dict = [reader objectWithData:data];
   
    NSLog(@"dict print %@",dict);
   
    NSString *idStr = [[dict objectForKey:@"iq"] objectForKey:@"@id"];
   
    NSLog(@"idStr %@",idStr);
   
    //- stream handler
    if ([dict objectForKey:@"stream:stream"]) {
        isStreamAvailable = YES;
        [self loginWithUserName:usernameStr andPassword:passwordStr];
    }
   
    //- ping handler
    else if ([[dict objectForKey:@"iq"] objectForKey:@"ping"]) {
        [self sendPingResponse:dict];
    }
   
    //- login handle
    else if (idStr && [idStr isEqualToString:@"login_request"]) {
        NSString *toServerStr = [NSString stringWithFormat:@"<iq type='set' xmlns='jabber:client' id='login'>"
                                 "<query xmlns='jabber:iq:auth'>"
                                 "<username>%@</username>"
                                 "<password>%@</password>"
                                 "<resource>iphone</resource>"
                                 "</query></iq>"
                                 "<presence><show>chat</show></presence>",usernameStr,passwordStr];
                                
                                
        /**
         presence  http://xmpp.org/rfcs/rfc3921.html
        
         away -- The entity or resource is temporarily away. (idle - yellow)
         chat -- The entity or resource is actively interested in chatting. (available - green)
         dnd -- The entity or resource is busy (dnd = "Do Not Disturb"). (busy - red)
         xa -- The entity or resource is away for an extended period (xa = "eXtended Away").(idle - yellow)
        
         demo : <presence><show>dnd</show></presence>
        
         <presence><show>chat</show></presence> and <presence><show/></presence> are same
         */
       
        [self writeToServer:toServerStr];
    }
    else if (idStr && [idStr isEqualToString:@"login"]) {
        [self responseLoginHandle:dict];
    }
   
    //- change password handler
    else if (idStr && [idStr isEqualToString:@"change_password"]) {
        [self responseChangePasswordHandle:dict];
       
    }
    //* MUC_unlockRoomAndConfig
    else if ([[[dict objectForKey:@"presence"] objectForKey:@"@id"] isEqualToString:@"MUC_create_join"]){
        [self MUC_unlockRoomAndConfig:dict];
    }
    // MUC chat reply message handler
    else if ([[[dict objectForKey:@"message"] objectForKey:@"@type"] isEqualToString:@"groupchat"]) {
        [self responseMUCHandle:dict];
    }
}

#pragma mark - Ping Handler
// http://xmpp.org/extensions/xep-0199.html#usecases-changepw
- (void)sendPingResponse:(NSDictionary*)dict{
    [self writeToServer:[NSString stringWithFormat:@"<iq from='%@' to='%@' id='%@' type='result'/>",
                         [[dict objectForKey:@"iq"] objectForKey:@"@to"],
                         [[dict objectForKey:@"iq"] objectForKey:@"@from"],
                         [[dict objectForKey:@"iq"] objectForKey:@"@id"]]];
}

#pragma mark - signup

- (void)signUpWithUserName:(NSString*)userName
               andPassword:(NSString*)password{
    /**
     http://wiki.xmpp.org/web/Programming_XMPP_Clients
     *  sign up : create a a/c
    
     C:  <iq type='get' id='signup_request'>
     <query xmlns='jabber:iq:register'/>
     </iq>
     S:  <iq type='result' id='signup_request'>
     <query xmlns='jabber:iq:register'>
     <username/>
     <password/>
     </query>
     </iq>
     C:  <iq type='set' id='signup'>
     <query xmlns='jabber:iq:register'>
     <username>abc</username>
     <password>123456</password>
     </query>
     </iq>
    
     * response :
     S:  <iq type='result' id='signup'>
     <query xmlns='jabber:iq:register'/>
     </iq>
    
    
     S:  <iq type='error' id='signup'>
     <query xmlns='jabber:iq:register'>
     <username>abc</username><password>123456</password>
     </query>
     <error code='409'>
     Username Not Available
     </error>
     </iq>
    
     * using
     <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='signup_request'>
     <iq type='get' xmlns='jabber:client'>
     <query xmlns='jabber:iq:register'/> </iq>
     <iq type='set' xmlns='jabber:client' id='signup'>
     <query xmlns='jabber:iq:register'>
     <username>abc</username>
     <password>123456</password>
     </query>
     </iq></stream:stream>
    
     */
    NSLog(@"ChatConnection:Method - signup ...");
   
// ---    ERROR 409 not Handle only create here(signUp)
   
    if ([ChatConnection isNotNull:userName] && [ChatConnection isNotNull:password]) {
       
        NSString *toServerStr = [NSString stringWithFormat:@"%@<iq type='get' xmlns='jabber:client' id='signup_request'>"
                                 "<query xmlns='jabber:iq:register'/> </iq>"
                                 "<iq type='set' xmlns='jabber:client' id='signup'>"
                                 "<query xmlns='jabber:iq:register'>"
                                 "<username>%@</username>"
                                 "<password>%@</password>"
                                 "</query>"
                                 "</iq>%@",STREAM_START,userName,password,STREAM_END];
       
        [self writeToServer:toServerStr];
    } else {
       
        NSLog(@"ChatConnection: signUp : uName or pwd empty");
    }
}

#pragma mark - Login
/**
 http://wiki.xmpp.org/web/Programming_XMPP_Clients
 // check that user available : login_request then login

 C: <iq type='get' to='shakespeare.lit' id='login_request'>
    <query xmlns='jabber:iq:auth'>
    <username>abc</username>
    </query>
    </iq>

 S: <iq type='result' id='login_request'>
    <query xmlns='jabber:iq:auth'>
    <username/>
    <password/>
    <digest/>
    <resource/>
    </query>
    </iq>

 C: <iq type='set' id='login'>
    <query xmlns='jabber:iq:auth'>
    <username>abc</username>
    <password>123456</password>
    <resource>iPhone</resource>
    </query>
    </iq>

 * response
 S: <iq type='result' id='login'/>

 S: <iq type='error' id='login'>
    <error code='401' type='auth'>
    <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    </error>
    </iq>

 S: <iq type='error' id='login'>
    <error code='406' type='modify'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    </error>
    </iq>

 S: <iq type='error' id='login'>
    <error code='409' type='cancel'>
    <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    </error>
    </iq>

  * using
     <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"
     <iq type='get' xmlns='jabber:client' id='login_request'>
     <query xmlns='jabber:iq:auth'>
     <username>abc</username>
     </query></iq>
     <iq type='set' xmlns='jabber:client' id='login'>
     <query xmlns='jabber:iq:auth'>
     <username>abc</username>
     <password>123456</password>
     <resource>iphone</resource>
     </query>
     </iq>
     <presence><show>chat</show></presence>

 */
- (void)loginWithUserName:(NSString*)userName
              andPassword:(NSString*)password{
   
    NSLog(@"ChatConnection:Method - login check ... :");
   
    NSLog(@"- (void)loginWithUserName:(NSString*)uName andPassword:(NSString*)pwd");
   
    if ([ChatConnection isNotNull:userName] && [ChatConnection isNotNull:password]) {

        usernameStr = userName;
        passwordStr = password;
       
        if (!isStreamAvailable){
            [self writeToServer:STREAM_START];
            return;
        }
       
        NSString *toServerStr = [NSString stringWithFormat:@"<iq type='get' xmlns='jabber:client' id='login_request'>"
                                 "<query xmlns='jabber:iq:auth'>"
                                 "<username>%@</username>"
                                 "</query></iq>",userName];
                                
//                                 "<iq type='set' xmlns='jabber:client' id='login'>"
//                                 "<query xmlns='jabber:iq:auth'>"
//                                 "<username>%@</username>"
//                                 "<password>%@</password>"
//                                 "<resource>iphone</resource>"
//                                 "</query></iq>"
//                                 "<presence><show>chat</show></presence>",STREAM_START,userName, userName,password];
        /**
         presence  http://xmpp.org/rfcs/rfc3921.html
        
         away -- The entity or resource is temporarily away. (idle - yellow)
         chat -- The entity or resource is actively interested in chatting. (available - green)
         dnd -- The entity or resource is busy (dnd = "Do Not Disturb"). (busy - red)
         xa -- The entity or resource is away for an extended period (xa = "eXtended Away").(idle - yellow)

         demo : <presence><show>dnd</show></presence>
        
         <presence><show>chat</show></presence> and <presence><show/></presence> are same
        */
       
        [self writeToServer:toServerStr];
    } else {
        NSLog(@"ChatConnection: login : uName or pwd empty");
    }
   
}

// --- private method
- (void)responseLoginHandle:(NSDictionary*)dict{
    NSLog(@"ChatConnection:Method - (void)responseLoginHandle:(NSDictionary*)dict");
   
    if ([[[dict objectForKey:@"iq"] objectForKey:@"@type"] isEqualToString:@"error"])
    {
        int errorResponseCode = [[[[dict objectForKey:@"iq"] objectForKey:@"error"] objectForKey:@"@code"] intValue];
       
        switch (errorResponseCode) {
            case 401: // not-authorized
            {
                [self alertTitle:@"Error !" withMessage:@"Username/password Incorrect"];
            }
                break;
               
            case 406: // not-acceptable
            {
                [self alertTitle:@"Error !" withMessage:@"not-acceptable"];
            }
                break;
               
            case 409: // conflict
            {
                [self alertTitle:@"Error !" withMessage:@"conflict"];
            }
                break;
               
            default:
                NSLog(@"not recognized error, error code:%d",errorResponseCode);
                break;
        }
        usernameStr = nil;
       
        if (delegate && [delegate respondsToSelector:@selector(chatLoginResponse:)]) {
            [delegate chatLoginResponse:kLoginFail];
        }
    }
    else
    {
        NSLog(@"successfull login");
        if (delegate && [delegate respondsToSelector:@selector(chatLoginResponse:)]) {
            [delegate chatLoginResponse:kLoginSuccess];
        }
    }
}

#pragma mark - change password
/**
 http://xmpp.org/extensions/xep-0077.html#usecases-changepw
 // chance password

 C: <iq type='set' to='shakespeare.lit' id='change_password'>
 <query xmlns='jabber:iq:register'>
 <username>abc</username>
 <password>newpass</password>
 </query>
 </iq>


 * response
 S: <iq type='result' id='change_password'/>


 S: <iq type='error' from='shakespeare.lit' to='bill@shakespeare.lit/globe' id='change_password'>
 <error code='400' type='modify'>
 <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
 </error>
 </iq>


 S: <iq type='error' from='shakespeare.lit' to='bill@shakespeare.lit/globe' id='change_password'>
 <error code='401' type='modify'>
 <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
 </error>
 </iq>


 S: <iq type='error' from='shakespeare.lit' to='bill@shakespeare.lit/globe' id='change_password'>
 <error code='405' type='cancel'>
 <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
 </error>
 </iq>


 * using
 <iq type='set' xmlns='jabber:client' id='change_password'>
 <query xmlns='jabber:iq:register'>
 <username>abc</username>
 <password>newPassword</password>
 </query></iq>

 */
- (void)changePasswordWithUserName:(NSString*)userName
                      andPassword:(NSString*)password{
   
    NSLog(@"ChatConnection:Method - change password:");
   
    NSLog(@"- (void)changePasswordWithUserName:(NSString*)uName andPassword:(NSString*)pwd");
   
    if (!userName) {
        userName = usernameStr;
    }
   
    if ([ChatConnection isNotNull:userName] && [ChatConnection isNotNull:password]) {
        NSString *toServerStr = [NSString stringWithFormat:@"<iq type='set' xmlns='jabber:client' id='change_password'>"
                                                             "<query xmlns='jabber:iq:register'>"
                                                             "<username>%@</username>"
                                                             "<password>%@</password>"
                                                             "</query></iq>",userName,password];
       
        [self writeToServer:toServerStr];
    } else {
        NSLog(@"ChatConnection: changePassword : uName or pwd empty");
    }
   

}

// --- private method
- (void)responseChangePasswordHandle:(NSDictionary*)dict{
    NSLog(@"ChatConnection:Method - (void)responseChangePasswordHandle:(NSDictionary*)dict");
   
    if ([[[dict objectForKey:@"iq"] objectForKey:@"@type"] isEqualToString:@"error"])
    {
        int errorResponseCode = [[[[dict objectForKey:@"iq"] objectForKey:@"error"] objectForKey:@"@code"] intValue];
       
        switch (errorResponseCode) {
            case 400:// bad-request
            {
                [self alertTitle:@"Error !" withMessage:@"bad-request"];
            }
                break;
            case 401: // not-authorized
            {
                [self alertTitle:@"Error !" withMessage:@"Username Incorrect"];
            }
                break;
               
            case 405: // not-allowed
            {
                [self alertTitle:@"Error !" withMessage:@"not-allowed"];
            }
                break;
               
            default:
                NSLog(@"not recognized error, error code:%d",errorResponseCode);
                break;
        }
    }
    else
    {
        NSLog(@"successfull password change");
    }
}

#pragma mark - Multi User Chat Room
/**
// http://xmpp.org/extensions/xep-0045.html

 // --- Create or Join a room
    <presence to='roomName@conference.gauravs-mac.local/abc'>
    <x xmlns='http://jabber.org/protocol/muc'/>
    </presence>

 // --- Unlock room and set set configuration file
    <iq type='set' from='abc@gauravs-mac.local/iphone' id='muc_config' to='roomName@conference.gauravs-mac.local'>
    <query xmlns='http://jabber.org/protocol/muc#owner'>
    <feature var="http://jabber.org/protocol/muc"/>
    <feature var="muc_public"/>
    <feature var="muc_persistent"/>
    <feature var="muc_open"/>
    <x xmlns='jabber:x:data' type='submit'/>
    </query></iq>

 // --- leave room
 <presence type='unavailable' to='darkcave@chat.shakespeare.lit/thirdwitch'/>

 // --- Send message on room
    <message from='abc@gauravs-mac.local/iphone' id='msgID' to='roomName@conference.gauravs-mac.local' type='groupchat'>
    <body>Message write here.</body></message>

 */

- (void)MUC_createOrJoinRoom:(NSString*)chatRoomName
                 andUsername:(NSString*)userName{
    NSLog(@"ChatConnection:Method -");
   
    NSLog(@"- (void)MUC_createOrJoinRoom:(NSString*)chatRoomName andUsername:(NSString*)userName");

    if (!userName) {
        userName = usernameStr;
    }
   
    if ([ChatConnection isNotNull:chatRoomName] && [ChatConnection isNotNull:userName]) {
       
        chatRoomName = [chatRoomName stringByReplacingOccurrencesOfString:@" " withString:@"_"];
       
        NSString *toServerStr = [NSString stringWithFormat:@"<presence to='%@@conference.%@/%@' id='MUC_create_join'>"
                                 "<x xmlns='http://jabber.org/protocol/muc'/></presence>",
                                 chatRoomName,SERVER_NAME,userName];
       
        [self writeToServer:toServerStr];
    } else {
        NSLog(@"ChatConnection: MUC_createOrJoinRoom:andUsername: chatRoomName or userName empty");
    }
}

- (void)MUC_unlockRoomAndConfig:(NSDictionary*)dict{
    NSLog(@"ChatConnection:Method - ");
   
    NSLog(@"- (void)MUC_unlockRoomAndConfig");
   
    if (dict) {
        NSLog(@"dict %@",dict);
        NSString *toServerStr = [NSString stringWithFormat:@"<iq type='set' from='%@' to='%@' id='muc_config'>"
                                 "<query xmlns='http://jabber.org/protocol/muc#owner'>"
//                                 "<feature var='http://jabber.org/protocol/muc' />"
//                                 "<feature var='muc_public' />"
//                                 "<feature var='muc_persistent' />"
//                                 "<feature var='muc_open' />"
                                 "<x xmlns='jabber:x:data' type='submit'/></query></iq>",
                                 [[dict objectForKey:@"presence"] objectForKey:@"@to"],
                                 [[dict objectForKey:@"presence"] objectForKey:@"@from"]];
       
        [self writeToServer:toServerStr];

    } else {
        NSLog(@"ChatConnection: MUC_unlockRoomAndConfig : dict empty");
    }
}

- (void)MUC_leaveChatRoomName:(NSString*)chatRoomName
                  andUsername:(NSString*)userName{
   
    NSLog(@"ChatConnection:Method - ");
   
    NSLog(@"- (void)MUC_leaveChatRoomName:(NSString*)chatRoomName andUsername:(NSString*)userName");
   
    if (!userName) {
        userName = usernameStr;
    }
   
    if ([ChatConnection isNotNull:chatRoomName] && [ChatConnection isNotNull:userName]) {
       
        chatRoomName = [chatRoomName stringByReplacingOccurrencesOfString:@" " withString:@"_"];

        NSString *toServerStr = [NSString stringWithFormat:@"<presence type='unavailable' to='%@@conference.%@/%@'/>",
                                 chatRoomName,SERVER_NAME,userName];
       
        [self writeToServer:toServerStr];
       
    } else {
        NSLog(@"ChatConnection: MUC_leaveChatRoomName:andUsername: chatRoomName or userName empty");
    }
}

- (void)MUC_chatOnChatRoomName:(NSString*)chatRoomName
                    andMessage:(NSString*)messageStr{
    NSLog(@"ChatConnection:Method -");
   
    NSLog(@"- (void)MUC_chatOnChatRoomName:(NSString*)chatRoomName andMessage:(NSString*)messageStr");
   
    if ([ChatConnection isNotNull:chatRoomName] && [ChatConnection isNotNull:messageStr]) {
       
        chatRoomName = [chatRoomName stringByReplacingOccurrencesOfString:@" " withString:@"_"];

        NSString *toServerStr = [NSString stringWithFormat:@"<message id='MUC_chat' to='%@@conference.%@' type='groupchat'>"
                                                          "<body>%@</body></message>",chatRoomName,SERVER_NAME,messageStr];
       
        [self writeToServer:toServerStr];
       
    } else {
        NSLog(@"ChatConnection: MUC_chatOnChatRoomName:andMessage: chatRoomName or messageStr empty");
    }
}

- (void)responseMUCHandle:(NSDictionary*)dict{
    // XMPP server response understand and then repond to delegate
    NSLog(@"ChatConnection :: - (void)responseMUCHandle:(NSDictionary*)dict");
    if (dict) {
        if ([dict objectForKey:@"message"]) {
            NSDictionary *dictMsg = [dict objectForKey:@"message"];
           
            NSString *from = [dictMsg objectForKey:@"@from"] ;
            from = [[from substringFromIndex:([from rangeOfString:@"/"
                                                          options:NSBackwardsSearch].location)+1]
                    stringByRemovingNewLinesAndWhitespace];
           
            NSString *body = [dictMsg objectForKey:@"body"];
            if (from && body){
                NSDictionary *dictResponse = [[NSDictionary alloc] initWithObjectsAndKeys:from,@"from",body,@"message", nil];
                if (delegate && [delegate respondsToSelector:@selector(chatMUCMessageReceiveResponse:)]) {
                    [delegate chatMUCMessageReceiveResponse:dictResponse];
                }
                else {
                    NSLog(@"delegate is empty or not response to selector");
                }
                                
            }
            else{
                NSLog(@"from name or body empty response");
            }
        }
    }
    else{
        NSLog(@"dict empty");
    }
   
}

#pragma mark - Single User Chat
//<message type="chat" to="gaurav@gauravs-mac.local/spark"><body>hello gaurav</body></message>
- (void)SUC_chatWithMessage:(NSString*)messageStr 
                     toUser:(NSString*)toUser{
    NSLog(@"ChatConnection:Method -");
   
    NSLog(@"- (void)SUC_chatWithMessage:fromUser:toUser:");
   
    if ([ChatConnection isNotNull:messageStr] && 
        [ChatConnection isNotNull:toUser]
        ) {
       
        NSString *toServerStr = [NSString stringWithFormat:@"<message type='chat' to='%@@%@/iphone'><body>%@</body></message>",toUser,SERVER_NAME,messageStr];
       
        [self writeToServer:toServerStr];
       
    } else {
        NSLog(@"ChatConnection: MUC_chatOnChatRoomName:andMessage: chatRoomName or messageStr empty");
    }
}

@end

No comments:

Post a Comment