/* SAAF: A static analyzer for APK files.
* Copyright (C) 2013 syssec.rub.de
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.rub.syssec.saaf.gui.editor;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.Vector;
import javax.swing.JEditorPane;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.Position;
import javax.swing.text.StyledDocument;
import javax.swing.text.StyledEditorKit;
import org.apache.log4j.Logger;
public class LinkEditorKit extends StyledEditorKit {
private static final long serialVersionUID = -3788854220848840779L;
// attribute on inline elements; if value is URL, will be used for the
// HyperlinkEvent
public static final Object LINK = new StringBuffer("link");
// can be static because it picks up the editor from the MouseEvent
private final MouseListener linkHandler;
private final File byteCodeDirectory;
private FileTree tree;
/**
* FIXME: Can this result in a Nullpointer? When is it set in FileTree?
*/
private File lastClickedFile = null;
private final Vector<Vector<String>> history;
/**
*
* @param history
* @param byteCodeDirectory the directory where SMALI files are found for the corresponding application
*/
public LinkEditorKit(Vector<Vector<String>> history, File byteCodeDirectory, FileTree t) {
linkHandler = new LinkHandler();
this.history = history;
this.byteCodeDirectory = byteCodeDirectory;
tree=t;
}
public void install(JEditorPane p) {
super.install(p);
p.addMouseListener(linkHandler);
}
public void deinstall(JEditorPane p) {
p.removeMouseListener(linkHandler);
super.deinstall(p);
}
private class LinkHandler extends MouseAdapter {
private Logger logger=Logger.getLogger(LinkEditorKit.class);
public LinkHandler() {
}
private Element characterElementAt(MouseEvent e) {
JEditorPane p = (JEditorPane) e.getComponent();
Position.Bias[] bias = new Position.Bias[1];
int position = p.getUI().viewToModel(p, e.getPoint(), bias);
if (bias[0] == Position.Bias.Backward && position != 0)
--position;
Element c = ((StyledDocument) p.getDocument())
.getCharacterElement(position);
// should test whether really inside
return c;
}
public void mouseReleased(MouseEvent e) {
if (!SwingUtilities.isLeftMouseButton(e))
return;
JEditorPane p = (JEditorPane) e.getComponent();
if (p.isEditable())
return;
Element c = characterElementAt(e);
if (c != null && c.getAttributes().getAttribute(LINK) != null) {
try {
// System.out.println(">> Link " +
// p.getDocument().getText(c.getStartOffset(),
// c.getEndOffset() - c.getStartOffset()));
String class_name = p
.getDocument()
.getText(c.getStartOffset(),
c.getEndOffset() - c.getStartOffset())
.split(";")[0].substring(
1,
p.getDocument()
.getText(
c.getStartOffset(),
c.getEndOffset()
- c.getStartOffset())
.split(";")[0].length());
File datei = new File(byteCodeDirectory, File.separator+"smali"+File.separator+ class_name + ".smali");
// zum abschneiden des Pfades
File AppDir = byteCodeDirectory.getParentFile();
if (p.getDocument()
.getText(c.getStartOffset(),
c.getEndOffset() - c.getStartOffset())
.split(";")[1].length() >= 2) {
// System.out.println(search);
// System.out.println(BytecodeSearcher.searchStringinFile(datei,
// search));
if (history.size() == 0) {
Vector<String> entry = new Vector<String>();
// File click = app.getLastClickedFile();
// entry.add(click.getAbsolutePath()
// .substring(
// AppDir.toString().length(),
// click.getAbsolutePath().toString()
// .length()));
// entry.add(BytecodeSearcher.searchStringinFile(click,
// search));
entry.add(lastClickedFile.getAbsolutePath()
.substring(
AppDir.getAbsolutePath().length(),
lastClickedFile.getAbsolutePath().toString()
.length()));
// entry.add(BytecodeSearcher.searchStringinFile(lastClickedFile,
// search));
history.add(entry);
}
// tree.searchNode(
// datei.getAbsolutePath().substring(
// AppDir.getAbsolutePath().length(),
// datei.getAbsolutePath().toString()
// .length()),
// BytecodeSearcher.searchStringinFile(datei, search));
Vector<String> entry = new Vector<String>();
entry.add(datei.getAbsolutePath().substring(
AppDir.getAbsolutePath().length(),
datei.getAbsolutePath().toString().length()));
// entry.add(BytecodeSearcher.searchStringinFile(datei, search));
history.add(entry);
} else {
tree.searchNode(
datei.getAbsolutePath().substring(
AppDir.getAbsolutePath().length(),
datei.getAbsolutePath().toString()
.length()), "0");
Vector<String> entry = new Vector<String>();
entry.add(datei.getAbsolutePath().substring(
// AppDir.toString().length(),
datei.getAbsolutePath().toString().length()));
entry.add("0");
history.add(entry);
}
//System.out.println(c.getStartOffset());
// System.out.println(p.getDocument().getText(c.getStartOffset(),
// c.getEndOffset() -
// c.getStartOffset()).split(";").length);
// FileTree.searchNode(tableContent.get(viewRow).get(0),tableContent.get(viewRow).get(1));
} catch (BadLocationException e1) {
logger.warn("Problem with history",e1);
} catch (Exception e1) {
logger.warn("Problem with history",e1);
}
}
}
}
/**
* Sets the last clicked file in the GUI.
* @param lastClickedFile
*/
protected void setLastClickedFile(File lastClickedFile) {
this.lastClickedFile = lastClickedFile;
}
}