views:

212

answers:

4

I have Ejabberd up and running with test users, and its working fine. I want to write a module that can intercept messages and modify them, as follows :

  1. intercept "messages"
  2. send them to a php file
  3. get the result from the same php file (immediate)
  4. Modify the message stanza and send it down the wire to the recipient

The ejabberd documentation is weak and tutorials are non-existent. Can you give me some sample code that does this. I can then figure how to configure it for my needs.

Thanks a bundle!

Adil

+2  A: 

Here's the basic example of such module:

-module(packet_interceptor).
-behaviour(gen_mod).

-export([start/2,
         stop/1]).

-export([on_filter_packet/1]).


start(Host, _Opts) ->
    ejabberd_hooks:add(filter_packet, global, ?MODULE, on_filter_packet, 0).

on_filter_packet({From, To, XML} = Packet) ->
    %% does something with a packet
    %% should return modified Packet or atom `drop` to drop the packet
    Packet.

And make sure to add this module into ejabberd's configuration into module section:

{modules,
 [...
  ...
  ...
  {packet_interceptor, []}
 ]}.

Just extend on_filter_packet/1 the way you want and return appropriately modified packet.

gleber
Thanks gleber. I've already gone this far and i can see from the ?INFO_MSG that my packet_interceptor is being called.How can send this XML data to php (via ?xml=<base64encoded string>)and retrieve the resulting XML and then pass it to the recipient?
Adil
You should probably use an http:request/1,2,3 to call your PHP script. IIRC on_filter_packet will be called in the same process as ejabberd's router process, so you shouldn't do anything too time-consuming there. So a solution is to spawn a new process for this, return a `drop` atom (to drop the packet) and when modified stanza is returned from PHP send it along using `ejabberd_router:route(From, To, Packet)`. Probably on_filter_packet will be called again on the new packet you sent, so make sure to detect it and not process it twice.
gleber
To detect the packet you can add `<x/>` tag into a packet with your own `xmlns`.
gleber
A: 

Hi,

It seems that what you want to do there is to create an XMPP server component. Lots of things has already been said on that post Which XMPP server to experiment developing a server component.

I can link you some useful links:

Gleber's solution is really "ejabberd" oriented (certainly the easiest one in your case), whereas this one can scale with other XMPP servers.

dasilvj
Thx for the links.
Adil
It is ejabberd-oriented as the question is ;)
gleber
A: 

There is the interface:

ejabberd_router:register_route(MyHost)

which I have used in the past and works well. Once the MyHost is registered with ejabberd, the module will receive the communications intended to MyHost through info messages (assuming gen_server).

As noted by @gleber, don't forget to add your module to the configuration file.

jldupont
Hi jldupont.I didnt quite understand what register_route does and what exatly is MyHost. Can you point me to where i should read further?
Adil
ejabberd_router:register_route/1 is used to create your own (sub)domain and to capture all packets which are sent to JID in this (sub)domain. You can read more here - http://www.process-one.net/en/wiki/ejabberd_route_table/
gleber
A: 

gleber's example is excellent. I also wrote a more complex example of packet manipulation that I built for Chesspark called mod_sunshine.

How can send this XML data to php (via ?xml=) and retrieve the resulting XML and then pass it to the recipient?

If you have a recent version of ejabberd that uses exmpp, you can use exmpp_xml:node_to_binary/1 or exmpp_xml:node_to_list/1 to turn the internal representation of the XML to a binary or a string respectively.

There were similarly named functions in the older ejabberd, but within the xml module.

metajack
Thanks metajack. I have read your article earlier. It helped me to get a start
Adil