package org.owasp.webgoat.lessons;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import org.apache.ecs.Element;
import org.apache.ecs.ElementContainer;
import org.apache.ecs.StringElement;
import org.apache.ecs.html.BR;
import org.apache.ecs.html.Div;
import org.apache.ecs.html.Form;
import org.apache.ecs.html.H1;
import org.apache.ecs.html.H3;
import org.apache.ecs.html.IMG;
import org.apache.ecs.html.Input;
import org.apache.ecs.html.PRE;
import org.apache.ecs.html.TD;
import org.apache.ecs.html.TR;
import org.apache.ecs.html.Table;
import org.owasp.webgoat.session.WebSession;

/*******************************************************************************
 * 
 * 
 * This file is part of WebGoat, an Open Web Application Security Project
 * utility. For details, please see http://www.owasp.org/
 * 
 * Copyright (c) 2002 - 2007 Bruce Mayhew
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA.
 * 
 * Getting Source ==============
 * 
 * Source for this application is maintained at code.google.com, a repository
 * for free software projects.
 * 
 * For details, please see http://code.google.com/p/webgoat/
 * 
 * @author     Sherif Koussa <a href="http://www.macadamian.com">Macadamian Technologies.</a>
 * @created    December 26, 2006
 */

public class SilentTransactions extends LessonAdapter
{

    private final static Integer DEFAULT_RANKING = new Integer(40);

    private final static Double CURRENT_BALANCE = 11987.09;

    private final static IMG MAC_LOGO = new IMG("images/logos/macadamian.gif").setAlt(
    "Macadamian Technologies").setBorder(0).setHspace(0).setVspace(0);

    public void handleRequest(WebSession s)
    {

	try
	{
	    if (s.getParser().getRawParameter("from", "").equals("ajax"))
	    {
		if (s.getParser().getRawParameter("confirm", "").equals(
			"Confirm"))
		{
		    String amount = s.getParser().getRawParameter("amount", "");
		    s.getResponse().setContentType("text/html");
		    s.getResponse().setHeader("Cache-Control", "no-cache");
		    PrintWriter out = new PrintWriter(s.getResponse()
			    .getOutputStream());
		    StringBuffer result = new StringBuffer();
		    result
			    .append("<br><br>* Congratulations. You have successfully completed this lesson.<br>");
		    if (!amount.equals(""))
		    {
			result.append("You have just silently authorized ");
			result.append(amount);
			result.append("$ without the user interaction.<br>");
		    }
		    result
			    .append("Now you can send out a spam email containing this link and whoever clicks on it<br>");
		    result
			    .append(" and happens to be logged in the same time will loose their money !!");
		    out.print(result.toString());
		    out.flush();
		    out.close();
		    getLessonTracker(s).setCompleted(true);
		    return;
		}
		else if (s.getParser().getRawParameter("confirm", "").equals(
			"Transferring"))
		{
		    s.getResponse().setContentType("text/html");
		    s.getResponse().setHeader("Cache-Control", "no-cache");
		    PrintWriter out = new PrintWriter(s.getResponse()
			    .getOutputStream());
		    out
			    .print("<br><br>The Transaction has Completed Successfully.");
		    out.flush();
		    out.close();
		    return;
		}
	    }
	}
	catch (Exception ex)
	{
	    ex.printStackTrace();
	}

	Form form = new Form(getFormAction(), Form.POST).setName("form")
		.setEncType("");

	form.addElement(createContent(s));

	setContent(form);

    }


    /**
     * Description of the Method
     * 
     * @param s Current WebSession
     */

