diff --git a/build/build.xml b/build/build.xml
new file mode 100644
index 0000000..182a1bd
--- /dev/null
+++ b/build/build.xml
@@ -0,0 +1,163 @@
+
+ Build ZAP extensions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/commons-configuration-1.9.jar b/lib/commons-configuration-1.9.jar
new file mode 100644
index 0000000..fa8fac1
Binary files /dev/null and b/lib/commons-configuration-1.9.jar differ
diff --git a/lib/zap-2.7.0.jar b/lib/zap-2.7.0.jar
new file mode 100644
index 0000000..b840e69
Binary files /dev/null and b/lib/zap-2.7.0.jar differ
diff --git a/src/org/zaproxy/zap/extension/endpointfinder/ExtensionEndpointFinder.java b/src/org/zaproxy/zap/extension/endpointfinder/ExtensionEndpointFinder.java
new file mode 100644
index 0000000..52a639c
--- /dev/null
+++ b/src/org/zaproxy/zap/extension/endpointfinder/ExtensionEndpointFinder.java
@@ -0,0 +1,135 @@
+/*
+ * Zed Attack Proxy (ZAP) and its related class files.
+ *
+ * ZAP is an HTTP/HTTPS proxy for assessing web application security.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.zaproxy.zap.extension.endpointfinder;
+
+import org.parosproxy.paros.extension.ExtensionAdaptor;
+import org.parosproxy.paros.extension.ExtensionHook;
+import org.zaproxy.zap.extension.httppanel.Message;
+import org.zaproxy.zap.extension.httppanel.component.split.response.ResponseSplitComponent;
+import org.zaproxy.zap.extension.httppanel.view.HttpPanelDefaultViewSelector;
+import org.zaproxy.zap.extension.httppanel.view.HttpPanelView;
+import org.zaproxy.zap.extension.httppanel.view.impl.models.http.response.ResponseBodyByteHttpPanelViewModel;
+import org.zaproxy.zap.view.HttpPanelManager;
+import org.zaproxy.zap.view.HttpPanelManager.HttpPanelDefaultViewSelectorFactory;
+import org.zaproxy.zap.view.HttpPanelManager.HttpPanelViewFactory;
+
+public class ExtensionEndpointFinder extends ExtensionAdaptor {
+ public static final String NAME = "ExtensionEndpointFinder";
+
+ public ExtensionEndpointFinder() {
+ super(NAME);
+ }
+
+ public void hook(ExtensionHook extensionHook) {
+ super.hook(extensionHook);
+
+ if (getView() != null) {
+ HttpPanelManager panelManager = HttpPanelManager.getInstance();
+
+ panelManager.addResponseViewFactory(ResponseSplitComponent.NAME, new ResponseEndpointFinderTextViewFactory());
+ panelManager.addResponseDefaultViewSelectorFactory(ResponseSplitComponent.NAME, new ResponseEndpointFinderTextViewDefaultViewSelectorFactory());
+ }
+ }
+
+ public boolean canUnload() {
+ return true;
+ }
+
+ public void unload() {
+ if (getView() != null) {
+ HttpPanelManager panelManager = HttpPanelManager.getInstance();
+
+ panelManager.removeResponseViewFactory(ResponseSplitComponent.NAME, ResponseEndpointFinderTextViewFactory.NAME);
+ panelManager.removeResponseViews(ResponseSplitComponent.NAME, ResponseEndpointFinderTextView.NAME, ResponseSplitComponent.ViewComponent.BODY);
+
+ panelManager.removeResponseDefaultViewSelectorFactory(ResponseSplitComponent.NAME, ResponseEndpointFinderTextViewDefaultViewSelectorFactory.NAME);
+ panelManager.removeResponseDefaultViewSelectors(ResponseSplitComponent.NAME, ResponseEndpointFinderTextViewDefaultViewSelector.NAME, ResponseSplitComponent.ViewComponent.BODY);
+ }
+ }
+
+ private static final class ResponseEndpointFinderTextViewFactory implements HttpPanelViewFactory {
+ public static final String NAME = "ResponseEndpointFinderTextViewFactory";
+
+ public String getName() {
+ return NAME;
+ }
+
+ public HttpPanelView getNewView() {
+ return new ResponseEndpointFinderTextView(new ResponseBodyByteHttpPanelViewModel());
+ }
+
+ public Object getOptions() {
+ return ResponseSplitComponent.ViewComponent.BODY;
+ }
+ }
+
+ private static final class ResponseEndpointFinderTextViewDefaultViewSelector implements HttpPanelDefaultViewSelector {
+ public static final String NAME = "ResponseEndpointFinderTextViewDefaultViewSelector";
+
+ public String getName() {
+ return NAME;
+ }
+
+ public boolean matchToDefaultView(Message message) {
+ return ResponseEndpointFinderTextView.isJavaScriptContent(message);
+ }
+
+ public String getViewName() {
+ return ResponseEndpointFinderTextView.NAME;
+ }
+
+ public int getOrder() {
+ return 20;
+ }
+ }
+
+ private static final class ResponseEndpointFinderTextViewDefaultViewSelectorFactory implements HttpPanelDefaultViewSelectorFactory {
+ private static HttpPanelDefaultViewSelector defaultViewSelector = null;
+ public static final String NAME = "ResponseEndpointFinderTextViewDefaultViewSelectorFactory";
+
+ private HttpPanelDefaultViewSelector getDefaultViewSelector() {
+ if (defaultViewSelector == null) {
+ createViewSelector();
+ }
+ return defaultViewSelector;
+ }
+
+ private synchronized void createViewSelector() {
+ if (defaultViewSelector == null) {
+ defaultViewSelector = new ResponseEndpointFinderTextViewDefaultViewSelector();
+ }
+ }
+
+ public String getName() {
+ return NAME;
+ }
+
+ public HttpPanelDefaultViewSelector getNewDefaultViewSelector() {
+ return getDefaultViewSelector();
+ }
+
+ public Object getOptions() {
+ System.out.println("Get Options ...");
+ return ResponseSplitComponent.ViewComponent.BODY;
+ }
+ }
+
+ public String getAuthor() {
+ return "Olivier Arteau";
+ }
+}
diff --git a/src/org/zaproxy/zap/extension/endpointfinder/ResponseEndpointFinderTextView.java b/src/org/zaproxy/zap/extension/endpointfinder/ResponseEndpointFinderTextView.java
new file mode 100644
index 0000000..e9308e9
--- /dev/null
+++ b/src/org/zaproxy/zap/extension/endpointfinder/ResponseEndpointFinderTextView.java
@@ -0,0 +1,176 @@
+/*
+ * Zed Attack Proxy (ZAP) and its related class files.
+ *
+ * ZAP is an HTTP/HTTPS proxy for assessing web application security.
+ *
+ * Copyright 2016 The ZAP Development Team
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.zaproxy.zap.extension.endpointfinder;
+
+import java.awt.BorderLayout;
+import java.util.List;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import org.apache.commons.configuration.FileConfiguration;
+import org.parosproxy.paros.network.HttpHeaderField;
+import org.parosproxy.paros.network.HttpMessage;
+import org.zaproxy.zap.extension.httppanel.Message;
+import org.zaproxy.zap.extension.httppanel.view.HttpPanelView;
+import org.zaproxy.zap.extension.httppanel.view.HttpPanelViewModel;
+import org.zaproxy.zap.extension.httppanel.view.HttpPanelViewModelEvent;
+import org.zaproxy.zap.extension.httppanel.view.HttpPanelViewModelListener;
+import org.zaproxy.zap.extension.httppanel.view.impl.models.http.AbstractHttpByteHttpPanelViewModel;
+import org.zaproxy.zap.extension.httppanel.view.impl.models.http.response.ResponseBodyByteHttpPanelViewModel;
+
+import ca.zhack.endpointfinder.EndpointEntry;
+import ca.zhack.endpointfinder.EndpointFinder;
+import ca.zhack.endpointfinder.EndpointResult;
+import ca.zhack.endpointfinder.Position;
+
+/**
+ * @author Olivier Arteau
+ */
+public class ResponseEndpointFinderTextView implements HttpPanelView, HttpPanelViewModelListener {
+ public static final String NAME = "ResponseEndpointFinderTextView";
+
+ private JPanel mainPanel;
+ private JLabel resultLabel;
+
+ private AbstractHttpByteHttpPanelViewModel model;
+
+ public ResponseEndpointFinderTextView(ResponseBodyByteHttpPanelViewModel model) {
+ this.model = model;
+
+ resultLabel = new JLabel();
+ resultLabel.setVerticalAlignment(JLabel.TOP);
+
+ mainPanel = new JPanel(new BorderLayout());
+ mainPanel.add(new JScrollPane(resultLabel));
+
+ this.model.addHttpPanelViewModelListener(this);
+ }
+
+ public void setSelected(boolean selected) {
+ if (selected) {
+ resultLabel.requestFocusInWindow();
+ }
+ }
+
+ public String getCaptionName() {
+ return "EndpointFinder";
+ }
+
+ public String getTargetViewName() {
+ return "";
+ }
+
+ public int getPosition() {
+ return 1;
+ }
+
+ public boolean isEnabled(Message message) {
+ return isJavaScriptContent(message);
+ }
+
+ public boolean hasChanged() {
+ return false;
+ }
+
+ public JComponent getPane() {
+ return mainPanel;
+ }
+
+ public boolean isEditable() {
+ return false;
+ }
+
+ public String getName() {
+ return NAME;
+ }
+
+ public HttpPanelViewModel getModel() {
+ return model;
+ }
+
+ public void dataChanged(HttpPanelViewModelEvent e) {
+ if (!isEnabled(model.getMessage())) {
+ resultLabel.setText("");
+ return;
+ }
+
+ try {
+ HttpMessage msg = (HttpMessage) model.getMessage();
+ String stringToParse = new String(msg.getResponseBody().getBytes());
+ StringBuilder display = new StringBuilder();
+ EndpointResult result = EndpointFinder.getEndpoints(stringToParse);
+ List entries = result.getEntries();
+
+ display.append("");
+ display.append("Results (" + entries.size() + ")
");
+
+ for (EndpointEntry entry : entries) {
+ display.append("--------------------
");
+ display.append("Path : " + entry.getPath() + "
");
+
+
+ if (entry.getUnknownPosition().size() > 0) {
+ int positionNumber = 1;
+ for (Position pos : entry.getUnknownPosition()) {
+ String formatUnknowInfo = "Variable #%d : %s (start: %d, end: %d)
";
+ display.append(String.format(
+ formatUnknowInfo,
+ positionNumber,
+ stringToParse.substring(pos.getStart(), pos.getEnd()),
+ pos.getStart(),
+ pos.getEnd()
+ ));
+ }
+ }
+ }
+
+ display.append("--------------------
");
+ display.append("");
+ resultLabel.setText(display.toString());
+ } catch (Exception err) {
+ String errMessage = "An error occured during the parsing of the content.\n\n";
+ errMessage += err.getMessage();
+ resultLabel.setText(errMessage);
+ }
+ }
+
+ public static boolean isJavaScriptContent(Message message) {
+ if (!(message instanceof HttpMessage)) {
+ return false;
+ }
+
+ for (HttpHeaderField field : ((HttpMessage) message).getResponseHeader().getHeaders()) {
+ if (field.getName().toLowerCase().equals("content-type")) {
+ return field.getValue().contains("javascript");
+ }
+ }
+
+ return false;
+ }
+
+ public void setEditable(boolean editable) { }
+ public void setParentConfigurationKey(String configurationKey) { }
+ public void loadConfiguration(FileConfiguration fileConfiguration) { }
+ public void saveConfiguration(FileConfiguration fileConfiguration) { }
+ public void save() { }
+}
diff --git a/src/org/zaproxy/zap/extension/endpointfinder/ZapAddOn.xml b/src/org/zaproxy/zap/extension/endpointfinder/ZapAddOn.xml
new file mode 100644
index 0000000..0056368
--- /dev/null
+++ b/src/org/zaproxy/zap/extension/endpointfinder/ZapAddOn.xml
@@ -0,0 +1,19 @@
+
+ EndpointFinder
+ 12
+ beta
+ Zap plugin for EndpointFinder
+ Olivier Arteau
+
+
+
+
+ org.zaproxy.zap.extension.endpointfinder.ExtensionEndpointFinder
+
+
+
+
+
+ 2.7.0
+
+
diff --git a/src/org/zaproxy/zap/extension/endpointfinder/lib/endpointfinder-java-0.0.1-SNAPSHOT.jar b/src/org/zaproxy/zap/extension/endpointfinder/lib/endpointfinder-java-0.0.1-SNAPSHOT.jar
new file mode 100644
index 0000000..4e1a4db
Binary files /dev/null and b/src/org/zaproxy/zap/extension/endpointfinder/lib/endpointfinder-java-0.0.1-SNAPSHOT.jar differ