package com.eviware.soapui.security.ui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.io.File;
import javax.activation.MimetypesFileTypeMap;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.KeyStroke;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableCellEditor;
import org.jdesktop.swingx.JXTable;
import com.eviware.soapui.config.MaliciousAttachmentConfig;
import com.eviware.soapui.config.MaliciousAttachmentElementConfig;
import com.eviware.soapui.config.MaliciousAttachmentSecurityScanConfig;
import com.eviware.soapui.impl.support.AbstractHttpRequest;
import com.eviware.soapui.impl.wsdl.support.HelpUrls;
import com.eviware.soapui.model.iface.Attachment;
import com.eviware.soapui.security.support.MaliciousAttachmentFilesListForm;
import com.eviware.soapui.security.support.MaliciousAttachmentGenerateTableModel;
import com.eviware.soapui.security.support.MaliciousAttachmentListToTableHolder;
import com.eviware.soapui.security.support.MaliciousAttachmentReplaceTableModel;
import com.eviware.soapui.security.support.MaliciousAttachmentTableModel;
import com.eviware.soapui.security.tools.AttachmentElement;
import com.eviware.soapui.settings.ProjectSettings;
import com.eviware.soapui.support.HelpActionMarker;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.Tools;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.components.JXToolBar;
import com.eviware.soapui.support.editor.inspectors.attachments.ContentTypeHandler;
import com.eviware.x.form.XFormDialog;
import com.eviware.x.form.XFormField;
import com.eviware.x.form.XFormFieldListener;
import com.eviware.x.form.support.ADialogBuilder;
import com.eviware.x.form.support.AField;
import com.eviware.x.form.support.AField.AFieldType;
import com.eviware.x.form.support.AForm;
import com.eviware.x.impl.swing.JCheckBoxFormField;
import com.eviware.x.impl.swing.JFormDialog;
import com.eviware.x.impl.swing.JTextFieldFormField;
public class MaliciousAttachmentMutationsPanel
{
private JFormDialog dialog;
private MaliciousAttachmentSecurityScanConfig config;
private JButton addGeneratedButton;
private JButton removeGeneratedButton;
private JButton addReplacementButton;
private JButton removeReplacementButton;
private AbstractHttpRequest<?> request;
private MaliciousAttachmentListToTableHolder holder = new MaliciousAttachmentListToTableHolder();
private JFormDialog tablesDialog;
public MaliciousAttachmentMutationsPanel( MaliciousAttachmentSecurityScanConfig config,
AbstractHttpRequest<?> request )
{
this.config = config;
this.request = request;
dialog = ( JFormDialog )ADialogBuilder.buildDialog( MutationSettings.class );
dialog.getFormField( MutationSettings.MUTATIONS_PANEL ).setProperty( "component", createMutationsPanel() );
dialog.getFormField( MutationSettings.MUTATIONS_PANEL ).setProperty( "dimension", new Dimension( 720, 320 ) );
}
private JComponent buildFilesList()
{
MaliciousAttachmentFilesListForm filesList = new MaliciousAttachmentFilesListForm( config, holder );
holder.setFilesList( filesList );
JScrollPane scrollPane = new JScrollPane( filesList );
return scrollPane;
}
private JComponent buildTables()
{
tablesDialog = ( JFormDialog )ADialogBuilder.buildDialog( MutationTables.class );
MaliciousAttachmentTableModel generateTableModel = new MaliciousAttachmentGenerateTableModel();
tablesDialog.getFormField( MutationTables.GENERATE_FILE ).setProperty( "dimension", new Dimension( 410, 120 ) );
tablesDialog.getFormField( MutationTables.GENERATE_FILE ).setProperty( "component",
buildGenerateTable( generateTableModel ) );
MaliciousAttachmentTableModel replaceTableModel = new MaliciousAttachmentReplaceTableModel();
tablesDialog.getFormField( MutationTables.REPLACE_FILE ).setProperty( "dimension", new Dimension( 410, 120 ) );
tablesDialog.getFormField( MutationTables.REPLACE_FILE ).setProperty( "component",
buildReplacementTable( replaceTableModel ) );
holder.setGenerateTableModel( generateTableModel );
holder.setReplaceTableModel( replaceTableModel );
holder.setTablesDialog( tablesDialog );
JCheckBoxFormField remove = ( JCheckBoxFormField )tablesDialog.getFormField( MutationTables.REMOVE_FILE );
remove.addFormFieldListener( new XFormFieldListener()
{
@Override
public void valueChanged( XFormField sourceField, String newValue, String oldValue )
{
int idx = holder.getFilesList().getList().getSelectedIndex();
if( idx != -1 )
{
ListModel listModel = holder.getFilesList().getList().getModel();
String key = ( ( AttachmentElement )listModel.getElementAt( idx ) ).getId();
for( MaliciousAttachmentElementConfig element : config.getElementList() )
{
if( key.equals( element.getKey() ) )
{
element.setRemove( Boolean.parseBoolean( newValue ) );
break;
}
}
}
}
} );
return tablesDialog.getPanel();
}
protected JPanel buildGenerateTable( MaliciousAttachmentTableModel tableModel )
{
final JPanel panel = new JPanel( new BorderLayout() );
final JXTable table = new JXTable( tableModel );
setupTable( table );
JScrollPane tableScrollPane = new JScrollPane( table );
tableScrollPane.setBorder( BorderFactory.createEmptyBorder() );
JXToolBar toolbar = UISupport.createToolbar();
addGeneratedButton = UISupport.createToolbarButton( new GenerateFileAction() );
toolbar.add( addGeneratedButton );
removeGeneratedButton = UISupport.createToolbarButton( new RemoveGeneratedFileAction( tableModel, table ) );
toolbar.add( removeGeneratedButton );
removeGeneratedButton.setEnabled( false );
toolbar.add( UISupport.createToolbarButton( new HelpAction( HelpUrls.SECURITY_MALICIOUS_ATTACHMENT_HELP ) ) );
panel.add( toolbar, BorderLayout.PAGE_START );
panel.add( tableScrollPane, BorderLayout.CENTER );
table.getSelectionModel().addListSelectionListener( new ListSelectionListener()
{
@Override
public void valueChanged( ListSelectionEvent e )
{
if( removeGeneratedButton != null )
{
removeGeneratedButton.setEnabled( table.getSelectedRowCount() > 0 );
}
}
} );
panel.setBorder( BorderFactory.createLineBorder( new Color( 0 ), 1 ) );
return panel;
}
protected JPanel buildReplacementTable( MaliciousAttachmentTableModel tableModel )
{
final JPanel panel = new JPanel( new BorderLayout() );
final JXTable table = new JXTable( tableModel );
setupTable( table );
JScrollPane tableScrollPane = new JScrollPane( table );
tableScrollPane.setBorder( BorderFactory.createEmptyBorder() );
JXToolBar toolbar = UISupport.createToolbar();
addReplacementButton = UISupport.createToolbarButton( new AddFileAction() );
toolbar.add( addReplacementButton );
removeReplacementButton = UISupport.createToolbarButton( new RemoveReplacementFileAction( tableModel, table ) );
toolbar.add( removeReplacementButton );
removeReplacementButton.setEnabled( false );
toolbar.add( UISupport.createToolbarButton( new HelpAction( HelpUrls.SECURITY_MALICIOUS_ATTACHMENT_HELP ) ) );
panel.add( toolbar, BorderLayout.PAGE_START );
panel.add( tableScrollPane, BorderLayout.CENTER );
table.getSelectionModel().addListSelectionListener( new ListSelectionListener()
{
@Override
public void valueChanged( ListSelectionEvent e )
{
if( removeReplacementButton != null )
{
removeReplacementButton.setEnabled( table.getSelectedRowCount() > 0 );
}
}
} );
panel.setBorder( BorderFactory.createLineBorder( new Color( 0 ), 1 ) );
return panel;
}
protected void setupTable( JXTable table )
{
table.setPreferredScrollableViewportSize( new Dimension( 50, 90 ) );
table.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
table.getTableHeader().setReorderingAllowed( false );
table.setDefaultEditor( String.class, getDefaultCellEditor() );
table.setSortable( false );
}
private Object createMutationsPanel()
{
JPanel panel = new JPanel( new BorderLayout() );
JSplitPane mainSplit = UISupport.createHorizontalSplit( buildFilesList(), buildTables() );
mainSplit.setResizeWeight( 1 );
panel.add( mainSplit, BorderLayout.CENTER );
return panel;
}
public JComponent getPanel()
{
MaliciousAttachmentFilesListForm filesList = holder.getFilesList();
Attachment[] data = new Attachment[request.getAttachments().length];
for( int i = 0; i < request.getAttachments().length; i++ )
{
data[i] = request.getAttachmentAt( i );
}
filesList.setData( data );
holder.refresh();
return dialog.getPanel();
}
@AForm( description = "Malicious Attachment Mutations", name = "Malicious Attachment Mutations" )
public interface MutationSettings
{
@AField( description = "###Mutations panel", name = "###Mutations panel", type = AFieldType.COMPONENT )
final static String MUTATIONS_PANEL = "###Mutations panel";
}
@AForm( description = "Malicious Attachment Mutation Tables", name = "Malicious Attachment Mutation Tables" )
public interface MutationTables
{
@AField( description = "<html><b>Specify below how selected attachment should be mutated</b></html>", name = "###Label", type = AFieldType.LABEL )
final static String LABEL = "###Label";
@AField( description = "Generate file", name = "Generate", type = AFieldType.COMPONENT )
final static String GENERATE_FILE = "Generate";
@AField( description = "Replace file", name = "Replace", type = AFieldType.COMPONENT )
final static String REPLACE_FILE = "Replace";
@AField( description = "Do not send the attachment with the request", name = "Remove", type = AFieldType.BOOLEAN )
final static String REMOVE_FILE = "Remove";
}
@AForm( description = "Generate File Mutation", name = "Generate File Mutation" )
public interface GenerateFile
{
@AField( description = "Size (bytes)", name = "Size (bytes)", type = AFieldType.INT )
final static String SIZE = "Size (bytes)";
@AField( description = "Content type", name = "Content type", type = AFieldType.STRING )
final static String CONTENT_TYPE = "Content type";
}
public class AddFileAction extends AbstractAction
{
private JFileChooser fileChooser;
public AddFileAction()
{
putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/add_property.gif" ) );
putValue( Action.SHORT_DESCRIPTION, "Add file" );
}
@Override
public void actionPerformed( ActionEvent e )
{
if( fileChooser == null )
{
fileChooser = new JFileChooser();
}
String root = ProjectSettings.PROJECT_ROOT;
if( StringUtils.hasContent( root ) )
{
fileChooser.setCurrentDirectory( new File( root ) );
}
int returnVal = fileChooser.showOpenDialog( UISupport.getMainFrame() );
if( returnVal == JFileChooser.APPROVE_OPTION )
{
File file = fileChooser.getSelectedFile();
Boolean retval = UISupport.confirmOrCancel( "Cache attachment in request?", "Add Attachment" );
if( retval == null )
{
return;
}
String filename = file.getAbsolutePath();
Long size = file.length();
String contentType = new MimetypesFileTypeMap().getContentType( file );
Boolean enabled = new Boolean( true );
Boolean cached = retval;
boolean added = false;
int idx = holder.getFilesList().getList().getSelectedIndex();
if( idx != -1 )
{
ListModel listModel = holder.getFilesList().getList().getModel();
String key = ( ( AttachmentElement )listModel.getElementAt( idx ) ).getId();
for( MaliciousAttachmentElementConfig element : config.getElementList() )
{
if( key.equals( element.getKey() ) )
{
MaliciousAttachmentConfig att = element.addNewReplaceAttachment();
att.setFilename( filename );
att.setSize( size );
att.setContentType( contentType );
att.setEnabled( enabled );
att.setCached( cached );
holder.addResultToReplaceTable( att );
added = true;
}
}
}
if( !added )
{
UISupport.showErrorMessage( "No attachments found in test step" );
}
}
}
}
public class GenerateFileAction extends AbstractAction
{
private XFormDialog dialog;
public GenerateFileAction()
{
putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/add_property.gif" ) );
putValue( Action.SHORT_DESCRIPTION, "Generate file" );
}
@Override
public void actionPerformed( ActionEvent e )
{
if( dialog == null )
{
dialog = ADialogBuilder.buildDialog( GenerateFile.class );
( ( JTextFieldFormField )dialog.getFormField( GenerateFile.CONTENT_TYPE ) ).setWidth( 30 );
}
dialog.show();
if( dialog.getReturnValue() == XFormDialog.OK_OPTION )
{
Long newSize = 0L;
String newSizeString = dialog.getValue( GenerateFile.SIZE );
String contentType = dialog.getFormField( GenerateFile.CONTENT_TYPE ).getValue();
try
{
newSize = Long.parseLong( newSizeString );
}
catch( NumberFormatException nfe )
{
UISupport.showErrorMessage( "Size must be numeric value" );
return;
}
try
{
File file = File.createTempFile( StringUtils.createFileName( "attachment", '-' ), "."
+ ContentTypeHandler.getExtensionForContentType( contentType ) );
String filename = file.getAbsolutePath();
Boolean enabled = new Boolean( true );
Boolean cached = new Boolean( true );
boolean added = false;
int idx = holder.getFilesList().getList().getSelectedIndex();
if( idx != -1 )
{
ListModel listModel = holder.getFilesList().getList().getModel();
String key = ( ( AttachmentElement )listModel.getElementAt( idx ) ).getId();
for( MaliciousAttachmentElementConfig element : config.getElementList() )
{
if( key.equals( element.getKey() ) )
{
MaliciousAttachmentConfig att = element.addNewGenerateAttachment();
att.setFilename( filename );
att.setSize( newSize );
att.setContentType( contentType );
att.setEnabled( enabled );
att.setCached( cached );
holder.addResultToGenerateTable( att );
added = true;
}
}
}
if( !added )
{
UISupport.showErrorMessage( "No attachments found in test step" );
}
}
catch( Exception e1 )
{
UISupport.showErrorMessage( e1 );
}
}
}
}
public class RemoveReplacementFileAction extends AbstractAction
{
private final MaliciousAttachmentTableModel tableModel;
private final JXTable table;
public RemoveReplacementFileAction( MaliciousAttachmentTableModel tableModel, JXTable table )
{
putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/remove_property.gif" ) );
putValue( Action.SHORT_DESCRIPTION, "Remove file" );
this.tableModel = tableModel;
this.table = table;
}
@Override
public void actionPerformed( ActionEvent e )
{
int row = table.getSelectedRow();
if( row >= 0 )
{
tableModel.removeResult( row );
int idx = holder.getFilesList().getList().getSelectedIndex();
if( idx != -1 )
{
ListModel listModel = holder.getFilesList().getList().getModel();
String key = ( ( AttachmentElement )listModel.getElementAt( idx ) ).getId();
for( int i = 0; i < config.getElementList().size(); i++ )
{
MaliciousAttachmentElementConfig element = config.getElementList().get( i );
if( key.equals( element.getKey() ) )
{
element.getReplaceAttachmentList().remove( row );
}
}
}
}
}
}
public class RemoveGeneratedFileAction extends AbstractAction
{
private final MaliciousAttachmentTableModel tableModel;
private final JXTable table;
public RemoveGeneratedFileAction( MaliciousAttachmentTableModel tableModel, JXTable table )
{
putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/remove_property.gif" ) );
putValue( Action.SHORT_DESCRIPTION, "Remove file" );
this.tableModel = tableModel;
this.table = table;
}
@Override
public void actionPerformed( ActionEvent e )
{
int row = table.getSelectedRow();
if( row >= 0 )
{
tableModel.removeResult( row );
int idx = holder.getFilesList().getList().getSelectedIndex();
if( idx != -1 )
{
ListModel listModel = holder.getFilesList().getList().getModel();
String key = ( ( AttachmentElement )listModel.getElementAt( idx ) ).getId();
for( int i = 0; i < config.getElementList().size(); i++ )
{
MaliciousAttachmentElementConfig element = config.getElementList().get( i );
if( key.equals( element.getKey() ) )
{
element.getGenerateAttachmentList().remove( row );
}
}
}
}
}
}
public class HelpAction extends AbstractAction implements HelpActionMarker
{
private final String url;
public HelpAction( String url )
{
this( "Online Help", url, UISupport.getKeyStroke( "F1" ) );
}
public HelpAction( String title, String url )
{
this( title, url, null );
}
public HelpAction( String title, String url, KeyStroke accelerator )
{
super( title );
this.url = url;
putValue( Action.SHORT_DESCRIPTION, "Show online help" );
if( accelerator != null )
putValue( Action.ACCELERATOR_KEY, accelerator );
putValue( Action.SMALL_ICON, UISupport.HELP_ICON );
}
@Override
public void actionPerformed( ActionEvent e )
{
Tools.openURL( url );
}
}
protected TableCellEditor getDefaultCellEditor()
{
return new XPathCellRender();
}
public MaliciousAttachmentSecurityScanConfig getConfig()
{
return config;
}
public void setConfig( MaliciousAttachmentSecurityScanConfig config )
{
this.config = config;
}
public void updateConfig( MaliciousAttachmentSecurityScanConfig config )
{
setConfig( config );
MaliciousAttachmentFilesListForm filesList = holder.getFilesList();
if( filesList != null )
{
filesList.updateConfig( config );
}
}
public MaliciousAttachmentListToTableHolder getHolder()
{
return holder;
}
public void release()
{
tablesDialog.release();
dialog.release();
config = null;
dialog = null;
request = null;
holder.release();
holder = null;
}
}