    protected Element createContent(WebSession s)
    {
	ElementContainer ec = new ElementContainer();
	String lineSep = System.getProperty("line.separator");
	String script = "<script>"
		+ lineSep
		+ "function processData(){"
		+ lineSep
		+ " var accountNo = document.getElementById('newAccount').value;"
		+ lineSep
		+ " var amount = document.getElementById('amount').value;"
		+ lineSep
		+ " if ( accountNo == ''){"
		+ lineSep
		+ " alert('Please enter a valid account number to transfer to.')"
		+ lineSep
		+ " return;"
		+ lineSep
		+ "}"
		+ lineSep
		+ " else if ( amount == ''){"
		+ lineSep
		+ " alert('Please enter a valid amount to transfer.')"
		+ lineSep
		+ " return;"
		+ lineSep
		+ "}"
		+ lineSep
		+ " var balanceValue = document.getElementById('balanceID').innerHTML;"
		+ lineSep
		+ " balanceValue = balanceValue.replace( new RegExp('$') , '');"
		+ lineSep
		+ " if ( parseFloat(amount) > parseFloat(balanceValue) ) {"
		+ lineSep
		+ " alert('You can not transfer more funds than what is available in your balance.')"
		+ lineSep
		+ " return;"
		+ lineSep
		+ "}"
		+ lineSep
		+ " document.getElementById('confirm').value  = 'Transferring'"
		+ lineSep
		+ "submitData(accountNo, amount);"
		+ lineSep
		+ " document.getElementById('confirm').value  = 'Confirm'"
		+ lineSep
		+ "balanceValue = parseFloat(balanceValue) - parseFloat(amount);"
		+ lineSep
		+ "balanceValue = balanceValue.toFixed(2);"
		+ lineSep
		+ "document.getElementById('balanceID').innerHTML = balanceValue + '$';"
		+ lineSep
		+ "}"
		+ lineSep
		+ "function submitData(accountNo, balance) {"
		+ lineSep
		+ "var url = '" + getLink()
		+ "&from=ajax&newAccount='+ accountNo+ '&amount=' + balance +'&confirm=' + document.getElementById('confirm').value; "
		+ lineSep + "if (typeof XMLHttpRequest != 'undefined') {"
		+ lineSep + "req = new XMLHttpRequest();" + lineSep
		+ "} else if (window.ActiveXObject) {" + lineSep
		+ "req = new ActiveXObject('Microsoft.XMLHTTP');" + lineSep
		+ "   }" + lineSep + "   req.open('GET', url, true);" + lineSep
		+ "   req.onreadystatechange = callback;" + lineSep
		+ "   req.send(null);" + lineSep + "}" + lineSep
		+ "function callback() {" + lineSep
		+ "    if (req.readyState == 4) { " + lineSep
		+ "        if (req.status == 200) { " + lineSep
		+ "                   var result =  req.responseText ;"
		+ lineSep
		+ "			 var resultsDiv = document.getElementById('resultsDiv');"
		+ lineSep + "				resultsDiv.innerHTML = '';" + lineSep
		+ "				resultsDiv.innerHTML = result;" + lineSep
		+ "        }}}" + lineSep + "</script>" + lineSep;

	ec.addElement(new StringElement(script));
	ec.addElement(new H1("Welcome to WebGoat Banking System"));
	ec.addElement(new BR());
	ec.addElement(new H3("Account Summary:"));

	Table t1 = new Table().setCellSpacing(0).setCellPadding(0).setBorder(1)
		.setWidth("70%").setAlign("left");
	ec.addElement(new BR());
	TR tr = new TR();
	tr.addElement(new TD(new StringElement("Account Balance:")));
	tr.addElement(new TD(new StringElement("<div id='balanceID'>"
		+ CURRENT_BALANCE.toString() + "$</div>")));
	t1.addElement(tr);

	tr = new TR();
	tr.addElement(new TD(new StringElement("Transfer to Account:")));
	Input newAccount = new Input();
	newAccount.addAttribute("id", "newAccount");
	newAccount.setType(Input.TEXT);
	newAccount.setName("newAccount");
	newAccount.setValue("");
	tr.addElement(new TD(newAccount));
	t1.addElement(tr);

	tr = new TR();
	tr.addElement(new TD(new StringElement("Transfer Amount:")));
	Input amount = new Input();
	amount.addAttribute("id", "amount");
	amount.setType(Input.TEXT);
	amount.setName("amount");
	amount.setValue(0);
	tr.addElement(new TD(amount));
	t1.addElement(tr);

	ec.addElement(t1);
	ec.addElement(new BR());
	ec.addElement(new BR());

	ec.addElement(new PRE());
	Input b = new Input();
	b.setType(Input.BUTTON);
	b.setName("confirm");
	b.addAttribute("id", "confirm");
	b.setValue("Confirm");
	b.setOnClick("processData();");
	ec.addElement(b);

	ec.addElement(new BR());
	Div div = new Div();
	div.addAttribute("name", "resultsDiv");
	div.addAttribute("id", "resultsDiv");
	div.setStyle("font-weight: bold;color:red;");
	ec.addElement(div);

	return ec;
    }


    protected Category getDefaultCategory()
    {
	return Category.AJAX_SECURITY;
    }


    protected List<String> getHints(WebSession s)
    {
	List<String> hints = new ArrayList<String>();
	hints.add("Check the javascript in the HTML source.");
	hints
		.add("Check how the application calls a specific javascript function to execute the transaction.");
	hints
		.add("Check the javascript functions processData and submitData()");
	hints
		.add("Function submitData() is the one responsible for actually ececuting the transaction.");
	hints
		.add("Check if your browser supports running javascript from the address bar.");
	hints.add("Try to navigate to 'javascript:submitData(1234556,11000);'");
	return hints;

    }


    protected Integer getDefaultRanking()
    {
	return DEFAULT_RANKING;
    }


    /**
     *  Gets the title attribute of the HelloScreen object
     *
     * @return    The title value
     */
    public String getTitle()
    {
	return ("Silent Transactions Attacks");
    }


    public Element getCredits()
    {
	return super.getCustomCredits("Created by Sherif Koussa ", MAC_LOGO);
    }

}