Issues with XMPP MAM Query in Delphi

Hello everyone,

I’ve been working on implementing MAM (Message Archive Management) in my Delphi XMPP client and am facing an issue. When I send a MAM query to the server, the response I receive is the MAM request itself instead of the expected archived messages.

Here’s how I’m constructing the MAM request:

function TfmxJabberXml.CreateMAMRequest(AFrom, ATo, AAfterID, ABeforeID: string): string;
var
  idFields: string;
begin
  if AAfterID <> '' then
    idFields := idFields + Format('<field var="after-id"><value>%s</value></field>', [AAfterID]);

  if ABeforeID <> '' then
    idFields := idFields + Format('<field var="before-id"><value>%s</value></field>', [ABeforeID]);

  Result := Format('<iq type="set" id="%s" from="%s" to="%s">' +
                   '<query xmlns="urn:xmpp:mam:2">' +
                   '<x xmlns="jabber:x:data" type="submit">' +
                   '<field var="FORM_TYPE" type="hidden"><value>urn:xmpp:mam:2</value></field>' +
                   '%s' + 
                   '</x>' +
                   '</query>' +
                   '</iq>',
                   [GetUniqueID, AFrom, ATo, idFields]);
end;

I’ve tried both with and without the ‘with’ field, as per the XMPP MAM specification.

When I send this MAM request, I expect a series of archived messages in response, but instead, I get the request itself as the response. Here’s how I’m handling the response:

procedure TfmxJabberXml.ProcessMAMResponse(ANode: PXMLNode);
var
  msgNode, fwdNode: PXMLNode;
  fromJid, messageBody: string;
begin
  for msgNode in ANode.SelectNodes('result') do
  begin
    fwdNode := msgNode.SelectNode('forwarded/message');
    if Assigned(fwdNode) then
    begin
      fromJid := fwdNode.GetAttribute('from');
      messageBody := fwdNode.SelectNode('body').Text;
      
      if Assigned(fOnChatHistoryReceived) then
        fOnChatHistoryReceived(fromJid, messageBody);
    end;
  end;
end;

If anyone has faced a similar issue or can point out what might be going wrong, I would greatly appreciate it. Thank you in advance for your assistance.


I hope this draft helps in getting a solution to your problem.

Can you provide a dump of the XMPP traffic that is being exchanged between your client and the server?

Hello,

Sorry for the delay. I am receiving the following response from my OpenFire server for the request:

<iq type="set" id="lastNMessages">
  <query xmlns="urn:xmpp:mam:2" queryid="lastNMessages">
    <x xmlns="jabber:x:data" type="submit">
      <field var="FORM_TYPE" type="hidden">
        <value>urn:xmpp:mam:2</value>
      </field>
      <field var="with">
        <value>renan@192.168.1.10</value>
      </field>
    </x>
    <set xmlns="http://jabber.org/protocol/rsm">
      <max>10</max>
    </set>
  </query>
</iq>

The sending is as usual according to the debugger. It’s the output of the function function TfmxJabberXml.CreateMAMRequest(AFrom, ATo, AAfterID, ABeforeID: string): string; that I specified above.


I do not think that this is what you receive from Openfire. When you receive something from Openfire, it nearly always contains a ‘to’ and ‘from’ attribute on the first element. That is not the case here.

Is it possible that you somehow intercepted the outgoing stanza, rather than the incoming one?

Is there anything in the Openfire logs that suggests that something is going wrong when you execute your code?

I was thinking that it might just be the server echoing back what I send. Today’s logs are:

2023.10.23

2023.10.23 08:19:22 e[32mINFO e[m [main]: org.jivesoftware.util.cache.ConsistencyMonitor - Applying configuration for cache consistency check. Enabled: false
2023.10.23 08:19:22 e[32mINFO e[m [main]: org.jivesoftware.openfire.XMPPServer - Openfire 4.7.5 [Oct 23, 2023 08:19:22]
2023.10.23 08:19:22 e[33mWARN e[m [PluginMonitorTask-2]: org.jivesoftware.util.LocaleUtils - Missing resource for key: system_property.xmpp.xmlutil.parser.core-pool-size in locale pt_BR
2023.10.23 08:19:22 e[33mWARN e[m [PluginMonitorTask-2]: org.jivesoftware.util.LocaleUtils - Missing resource for key: system_property.xmpp.xmlutil.parser.maximum-pool-size in locale pt_BR
2023.10.23 08:19:22 e[33mWARN e[m [PluginMonitorTask-2]: org.jivesoftware.util.LocaleUtils - Missing resource for key: system_property.xmpp.xmlutil.parser.keep_alive_time in locale pt_BR
2023.10.23 08:19:23 e[33mWARN e[m [PluginMonitorTask-2]: org.jivesoftware.openfire.container.AdminConsolePlugin - Admin console: CertificateStoreManager has not been initialized yet. HTTPS will be unavailable.
2023.10.23 08:19:26 e[32mINFO e[m [PluginMonitorTask-2]: org.jivesoftware.util.cache.CacheFactory - Created cache [org.jivesoftware.util.cache.DefaultLocalCacheStrategy] for Favicon Misses
2023.10.23 08:19:26 e[32mINFO e[m [PluginMonitorTask-2]: org.jivesoftware.util.cache.CacheFactory - Created cache [org.jivesoftware.util.cache.DefaultLocalCacheStrategy] for Favicon Hits
2023.10.23 08:19:26 e[32mINFO e[m [PluginMonitorTask-2]: org.jivesoftware.openfire.container.AdminConsolePlugin - Administration Console listening at http://desktop-dfn0tmd:9090
2023.10.23 08:19:26 e[32mINFO e[m [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginManager - Successfully loaded plugin 'admin'.

I sent messages and received them, tried to fetch old messages and it returned what I had mentioned I thought was an echo on the server, but it might be some redirection error that I’m not seeing, maybe here?

function TfmxJabberXml.CreateMAMRequest(AFrom, ATo, AAfterID, ABeforeID: string): string;
var
  idFields: string;
begin
  if AAfterID <> '' then
    idFields := idFields + Format('<field var="after-id"><value>%s</value></field>', [AAfterID]);

  if ABeforeID <> '' then
    idFields := idFields + Format('<field var="before-id"><value>%s</value></field>', [ABeforeID]);

  Result := Format('<iq type="set" id="%s" from="%s" to="%s">' +
                   '<query xmlns="urn:xmpp:mam:2">' +
                   '<x xmlns="jabber:x:data" type="submit">' +
                   '<field var="FORM_TYPE" type="hidden"><value>urn:xmpp:mam:2</value></field>' +
                   '%s' +
                   '</x>' +
                   '</query>' +
                   '</iq>',
                   [GetUniqueID, AFrom, ATo, idFields]);
end;

Thank you in advance for your patience as I might be very “noobish” in my questions and implementation.

I don’t know Delphi, so I can’t help you with the code much.

The server will not ‘echo’ a stanza without changing the addressing (the to and from attributes) and attaching some kind of error to it. That’s not the case in your example.

I strongly suspect that what you are seeing is not something that is returned by the server.

If you enable ‘trace’ logging on the server, then you should see activity when a MAM request is being processed. What you copied now are all log messages that are unrelated.