14

I am developing a chat app for iPhone using XMPP and openfire server,OpenFire server is storing all the chat history between users but When I try to retrieve the chat history for a particular user I get only the date and the number of chat messages but not the actual text messages

I have already installed open archive plugin for message archiving on openfire

This is the stanza which I have passed to Openfire Server

    <iq type='get' id='pk1'>
    <list xmlns='urn:xmpp:archive'
    with='piyush@openfire'>
    <set xmlns='http://jabber.org/protocol/rsm'>
    <max>30</max>
    </set>
    </list>
    </iq>

This is the result which I received from server

  <iq type="result" id="pk1" to="vivek@openfire/iphone">
  <list xmlns="urn:xmpp:archive">
  <chat with="piyush@openfire" start="2012-07-04T13:16:12.291Z"/>
  <chat with="piyush@openfire" start="2012-07-05T08:25:31.555Z"/>
  <chat with="piyush@openfire" start="2012-07-05T12:38:24.098Z"/>
  <set xmlns="http://jabber.org/protocol/rsm">
  <first index="0">15</first>
  <last>25</last>
  <count>3</count>
  </set>
  </list>
  </iq>

This is the result which I want and which I expected

 <iq type='result' to='vivek@openfire/iphone' id='page1'>
 <chat xmlns='urn:xmpp:archive'
    with='piyush@openfire'
    start='2012-07-04T13:16:12.291Z'
    subject='She speaks!'
    version='4'>
<from secs='0'><body>Art thou not Romeo, and a Montague?</body></from>
<to secs='11'><body>Neither, fair saint, if either thee dislike.</body></to>
.
[98 more messages]
.
<from secs='9'><body>How cam'st thou hither, tell me, and wherefore?</body></from>
<set xmlns='http://jabber.org/protocol/rsm'>
  <first index='0'>0</first>
  <last>99</last>
  <count>217</count>
</set>

Please Help me out to get the desired result

Thanks

Keith OYS
  • 2,285
  • 5
  • 32
  • 38
Piyush Kashyap
  • 1,965
  • 1
  • 14
  • 16
  • 1
    I think this is more an OpenFire API problem than an iOS problem. – Pfitz Jul 09 '12 at 14:38
  • Hey piyush, m also trying to achieve the same thing.But (please forgive my ignorance) I have no clue how to send this stanza to the openfire server.Is there an api call for it?Would you mind elaborating about it a bit – Anidhya Ahuja Feb 04 '13 at 04:59
  • @Piyush Kashyap how did you enable the chat history , as i have installed `monitoring` plugin but when i fire above stanza it returns feature not implemented – Hunt Dec 30 '13 at 16:44
  • please have a look: http://stackoverflow.com/a/29097289/2225439 Hope it will help. – Mrug Mar 17 '15 at 10:56
  • @KeithOYS, bro can you help me this problem https://stackoverflow.com/questions/44172852/how-to-parse-xmppmessage-element-attribute-and-node-in-xmppframework-with-swif ? – May Phyu May 25 '17 at 08:57

5 Answers5

17

