package coreservlets.filters;

import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

/** Filtr blokuje dostęp do strony każdemu, kto łączy się bezpośrednio
 *  z zabronionej witryny lub za pośrednictwem łącza z takiej witryny
 *  <P>
 *  Taken from Core Servlets and JavaServer Pages Volume II
 *  from Prentice Hall and Sun Microsystems Press,
 *  http://volume2.coreservlets.com/.
 *  (C) 2007 Marty Hall, Larry Brown, and Yaakov Chaikin;
 *  may be freely used or adapted.
 */
public class BannedAccessFilter implements Filter {
  private HashSet<String> bannedSiteTable;

  /** Zablokowanie dostępu, jeśli wywołanie pochodzi z zabronionej witryny
   *  lub łącze wywołujące znajduje się na zabronionej witrynie.
   */
  public void doFilter(ServletRequest request,
                       ServletResponse response,
                       FilterChain chain)
      throws ServletException, IOException {
    HttpServletRequest req = (HttpServletRequest)request;
    String requestingHost = req.getRemoteHost();
    String referringHost =
      getReferringHost(req.getHeader("Referer"));
    String bannedSite = null;
    boolean isBanned = false;
    if (bannedSiteTable.contains(requestingHost)) {
      bannedSite = requestingHost;
      isBanned = true;
    } else if (bannedSiteTable.contains(referringHost)) {
      bannedSite = referringHost;
      isBanned = true;
    }
    if (isBanned) {
      showWarning(response, bannedSite);
    } else {
      chain.doFilter(request,response);
    }
  }

  /** Utworzenie tabeli z zabronionymi witrynami
   *  na podstawie parametrów inicjalizacyjnych.
   */
  public void init(FilterConfig config)
      throws ServletException {
    bannedSiteTable = new HashSet<String>();
    String bannedSites =
      config.getInitParameter("bannedSites");
    if (bannedSites == null) {
    	return;
    }
    // Podział na podstawie jednego lub więcej znaków niewidocznych.
    String[] sites = bannedSites.split("\\s++");
    for (String bannedSite: sites) {
    	bannedSiteTable.add(bannedSite);
    	System.out.println("Zabroniona " + bannedSite);
    }
  }
  
  public void destroy() {}

  private String getReferringHost(String refererringURLString) {
    try {
      URL referringURL = new URL(refererringURLString);
      return(referringURL.getHost());
    } catch(MalformedURLException mue) { // Malformed or null
      return(null);
    }
  }

  // Zastąpienie odpowiedzi zwróconej do użytkownika,
  // który pochodzi lub odwołuje się z zabronionej witryny.

  private void showWarning(ServletResponse response,
                           String bannedSite)
      throws ServletException, IOException {
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    String docType =
      "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " +
      "Transitional//EN\">\n";
    out.println
      (docType +
       "<HTML>\n" +
       "<HEAD><TITLE>Dostęp zabroniony</TITLE></HEAD>\n" +
       "<BODY BGCOLOR=\"WHITE\">\n" +
       "<H1>Dostęp zabroniony</H1>\n" +
       "Przepraszamy, dostęp z lub za pośrednictwem witryny " + bannedSite + "\n" +
       "jest zablokowany.\n" +
       "</BODY></HTML>");
  }
}
