/*
* Copyright (C) 2012 Sony Mobile Communications AB
*
* This file is part of ApkAnalyser.
*
* 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 andreflect;
import javax.swing.JViewport;
import mereflect.MEMethod;
import mereflect.Type;
import org.jf.dexlib.ClassDefItem;
import org.jf.dexlib.FieldIdItem;
import org.jf.dexlib.TypeIdItem;
import org.jf.dexlib.Code.Instruction;
import analyser.gui.Selection;
import analyser.gui.TextBuilder;
import andreflect.gui.linebuilder.DalvikByteCodeLineBuilder;
import andreflect.injection.abs.DalvikInjectionMethod;
public final class Util {
public static String shortenClassName(String str) {
String ret = str;
if (str.lastIndexOf(".") != -1) {
ret = ret.substring(ret.lastIndexOf(".") + 1);
}
if (str.lastIndexOf("$") != -1) {
ret = ret.substring(ret.lastIndexOf("$") + 1);
}
return ret;
}
public static String getClassRawName(String classDescriptor) {
String res = new String(classDescriptor);
int i = 0;
while (classDescriptor.charAt(i) == '[' && i < res.length()) {
i++;
}
if (i == res.length()) {
System.out.println("Unrecognized class descriptor" + res);
} else if (i == res.length() - 1) {
switch (classDescriptor.charAt(i)) {
case 'I'://int
case 'Z'://boolean
case 'B'://byte
case 'C'://char
case 'F'://float
case 'S'://short
case 'D'://double
case 'J'://long
break;
case 'L'://object
default:
System.out.println("Unrecognized class descriptor" + res);
break;
}
} else if (res.charAt(i) != 'L' ||
res.charAt(res.length() - 1) != ';') {
System.out.println("Unrecognized class descriptor" + res);
} else {
res = res.substring(i + 1, res.length() - 1);
}
return res;
}
public static String getClassRawName(ClassDefItem classDefItem) {
String res = new String(classDefItem.getClassType().getTypeDescriptor());
return getClassRawName(res);
}
public static String getClassRawName(TypeIdItem typeIdItem) {
String res = new String(typeIdItem.getTypeDescriptor());
return getClassRawName(res);
}
public static String getClassName(ClassDefItem classDefItem) {
return getClassRawName(classDefItem).replace('/', '.');
}
public static String getClassName(String classDescriptor) {
return getClassRawName(classDescriptor).replace('/', '.');
}
public static String getClassName(TypeIdItem typeIdItem) {
return getClassRawName(typeIdItem).replace('/', '.');
}
public static String getProtoString(String descr) {
StringBuffer sb = new StringBuffer();
int arrayDepth = 0;
boolean first = true;
char c;
for (int i = 0; i < descr.length(); i++) {
c = descr.charAt(i);
switch (c) {
case Type.CH_ARRAY:
//if (first == false){ sb.append(", "); }
i++;
arrayDepth = 1;
while ((c = descr.charAt(i)) == Type.CH_ARRAY) {
arrayDepth++;
i++;
}
i--;
break;
case Type.CH_CLASS_PRE:
if (first == false) {
sb.append(", ");
}
i++;
while ((c = descr.charAt(i)) != Type.CH_CLASS_POST
&& c != '<' && c != '>') {
if (c == '/') {
sb.append('.');
} else {
sb.append(c);
}
i++;
}
i--;
first = false;
if (arrayDepth != 0) {
for (int j = 0; j < arrayDepth; j++) {
sb.append("[]");
}
arrayDepth = 0;
}
break;
case Type.CH_BOOLEAN:
if (first == false) {
sb.append(", ");
}
sb.append("boolean");
first = false;
if (arrayDepth != 0) {
for (int j = 0; j < arrayDepth; j++) {
sb.append("[]");
}
arrayDepth = 0;
}
break;
case Type.CH_BYTE:
if (first == false) {
sb.append(", ");
}
sb.append("byte");
first = false;
if (arrayDepth != 0) {
for (int j = 0; j < arrayDepth; j++) {
sb.append("[]");
}
arrayDepth = 0;
}
break;
case Type.CH_CHAR:
if (first == false) {
sb.append(", ");
}
sb.append("char");
first = false;
if (arrayDepth != 0) {
for (int j = 0; j < arrayDepth; j++) {
sb.append("[]");
}
arrayDepth = 0;
}
break;
case Type.CH_DOUBLE:
if (first == false) {
sb.append(", ");
}
sb.append("double");
first = false;
if (arrayDepth != 0) {
for (int j = 0; j < arrayDepth; j++) {
sb.append("[]");
}
arrayDepth = 0;
}
break;
case Type.CH_FLOAT:
if (first == false) {
sb.append(", ");
}
sb.append("float");
first = false;
if (arrayDepth != 0) {
for (int j = 0; j < arrayDepth; j++) {
sb.append("[]");
}
arrayDepth = 0;
}
break;
case Type.CH_INT:
if (first == false) {
sb.append(", ");
}
sb.append("int");
first = false;
if (arrayDepth != 0) {
for (int j = 0; j < arrayDepth; j++) {
sb.append("[]");
}
arrayDepth = 0;
}
break;
case Type.CH_LONG:
if (first == false) {
sb.append(", ");
}
sb.append("long");
first = false;
if (arrayDepth != 0) {
for (int j = 0; j < arrayDepth; j++) {
sb.append("[]");
}
arrayDepth = 0;
}
break;
case Type.CH_SHORT:
if (first == false) {
sb.append(", ");
}
sb.append("short");
first = false;
if (arrayDepth != 0) {
for (int j = 0; j < arrayDepth; j++) {
sb.append("[]");
}
arrayDepth = 0;
}
break;
case Type.CH_VOID:
if (first == false) {
sb.append(", ");
}
sb.append("void");
first = false;
if (arrayDepth != 0) {
for (int j = 0; j < arrayDepth; j++) {
sb.append("[]");
}
arrayDepth = 0;
}
break;
case '(':
case ')':
case '<':
case '>':
sb.append(c);
first = true;
break;
default:
case ';':
break;
}
}
return sb.toString();
}
public static String getMethodSignature(MEMethod method) {
return method.getName() + "(" + method.getArgumentsString() + ")" + method.getReturnClassString();
}
public static FieldIdItem getFieldIdItem() {
if (!(Selection.getSelectedView() instanceof TextBuilder)) {
return null;
}
TextBuilder text = (TextBuilder) Selection.getSelectedView();
if (text == null) {
return null;
}
Object ref = Selection.getSelectedObject();
if (ref == null || !DexField.class.isAssignableFrom(ref.getClass())) {
return null;
}
DexField dexField = (DexField) ref;
return dexField.getFieldIdItem();
}
public static DalvikByteCodeLineBuilder.DalvikBytecodeOffset getDalvikBytecodeOffset() {
if (!(Selection.getSelectedView() instanceof TextBuilder)) {
return null;
}
TextBuilder text = (TextBuilder) Selection.getSelectedView();
if (text == null) {
return null;
}
Object ref = Selection.getSelectedObject();
if (ref == null || !DalvikByteCodeLineBuilder.DalvikBytecodeOffset.class.isAssignableFrom(ref.getClass())) {
return null;
}
return (DalvikByteCodeLineBuilder.DalvikBytecodeOffset) ref;
}
public static void printInjectionInfoInTextBuilder(String text1, String text2, DalvikInjectionMethod injection) {
if (!(Selection.getSelectedView() instanceof TextBuilder)) {
return;
}
TextBuilder text = (TextBuilder) Selection.getSelectedView();
if (text == null) {
return;
}
int pos = text.getCaretPosition();
JViewport view = text.getScrollPane().getViewport();
text.getLineBuilder().insertLineBefore(text.getCurrentLine());
text.getLineBuilder().append(" >>> ", 0xbb0000);
text.getLineBuilder().append("PRINT(", 0x000000);
text.getLineBuilder().append("\"" + text1 + "\"", 0x0000bb);
if (text2 != null) {
text.getLineBuilder().append("+" + text2, 0x000000);
}
text.getLineBuilder().append(")", 0x000000);
text.getLineBuilder().setReferenceToCurrent(injection);
text.updateDocument();
text.setCaretPosition(pos);
text.getScrollPane().setViewport(view);
}
public static String appendCodeAddressAndLineNum(String str, Instruction ins) {
StringBuffer sb = new StringBuffer(str);
sb.append("(");
sb.append(String.format("%X", ins.codeAddress));
if (ins.line != -1) {
sb.append(",");
sb.append(ins.line);
}
sb.append(")");
return sb.toString();
}
}