diff --git a/src/burp/BurpExtender.java b/src/burp/BurpExtender.java index ce46d30..a330bf9 100644 --- a/src/burp/BurpExtender.java +++ b/src/burp/BurpExtender.java @@ -2,7 +2,6 @@ import com.k4ch0w.pwnback.PwnBackGUI; import com.k4ch0w.pwnback.PwnBackMediator; -import com.k4ch0w.pwnback.PwnBackSettings; import javax.swing.*; import java.awt.*; @@ -11,7 +10,6 @@ public class BurpExtender implements IBurpExtender, ITab { private IBurpExtenderCallbacks callbacks; private IExtensionHelpers helpers; private PwnBackGUI panel; - // private DocumentFrame d; @Override public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks) { @@ -19,25 +17,9 @@ public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks) { helpers = callbacks.getHelpers(); callbacks.setExtensionName("PwnBack"); SwingUtilities.invokeLater(() -> { - PwnBackSettings settings = new PwnBackSettings(); //Singleton Initialization PwnBackMediator mediator = new PwnBackMediator(); panel = mediator.getGui(); callbacks.customizeUiComponent(panel); - - /* - try { - ArrayList temp = new ArrayList(); - temp.add("fuckit"); - - d = new DocumentFrame(temp, "Ain't no way I'mma fail "); - } catch (IOException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } - callbacks.customizeUiComponent(d); - - */ callbacks.addSuiteTab(BurpExtender.this); }); } diff --git a/src/com.k4ch0w.pwnback/PwnBackDocumentFrame.java b/src/com.k4ch0w.pwnback/PwnBackDocumentFrame.java new file mode 100644 index 0000000..112c489 --- /dev/null +++ b/src/com.k4ch0w.pwnback/PwnBackDocumentFrame.java @@ -0,0 +1,90 @@ +/* + * Created by JFormDesigner on Mon Apr 10 14:57:16 PDT 2017 + */ + +package com.k4ch0w.pwnback; + +import net.miginfocom.swing.MigLayout; +import org.xml.sax.SAXException; + +import javax.swing.*; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.io.IOException; +import java.util.ArrayList; + +/** + * @author Paul Ganea + */ +class PwnBackDocumentFrame extends JFrame { + // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables + // Generated using JFormDesigner commercial license + private JScrollPane scrollPane1; + private JList list1; + private JPanel panel1; + private JScrollPane scrollPane2; + private JTextPane textPane1; + + PwnBackDocumentFrame(ArrayList docs) throws IOException, SAXException { + initComponents(); + DefaultListModel listModel; + listModel = new DefaultListModel<>(); + for (PwnBackDocument doc : docs) { + listModel.addElement(doc); + } + list1.setModel(listModel); + ListSelectionListener listSelectionListener = listSelectionEvent -> { + if (!listSelectionEvent.getValueIsAdjusting()) { + textPane1.setText(listModel.get(list1.getSelectedIndex()).getDocument()); + } + }; + list1.addListSelectionListener(listSelectionListener); + textPane1.setText(docs.get(0).getDocument()); + textPane1.setEditable(false); + } + + private void initComponents() { + // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents + // Generated using JFormDesigner non-commercial license + scrollPane1 = new JScrollPane(); + list1 = new JList<>(); + panel1 = new JPanel(); + scrollPane2 = new JScrollPane(); + textPane1 = new JTextPane(); + + //======== this ======== + setMinimumSize(new Dimension(1000, 700)); + Container contentPane = getContentPane(); + contentPane.setLayout(new MigLayout( + "insets 0,hidemode 3", + // columns + "[fill]" + + "[grow]", + // rows + "[grow,fill]")); + + //======== scrollPane1 ======== + { + scrollPane1.setMinimumSize(new Dimension(250, 148)); + scrollPane1.setPreferredSize(new Dimension(250, 148)); + scrollPane1.setViewportView(list1); + } + contentPane.add(scrollPane1, "cell 0 0"); + + //======== panel1 ======== + { + panel1.setLayout(new GridLayout()); + + //======== scrollPane2 ======== + { + scrollPane2.setViewportView(textPane1); + } + panel1.add(scrollPane2); + } + contentPane.add(panel1, "cell 1 0,growx"); + pack(); + setLocationRelativeTo(getOwner()); + // JFormDesigner - End of component initialization //GEN-END:initComponents + } + // JFormDesigner - End of variables declaration //GEN-END:variables +} diff --git a/src/com.k4ch0w.pwnback/PwnBackDocumentFrame.jfd b/src/com.k4ch0w.pwnback/PwnBackDocumentFrame.jfd new file mode 100644 index 0000000..dee7b9e --- /dev/null +++ b/src/com.k4ch0w.pwnback/PwnBackDocumentFrame.jfd @@ -0,0 +1,42 @@ +JFDML JFormDesigner: "6.0.0.0.84" Java: "1.8.0_112-release" encoding: "UTF-8" + +new FormModel { + contentType: "form/swing" + root: new FormRoot { + add( new FormWindow( "javax.swing.JFrame", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "insets 0,hidemode 3" + "$columnConstraints": "[fill][grow]" + "$rowConstraints": "[grow,fill]" + } ) { + name: "this" + "minimumSize": new java.awt.Dimension( 1000, 700 ) + add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { + name: "scrollPane1" + "minimumSize": new java.awt.Dimension( 250, 148 ) + "preferredSize": new java.awt.Dimension( 250, 148 ) + add( new FormComponent( "javax.swing.JList" ) { + name: "list1" + auxiliary() { + "JavaCodeGenerator.typeParameters": "String" + } + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.GridLayout ) ) { + name: "panel1" + add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { + name: "scrollPane2" + add( new FormComponent( "javax.swing.JTextPane" ) { + name: "textPane1" + } ) + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0,growx" + } ) + }, new FormLayoutConstraints( null ) { + "location": new java.awt.Point( 0, 0 ) + "size": new java.awt.Dimension( 600, 400 ) + } ) + } +} diff --git a/src/com.k4ch0w.pwnback/PwnBackMediator.java b/src/com.k4ch0w.pwnback/PwnBackMediator.java index b55db2f..2252e6e 100644 --- a/src/com.k4ch0w.pwnback/PwnBackMediator.java +++ b/src/com.k4ch0w.pwnback/PwnBackMediator.java @@ -23,13 +23,11 @@ //Wayback documentation located at https://github.com/internetarchive/wayback/tree/master/wayback-cdx-server public class PwnBackMediator { + private static final String waybackString = "http://web.archive.org/cdx/search/cdx?url=%s&limit=%s&from=%s&to=%s" + + "&showResumeKey=True&collapse=digest";//Remove duplicates based on page digest public final ReentrantLock treeModelLock = new ReentrantLock(); public final ReentrantLock logTableLock = new ReentrantLock(); - private final String waybackString = "http://web.archive.org/cdx/search/cdx?url=%s&limit=%s&from=%s&to=%s" + - "&showResumeKey=True&collapse=digest";//Remove duplicates based on page digest - private final int recordLimit; - private final String yearStart; - private final String yearEnd; + private final int recordLimit = 1000; private final List tableEntries = new ArrayList<>(); private final PwnBackGUI gui = new PwnBackGUI(this); private final BlockingQueue documentsToParse = new ArrayBlockingQueue<>(1000); @@ -37,17 +35,17 @@ public class PwnBackMediator { private ExecutorService docParsers; private ExecutorService webDrivers; - public PwnBackMediator() { - recordLimit = 1000; - yearStart = Integer.toString(PwnBackSettings.startYear); - yearEnd = Integer.toString(PwnBackSettings.endYear); - } + private String yearStart = Integer.toString(PwnBackSettings.startYear); + private String yearEnd = Integer.toString(PwnBackSettings.endYear); void start() { LOG_INFO("Marty McFly: Wait a minute. Wait a minute, Doc. Ah..." + " Are you telling me that you built a time machine... out of a DeLorean?"); LOG_INFO("Dr. Emmett Brown: The way I see it, if you're gonna build a time machine into a car," + " why not do it with some *style?*"); + + yearStart = Integer.toString(PwnBackSettings.endYear); + yearEnd = Integer.toString(PwnBackSettings.endYear); docParsers = Executors.newFixedThreadPool(PwnBackSettings.numofHttpResponseParsers); webDrivers = Executors.newFixedThreadPool(PwnBackSettings.numOfJSWebDrivers); for (int i = 0; i < PwnBackSettings.numofHttpResponseParsers; i++) { @@ -89,8 +87,6 @@ private void LOG(PwnBackTableEntry entry) { } finally { logTableLock.unlock(); } - - } void addPath(PwnBackNode entry) { @@ -102,16 +98,20 @@ void addPath(PwnBackNode entry) { } } - private String generatePath(TreeModel model, Object object, String indent) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) object; - if (node.getParent() != null && node.getParent().equals(model.getRoot())) { - indent = "/"; //root node case otherwise will be // instead of / + private boolean checkIfRootNode(TreeModel model, DefaultMutableTreeNode node) { + return node.getParent() != null && node.getParent().equals(model.getRoot()); + } + + private String generatePath(TreeModel model, Object currentNode, String path) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) currentNode; + if (checkIfRootNode(model, node)) { + path = "/"; } - StringBuilder myRow = new StringBuilder(indent + object + System.getProperty("line.separator")); - for (int i = 0; i < model.getChildCount(object); i++) { - myRow.append(generatePath(model, model.getChild(object, i), indent + object + "/")); + StringBuilder pathBuilder = new StringBuilder(path + currentNode + System.getProperty("line.separator")); + for (int i = 0; i < model.getChildCount(currentNode); i++) { + pathBuilder.append(generatePath(model, model.getChild(currentNode, i), path + currentNode + "/")); } - return myRow.toString(); + return pathBuilder.toString(); } boolean exportPathsToFile(TreeModel tree, Path filename) { diff --git a/src/com.k4ch0w.pwnback/PwnBackNode.java b/src/com.k4ch0w.pwnback/PwnBackNode.java index 06c0d33..3a9aed4 100644 --- a/src/com.k4ch0w.pwnback/PwnBackNode.java +++ b/src/com.k4ch0w.pwnback/PwnBackNode.java @@ -12,8 +12,8 @@ public class PwnBackNode { /* Root init only */ - PwnBackNode(String path) { - this.path = path; + PwnBackNode(String rootPath) { + this.path = rootPath; } PwnBackNode(String path, PwnBackDocument doc) { diff --git a/src/com.k4ch0w.pwnback/PwnBackParser.java b/src/com.k4ch0w.pwnback/PwnBackParser.java index 5797f59..00369c3 100644 --- a/src/com.k4ch0w.pwnback/PwnBackParser.java +++ b/src/com.k4ch0w.pwnback/PwnBackParser.java @@ -18,6 +18,8 @@ * Created by k4ch0w on 3/27/17. */ public class PwnBackParser implements Runnable { + private static final String ROBOTS_TXT = "robots.txt"; + private static final String SITEMAP_XML = "sitemap.xml"; private final PwnBackMediator mediator; PwnBackParser(PwnBackMediator mediator) { @@ -60,62 +62,78 @@ private String stripHTMLTags(String html) { return Jsoup.parse(html).text(); } + private void parseRobotsTxtLine(String line, PwnBackDocument doc) { + String[] tokens = line.split(" "); + if (tokens.length == 2) { + switch (tokens[0]) { + case "disallow:": + mediator.addPath(new PwnBackNode(tokens[1], doc)); + break; + case "allow:": + mediator.addPath(new PwnBackNode(tokens[1], doc)); + break; + case "sitemap:": + mediator.addURL(new PwnBackURL(tokens[1], PwnBackType.SITEMAPXML)); + break; + } + } else { + mediator.LOG_DEBUG("Fix this? " + Arrays.toString(tokens)); + } + } + private void parseRobotsTxt(PwnBackDocument doc) { String txt = stripHTMLTags(doc.getDocument()); Scanner scanner = new Scanner(txt); while (scanner.hasNextLine()) { String line = scanner.nextLine().toLowerCase(); - String[] temp = line.split(" "); - if (temp.length == 2) { - switch (temp[0]) { - case "disallow:": - mediator.addPath(new PwnBackNode(temp[1], doc)); - break; - case "allow:": - mediator.addPath(new PwnBackNode(temp[1], doc)); - break; - case "sitemap:": - mediator.addURL(new PwnBackURL(temp[1], PwnBackType.SITEMAPXML)); - break; + parseRobotsTxtLine(line, doc); + } + scanner.close(); + } + + private boolean isEmailAddress(String href) { + return href.startsWith("mailto:"); + } + + private boolean isHttpHref(String href) { + return href.startsWith("/web/") && href.contains("http"); + } + + private boolean checkValidPath(String path) { + return !path.isEmpty() && !path.equals("/") && !path.equals("/web/"); + } + + private void parseHrefTag(Element tag, PwnBackDocument document) { + String relHref = tag.attr("href"); + if (isEmailAddress(relHref)) { + mediator.LOG_INFO("Found email address " + relHref.replace("mailto:", "")); + } else if (isHttpHref(relHref)) { + String sanitizedURL = relHref.substring(relHref.indexOf("http")); + try { + URL temp = new URL(sanitizedURL); + String path = temp.getPath(); + if (checkValidPath(path) && checkValidURL(sanitizedURL)) { + mediator.addPath(new PwnBackNode(path, document)); } - } else { - mediator.LOG_DEBUG("Fix this? " + Arrays.toString(temp)); + } catch (MalformedURLException e) { + mediator.LOG_ERROR("Error parsing URL : " + sanitizedURL); + } + } else if (relHref.equals("") || relHref.startsWith("#") || relHref.equals("/")) { + mediator.LOG_DEBUG("Empty or starts with #: " + relHref); + } else { + if (checkValidURL(relHref)) { + mediator.addPath(new PwnBackNode(relHref, document)); } } - scanner.close(); } private void parseHTML(PwnBackDocument document) { String html = removeWaybackToolbar(document.getDocument()); Document doc = Jsoup.parse(html); Elements links = doc.select("a"); - for (Element link : + for (Element tag : links) { - String relHref = link.attr("href"); - if (relHref.startsWith("mailto:")) { - mediator.LOG_INFO("Found email address " + relHref.replace("mailto:", "")); - } else if (relHref.startsWith("/web/") && relHref.contains("http")) { - //Wayback machine uses it's domain to serve content thus things are prepended - // with http://archive.org/web and why I split them here - String clean = relHref.substring(relHref.indexOf("http")); - try { - URL temp = new URL(clean); - String path = temp.getPath(); - if (!path.isEmpty() && !path.equals("/") && !path.equals("/web/") - && !temp.getHost().contains("archive.org")) { - mediator.addPath(new PwnBackNode(path, document)); - } - } catch (MalformedURLException e) { - mediator.LOG_ERROR("Error parsing URL : " + clean); - } - } else if (relHref.equals("") || relHref.startsWith("#") || relHref.equals("/")) { - mediator.LOG_DEBUG("Empty or starts with #: " + relHref); - } else { - - if (checkValidURL(relHref)) { - mediator.addPath(new PwnBackNode(relHref, document)); - } - } + parseHrefTag(tag, document); } } @@ -134,19 +152,20 @@ private boolean checkValidURL(String url) { return false; } + private boolean checkValidWayBackArchive(String[] archive) { + return archive.length == 7 && (!archive[1].equals("http:///") || !archive[1].equals("https:///")); + } + private void parseWayBackAPI(PwnBackDocument doc) { String[] waybackUrls = stripHTMLTags(doc.getDocument()).split("\\r?\\n"); - for (String u : - waybackUrls) { + for (String u : waybackUrls) { String[] archive = u.split(" "); - if (archive.length == 7 && (!archive[1].equals("http:///") || !archive[1].equals("https:///"))) { //Each archive address has 7 values return + if (checkValidWayBackArchive(archive)) { String waybackRequestString = "http://web.archive.org/web/%s/%s"; String url = String.format(waybackRequestString, archive[1], archive[2]); mediator.addURL(new PwnBackURL(url, PwnBackType.HTML)); - String ROBOTS_TXT = "robots.txt"; mediator.addURL(new PwnBackURL(url + ROBOTS_TXT, PwnBackType.ROBOTS)); - String SITEMAP_XML = "sitemap.xml"; mediator.addURL(new PwnBackURL(url + SITEMAP_XML, PwnBackType.SITEMAPXML)); } } @@ -172,14 +191,14 @@ private void parseSitemapXML(PwnBackDocument doc) { SiteMap sm = (SiteMap) asmi; addSiteMapURLS(sm, doc); } else { - mediator.LOG_ERROR("Error figuring out ASM type: " + asmi.getClass()); + mediator.LOG_ERROR("Error figuring out SiteMap type: " + asmi.getClass()); } } } else { mediator.LOG_ERROR("Shouldn't be here"); } } catch (IOException | UnknownFormatException e) { - e.printStackTrace(); + mediator.LOG_DEBUG(e.getLocalizedMessage()); } } diff --git a/src/com.k4ch0w.pwnback/PwnBackWebDriver.java b/src/com.k4ch0w.pwnback/PwnBackWebDriver.java index 11463be..944a963 100644 --- a/src/com.k4ch0w.pwnback/PwnBackWebDriver.java +++ b/src/com.k4ch0w.pwnback/PwnBackWebDriver.java @@ -22,17 +22,22 @@ public class PwnBackWebDriver implements Runnable { .build(); DesiredCapabilities capability = new DesiredCapabilities(); capability.setCapability("takesScreenshot", false); - File f = new File(PwnBackSettings.caBundleLocation); String[] args = new String[1]; args[0] = ""; - if (f.exists() && !f.isDirectory()) { + if (checkSSLCertPathDefined()) { args[0] = "--ssl-certificates-path=" + PwnBackSettings.caBundleLocation; } capability.setCapability(PhantomJSDriverService.PHANTOMJS_CLI_ARGS, args); capability.setCapability("phantomjs.page.settings.userAgent", "Mozilla/5.0 (Windows NT 5.1; rv:22.0) Gecko/20100101 Firefox/22.0"); driver = new PhantomJSDriver(driverService, capability); + } - + private boolean checkSSLCertPathDefined() { + File f = new File(PwnBackSettings.caBundleLocation); + if (f.exists() && !f.isDirectory()) { + return true; + } + return false; } @Override diff --git a/src/com.k4ch0w.pwnback/PwnBackWebTree.java b/src/com.k4ch0w.pwnback/PwnBackWebTree.java index 953706b..0490f46 100644 --- a/src/com.k4ch0w.pwnback/PwnBackWebTree.java +++ b/src/com.k4ch0w.pwnback/PwnBackWebTree.java @@ -20,6 +20,7 @@ class PwnBackWebTree extends JPanel { private DefaultTreeModel treeModel; private JTree tree; + PwnBackWebTree() { super(new GridLayout(1, 0)); rootNode = new DefaultMutableTreeNode(new PwnBackNode("/")); @@ -29,27 +30,7 @@ class PwnBackWebTree extends JPanel { tree.getSelectionModel().setSelectionMode (TreeSelectionModel.SINGLE_TREE_SELECTION); tree.setShowsRootHandles(true); - tree.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) - tree.getLastSelectedPathComponent(); - if (node == null) return; - PwnBackNode nodeInfo = (PwnBackNode) node.getUserObject(); - DocumentFrame docPanel; - try { - docPanel = new DocumentFrame(nodeInfo.getDocuments()); - docPanel.setTitle(nodeInfo.getPath()); - docPanel.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - docPanel.setVisible(true); - } catch (IOException | SAXException e1) { - e1.printStackTrace(); - } - - } - } - }); + tree.addMouseListener(new PwnBackTreeMouseListener()); JScrollPane scrollPane = new JScrollPane(tree); add(scrollPane); } @@ -78,43 +59,60 @@ void addTreeNode(PwnBackNode node) { addTreeNode(null, temp, node.getFirstDocument()); } - private void addTreeNode(DefaultMutableTreeNode parent, String[] paths, PwnBackDocument doc) { - DefaultMutableTreeNode child; + private String[] removeEmptyOrNull(String[] paths) { while (paths[0] == null || paths[0].equals("")) { paths = Arrays.copyOfRange(paths, 1, paths.length); } - if (parent == null) { - parent = rootNode; + return paths; + } + + private boolean isLeafPath(String[] paths) { + return paths.length == 1; + } + + private void addNewLeaf(DefaultMutableTreeNode parent, DefaultMutableTreeNode child, PwnBackNode newNode) { + if (child == null) { + addChildNode(parent, newNode, false); + } else { + PwnBackNode existingNode = (PwnBackNode) child.getUserObject(); + existingNode.addDocument(newNode.getFirstDocument()); } - PwnBackNode newNode = new PwnBackNode(paths[0], doc); - if (paths.length == 1) { - child = pathExists(parent, paths[0]); - if (child == null) { - addObject(parent, newNode, false); + } + + private DefaultMutableTreeNode addNewChildNode(DefaultMutableTreeNode parent, DefaultMutableTreeNode child, PwnBackNode newNode) { + if (child == null) { + if (parent.equals(rootNode)) { + return addChildNode(parent, newNode, true); } else { - PwnBackNode existingNode = (PwnBackNode) child.getUserObject(); - existingNode.addDocument(doc); + return addChildNode(parent, newNode, false); } + } + return null; + } + + private void addTreeNode(DefaultMutableTreeNode parent, String[] paths, PwnBackDocument doc) { + if (parent == null) { + parent = rootNode; + } + paths = removeEmptyOrNull(paths); + String currentPath = paths[0]; + DefaultMutableTreeNode child; + child = pathExists(parent, currentPath); + PwnBackNode newNode = new PwnBackNode(currentPath, doc); + if (isLeafPath(paths)) { + addNewLeaf(parent, child, newNode); } else { - child = pathExists(parent, paths[0]); - if (child == null) { - //New Leaf - if (parent.equals(rootNode)) { - child = addObject(parent, newNode, true); - } else { - child = addObject(parent, newNode, false); - } - } + child = addNewChildNode(parent, child, newNode); addTreeNode(child, Arrays.copyOfRange(paths, 1, paths.length), doc); } } - private DefaultMutableTreeNode addObject(final DefaultMutableTreeNode parent, - Object child, - boolean shouldBeVisible) { - DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child); + private DefaultMutableTreeNode addChildNode(final DefaultMutableTreeNode parent, + Object child, + boolean shouldBeVisible) { + DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child); if (SwingUtilities.isEventDispatchThread()) { treeModel.insertNodeInto(childNode, parent, @@ -134,6 +132,26 @@ private DefaultMutableTreeNode addObject(final DefaultMutableTreeNode parent, return childNode; } + private class PwnBackTreeMouseListener extends MouseAdapter { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) + tree.getLastSelectedPathComponent(); + if (node == null) return; + PwnBackNode nodeInfo = (PwnBackNode) node.getUserObject(); + PwnBackDocumentFrame docPanel; + try { + docPanel = new PwnBackDocumentFrame(nodeInfo.getDocuments()); + docPanel.setTitle(nodeInfo.getPath()); + docPanel.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + docPanel.setVisible(true); + } catch (IOException | SAXException e1) { + e1.printStackTrace(); + } + + } + } + } }