Project

General

Profile

Where is the best place for "Filter and Block message" logic?

Igor Khomenko
Added about 4 years ago

Where is the best place for "Filter and Block message" logic?

For example I would like to build a logic to filter messages for bad words and block messages if there are to many bad words in a message.

Let's say we would like to filter all messages for word 'sucks'.

If there are 3 or less occurrences - just replace it with ****, but if more than 3 - block a message.

I read this guide http://docs.tigase.org/tigase-server/5.3.0/devguide/#_introduction

and found that the best place to block messages is Pre-processor*, so I customised *MessageAmp.java class with next way:

@Override
public boolean preProcess(Packet packet, XMPPResourceConnection xmppResourceConnection, NonAuthUserRepository nonAuthUserRepository, Queue<Packet> packets, Map<String, Object> stringObjectMap) {
    Element bodyChild = packet.getElement().getChild("body");
    String body = bodyChild.getCData();

    String repfrom = "sucks";
    String repto = "****";

    int counter = 0;
    Pattern p = Pattern.compile(repfrom, Pattern.LITERAL);
    Matcher m = p.matcher(filteredBody);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
        counter++;
        m.appendReplacement(sb, repto);
    }
    m.appendTail(sb);

    String filteredBody = sb.toString();

    if(counter > 3){
        return true;
    }

    // set filtered body
    List<XMLNodeIfc> newChildren = new LinkedList<XMLNodeIfc>();
    newChildren.add(new CData(filteredBody));
    bodyChild.setChildren(newChildren);

    return false;
}

It works, but then I found next info in a guide:

Pre-processing - all loaded pre-processors receive the packet for processing. They work within session manager thread and they have no internal queue for processing. As they work within Session Manager thread it is important that they limit processing time to absolute minimum as they may affect the Session Manager performance. The intention for the pre-processors is to allow them for packet blocking. If the pre-processing result is true then the packet is blocked and no further processing is performed.

So I'm not sure about this solution

Could you please assist?


Replies (7)

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 4 years ago

This is correct. A better place for the filtering like in your case would be to implement it as a filter: *XMPPPacketFilterIfc *.

Added by Igor Khomenko about 4 years ago

Thanks Artur,

not sure that I can use XMPPPacketFilterIfc here because I have to filter a message before block it.

As I know, XMPPPacketFilterIfc is the last chaine in Session Manager process packets logic.

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 4 years ago

You can do the same thing in the "filer" as you do in the "preprocessor". You can amend the message or block it completely form delivering. The main difference is that you do it later in the processing chain. This may mean like a bad idea as if you block something you want to do it as quickly as possible. However, the main advantage is that "filter" is being processed in the plugin thread pool. Therefore it does not impact main processing in SessionManager, therefore it overall impact on the server performance is much lower.

Added by Igor Khomenko about 4 years ago

Got it,

so, to block a message in XMPPPacketFilterIfc

public void filter(Packet packet, XMPPResourceConnection session,
            NonAuthUserRepository repo, Queue<Packet> results) {

we should remove this message from the results queue?

like

for (Iterator<Packet> it = results.iterator(); it.hasNext(); ) {
    Packet res = it.next();

   // check a packet here and remove if need
   // ...

    it.remove();
}
Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 4 years ago

Yes, this is correct.

Added by Igor Khomenko about 4 years ago

Thanks Artur,

could you please confirm a logic to filter a message

For example I would like to update message's body

Should I do something like this:

public void filter(Packet packet, XMPPResourceConnection session,
            NonAuthUserRepository repo, Queue<Packet> results) {

        for (Iterator<Packet> it = results.iterator(); it.hasNext(); ) {
        Packet res = it.next();

           // find a packet in a queue
           if(res.getStanzaId() == packet.getStanzaId()) {

               // set filtered body
              List<XMLNodeIfc> newChildren = new LinkedList<XMLNodeIfc>();
               newChildren.add(new CData("new body"));
               res.getElement().getChild("body").setChildren(newChildren);
        }
    }
}

As I understand we can't work with a packet entity here, only with results

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 4 years ago

Looks correct to me.

    (1-7/7)