You have to do a request with <retrieve> (see http://xmpp.org/extensions/xep-0136.html) then you can take a specific time from the received <list> result. For example:

Send:

    <iq type='get' id='pk1'>
       <list xmlns='urn:xmpp:archive'
               with='piyush@openfire'>
        <set xmlns='http://jabber.org/protocol/rsm'>
            <max>30</max>
        </set>
      </list>
   </iq>

Receive:

 <iq type="result" id="pk1" to="vivek@openfire/iphone">
     <list xmlns="urn:xmpp:archive">
      <chat with="piyush@openfire" start="2012-07-04T13:16:12.291Z"/>
      <chat with="piyush@openfire" start="2012-07-05T08:25:31.555Z"/>
      <chat with="piyush@openfire" start="2012-07-05T12:38:24.098Z"/>
      <set xmlns="http://jabber.org/protocol/rsm">
          <first index="0">15</first>
           <last>25</last>
           <count>3</count>
      </set>
    </list>
 </iq>            

Now you choose one of starts and send (date and hour must be exacts):

  <iq type='get' id='pk1'>
    <retrieve xmlns='urn:xmpp:archive'
        with='piyush@openfire''
        start='2012-07-04T13:16:12.291Z'>
     <set xmlns='http://jabber.org/protocol/rsm'>
       <max>100</max>
     </set>
    </retrieve>
 </iq>

You will receive something like this (depends the max value -> max=30, bodies=30):

   <iq type='result' to='vivek@openfire/iphone' id='page1'>
      <chat xmlns='urn:xmpp:archive'
             with='piyush@openfire'
              start='2012-07-04T13:16:12.291Z'
            subject='She speaks!'
       version='4'>
         <from secs='0'><body>Art thou not Romeo, and a Montague?</body></from>
         <to secs='11'><body>Neither, fair saint, if either thee dislike.</body></to>
          .
          [28 more messages]
          .
         <from secs='9'><body>How cam'st thou hither, tell me, and therefore?           </body>   
         </from>
      <set xmlns='http://jabber.org/protocol/rsm'>
       <first index='0'>0</first>
       <last>29</last>
       <count></count>
     </set>
  <iq>
Uluk Biy
  • 48,655
  • 13
  • 146
  • 153
DRMA
  • 186
  • 2
  • 3
10

To retrieve the Specific time of chat

Send it to get the time:

 NSXMLElement *iq1 = [NSXMLElement elementWithName:@"iq"];
 [iq1 addAttributeWithName:@"type" stringValue:@"get"];
 [iq1 addAttributeWithName:@"id" stringValue:@"pk1"];
 NSXMLElement *retrieve = [NSXMLElement elementWithName:@"list" xmlns:@"urn:xmpp:archive"];
 [retrieve addAttributeWithName:@"with" stringValue:@"amit@openfire"];
 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];


 [xmppStream sendElement:iq1];

To retrieve the Chat History

Use Start date and send:

 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:@"amit@openfire"];
 [retrieve addAttributeWithName:@"start" stringValue:@"2013-11-18T05:11:53.460Z"];
 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];
 [xmppStream sendElement:iq1];
legoscia
  • 39,593
  • 22
  • 116
  • 167
Amit Gupta
  • 371
  • 2
  • 9
  • 1
    @Amit Gupta yes i also stuck here. please tell me what is pk1 here ? – Sam Dec 18 '13 at 05:38
  • If i do the above code, then xmppstream delegate method i.e didReceiveMessage will call, but im not getting any result, im using open fire, so can i do any trick on my server, please help me. – Sri.. Jan 21 '14 at 09:40
  • 1
    I am getting Error 500,Feature not implemented error , What to do?? – Mrug Feb 26 '14 at 07:52
  • 1
    Pk1 is the custom id name. You can use any id name you want. No issues. – Karun Mar 10 '14 at 08:10
  • I am getting error 503 service unavailable. I am using OpenFire. Could you tell me its reason. For Details Please check: http://stackoverflow.com/questions/35935397/get-xmpp-chat-history-openfire – Hassan Aftab Mar 11 '16 at 14:03
2

Firstly, to retrieve chat history from openfire you need install Open Archive plugin because Monitering Plugin is just for monitering and logging chat history at admin panel so once you will install Open Archive you won't get any error with code '500'.

You can download and learn to install Open Archive from the following links.

https://nexus.reucon.com/content/repositories/opensource-snapshots/com/reucon/openfire/plugins/archive/

https://maven.reucon.com/projects/public/archive/

Another issue in above code is that 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'. 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:@"rahul@vishals-mac-pro.local"];
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

sajgan2015
  • 305
  • 3
  • 10
1

Swift version of fetch archive messages from openfire server Request:

