• Welcome to Valhalla Legends Archive.
 

Simple character filtering system

Started by Tuberload, February 20, 2004, 06:26 PM

Previous topic - Next topic

Tuberload

EDIT (Disclaimer): There is some profanity in this post, but I assure you it is only being used for a better cause.

After reading threads about filtering out incoming data from battle.net as a means of protection, I started work on a plug-able filtering system for character arrays. It is nothing special at the moment, but it does contain some of what I consider bare essentials for a filtering system. Future versions will use class loaders, to allow individual programmers a way to make their own filters.

Filter.java:
    This is the interface for filters. It makes it so I can create new filters, without modifying existing code through inheritance.

/**
*   Interface for filters.
*   @author Tuberload
*   @version 1.0
*/

public interface Filter
{
   /**
    *   Executes the filter.
    *   @param data The data to be filtered.
   */
   public CharBuffer execute (CharBuffer data);
   /**
    *   Returns the version of the filter.
   */
   public String version();
   /**
    *   Returns the author of the filter.
   */
   public String author();
}


ProfanityFilter.java:
    A simple example of how a filter might work.

/**
*   Filters out common profanity.
*   @author Tuberload
*   @version 1.0
*/

public class ProfanityFilter implements Filter
{
   private static final String[] PROFANITY =
      { "shit", "fuck", "ass", "bitch", "pussy", "dick", "whore", "slut" };
   private static final char REPLACEMENT = '#';
   /**
    *   Executes the filter.
    *   @param data The data to be filtered.
    *   @return Filtered data.
   */
   public CharBuffer execute (CharBuffer data)
   {
      if (data != null)
      {
         int index = 0;
         for (int i = 0; i < PROFANITY.length; i++)
         {
            index = data.indexOf (PROFANITY[i].toCharArray());
            if (index != -1)
            {
               data.fillRegion (index, PROFANITY[i].length()-1,
                              REPLACEMENT);
            }
         }
      }
      return data;
   }
   
   /**
    *   Returns the author of the filter.
   */
   public String author()
   {
      return new String ("Tuberload");
   }
   
   /**
    *   Returns the version of the filter
   */
   public String version()
   {
      return new String ("v1.0");
   }
}



CharBuffer.java:
    A wrapper for char[] arrays to add whatever functionality I think is necessary. I know there is probably some pre-made classes for this in the Java API, but what's the fun in that.

/**
*   Character buffer
*   @author Tuberload
*   @version 1.0
*/

public class CharBuffer
{
   private char[] buffer;
   private static final int DEF_BUF_LEN = 256;
   
   /**
    *   Create a new DataBuffer and populate it with data.
    *   @param data The data to be inserted into the buffer.
   */
   public CharBuffer (char[] data)
   {
      int dataLength = data.length;
      if (dataLength > 0)
      {
         buffer = new char[dataLength];
         System.arraycopy (data, 0, buffer, 0, dataLength);
      }
      else
      {
         buffer = new char[DEF_BUF_LEN];
      }
   }
   
   /**
    *   Gets characters from the buffer.
    *   @param srcBegin The index of the first character to be retrieved.
    *   @param srcEnd The index of the last character the be retrieved.
   */
   public char[] getChars (int srcBegin, int srcEnd)
   {
      int length = srcEnd - srcBegin;
      char[] data = new char[length];
      System.arraycopy (buffer, srcBegin, data, 0, length);
      
      return data;
   }
   
   /**
    *   Retrieves the entire data buffer.
   */
   public char[] getChars()
   {
      return buffer;
   }
   
   /**
    *   Replace a region of the data buffer.
    *   @param start The index of the region to be replaced.
    *   @param data Data to be inserted into the buffer.
   */
   public void replaceRegion (int start, char[] data)
   {
      int pos = 0;
      for (int i = start; i < data.length; i++)
      {
         buffer[i] = data[pos++];
      }
   }
   
   /**
    *   Fill a region of the data buffer with a specific character.
    *   @param start The index of the region to be replaced.
    *   @param length Length of region to be filled.
    *  @param replacement The character used to fill the region
   */
   public void fillRegion (int start, int length, char replacement)
   {
      for (int i = start; i <= start+length; i++)
      {
         buffer[i] = replacement;
      }
   }
   
   /**
    *   Finds the index of a character array inside of the buffer.
    *   @param data Data to look for inside of the buffer.
    *   @return The index of the data. -1 if array not found.
   */
   public int indexOf (char[] data)
   {
      int contains = -1;   // If data array is not found -1 will be returned
      
      if (data != null && data.length > 0)
      {
         int pos = 0;   // Position inside of data array

         for (int i = 0; i < buffer.length; i++)
         {
            if (buffer[i] == data[pos++])   // A match was found
            {
               if (pos == data.length)      // Check if data array found
               {
                  contains = i-data.length+1;      // Index of data array
                                          // in the buffer
                  break;
               }
            }
            else   // A match was not found
            {
               if (pos != 0)   // Check if the position in data was > 0 and if
                           // so restart the search at failed index
               {
                  pos = 0;
                  if (buffer[i] == data[pos++]);
                  else pos = 0;
               }
            }
         }
      }
      
      return contains;
   }
}


FilterTest.java:
    A quick example of how to use the filtering system.

public class FilterTest
{
   public static void main (String[] args)
   {
      String data = "This is so fucking cool asshole";
      CharBuffer buffer = new CharBuffer (data.toCharArray());
      
      System.out.println (buffer.getChars());
      
      ProfanityFilter filter = new ProfanityFilter ();
      buffer = filter.execute (buffer);
      
      System.out.println (buffer.getChars());
   }
}
Quote"Pray not for lighter burdens, but for stronger backs." -- Teddy Roosevelt
"Your forefathers have given you freedom, so good luck, see you around, hope you make it" -- Unknown

Kp

A minor comment about your choice of filters -- as written, it'd be bad for you to filter "ass", because you're not detecting its use in larger words, such as assignment. :P
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Hostile

#2
Don't forget how bad Dick will feel either.
- Hostile is sexy.

K

#3
Quote from: Kp on February 21, 2004, 11:46 AM
A minor comment about your choice of filters -- as written, it'd be bad for you to filter "ass", because you're not detecting its use in larger words, such as assignment. :P

True; it would be better to perhaps use regular expressions and do something like (^|\W)ass(\W|$)

Tuberload

Quote from: K on February 22, 2004, 03:13 PM
Quote from: Kp on February 21, 2004, 11:46 AM
A minor comment about your choice of filters -- as written, it'd be bad for you to filter "ass", because you're not detecting its use in larger words, such as assignment. :P

True; it would be better to perhaps use regular expressions and do something like (^|\W)ass(\W|$)

Bah! ;) I will modify the code using my own algorithms here soon. Plus I have a few other fixes/additions to add as well.
Quote"Pray not for lighter burdens, but for stronger backs." -- Teddy Roosevelt
"Your forefathers have given you freedom, so good luck, see you around, hope you make it" -- Unknown

iago

Look up perltools.  It lets you use perl regular expressions, like mystr = perltools.filter(mystr, "s/ass/bum/g");
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Banana fanna fo fanna