org.parosproxy.paros.extension.manualrequest.ManualRequestEditorDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.parosproxy.paros.extension.manualrequest.ManualRequestEditorDialog.java

Source

/*
 *
 * 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: 2011/08/04 Changed to support new Features
// ZAP: 2011/08/04 Changed to support new interface
// ZAP: 2012/03/15 Changed so the display options can be modified dynamically.
// ZAP: 2012/07/02 Wraps no HttpMessage object, but more generalized Message.
// new map of supported message types; removed history list; removed unused
// methods.
// ZAP: 2012/07/16 Issue 326: Add response time and total length to manual request dialog 
// ZAP: 2012/07/31 Removed the instance variables followRedirect,
// useTrackingSessionState and httpSender. Removed the methods getHttpSender,
// getButtonFollowRedirect and getButtonUseTrackingSessionState and changed the
// methods windowClosing and setVisible.
// ZAP: 2012/08/01 Issue 332: added support for Modes
// ZAP: 2012/11/21 Heavily refactored extension to support non-HTTP messages.
// ZAP: 2013/05/02 Re-arranged all modifiers into Java coding standard order
// ZAP: 2014/01/28 Issue 207: Support keyboard shortcuts 
// ZAP: 2017/02/20 Issue 2699: Make SSLException handling more user friendly

package org.parosproxy.paros.extension.manualrequest;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.net.ssl.SSLException;
import javax.swing.JButton;
import javax.swing.JPanel;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.control.Control;
import org.parosproxy.paros.control.Control.Mode;
import org.parosproxy.paros.extension.option.OptionsParamView;
import org.parosproxy.paros.network.HttpMessage;
import org.parosproxy.paros.view.AbstractFrame;
import org.parosproxy.paros.view.View;
import org.zaproxy.zap.extension.httppanel.HttpPanelRequest;
import org.zaproxy.zap.extension.httppanel.Message;
import org.zaproxy.zap.extension.tab.Tab;
import org.zaproxy.zap.view.ZapMenuItem;

/**
 * Send custom crafted messages via HTTP or other TCP based protocols. 
 */
public abstract class ManualRequestEditorDialog extends AbstractFrame implements Tab {
    private static final long serialVersionUID = 1L;

    private static final Logger logger = Logger.getLogger(ManualRequestEditorDialog.class);

    private boolean isSendEnabled = true;

    protected String configurationKey;

    private JPanel panelWindow = null;

    private JButton btnSend = null;

    /**
     * Non-abstract classes should call {@link #initialize()} in their constructor.
     * 
     * @param isSendEnabled
     * @param configurationKey
     * @throws HeadlessException
     */
    public ManualRequestEditorDialog(boolean isSendEnabled, String configurationKey) throws HeadlessException {
        super();

        this.isSendEnabled = isSendEnabled;
        this.configurationKey = OptionsParamView.BASE_VIEW_KEY + "." + configurationKey + ".";

        this.setPreferredSize(new Dimension(700, 800));
    }

    protected void initialize() {
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                getMessageSender().cleanup();
                saveConfig();
            }
        });

        setContentPane(getWindowPanel());
    }

    /**
     * Returns type of message it handles.
     * 
     * @return
     */
    public abstract Class<? extends Message> getMessageType();

    /**
     * Message sender for the given {@link #getMessageType()}.
     * 
     * @return
     */
    protected abstract MessageSender getMessageSender();

    /**
     * Menu item that calls this editor.
     * 
     * @return
     */
    public abstract ZapMenuItem getMenuItem();

    protected JPanel getWindowPanel() {
        if (panelWindow == null) {
            panelWindow = new JPanel();
            panelWindow.setLayout(new BorderLayout());

            panelWindow.add(getManualSendPanel());
        }

        return panelWindow;
    }

    protected abstract Component getManualSendPanel();

    @Override
    public void setVisible(boolean show) {
        if (!show && getMessageSender() != null) {
            getMessageSender().cleanup();
        }

        super.setVisible(show);
    }

    public abstract void setDefaultMessage();

    public abstract void setMessage(Message aMessage);

    public abstract Message getMessage();

    public void clear() {
        getRequestPanel().clearView();
    }

    protected JButton getBtnSend() {
        if (btnSend == null) {
            btnSend = new JButton();
            btnSend.setText(Constant.messages.getString("manReq.button.send"));
            btnSend.setEnabled(isSendEnabled);
            btnSend.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    btnSend.setEnabled(false);

                    // save current message (i.e. set payload/body)
                    getRequestPanel().saveData();

                    Mode mode = Control.getSingleton().getMode();
                    if (mode.equals(Mode.safe)) {
                        // Can happen if the user turns on safe mode with the dialog open
                        View.getSingleton().showWarningDialog(Constant.messages.getString("manReq.safe.warning"));
                        btnSend.setEnabled(true);
                        return;
                    } else if (mode.equals(Mode.protect)) {
                        if (!getMessage().isInScope()) {
                            // In protected mode and not in scope, so fail
                            View.getSingleton()
                                    .showWarningDialog(Constant.messages.getString("manReq.outofscope.warning"));
                            btnSend.setEnabled(true);
                            return;
                        }
                    }

                    btnSendAction();
                }
            });
        }
        return btnSend;
    }

    /**
     * Do not forget to enable the send button again i
     */
    protected abstract void btnSendAction();

    protected void send(final Message aMessage) {
        final Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    getMessageSender().handleSendMessage(aMessage);
                    postSend();
                } catch (SSLException sslEx) {
                    StringBuilder strBuilder = new StringBuilder();

                    strBuilder.append(Constant.messages.getString("network.ssl.error.connect"));
                    strBuilder.append(((HttpMessage) aMessage).getRequestHeader().getURI().toString()).append('\n');
                    strBuilder.append(Constant.messages.getString("network.ssl.error.exception"))
                            .append(sslEx.getMessage()).append('\n');
                    strBuilder.append(Constant.messages.getString("network.ssl.error.exception.rootcause"))
                            .append(ExceptionUtils.getRootCauseMessage(sslEx)).append('\n');
                    strBuilder.append(Constant.messages.getString("network.ssl.error.help",
                            Constant.messages.getString("network.ssl.error.help.url")));
                    logger.warn(strBuilder.toString());
                    if (logger.isDebugEnabled()) {
                        logger.debug(sslEx, sslEx);
                    }
                    View.getSingleton().showWarningDialog(strBuilder.toString());
                } catch (Exception e) {
                    logger.warn(e.getMessage(), e);
                    View.getSingleton().showWarningDialog(e.getMessage());
                } finally {
                    btnSend.setEnabled(true);
                }
            }
        });
        t.setPriority(Thread.NORM_PRIORITY);
        t.start();
    }

    protected void postSend() {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                // redraw, as message may have changed after sending
                getRequestPanel().updateContent();
            }
        });
    }

    protected abstract void saveConfig();

    protected abstract HttpPanelRequest getRequestPanel();
}