// 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;
	} 
    }

}