XMPPFramework - Retrieving Openfire Message Archives
Asked Answered
N

4

5

Spent hours trying to solve this problem and I'm stumped!

Trying to grab the Chat History between 2 users on my OpenFire server and I read that I plugin was needed to do this.

So, I installed the 'Open Archive' plugin on my OpenFire server and send the following XML (as per the XMPP-0136 protocol documentation):

<iq type="get" id="page1">
   <retrieve xmlns="urn:xmpp:archive" with="[email protected]" start="1469-07-21T02:56:15Z">
      <set xmlns="http://jabber.org/protocol/rsm">
         <max>100</max>
      </set>
   </retrieve>
</iq>

In code, this is achieved via the following:

NSXMLElement *iQ = [NSXMLElement elementWithName:@"iq"];
[iQ addAttributeWithName:@"type" stringValue:@"get"];
[iQ addAttributeWithName:@"id" stringValue:@"page1"];

NSXMLElement *retrieve = [NSXMLElement elementWithName:@"retrieve"];
[retrieve addAttributeWithName:@"xmlns" stringValue:@"urn:xmpp:archive"];
[retrieve addAttributeWithName:@"with" stringValue:@"[email protected]"];
[retrieve addAttributeWithName:@"start" stringValue:@"1469-07-21T02:56:15Z"];

NSXMLElement *set = [NSXMLElement elementWithName:@"set"];
[set addAttributeWithName:@"xmlns" stringValue:@"http://jabber.org/protocol/rsm"];
NSXMLElement *max = [NSXMLElement elementWithName:@"max"];
max.stringValue = @"100";
[set addChild:max];

[retrieve addChild:set];
[iQ addChild:retrieve];

[[[self appDelegate] xmppStream] sendElement:iQ];

Which returns the following error:

<iq xmlns="jabber:client" type="error" id="page1" to="[email protected]">
   <error code="404" type="cancel">
      <item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
   </error>
</iq>

My Xcode project can successfully send/receive messages to the user I'm trying to receive chat history from so I really don't know what I'm doing wrong. Also the Plugin enables me to search through Chat Messages (via OpenFire admin) with successful results so it seems to be working and storing the messages.

Any help would be appreciated. Thanks!

Nigelniger answered 5/1, 2013 at 15:31 Comment(1)
Here is the solution. #11397672Royer
C
7

If you are looking for a chat history, I think you have to save the messages to core data and retrieve them from there. For saving data using the XMPPFramework inbuilt functionality, you have to use this code:

XMPPMessageArchivingCoreDataStorage *storage = [XMPPMessageArchivingCoreDataStorage   sharedInstance];
NSManagedObjectContext *moc = [storage mainThreadManagedObjectContext];

xmppMessageArchivingStorage = [XMPPMessageArchivingCoreDataStorage sharedInstance];
xmppMessageArchivingModule = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:xmppMessageArchivingStorage];
[xmppMessageArchivingModule activate:xmppStream];
[xmppMessageArchivingModule  addDelegate:self delegateQueue:dispatch_get_main_queue()];

Now you have to retrieve that messages from core data by this:

-(void)loadarchivemsg
{  
    XMPPMessageArchivingCoreDataStorage *storage = [XMPPMessageArchivingCoreDataStorage sharedInstance];
    NSManagedObjectContext *moc = [storage mainThreadManagedObjectContext];
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject"
                                                      inManagedObjectContext:moc];
    NSFetchRequest *request = [[NSFetchRequest alloc]init];

    NSString *predicateFrmt = @"bareJidStr like %@ ";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFrmt, chatWithUser];
    request.predicate = predicate;
    NSLog(@"%@",[[NSUserDefaults standardUserDefaults] stringForKey:@"kXMPPmyJID"]);
    [request setEntity:entityDescription];
    NSError *error;
    NSArray *messages_arc = [moc executeFetchRequest:request error:&error];

    [self print:[[NSMutableArray alloc]initWithArray:messages_arc]];
}

