# -*- coding: utf-8 -*-
"""
Sample client script for PNF Software's JEB2.
More samples are available on our website and within the scripts/ folder.
Refer to SCRIPTS.TXT for more information.
"""
import string
import re,collections
from com.pnfsoftware.jeb.client.api import IScript
from com.pnfsoftware.jeb.client.api import IScript, IGraphicalClientContext
from com.pnfsoftware.jeb.core import RuntimeProjectUtil
from com.pnfsoftware.jeb.core.actions import Actions, ActionContext, ActionXrefsData
from com.pnfsoftware.jeb.core.events import JebEvent, J
from com.pnfsoftware.jeb.core.output import AbstractUnitRepresentation, UnitRepresentationAdapter
from com.pnfsoftware.jeb.core.units.code import ICodeUnit, ICodeItem
from com.pnfsoftware.jeb.core.units.code.java import IJavaSourceUnit, IJavaStaticField, IJavaNewArray, IJavaConstant, IJavaCall, IJavaField, IJavaMethod, IJavaClass
from com.pnfsoftware.jeb.core.actions import ActionTypeHierarchyData
from com.pnfsoftware.jeb.core.actions import ActionRenameData
from com.pnfsoftware.jeb.core.util import DecompilerHelper
from com.pnfsoftware.jeb.core.output.text import ITextDocument
from com.pnfsoftware.jeb.core.units.code.android import IDexUnit
class JEB2_AutoRenameDerivedClass_V2(IScript):
def run(self, ctx):
engctx = ctx.getEnginesContext()
if not engctx:
print('Back-end engines not initialized')
return
projects = engctx.getProjects()
if not projects:
print('There is no opened project')
return
# 逻辑开始
self.debug = 0 #0=False, 1=True
self.ctx = ctx
self.prj = projects[0]
errMsg1 = u'请移动鼠标,将光标输入点放到源码文件中的 基类类名 处~然后使用F2快捷键运行此脚本(JEB 中 F2快捷键的功能是运行最近使用的脚本)'
self.focusView = ctx.getFocusedView()
if not self.focusView:
print(errMsg1)
return
self.focusFragment = self.focusView.getActiveFragment()
if not self.focusFragment:
print(errMsg1)
return
self.focusUnit = self.focusFragment.getUnit()
if not self.focusUnit:
print(errMsg1)
return
self.activeAddress = self.focusFragment.getActiveAddress()
self.activeItem = self.focusFragment.getActiveItem()
if not self.activeItem:
print(errMsg1)
return
itemStr = self.activeItem.toString()
if(itemStr.find('cid=CLASS_NAME') < 0):
print(errMsg1)
return
self.focusUnit2 = RuntimeProjectUtil.findUnitsByType(self.prj, ICodeUnit, False)[0]
actCntx = ActionContext(self.focusUnit, Actions.QUERY_TYPE_HIER, self.activeItem.getItemId(), self.activeAddress)
actData = ActionTypeHierarchyData()
# 获取所有派生自该类的清单,然后逐个重命名
self.nTotal = 0
self.nSucc = 0
self.nFail = 0
if(self.focusUnit.prepareExecution(actCntx, actData)):
try:
bRlt = self.focusUnit.executeAction(actCntx, actData)
if(not bRlt):
print('executeAction fail!')
else:
cNode = actData.getBaseNode().getChildren()[0]
if(cNode):
print(u'派生类如下:')
childs = cNode.getChildren()
#print(childs)
for n in childs:
#print(n)
self.nTotal += 1
if(self.RenameClass(self.focusUnit2, n)):
self.nSucc += 1
else:
self.nFail += 1
if(self.debug):
break
except Exception,e:
print Exception,":",e
print('total:%d succ:%d fail:%d' %(self.nTotal, self.nSucc, self.nFail))
print('Done.')
## end of run
def RenameClass(self, unit, codeNode):
codeItem = codeNode.getObject()
codeClass = codeItem.getImplementingClass()
if(not codeClass):
print(u'正在跳过 %s' % (codeItem.getAddress()))
return False
#print(u'正在处理 %s' % codeItem.getAddress())
decomp = DecompilerHelper.getDecompiler(unit)
if not decomp:
print('There is no decompiler available for code unit %s' % unit)
return False
tmpUnit = decomp.decompile(codeItem.getAddress())
#print(tmpUnit)
doc = self.getTextDocument(tmpUnit)
#text = self.formatTextDocument(doc)
#print(text)
# 从反编译得到的 Java 源文件中逐行查找 log
pattern = re.compile('\.NetScene([^";]+)', re.I)
lines = doc.getDocumentPart(0, 10000000).getLines()
m = []
for l in lines:
#print('%s' % l.getText().toString())
line = l.getText().toString()
matches = pattern.findall(line)
for match in matches:
#print('%s\t\t\t%s' % (match, line))
#print(line)
if(match == 'Base'):
continue
m.append(match)
# 统计词频
if(len(m) < 1):
print(u'正在跳过 %s' % (codeItem.getAddress()))
return False
a=collections.Counter(m)
b=a.most_common(10)
l = list(b);
#print(l)
msg = ''
i = 0
for s in l:
msg = msg + 'index:' + str(i) + '\ttimes:' + str(s[1])+ '\t' + s[0] + '\n'
i += 1
sel = 0;
#print(msg)
## value = self.ctx.displayQuestionBox('sel', msg + '\n\n', str(sel))
## if value != None:
## sel = int(value)
baseStr = l[sel][0]
newClassName = "NetScene" + baseStr
print(u'正在处理 %s\t=:>%s' % (codeItem.getAddress(), newClassName))
# 重命名类
actCntx = ActionContext(unit, Actions.RENAME, codeClass.getItemId(), codeClass.getAddress())
actData = ActionRenameData()
actData.setNewName(newClassName)
if(unit.prepareExecution(actCntx, actData)):
# 执行重命名动作
try:
bRlt = unit.executeAction(actCntx, actData)
if(not bRlt):
print(u'executeAction fail!')
return False
else:
return True
except Exception,e:
print Exception,":",e
## end of RenameClass
# 获取指定基类的所有派生类
def GetTypeHierarchy(self, unit, c):
#print(u'class name:%s\t\t\told name:%s\n' % (cname, oname))
print(c)
cType = c.getClassType()
#print('getName:%s\tgetSignature:%s\tgetAddress:%s\tgetItemId:%d\tgetIndex:%d' % (cType.getName(True), cType.getSignature(True), cType.getAddress(), cType.getItemId(), cType.getIndex()))
#print(cType)
# 获取基类 c 的型层次树
actCntx = ActionContext(unit, Actions.QUERY_TYPE_HIER, c.getItemId(), c.getAddress())
actData = ActionTypeHierarchyData()
if(unit.prepareExecution(actCntx, actData)):
bNode = actData.getBaseNode()
if(bNode):
cNode = bNode.findNodeByObject(cType)
if(cNode):
print(u'派生类如下:')
childs = cNode.getChildren()
#print(childs)
for n in childs:
print(n)
#self.processSubClass(unit, n)
if(self.debug):
break
## end of GetTypeHierarchy
def getHierarchyFragment(self, ctx):
views = ctx.getViews()
for view in views:
viewLabel = view.getLabel()
#print('- view:%s' % view.getLabel())
fragments = view.getFragments()
for fragment in fragments:
fragmentLabel = view.getFragmentLabel(fragment)
#print(fragmentLabel)
if(fragmentLabel == 'Hierarchy' ):
return fragment;
return None
## end of formatTextDocument
def getTextDocument(self, srcUnit):
formatter = srcUnit.getFormatter()
if formatter and formatter.getDocumentPresentations():
doc = formatter.getDocumentPresentations()[0].getDocument()
if isinstance(doc, ITextDocument):
return doc
return None
## end of getTextDocument
def formatTextDocument(self, doc):
s = ''
# retrieve the entire document -it's a source file,
# no need to buffer individual parts. 10 MLoC is enough
alldoc = doc.getDocumentPart(0, 10000000)
for line in alldoc.getLines():
s += line.getText().toString() + '\n'
return s
## end of formatTextDocument
## targetUnit.notifyListeners(JebEvent(J.UnitChange))