func getArchieveMessages(){
        let iQ = DDXMLElement.elementWithName("iq")
        iQ.addAttributeWithName("type", stringValue: "get")
        iQ.addAttributeWithName("id", stringValue: "page1")
        let list = DDXMLElement.elementWithName("retrieve")
        list.addAttributeWithName("xmlns", stringValue: "urn:xmpp:archive")
        list.addAttributeWithName("with", stringValue: "partner@domain")
        let set = DDXMLElement.elementWithName("set")
        set.addAttributeWithName("xmlns", stringValue: "http://jabber.org/protocol/rsm")
        let max = DDXMLElement.elementWithName("max")
        max.addAttributeWithName("xmlns", stringValue: "http://jabber.org/protocol/rsm")
        //(max as! DDXMLElement).setStringValue("30")
        (set as! DDXMLElement).addChild(max as! DDXMLNode)
        list.addChild(set as! DDXMLNode)
        iQ.addChild(list as! DDXMLNode)
        xmppStream.sendElement(iQ as! DDXMLElement)
    }

Response:

func xmppStream(sender: XMPPStream!, didReceiveIQ iq: XMPPIQ!) -> Bool {
        let chat = iq.elementForName("chat")
        let chats = (chat as DDXMLElement).children()
        for chat in chats{
            let msg = chat
            let body = (msg as! DDXMLElement).elementForName("body")
            if body != nil{
                if body.stringValue() != nil{
                    //print(body.stringValue()!)
                    chatMessages.append(body.stringValue()!)
                    if msg.attributeForName("jid") == nil{
                        type.append("Send")
                    }
                    else{
                        type.append("Receive")
                    }
                }
            }
        }
        print("Did receive IQ")
        return false
    }

*with is the jid of the person whose archive messages you want to fetch

Mughees
  • 607
  • 1
  • 6
  • 15
1

an example to get archived messages in Swift 4

declares and initializes the variables XMPPMessageArchivingCoreDataStorage where I initialize the XMPPStream

var xmppMessageStorage: XMPPMessageArchivingCoreDataStorage?
var xmppMessageArchiving: XMPPMessageArchiving?

xmppMessageStorage = XMPPMessageArchivingCoreDataStorage.sharedInstance()
    xmppMessageArchiving = XMPPMessageArchiving(messageArchivingStorage: xmppMessageStorage)

    xmppMessageArchiving?.clientSideMessageArchivingOnly = true
    xmppMessageArchiving?.activate(stream)
    xmppMessageArchiving?.addDelegate(self, delegateQueue: DispatchQueue.main)

doing this, whenever a message arrives, this will cause it to be archived without needing to do anything else.

then, to retrieve the archived message

func RecibedMessageArchiving(idFriend: String) {

        let JabberIDFriend = idFriend   //id friend chat, example test1@example.com


        let moc = xmppMessageStorage?.mainThreadManagedObjectContext
        let entityDescription = NSEntityDescription.entity(forEntityName: "XMPPMessageArchiving_Message_CoreDataObject", in: moc!)
        let request = NSFetchRequest<NSFetchRequestResult>()
        let predicateFormat = "bareJidStr like %@ "
        let predicate = NSPredicate(format: predicateFormat, JabberIDFriend)

        request.predicate = predicate
        request.entity = entityDescription

        //jabberID id del usuario, cliente
        var jabberIDCliente = ""
        if let jabberj = globalChat.value(forKey: "jabberID"){
            jabberIDCliente = jabberj as! String
        }


        do {
            let results = try moc?.fetch(request)

            for message: XMPPMessageArchiving_Message_CoreDataObject? in results as? [XMPPMessageArchiving_Message_CoreDataObject?] ?? [] {

                var element: DDXMLElement!
                do {
                    element = try DDXMLElement(xmlString: (message as AnyObject).messageStr)
                } catch _ {
                    element = nil
                }

                let body: String
                let sender: String
                let date: NSDate
                let isIncomings: Bool
Jose Tovar
  • 149
  • 2
  • 13