package stocks;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import sun.misc.BASE64Decoder;

/** Serwlet wskazujący papiery, w które warto inwestować.
 *  Jest on na tyle wyrafinowany, że dostęp do niego mają tylko
 *  wybrani użytkownicy (to znaczy ci, którzy wnieśli
 *  odpowiednią opłatę).
 *  <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 StockTip extends HttpServlet {

  /** Blokuje dostęp wszystkim użytkownikom, którzy nie znają
   *  odpowiedniej kombinacji nazwa użytkownika/hasło.
   */
  
  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
      throws ServletException, IOException {
    String authorization = request.getHeader("Authorization");
    if (authorization == null) {
      askForPassword(response);
    } else {
      // Nagłówki Authorization mają postać "Basic cośtamcośtam",
      // where cośtamcośtam to zakodowane w formacie base64 
      // nazwa użytkownika i hasło. Nas interesuje część
      // występująca po słowie "Basic ".
      String userInfo = authorization.substring(6).trim();
      BASE64Decoder decoder = new BASE64Decoder();
      String nameAndPassword =
        new String(decoder.decodeBuffer(userInfo));
      // Rozkodowany fragment ma postać "użytkownik:hasło".
      int index = nameAndPassword.indexOf(":");
      String user = nameAndPassword.substring(0, index);
      String password = nameAndPassword.substring(index+1);
      // Dodatkowe zabezpieczenie: nazwa użytkownika musi być
      // odwrotnością hasła.
      if (areEqualReversed(user, password)) {
        showStock(request, response);
      } else {
        askForPassword(response);
      }
    }
  }

  // Wyświetlenie strony prezentującej symbol najbardziej
  // atrakcyjnego papieru wartościowego.

  private void showStock(HttpServletRequest request,
                         HttpServletResponse response)
      throws ServletException, IOException {
        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>Najatrakcyjniejszy papier!</TITLE></HEAD>\n" +
                "<BODY BGCOLOR=\"#FDF5E6\">\n" +
                "<H1>Dzisiaj najbardziej atrakcyjnym papierem jest:");
    for(int i=0; i<3; i++) {
      out.print(randomLetter());
    }
    out.println("</H1>\n" +
                "</BODY></HTML>");
  }

  // Jeśli w wywołaniu zabrakło nagłówka Authorization.
  
  private void askForPassword(HttpServletResponse response) {
  	// Wysłanie kodu 401
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    response.setHeader("WWW-Authenticate",
                       "BASIC realm=\"Insider-Trading\"");
  }

  // Zwraca wartość true, jeśli s1 jest odwrotnością s2.
  // Puste ciągi nie są brane pod uwagę.
  
  private boolean areEqualReversed(String s1, String s2) {
    s2 = (new StringBuffer(s2)).reverse().toString();
    return((s1.length() > 0) && s1.equals(s2));
  }
  
  private final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

  // Zwraca losową liczbę z przedziału obustronnie 
  // domkniętego od 0 do n-1.
  
  private int randomInt(int n) {
    return((int)(Math.random() * n));
  }

  // Losowa litera alfabetu.
  
  private char randomLetter() {
    return(ALPHABET.charAt(randomInt(ALPHABET.length())));
  }
}
