    // PutFilter.java
    // $Id: GrepPutFilter.html,v 1.2 1999/10/27 22:10:35 ylafon Exp $
    // (c) COPYRIGHT MIT and INRIA, 1996.
    // Please first read the full copyright statement in file COPYRIGHT.html

    package org.w3c.jigsaw.filters;

    import java.io.*;

    import org.w3c.tools.resources.*;
    import org.w3c.www.http.*;
    import org.w3c.jigsaw.http.*;
    import org.w3c.jigsaw.frames.*;
    import org.w3c.jigsaw.resources.*;

    public class GrepPutFilter extends PutFilter {

        /**
         * Attribute index - The string to grep.
         */
        protected static int ATTR_FORBIDSTRING = -1;

        /**
         * Attribute index - The url to redirect.
         */
        protected static int ATTR_REDIRECT = -1;

        static {
    	Class     c = null;
    	Attribute a = null;

    	try {
    	    c = Class.forName("org.w3c.jigsaw.filters.GrepPutFilter");
    	} catch (Exception ex) {
    	    ex.printStackTrace();
    	    System.exit(1);
    	}
    	a = new StringAttribute("forbidden-string"
    				, null
    				, Attribute.EDITABLE|Attribute.MANDATORY);
    	ATTR_FORBIDSTRING = AttributeRegistry.registerAttribute(c, a);

    	a = new StringAttribute("redirect-url"
    				, null
    				, Attribute.EDITABLE|Attribute.MANDATORY);
    	ATTR_REDIRECT = AttributeRegistry.registerAttribute(c, a);
        }

        protected String getForbiddenString() {
    	return (String) getValue(ATTR_FORBIDSTRING, null);
        }

        protected String getRedirectURL() {
    	return (String) getValue(ATTR_REDIRECT, null);
        }

        /**
         * Search the forbidden string in the body, if found return
         * an ACCES FORBIDDEN Reply.
         * @param request The request that is about to be processsed.
         */

        public ReplyInterface ingoingFilter(RequestInterface req) {
    	Request request = (Request) req;
    	String expect = request.getExpect();
    	if (expect != null) {
    	    if (expect.startsWith("100")) { // expect 100?
    		Client client = request.getClient();
    		if (client != null) {
    		    try {
    			client.sendContinue();
    		    } catch (java.io.IOException ex) {
    			return null;
    		    }
    		}
    	    }
    	}
    	if(request.getMethod().equals("PUT")) {
    	    InputStream in = null;
    	    try {
    		in = request.getInputStream();
    		if ( in == null ) {
    		    return null;
    		}
    	    } catch (IOException ex) {
    		return null;
    	    }
    	    // verify that the target resource is putable
    	    ResourceReference rr = request.getTargetResource();
    	    if (rr != null) {
    		try {
    		    FramedResource target = (FramedResource) rr.lock();
    		    HTTPFrame frame = null;
    		    try {
    			frame = (HTTPFrame) target.getFrame(
    			   Class.forName("org.w3c.jigsaw.frames.HTTPFrame"));
    		    } catch (ClassNotFoundException cex) {
    			cex.printStackTrace();
    			//big big problem ...
    		    }
    		    if (frame == null) // can't be putable
    			return null;
    		    // now we can verify if the target resource is putable
    		    if (! frame.getPutableFlag()) {
    			return null;
    		    }
    		} catch (InvalidResourceException ex) {
    		    ex.printStackTrace();
    		    // problem ...
    		} finally {
    		    rr.unlock();
    		}
    	    }

    	    if (searchForbiddenString(in)) {
    		Reply error = request.makeReply(HTTP.FORBIDDEN);
    		error.setContent ("<p>the string \""+getForbiddenString()+
    				  "\" is forbidden.</p><br> click "+
    				  "<A HREF=\""+getRedirectURL()+"\">here</A>"+
    				  " for explaination.");
    		return error;
    	    }
    	    return null;
    	} else
    	    return null;
        }

        protected boolean searchForbiddenString(InputStream in) {
    	try {
    	    int len = in.available();
    	    in.mark(len);

    	    int c;
    	    byte forbid [] = getForbiddenString().getBytes();
    	    int lenforbid = forbid.length;
    	    int forbididx = 0;

    	    while ((c = in.read()) != -1) {
    		if (forbid[forbididx] == (byte) c) {
    		    if (++forbididx == forbid.length) {
    			in.reset();
    			return true;
    		    }
    		} else
    		    forbididx = 0;
    	    }
    	    in.reset();
    	    return false;
    	} catch (IOException ex) {
    	    return false;
    	}
        }

    }