/*
*
* 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.
*/
// ZAP: 2012/03/14 Changed to use the internationalised strings.
// ZAP: 2012/04/25 Changed to use the method Boolean.valueOf.
// ZAP: 2013/01/27 Changed to only notify the listeners if the value was really changed.
// ZAP: 2013/03/03 Issue 546: Remove all template Javadoc comments
// ZAP: 2013/11/28 Issue 923: Allow individual rule thresholds and strengths to be set via GUI
// ZAP: 2014/05/20 Issue 377: Unfulfilled dependencies hang the active scan
// ZAP: 2014/11/19 Issue 1412: Manage scan policies
// ZAP: 2016/04/04 Use StatusUI in scanners' dialogues
package org.zaproxy.zap.extension.ascan;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.table.DefaultTableModel;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.core.scanner.Plugin;
import org.parosproxy.paros.core.scanner.Plugin.AlertThreshold;
import org.parosproxy.paros.core.scanner.Plugin.AttackStrength;
import org.parosproxy.paros.core.scanner.PluginFactory;
import org.parosproxy.paros.view.View;
import org.zaproxy.zap.view.StatusUI;
public class CategoryTableModel extends DefaultTableModel {
private static final long serialVersionUID = 1L;
private Map<String, String> i18nToStr = null;
// ZAP: i18n
private static final String[] columnNames = {
Constant.messages.getString("ascan.policy.table.testname"),
Constant.messages.getString("ascan.policy.table.threshold"),
Constant.messages.getString("ascan.policy.table.strength"),
Constant.messages.getString("ascan.policy.table.quality")};
private static final int QUALITY_COLUMN_IDX = 3;
private List<PluginWrapper> listTestCategory;
private PluginFactory pluginFactory;
private int category;
private AlertThreshold defaultThreshold;
public CategoryTableModel() {
}
public void setTable(int category, PluginFactory pluginFactory, AlertThreshold defaultThreshold) {
listTestCategory.clear();
this.pluginFactory = pluginFactory;
this.category = category ;
this.defaultThreshold = defaultThreshold;
for (Plugin test : pluginFactory.getAllPlugin()) {
if (test.getCategory() == category) {
listTestCategory.add(new PluginWrapper(test, View.getSingleton().getStatusUI(test.getStatus())));
}
}
fireTableDataChanged();
}
@Override
public Class<?> getColumnClass(int c) {
if (c == QUALITY_COLUMN_IDX) {
return StatusUI.class;
}
return String.class;
}
@Override
public String getColumnName(int col) {
return columnNames[col];
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0: // Name
return false;
case 1: // Strength
return true;
case 2: // Alert
return true;
case QUALITY_COLUMN_IDX:
return false;
default:
return false;
}
}
@Override
public void setValueAt(Object value, int row, int col) {
Plugin test = listTestCategory.get(row).getPlugin();
switch (col) {
case 0: break;
case 1: AlertThreshold af = AlertThreshold.valueOf(i18nToStr((String)value));
boolean enable = !AlertThreshold.OFF.equals(af);
if (test.isEnabled() != enable) {
if (enable) {
String[] dependencies = test.getDependency();
if (dependencies != null && dependencies.length != 0) {
List<Plugin> allDeps = new ArrayList<>(dependencies.length);
if (!pluginFactory.addAllDependencies(test, allDeps)) {
View.getSingleton().showWarningDialog(
Constant.messages.getString("ascan.policy.unfulfilled.dependencies"));
return;
}
List<Plugin> disabledDependencies = new ArrayList<>();
for (Plugin plugin : allDeps) {
if (!plugin.isEnabled()) {
disabledDependencies.add(plugin);
}
}
if (!disabledDependencies.isEmpty()) {
setPluginsEnabled(disabledDependencies, true);
}
}
} else {
List<Plugin> enabledDependents = new ArrayList<>();
for (Plugin plugin : pluginFactory.getDependentPlugins(test)) {
if (plugin.isEnabled()) {
enabledDependents.add(plugin);
}
}
if (!enabledDependents.isEmpty()) {
setPluginsEnabled(enabledDependents, false);
}
}
}
test.setAlertThreshold(af);
test.setEnabled(enable);
fireTableCellUpdated(row, col);
break;
case 2: test.setAttackStrength(AttackStrength.valueOf(i18nToStr((String)value)));
fireTableCellUpdated(row, col);
break;
}
}
private void setPluginsEnabled(List<Plugin> plugins, boolean enabled) {
AlertThreshold alertThreshold = enabled ? defaultThreshold : AlertThreshold.OFF;
for (Plugin plugin : plugins) {
plugin.setEnabled(enabled);
plugin.setAlertThreshold(alertThreshold);
if (plugin.getCategory() == category) {
int rowDep = getPluginRow(plugin);
if (rowDep != -1) {
fireTableCellUpdated(rowDep, 1);
}
}
}
}
private int getPluginRow(Plugin plugin) {
for (int i = 0; i < listTestCategory.size(); i++) {
if (plugin.equals(listTestCategory.get(i))) {
return i;
}
}
return -1;
}
private String strToI18n (String str) {
// I18n's threshold and strength enums
return Constant.messages.getString("ascan.policy.level." + str.toLowerCase());
}
private String i18nToStr (String str) {
// Converts to i18n'ed names back to the enum names
if (i18nToStr == null) {
i18nToStr = new HashMap<>();
for (AlertThreshold at : AlertThreshold.values()) {
i18nToStr.put(this.strToI18n(at.name()), at.name());
}
for (AttackStrength as : AttackStrength.values()) {
i18nToStr.put(this.strToI18n(as.name()), as.name());
}
}
return i18nToStr.get(str);
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public int getRowCount() {
return getTestList().size();
}
@Override
public Object getValueAt(int row, int col) {
PluginWrapper wrapper = listTestCategory.get(row);
switch (col) {
case 0:
return wrapper.getPlugin().getName();
case 1:
return strToI18n(wrapper.getPlugin().getAlertThreshold(true).name());
case 2:
return strToI18n(wrapper.getPlugin().getAttackStrength(true).name());
case QUALITY_COLUMN_IDX:
return wrapper.getQuality();
default:
return "";
}
}
private List<PluginWrapper> getTestList() {
if (listTestCategory == null) {
listTestCategory = new ArrayList<>();
}
return listTestCategory;
}
private static class PluginWrapper {
private final Plugin plugin;
private final StatusUI quality;
public PluginWrapper(Plugin plugin, StatusUI quality) {
this.plugin = plugin;
this.quality = quality;
}
public Plugin getPlugin() {
return plugin;
}
public StatusUI getQuality() {
return quality;
}
}
}