-(void)print:(NSMutableArray*)messages_arc{
    @autoreleasepool {
        for (XMPPMessageArchiving_Message_CoreDataObject *message in messages_arc) {
            NSXMLElement *element = [[NSXMLElement alloc] initWithXMLString:message.messageStr error:nil];
            NSLog(@"to param is %@",[element attributeStringValueForName:@"to"]);

            NSMutableDictionary *m = [[NSMutableDictionary alloc] init];
            [m setObject:message.body forKey:@"msg"];

            if ([[element attributeStringValueForName:@"to"] isEqualToString:chatWithUser]) {               
                [m setObject:@"you" forKey:@"sender"];
            }
            else {
                [m setObject:chatWithUser forKey:@"sender"];
            }

            [messages addObject:m];

            NSLog(@"bareJid param is %@",message.bareJid);
            NSLog(@"bareJidStr param is %@",message.bareJidStr);
            NSLog(@"body param is %@",message.body);
            NSLog(@"timestamp param is %@",message.timestamp);
            NSLog(@"outgoing param is %d",[message.outgoing intValue]);
            NSLog(@"***************************************************");
        }
    }
}
Conclusive answered 12/12, 2013 at 6:52 Comment(15)
I not getting one point where should we have to give the other user JID.Can you show the particular place with comment.Inandin
[NSPredicate predicateWithFormat:predicateFrmt, chatWithUser]; here chatWithUser is other user JID you can set there other user JIDConclusive
yes i got it, I am facing some other issue,i am using your code but while i am reterving the code iam getting last two messages of the chat history and i am not getting full history.Plz giveme sol.Inandin
@Inandin i am using the same code and i get all messages of between to JID , check twice (check you sqlite data also and compare both) it's working perfect.Conclusive
i was not using any sqlite i want to reterive whole information from xmpp so can i able do that , and that too while sending the message you have kept one code in the answer, xmppMessageArchivingStorage = [XMPPMessageArchivingCoreDataStorage sharedInstance]; xmppMessageArchivingModule = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:xmppMessageArchivingStorage]; [xmppMessageArchivingModule activate:xmppStream]; [xmppMessageArchivingModule addDelegate:self delegateQueue:dispatch_get_main_queue()];.Can i know when it usefull.what will it perform.Inandin
that code is put when you are create xmppstream connection. that is enable you to create codedata XMPPMessageArchivingCoreDataStorage is for send receive message storage (exmpp not maintain any message history )Conclusive
let us continue this discussion in chatInandin
@MitsBhadeshiya What if I get a message when I am not there in online... means how can we retrieve off line messages.....Bathos
@Mohan if user is offline that all messages stored in server when user online that all messages are send to the user as a delay messages. so that you have to handle that messages... i hope you are understandConclusive
@Mohan can you please give up Mark if you are getting your solution .. :)Conclusive
This is the process for client side archiving. could you please share the retrieval of messages from openfire server?Royer
hi ... in this method i am getting the actual message ...- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message... where i need to write the code for to save the message in the databaseUndamped
Hi @MitulBhadeshiya I have implemented XMPP with openfire and trying to get offline messages. I have initialized XMPPMessageArchiving and also added delegate. But still I am not getting offline message. Have you done any additional setup to get offline messages?Corr
Its working fine but I tried to get all messages after deleting application or by login to another device, in both of this case this solution failed. Any idea for this type of requirement?Selfsupporting
Helllo .... I am facing a issue friends. Unable to archive messages, it gives error here - (id)initWithMessageArchivingStorage:(id <XMPPMessageArchivingStorage>)storage dispatchQueue:(dispatch_queue_t)queue in XMPPMessageArchiving.mAnting
P
4

Please have a detailed Stanza detail at : https://mcmap.net/q/828230/-ios-xmpp-message-archiving-for-group-chat-message

It is Platform independent just you need to understand the structure of Stanza and can be created as per the libraries that you are using.

This is the Series of Stanza that you will need to send to get Archived Messages. For more detail you can checkout XEP 0136 (http://xmpp.org/extensions/xep-0136.html#manual)

REQ

<iq type='get' id='[email protected]'>
       <list xmlns='urn:xmpp:archive'
               with='[email protected]'>
        <set xmlns='http://jabber.org/protocol/rsm'>
            <max>6900</max>
        </set>
      </list>
   </iq>

RES

<iq type="result" id="[email protected]" to="[email protected]/Psi">
<list xmlns="urn:xmpp:archive">
<chat with="[email protected]" start="2014-06-07T06:52:26.041Z"/>
<chat with="[email protected]" start="2014-06-07T07:06:53.372Z"/>
<set xmlns="http://jabber.org/protocol/rsm">
<first index="0">866</first>
<last>867</last>
<count>2</count>
</set>
</list>
</iq>

REQ

<iq type='get' id='[email protected]'>
    <retrieve xmlns='urn:xmpp:archive'  with='[email protected]'  start='2014-06-07T06:52:26.041Z'>
     <set xmlns='http://jabber.org/protocol/rsm'>
       <max>8000</max>
     </set>
    </retrieve>
 </iq>

RES

<iq type="result" id="[email protected]" to="[email protected]/Psi">
<chat xmlns="urn:xmpp:archive" with="[email protected]" start="2014-06-07T06:52:26.041Z">
<from secs="0" jid="[email protected]">
<body>Hello This is Cool</body>
</from>
<set xmlns="http://jabber.org/protocol/rsm">
<first index="0">0</first>
<last>0</last>
<count>1</count>
</set>
</chat>
</iq>

To Fetch List of all Conversations

<iq type='get' id='[email protected]'>
       <list xmlns='urn:xmpp:archive'>
        <set xmlns='http://jabber.org/protocol/rsm'>
            <max>6900</max>
        </set>
      </list>
</iq>
Phenol answered 17/3, 2015 at 11:1 Comment(0)
A
1

When you mention start tag in the request then it matches with the chat having the exact time stamp that's why it returns error code '404' or '500'. I ommited start tag from my request and wrote following code which returns whole chat history with the user.

NSXMLElement *iq1 = [NSXMLElement elementWithName:@"iq"];
[iq1 addAttributeWithName:@"type" stringValue:@"get"];
[iq1 addAttributeWithName:@"id" stringValue:@"pk1"];

NSXMLElement *retrieve = [NSXMLElement elementWithName:@"retrieve" xmlns:@"urn:xmpp:archive"];

[retrieve addAttributeWithName:@"with" stringValue:@"[email protected]"];
NSXMLElement *set = [NSXMLElement elementWithName:@"set" xmlns:@"http://jabber.org/protocol/rsm"];
NSXMLElement *max = [NSXMLElement elementWithName:@"max" stringValue:@"100"];

[iq1 addChild:retrieve];
[retrieve addChild:set];
[set addChild:max];
[[[self appDelegate] xmppStream] sendElement:iq1]; 

Here this will return whole chat history in XML response between user Rahul and the user currently logged in.

For more detailed info please refer this blog http://question.ikende.com/question/363439343236313430

Armchair answered 18/6, 2015 at 5:15 Comment(0)
D
0

XMPPFramework implements XEP-0136. Have you tried using XMPPMessageArchiving to set preferences or synchronize the server's archive to the client?

Dependable answered 23/1, 2013 at 15:18 Comment(1)
Hi @noa! Could you please share an example of how to set preferences for archiving and synchronizing the server's archive to the client.Royer

© 2022 - 2024 — McMap. All rights reserved.