JEB2 script 中調用 api 重命名所有派生類 V2.0

# -*- 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))


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章