/*
*
* Paros and its related class files.
* 
* Paros is an HTTP/HTTPS proxy for assessing web application security.
* Copyright (C) 2003-2004 Chinotec Technologies Company
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Clarified Artistic License
* as published by the Free Software Foundation.
* 
* 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
* Clarified Artistic License for more details.
* 
* You should have received a copy of the Clarified Artistic License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package org.parosproxy.paros.core.scanner;

import org.parosproxy.paros.db.RecordAlert;
import org.parosproxy.paros.extension.report.ReportGenerator;
import org.parosproxy.paros.model.HistoryReference;
import org.parosproxy.paros.network.HttpMessage;


public class Alert implements Comparable  {

	public static final int RISK_INFO 	= 0;
	public static final int RISK_LOW 	= 1;
	public static final int RISK_MEDIUM = 2;
	public static final int RISK_HIGH 	= 3;

	public static final int SUSPICIOUS = 0;
	public static final int WARNING = 1;
	
	public static final String MSG_RISK[] = {"Informational", "Low", "Medium", "High"};
	public static final String MSG_RELIABILITY[] = {"Suspicious", "Warning"};
	
	private int		alertId = 0;
	private int		pluginId = 0;
	private String 	alert = "";
	private int risk = RISK_INFO;
	private int reliability = WARNING;
	private String 	description = "";
	private String 	uri = "";
	private String 	param = "";
	private String 	otherInfo = "";
	private String 	solution = "";
	private String	reference = "";
	private HttpMessage message = null;
	
	public Alert(int pluginId) {
		this.pluginId = pluginId;
		
	}
	
	public Alert(int pluginId, int risk, int reliability, String alert) {
		this(pluginId);
		setRiskReliability(risk, reliability);
		setAlert(alert);
	}

	public Alert(RecordAlert recordAlert) {
	    this(recordAlert.getPluginId(), recordAlert.getRisk(), recordAlert.getReliability(), recordAlert.getAlert());
	    HistoryReference ref = null;
        try {
            ref = new HistoryReference(recordAlert.getHistoryId());
            setDetail(recordAlert.getDescription(), recordAlert.getUri(), recordAlert.getParam(), recordAlert.getOtherInfo(), recordAlert.getSolution(), recordAlert.getReference(), ref.getHttpMessage());

        } catch (Exception e) {
        }
	    
	}
	
	public void setRiskReliability(int risk, int reliability) {
		this.risk = risk;
		this.reliability = reliability;
	}
	
	public void setAlert(String alert) {
	    if (alert == null) return;
	    this.alert = new String(alert);
	}
	
	

	public void setDetail(String description, String uri, String param, String otherInfo, String solution, String reference, HttpMessage msg) {
		setDescription(description);
		setUri(uri);
		setParam(param);
		setOtherInfo(otherInfo);
		setSolution(solution);
		setReference(reference);
		setMessage(msg);
	}

	public void setUri(String uri) {
		this.uri = new String(uri);
	}
	
	
	public void setDescription(String description) {
	    if (description == null) return;
		this.description = new String(description);
	}
	
	public void setParam(String param) {
	    if (param == null) return;
		this.param = new String(param);
	}
	
	
	public void setOtherInfo(String otherInfo) {
	    if (otherInfo == null) return;
		this.otherInfo = new String(otherInfo);
	}

	public void setSolution(String solution) {
	    if (solution == null) return;
		this.solution = new String(solution);
	}

	public void setReference(String reference) {
	    if (reference == null) return;
		this.reference = new String(reference);
	}

	public void setMessage(HttpMessage message) {
	    if (message != null) {
	        this.message = message.cloneAll();
	    } else {
	        this.message = message;
	    }
	}
	
	public int compareTo(Object o2) throws ClassCastException {
		Alert alert2 = (Alert) o2;
		int result = 0;
		
		if (risk < alert2.risk) {
			return -1;
		} else if (risk > alert2.risk) {
			return 1;
		}
		
		if (reliability < alert2.reliability) {
			return -1;
		} else if (reliability > alert2.reliability) {
			return 1;
		}
		
		result = alert.compareToIgnoreCase(alert2.alert);
		if (result != 0) {
			return result;
		}
		
		result = alert.compareToIgnoreCase(alert2.uri);
		if (result != 0) {
			return result;
		}
		
		result = alert.compareToIgnoreCase(alert2.param);
		if (result != 0) {
			return result;
		}
		
		return otherInfo.compareToIgnoreCase(alert2.otherInfo);
	} 


	/**
	Override equals.  Alerts are equal if the alert, uri and param is the same.
	*/
	public boolean equals(Object obj) {
		Alert item = null;
		if (obj instanceof Alert) {
			item = (Alert) obj;
			if ((pluginId == item.pluginId) && uri.equalsIgnoreCase(item.uri)
				&& param.equalsIgnoreCase(item.param) && otherInfo.equalsIgnoreCase(item.otherInfo)) {
				return true;
			}
		}
		return false;
	}
	
	/**
	Create a new instance of AlertItem with same members.
	*/
	public Alert newInstance() {
		Alert item = new Alert(this.pluginId);
		item.setRiskReliability(this.risk, this.reliability);
		item.setAlert(this.alert);
		item.setDetail(this.description, this.uri, this.param, this.otherInfo, this.solution, this.reference, this.message);
		return item;
	}
	
	public String toXML() {
		StringBuffer sb = new StringBuffer(150);
		sb.append("<alertitem>\r\n");
		sb.append("<pluginid>" + pluginId + "</pluginid>");
		sb.append("<alert>" + alert + "</alert>");
		sb.append("<riskcode>" + risk + "</riskcode>");
		sb.append("<reliability>" + reliability + "</reliability>");
		sb.append("<riskdesc>" + replaceEntity(MSG_RISK[risk] + " (" + MSG_RELIABILITY[reliability] + ")") + "</riskdesc>");
		sb.append("<desc>" + paragraph(replaceEntity(description)) + "</desc>");
		sb.append("<uri>" + paragraph(replaceEntity(uri)) + "</uri>");
		sb.append("<param>" + paragraph(replaceEntity(param)) + "</param>");
		sb.append("<otherinfo>" + paragraph(replaceEntity(otherInfo)) + "</otherinfo>");
		sb.append("<solution>" + paragraph(replaceEntity(solution)) + "</solution>");
		sb.append("<reference>" + paragraph(replaceEntity(reference)) + "</reference>");
		
		sb.append("</alertitem>\r\n");
		return sb.toString();
	}
	
	private String replaceEntity(String text) {
		String result = null;
		if (text != null) {
			result = ReportGenerator.entityEncode(text);
		}
		return result;
	}
	
	private String paragraph(String text) {
		String result = null;
		result = text.replaceAll("\\r\\n","<br/>").replaceAll("\\n","<br/>");
		return result;
	}
		
    /**
     * @return Returns the alert.
     */
    public String getAlert() {
        return alert;
    }
    /**
     * @return Returns the description.
     */
    public String getDescription() {
        return description;
    }
    /**
     * @return Returns the id.
     */
    public int getPluginId() {
        return pluginId;
    }
    /**
     * @return Returns the message.
     */
    public HttpMessage getMessage() {
        return message;
    }
    /**
     * @return Returns the otherInfo.
     */
    public String getOtherInfo() {
        return otherInfo;
    }
    /**
     * @return Returns the param.
     */
    public String getParam() {
        return param;
    }
    /**
     * @return Returns the reference.
     */
    public String getReference() {
        return reference;
    }
    /**
     * @return Returns the reliability.
     */
    public int getReliability() {
        return reliability;
    }
    /**
     * @return Returns the risk.
     */
    public int getRisk() {
        return risk;
    }
    /**
     * @return Returns the solution.
     */
    public String getSolution() {
        return solution;
    }
    /**
     * @return Returns the uri.
     */
    public String getUri() {
        return uri;
    }
    /**
     * @return Returns the alertId.
     */
    public int getAlertId() {
        return alertId;
    }
    /**
     * @param alertId The alertId to set.
     */
    public void setAlertId(int alertId) {
        this.alertId = alertId;
    }
}	


