#!/usr/bin/python
import os
import os.path
import xml.dom.minidom

var1 = 'smali'
print var1+'/android'

manifest = 'AndroidManifest.xml'
ShellHelper = '../stubshell/smali/com/ceprei/stubshell/ShellHelper.smali'

tranfile = 'tranfile'
#packagename = ''

smalicode1 = '.method static constructor <clinit>()V\n'
smalicode2 = '    .locals 2\n'
#smalicode3 = '    const-string v0, ' + packagename + '\n\n'
smalicode3 = '    const-string v0, '
smalicode4 = '    const/16 v1, '
smalicode5 = '    invoke-static {v0, v1}, Lcom/ceprei/stubshell/ShellHelper;->StartShell(Ljava/lang/String;I)Z\n\n'
smalicode6 = '    return-void\n'
smalicode7 = '.end method\n\n'

class PyAddSmaliCode():
    def __init__(self):
        """constructor"""

    def EditShellHelper(self, packagename):
        fp = file(ShellHelper)
        lines = []
        for line in fp:
            lines.append(line)
        fp.close()

        for num in range(0, len(lines)):
            if (lines[num].find('com.boco.nfc.activity') != -1):
                lines[num] = '    const-string v0, ' + packagename + '\n'
                #print lines[num]
                break

        s = ''.join(lines)
        fp = file(ShellHelper, 'w')
        fp.write(s)
        fp.close()

    def findPackageName(self):
        dom = xml.dom.minidom.parse(manifest)
        root = dom.documentElement
        #print root.nodeName
        package = root.getAttribute("package")
        packagename = '"' + package + '"'
        print packagename
        self.EditShellHelper(packagename)
        return packagename

    def EditSmaliCode(self, ospath, start, length, packagename):
        tranfilefp = file(tranfile)
        tranfilelines = []
        for tranfileline in tranfilefp:
            tranfilelines.append(tranfileline)
        tranfilefp.close()

        fp = file(ospath)
        lines = []
        for line in fp:
            lines.append(line)
        fp.close()

        #tranfilelines.append('%d' % start + '!' + '%d' % length + '!' + lines[0][14:])
        #tranfilefp.write('%d' % start + '!' + '%d' % length + '!' + lines[0][14:])

        tmplines = ''.join(lines)
        if tmplines.find('# direct methods') == -1:
            print "did not find method, exit!" + ospath
            return -1
        index = lines.index('# direct methods\n')
        if lines[index+1].find('.method static constructor <clinit>()V') != -1:
            index = index+1
            if (lines[index+1].find('\n') == 0):
                index = index + 1
            #print lines[index+1]
            #print lines[index+1].find('.locals')
            if (lines[index+1].find('.locals ') != -1):
                index = index + 1;
                #print int(lines[index][12:])
                if int(lines[index][12:]) < 2:
                    lines[index] = smalicode2
                if (lines[index+1].find('\n') == 0):
                    index = index + 1
                for num in range(0, length):
                    index = index + 1
                    lines.insert(index, smalicode3 + packagename + '\n\n')
                    index = index + 1
                    lines.insert(index, smalicode4 + hex(start + num) + '\n\n') #no padding 0
                    index = index + 1
                    lines.insert(index, smalicode5)
            else:
                print "EditSmaliCode false in " + ospath
                return -1
        else:
            index = index + 1
            lines.insert(index, smalicode1)
            index = index + 1
            lines.insert(index, smalicode2 + '\n')
            for num in range(0, length):
                index = index + 1
                lines.insert(index, smalicode3 + packagename + '\n\n')
                index = index + 1
                lines.insert(index, smalicode4 + hex(start + num) + '\n\n') #no padding 0
                index = index + 1
                lines.insert(index, smalicode5)
            index = index + 1
            lines.insert(index, smalicode6)
            index = index + 1
            lines.insert(index, smalicode7)
        
        foundmethod = 0
        for num in range(index, len(lines)):
            if (lines[num].find('.method') != -1):
                if (lines[num].find('<init>') != -1):
                    tranfilelines.append('%d' % (start + foundmethod) + '!' + lines[0][lines[0].rindex(" ")+1:])
                    tranfilelines.append("<init>\n")
                    #tranfilefp.write("init\n")
#                else:
#                    if (lines[num].find('(') != -1):
#                        lindex = lines[num][:lines[num].find('(')].rindex(' ') + 1
#                        rindex = lines[num].find('(')
#                        tranfilelines.append('%d' % (start + foundmethod) + '!' + lines[0][lines[0].rindex(" ")+1:])
#                        tranfilelines.append(lines[num][lindex:rindex] + '\n')
#                        #tranfilefp.write(lines[num][lindex:rindex] + '\n')
#                    else:
#                        print "EditSmaliCode-findmethod false in " + ospath
                    foundmethod = foundmethod + 1
                    if foundmethod == length:
                        break;
        if foundmethod != length:
            print "did not find method, exit!" + ospath
            return -1

        s = ''.join(lines)
        fp = file(ospath, 'w')
        fp.write(s)
        fp.close()

        tranfiles = ''.join(tranfilelines)
        tranfilefp = file(tranfile, 'w')
        tranfilefp.write(tranfiles)
        tranfilefp.close()
        return 0

    def findpath(self, packagename):
        size = 0L
        count = 0
        for root, dirs, files in os.walk(var1):
            for name in files:
                if (root.find(var1+'/android') == -1) and (root.find('ceprei') == -1) and (root.find('spongycastle') == -1):
                    count = count + 1
                    size = size + os.path.getsize(os.path.join(root, name))
                    #print root + '/' + name
        perfile = size/count
        #print count
        #print size
        count = 0
        for root, dirs, files in os.walk(var1):
            for name in files:
                if (root.find(var1+'/android') == -1) and (root.find('ceprei') == -1) and (root.find('spongycastle') == -1):
                    i = os.path.getsize(os.path.join(root, name))/perfile/2 - 1
                    #print i
                    if (i > 0):
                        if (i > 2):
                            i = 2
                        print root + '/' + name
                        #string = root + '/' + name
                        i = 1
                        result = self.EditSmaliCode(root + '/' + name, count, i, packagename)
                        print result
                        if (result == 0):
                            count = count + i
        print count
        #print string
        #self.EditSmaliCode('/home/mak/tmp/apktool/smali/com/tencent/mm/sdk/platformtools/LBSManager.smali', 300, 5)

if __name__ == "__main__":
    t = PyAddSmaliCode()
    packagename = t.findPackageName()
    t.findpath(packagename)
