mirror of
https://github.com/androguard/androguard.git
synced 2024-11-23 13:09:55 +00:00
auto format code
This commit is contained in:
parent
7f44b13e57
commit
1ce2a7f1ae
@ -36,14 +36,12 @@ options = [option_0, option_1]
|
||||
|
||||
|
||||
class AndroLog(object):
|
||||
|
||||
def __init__(self, id_file, filename):
|
||||
self.id_file = id_file
|
||||
self.filename = filename
|
||||
|
||||
|
||||
class AndroTest(auto.DirectoryAndroAnalysis):
|
||||
|
||||
def analysis_app(self, log, apkobj, dexobj, adexobj):
|
||||
print(log.id_file, log.filename, apkobj, dexobj, adexobj)
|
||||
|
||||
|
@ -105,12 +105,12 @@ def export_apps_to_format(filename,
|
||||
if decompiler_type == "dex2jad":
|
||||
vm.set_decompiler(decompiler.DecompilerDex2Jad(
|
||||
vm, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"
|
||||
], androconf.CONF["PATH_JAD"],
|
||||
], androconf.CONF["PATH_JAD"],
|
||||
androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"]))
|
||||
elif decompiler_type == "dex2winejad":
|
||||
vm.set_decompiler(decompiler.DecompilerDex2WineJad(
|
||||
vm, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"
|
||||
], androconf.CONF["PATH_JAD"],
|
||||
], androconf.CONF["PATH_JAD"],
|
||||
androconf.CONF["BIN_WINEJAD"], androconf.CONF["TMP_DIRECTORY"]))
|
||||
elif decompiler_type == "ded":
|
||||
vm.set_decompiler(decompiler.DecompilerDed(
|
||||
@ -123,7 +123,7 @@ def export_apps_to_format(filename,
|
||||
], androconf.CONF["PATH_FERNFLOWER"], androconf.CONF[
|
||||
"BIN_FERNFLOWER"
|
||||
], androconf.CONF["OPTIONS_FERNFLOWER"
|
||||
], androconf.CONF["TMP_DIRECTORY"]))
|
||||
], androconf.CONF["TMP_DIRECTORY"]))
|
||||
|
||||
print("End")
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
from __future__ import print_function
|
||||
|
||||
from future import standard_library
|
||||
|
||||
standard_library.install_aliases()
|
||||
from builtins import str
|
||||
from builtins import range
|
||||
@ -8,12 +9,12 @@ from builtins import object
|
||||
import re, collections
|
||||
import threading, queue, time
|
||||
|
||||
|
||||
from androguard.core.androconf import error, warning, debug, is_ascii_problem,\
|
||||
from androguard.core.androconf import error, warning, debug, is_ascii_problem, \
|
||||
load_api_specific_resource_module
|
||||
from androguard.core.bytecodes import dvm
|
||||
from androguard.core.bytecodes.api_permissions import DVM_PERMISSIONS_BY_PERMISSION, DVM_PERMISSIONS_BY_ELEMENT
|
||||
|
||||
|
||||
class DVMBasicBlock(object):
|
||||
"""
|
||||
A simple basic block of a dalvik method
|
||||
@ -108,7 +109,7 @@ class DVMBasicBlock(object):
|
||||
return self.last_length
|
||||
|
||||
def set_childs(self, values):
|
||||
#print self, self.start, self.end, values
|
||||
# print self, self.start, self.end, values
|
||||
if values == []:
|
||||
next_block = self.context.get_basic_block(self.end + 1)
|
||||
if next_block != None:
|
||||
@ -162,7 +163,6 @@ class DVMBasicBlock(object):
|
||||
|
||||
|
||||
class Enum(object):
|
||||
|
||||
def __init__(self, names):
|
||||
self.names = names
|
||||
for value, name in enumerate(self.names):
|
||||
@ -309,7 +309,6 @@ class BasicBlocks(object):
|
||||
|
||||
|
||||
class ExceptionAnalysis(object):
|
||||
|
||||
def __init__(self, exception, bb):
|
||||
self.start = exception[0]
|
||||
self.end = exception[1]
|
||||
@ -340,7 +339,6 @@ class ExceptionAnalysis(object):
|
||||
|
||||
|
||||
class Exceptions(object):
|
||||
|
||||
def __init__(self, _vm):
|
||||
self.__vm = _vm
|
||||
self.exceptions = []
|
||||
@ -514,14 +512,13 @@ class MethodAnalysis(object):
|
||||
|
||||
|
||||
class StringAnalysis(object):
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
self.orig_value = value
|
||||
self.xreffrom = set()
|
||||
|
||||
def AddXrefFrom(self, classobj, methodobj):
|
||||
#debug("Added strings xreffrom for %s to %s" % (self.value, methodobj))
|
||||
# debug("Added strings xreffrom for %s to %s" % (self.value, methodobj))
|
||||
self.xreffrom.add((classobj, methodobj))
|
||||
|
||||
def get_xref_from(self):
|
||||
@ -540,23 +537,22 @@ class StringAnalysis(object):
|
||||
data = "XREFto for string %s in\n" % repr(self.get_value())
|
||||
for ref_class, ref_method in self.xreffrom:
|
||||
data += "%s:%s\n" % (ref_class.get_vm_class().get_name(), ref_method
|
||||
)
|
||||
)
|
||||
return data
|
||||
|
||||
|
||||
class MethodClassAnalysis(object):
|
||||
|
||||
def __init__(self, method):
|
||||
self.method = method
|
||||
self.xrefto = set()
|
||||
self.xreffrom = set()
|
||||
|
||||
def AddXrefTo(self, classobj, methodobj, offset):
|
||||
#debug("Added method xrefto for %s [%s] to %s" % (self.method, classobj, methodobj))
|
||||
# debug("Added method xrefto for %s [%s] to %s" % (self.method, classobj, methodobj))
|
||||
self.xrefto.add((classobj, methodobj, offset))
|
||||
|
||||
def AddXrefFrom(self, classobj, methodobj, offset):
|
||||
#debug("Added method xreffrom for %s [%s] to %s" % (self.method, classobj, methodobj))
|
||||
# debug("Added method xreffrom for %s [%s] to %s" % (self.method, classobj, methodobj))
|
||||
self.xreffrom.add((classobj, methodobj, offset))
|
||||
|
||||
def get_xref_from(self):
|
||||
@ -570,30 +566,29 @@ class MethodClassAnalysis(object):
|
||||
for ref_class, ref_method, offset in self.xrefto:
|
||||
data += "in\n"
|
||||
data += "%s:%s @0x%x\n" % (ref_class.get_vm_class().get_name(), ref_method, offset
|
||||
)
|
||||
)
|
||||
|
||||
data += "XREFFrom for %s\n" % self.method
|
||||
for ref_class, ref_method, offset in self.xreffrom:
|
||||
data += "in\n"
|
||||
data += "%s:%s @0x%x\n" % (ref_class.get_vm_class().get_name(), ref_method, offset
|
||||
)
|
||||
)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class FieldClassAnalysis(object):
|
||||
|
||||
def __init__(self, field):
|
||||
self.field = field
|
||||
self.xrefread = set()
|
||||
self.xrefwrite = set()
|
||||
|
||||
def AddXrefRead(self, classobj, methodobj):
|
||||
#debug("Added method xrefto for %s [%s] to %s" % (self.method, classobj, methodobj))
|
||||
# debug("Added method xrefto for %s [%s] to %s" % (self.method, classobj, methodobj))
|
||||
self.xrefread.add((classobj, methodobj))
|
||||
|
||||
def AddXrefWrite(self, classobj, methodobj):
|
||||
#debug("Added method xreffrom for %s [%s] to %s" % (self.method, classobj, methodobj))
|
||||
# debug("Added method xreffrom for %s [%s] to %s" % (self.method, classobj, methodobj))
|
||||
self.xrefwrite.add((classobj, methodobj))
|
||||
|
||||
def get_xref_read(self):
|
||||
@ -607,19 +602,21 @@ class FieldClassAnalysis(object):
|
||||
for ref_class, ref_method in self.xrefread:
|
||||
data += "in\n"
|
||||
data += "%s:%s\n" % (ref_class.get_vm_class().get_name(), ref_method
|
||||
)
|
||||
)
|
||||
|
||||
data += "XREFWrite for %s\n" % self.field
|
||||
for ref_class, ref_method in self.xrefwrite:
|
||||
data += "in\n"
|
||||
data += "%s:%s\n" % (ref_class.get_vm_class().get_name(), ref_method
|
||||
)
|
||||
)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
REF_NEW_INSTANCE = 0
|
||||
REF_CLASS_USAGE = 1
|
||||
|
||||
|
||||
class ExternalClass(object):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
@ -632,6 +629,7 @@ class ExternalClass(object):
|
||||
|
||||
return self.methods[key]
|
||||
|
||||
|
||||
class ExternalMethod(object):
|
||||
def __init__(self, class_name, name, descriptor):
|
||||
self.class_name = class_name
|
||||
@ -650,8 +648,8 @@ class ExternalMethod(object):
|
||||
def __str__(self):
|
||||
return "%s->%s%s" % (self.class_name, self.name, ''.join(self.descriptor))
|
||||
|
||||
class ClassAnalysis(object):
|
||||
|
||||
class ClassAnalysis(object):
|
||||
def __init__(self, classobj, internal=False):
|
||||
self.orig_class = classobj
|
||||
self._inherits_methods = {}
|
||||
@ -745,7 +743,6 @@ class ClassAnalysis(object):
|
||||
|
||||
|
||||
class Analysis(object):
|
||||
|
||||
def __init__(self, vm):
|
||||
self.vms = [vm]
|
||||
self.classes = {}
|
||||
@ -827,7 +824,7 @@ class Analysis(object):
|
||||
current_method, off)
|
||||
|
||||
elif ((op_value >= 0x6e and op_value <= 0x72) or
|
||||
(op_value >= 0x74 and op_value <= 0x78)):
|
||||
(op_value >= 0x74 and op_value <= 0x78)):
|
||||
idx_meth = instruction.get_ref_kind()
|
||||
method_info = last_vm.get_cm_method(idx_meth)
|
||||
if method_info:
|
||||
@ -840,9 +837,10 @@ class Analysis(object):
|
||||
# Seems to be an external classes
|
||||
if not method_item:
|
||||
if method_info[0] not in self.classes:
|
||||
self.classes[method_info[0]] = ClassAnalysis(ExternalClass(method_info[0]), False)
|
||||
method_item = self.classes[method_info[0]].GetFakeMethod(method_info[1], method_info[2])
|
||||
|
||||
self.classes[method_info[0]] = ClassAnalysis(ExternalClass(method_info[0]),
|
||||
False)
|
||||
method_item = self.classes[method_info[0]].GetFakeMethod(method_info[1],
|
||||
method_info[2])
|
||||
|
||||
if method_item:
|
||||
self.classes[current_class.get_name(
|
||||
@ -886,7 +884,7 @@ class Analysis(object):
|
||||
if field_item:
|
||||
# read access to a field
|
||||
if (op_value >= 0x52 and op_value <= 0x58) or (
|
||||
op_value >= 0x60 and op_value <= 0x66):
|
||||
op_value >= 0x60 and op_value <= 0x66):
|
||||
self.classes[current_class.get_name(
|
||||
)].AddFXrefRead(
|
||||
current_method,
|
||||
@ -959,6 +957,7 @@ class Analysis(object):
|
||||
self.classes[current_class.get_name()] = ClassAnalysis(
|
||||
current_class, True)
|
||||
|
||||
|
||||
def is_ascii_obfuscation(vm):
|
||||
for classe in vm.get_classes():
|
||||
if is_ascii_problem(classe.get_name()):
|
||||
|
@ -1,4 +1,5 @@
|
||||
from future import standard_library
|
||||
|
||||
standard_library.install_aliases()
|
||||
from builtins import range
|
||||
from builtins import object
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@ from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from future import standard_library
|
||||
|
||||
standard_library.install_aliases()
|
||||
from builtins import chr
|
||||
from builtins import str
|
||||
@ -42,6 +43,7 @@ ZIPMODULE = 1
|
||||
if sys.hexversion < 0x2070000:
|
||||
try:
|
||||
import chilkat
|
||||
|
||||
ZIPMODULE = 0
|
||||
# UNLOCK : change it with your valid key !
|
||||
try:
|
||||
@ -57,7 +59,6 @@ else:
|
||||
|
||||
################################################### CHILKAT ZIP FORMAT #####################################################
|
||||
class ChilkatZip(object):
|
||||
|
||||
def __init__(self, raw):
|
||||
self.files = []
|
||||
self.zip = chilkat.CkZip()
|
||||
@ -251,7 +252,6 @@ class APK(object):
|
||||
self.permission_module = androconf.load_api_specific_resource_module(
|
||||
"aosp_permissions", self.get_target_sdk_version())
|
||||
|
||||
|
||||
def __getstate__(self):
|
||||
# Upon pickling, we need to remove the ZipFile
|
||||
x = self.__dict__
|
||||
@ -587,7 +587,7 @@ class APK(object):
|
||||
:rtype: string
|
||||
"""
|
||||
for i in self.xml:
|
||||
if self.xml[i] is None :
|
||||
if self.xml[i] is None:
|
||||
continue
|
||||
tag = self.xml[i].getElementsByTagName(tag_name)
|
||||
if tag is None:
|
||||
@ -686,7 +686,7 @@ class APK(object):
|
||||
for item in self.xml[i].getElementsByTagName(category):
|
||||
if self.format_value(
|
||||
item.getAttributeNS(NS_ANDROID_URI, "name")
|
||||
) == name:
|
||||
) == name:
|
||||
for sitem in item.getElementsByTagName("intent-filter"):
|
||||
for ssitem in sitem.getElementsByTagName("action"):
|
||||
if ssitem.getAttributeNS(NS_ANDROID_URI, "name") \
|
||||
@ -853,9 +853,9 @@ class APK(object):
|
||||
if not isinstance(l, int):
|
||||
l = ord(l)
|
||||
cert = cert[2 + (l & 0x7F) if l & 0x80 > 1 else 2:]
|
||||
|
||||
|
||||
certificate = x509.load_der_x509_certificate(cert, default_backend())
|
||||
|
||||
|
||||
return certificate
|
||||
|
||||
def new_zip(self, filename, deleted_files=None, new_files={}):
|
||||
@ -1029,21 +1029,23 @@ def get_Name(name, short=False):
|
||||
|
||||
:rtype: str
|
||||
"""
|
||||
|
||||
|
||||
# For the shortform, we have a lookup table
|
||||
# See RFC4514 for more details
|
||||
sf = {
|
||||
"countryName": "C",
|
||||
"stateOrProvinceName": "ST",
|
||||
"localityName": "L",
|
||||
"organizationalUnitName": "OU",
|
||||
"organizationName": "O",
|
||||
"commonName": "CN",
|
||||
"emailAddress": "E",
|
||||
}
|
||||
return ", ".join(["{}={}".format(attr.oid._name if not short or attr.oid._name not in sf else sf[attr.oid._name], attr.value) for attr in name])
|
||||
|
||||
|
||||
"countryName": "C",
|
||||
"stateOrProvinceName": "ST",
|
||||
"localityName": "L",
|
||||
"organizationalUnitName": "OU",
|
||||
"organizationName": "O",
|
||||
"commonName": "CN",
|
||||
"emailAddress": "E",
|
||||
}
|
||||
return ", ".join(
|
||||
["{}={}".format(attr.oid._name if not short or attr.oid._name not in sf else sf[attr.oid._name], attr.value) for
|
||||
attr in name])
|
||||
|
||||
|
||||
def show_Certificate(cert, short=False):
|
||||
"""
|
||||
Print Fingerprints, Issuer and Subject of an X509 Certificate.
|
||||
@ -1054,12 +1056,13 @@ def show_Certificate(cert, short=False):
|
||||
:type cert: :class:`cryptography.x509.Certificate`
|
||||
:type short: Boolean
|
||||
"""
|
||||
|
||||
|
||||
for h in [hashes.MD5, hashes.SHA1, hashes.SHA256, hashes.SHA512]:
|
||||
print("{}: {}".format(h.name, binascii.hexlify(cert.fingerprint(h())).decode("ascii")))
|
||||
print("Issuer: {}".format(get_Name(cert.issuer, short=short)))
|
||||
print("Subject: {}".format(get_Name(cert.subject, short=short)))
|
||||
|
||||
|
||||
################################## AXML FORMAT ########################################
|
||||
# Translated from
|
||||
# http://code.google.com/p/android4me/source/browse/src/android/content/res/AXmlResourceParser.java
|
||||
@ -1068,7 +1071,6 @@ UTF8_FLAG = 0x00000100
|
||||
|
||||
|
||||
class StringBlock(object):
|
||||
|
||||
def __init__(self, buff, header):
|
||||
self._cache = {}
|
||||
self.header = header
|
||||
@ -1213,7 +1215,6 @@ TEXT = 4
|
||||
|
||||
|
||||
class AXMLParser(object):
|
||||
|
||||
def __init__(self, raw_buff):
|
||||
self.reset()
|
||||
|
||||
@ -1379,7 +1380,7 @@ class AXMLParser(object):
|
||||
|
||||
def getName(self):
|
||||
if self.m_name == -1 or (self.m_event != START_TAG and
|
||||
self.m_event != END_TAG):
|
||||
self.m_event != END_TAG):
|
||||
return u''
|
||||
|
||||
return self.sb.getString(self.m_name)
|
||||
@ -1567,7 +1568,6 @@ def format_value(_type, _data, lookup_string=lambda ix: "<string>"):
|
||||
|
||||
|
||||
class AXMLPrinter(object):
|
||||
|
||||
def __init__(self, raw_buff):
|
||||
self.axml = AXMLParser(raw_buff)
|
||||
self.xmlns = False
|
||||
@ -1675,7 +1675,6 @@ ACONFIGURATION_UI_MODE = 0x1000
|
||||
|
||||
|
||||
class ARSCParser(object):
|
||||
|
||||
def __init__(self, raw_buff):
|
||||
self.analyzed = False
|
||||
self._resolved_strings = None
|
||||
@ -1755,7 +1754,7 @@ class ARSCParser(object):
|
||||
a_res_type = ARSCResType(self.buff, pc)
|
||||
self.packages[package_name].append(a_res_type)
|
||||
self.resource_configs[package_name][a_res_type].add(
|
||||
a_res_type.config)
|
||||
a_res_type.config)
|
||||
|
||||
entries = []
|
||||
for i in range(0, a_res_type.entryCount):
|
||||
@ -1898,7 +1897,7 @@ class ARSCParser(object):
|
||||
ate.get_value(), "%s%s" % (
|
||||
complexToFloat(ate.key.get_data()),
|
||||
DIMENSION_UNITS[ate.key.get_data() & COMPLEX_UNIT_MASK])
|
||||
]
|
||||
]
|
||||
except IndexError:
|
||||
androconf.debug("Out of range dimension unit index for %s: %s" % (
|
||||
complexToFloat(ate.key.get_data()),
|
||||
@ -2202,14 +2201,13 @@ class ARSCParser(object):
|
||||
|
||||
for res_type, configs in list(self.resource_configs[package_name].items()):
|
||||
if res_type.get_package_name() == package_name and (
|
||||
type_name is None or res_type.get_type() == type_name):
|
||||
type_name is None or res_type.get_type() == type_name):
|
||||
result[res_type.get_type()].extend(configs)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class PackageContext(object):
|
||||
|
||||
def __init__(self, current_package, stringpool_main, mTableStrings,
|
||||
mKeyStrings):
|
||||
self.stringpool_main = stringpool_main
|
||||
@ -2238,7 +2236,6 @@ class ARSCHeader(object):
|
||||
|
||||
|
||||
class ARSCResTablePackage(object):
|
||||
|
||||
def __init__(self, buff, header):
|
||||
self.header = header
|
||||
self.start = buff.get_idx()
|
||||
@ -2257,7 +2254,6 @@ class ARSCResTablePackage(object):
|
||||
|
||||
|
||||
class ARSCResTypeSpec(object):
|
||||
|
||||
def __init__(self, buff, parent=None):
|
||||
self.start = buff.get_idx()
|
||||
self.parent = parent
|
||||
@ -2272,7 +2268,6 @@ class ARSCResTypeSpec(object):
|
||||
|
||||
|
||||
class ARSCResType(object):
|
||||
|
||||
def __init__(self, buff, parent=None):
|
||||
self.start = buff.get_idx()
|
||||
self.parent = parent
|
||||
@ -2412,7 +2407,6 @@ class ARSCResTableConfig(object):
|
||||
|
||||
|
||||
class ARSCResTableEntry(object):
|
||||
|
||||
def __init__(self, buff, mResId, parent=None):
|
||||
self.start = buff.get_idx()
|
||||
self.mResId = mResId
|
||||
@ -2452,7 +2446,6 @@ class ARSCResTableEntry(object):
|
||||
|
||||
|
||||
class ARSCComplex(object):
|
||||
|
||||
def __init__(self, buff, parent=None):
|
||||
self.start = buff.get_idx()
|
||||
self.parent = parent
|
||||
@ -2470,7 +2463,6 @@ class ARSCComplex(object):
|
||||
|
||||
|
||||
class ARSCResStringPoolRef(object):
|
||||
|
||||
def __init__(self, buff, parent=None):
|
||||
self.start = buff.get_idx()
|
||||
self.parent = parent
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,322 +2,493 @@
|
||||
DVM_PERMISSIONS = {
|
||||
"MANIFEST_PERMISSION": {
|
||||
|
||||
# MESSAGES
|
||||
"SEND_SMS": ["dangerous", "send SMS messages", "Allows application to send SMS messages. Malicious applications may cost you money by sending messages without your confirmation."],
|
||||
"SEND_SMS_NO_CONFIRMATION": ["signatureOrSystem", "send SMS messages", "send SMS messages via the Messaging app with no user input or confirmation"],
|
||||
"RECEIVE_SMS": ["dangerous", "receive SMS", "Allows application to receive and process SMS messages. Malicious applications may monitor your messages or delete them without showing them to you."],
|
||||
"RECEIVE_MMS": ["dangerous", "receive MMS", "Allows application to receive and process MMS messages. Malicious applications may monitor your messages or delete them without showing them to you."],
|
||||
"RECEIVE_EMERGENCY_BROADCAST": [ "signatureOrSystem", "", "Allows an application to receive emergency cell broadcast messages, to record or display them to the user. Reserved for system apps." ],
|
||||
"READ_CELL_BROADCASTS" : [ "dangerous", "received cell broadcast messages", "Allows an application to read previously received cell broadcast "\
|
||||
"messages and to register a content observer to get notifications when "\
|
||||
"a cell broadcast has been received and added to the database. For "\
|
||||
"emergency alerts, the database is updated immediately after the "\
|
||||
"alert dialog and notification sound/vibration/speech are presented."\
|
||||
"The \"read\" column is then updated after the user dismisses the alert."\
|
||||
"This enables supplementary emergency assistance apps to start loading "\
|
||||
"additional emergency information (if Internet access is available) "\
|
||||
"when the alert is first received, and to delay presenting the info "\
|
||||
"to the user until after the initial alert dialog is dismissed." ],
|
||||
"READ_SMS" : [ "dangerous" , "read SMS or MMS" , "Allows application to read SMS messages stored on your phone or SIM card. Malicious applications may read your confidential messages." ],
|
||||
"WRITE_SMS" : [ "dangerous" , "edit SMS or MMS" , "Allows application to write to SMS messages stored on your phone or SIM card. Malicious applications may delete your messages." ],
|
||||
"RECEIVE_WAP_PUSH" : [ "dangerous" , "receive WAP" , "Allows application to receive and process WAP messages. Malicious applications may monitor your messages or delete them without showing them to you." ],
|
||||
"BROADCAST_SMS" : [ "signature" , "send SMS-received broadcast" , "Allows an application to broadcast a notification that an SMS message has been received. Malicious applications may use this to forge incoming SMS messages." ],
|
||||
"BROADCAST_WAP_PUSH" : [ "signature" , "send WAP-PUSH-received broadcast" , "Allows an application to broadcast a notification that a WAP-PUSH message has been received. Malicious applications may use this to forge MMS message receipt or to replace the content of any web page silently with malicious variants." ],
|
||||
# MESSAGES
|
||||
"SEND_SMS": ["dangerous", "send SMS messages",
|
||||
"Allows application to send SMS messages. Malicious applications may cost you money by sending messages without your confirmation."],
|
||||
"SEND_SMS_NO_CONFIRMATION": ["signatureOrSystem", "send SMS messages",
|
||||
"send SMS messages via the Messaging app with no user input or confirmation"],
|
||||
"RECEIVE_SMS": ["dangerous", "receive SMS",
|
||||
"Allows application to receive and process SMS messages. Malicious applications may monitor your messages or delete them without showing them to you."],
|
||||
"RECEIVE_MMS": ["dangerous", "receive MMS",
|
||||
"Allows application to receive and process MMS messages. Malicious applications may monitor your messages or delete them without showing them to you."],
|
||||
"RECEIVE_EMERGENCY_BROADCAST": ["signatureOrSystem", "",
|
||||
"Allows an application to receive emergency cell broadcast messages, to record or display them to the user. Reserved for system apps."],
|
||||
"READ_CELL_BROADCASTS": ["dangerous", "received cell broadcast messages",
|
||||
"Allows an application to read previously received cell broadcast " \
|
||||
"messages and to register a content observer to get notifications when " \
|
||||
"a cell broadcast has been received and added to the database. For " \
|
||||
"emergency alerts, the database is updated immediately after the " \
|
||||
"alert dialog and notification sound/vibration/speech are presented." \
|
||||
"The \"read\" column is then updated after the user dismisses the alert." \
|
||||
"This enables supplementary emergency assistance apps to start loading " \
|
||||
"additional emergency information (if Internet access is available) " \
|
||||
"when the alert is first received, and to delay presenting the info " \
|
||||
"to the user until after the initial alert dialog is dismissed."],
|
||||
"READ_SMS": ["dangerous", "read SMS or MMS",
|
||||
"Allows application to read SMS messages stored on your phone or SIM card. Malicious applications may read your confidential messages."],
|
||||
"WRITE_SMS": ["dangerous", "edit SMS or MMS",
|
||||
"Allows application to write to SMS messages stored on your phone or SIM card. Malicious applications may delete your messages."],
|
||||
"RECEIVE_WAP_PUSH": ["dangerous", "receive WAP",
|
||||
"Allows application to receive and process WAP messages. Malicious applications may monitor your messages or delete them without showing them to you."],
|
||||
"BROADCAST_SMS": ["signature", "send SMS-received broadcast",
|
||||
"Allows an application to broadcast a notification that an SMS message has been received. Malicious applications may use this to forge incoming SMS messages."],
|
||||
"BROADCAST_WAP_PUSH": ["signature", "send WAP-PUSH-received broadcast",
|
||||
"Allows an application to broadcast a notification that a WAP-PUSH message has been received. Malicious applications may use this to forge MMS message receipt or to replace the content of any web page silently with malicious variants."],
|
||||
|
||||
# SOCIAL_INFO
|
||||
"READ_CONTACTS" : [ "dangerous" , "read contact data" , "Allows an application to read all of the contact (address) data stored on your phone. Malicious applications can use this to send your data to other people." ],
|
||||
"WRITE_CONTACTS" : [ "dangerous" , "write contact data" , "Allows an application to modify the contact (address) data stored on your phone. Malicious applications can use this to erase or modify your contact data." ],
|
||||
"BIND_DIRECTORY_SEARCH" : [ "signatureOrSystem", "execute contacts directory search", "Allows an application to execute contacts directory search. This should only be used by ContactsProvider." ],
|
||||
"READ_CALL_LOG": [ "dangerous", "read the user's call log.", "Allows an application to read the user's call log." ],
|
||||
"WRITE_CALL_LOG": [ "dangerous", "write (but not read) the user's contacts data.", "Allows an application to write (but not read) the user's contacts data." ],
|
||||
"READ_SOCIAL_STREAM" : [ "dangerous", "read from the user's social stream", "Allows an application to read from the user's social stream." ],
|
||||
"WRITE_SOCIAL_STREAM" : [ "dangerous", "write the user's social stream", "Allows an application to write (but not read) the user's social stream data." ],
|
||||
# SOCIAL_INFO
|
||||
"READ_CONTACTS": ["dangerous", "read contact data",
|
||||
"Allows an application to read all of the contact (address) data stored on your phone. Malicious applications can use this to send your data to other people."],
|
||||
"WRITE_CONTACTS": ["dangerous", "write contact data",
|
||||
"Allows an application to modify the contact (address) data stored on your phone. Malicious applications can use this to erase or modify your contact data."],
|
||||
"BIND_DIRECTORY_SEARCH": ["signatureOrSystem", "execute contacts directory search",
|
||||
"Allows an application to execute contacts directory search. This should only be used by ContactsProvider."],
|
||||
"READ_CALL_LOG": ["dangerous", "read the user's call log.",
|
||||
"Allows an application to read the user's call log."],
|
||||
"WRITE_CALL_LOG": ["dangerous", "write (but not read) the user's contacts data.",
|
||||
"Allows an application to write (but not read) the user's contacts data."],
|
||||
"READ_SOCIAL_STREAM": ["dangerous", "read from the user's social stream",
|
||||
"Allows an application to read from the user's social stream."],
|
||||
"WRITE_SOCIAL_STREAM": ["dangerous", "write the user's social stream",
|
||||
"Allows an application to write (but not read) the user's social stream data."],
|
||||
|
||||
# PERSONAL_INFO
|
||||
"READ_PROFILE" : [ "dangerous", "read the user's personal profile data", "Allows an application to read the user's personal profile data."],
|
||||
"WRITE_PROFILE" : [ "dangerous", "write the user's personal profile data", "Allows an application to write (but not read) the user's personal profile data."],
|
||||
"RETRIEVE_WINDOW_CONTENT": [ "signatureOrSystem", "", "Allows an application to retrieve the content of the active window An active window is the window that has fired an accessibility event. " ],
|
||||
"BIND_APPWIDGET" : [ "signatureOrSystem" , "choose widgets" , "Allows the application to tell the system which widgets can be used by which application. With this permission, applications can give access to personal data to other applications. Not for use by normal applications." ],
|
||||
"BIND_KEYGUARD_APPWIDGET" : [ "signatureOrSystem", "", "Private permission, to restrict who can bring up a dialog to add a new keyguard widget" ],
|
||||
# PERSONAL_INFO
|
||||
"READ_PROFILE": ["dangerous", "read the user's personal profile data",
|
||||
"Allows an application to read the user's personal profile data."],
|
||||
"WRITE_PROFILE": ["dangerous", "write the user's personal profile data",
|
||||
"Allows an application to write (but not read) the user's personal profile data."],
|
||||
"RETRIEVE_WINDOW_CONTENT": ["signatureOrSystem", "",
|
||||
"Allows an application to retrieve the content of the active window An active window is the window that has fired an accessibility event. "],
|
||||
"BIND_APPWIDGET": ["signatureOrSystem", "choose widgets",
|
||||
"Allows the application to tell the system which widgets can be used by which application. With this permission, applications can give access to personal data to other applications. Not for use by normal applications."],
|
||||
"BIND_KEYGUARD_APPWIDGET": ["signatureOrSystem", "",
|
||||
"Private permission, to restrict who can bring up a dialog to add a new keyguard widget"],
|
||||
|
||||
# CALENDAR
|
||||
"READ_CALENDAR" : [ "dangerous" , "read calendar events" , "Allows an application to read all of the calendar events stored on your phone. Malicious applications can use this to send your calendar events to other people." ],
|
||||
"WRITE_CALENDAR": [ "dangerous" , "add or modify calendar events and send emails to guests" , "Allows an application to add or change the events on your calendar, which may send emails to guests. Malicious applications can use this to erase or modify your calendar events or to send emails to guests." ],
|
||||
# CALENDAR
|
||||
"READ_CALENDAR": ["dangerous", "read calendar events",
|
||||
"Allows an application to read all of the calendar events stored on your phone. Malicious applications can use this to send your calendar events to other people."],
|
||||
"WRITE_CALENDAR": ["dangerous", "add or modify calendar events and send emails to guests",
|
||||
"Allows an application to add or change the events on your calendar, which may send emails to guests. Malicious applications can use this to erase or modify your calendar events or to send emails to guests."],
|
||||
|
||||
# USER_DICTIONARY
|
||||
"READ_USER_DICTIONARY": ["dangerous", "read user-defined dictionary",
|
||||
"Allows an application to read any private words, names and phrases that the user may have stored in the user dictionary."],
|
||||
|
||||
# USER_DICTIONARY
|
||||
"READ_USER_DICTIONARY" : [ "dangerous" , "read user-defined dictionary" , "Allows an application to read any private words, names and phrases that the user may have stored in the user dictionary." ],
|
||||
# WRITE_USER_DICTIONARY
|
||||
"WRITE_USER_DICTIONARY": ["normal", "write to user-defined dictionary",
|
||||
"Allows an application to write new words into the user dictionary."],
|
||||
|
||||
# WRITE_USER_DICTIONARY
|
||||
"WRITE_USER_DICTIONARY" : [ "normal" , "write to user-defined dictionary" , "Allows an application to write new words into the user dictionary." ],
|
||||
# BOOKMARKS
|
||||
"READ_HISTORY_BOOKMARKS": ["dangerous", "read Browser\'s history and bookmarks",
|
||||
"Allows the application to read all the URLs that the browser has visited and all of the browser\'s bookmarks."],
|
||||
"WRITE_HISTORY_BOOKMARKS": ["dangerous", "write Browser\'s history and bookmarks",
|
||||
"Allows an application to modify the browser\'s history or bookmarks stored on your phone. Malicious applications can use this to erase or modify your browser\'s data."],
|
||||
|
||||
# BOOKMARKS
|
||||
"READ_HISTORY_BOOKMARKS" : [ "dangerous" , "read Browser\'s history and bookmarks" , "Allows the application to read all the URLs that the browser has visited and all of the browser\'s bookmarks." ],
|
||||
"WRITE_HISTORY_BOOKMARKS" : [ "dangerous" , "write Browser\'s history and bookmarks" , "Allows an application to modify the browser\'s history or bookmarks stored on your phone. Malicious applications can use this to erase or modify your browser\'s data." ],
|
||||
# DEVICE_ALARMS
|
||||
"SET_ALARM": ["normal", "set alarm in alarm clock",
|
||||
"Allows the application to set an alarm in an installed alarm clock application. Some alarm clock applications may not implement this feature."],
|
||||
|
||||
# DEVICE_ALARMS
|
||||
"SET_ALARM" : [ "normal" , "set alarm in alarm clock" , "Allows the application to set an alarm in an installed alarm clock application. Some alarm clock applications may not implement this feature." ],
|
||||
# VOICEMAIL
|
||||
"ADD_VOICEMAIL": ["dangerous", "add voicemails into the system",
|
||||
"Allows an application to add voicemails into the system."],
|
||||
|
||||
# VOICEMAIL
|
||||
"ADD_VOICEMAIL" : [ "dangerous", "add voicemails into the system", "Allows an application to add voicemails into the system." ],
|
||||
# LOCATION
|
||||
"ACCESS_FINE_LOCATION": ["dangerous", "fine (GPS) location",
|
||||
"Access fine location sources, such as the Global Positioning System on the phone, where available. Malicious applications can use this to determine where you are and may consume additional battery power."],
|
||||
"ACCESS_COARSE_LOCATION": ["dangerous", "coarse (network-based) location",
|
||||
"Access coarse location sources, such as the mobile network database, to determine an approximate phone location, where available. Malicious applications can use this to determine approximately where you are."],
|
||||
"ACCESS_MOCK_LOCATION": ["dangerous", "mock location sources for testing",
|
||||
"Create mock location sources for testing. Malicious applications can use this to override the location and/or status returned by real-location sources such as GPS or Network providers."],
|
||||
"ACCESS_LOCATION_EXTRA_COMMANDS": ["normal", "access extra location provider commands",
|
||||
"Access extra location provider commands. Malicious applications could use this to interfere with the operation of the GPS or other location sources."],
|
||||
"INSTALL_LOCATION_PROVIDER": ["signatureOrSystem", "permission to install a location provider",
|
||||
"Create mock location sources for testing. Malicious applications can use this to override the location and/or status returned by real-location sources such as GPS or Network providers, or monitor and report your location to an external source."],
|
||||
|
||||
# LOCATION
|
||||
"ACCESS_FINE_LOCATION" : [ "dangerous" , "fine (GPS) location" , "Access fine location sources, such as the Global Positioning System on the phone, where available. Malicious applications can use this to determine where you are and may consume additional battery power." ],
|
||||
"ACCESS_COARSE_LOCATION" : [ "dangerous" , "coarse (network-based) location" , "Access coarse location sources, such as the mobile network database, to determine an approximate phone location, where available. Malicious applications can use this to determine approximately where you are." ],
|
||||
"ACCESS_MOCK_LOCATION" : [ "dangerous" , "mock location sources for testing" , "Create mock location sources for testing. Malicious applications can use this to override the location and/or status returned by real-location sources such as GPS or Network providers." ],
|
||||
"ACCESS_LOCATION_EXTRA_COMMANDS" : [ "normal" , "access extra location provider commands" , "Access extra location provider commands. Malicious applications could use this to interfere with the operation of the GPS or other location sources." ],
|
||||
"INSTALL_LOCATION_PROVIDER" : [ "signatureOrSystem" , "permission to install a location provider" , "Create mock location sources for testing. Malicious applications can use this to override the location and/or status returned by real-location sources such as GPS or Network providers, or monitor and report your location to an external source." ],
|
||||
# NETWORK
|
||||
"INTERNET": ["dangerous", "full Internet access", "Allows an application to create network sockets."],
|
||||
"ACCESS_NETWORK_STATE": ["normal", "view network status",
|
||||
"Allows an application to view the status of all networks."],
|
||||
"ACCESS_WIFI_STATE": ["normal", "view Wi-Fi status",
|
||||
"Allows an application to view the information about the status of Wi-Fi."],
|
||||
"CHANGE_WIFI_STATE": ["dangerous", "change Wi-Fi status",
|
||||
"Allows an application to connect to and disconnect from Wi-Fi access points and to make changes to configured Wi-Fi networks."],
|
||||
"CHANGE_NETWORK_STATE": ["normal", "change network connectivity",
|
||||
"Allows an application to change the state of network connectivity."],
|
||||
"ACCESS_WIMAX_STATE": ["normal", "", ""],
|
||||
"CHANGE_WIMAX_STATE": ["dangerous", "", ""],
|
||||
"NFC": ["dangerous", "control Near-Field Communication",
|
||||
"Allows an application to communicate with Near-Field Communication (NFC) tags, cards and readers."],
|
||||
"CONNECTIVITY_INTERNAL": ["signatureOrSystem", "use privileged ConnectivityManager API",
|
||||
"Allows an internal user to use privileged ConnectivityManager API"],
|
||||
"RECEIVE_DATA_ACTIVITY_CHANGE": ["signatureOrSystem", "", ""],
|
||||
|
||||
# BLUETOOTH_NETWORK
|
||||
"BLUETOOTH": ["dangerous", "create Bluetooth connections",
|
||||
"Allows an application to view configuration of the local Bluetooth phone and to make and accept connections with paired devices."],
|
||||
"BLUETOOTH_ADMIN": ["dangerous", "bluetooth administration",
|
||||
"Allows an application to configure the local Bluetooth phone and to discover and pair with remote devices."],
|
||||
|
||||
# NETWORK
|
||||
"INTERNET" : [ "dangerous" , "full Internet access" , "Allows an application to create network sockets." ],
|
||||
"ACCESS_NETWORK_STATE" : [ "normal" , "view network status" , "Allows an application to view the status of all networks." ],
|
||||
"ACCESS_WIFI_STATE" : [ "normal" , "view Wi-Fi status" , "Allows an application to view the information about the status of Wi-Fi." ],
|
||||
"CHANGE_WIFI_STATE" : [ "dangerous" , "change Wi-Fi status" , "Allows an application to connect to and disconnect from Wi-Fi access points and to make changes to configured Wi-Fi networks." ],
|
||||
"CHANGE_NETWORK_STATE" : [ "normal" , "change network connectivity" , "Allows an application to change the state of network connectivity." ],
|
||||
"ACCESS_WIMAX_STATE": [ "normal", "", "" ],
|
||||
"CHANGE_WIMAX_STATE": [ "dangerous", "", "" ],
|
||||
"NFC" : [ "dangerous" , "control Near-Field Communication" , "Allows an application to communicate with Near-Field Communication (NFC) tags, cards and readers." ],
|
||||
"CONNECTIVITY_INTERNAL": [ "signatureOrSystem", "use privileged ConnectivityManager API", "Allows an internal user to use privileged ConnectivityManager API" ],
|
||||
"RECEIVE_DATA_ACTIVITY_CHANGE": [ "signatureOrSystem", "", "" ],
|
||||
|
||||
|
||||
# BLUETOOTH_NETWORK
|
||||
"BLUETOOTH" : [ "dangerous" , "create Bluetooth connections" , "Allows an application to view configuration of the local Bluetooth phone and to make and accept connections with paired devices." ],
|
||||
"BLUETOOTH_ADMIN" : [ "dangerous" , "bluetooth administration" , "Allows an application to configure the local Bluetooth phone and to discover and pair with remote devices." ],
|
||||
|
||||
|
||||
# SYSTEM TOOLS
|
||||
"BLUETOOTH_STACK": [ "signature", "", "" ],
|
||||
"NET_ADMIN": [ "signature", "configure network interfaces, configure/use IPSec, etc", "Allows access to configure network interfaces, configure/use IPSec, etc." ],
|
||||
"REMOTE_AUDIO_PLAYBACK": [ "signature", "remote audio playback", "Allows registration for remote audio playback" ],
|
||||
"READ_EXTERNAL_STORAGE" : [ "normal", "read from external storage", "Allows an application to read from external storage" ],
|
||||
"INTERACT_ACROSS_USERS": [ "signatureOrSystemOrDevelopment", "", "Allows an application to call APIs that allow it to do interactions across the users on the device, using singleton services and user-targeted broadcasts. This permission is not available to third party applications." ],
|
||||
"INTERACT_ACROSS_USERS_FULL": [ "signature", "", "Fuller form of INTERACT_ACROSS_USERS that removes restrictions on where broadcasts can be sent and allows other types of interactions." ],
|
||||
"MANAGE_USERS": [ "signatureOrSystem", "", "Allows an application to call APIs that allow it to query and manage users on the device. This permission is not available to third party applications." ],
|
||||
"GET_DETAILED_TASKS": [ "signature", "", "Allows an application to get full detailed information about recently running tasks, with full fidelity to the real state." ],
|
||||
"START_ANY_ACTIVITY": [ "signature", "", "Allows an application to start any activity, regardless of permission protection or exported state." ],
|
||||
"SET_SCREEN_COMPATIBILITY": [ "signature", "", "Change the screen compatibility mode of applications" ],
|
||||
"CHANGE_CONFIGURATION" : [ "signatureOrSystemOrDevelopment" , "change your UI settings" , "Allows an application to change the current configuration, such as the locale or overall font size." ],
|
||||
"FORCE_STOP_PACKAGES" : [ "signature" , "force-stop other applications" , "Allows an application to stop other applications forcibly." ],
|
||||
"SET_ANIMATION_SCALE" : [ "signatureOrSystemOrDevelopment" , "modify global animation speed" , "Allows an application to change the global animation speed (faster or slower animations) at any time." ],
|
||||
"GET_PACKAGE_SIZE" : [ "normal" , "measure application storage space" , "Allows an application to retrieve its code, data and cache sizes" ],
|
||||
"SET_PREFERRED_APPLICATIONS" : [ "signature" , "set preferred applications" , "Allows an application to modify your preferred applications. This can allow malicious applications to silently change the applications that are run, spoofing your existing applications to collect private data from you." ],
|
||||
"BROADCAST_STICKY" : [ "normal" , "send sticky broadcast" , "Allows an application to send sticky broadcasts, which remain after the broadcast ends. Malicious applications can make the phone slow or unstable by causing it to use too much memory." ],
|
||||
"MOUNT_UNMOUNT_FILESYSTEMS" : [ "signatureOrSystem" , "mount and unmount file systems" , "Allows the application to mount and unmount file systems for removable storage." ],
|
||||
"MOUNT_FORMAT_FILESYSTEMS" : [ "signatureOrSystem" , "format external storage" , "Allows the application to format removable storage." ],
|
||||
"ASEC_ACCESS" : [ "signature" , "get information on internal storage" , "Allows the application to get information on internal storage." ],
|
||||
"ASEC_CREATE" : [ "signature" , "create internal storage" , "Allows the application to create internal storage." ],
|
||||
"ASEC_DESTROY" : [ "signature" , "destroy internal storage" , "Allows the application to destroy internal storage." ],
|
||||
"ASEC_MOUNT_UNMOUNT" : [ "signature" , "mount/unmount internal storage" , "Allows the application to mount/unmount internal storage." ],
|
||||
"ASEC_RENAME" : [ "signature" , "rename internal storage" , "Allows the application to rename internal storage." ],
|
||||
"WRITE_APN_SETTINGS" : [ "signatureOrSystem" , "write Access Point Name settings" , "Allows an application to modify the APN settings, such as Proxy and Port of any APN." ],
|
||||
"SUBSCRIBED_FEEDS_READ" : [ "normal" , "read subscribed feeds" , "Allows an application to receive details about the currently synced feeds." ],
|
||||
"SUBSCRIBED_FEEDS_WRITE" : [ "dangerous" , "write subscribed feeds" , "Allows an application to modify your currently synced feeds. This could allow a malicious application to change your synced feeds." ],
|
||||
"CLEAR_APP_CACHE" : [ "dangerous" , "delete all application cache data" , "Allows an application to free phone storage by deleting files in application cache directory. Access is usually very restricted to system process." ],
|
||||
"DIAGNOSTIC" : [ "signature" , "read/write to resources owned by diag" , "Allows an application to read and write to any resource owned by the diag group; for example, files in /dev. This could potentially affect system stability and security. This should ONLY be used for hardware-specific diagnostics by the manufacturer or operator." ],
|
||||
"BROADCAST_PACKAGE_REMOVED" : [ "signature" , "send package removed broadcast" , "Allows an application to broadcast a notification that an application package has been removed. Malicious applications may use this to kill any other application running." ],
|
||||
"BATTERY_STATS" : [ "dangerous" , "modify battery statistics" , "Allows the modification of collected battery statistics. Not for use by normal applications." ],
|
||||
"MODIFY_APPWIDGET_BIND_PERMISSIONS" : [ "signatureOrSystem", "query/set which applications can bind AppWidgets.", "Internal permission allowing an application to query/set which applications can bind AppWidgets." ],
|
||||
"CHANGE_BACKGROUND_DATA_SETTING" : [ "signature" , "change background data usage setting" , "Allows an application to change the background data usage setting." ],
|
||||
"GLOBAL_SEARCH" : [ "signatureOrSystem" , "" , "This permission can be used on content providers to allow the global search " \
|
||||
"system to access their data. Typically it used when the provider has some " \
|
||||
# SYSTEM TOOLS
|
||||
"BLUETOOTH_STACK": ["signature", "", ""],
|
||||
"NET_ADMIN": ["signature", "configure network interfaces, configure/use IPSec, etc",
|
||||
"Allows access to configure network interfaces, configure/use IPSec, etc."],
|
||||
"REMOTE_AUDIO_PLAYBACK": ["signature", "remote audio playback",
|
||||
"Allows registration for remote audio playback"],
|
||||
"READ_EXTERNAL_STORAGE": ["normal", "read from external storage",
|
||||
"Allows an application to read from external storage"],
|
||||
"INTERACT_ACROSS_USERS": ["signatureOrSystemOrDevelopment", "",
|
||||
"Allows an application to call APIs that allow it to do interactions across the users on the device, using singleton services and user-targeted broadcasts. This permission is not available to third party applications."],
|
||||
"INTERACT_ACROSS_USERS_FULL": ["signature", "",
|
||||
"Fuller form of INTERACT_ACROSS_USERS that removes restrictions on where broadcasts can be sent and allows other types of interactions."],
|
||||
"MANAGE_USERS": ["signatureOrSystem", "",
|
||||
"Allows an application to call APIs that allow it to query and manage users on the device. This permission is not available to third party applications."],
|
||||
"GET_DETAILED_TASKS": ["signature", "",
|
||||
"Allows an application to get full detailed information about recently running tasks, with full fidelity to the real state."],
|
||||
"START_ANY_ACTIVITY": ["signature", "",
|
||||
"Allows an application to start any activity, regardless of permission protection or exported state."],
|
||||
"SET_SCREEN_COMPATIBILITY": ["signature", "", "Change the screen compatibility mode of applications"],
|
||||
"CHANGE_CONFIGURATION": ["signatureOrSystemOrDevelopment", "change your UI settings",
|
||||
"Allows an application to change the current configuration, such as the locale or overall font size."],
|
||||
"FORCE_STOP_PACKAGES": ["signature", "force-stop other applications",
|
||||
"Allows an application to stop other applications forcibly."],
|
||||
"SET_ANIMATION_SCALE": ["signatureOrSystemOrDevelopment", "modify global animation speed",
|
||||
"Allows an application to change the global animation speed (faster or slower animations) at any time."],
|
||||
"GET_PACKAGE_SIZE": ["normal", "measure application storage space",
|
||||
"Allows an application to retrieve its code, data and cache sizes"],
|
||||
"SET_PREFERRED_APPLICATIONS": ["signature", "set preferred applications",
|
||||
"Allows an application to modify your preferred applications. This can allow malicious applications to silently change the applications that are run, spoofing your existing applications to collect private data from you."],
|
||||
"BROADCAST_STICKY": ["normal", "send sticky broadcast",
|
||||
"Allows an application to send sticky broadcasts, which remain after the broadcast ends. Malicious applications can make the phone slow or unstable by causing it to use too much memory."],
|
||||
"MOUNT_UNMOUNT_FILESYSTEMS": ["signatureOrSystem", "mount and unmount file systems",
|
||||
"Allows the application to mount and unmount file systems for removable storage."],
|
||||
"MOUNT_FORMAT_FILESYSTEMS": ["signatureOrSystem", "format external storage",
|
||||
"Allows the application to format removable storage."],
|
||||
"ASEC_ACCESS": ["signature", "get information on internal storage",
|
||||
"Allows the application to get information on internal storage."],
|
||||
"ASEC_CREATE": ["signature", "create internal storage", "Allows the application to create internal storage."],
|
||||
"ASEC_DESTROY": ["signature", "destroy internal storage",
|
||||
"Allows the application to destroy internal storage."],
|
||||
"ASEC_MOUNT_UNMOUNT": ["signature", "mount/unmount internal storage",
|
||||
"Allows the application to mount/unmount internal storage."],
|
||||
"ASEC_RENAME": ["signature", "rename internal storage", "Allows the application to rename internal storage."],
|
||||
"WRITE_APN_SETTINGS": ["signatureOrSystem", "write Access Point Name settings",
|
||||
"Allows an application to modify the APN settings, such as Proxy and Port of any APN."],
|
||||
"SUBSCRIBED_FEEDS_READ": ["normal", "read subscribed feeds",
|
||||
"Allows an application to receive details about the currently synced feeds."],
|
||||
"SUBSCRIBED_FEEDS_WRITE": ["dangerous", "write subscribed feeds",
|
||||
"Allows an application to modify your currently synced feeds. This could allow a malicious application to change your synced feeds."],
|
||||
"CLEAR_APP_CACHE": ["dangerous", "delete all application cache data",
|
||||
"Allows an application to free phone storage by deleting files in application cache directory. Access is usually very restricted to system process."],
|
||||
"DIAGNOSTIC": ["signature", "read/write to resources owned by diag",
|
||||
"Allows an application to read and write to any resource owned by the diag group; for example, files in /dev. This could potentially affect system stability and security. This should ONLY be used for hardware-specific diagnostics by the manufacturer or operator."],
|
||||
"BROADCAST_PACKAGE_REMOVED": ["signature", "send package removed broadcast",
|
||||
"Allows an application to broadcast a notification that an application package has been removed. Malicious applications may use this to kill any other application running."],
|
||||
"BATTERY_STATS": ["dangerous", "modify battery statistics",
|
||||
"Allows the modification of collected battery statistics. Not for use by normal applications."],
|
||||
"MODIFY_APPWIDGET_BIND_PERMISSIONS": ["signatureOrSystem", "query/set which applications can bind AppWidgets.",
|
||||
"Internal permission allowing an application to query/set which applications can bind AppWidgets."],
|
||||
"CHANGE_BACKGROUND_DATA_SETTING": ["signature", "change background data usage setting",
|
||||
"Allows an application to change the background data usage setting."],
|
||||
"GLOBAL_SEARCH": ["signatureOrSystem", "",
|
||||
"This permission can be used on content providers to allow the global search " \
|
||||
"system to access their data. Typically it used when the provider has some " \
|
||||
"permissions protecting it (which global search would not be expected to hold)," \
|
||||
"and added as a read-only permission to the path in the provider where global "\
|
||||
"search queries are performed. This permission can not be held by regular applications; "\
|
||||
"it is used by applications to protect themselves from everyone else besides global search" ],
|
||||
"GLOBAL_SEARCH_CONTROL" : [ "signature" , "" , "Internal permission protecting access to the global search " \
|
||||
"system: ensures that only the system can access the provider " \
|
||||
"to perform queries (since this otherwise provides unrestricted " \
|
||||
"access to a variety of content providers), and to write the " \
|
||||
"search statistics (to keep applications from gaming the source " \
|
||||
"ranking)." ],
|
||||
"SET_WALLPAPER_COMPONENT" : [ "signatureOrSystem" , "set a live wallpaper" , "Allows applications to set a live wallpaper." ],
|
||||
"READ_DREAM_STATE" : [ "signature", "", "Allows applications to read dream settings and dream state." ],
|
||||
"WRITE_DREAM_STATE" : [ "signature", "", "Allows applications to write dream settings, and start or stop dreaming." ],
|
||||
"WRITE_SETTINGS" : [ "normal" , "modify global system settings" , "Allows an application to modify the system\'s settings data. Malicious applications can corrupt your system\'s configuration." ],
|
||||
"and added as a read-only permission to the path in the provider where global " \
|
||||
"search queries are performed. This permission can not be held by regular applications; " \
|
||||
"it is used by applications to protect themselves from everyone else besides global search"],
|
||||
"GLOBAL_SEARCH_CONTROL": ["signature", "", "Internal permission protecting access to the global search " \
|
||||
"system: ensures that only the system can access the provider " \
|
||||
"to perform queries (since this otherwise provides unrestricted " \
|
||||
"access to a variety of content providers), and to write the " \
|
||||
"search statistics (to keep applications from gaming the source " \
|
||||
"ranking)."],
|
||||
"SET_WALLPAPER_COMPONENT": ["signatureOrSystem", "set a live wallpaper",
|
||||
"Allows applications to set a live wallpaper."],
|
||||
"READ_DREAM_STATE": ["signature", "", "Allows applications to read dream settings and dream state."],
|
||||
"WRITE_DREAM_STATE": ["signature", "",
|
||||
"Allows applications to write dream settings, and start or stop dreaming."],
|
||||
"WRITE_SETTINGS": ["normal", "modify global system settings",
|
||||
"Allows an application to modify the system\'s settings data. Malicious applications can corrupt your system\'s configuration."],
|
||||
|
||||
# ACCOUNTS
|
||||
"GET_ACCOUNTS" : [ "normal" , "discover known accounts" , "Allows an application to access the list of accounts known by the phone." ],
|
||||
"AUTHENTICATE_ACCOUNTS" : [ "dangerous" , "act as an account authenticator" , "Allows an application to use the account authenticator capabilities of the Account Manager, including creating accounts as well as obtaining and setting their passwords." ],
|
||||
"USE_CREDENTIALS" : [ "dangerous" , "use the authentication credentials of an account" , "Allows an application to request authentication tokens." ],
|
||||
"MANAGE_ACCOUNTS" : [ "dangerous" , "manage the accounts list" , "Allows an application to perform operations like adding and removing accounts and deleting their password." ],
|
||||
"ACCOUNT_MANAGER" : [ "signature" , "act as the Account Manager Service" , "Allows an application to make calls to Account Authenticators" ],
|
||||
# ACCOUNTS
|
||||
"GET_ACCOUNTS": ["normal", "discover known accounts",
|
||||
"Allows an application to access the list of accounts known by the phone."],
|
||||
"AUTHENTICATE_ACCOUNTS": ["dangerous", "act as an account authenticator",
|
||||
"Allows an application to use the account authenticator capabilities of the Account Manager, including creating accounts as well as obtaining and setting their passwords."],
|
||||
"USE_CREDENTIALS": ["dangerous", "use the authentication credentials of an account",
|
||||
"Allows an application to request authentication tokens."],
|
||||
"MANAGE_ACCOUNTS": ["dangerous", "manage the accounts list",
|
||||
"Allows an application to perform operations like adding and removing accounts and deleting their password."],
|
||||
"ACCOUNT_MANAGER": ["signature", "act as the Account Manager Service",
|
||||
"Allows an application to make calls to Account Authenticators"],
|
||||
|
||||
# AFFECTS_BATTERY
|
||||
"CHANGE_WIFI_MULTICAST_STATE" : [ "dangerous" , "allow Wi-Fi Multicast reception" , "Allows an application to receive packets not directly addressed to your device. This can be useful when discovering services offered nearby. It uses more power than the non-multicast mode." ],
|
||||
"VIBRATE" : [ "normal" , "control vibrator" , "Allows the application to control the vibrator." ],
|
||||
"FLASHLIGHT" : [ "normal" , "control flashlight" , "Allows the application to control the flashlight." ],
|
||||
"WAKE_LOCK" : [ "normal" , "prevent phone from sleeping" , "Allows an application to prevent the phone from going to sleep." ],
|
||||
# AFFECTS_BATTERY
|
||||
"CHANGE_WIFI_MULTICAST_STATE": ["dangerous", "allow Wi-Fi Multicast reception",
|
||||
"Allows an application to receive packets not directly addressed to your device. This can be useful when discovering services offered nearby. It uses more power than the non-multicast mode."],
|
||||
"VIBRATE": ["normal", "control vibrator", "Allows the application to control the vibrator."],
|
||||
"FLASHLIGHT": ["normal", "control flashlight", "Allows the application to control the flashlight."],
|
||||
"WAKE_LOCK": ["normal", "prevent phone from sleeping",
|
||||
"Allows an application to prevent the phone from going to sleep."],
|
||||
|
||||
# AUDIO_SETTINGS
|
||||
"MODIFY_AUDIO_SETTINGS" : [ "normal" , "change your audio settings" , "Allows application to modify global audio settings, such as volume and routing." ],
|
||||
# AUDIO_SETTINGS
|
||||
"MODIFY_AUDIO_SETTINGS": ["normal", "change your audio settings",
|
||||
"Allows application to modify global audio settings, such as volume and routing."],
|
||||
|
||||
# HARDWARE_CONTROLS
|
||||
"MANAGE_USB": [ "signatureOrSystem", "manage preferences and permissions for USB devices", "Allows an application to manage preferences and permissions for USB devices" ],
|
||||
"ACCESS_MTP": [ "signatureOrSystem", "access the MTP USB kernel driver", "Allows an application to access the MTP USB kernel driver. For use only by the device side MTP implementation." ],
|
||||
"HARDWARE_TEST" : [ "signature" , "test hardware" , "Allows the application to control various peripherals for the purpose of hardware testing." ],
|
||||
# HARDWARE_CONTROLS
|
||||
"MANAGE_USB": ["signatureOrSystem", "manage preferences and permissions for USB devices",
|
||||
"Allows an application to manage preferences and permissions for USB devices"],
|
||||
"ACCESS_MTP": ["signatureOrSystem", "access the MTP USB kernel driver",
|
||||
"Allows an application to access the MTP USB kernel driver. For use only by the device side MTP implementation."],
|
||||
"HARDWARE_TEST": ["signature", "test hardware",
|
||||
"Allows the application to control various peripherals for the purpose of hardware testing."],
|
||||
|
||||
# MICROPHONE
|
||||
"RECORD_AUDIO" : [ "dangerous" , "record audio" , "Allows application to access the audio record path." ],
|
||||
# MICROPHONE
|
||||
"RECORD_AUDIO": ["dangerous", "record audio", "Allows application to access the audio record path."],
|
||||
|
||||
# CAMERA
|
||||
"CAMERA" : [ "dangerous" , "take pictures and videos" , "Allows application to take pictures and videos with the camera. This allows the application to collect images that the camera is seeing at any time." ],
|
||||
# CAMERA
|
||||
"CAMERA": ["dangerous", "take pictures and videos",
|
||||
"Allows application to take pictures and videos with the camera. This allows the application to collect images that the camera is seeing at any time."],
|
||||
|
||||
# PHONE_CALLS
|
||||
"PROCESS_OUTGOING_CALLS" : [ "dangerous" , "intercept outgoing calls" , "Allows application to process outgoing calls and change the number to be dialled. Malicious applications may monitor, redirect or prevent outgoing calls." ],
|
||||
"MODIFY_PHONE_STATE" : [ "signatureOrSystem" , "modify phone status" , "Allows modification of the telephony state - power on, mmi, etc. Does not include placing calls." ],
|
||||
"READ_PHONE_STATE" : [ "dangerous" , "read phone state and identity" , "Allows the application to access the phone features of the device. An application with this permission can determine the phone number and serial number of this phone, whether a call is active, the number that call is connected to and so on." ],
|
||||
"READ_PRIVILEGED_PHONE_STATE": [ "signatureOrSystem", "read access to privileged phone state", "Allows read access to privileged phone state." ],
|
||||
"CALL_PHONE" : [ "dangerous" , "directly call phone numbers" , "Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call being placed. " ],
|
||||
"USE_SIP" : [ "dangerous" , "make/receive Internet calls" , "Allows an application to use the SIP service to make/receive Internet calls." ],
|
||||
# PHONE_CALLS
|
||||
"PROCESS_OUTGOING_CALLS": ["dangerous", "intercept outgoing calls",
|
||||
"Allows application to process outgoing calls and change the number to be dialled. Malicious applications may monitor, redirect or prevent outgoing calls."],
|
||||
"MODIFY_PHONE_STATE": ["signatureOrSystem", "modify phone status",
|
||||
"Allows modification of the telephony state - power on, mmi, etc. Does not include placing calls."],
|
||||
"READ_PHONE_STATE": ["dangerous", "read phone state and identity",
|
||||
"Allows the application to access the phone features of the device. An application with this permission can determine the phone number and serial number of this phone, whether a call is active, the number that call is connected to and so on."],
|
||||
"READ_PRIVILEGED_PHONE_STATE": ["signatureOrSystem", "read access to privileged phone state",
|
||||
"Allows read access to privileged phone state."],
|
||||
"CALL_PHONE": ["dangerous", "directly call phone numbers",
|
||||
"Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call being placed. "],
|
||||
"USE_SIP": ["dangerous", "make/receive Internet calls",
|
||||
"Allows an application to use the SIP service to make/receive Internet calls."],
|
||||
|
||||
# STORAGE
|
||||
"WRITE_EXTERNAL_STORAGE" : [ "dangerous" , "modify/delete SD card contents" , "Allows an application to write to the SD card." ],
|
||||
"WRITE_MEDIA_STORAGE": [ "signatureOrSystem", "write to internal media storage", "Allows an application to write to internal media storage" ],
|
||||
# STORAGE
|
||||
"WRITE_EXTERNAL_STORAGE": ["dangerous", "modify/delete SD card contents",
|
||||
"Allows an application to write to the SD card."],
|
||||
"WRITE_MEDIA_STORAGE": ["signatureOrSystem", "write to internal media storage",
|
||||
"Allows an application to write to internal media storage"],
|
||||
|
||||
# SCREENLOCK
|
||||
"DISABLE_KEYGUARD" : [ "dangerous" , "disable key lock" , "Allows an application to disable the key lock and any associated password security. A legitimate example of this is the phone disabling the key lock when receiving an incoming phone call, then re-enabling the key lock when the call is finished." ],
|
||||
# SCREENLOCK
|
||||
"DISABLE_KEYGUARD": ["dangerous", "disable key lock",
|
||||
"Allows an application to disable the key lock and any associated password security. A legitimate example of this is the phone disabling the key lock when receiving an incoming phone call, then re-enabling the key lock when the call is finished."],
|
||||
|
||||
# APP_INFO
|
||||
"GET_TASKS" : [ "dangerous" , "retrieve running applications" , "Allows application to retrieve information about currently and recently running tasks. May allow malicious applications to discover private information about other applications." ],
|
||||
"REORDER_TASKS" : [ "normal" , "reorder applications running" , "Allows an application to move tasks to the foreground and background. Malicious applications can force themselves to the front without your control." ],
|
||||
"REMOVE_TASKS": [ "signature", "", "Allows an application to change to remove/kill tasks" ],
|
||||
"RESTART_PACKAGES" : [ "normal" , "kill background processes" , "Allows an application to kill background processes of other applications, even if memory is not low." ],
|
||||
"KILL_BACKGROUND_PROCESSES" : [ "normal" , "kill background processes" , "Allows an application to kill background processes of other applications, even if memory is not low." ],
|
||||
"PERSISTENT_ACTIVITY" : [ "normal" , "make application always run" , "Allows an application to make parts of itself persistent, so that the system can\'t use it for other applications." ],
|
||||
"RECEIVE_BOOT_COMPLETED" : [ "normal" , "automatically start at boot" , "Allows an application to start itself as soon as the system has finished booting. This can make it take longer to start the phone and allow the application to slow down the overall phone by always running." ],
|
||||
# APP_INFO
|
||||
"GET_TASKS": ["dangerous", "retrieve running applications",
|
||||
"Allows application to retrieve information about currently and recently running tasks. May allow malicious applications to discover private information about other applications."],
|
||||
"REORDER_TASKS": ["normal", "reorder applications running",
|
||||
"Allows an application to move tasks to the foreground and background. Malicious applications can force themselves to the front without your control."],
|
||||
"REMOVE_TASKS": ["signature", "", "Allows an application to change to remove/kill tasks"],
|
||||
"RESTART_PACKAGES": ["normal", "kill background processes",
|
||||
"Allows an application to kill background processes of other applications, even if memory is not low."],
|
||||
"KILL_BACKGROUND_PROCESSES": ["normal", "kill background processes",
|
||||
"Allows an application to kill background processes of other applications, even if memory is not low."],
|
||||
"PERSISTENT_ACTIVITY": ["normal", "make application always run",
|
||||
"Allows an application to make parts of itself persistent, so that the system can\'t use it for other applications."],
|
||||
"RECEIVE_BOOT_COMPLETED": ["normal", "automatically start at boot",
|
||||
"Allows an application to start itself as soon as the system has finished booting. This can make it take longer to start the phone and allow the application to slow down the overall phone by always running."],
|
||||
|
||||
# DISPLAY
|
||||
"SYSTEM_ALERT_WINDOW" : [ "dangerous" , "display system-level alerts" , "Allows an application to show system-alert windows. Malicious applications can take over the entire screen of the phone." ],
|
||||
# DISPLAY
|
||||
"SYSTEM_ALERT_WINDOW": ["dangerous", "display system-level alerts",
|
||||
"Allows an application to show system-alert windows. Malicious applications can take over the entire screen of the phone."],
|
||||
|
||||
# WALLPAPER
|
||||
"SET_WALLPAPER" : [ "normal" , "set wallpaper" , "Allows the application to set the system wallpaper." ],
|
||||
"SET_WALLPAPER_HINTS" : [ "normal" , "set wallpaper size hints" , "Allows the application to set the system wallpaper size hints." ],
|
||||
# WALLPAPER
|
||||
"SET_WALLPAPER": ["normal", "set wallpaper", "Allows the application to set the system wallpaper."],
|
||||
"SET_WALLPAPER_HINTS": ["normal", "set wallpaper size hints",
|
||||
"Allows the application to set the system wallpaper size hints."],
|
||||
|
||||
# SYSTEM_CLOCK
|
||||
"SET_TIME_ZONE" : [ "normal" , "set time zone" , "Allows an application to change the phone\'s time zone." ],
|
||||
# SYSTEM_CLOCK
|
||||
"SET_TIME_ZONE": ["normal", "set time zone", "Allows an application to change the phone\'s time zone."],
|
||||
|
||||
# STATUS_BAR
|
||||
"EXPAND_STATUS_BAR" : [ "normal" , "expand/collapse status bar" , "Allows application to expand or collapse the status bar." ],
|
||||
# STATUS_BAR
|
||||
"EXPAND_STATUS_BAR": ["normal", "expand/collapse status bar",
|
||||
"Allows application to expand or collapse the status bar."],
|
||||
|
||||
# SYNC_SETTINGS
|
||||
"READ_SYNC_SETTINGS" : [ "normal" , "read sync settings" , "Allows an application to read the sync settings, such as whether sync is enabled for Contacts." ],
|
||||
"WRITE_SYNC_SETTINGS" : [ "normal" , "write sync settings" , "Allows an application to modify the sync settings, such as whether sync is enabled for Contacts." ],
|
||||
"READ_SYNC_STATS" : [ "normal" , "read sync statistics" , "Allows an application to read the sync stats; e.g. the history of syncs that have occurred." ],
|
||||
# SYNC_SETTINGS
|
||||
"READ_SYNC_SETTINGS": ["normal", "read sync settings",
|
||||
"Allows an application to read the sync settings, such as whether sync is enabled for Contacts."],
|
||||
"WRITE_SYNC_SETTINGS": ["normal", "write sync settings",
|
||||
"Allows an application to modify the sync settings, such as whether sync is enabled for Contacts."],
|
||||
"READ_SYNC_STATS": ["normal", "read sync statistics",
|
||||
"Allows an application to read the sync stats; e.g. the history of syncs that have occurred."],
|
||||
|
||||
# DEVELOPMENT_TOOLS
|
||||
"WRITE_SECURE_SETTINGS" : [ "signatureOrSystemOrDevelopment" , "modify secure system settings" , "Allows an application to modify the system\'s secure settings data. Not for use by normal applications." ],
|
||||
"DUMP" : [ "signatureOrSystemOrDevelopment" , "retrieve system internal status" , "Allows application to retrieve internal status of the system. Malicious applications may retrieve a wide variety of private and secure information that they should never normally need." ],
|
||||
"READ_LOGS" : [ "signatureOrSystemOrDevelopment" , "read sensitive log data" , "Allows an application to read from the system\'s various log files. This allows it to discover general information about what you are doing with the phone, potentially including personal or private information." ],
|
||||
"SET_DEBUG_APP" : [ "signatureOrSystemOrDevelopment" , "enable application debugging" , "Allows an application to turn on debugging for another application. Malicious applications can use this to kill other applications." ],
|
||||
"SET_PROCESS_LIMIT" : [ "signatureOrSystemOrDevelopment" , "limit number of running processes" , "Allows an application to control the maximum number of processes that will run. Never needed for normal applications." ],
|
||||
"SET_ALWAYS_FINISH" : [ "signatureOrSystemOrDevelopment" , "make all background applications close" , "Allows an application to control whether activities are always finished as soon as they go to the background. Never needed for normal applications." ],
|
||||
"SIGNAL_PERSISTENT_PROCESSES" : [ "signatureOrSystemOrDevelopment" , "send Linux signals to applications" , "Allows application to request that the supplied signal be sent to all persistent processes." ],
|
||||
"ACCESS_ALL_EXTERNAL_STORAGE" : [ "signature", "", "Allows an application to access all multi-user external storage" ],
|
||||
# DEVELOPMENT_TOOLS
|
||||
"WRITE_SECURE_SETTINGS": ["signatureOrSystemOrDevelopment", "modify secure system settings",
|
||||
"Allows an application to modify the system\'s secure settings data. Not for use by normal applications."],
|
||||
"DUMP": ["signatureOrSystemOrDevelopment", "retrieve system internal status",
|
||||
"Allows application to retrieve internal status of the system. Malicious applications may retrieve a wide variety of private and secure information that they should never normally need."],
|
||||
"READ_LOGS": ["signatureOrSystemOrDevelopment", "read sensitive log data",
|
||||
"Allows an application to read from the system\'s various log files. This allows it to discover general information about what you are doing with the phone, potentially including personal or private information."],
|
||||
"SET_DEBUG_APP": ["signatureOrSystemOrDevelopment", "enable application debugging",
|
||||
"Allows an application to turn on debugging for another application. Malicious applications can use this to kill other applications."],
|
||||
"SET_PROCESS_LIMIT": ["signatureOrSystemOrDevelopment", "limit number of running processes",
|
||||
"Allows an application to control the maximum number of processes that will run. Never needed for normal applications."],
|
||||
"SET_ALWAYS_FINISH": ["signatureOrSystemOrDevelopment", "make all background applications close",
|
||||
"Allows an application to control whether activities are always finished as soon as they go to the background. Never needed for normal applications."],
|
||||
"SIGNAL_PERSISTENT_PROCESSES": ["signatureOrSystemOrDevelopment", "send Linux signals to applications",
|
||||
"Allows application to request that the supplied signal be sent to all persistent processes."],
|
||||
"ACCESS_ALL_EXTERNAL_STORAGE": ["signature", "",
|
||||
"Allows an application to access all multi-user external storage"],
|
||||
|
||||
# No groups ...
|
||||
"SET_TIME": [ "signatureOrSystem" , "set time" , "Allows an application to change the phone\'s clock time." ],
|
||||
"ALLOW_ANY_CODEC_FOR_PLAYBACK": [ "signatureOrSystem", "", "Allows an application to use any media decoder when decoding for playback." ],
|
||||
"STATUS_BAR" : [ "signatureOrSystem" , "disable or modify status bar" , "Allows application to disable the status bar or add and remove system icons." ],
|
||||
"STATUS_BAR_SERVICE" : [ "signature" , "status bar" , "Allows the application to be the status bar." ],
|
||||
"FORCE_BACK" : [ "signature" , "force application to close" , "Allows an application to force any activity that is in the foreground to close and go back. Should never be needed for normal applications." ],
|
||||
"UPDATE_DEVICE_STATS" : [ "signatureOrSystem" , "modify battery statistics" , "Allows the modification of collected battery statistics. Not for use by normal applications." ],
|
||||
"INTERNAL_SYSTEM_WINDOW" : [ "signature" , "display unauthorised windows" , "Allows the creation of windows that are intended to be used by the internal system user interface. Not for use by normal applications." ],
|
||||
"MANAGE_APP_TOKENS" : [ "signature" , "manage application tokens" , "Allows applications to create and manage their own tokens, bypassing their normal Z-ordering. Should never be needed for normal applications." ],
|
||||
"FREEZE_SCREEN": [ "signature", "", "Allows the application to temporarily freeze the screen for a full-screen transition." ],
|
||||
"INJECT_EVENTS" : [ "signature" , "inject user events" , "Allows an application to inject user events (keys, touch, trackball) into the event stream and deliver them to ANY window. Without this permission, you can only deliver events to windows in your own process. Very few applications should need to use this permission" ],
|
||||
"FILTER_EVENTS": [ "signature", "", "Allows an application to register an input filter which filters the stream of user events (keys, touch, trackball) before they are dispatched to any window" ],
|
||||
"RETRIEVE_WINDOW_INFO" : [ "signature", "", "Allows an application to retrieve info for a window from the window manager." ],
|
||||
"TEMPORARY_ENABLE_ACCESSIBILITY": [ "signature", "", "Allows an application to temporary enable accessibility on the device." ],
|
||||
"MAGNIFY_DISPLAY": [ "signature", "", "Allows an application to magnify the content of a display." ],
|
||||
"SET_ACTIVITY_WATCHER" : [ "signature" , "monitor and control all application launching" , "Allows an application to monitor and control how the system launches activities. Malicious applications may compromise the system completely. This permission is needed only for development, never for normal phone usage." ],
|
||||
"SHUTDOWN" : [ "signatureOrSystem" , "partial shutdown" , "Puts the activity manager into a shut-down state. Does not perform a complete shut down." ],
|
||||
"STOP_APP_SWITCHES" : [ "signatureOrSystem" , "prevent app switches" , "Prevents the user from switching to another application." ],
|
||||
"READ_INPUT_STATE" : [ "signature" , "record what you type and actions that you take" , "Allows applications to watch the keys that you press even when interacting with another application (such as entering a password). Should never be needed for normal applications." ],
|
||||
"BIND_INPUT_METHOD" : [ "signature" , "bind to an input method" , "Allows the holder to bind to the top-level interface of an input method. Should never be needed for normal applications." ],
|
||||
"BIND_ACCESSIBILITY_SERVICE" : [ "signature", "", "Must be required by an android.accessibilityservice.AccessibilityService to ensure that only the system can bind to it. " ],
|
||||
"BIND_TEXT_SERVICE" : [ "signature", "", "Must be required by a TextService (e.g. SpellCheckerService) to ensure that only the system can bind to it." ],
|
||||
"BIND_VPN_SERVICE" : [ "signature", "", "Must be required by an {@link android.net.VpnService}, to ensure that only the system can bind to it." ],
|
||||
"BIND_WALLPAPER" : [ "signatureOrSystem" , "bind to wallpaper" , "Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications." ],
|
||||
"BIND_DEVICE_ADMIN" : [ "signature" , "interact with device admin" , "Allows the holder to send intents to a device administrator. Should never be needed for normal applications." ],
|
||||
"SET_ORIENTATION" : [ "signature" , "change screen orientation" , "Allows an application to change the rotation of the screen at any time. Should never be needed for normal applications." ],
|
||||
"SET_POINTER_SPEED" : [ "signature", "", "Allows low-level access to setting the pointer speed. Not for use by normal applications. " ],
|
||||
"SET_KEYBOARD_LAYOUT" : [ "signature", "", "Allows low-level access to setting the keyboard layout. Not for use by normal applications." ],
|
||||
"INSTALL_PACKAGES" : [ "signatureOrSystem" , "directly install applications" , "Allows an application to install new or updated Android packages. Malicious applications can use this to add new applications with arbitrarily powerful permissions." ],
|
||||
"CLEAR_APP_USER_DATA" : [ "signature" , "delete other applications\' data" , "Allows an application to clear user data." ],
|
||||
"DELETE_CACHE_FILES" : [ "signatureOrSystem" , "delete other applications\' caches" , "Allows an application to delete cache files." ],
|
||||
"DELETE_PACKAGES" : [ "signatureOrSystem" , "delete applications" , "Allows an application to delete Android packages. Malicious applications can use this to delete important applications." ],
|
||||
"MOVE_PACKAGE" : [ "signatureOrSystem" , "Move application resources" , "Allows an application to move application resources from internal to external media and vice versa." ],
|
||||
"CHANGE_COMPONENT_ENABLED_STATE" : [ "signatureOrSystem" , "enable or disable application components" , "Allows an application to change whether or not a component of another application is enabled. Malicious applications can use this to disable important phone capabilities. It is important to be careful with permission, as it is possible to bring application components into an unusable, inconsistent or unstable state." ],
|
||||
"GRANT_REVOKE_PERMISSIONS" : [ "signature", "", "Allows an application to grant or revoke specific permissions." ],
|
||||
"ACCESS_SURFACE_FLINGER" : [ "signature" , "access SurfaceFlinger" , "Allows application to use SurfaceFlinger low-level features." ],
|
||||
"READ_FRAME_BUFFER" : [ "signatureOrSystem" , "read frame buffer" , "Allows application to read the content of the frame buffer." ],
|
||||
"CONFIGURE_WIFI_DISPLAY" : [ "signature", "", "Allows an application to configure and connect to Wifi displays" ],
|
||||
"CONTROL_WIFI_DISPLAY" : [ "signature", "", "Allows an application to control low-level features of Wifi displays such as opening an RTSP socket. This permission should only be used by the display manager." ],
|
||||
"BRICK" : [ "signature" , "permanently disable phone" , "Allows the application to disable the entire phone permanently. This is very dangerous." ],
|
||||
"REBOOT" : [ "signatureOrSystem" , "force phone reboot" , "Allows the application to force the phone to reboot." ],
|
||||
"DEVICE_POWER" : [ "signature" , "turn phone on or off" , "Allows the application to turn the phone on or off." ],
|
||||
"NET_TUNNELING" : [ "signature", "", "Allows low-level access to tun tap driver " ],
|
||||
"FACTORY_TEST" : [ "signature" , "run in factory test mode" , "Run as a low-level manufacturer test, allowing complete access to the phone hardware. Only available when a phone is running in manufacturer test mode." ],
|
||||
"MASTER_CLEAR" : [ "signatureOrSystem" , "reset system to factory defaults" , "Allows an application to completely reset the system to its factory settings, erasing all data, configuration and installed applications." ],
|
||||
"CALL_PRIVILEGED" : [ "signatureOrSystem" , "directly call any phone numbers" , "Allows the application to call any phone number, including emergency numbers, without your intervention. Malicious applications may place unnecessary and illegal calls to emergency services." ],
|
||||
"PERFORM_CDMA_PROVISIONING" : [ "signatureOrSystem" , "directly start CDMA phone setup" , "Allows the application to start CDMA provisioning. Malicious applications may start CDMA provisioning unnecessarily" ],
|
||||
"CONTROL_LOCATION_UPDATES" : [ "signatureOrSystem" , "control location update notifications" , "Allows enabling/disabling location update notifications from the radio. Not for use by normal applications." ],
|
||||
"ACCESS_CHECKIN_PROPERTIES" : [ "signatureOrSystem" , "access check-in properties" , "Allows read/write access to properties uploaded by the check-in service. Not for use by normal applications." ],
|
||||
"PACKAGE_USAGE_STATS" : [ "signatureOrSystem" , "update component usage statistics" , "Allows the modification of collected component usage statistics. Not for use by normal applications." ],
|
||||
"BACKUP" : [ "signatureOrSystem" , "control system back up and restore" , "Allows the application to control the system\'s back-up and restore mechanism. Not for use by normal applications." ],
|
||||
"CONFIRM_FULL_BACKUP" : [ "signature", "", "Allows a package to launch the secure full-backup confirmation UI. ONLY the system process may hold this permission." ],
|
||||
"BIND_REMOTEVIEWS" : [ "signatureOrSystem", "", "Must be required by a {@link android.widget.RemoteViewsService}, to ensure that only the system can bind to it." ],
|
||||
"ACCESS_CACHE_FILESYSTEM" : [ "signatureOrSystem" , "access the cache file system" , "Allows an application to read and write the cache file system." ],
|
||||
"COPY_PROTECTED_DATA" : [ "signature" , "Allows to invoke default container service to copy content. Not for use by normal applications." , "Allows to invoke default container service to copy content. Not for use by normal applications." ],
|
||||
"CRYPT_KEEPER" : [ "signatureOrSystem", "access to the encryption methods", "Internal permission protecting access to the encryption methods" ],
|
||||
"READ_NETWORK_USAGE_HISTORY" : [ "signatureOrSystem", "read historical network usage for specific networks and applications.", "Allows an application to read historical network usage for specific networks and applications."],
|
||||
"MANAGE_NETWORK_POLICY": [ "signature", "manage network policies and to define application-specific rules.", "Allows an application to manage network policies and to define application-specific rules."],
|
||||
"MODIFY_NETWORK_ACCOUNTING" : [ "signatureOrSystem", "account its network traffic against other UIDs.", "Allows an application to account its network traffic against other UIDs."],
|
||||
"C2D_MESSAGE" : [ "signature" , "C2DM permission." , "C2DM permission." ],
|
||||
"PACKAGE_VERIFICATION_AGENT" : [ "signatureOrSystem", "Package verifier needs to have this permission before the PackageManager will trust it to verify packages.", "Package verifier needs to have this permission before the PackageManager will trust it to verify packages."],
|
||||
"BIND_PACKAGE_VERIFIER" : [ "signature", "", "Must be required by package verifier receiver, to ensure that only the system can interact with it.."],
|
||||
"SERIAL_PORT" : [ "signature", "", "Allows applications to access serial ports via the SerialManager." ],
|
||||
"ACCESS_CONTENT_PROVIDERS_EXTERNALLY": [ "signature", "", "Allows the holder to access content providers from outside an ApplicationThread. This permission is enforced by the ActivityManagerService on the corresponding APIs,in particular ActivityManagerService#getContentProviderExternal(String) and ActivityManagerService#removeContentProviderExternal(String)."],
|
||||
"UPDATE_LOCK" : [ "signatureOrSystem", "", "Allows an application to hold an UpdateLock, recommending that a headless OTA reboot "\
|
||||
"*not* occur while the lock is held"],
|
||||
"WRITE_GSERVICES" : [ "signatureOrSystem" , "modify the Google services map" , "Allows an application to modify the Google services map. Not for use by normal applications." ],
|
||||
# No groups ...
|
||||
"SET_TIME": ["signatureOrSystem", "set time", "Allows an application to change the phone\'s clock time."],
|
||||
"ALLOW_ANY_CODEC_FOR_PLAYBACK": ["signatureOrSystem", "",
|
||||
"Allows an application to use any media decoder when decoding for playback."],
|
||||
"STATUS_BAR": ["signatureOrSystem", "disable or modify status bar",
|
||||
"Allows application to disable the status bar or add and remove system icons."],
|
||||
"STATUS_BAR_SERVICE": ["signature", "status bar", "Allows the application to be the status bar."],
|
||||
"FORCE_BACK": ["signature", "force application to close",
|
||||
"Allows an application to force any activity that is in the foreground to close and go back. Should never be needed for normal applications."],
|
||||
"UPDATE_DEVICE_STATS": ["signatureOrSystem", "modify battery statistics",
|
||||
"Allows the modification of collected battery statistics. Not for use by normal applications."],
|
||||
"INTERNAL_SYSTEM_WINDOW": ["signature", "display unauthorised windows",
|
||||
"Allows the creation of windows that are intended to be used by the internal system user interface. Not for use by normal applications."],
|
||||
"MANAGE_APP_TOKENS": ["signature", "manage application tokens",
|
||||
"Allows applications to create and manage their own tokens, bypassing their normal Z-ordering. Should never be needed for normal applications."],
|
||||
"FREEZE_SCREEN": ["signature", "",
|
||||
"Allows the application to temporarily freeze the screen for a full-screen transition."],
|
||||
"INJECT_EVENTS": ["signature", "inject user events",
|
||||
"Allows an application to inject user events (keys, touch, trackball) into the event stream and deliver them to ANY window. Without this permission, you can only deliver events to windows in your own process. Very few applications should need to use this permission"],
|
||||
"FILTER_EVENTS": ["signature", "",
|
||||
"Allows an application to register an input filter which filters the stream of user events (keys, touch, trackball) before they are dispatched to any window"],
|
||||
"RETRIEVE_WINDOW_INFO": ["signature", "",
|
||||
"Allows an application to retrieve info for a window from the window manager."],
|
||||
"TEMPORARY_ENABLE_ACCESSIBILITY": ["signature", "",
|
||||
"Allows an application to temporary enable accessibility on the device."],
|
||||
"MAGNIFY_DISPLAY": ["signature", "", "Allows an application to magnify the content of a display."],
|
||||
"SET_ACTIVITY_WATCHER": ["signature", "monitor and control all application launching",
|
||||
"Allows an application to monitor and control how the system launches activities. Malicious applications may compromise the system completely. This permission is needed only for development, never for normal phone usage."],
|
||||
"SHUTDOWN": ["signatureOrSystem", "partial shutdown",
|
||||
"Puts the activity manager into a shut-down state. Does not perform a complete shut down."],
|
||||
"STOP_APP_SWITCHES": ["signatureOrSystem", "prevent app switches",
|
||||
"Prevents the user from switching to another application."],
|
||||
"READ_INPUT_STATE": ["signature", "record what you type and actions that you take",
|
||||
"Allows applications to watch the keys that you press even when interacting with another application (such as entering a password). Should never be needed for normal applications."],
|
||||
"BIND_INPUT_METHOD": ["signature", "bind to an input method",
|
||||
"Allows the holder to bind to the top-level interface of an input method. Should never be needed for normal applications."],
|
||||
"BIND_ACCESSIBILITY_SERVICE": ["signature", "",
|
||||
"Must be required by an android.accessibilityservice.AccessibilityService to ensure that only the system can bind to it. "],
|
||||
"BIND_TEXT_SERVICE": ["signature", "",
|
||||
"Must be required by a TextService (e.g. SpellCheckerService) to ensure that only the system can bind to it."],
|
||||
"BIND_VPN_SERVICE": ["signature", "",
|
||||
"Must be required by an {@link android.net.VpnService}, to ensure that only the system can bind to it."],
|
||||
"BIND_WALLPAPER": ["signatureOrSystem", "bind to wallpaper",
|
||||
"Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications."],
|
||||
"BIND_DEVICE_ADMIN": ["signature", "interact with device admin",
|
||||
"Allows the holder to send intents to a device administrator. Should never be needed for normal applications."],
|
||||
"SET_ORIENTATION": ["signature", "change screen orientation",
|
||||
"Allows an application to change the rotation of the screen at any time. Should never be needed for normal applications."],
|
||||
"SET_POINTER_SPEED": ["signature", "",
|
||||
"Allows low-level access to setting the pointer speed. Not for use by normal applications. "],
|
||||
"SET_KEYBOARD_LAYOUT": ["signature", "",
|
||||
"Allows low-level access to setting the keyboard layout. Not for use by normal applications."],
|
||||
"INSTALL_PACKAGES": ["signatureOrSystem", "directly install applications",
|
||||
"Allows an application to install new or updated Android packages. Malicious applications can use this to add new applications with arbitrarily powerful permissions."],
|
||||
"CLEAR_APP_USER_DATA": ["signature", "delete other applications\' data",
|
||||
"Allows an application to clear user data."],
|
||||
"DELETE_CACHE_FILES": ["signatureOrSystem", "delete other applications\' caches",
|
||||
"Allows an application to delete cache files."],
|
||||
"DELETE_PACKAGES": ["signatureOrSystem", "delete applications",
|
||||
"Allows an application to delete Android packages. Malicious applications can use this to delete important applications."],
|
||||
"MOVE_PACKAGE": ["signatureOrSystem", "Move application resources",
|
||||
"Allows an application to move application resources from internal to external media and vice versa."],
|
||||
"CHANGE_COMPONENT_ENABLED_STATE": ["signatureOrSystem", "enable or disable application components",
|
||||
"Allows an application to change whether or not a component of another application is enabled. Malicious applications can use this to disable important phone capabilities. It is important to be careful with permission, as it is possible to bring application components into an unusable, inconsistent or unstable state."],
|
||||
"GRANT_REVOKE_PERMISSIONS": ["signature", "", "Allows an application to grant or revoke specific permissions."],
|
||||
"ACCESS_SURFACE_FLINGER": ["signature", "access SurfaceFlinger",
|
||||
"Allows application to use SurfaceFlinger low-level features."],
|
||||
"READ_FRAME_BUFFER": ["signatureOrSystem", "read frame buffer",
|
||||
"Allows application to read the content of the frame buffer."],
|
||||
"CONFIGURE_WIFI_DISPLAY": ["signature", "", "Allows an application to configure and connect to Wifi displays"],
|
||||
"CONTROL_WIFI_DISPLAY": ["signature", "",
|
||||
"Allows an application to control low-level features of Wifi displays such as opening an RTSP socket. This permission should only be used by the display manager."],
|
||||
"BRICK": ["signature", "permanently disable phone",
|
||||
"Allows the application to disable the entire phone permanently. This is very dangerous."],
|
||||
"REBOOT": ["signatureOrSystem", "force phone reboot", "Allows the application to force the phone to reboot."],
|
||||
"DEVICE_POWER": ["signature", "turn phone on or off", "Allows the application to turn the phone on or off."],
|
||||
"NET_TUNNELING": ["signature", "", "Allows low-level access to tun tap driver "],
|
||||
"FACTORY_TEST": ["signature", "run in factory test mode",
|
||||
"Run as a low-level manufacturer test, allowing complete access to the phone hardware. Only available when a phone is running in manufacturer test mode."],
|
||||
"MASTER_CLEAR": ["signatureOrSystem", "reset system to factory defaults",
|
||||
"Allows an application to completely reset the system to its factory settings, erasing all data, configuration and installed applications."],
|
||||
"CALL_PRIVILEGED": ["signatureOrSystem", "directly call any phone numbers",
|
||||
"Allows the application to call any phone number, including emergency numbers, without your intervention. Malicious applications may place unnecessary and illegal calls to emergency services."],
|
||||
"PERFORM_CDMA_PROVISIONING": ["signatureOrSystem", "directly start CDMA phone setup",
|
||||
"Allows the application to start CDMA provisioning. Malicious applications may start CDMA provisioning unnecessarily"],
|
||||
"CONTROL_LOCATION_UPDATES": ["signatureOrSystem", "control location update notifications",
|
||||
"Allows enabling/disabling location update notifications from the radio. Not for use by normal applications."],
|
||||
"ACCESS_CHECKIN_PROPERTIES": ["signatureOrSystem", "access check-in properties",
|
||||
"Allows read/write access to properties uploaded by the check-in service. Not for use by normal applications."],
|
||||
"PACKAGE_USAGE_STATS": ["signatureOrSystem", "update component usage statistics",
|
||||
"Allows the modification of collected component usage statistics. Not for use by normal applications."],
|
||||
"BACKUP": ["signatureOrSystem", "control system back up and restore",
|
||||
"Allows the application to control the system\'s back-up and restore mechanism. Not for use by normal applications."],
|
||||
"CONFIRM_FULL_BACKUP": ["signature", "",
|
||||
"Allows a package to launch the secure full-backup confirmation UI. ONLY the system process may hold this permission."],
|
||||
"BIND_REMOTEVIEWS": ["signatureOrSystem", "",
|
||||
"Must be required by a {@link android.widget.RemoteViewsService}, to ensure that only the system can bind to it."],
|
||||
"ACCESS_CACHE_FILESYSTEM": ["signatureOrSystem", "access the cache file system",
|
||||
"Allows an application to read and write the cache file system."],
|
||||
"COPY_PROTECTED_DATA": ["signature",
|
||||
"Allows to invoke default container service to copy content. Not for use by normal applications.",
|
||||
"Allows to invoke default container service to copy content. Not for use by normal applications."],
|
||||
"CRYPT_KEEPER": ["signatureOrSystem", "access to the encryption methods",
|
||||
"Internal permission protecting access to the encryption methods"],
|
||||
"READ_NETWORK_USAGE_HISTORY": ["signatureOrSystem",
|
||||
"read historical network usage for specific networks and applications.",
|
||||
"Allows an application to read historical network usage for specific networks and applications."],
|
||||
"MANAGE_NETWORK_POLICY": ["signature", "manage network policies and to define application-specific rules.",
|
||||
"Allows an application to manage network policies and to define application-specific rules."],
|
||||
"MODIFY_NETWORK_ACCOUNTING": ["signatureOrSystem", "account its network traffic against other UIDs.",
|
||||
"Allows an application to account its network traffic against other UIDs."],
|
||||
"C2D_MESSAGE": ["signature", "C2DM permission.", "C2DM permission."],
|
||||
"PACKAGE_VERIFICATION_AGENT": ["signatureOrSystem",
|
||||
"Package verifier needs to have this permission before the PackageManager will trust it to verify packages.",
|
||||
"Package verifier needs to have this permission before the PackageManager will trust it to verify packages."],
|
||||
"BIND_PACKAGE_VERIFIER": ["signature", "",
|
||||
"Must be required by package verifier receiver, to ensure that only the system can interact with it.."],
|
||||
"SERIAL_PORT": ["signature", "", "Allows applications to access serial ports via the SerialManager."],
|
||||
"ACCESS_CONTENT_PROVIDERS_EXTERNALLY": ["signature", "",
|
||||
"Allows the holder to access content providers from outside an ApplicationThread. This permission is enforced by the ActivityManagerService on the corresponding APIs,in particular ActivityManagerService#getContentProviderExternal(String) and ActivityManagerService#removeContentProviderExternal(String)."],
|
||||
"UPDATE_LOCK": ["signatureOrSystem", "",
|
||||
"Allows an application to hold an UpdateLock, recommending that a headless OTA reboot " \
|
||||
"*not* occur while the lock is held"],
|
||||
"WRITE_GSERVICES": ["signatureOrSystem", "modify the Google services map",
|
||||
"Allows an application to modify the Google services map. Not for use by normal applications."],
|
||||
|
||||
"ACCESS_USB" : [ "signatureOrSystem" , "access USB devices" , "Allows the application to access USB devices." ],
|
||||
"ACCESS_USB": ["signatureOrSystem", "access USB devices", "Allows the application to access USB devices."],
|
||||
},
|
||||
|
||||
"MANIFEST_PERMISSION_GROUP":
|
||||
{
|
||||
"ACCOUNTS": "Permissions for direct access to the accounts managed by the Account Manager.",
|
||||
"AFFECTS_BATTERY": "Used for permissions that provide direct access to the hardware on the device that has an effect on battery life. This includes vibrator, flashlight, etc.",
|
||||
"APP_INFO": "Group of permissions that are related to the other applications installed on the system.",
|
||||
"AUDIO_SETTINGS": "Used for permissions that provide direct access to speaker settings the device.",
|
||||
"BLUETOOTH_NETWORK": "Used for permissions that provide access to other devices through Bluetooth.",
|
||||
"BOOKMARKS": "Used for permissions that provide access to the user bookmarks and browser history.",
|
||||
"CALENDAR": "Used for permissions that provide access to the device calendar to create / view events",
|
||||
"CAMERA": "Used for permissions that are associated with accessing camera or capturing images/video from the device.",
|
||||
"COST_MONEY": "Used for permissions that can be used to make the user spend money without their direct involvement.",
|
||||
"DEVICE_ALARMS": "Used for permissions that provide access to the user voicemail box.",
|
||||
"DEVELOPMENT_TOOLS": "Group of permissions that are related to development features.",
|
||||
"DISPLAY": "Group of permissions that allow manipulation of how another application displays UI to the user.",
|
||||
"HARDWARE_CONTROLS": "Used for permissions that provide direct access to the hardware on the device.",
|
||||
"LOCATION": "Used for permissions that allow access to the user's current location.",
|
||||
"MESSAGES": "Used for permissions that allow an application to send messages on behalf of the user or intercept messages being received by the user.",
|
||||
"MICROPHONE": "Used for permissions that are associated with accessing microphone audio from the device. Note that phone calls also capture audio but are in a separate (more visible) permission group.",
|
||||
"NETWORK": "Used for permissions that provide access to networking services.",
|
||||
"PERSONAL_INFO": "Used for permissions that provide access to the user's private data, such as contacts, calendar events, e-mail messages, etc.",
|
||||
"PHONE_CALLS": "Used for permissions that are associated with accessing and modifyign telephony state: intercepting outgoing calls, reading and modifying the phone state.",
|
||||
"STORAGE": "Group of permissions that are related to SD card access.",
|
||||
"SOCIAL_INFO": "Used for permissions that provide access to the user's social connections, such as contacts, call logs, social stream, etc. This includes both reading and writing of this data (which should generally be expressed as two distinct permissions)",
|
||||
"SCREENLOCK": "Group of permissions that are related to the screenlock.",
|
||||
"STATUS_BAR": "Used for permissions that change the status bar.",
|
||||
"SYSTEM_CLOCK": "Group of permissions that are related to system clock.",
|
||||
"SYSTEM_TOOLS": "Group of permissions that are related to system APIs.",
|
||||
"SYNC_SETTINGS": "Used for permissions that access the sync settings or sync related information.",
|
||||
"USER_DICTIONARY": "Used for permissions that provide access to the user calendar to create / view events.",
|
||||
"VOICEMAIL": "Used for permissions that provide access to the user voicemail box.",
|
||||
"WALLPAPER": "Group of permissions that allow manipulation of how another application displays UI to the user.",
|
||||
"WRITE_USER_DICTIONARY": "Used for permissions that provide access to the user calendar to create / view events.",
|
||||
},
|
||||
"ACCOUNTS": "Permissions for direct access to the accounts managed by the Account Manager.",
|
||||
"AFFECTS_BATTERY": "Used for permissions that provide direct access to the hardware on the device that has an effect on battery life. This includes vibrator, flashlight, etc.",
|
||||
"APP_INFO": "Group of permissions that are related to the other applications installed on the system.",
|
||||
"AUDIO_SETTINGS": "Used for permissions that provide direct access to speaker settings the device.",
|
||||
"BLUETOOTH_NETWORK": "Used for permissions that provide access to other devices through Bluetooth.",
|
||||
"BOOKMARKS": "Used for permissions that provide access to the user bookmarks and browser history.",
|
||||
"CALENDAR": "Used for permissions that provide access to the device calendar to create / view events",
|
||||
"CAMERA": "Used for permissions that are associated with accessing camera or capturing images/video from the device.",
|
||||
"COST_MONEY": "Used for permissions that can be used to make the user spend money without their direct involvement.",
|
||||
"DEVICE_ALARMS": "Used for permissions that provide access to the user voicemail box.",
|
||||
"DEVELOPMENT_TOOLS": "Group of permissions that are related to development features.",
|
||||
"DISPLAY": "Group of permissions that allow manipulation of how another application displays UI to the user.",
|
||||
"HARDWARE_CONTROLS": "Used for permissions that provide direct access to the hardware on the device.",
|
||||
"LOCATION": "Used for permissions that allow access to the user's current location.",
|
||||
"MESSAGES": "Used for permissions that allow an application to send messages on behalf of the user or intercept messages being received by the user.",
|
||||
"MICROPHONE": "Used for permissions that are associated with accessing microphone audio from the device. Note that phone calls also capture audio but are in a separate (more visible) permission group.",
|
||||
"NETWORK": "Used for permissions that provide access to networking services.",
|
||||
"PERSONAL_INFO": "Used for permissions that provide access to the user's private data, such as contacts, calendar events, e-mail messages, etc.",
|
||||
"PHONE_CALLS": "Used for permissions that are associated with accessing and modifyign telephony state: intercepting outgoing calls, reading and modifying the phone state.",
|
||||
"STORAGE": "Group of permissions that are related to SD card access.",
|
||||
"SOCIAL_INFO": "Used for permissions that provide access to the user's social connections, such as contacts, call logs, social stream, etc. This includes both reading and writing of this data (which should generally be expressed as two distinct permissions)",
|
||||
"SCREENLOCK": "Group of permissions that are related to the screenlock.",
|
||||
"STATUS_BAR": "Used for permissions that change the status bar.",
|
||||
"SYSTEM_CLOCK": "Group of permissions that are related to system clock.",
|
||||
"SYSTEM_TOOLS": "Group of permissions that are related to system APIs.",
|
||||
"SYNC_SETTINGS": "Used for permissions that access the sync settings or sync related information.",
|
||||
"USER_DICTIONARY": "Used for permissions that provide access to the user calendar to create / view events.",
|
||||
"VOICEMAIL": "Used for permissions that provide access to the user voicemail box.",
|
||||
"WALLPAPER": "Group of permissions that allow manipulation of how another application displays UI to the user.",
|
||||
"WRITE_USER_DICTIONARY": "Used for permissions that provide access to the user calendar to create / view events.",
|
||||
},
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ class DexViewer(object):
|
||||
|
||||
def add_exception_node(self, exception, id_i):
|
||||
buff = ""
|
||||
# 9933FF
|
||||
# 9933FF
|
||||
height = 2
|
||||
width = 0
|
||||
label = ""
|
||||
@ -49,7 +49,7 @@ class DexViewer(object):
|
||||
width = max(len(c_label), width)
|
||||
height += 1
|
||||
|
||||
return self._create_node( id_i, height, width, "9333FF", label )
|
||||
return self._create_node(id_i, height, width, "9333FF", label)
|
||||
|
||||
def add_method_node(self, i, id_i):
|
||||
height = 0
|
||||
@ -62,7 +62,7 @@ class DexViewer(object):
|
||||
height = 3
|
||||
width = len(label)
|
||||
|
||||
return self._create_node( id_i, height, width, "FF0000", label )
|
||||
return self._create_node(id_i, height, width, "FF0000", label)
|
||||
|
||||
def add_node(self, i, id_i):
|
||||
height = 0
|
||||
@ -79,7 +79,7 @@ class DexViewer(object):
|
||||
if height < 10:
|
||||
height += 3
|
||||
|
||||
return self._create_node( id_i, height, width, "FFCC00", label )
|
||||
return self._create_node(id_i, height, width, "FFCC00", label)
|
||||
|
||||
def add_edge(self, i, id_i, j, id_j, l_eid, val):
|
||||
buff = "<edge id=\"%d\" source=\"%d\" target=\"%d\">\n" % (len(l_eid), id_i, id_j)
|
||||
@ -100,7 +100,7 @@ class DexViewer(object):
|
||||
|
||||
buff += "</edge>\n"
|
||||
|
||||
l_eid[ "%d+%d" % (id_i, id_j) ] = len(l_eid)
|
||||
l_eid["%d+%d" % (id_i, id_j)] = len(l_eid)
|
||||
return buff
|
||||
|
||||
def new_id(self, i, l):
|
||||
@ -136,7 +136,7 @@ class DexViewer(object):
|
||||
l_eid = {}
|
||||
|
||||
for method in _class.get_methods():
|
||||
mx = self.vmx.get_method( method )
|
||||
mx = self.vmx.get_method(method)
|
||||
exceptions = mx.exceptions
|
||||
|
||||
id_method = self.new_id(method, l_id)
|
||||
@ -146,7 +146,7 @@ class DexViewer(object):
|
||||
id_i = self.new_id(i, l_id)
|
||||
print(i, id_i, i.exception_analysis)
|
||||
|
||||
buff_nodes += self.add_node( i, id_i )
|
||||
buff_nodes += self.add_node(i, id_i)
|
||||
|
||||
# add childs nodes
|
||||
val = 0
|
||||
@ -169,18 +169,18 @@ class DexViewer(object):
|
||||
buff_nodes += self.add_exception_node(i.exception_analysis, id_exceptions)
|
||||
buff_edges += self.add_edge(None, id_exceptions, None, id_i, l_eid, 2)
|
||||
|
||||
buff_edges += self.add_edge(None, id_method, None, id_method+1, l_eid, 2)
|
||||
buff_edges += self.add_edge(None, id_method, None, id_method + 1, l_eid, 2)
|
||||
|
||||
buff += buff_nodes
|
||||
buff += buff_edges
|
||||
|
||||
|
||||
buff += "</graph>\n"
|
||||
buff += "</graphml>\n"
|
||||
|
||||
H[ name ] = buff
|
||||
H[name] = buff
|
||||
return H
|
||||
|
||||
|
||||
class Directory(object):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
@ -192,6 +192,7 @@ class Directory(object):
|
||||
def set_color(self, color):
|
||||
self.color = color
|
||||
|
||||
|
||||
class File(object):
|
||||
def __init__(self, name, file_type, file_crc):
|
||||
self.name = name
|
||||
@ -203,15 +204,17 @@ class File(object):
|
||||
|
||||
self.width = max(len(self.name), len(self.file_type))
|
||||
|
||||
|
||||
def splitall(path, z):
|
||||
if len(path) == 0:
|
||||
return
|
||||
|
||||
l = os.path.split( path )
|
||||
l = os.path.split(path)
|
||||
z.append(l[0])
|
||||
|
||||
for i in l:
|
||||
return splitall( i, z )
|
||||
return splitall(i, z)
|
||||
|
||||
|
||||
class ApkViewer(object):
|
||||
def __init__(self, a):
|
||||
@ -221,38 +224,37 @@ class ApkViewer(object):
|
||||
self.all_files = {}
|
||||
self.ids = {}
|
||||
|
||||
root = Directory( "APK" )
|
||||
root.set_color( "00FF00" )
|
||||
root = Directory("APK")
|
||||
root.set_color("00FF00")
|
||||
|
||||
self.ids[ root ] = len(self.ids)
|
||||
self.G.add_node( root )
|
||||
self.ids[root] = len(self.ids)
|
||||
self.G.add_node(root)
|
||||
|
||||
for x, y, z in self.a.get_files_information():
|
||||
print(x, y, z, os.path.basename(x))
|
||||
|
||||
l = []
|
||||
splitall( x, l )
|
||||
splitall(x, l)
|
||||
l.reverse()
|
||||
l.pop(0)
|
||||
|
||||
|
||||
last = root
|
||||
for i in l:
|
||||
if i not in self.all_files:
|
||||
tmp = Directory( i )
|
||||
self.ids[ tmp ] = len(self.ids)
|
||||
self.all_files[ i ] = tmp
|
||||
tmp = Directory(i)
|
||||
self.ids[tmp] = len(self.ids)
|
||||
self.all_files[i] = tmp
|
||||
else:
|
||||
tmp = self.all_files[ i ]
|
||||
tmp = self.all_files[i]
|
||||
|
||||
self.G.add_edge(last, tmp)
|
||||
last = tmp
|
||||
|
||||
n1 = last
|
||||
n2 = File( x, y, z )
|
||||
n2 = File(x, y, z)
|
||||
self.G.add_edge(n1, n2)
|
||||
|
||||
self.ids[ n2 ] = len(self.ids)
|
||||
self.ids[n2] = len(self.ids)
|
||||
|
||||
def export_to_gml(self):
|
||||
buff = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
|
||||
@ -261,10 +263,8 @@ class ApkViewer(object):
|
||||
buff += "<key attr.name=\"description\" attr.type=\"string\" for=\"node\" id=\"d5\"/>\n"
|
||||
buff += "<key for=\"node\" id=\"d6\" yfiles.type=\"nodegraphics\"/>\n"
|
||||
|
||||
|
||||
buff += "<graph edgedefault=\"directed\" id=\"G\">\n"
|
||||
|
||||
|
||||
for node in self.G.nodes():
|
||||
print(node)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -90,6 +90,7 @@ def var_decl(typen, var):
|
||||
def dummy(*args):
|
||||
return ['Dummy', args]
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
@ -142,6 +143,7 @@ def _append(sb, stmt):
|
||||
if stmt is not None:
|
||||
sb[2].append(stmt)
|
||||
|
||||
|
||||
################################################################################
|
||||
TYPE_DESCRIPTOR = {
|
||||
'V': 'void',
|
||||
@ -449,7 +451,6 @@ def visit_ins(op, isCtor=False):
|
||||
|
||||
|
||||
class JSONWriter(object):
|
||||
|
||||
def __init__(self, graph, method):
|
||||
self.graph = graph
|
||||
self.method = method
|
||||
@ -624,8 +625,8 @@ class JSONWriter(object):
|
||||
|
||||
self.add(if_stmt(cond_expr, scopes))
|
||||
elif follow is not None:
|
||||
if cond.true in (follow, self.next_case) or\
|
||||
cond.num > cond.true.num:
|
||||
if cond.true in (follow, self.next_case) or \
|
||||
cond.num > cond.true.num:
|
||||
# or cond.true.num > cond.false.num:
|
||||
cond.neg()
|
||||
cond.true, cond.false = cond.false, cond.true
|
||||
|
@ -29,7 +29,6 @@ logger = logging.getLogger('dad.basic_blocks')
|
||||
|
||||
|
||||
class BasicBlock(Node):
|
||||
|
||||
def __init__(self, name, block_ins):
|
||||
super(BasicBlock, self).__init__(name)
|
||||
self.ins = block_ins
|
||||
@ -68,7 +67,6 @@ class BasicBlock(Node):
|
||||
|
||||
|
||||
class StatementBlock(BasicBlock):
|
||||
|
||||
def __init__(self, name, block_ins):
|
||||
super(StatementBlock, self).__init__(name, block_ins)
|
||||
self.type.is_stmt = True
|
||||
@ -81,7 +79,6 @@ class StatementBlock(BasicBlock):
|
||||
|
||||
|
||||
class ReturnBlock(BasicBlock):
|
||||
|
||||
def __init__(self, name, block_ins):
|
||||
super(ReturnBlock, self).__init__(name, block_ins)
|
||||
self.type.is_return = True
|
||||
@ -94,7 +91,6 @@ class ReturnBlock(BasicBlock):
|
||||
|
||||
|
||||
class ThrowBlock(BasicBlock):
|
||||
|
||||
def __init__(self, name, block_ins):
|
||||
super(ThrowBlock, self).__init__(name, block_ins)
|
||||
self.type.is_throw = True
|
||||
@ -107,7 +103,6 @@ class ThrowBlock(BasicBlock):
|
||||
|
||||
|
||||
class SwitchBlock(BasicBlock):
|
||||
|
||||
def __init__(self, name, switch, block_ins):
|
||||
super(SwitchBlock, self).__init__(name, block_ins)
|
||||
self.switch = switch
|
||||
@ -146,7 +141,6 @@ class SwitchBlock(BasicBlock):
|
||||
|
||||
|
||||
class CondBlock(BasicBlock):
|
||||
|
||||
def __init__(self, name, block_ins):
|
||||
super(CondBlock, self).__init__(name, block_ins)
|
||||
self.true = None
|
||||
@ -176,7 +170,6 @@ class CondBlock(BasicBlock):
|
||||
|
||||
|
||||
class Condition(object):
|
||||
|
||||
def __init__(self, cond1, cond2, isand, isnot):
|
||||
self.cond1 = cond1
|
||||
self.cond2 = cond2
|
||||
@ -213,7 +206,6 @@ class Condition(object):
|
||||
|
||||
|
||||
class ShortCircuitBlock(CondBlock):
|
||||
|
||||
def __init__(self, name, cond):
|
||||
super(ShortCircuitBlock, self).__init__(name, None)
|
||||
self.cond = cond
|
||||
@ -235,7 +227,6 @@ class ShortCircuitBlock(CondBlock):
|
||||
|
||||
|
||||
class LoopBlock(CondBlock):
|
||||
|
||||
def __init__(self, name, cond):
|
||||
super(LoopBlock, self).__init__(name, None)
|
||||
self.cond = cond
|
||||
@ -272,7 +263,6 @@ class LoopBlock(CondBlock):
|
||||
|
||||
|
||||
class TryBlock(BasicBlock):
|
||||
|
||||
def __init__(self, node):
|
||||
super(TryBlock, self).__init__('Try-%s' % node.name, None)
|
||||
self.try_start = node
|
||||
@ -298,7 +288,6 @@ class TryBlock(BasicBlock):
|
||||
|
||||
|
||||
class CatchBlock(BasicBlock):
|
||||
|
||||
def __init__(self, node):
|
||||
first_ins = node.ins[0]
|
||||
self.exception_ins = None
|
||||
|
@ -54,7 +54,7 @@ def intervals(graph):
|
||||
change = False
|
||||
for node in graph.rpo[1:]:
|
||||
if all(
|
||||
p in interv_heads[head] for p in graph.all_preds(node)):
|
||||
p in interv_heads[head] for p in graph.all_preds(node)):
|
||||
change |= interv_heads[head].add_node(node)
|
||||
|
||||
# At this stage, a node which is not in the interval, but has one
|
||||
@ -63,7 +63,7 @@ def intervals(graph):
|
||||
for node in graph:
|
||||
if node not in interv_heads[head] and node not in heads:
|
||||
if any(
|
||||
p in interv_heads[head] for p in graph.all_preds(node)):
|
||||
p in interv_heads[head] for p in graph.all_preds(node)):
|
||||
edges[interv_heads[head]].append(node)
|
||||
assert (node not in heads)
|
||||
heads.append(node)
|
||||
@ -165,11 +165,11 @@ def loop_follow(start, end, nodes_in_loop):
|
||||
for node in nodes_in_loop:
|
||||
if node.type.is_cond:
|
||||
if (node.true.num < num_next and
|
||||
node.true not in nodes_in_loop):
|
||||
node.true not in nodes_in_loop):
|
||||
follow = node.true
|
||||
num_next = follow.num
|
||||
elif (node.false.num < num_next and
|
||||
node.false not in nodes_in_loop):
|
||||
node.false not in nodes_in_loop):
|
||||
follow = node.false
|
||||
num_next = follow.num
|
||||
start.follow['loop'] = follow
|
||||
@ -239,7 +239,6 @@ def switch_struct(graph, idoms):
|
||||
|
||||
# TODO: deal with preds which are in catch
|
||||
def short_circuit_struct(graph, idom, node_map):
|
||||
|
||||
def MergeNodes(node1, node2, is_and, is_not):
|
||||
lpreds = set()
|
||||
ldests = set()
|
||||
|
@ -27,7 +27,6 @@ logger = logging.getLogger('dad.control_flow')
|
||||
|
||||
|
||||
class BasicReachDef(object):
|
||||
|
||||
def __init__(self, graph, params):
|
||||
self.g = graph
|
||||
self.A = defaultdict(set)
|
||||
@ -313,7 +312,6 @@ def register_propagation(graph, du, ud):
|
||||
|
||||
|
||||
class DummyNode(Node):
|
||||
|
||||
def __init__(self, name):
|
||||
super(DummyNode, self).__init__(name)
|
||||
|
||||
@ -465,7 +463,7 @@ def place_declarations(graph, dvars, du, ud):
|
||||
for loc, ins in node.get_loc_with_ins():
|
||||
for var in ins.get_used_vars():
|
||||
if (not isinstance(dvars[var], Variable) or
|
||||
isinstance(dvars[var], Param)):
|
||||
isinstance(dvars[var], Param)):
|
||||
continue
|
||||
var_defs_locs = ud[var, loc]
|
||||
def_nodes = set()
|
||||
|
@ -23,6 +23,7 @@ from builtins import str
|
||||
from builtins import range
|
||||
from builtins import object
|
||||
import sys
|
||||
|
||||
sys.path.append('./')
|
||||
|
||||
import logging
|
||||
@ -82,7 +83,6 @@ def get_field_ast(field):
|
||||
|
||||
|
||||
class DvMethod(object):
|
||||
|
||||
def __init__(self, methanalysis):
|
||||
method = methanalysis.get_method()
|
||||
self.method = method
|
||||
@ -122,7 +122,7 @@ class DvMethod(object):
|
||||
if not __debug__:
|
||||
from androguard.core import bytecode
|
||||
bytecode.method2png('/tmp/dad/graphs/%s#%s.png' % \
|
||||
(self.cls_name.split('/')[-1][:-1], self.name), methanalysis)
|
||||
(self.cls_name.split('/')[-1][:-1], self.name), methanalysis)
|
||||
|
||||
def process(self, doAST=False):
|
||||
logger.debug('METHOD : %s', self.name)
|
||||
@ -194,12 +194,11 @@ class DvMethod(object):
|
||||
return []
|
||||
|
||||
def __repr__(self):
|
||||
#return 'Method %s' % self.name
|
||||
# return 'Method %s' % self.name
|
||||
return 'class DvMethod(object): %s' % self.name
|
||||
|
||||
|
||||
class DvClass(object):
|
||||
|
||||
def __init__(self, dvclass, vma):
|
||||
name = dvclass.get_name()
|
||||
if name.find('/') > 0:
|
||||
@ -270,8 +269,8 @@ class DvClass(object):
|
||||
fields = [get_field_ast(f) for f in self.fields]
|
||||
methods = []
|
||||
for m in self.methods:
|
||||
if isinstance(m, DvMethod) and m.ast:
|
||||
methods.append(m.get_ast())
|
||||
if isinstance(m, DvMethod) and m.ast:
|
||||
methods.append(m.get_ast())
|
||||
isInterface = 'interface' in self.access
|
||||
return {
|
||||
'rawname': self.thisclass[1:-1],
|
||||
@ -338,7 +337,7 @@ class DvClass(object):
|
||||
source.append(
|
||||
('PACKAGE', [('PACKAGE_START', 'package '), (
|
||||
'NAME_PACKAGE', '%s' % self.package), ('PACKAGE_END', ';\n')
|
||||
]))
|
||||
]))
|
||||
list_proto = []
|
||||
list_proto.append(
|
||||
('PROTOTYPE_ACCESS', '%s class ' % ' '.join(self.access)))
|
||||
@ -391,14 +390,14 @@ class DvClass(object):
|
||||
source.append(
|
||||
('FIELD', [('FIELD_ACCESS', access_str), (
|
||||
'FIELD_TYPE', '%s' % f_type), ('SPACE', ' '), (
|
||||
'NAME_FIELD', '%s' % name, f_type, field), ('FIELD_VALUE', value), ('FIELD_END',
|
||||
';\n')]))
|
||||
'NAME_FIELD', '%s' % name, f_type, field), ('FIELD_VALUE', value), ('FIELD_END',
|
||||
';\n')]))
|
||||
else:
|
||||
source.append(
|
||||
('FIELD', [('FIELD_ACCESS', access_str), (
|
||||
'FIELD_TYPE', '%s' % f_type), ('SPACE', ' '), (
|
||||
'NAME_FIELD', '%s' % name, f_type, field), ('FIELD_END',
|
||||
';\n')]))
|
||||
'NAME_FIELD', '%s' % name, f_type, field), ('FIELD_END',
|
||||
';\n')]))
|
||||
|
||||
for method in self.methods:
|
||||
if isinstance(method, DvMethod):
|
||||
@ -414,7 +413,6 @@ class DvClass(object):
|
||||
|
||||
|
||||
class DvMachine(object):
|
||||
|
||||
def __init__(self, name):
|
||||
vm = auto_vm(name)
|
||||
if vm is None:
|
||||
@ -422,7 +420,7 @@ class DvMachine(object):
|
||||
self.vma = analysis.Analysis(vm)
|
||||
self.classes = dict((dvclass.get_name(), dvclass)
|
||||
for dvclass in vm.get_classes())
|
||||
#util.merge_inner(self.classes)
|
||||
# util.merge_inner(self.classes)
|
||||
|
||||
def get_classes(self):
|
||||
return list(self.classes.keys())
|
||||
|
@ -30,7 +30,6 @@ logger = logging.getLogger('dad.graph')
|
||||
|
||||
|
||||
class Graph(object):
|
||||
|
||||
def __init__(self):
|
||||
self.entry = None
|
||||
self.exit = None
|
||||
@ -289,8 +288,8 @@ def simplify(graph):
|
||||
graph.entry = suc
|
||||
graph.remove_node(node)
|
||||
elif (suc.type.is_stmt and len(graph.all_preds(suc)) == 1 and
|
||||
not (suc in graph.catch_edges) and not (
|
||||
(node is suc) or (suc is graph.entry))):
|
||||
not (suc in graph.catch_edges) and not (
|
||||
(node is suc) or (suc is graph.entry))):
|
||||
ins_to_merge = suc.get_ins()
|
||||
node.add_ins(ins_to_merge)
|
||||
for var in suc.var_to_declare:
|
||||
@ -389,7 +388,6 @@ def bfs(start):
|
||||
|
||||
|
||||
class GenInvokeRetName(object):
|
||||
|
||||
def __init__(self):
|
||||
self.num = 0
|
||||
self.ret = None
|
||||
|
@ -20,7 +20,6 @@ import androguard.decompiler.dad.util as util
|
||||
|
||||
|
||||
class IRForm(object):
|
||||
|
||||
def __init__(self):
|
||||
self.var_map = {}
|
||||
self.type = None
|
||||
@ -75,7 +74,6 @@ class IRForm(object):
|
||||
|
||||
|
||||
class Constant(IRForm):
|
||||
|
||||
def __init__(self, value, atype, int_value=None, descriptor=None):
|
||||
self.v = 'c%s' % value
|
||||
self.cst = value
|
||||
@ -117,7 +115,6 @@ class Constant(IRForm):
|
||||
|
||||
|
||||
class BaseClass(IRForm):
|
||||
|
||||
def __init__(self, name, descriptor=None):
|
||||
self.v = 'c%s' % name
|
||||
self.cls = name
|
||||
@ -135,7 +132,6 @@ class BaseClass(IRForm):
|
||||
|
||||
|
||||
class Variable(IRForm):
|
||||
|
||||
def __init__(self, value):
|
||||
self.v = value
|
||||
self.declared = False
|
||||
@ -162,7 +158,6 @@ class Variable(IRForm):
|
||||
|
||||
|
||||
class Param(Variable):
|
||||
|
||||
def __init__(self, value, atype):
|
||||
super(Param, self).__init__(value)
|
||||
self.declared = True
|
||||
@ -180,7 +175,6 @@ class Param(Variable):
|
||||
|
||||
|
||||
class ThisParam(Param):
|
||||
|
||||
def __init__(self, value, atype):
|
||||
super(ThisParam, self).__init__(value, atype)
|
||||
self.this = True
|
||||
@ -188,7 +182,7 @@ class ThisParam(Param):
|
||||
|
||||
def visit(self, visitor):
|
||||
if self.super:
|
||||
return visitor.visit_super()
|
||||
return visitor.visit_super()
|
||||
return visitor.visit_this()
|
||||
|
||||
def __str__(self):
|
||||
@ -196,7 +190,6 @@ class ThisParam(Param):
|
||||
|
||||
|
||||
class AssignExpression(IRForm):
|
||||
|
||||
def __init__(self, lhs, rhs):
|
||||
super(AssignExpression, self).__init__()
|
||||
if lhs:
|
||||
@ -246,7 +239,6 @@ class AssignExpression(IRForm):
|
||||
|
||||
|
||||
class MoveExpression(IRForm):
|
||||
|
||||
def __init__(self, lhs, rhs):
|
||||
super(MoveExpression, self).__init__()
|
||||
self.lhs = lhs.v
|
||||
@ -303,7 +295,6 @@ class MoveExpression(IRForm):
|
||||
|
||||
|
||||
class MoveResultExpression(MoveExpression):
|
||||
|
||||
def __init__(self, lhs, rhs):
|
||||
super(MoveResultExpression, self).__init__(lhs, rhs)
|
||||
|
||||
@ -323,7 +314,6 @@ class MoveResultExpression(MoveExpression):
|
||||
|
||||
|
||||
class ArrayStoreInstruction(IRForm):
|
||||
|
||||
def __init__(self, rhs, array, index, _type):
|
||||
super(ArrayStoreInstruction, self).__init__()
|
||||
self.rhs = rhs.v
|
||||
@ -387,7 +377,6 @@ class ArrayStoreInstruction(IRForm):
|
||||
|
||||
|
||||
class StaticInstruction(IRForm):
|
||||
|
||||
def __init__(self, rhs, klass, ftype, name):
|
||||
super(StaticInstruction, self).__init__()
|
||||
self.rhs = rhs.v
|
||||
@ -433,7 +422,6 @@ class StaticInstruction(IRForm):
|
||||
|
||||
|
||||
class InstanceInstruction(IRForm):
|
||||
|
||||
def __init__(self, rhs, lhs, klass, atype, name):
|
||||
super(InstanceInstruction, self).__init__()
|
||||
self.lhs = lhs.v
|
||||
@ -499,7 +487,6 @@ class InstanceInstruction(IRForm):
|
||||
|
||||
|
||||
class NewInstance(IRForm):
|
||||
|
||||
def __init__(self, ins_type):
|
||||
super(NewInstance, self).__init__()
|
||||
self.type = ins_type
|
||||
@ -521,7 +508,6 @@ class NewInstance(IRForm):
|
||||
|
||||
|
||||
class InvokeInstruction(IRForm):
|
||||
|
||||
def __init__(self, clsname, name, base, rtype, ptype, args, triple):
|
||||
super(InvokeInstruction, self).__init__()
|
||||
self.cls = clsname
|
||||
@ -611,7 +597,6 @@ class InvokeInstruction(IRForm):
|
||||
|
||||
|
||||
class InvokeRangeInstruction(InvokeInstruction):
|
||||
|
||||
def __init__(self, clsname, name, rtype, ptype, args, triple):
|
||||
base = args.pop(0)
|
||||
super(InvokeRangeInstruction, self).__init__(clsname, name, base, rtype,
|
||||
@ -619,14 +604,12 @@ class InvokeRangeInstruction(InvokeInstruction):
|
||||
|
||||
|
||||
class InvokeDirectInstruction(InvokeInstruction):
|
||||
|
||||
def __init__(self, clsname, name, base, rtype, ptype, args, triple):
|
||||
super(InvokeDirectInstruction, self).__init__(
|
||||
clsname, name, base, rtype, ptype, args, triple)
|
||||
|
||||
|
||||
class InvokeStaticInstruction(InvokeInstruction):
|
||||
|
||||
def __init__(self, clsname, name, base, rtype, ptype, args, triple):
|
||||
super(InvokeStaticInstruction, self).__init__(
|
||||
clsname, name, base, rtype, ptype, args, triple)
|
||||
@ -640,7 +623,6 @@ class InvokeStaticInstruction(InvokeInstruction):
|
||||
|
||||
|
||||
class ReturnInstruction(IRForm):
|
||||
|
||||
def __init__(self, arg):
|
||||
super(ReturnInstruction, self).__init__()
|
||||
self.arg = arg
|
||||
@ -686,7 +668,6 @@ class ReturnInstruction(IRForm):
|
||||
|
||||
|
||||
class NopExpression(IRForm):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@ -701,7 +682,6 @@ class NopExpression(IRForm):
|
||||
|
||||
|
||||
class SwitchExpression(IRForm):
|
||||
|
||||
def __init__(self, src, branch):
|
||||
super(SwitchExpression, self).__init__()
|
||||
self.src = src.v
|
||||
@ -736,7 +716,6 @@ class SwitchExpression(IRForm):
|
||||
|
||||
|
||||
class CheckCastExpression(IRForm):
|
||||
|
||||
def __init__(self, arg, _type, descriptor=None):
|
||||
super(CheckCastExpression, self).__init__()
|
||||
self.arg = arg.v
|
||||
@ -777,13 +756,11 @@ class CheckCastExpression(IRForm):
|
||||
|
||||
|
||||
class ArrayExpression(IRForm):
|
||||
|
||||
def __init__(self):
|
||||
super(ArrayExpression, self).__init__()
|
||||
|
||||
|
||||
class ArrayLoadExpression(ArrayExpression):
|
||||
|
||||
def __init__(self, arg, index, _type):
|
||||
super(ArrayLoadExpression, self).__init__()
|
||||
self.array = arg.v
|
||||
@ -839,7 +816,6 @@ class ArrayLoadExpression(ArrayExpression):
|
||||
|
||||
|
||||
class ArrayLengthExpression(ArrayExpression):
|
||||
|
||||
def __init__(self, array):
|
||||
super(ArrayLengthExpression, self).__init__()
|
||||
self.array = array.v
|
||||
@ -876,7 +852,6 @@ class ArrayLengthExpression(ArrayExpression):
|
||||
|
||||
|
||||
class NewArrayExpression(ArrayExpression):
|
||||
|
||||
def __init__(self, asize, atype):
|
||||
super(NewArrayExpression, self).__init__()
|
||||
self.size = asize.v
|
||||
@ -914,7 +889,6 @@ class NewArrayExpression(ArrayExpression):
|
||||
|
||||
|
||||
class FilledArrayExpression(ArrayExpression):
|
||||
|
||||
def __init__(self, asize, atype, args):
|
||||
super(FilledArrayExpression, self).__init__()
|
||||
self.size = asize
|
||||
@ -972,7 +946,6 @@ class FilledArrayExpression(ArrayExpression):
|
||||
|
||||
|
||||
class FillArrayExpression(ArrayExpression):
|
||||
|
||||
def __init__(self, reg, value):
|
||||
super(FillArrayExpression, self).__init__()
|
||||
self.reg = reg.v
|
||||
@ -1010,7 +983,6 @@ class FillArrayExpression(ArrayExpression):
|
||||
|
||||
|
||||
class RefExpression(IRForm):
|
||||
|
||||
def __init__(self, ref):
|
||||
super(RefExpression, self).__init__()
|
||||
self.ref = ref.v
|
||||
@ -1041,7 +1013,6 @@ class RefExpression(IRForm):
|
||||
|
||||
|
||||
class MoveExceptionExpression(RefExpression):
|
||||
|
||||
def __init__(self, ref, _type):
|
||||
super(MoveExceptionExpression, self).__init__(ref)
|
||||
self.type = _type
|
||||
@ -1069,7 +1040,6 @@ class MoveExceptionExpression(RefExpression):
|
||||
|
||||
|
||||
class MonitorEnterExpression(RefExpression):
|
||||
|
||||
def __init__(self, ref):
|
||||
super(MonitorEnterExpression, self).__init__(ref)
|
||||
|
||||
@ -1078,7 +1048,6 @@ class MonitorEnterExpression(RefExpression):
|
||||
|
||||
|
||||
class MonitorExitExpression(RefExpression):
|
||||
|
||||
def __init__(self, ref):
|
||||
super(MonitorExitExpression, self).__init__(ref)
|
||||
|
||||
@ -1087,7 +1056,6 @@ class MonitorExitExpression(RefExpression):
|
||||
|
||||
|
||||
class ThrowExpression(RefExpression):
|
||||
|
||||
def __init__(self, ref):
|
||||
super(ThrowExpression, self).__init__(ref)
|
||||
|
||||
@ -1099,7 +1067,6 @@ class ThrowExpression(RefExpression):
|
||||
|
||||
|
||||
class BinaryExpression(IRForm):
|
||||
|
||||
def __init__(self, op, arg1, arg2, _type):
|
||||
super(BinaryExpression, self).__init__()
|
||||
self.op = op
|
||||
@ -1158,7 +1125,6 @@ class BinaryExpression(IRForm):
|
||||
|
||||
|
||||
class BinaryCompExpression(BinaryExpression):
|
||||
|
||||
def __init__(self, op, arg1, arg2, _type):
|
||||
super(BinaryCompExpression, self).__init__(op, arg1, arg2, _type)
|
||||
|
||||
@ -1169,19 +1135,16 @@ class BinaryCompExpression(BinaryExpression):
|
||||
|
||||
|
||||
class BinaryExpression2Addr(BinaryExpression):
|
||||
|
||||
def __init__(self, op, dest, arg, _type):
|
||||
super(BinaryExpression2Addr, self).__init__(op, dest, arg, _type)
|
||||
|
||||
|
||||
class BinaryExpressionLit(BinaryExpression):
|
||||
|
||||
def __init__(self, op, arg1, arg2):
|
||||
super(BinaryExpressionLit, self).__init__(op, arg1, arg2, 'I')
|
||||
|
||||
|
||||
class UnaryExpression(IRForm):
|
||||
|
||||
def __init__(self, op, arg, _type):
|
||||
super(UnaryExpression, self).__init__()
|
||||
self.op = op
|
||||
@ -1220,7 +1183,6 @@ class UnaryExpression(IRForm):
|
||||
|
||||
|
||||
class CastExpression(UnaryExpression):
|
||||
|
||||
def __init__(self, op, atype, arg):
|
||||
super(CastExpression, self).__init__(op, arg, atype)
|
||||
self.clsdesc = atype
|
||||
@ -1241,11 +1203,10 @@ class CastExpression(UnaryExpression):
|
||||
return 'CAST_%s(%s)' % (self.op, self.var_map[self.arg])
|
||||
|
||||
|
||||
CONDS = {'==': '!=', '!=': '==', '<': '>=', '<=': '>', '>=': '<', '>': '<=',}
|
||||
CONDS = {'==': '!=', '!=': '==', '<': '>=', '<=': '>', '>=': '<', '>': '<=', }
|
||||
|
||||
|
||||
class ConditionalExpression(IRForm):
|
||||
|
||||
def __init__(self, op, arg1, arg2):
|
||||
super(ConditionalExpression, self).__init__()
|
||||
self.op = op
|
||||
@ -1307,7 +1268,6 @@ class ConditionalExpression(IRForm):
|
||||
|
||||
|
||||
class ConditionalZExpression(IRForm):
|
||||
|
||||
def __init__(self, op, arg):
|
||||
super(ConditionalZExpression, self).__init__()
|
||||
self.op = op
|
||||
@ -1351,7 +1311,6 @@ class ConditionalZExpression(IRForm):
|
||||
|
||||
|
||||
class InstanceExpression(IRForm):
|
||||
|
||||
def __init__(self, arg, klass, ftype, name):
|
||||
super(InstanceExpression, self).__init__()
|
||||
self.arg = arg.v
|
||||
@ -1396,7 +1355,6 @@ class InstanceExpression(IRForm):
|
||||
|
||||
|
||||
class StaticExpression(IRForm):
|
||||
|
||||
def __init__(self, cls_name, field_type, field_name):
|
||||
super(StaticExpression, self).__init__()
|
||||
self.cls = util.get_type(cls_name)
|
||||
|
@ -18,8 +18,9 @@
|
||||
|
||||
from builtins import object
|
||||
from future.utils import with_metaclass
|
||||
class MakeProperties(type):
|
||||
|
||||
|
||||
class MakeProperties(type):
|
||||
def __init__(cls, name, bases, dct):
|
||||
|
||||
def _wrap_set(names, name):
|
||||
@ -82,7 +83,6 @@ class NodeType(with_metaclass(MakeProperties, object)):
|
||||
|
||||
|
||||
class Node(object):
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.num = 0
|
||||
@ -123,7 +123,6 @@ class Node(object):
|
||||
|
||||
|
||||
class Interval(object):
|
||||
|
||||
def __init__(self, head):
|
||||
self.name = 'Interval-%s' % head.name
|
||||
self.content = set([head])
|
||||
|
@ -543,7 +543,7 @@ def iflez(ins, vmap):
|
||||
return ConditionalZExpression(Op.LEQUAL, get_variables(vmap, ins.AA))
|
||||
|
||||
|
||||
#TODO: check type for all aget
|
||||
# TODO: check type for all aget
|
||||
# aget vAA, vBB, vCC ( 8b, 8b, 8b )
|
||||
def aget(ins, vmap):
|
||||
logger.debug('AGet : %s', ins.get_output())
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""Tests for def_use."""
|
||||
|
||||
import sys
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import collections
|
||||
@ -14,7 +15,6 @@ from androguard.decompiler.dad import basic_blocks
|
||||
|
||||
|
||||
class DataflowTest(unittest.TestCase):
|
||||
|
||||
def assertItemsEqual(self, a, b):
|
||||
"""
|
||||
This method was renamed in python3.
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""Tests for graph."""
|
||||
|
||||
import sys
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import unittest
|
||||
@ -9,7 +10,6 @@ from androguard.decompiler.dad import node
|
||||
|
||||
|
||||
class DominatorTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.graph = graph.Graph()
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""Tests for rpo."""
|
||||
|
||||
import sys
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import unittest
|
||||
@ -9,7 +10,6 @@ from androguard.decompiler.dad import node
|
||||
|
||||
|
||||
class NodeTest(node.Node):
|
||||
|
||||
def __init__(self, name):
|
||||
super(NodeTest, self).__init__(name)
|
||||
|
||||
@ -18,7 +18,6 @@ class NodeTest(node.Node):
|
||||
|
||||
|
||||
class RpoTest(unittest.TestCase):
|
||||
|
||||
def _getNode(self, node_map, n):
|
||||
ret_node = node_map.get(n)
|
||||
if not ret_node:
|
||||
@ -67,7 +66,7 @@ class RpoTest(unittest.TestCase):
|
||||
}
|
||||
n_map = self._createGraphFrom(edges)
|
||||
self.graph.compute_rpo()
|
||||
#self.graph.draw('_testTarjan_graph', '/tmp')
|
||||
# self.graph.draw('_testTarjan_graph', '/tmp')
|
||||
expected_rpo = {
|
||||
'r': 1,
|
||||
'a': 7,
|
||||
@ -111,7 +110,7 @@ class RpoTest(unittest.TestCase):
|
||||
}
|
||||
n_map = self._createGraphFrom(edges)
|
||||
self.graph.compute_rpo()
|
||||
#self.graph.draw('_testFirst_graph', '/tmp')
|
||||
# self.graph.draw('_testFirst_graph', '/tmp')
|
||||
expected_rpo = {
|
||||
'r': 1,
|
||||
'x1': 2,
|
||||
@ -150,7 +149,7 @@ class RpoTest(unittest.TestCase):
|
||||
}
|
||||
n_map = self._createGraphFrom(edges)
|
||||
self.graph.compute_rpo()
|
||||
#self.graph.draw('_testSecond_graph', '/tmp')
|
||||
# self.graph.draw('_testSecond_graph', '/tmp')
|
||||
expected_rpo = {
|
||||
'r': 1,
|
||||
'x11': 3,
|
||||
@ -186,7 +185,7 @@ class RpoTest(unittest.TestCase):
|
||||
}
|
||||
n_map = self._createGraphFrom(edges)
|
||||
self.graph.compute_rpo()
|
||||
#self.graph.draw('_testFourth_graph', '/tmp')
|
||||
# self.graph.draw('_testFourth_graph', '/tmp')
|
||||
expected_rpo = {'r': 1, 'x1': 2, 'x2': 3, 'y1': 5, 'y2': 4}
|
||||
self._verifyRpo(n_map, expected_rpo)
|
||||
|
||||
@ -205,7 +204,7 @@ class RpoTest(unittest.TestCase):
|
||||
}
|
||||
n_map = self._createGraphFrom(edges)
|
||||
self.graph.compute_rpo()
|
||||
#self.graph.draw('_testFifth_graph', '/tmp')
|
||||
# self.graph.draw('_testFifth_graph', '/tmp')
|
||||
expected_rpo = {
|
||||
'r': 1,
|
||||
'a': 2,
|
||||
@ -236,7 +235,7 @@ class RpoTest(unittest.TestCase):
|
||||
}
|
||||
n_map = self._createGraphFrom(edges)
|
||||
self.graph.compute_rpo()
|
||||
#self.graph.draw('_testLinearVit_graph', '/tmp')
|
||||
# self.graph.draw('_testLinearVit_graph', '/tmp')
|
||||
expected_rpo = {
|
||||
'r': 1,
|
||||
'w': 3,
|
||||
@ -264,7 +263,7 @@ class RpoTest(unittest.TestCase):
|
||||
}
|
||||
n_map = self._createGraphFrom(edges)
|
||||
self.graph.compute_rpo()
|
||||
#self.graph.draw('_testCross_graph', '/tmp')
|
||||
# self.graph.draw('_testCross_graph', '/tmp')
|
||||
expected_rpo = {
|
||||
'r': 1,
|
||||
'a': 2,
|
||||
@ -295,7 +294,7 @@ class RpoTest(unittest.TestCase):
|
||||
}
|
||||
n_map = self._createGraphFrom(edges)
|
||||
self.graph.compute_rpo()
|
||||
#self.graph.draw('_testTVerify_graph', '/tmp')
|
||||
# self.graph.draw('_testTVerify_graph', '/tmp')
|
||||
expected_rpo = {
|
||||
'n1': 1,
|
||||
'n2': 2,
|
||||
|
@ -76,7 +76,7 @@ ACCESS_FLAGS_METHODS = {
|
||||
ACCESS_ORDER = [0x1, 0x4, 0x2, 0x400, 0x8, 0x10, 0x80, 0x40, 0x20, 0x100, 0x800,
|
||||
0x200, 0x1000, 0x2000, 0x4000, 0x10000, 0x20000]
|
||||
|
||||
TYPE_LEN = {'J': 2, 'D': 2,}
|
||||
TYPE_LEN = {'J': 2, 'D': 2, }
|
||||
|
||||
|
||||
def get_access_class(access):
|
||||
|
@ -32,7 +32,6 @@ logger = logging.getLogger('dad.writer')
|
||||
|
||||
|
||||
class Writer(object):
|
||||
|
||||
def __init__(self, graph, method):
|
||||
self.graph = graph
|
||||
self.method = method
|
||||
@ -104,7 +103,7 @@ class Writer(object):
|
||||
rhs.visit(self)
|
||||
self.end_ins()
|
||||
|
||||
#TODO: prefer this class as write_ind_visit_end that should be deprecated
|
||||
# TODO: prefer this class as write_ind_visit_end that should be deprecated
|
||||
# at the end
|
||||
def write_ind_visit_end_ext(self,
|
||||
lhs,
|
||||
@ -127,8 +126,8 @@ class Writer(object):
|
||||
def write_inplace_if_possible(self, lhs, rhs):
|
||||
if isinstance(rhs, BinaryExpression) and lhs == rhs.var_map[rhs.arg1]:
|
||||
exp_rhs = rhs.var_map[rhs.arg2]
|
||||
if rhs.op in '+-' and isinstance(exp_rhs, Constant) and\
|
||||
exp_rhs.get_int_value() == 1:
|
||||
if rhs.op in '+-' and isinstance(exp_rhs, Constant) and \
|
||||
exp_rhs.get_int_value() == 1:
|
||||
return self.write_ind_visit_end(lhs, rhs.op * 2, data=rhs)
|
||||
return self.write_ind_visit_end(
|
||||
lhs,
|
||||
@ -172,7 +171,7 @@ class Writer(object):
|
||||
self.write_ext(('PARENTHESIS_START', '('))
|
||||
if self.method.params_type:
|
||||
proto = ', '.join(['%s p%s' % (get_type(p_type), param) for p_type,
|
||||
param in zip(self.method.params_type, params)])
|
||||
param in zip(self.method.params_type, params)])
|
||||
first = True
|
||||
for p_type, param in zip(self.method.params_type, params):
|
||||
if not first:
|
||||
@ -288,8 +287,8 @@ class Writer(object):
|
||||
self.write('%s}\n' % self.space(), data="IF_END_2")
|
||||
self.visit_node(cond.false)
|
||||
elif follow is not None:
|
||||
if cond.true in (follow, self.next_case) or\
|
||||
cond.num > cond.true.num:
|
||||
if cond.true in (follow, self.next_case) or \
|
||||
cond.num > cond.true.num:
|
||||
# or cond.true.num > cond.false.num:
|
||||
cond.neg()
|
||||
cond.true, cond.false = cond.false, cond.true
|
||||
@ -525,7 +524,7 @@ class Writer(object):
|
||||
call_name = "%s -> %s" % (base2base.type, name)
|
||||
break
|
||||
elif (hasattr(base2base, "base") and
|
||||
hasattr(base2base, "var_map")):
|
||||
hasattr(base2base, "var_map")):
|
||||
continue
|
||||
else:
|
||||
call_name = "UNKNOWN_TODO"
|
||||
|
@ -37,12 +37,12 @@ try:
|
||||
except ImportError:
|
||||
PYGMENTS = False
|
||||
|
||||
|
||||
class Filter(object):
|
||||
pass
|
||||
|
||||
|
||||
class Dex2Jar(object):
|
||||
|
||||
def __init__(self,
|
||||
vm,
|
||||
path_dex2jar="./decompiler/dex2jar/",
|
||||
@ -70,7 +70,6 @@ class Dex2Jar(object):
|
||||
|
||||
|
||||
class DecompilerDex2Jad(object):
|
||||
|
||||
def __init__(self,
|
||||
vm,
|
||||
path_dex2jar="./decompiler/dex2jar/",
|
||||
@ -164,7 +163,6 @@ class DecompilerDex2Jad(object):
|
||||
|
||||
|
||||
class DecompilerDex2WineJad(object):
|
||||
|
||||
def __init__(self,
|
||||
vm,
|
||||
path_dex2jar="./decompiler/dex2jar/",
|
||||
@ -258,7 +256,6 @@ class DecompilerDex2WineJad(object):
|
||||
|
||||
|
||||
class DecompilerDed(object):
|
||||
|
||||
def __init__(self,
|
||||
vm,
|
||||
path="./decompiler/ded/",
|
||||
@ -298,7 +295,7 @@ class DecompilerDed(object):
|
||||
|
||||
for i in vm.get_classes():
|
||||
fname = findsrc + "/" + i.get_name()[1:-1] + ".java"
|
||||
#print fname
|
||||
# print fname
|
||||
if os.path.isfile(fname) == True:
|
||||
self.classes[i.get_name()] = read(fname, binary=False)
|
||||
else:
|
||||
@ -339,7 +336,6 @@ class DecompilerDed(object):
|
||||
|
||||
|
||||
class DecompilerDex2Fernflower(object):
|
||||
|
||||
def __init__(self,
|
||||
vm,
|
||||
path_dex2jar="./decompiler/dex2jar/",
|
||||
@ -440,15 +436,14 @@ class DecompilerDex2Fernflower(object):
|
||||
|
||||
|
||||
class MethodFilter(Filter):
|
||||
|
||||
def __init__(self, **options):
|
||||
Filter.__init__(self, **options)
|
||||
|
||||
self.method_name = options["method_name"]
|
||||
#self.descriptor = options["descriptor"]
|
||||
# self.descriptor = options["descriptor"]
|
||||
|
||||
self.present = False
|
||||
self.get_desc = True #False
|
||||
self.get_desc = True # False
|
||||
|
||||
def filter(self, lexer, stream):
|
||||
a = []
|
||||
@ -457,8 +452,8 @@ class MethodFilter(Filter):
|
||||
|
||||
for ttype, value in stream:
|
||||
if self.method_name == value and (ttype is Token.Name.Function or
|
||||
ttype is Token.Name):
|
||||
#print ttype, value
|
||||
ttype is Token.Name):
|
||||
# print ttype, value
|
||||
|
||||
item_decl = -1
|
||||
for i in range(len(a) - 1, 0, -1):
|
||||
@ -504,7 +499,6 @@ class MethodFilter(Filter):
|
||||
|
||||
|
||||
class DecompilerDAD(object):
|
||||
|
||||
def __init__(self, vm, vmx):
|
||||
self.vm = vm
|
||||
self.vmx = vmx
|
||||
|
@ -9,6 +9,7 @@ import os, sys, inspect
|
||||
|
||||
from .TextDecorators import *
|
||||
|
||||
|
||||
class Banner(object):
|
||||
def getOrientation(self):
|
||||
NotImplementedError('method not implemented.')
|
||||
@ -32,11 +33,11 @@ class Banner(object):
|
||||
Orientation = enum(Left=0, Bottom=1, Top=2)
|
||||
|
||||
|
||||
|
||||
class Observer(object):
|
||||
def changeViewMode(self, viewMode):
|
||||
self.setViewMode(viewMode)
|
||||
|
||||
|
||||
class Banners(Observer):
|
||||
BOTTOM_SEPARATOR = 5
|
||||
|
||||
@ -51,7 +52,7 @@ class Banners(Observer):
|
||||
|
||||
def banners(self):
|
||||
return self._Banners
|
||||
|
||||
|
||||
def getLeftOffset(self):
|
||||
offset = 0
|
||||
for banner in self._Banners:
|
||||
@ -84,7 +85,7 @@ class Banners(Observer):
|
||||
for banner in self._Banners:
|
||||
# banners are not resizeable actually
|
||||
if banner.getOrientation() == Orientation.Left:
|
||||
banner.resize(banner.getDesiredGeometry(), height - limit + 4) # +4 , make to look nice
|
||||
banner.resize(banner.getDesiredGeometry(), height - limit + 4) # +4 , make to look nice
|
||||
|
||||
if banner.getOrientation() == Orientation.Bottom:
|
||||
banner.resize(width, banner.getDesiredGeometry())
|
||||
@ -101,7 +102,7 @@ class Banners(Observer):
|
||||
for banner in self._Banners:
|
||||
if banner.getOrientation() == Orientation.Top:
|
||||
banner.draw()
|
||||
qp.drawPixmap(offsetLeft-4, offsetBottom, banner.getPixmap())
|
||||
qp.drawPixmap(offsetLeft - 4, offsetBottom, banner.getPixmap())
|
||||
offsetBottom += banner.getDesiredGeometry() + self.separatorLeft
|
||||
|
||||
for banner in self._Banners:
|
||||
@ -120,7 +121,6 @@ class Banners(Observer):
|
||||
offsetBottom += banner.getDesiredGeometry() + self.separatorBottom
|
||||
|
||||
|
||||
|
||||
class FileAddrBanner(Banner):
|
||||
def __init__(self, themes, dataModel, viewMode):
|
||||
self.width = 0
|
||||
@ -137,7 +137,7 @@ class FileAddrBanner(Banner):
|
||||
self.font.setKerning(False)
|
||||
self.font.setFixedPitch(True)
|
||||
fm = QtGui.QFontMetrics(self.font)
|
||||
self.fontWidth = fm.width('a')
|
||||
self.fontWidth = fm.width('a')
|
||||
self.fontHeight = fm.height()
|
||||
|
||||
self.textPen = QtGui.QPen(QtGui.QColor(192, 192, 192), 0, QtCore.Qt.SolidLine)
|
||||
@ -164,16 +164,15 @@ class FileAddrBanner(Banner):
|
||||
columns, rows = self.viewMode.getGeometry()
|
||||
|
||||
qp.begin(self.qpix)
|
||||
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
|
||||
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
|
||||
qp.setPen(self.textPen)
|
||||
qp.setFont(self.font)
|
||||
|
||||
|
||||
for i in range(rows):
|
||||
s = '{0:08x}'.format(offset)
|
||||
qp.drawText(0+5, (i+1) * self.fontHeight, s)
|
||||
qp.drawText(0 + 5, (i + 1) * self.fontHeight, s)
|
||||
columns = self.viewMode.getColumnsbyRow(i)
|
||||
offset += columns
|
||||
|
||||
|
||||
qp.end()
|
||||
|
||||
@ -182,7 +181,6 @@ class FileAddrBanner(Banner):
|
||||
self.height = height
|
||||
|
||||
self.qpix = self._getNewPixmap(self.width, self.height)
|
||||
|
||||
|
||||
|
||||
class BottomBanner(Banner):
|
||||
@ -194,16 +192,15 @@ class BottomBanner(Banner):
|
||||
self.backgroundBrush = QtGui.QBrush(themes['background'])
|
||||
|
||||
self.qpix = self._getNewPixmap(self.width, self.height)
|
||||
|
||||
|
||||
# text font
|
||||
self.font = themes['font']
|
||||
|
||||
|
||||
# font metrics. assume font is monospaced
|
||||
self.font.setKerning(False)
|
||||
self.font.setFixedPitch(True)
|
||||
fm = QtGui.QFontMetrics(self.font)
|
||||
self.fontWidth = fm.width('a')
|
||||
self.fontWidth = fm.width('a')
|
||||
self.fontHeight = fm.height()
|
||||
|
||||
self.textPen = QtGui.QPen(themes['pen'], 0, QtCore.Qt.SolidLine)
|
||||
@ -221,7 +218,7 @@ class BottomBanner(Banner):
|
||||
qp = QtGui.QPainter()
|
||||
qp.begin(self.qpix)
|
||||
|
||||
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
|
||||
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
|
||||
qp.setPen(self.textPen)
|
||||
qp.setFont(self.font)
|
||||
|
||||
@ -235,8 +232,6 @@ class BottomBanner(Banner):
|
||||
|
||||
pos = 'POS: {0:08x}'.format(self.viewMode.getCursorAbsolutePosition())
|
||||
|
||||
|
||||
|
||||
qword = self.dataModel.getQWORD(self.viewMode.getCursorAbsolutePosition(), asString=True)
|
||||
if qword is None:
|
||||
qword = '----'
|
||||
@ -248,7 +243,7 @@ class BottomBanner(Banner):
|
||||
|
||||
sb = 'BYTE: {0}'.format(byte)
|
||||
|
||||
cemu.writeAt(1, 0, pos)
|
||||
cemu.writeAt(1, 0, pos)
|
||||
cemu.writeAt(17, 0, sd)
|
||||
cemu.writeAt(35, 0, sq)
|
||||
cemu.writeAt(62, 0, sb)
|
||||
@ -265,7 +260,7 @@ class BottomBanner(Banner):
|
||||
qp.setPen(pen)
|
||||
|
||||
cemu.writeAt(73, 0, 'Selection: ')
|
||||
cemu.write('{0:x}:{1}'.format(u, v-u))
|
||||
cemu.write('{0:x}:{1}'.format(u, v - u))
|
||||
else:
|
||||
pen = QtGui.QPen(QtGui.QColor(128, 128, 128), 0, QtCore.Qt.SolidLine)
|
||||
qp.setPen(pen)
|
||||
@ -278,9 +273,9 @@ class BottomBanner(Banner):
|
||||
qp.drawLine(self.fontWidth*(len(pos + sd + sq) + 1) + 5*15, 0, self.fontWidth*(len(pos + sd + sq) + 1) + 5*15, 50)
|
||||
qp.drawLine(self.fontWidth*(len(pos + sd + sq + sb) + 1) + 8*15, 0, self.fontWidth*(len(pos + sd + sq + sb) + 1) + 8*15, 50)
|
||||
"""
|
||||
#qp.drawLine(270, 0, 270, 50)
|
||||
#qp.drawLine(480, 0, 480, 50)
|
||||
#qp.drawLine(570, 0, 570, 50)
|
||||
# qp.drawLine(270, 0, 270, 50)
|
||||
# qp.drawLine(480, 0, 480, 50)
|
||||
# qp.drawLine(570, 0, 570, 50)
|
||||
"""
|
||||
# position
|
||||
qp.drawText(0 + 5, self.fontHeight, pos)
|
||||
@ -302,10 +297,11 @@ class BottomBanner(Banner):
|
||||
# separator
|
||||
qp.drawLine(570, 0, 570, 50)
|
||||
"""
|
||||
|
||||
|
||||
qp.end()
|
||||
|
||||
pass
|
||||
|
||||
def getPixmap(self):
|
||||
return self.qpix
|
||||
|
||||
@ -328,7 +324,6 @@ class TopBanner(Banner):
|
||||
self.qpix = self._getNewPixmap(self.width, self.height)
|
||||
self.backgroundBrush = QtGui.QBrush(themes['background'])
|
||||
|
||||
|
||||
# text font
|
||||
self.font = themes['font']
|
||||
|
||||
@ -336,7 +331,7 @@ class TopBanner(Banner):
|
||||
self.font.setKerning(False)
|
||||
self.font.setFixedPitch(True)
|
||||
fm = QtGui.QFontMetrics(self.font)
|
||||
self.fontWidth = fm.width('a')
|
||||
self.fontWidth = fm.width('a')
|
||||
self.fontHeight = fm.height()
|
||||
|
||||
self.textPen = QtGui.QPen(themes['pen'], 0, QtCore.Qt.SolidLine)
|
||||
@ -345,7 +340,7 @@ class TopBanner(Banner):
|
||||
return Orientation.Top
|
||||
|
||||
def getDesiredGeometry(self):
|
||||
return 26#22
|
||||
return 26 # 22
|
||||
|
||||
def setViewMode(self, viewMode):
|
||||
self.viewMode = viewMode
|
||||
@ -358,7 +353,7 @@ class TopBanner(Banner):
|
||||
qp = QtGui.QPainter()
|
||||
qp.begin(self.qpix)
|
||||
|
||||
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
|
||||
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
|
||||
qp.setPen(self.textPen)
|
||||
qp.setFont(self.font)
|
||||
|
||||
@ -371,7 +366,7 @@ class TopBanner(Banner):
|
||||
text = self.viewMode.getHeaderInfo()
|
||||
|
||||
cemu.writeAt(offset, 0, text)
|
||||
|
||||
|
||||
qp.end()
|
||||
|
||||
def getPixmap(self):
|
||||
@ -384,4 +379,3 @@ class TopBanner(Banner):
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.qpix = self._getNewPixmap(self.width, self.height)
|
||||
|
||||
|
@ -5,15 +5,16 @@ from builtins import range
|
||||
from .ViewMode import *
|
||||
from .cemu import *
|
||||
from . import TextSelection
|
||||
from .TextDecorators import *
|
||||
from .TextDecorators import *
|
||||
|
||||
from PyQt5 import QtGui, QtCore
|
||||
import PyQt5
|
||||
from time import time
|
||||
from time import time
|
||||
import sys
|
||||
import threading
|
||||
import string
|
||||
|
||||
|
||||
class BinViewMode(ViewMode):
|
||||
def __init__(self, themes, width, height, data, cursor, widget=None):
|
||||
super(BinViewMode, self).__init__()
|
||||
@ -41,11 +42,9 @@ class BinViewMode(ViewMode):
|
||||
self.font.setKerning(False)
|
||||
self.font.setFixedPitch(True)
|
||||
fm = QtGui.QFontMetrics(self.font)
|
||||
self._fontWidth = fm.width('a')
|
||||
self._fontWidth = fm.width('a')
|
||||
self._fontHeight = fm.height()
|
||||
|
||||
|
||||
|
||||
self.textPen = QtGui.QPen(self.themes['pen'], 0, QtCore.Qt.SolidLine)
|
||||
self.resize(width, height)
|
||||
|
||||
@ -64,8 +63,8 @@ class BinViewMode(ViewMode):
|
||||
def startCaching(self):
|
||||
# cache
|
||||
self.cache()
|
||||
#t = threading.Thread(target=self.cache)
|
||||
#t.start()
|
||||
# t = threading.Thread(target=self.cache)
|
||||
# t.start()
|
||||
|
||||
def isInCache(self, page):
|
||||
if page in self.Paints:
|
||||
@ -73,13 +72,13 @@ class BinViewMode(ViewMode):
|
||||
|
||||
def cache(self):
|
||||
|
||||
for i in [1,2]:
|
||||
#pix = self._getNewPixmap(self.width, self.height)
|
||||
for i in [1, 2]:
|
||||
# pix = self._getNewPixmap(self.width, self.height)
|
||||
if not self.isInCache(self.dataModel.getPageOffset(i)):
|
||||
pix = QtGui.QImage(self.width, self.height, QtGui.QImage.Format_ARGB32)
|
||||
self.scrollPages(1, cachePix=pix, pageOffset=i)
|
||||
self.Paints[self.dataModel.getPageOffset(i)] = pix
|
||||
#print 'cache'
|
||||
# print 'cache'
|
||||
|
||||
def _getNewPixmap(self, width, height):
|
||||
return QtGui.QPixmap(width, height)
|
||||
@ -90,7 +89,7 @@ class BinViewMode(ViewMode):
|
||||
|
||||
def computeTextArea(self):
|
||||
self.COLUMNS = self.width // self.fontWidth
|
||||
self.ROWS = self.height // self.fontHeight
|
||||
self.ROWS = self.height // self.fontHeight
|
||||
self.notify(self.ROWS, self.COLUMNS)
|
||||
|
||||
def drawAdditionals(self):
|
||||
@ -99,7 +98,7 @@ class BinViewMode(ViewMode):
|
||||
qp.begin(self.newPix)
|
||||
qp.drawPixmap(0, 0, self.qpix)
|
||||
|
||||
#self.transformationEngine.decorateText()
|
||||
# self.transformationEngine.decorateText()
|
||||
|
||||
# highlight selected text
|
||||
self.selector.highlightText()
|
||||
@ -133,33 +132,32 @@ class BinViewMode(ViewMode):
|
||||
if self.dataModel.getOffset() in self.Paints:
|
||||
self.refresh = False
|
||||
self.qpix = QtGui.QPixmap(self.Paints[self.dataModel.getOffset()])
|
||||
#print 'hit'
|
||||
# print 'hit'
|
||||
self.drawAdditionals()
|
||||
return
|
||||
|
||||
if self.refresh or refresh:
|
||||
qp = QtGui.QPainter()
|
||||
qp.begin(self.qpix)
|
||||
#start = time()
|
||||
# start = time()
|
||||
if not howMany:
|
||||
howMany = self.ROWS
|
||||
|
||||
self.drawTextMode(qp, row=row, howMany=howMany)
|
||||
#end = time() - start
|
||||
#print 'Time ' + str(end)
|
||||
# end = time() - start
|
||||
# print 'Time ' + str(end)
|
||||
self.refresh = False
|
||||
qp.end()
|
||||
|
||||
# self.Paints[self.dataModel.getOffset()] = QtGui.QPixmap(self.qpix)
|
||||
# self.Paints[self.dataModel.getOffset()] = QtGui.QPixmap(self.qpix)
|
||||
self.drawAdditionals()
|
||||
|
||||
|
||||
def draw2(self, qp, refresh=False):
|
||||
if self.refresh or refresh:
|
||||
start = time()
|
||||
self.drawTextMode(qp, howMany=self.ROWS)
|
||||
end = time() - start
|
||||
#print 'Time ' + str(end)
|
||||
# print 'Time ' + str(end)
|
||||
qp = QtGui.QPainter()
|
||||
qp.begin(self.qpix)
|
||||
|
||||
@ -173,24 +171,24 @@ class BinViewMode(ViewMode):
|
||||
qp.setBrush(QtGui.QColor(255, 102, 179))
|
||||
|
||||
qp.setOpacity(0.8)
|
||||
qp.drawRect(cursorX*self.fontWidth, cursorY*self.fontHeight, self.fontWidth, self.fontHeight + 2)
|
||||
qp.setOpacity(1)
|
||||
|
||||
qp.drawRect(cursorX * self.fontWidth, cursorY * self.fontHeight, self.fontWidth, self.fontHeight + 2)
|
||||
qp.setOpacity(1)
|
||||
|
||||
def scroll_h(self, dx):
|
||||
self.qpix.scroll(dx*self.fontWidth, 0, self.qpix.rect())
|
||||
self.qpix.scroll(dx * self.fontWidth, 0, self.qpix.rect())
|
||||
|
||||
qp = QtGui.QPainter()
|
||||
|
||||
|
||||
qp.begin(self.qpix)
|
||||
qp.setFont(self.font)
|
||||
qp.setPen(self.textPen)
|
||||
|
||||
factor = abs(dx)
|
||||
if dx < 0:
|
||||
qp.fillRect((self.COLUMNS - 1*factor)*self.fontWidth, 0, factor * self.fontWidth, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
qp.fillRect((self.COLUMNS - 1 * factor) * self.fontWidth, 0, factor * self.fontWidth,
|
||||
self.ROWS * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
if dx > 0:
|
||||
qp.fillRect(0, 0, factor * self.fontWidth, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
qp.fillRect(0, 0, factor * self.fontWidth, self.ROWS * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
|
||||
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
|
||||
|
||||
@ -202,11 +200,11 @@ class BinViewMode(ViewMode):
|
||||
|
||||
if dx < 0:
|
||||
# cu (column) selectam coloana
|
||||
idx = (i+1)*(self.COLUMNS) - (column + 1)
|
||||
idx = (i + 1) * (self.COLUMNS) - (column + 1)
|
||||
if dx > 0:
|
||||
idx = (i)*(self.COLUMNS) + (column)
|
||||
idx = (i) * (self.COLUMNS) + (column)
|
||||
|
||||
#c = self.dataModel.getDisplayablePage()[idx]
|
||||
# c = self.dataModel.getDisplayablePage()[idx]
|
||||
c = self.transformationEngine.getChar(idx)
|
||||
qp.setPen(self.transformationEngine.choosePen(idx))
|
||||
|
||||
@ -215,7 +213,7 @@ class BinViewMode(ViewMode):
|
||||
qp.setBackground(self.transformationEngine.chooseBrush(idx))
|
||||
|
||||
|
||||
# self.decorate(qp, (idx, c), self.dataModel.getDisplayablePage())
|
||||
# self.decorate(qp, (idx, c), self.dataModel.getDisplayablePage())
|
||||
if dx < 0:
|
||||
cemu.writeAt(self.COLUMNS - (column + 1), i, self.cp437(c))
|
||||
|
||||
@ -225,15 +223,14 @@ class BinViewMode(ViewMode):
|
||||
qp.setBackgroundMode(0)
|
||||
qp.end()
|
||||
|
||||
|
||||
def scroll_v(self, dy, cachePix=None, pageOffset=None):
|
||||
start = time()
|
||||
start = time()
|
||||
|
||||
# if cachePix:
|
||||
# print 'da'
|
||||
# if cachePix:
|
||||
# print 'da'
|
||||
|
||||
if not cachePix:
|
||||
self.qpix.scroll(0, dy*self.fontHeight, self.qpix.rect())
|
||||
self.qpix.scroll(0, dy * self.fontHeight, self.qpix.rect())
|
||||
|
||||
qp = QtGui.QPainter()
|
||||
|
||||
@ -242,7 +239,7 @@ class BinViewMode(ViewMode):
|
||||
else:
|
||||
qp.begin(self.qpix)
|
||||
|
||||
#self.font.setStyleHint(QtGui.QFont.AnyStyle, QtGui.QFont.PreferAntialias)
|
||||
# self.font.setStyleHint(QtGui.QFont.AnyStyle, QtGui.QFont.PreferAntialias)
|
||||
qp.setFont(self.font)
|
||||
qp.setPen(self.textPen)
|
||||
|
||||
@ -250,17 +247,17 @@ class BinViewMode(ViewMode):
|
||||
# same problem when scrolling up.
|
||||
factor = abs(dy)
|
||||
if dy < 0:
|
||||
qp.fillRect(0, (self.ROWS-factor)*self.fontHeight, self.fontWidth*self.COLUMNS, factor * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
qp.fillRect(0, (self.ROWS - factor) * self.fontHeight, self.fontWidth * self.COLUMNS,
|
||||
factor * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
|
||||
if dy > 0:
|
||||
qp.fillRect(0, 0, self.fontWidth*self.COLUMNS, factor * self.fontHeight, self.backgroundBrush)
|
||||
qp.fillRect(0, 0, self.fontWidth * self.COLUMNS, factor * self.fontHeight, self.backgroundBrush)
|
||||
|
||||
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
|
||||
|
||||
#page = self.dataModel.getDisplayablePage()
|
||||
# page = self.dataModel.getDisplayablePage()
|
||||
page = self.transformationEngine.decorate(pageOffset=pageOffset)
|
||||
|
||||
|
||||
lastPen = None
|
||||
lastBrush = None
|
||||
|
||||
@ -268,25 +265,23 @@ class BinViewMode(ViewMode):
|
||||
k = time()
|
||||
for row in range(factor):
|
||||
# desenam caracterele
|
||||
#cemu.writeAt(0, row, str(page[row*self.COLUMNS:row*self.COLUMNS+self.COLUMNS]))
|
||||
|
||||
# cemu.writeAt(0, row, str(page[row*self.COLUMNS:row*self.COLUMNS+self.COLUMNS]))
|
||||
|
||||
for i in range(self.COLUMNS):
|
||||
|
||||
if dy < 0:
|
||||
idx = (self.ROWS - (row + 1))*self.COLUMNS + i
|
||||
idx = (self.ROWS - (row + 1)) * self.COLUMNS + i
|
||||
|
||||
if dy > 0:
|
||||
idx = i + (self.COLUMNS*row)
|
||||
idx = i + (self.COLUMNS * row)
|
||||
|
||||
c = self.transformationEngine.getChar(idx)
|
||||
|
||||
|
||||
nextPen = self.transformationEngine.choosePen(idx)
|
||||
if nextPen != lastPen:
|
||||
qp.setPen(nextPen)
|
||||
lastPen = nextPen
|
||||
|
||||
|
||||
qp.setBackgroundMode(0)
|
||||
nextBrush = self.transformationEngine.chooseBrush(idx)
|
||||
if nextBrush != None:
|
||||
@ -296,20 +291,19 @@ class BinViewMode(ViewMode):
|
||||
qp.setBackground(nextBrush)
|
||||
lastBrush = nextBrush
|
||||
|
||||
|
||||
if dy < 0:
|
||||
cemu.writeAt_c(i, self.ROWS - 1 - row, self.cp437(c))
|
||||
|
||||
if dy > 0:
|
||||
cemu.writeAt_c(i, row, self.cp437(c))
|
||||
|
||||
|
||||
|
||||
# TODO: text decorator is taking too much! print time() - k
|
||||
qp.end()
|
||||
|
||||
end = time() - start
|
||||
# print end
|
||||
# sys.exit()
|
||||
|
||||
# print end
|
||||
# sys.exit()
|
||||
|
||||
|
||||
def scroll(self, dx, dy, cachePix=None, pageOffset=None):
|
||||
@ -324,16 +318,16 @@ class BinViewMode(ViewMode):
|
||||
self.scroll_h(dx)
|
||||
|
||||
if dy != 0:
|
||||
if self.dataModel.inLimits((self.dataModel.getOffset() - dy*self.COLUMNS)):
|
||||
self.dataModel.slide(-dy*self.COLUMNS)
|
||||
#import time
|
||||
#k = time.time()
|
||||
if self.dataModel.inLimits((self.dataModel.getOffset() - dy * self.COLUMNS)):
|
||||
self.dataModel.slide(-dy * self.COLUMNS)
|
||||
# import time
|
||||
# k = time.time()
|
||||
self.scroll_v(dy, cachePix, pageOffset)
|
||||
#print time.time() - k
|
||||
# print time.time() - k
|
||||
else:
|
||||
if dy <= 0:
|
||||
pass
|
||||
#self.dataModel.slideToLastPage()
|
||||
# self.dataModel.slideToLastPage()
|
||||
else:
|
||||
self.dataModel.slideToFirstPage()
|
||||
|
||||
@ -343,9 +337,8 @@ class BinViewMode(ViewMode):
|
||||
if not cachePix:
|
||||
self.draw()
|
||||
|
||||
|
||||
def scrollPages(self, number, cachePix=None, pageOffset=None):
|
||||
self.scroll(0, -number*self.ROWS, cachePix=cachePix, pageOffset=pageOffset)
|
||||
self.scroll(0, -number * self.ROWS, cachePix=cachePix, pageOffset=pageOffset)
|
||||
|
||||
def getPixmap(self):
|
||||
for t in self.Ops:
|
||||
@ -356,38 +349,39 @@ class BinViewMode(ViewMode):
|
||||
t[0](*t[1:])
|
||||
|
||||
self.Ops = []
|
||||
|
||||
|
||||
if not self.newPix:
|
||||
self.draw()
|
||||
|
||||
return self.newPix
|
||||
|
||||
def resize(self, width, height):
|
||||
self.width = width - width%self.fontWidth
|
||||
self.height = height - height%self.fontHeight
|
||||
self.width = width - width % self.fontWidth
|
||||
self.height = height - height % self.fontHeight
|
||||
self.computeTextArea()
|
||||
self.qpix = self._getNewPixmap(self.width, self.height + self.SPACER)
|
||||
self.refresh = True
|
||||
|
||||
def drawTextMode(self, qp, row=0, howMany=1):
|
||||
# draw background
|
||||
qp.fillRect(0, row * self.fontHeight, self.COLUMNS * self.fontWidth, howMany * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
qp.fillRect(0, row * self.fontHeight, self.COLUMNS * self.fontWidth, howMany * self.fontHeight + self.SPACER,
|
||||
self.backgroundBrush)
|
||||
|
||||
# set text pen&font
|
||||
qp.setFont(self.font)
|
||||
qp.setPen(self.textPen)
|
||||
|
||||
|
||||
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
|
||||
|
||||
self.page = self.transformationEngine.decorate()
|
||||
|
||||
cemu.gotoXY(0, row)
|
||||
|
||||
for i, c in enumerate(self.getDisplayablePage()[row*self.COLUMNS:(row + howMany)*self.COLUMNS]):
|
||||
x = i + row*self.COLUMNS
|
||||
for i, c in enumerate(self.getDisplayablePage()[row * self.COLUMNS:(row + howMany) * self.COLUMNS]):
|
||||
x = i + row * self.COLUMNS
|
||||
|
||||
c = self.transformationEngine.getChar(x)
|
||||
|
||||
|
||||
qp.setPen(self.transformationEngine.choosePen(x))
|
||||
|
||||
if self.transformationEngine.chooseBrush(x) != None:
|
||||
@ -395,12 +389,11 @@ class BinViewMode(ViewMode):
|
||||
qp.setBackground(self.transformationEngine.chooseBrush(x))
|
||||
|
||||
cemu.write(self.cp437(c))
|
||||
qp.setBackgroundMode(0)
|
||||
qp.setBackgroundMode(0)
|
||||
|
||||
|
||||
def getCursorAbsolutePosition(self):
|
||||
x, y = self.cursor.getPosition()
|
||||
return self.dataModel.getOffset() + y*self.COLUMNS + x
|
||||
return self.dataModel.getOffset() + y * self.COLUMNS + x
|
||||
|
||||
def moveCursor(self, direction):
|
||||
cursorX, cursorY = self.cursor.getPosition()
|
||||
@ -410,31 +403,29 @@ class BinViewMode(ViewMode):
|
||||
if cursorY == 0:
|
||||
self.scroll(1, 0)
|
||||
else:
|
||||
self.cursor.moveAbsolute(self.COLUMNS-1, cursorY - 1)
|
||||
self.cursor.moveAbsolute(self.COLUMNS - 1, cursorY - 1)
|
||||
else:
|
||||
self.cursor.move(-1, 0)
|
||||
|
||||
|
||||
if direction == Directions.Right:
|
||||
if self.getCursorAbsolutePosition() + 1 >= self.dataModel.getDataSize():
|
||||
return
|
||||
|
||||
if cursorX == self.COLUMNS-1:
|
||||
if cursorY == self.ROWS-1:
|
||||
if cursorX == self.COLUMNS - 1:
|
||||
if cursorY == self.ROWS - 1:
|
||||
self.scroll(-1, 0)
|
||||
else:
|
||||
self.cursor.moveAbsolute(0, cursorY + 1)
|
||||
else:
|
||||
self.cursor.move(1, 0)
|
||||
|
||||
|
||||
if direction == Directions.Down:
|
||||
if self.getCursorAbsolutePosition() + self.COLUMNS >= self.dataModel.getDataSize():
|
||||
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize()-1)
|
||||
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize() - 1)
|
||||
self.cursor.moveAbsolute(x, y)
|
||||
return
|
||||
|
||||
if cursorY == self.ROWS-1:
|
||||
if cursorY == self.ROWS - 1:
|
||||
self.scroll(0, -1)
|
||||
else:
|
||||
self.cursor.move(0, 1)
|
||||
@ -447,11 +438,11 @@ class BinViewMode(ViewMode):
|
||||
|
||||
if direction == Directions.End:
|
||||
if self.dataModel.getDataSize() < self.getCursorAbsolutePosition() + self.ROWS * self.COLUMNS:
|
||||
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize()-1)
|
||||
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize() - 1)
|
||||
self.cursor.moveAbsolute(x, y)
|
||||
|
||||
else:
|
||||
self.cursor.moveAbsolute(self.COLUMNS-1, self.ROWS-1)
|
||||
self.cursor.moveAbsolute(self.COLUMNS - 1, self.ROWS - 1)
|
||||
|
||||
if direction == Directions.Home:
|
||||
self.cursor.moveAbsolute(0, 0)
|
||||
@ -468,25 +459,23 @@ class BinViewMode(ViewMode):
|
||||
|
||||
def keyFilter(self):
|
||||
return [
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Right),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Left),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Up),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Down),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_End),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Home),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Right),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Left),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Up),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Down),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_End),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Home),
|
||||
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Right),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Left),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Up),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Down),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_End),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Home),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageDown),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageUp)
|
||||
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Right),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Left),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Up),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Down),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_End),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Home),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageDown),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageUp)
|
||||
|
||||
|
||||
]
|
||||
]
|
||||
|
||||
def anon(self, dx, dy):
|
||||
self.scroll(dx, dy)
|
||||
@ -510,17 +499,18 @@ class BinViewMode(ViewMode):
|
||||
|
||||
self.dataModel.setData_b(self.dataModel.getOffset() + offs, str(event.text()))
|
||||
|
||||
z = self.dataModel.getOffset() + offs
|
||||
#TODO: sa nu se repete, tre original_transformengine
|
||||
self.transformationEngine = RangePen(self.original_textdecorator, z, z + 0, QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine), ignoreHighlights=True)
|
||||
z = self.dataModel.getOffset() + offs
|
||||
# TODO: sa nu se repete, tre original_transformengine
|
||||
self.transformationEngine = RangePen(self.original_textdecorator, z, z + 0,
|
||||
QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine),
|
||||
ignoreHighlights=True)
|
||||
|
||||
self.moveCursor(Directions.Right)
|
||||
|
||||
|
||||
x, y = self.cursor.getPosition()
|
||||
|
||||
self.draw(refresh=True, row=y, howMany=1)
|
||||
|
||||
|
||||
def handleKeyEvent(self, modifiers, key, event=None):
|
||||
if event.type() == QtCore.QEvent.KeyRelease:
|
||||
if key == QtCore.Qt.Key_Shift:
|
||||
@ -529,11 +519,11 @@ class BinViewMode(ViewMode):
|
||||
|
||||
if event.type() == QtCore.QEvent.KeyPress:
|
||||
if modifiers & QtCore.Qt.ShiftModifier:
|
||||
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up, QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
|
||||
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up,
|
||||
QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
|
||||
if key in keys:
|
||||
self.startSelection()
|
||||
|
||||
|
||||
if modifiers & QtCore.Qt.ControlModifier:
|
||||
if key == QtCore.Qt.Key_Right:
|
||||
self.addop((self.anon, -1, 0))
|
||||
@ -555,10 +545,9 @@ class BinViewMode(ViewMode):
|
||||
self.moveCursor(Directions.CtrlHome)
|
||||
self.addop((self.draw,))
|
||||
|
||||
|
||||
return True
|
||||
|
||||
else:#elif modifiers == QtCore.Qt.NoModifier or modifiers == QtCore.Qt.ShiftModifier::
|
||||
else: # elif modifiers == QtCore.Qt.NoModifier or modifiers == QtCore.Qt.ShiftModifier::
|
||||
|
||||
if key == QtCore.Qt.Key_Escape:
|
||||
self.selector.resetSelections()
|
||||
@ -571,15 +560,15 @@ class BinViewMode(ViewMode):
|
||||
if key == QtCore.Qt.Key_Right:
|
||||
self.moveCursor(Directions.Right)
|
||||
self.addop((self.draw,))
|
||||
|
||||
|
||||
if key == QtCore.Qt.Key_Down:
|
||||
self.moveCursor(Directions.Down)
|
||||
self.addop((self.draw,))
|
||||
|
||||
|
||||
if key == QtCore.Qt.Key_End:
|
||||
self.moveCursor(Directions.End)
|
||||
self.addop((self.draw,))
|
||||
|
||||
|
||||
if key == QtCore.Qt.Key_Home:
|
||||
self.moveCursor(Directions.Home)
|
||||
self.addop((self.draw,))
|
||||
@ -587,10 +576,10 @@ class BinViewMode(ViewMode):
|
||||
if key == QtCore.Qt.Key_Up:
|
||||
self.moveCursor(Directions.Up)
|
||||
self.addop((self.draw,))
|
||||
|
||||
|
||||
if key == QtCore.Qt.Key_PageDown:
|
||||
self.addop((self.scrollPages, 1))
|
||||
|
||||
|
||||
if key == QtCore.Qt.Key_PageUp:
|
||||
self.addop((self.scrollPages, -1))
|
||||
|
||||
@ -615,7 +604,6 @@ class BinViewMode(ViewMode):
|
||||
self.transformationEngine.reset()
|
||||
self.draw(refresh=True)
|
||||
|
||||
|
||||
"""
|
||||
def handleKeyPressEvent(self, modifier, key):
|
||||
if modifier == QtCore.Qt.ShiftModifier:
|
||||
@ -627,6 +615,7 @@ class BinViewMode(ViewMode):
|
||||
self.stopSelection()
|
||||
return True
|
||||
"""
|
||||
|
||||
def addop(self, t):
|
||||
self.Ops.append(t)
|
||||
|
||||
|
@ -2,6 +2,7 @@ from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import absolute_import
|
||||
from future import standard_library
|
||||
|
||||
standard_library.install_aliases()
|
||||
from builtins import str
|
||||
from builtins import object
|
||||
@ -13,10 +14,12 @@ from .HexViewMode import *
|
||||
from .DisasmViewMode import *
|
||||
from .SourceViewMode import *
|
||||
|
||||
|
||||
class Observer(object):
|
||||
def update_geometry(self):
|
||||
NotImplementedError('method not implemented.')
|
||||
|
||||
|
||||
class DataModel(Observer):
|
||||
def __init__(self, data):
|
||||
self._dataOffset = 0
|
||||
@ -28,7 +31,7 @@ class DataModel(Observer):
|
||||
@property
|
||||
def dataOffset(self):
|
||||
return self._dataOffset
|
||||
|
||||
|
||||
@dataOffset.setter
|
||||
def dataOffset(self, value):
|
||||
print("DATA OFFSET", value)
|
||||
@ -53,7 +56,7 @@ class DataModel(Observer):
|
||||
self.dataOffset = off
|
||||
|
||||
def offsetInPage(self, off):
|
||||
if off >= self.dataOffset and off <= self.dataOffset + self.rows*self.cols:
|
||||
if off >= self.dataOffset and off <= self.dataOffset + self.rows * self.cols:
|
||||
return True
|
||||
|
||||
return False
|
||||
@ -63,87 +66,87 @@ class DataModel(Observer):
|
||||
self.cols = cols
|
||||
|
||||
def slideLine(self, factor):
|
||||
self.slide(factor*self.cols)
|
||||
self.slide(factor * self.cols)
|
||||
|
||||
def slidePage(self, factor):
|
||||
self.slide(factor*self.cols*self.rows)
|
||||
self.slide(factor * self.cols * self.rows)
|
||||
|
||||
def slideToLastPage(self):
|
||||
if self.rows*self.cols > len(self.data):
|
||||
if self.rows * self.cols > len(self.data):
|
||||
return
|
||||
|
||||
self.dataOffset = len(self.data) - self.cols*self.rows
|
||||
self.dataOffset = len(self.data) - self.cols * self.rows
|
||||
|
||||
def slideToFirstPage(self):
|
||||
self.dataOffset = 0
|
||||
|
||||
def getXYInPage(self, off):
|
||||
off -= self.dataOffset
|
||||
x, y = off // self.cols, off%self.cols
|
||||
x, y = off // self.cols, off % self.cols
|
||||
return x, y
|
||||
|
||||
def getPageOffset(self, page):
|
||||
return self.getOffset() + (page)*self.rows*self.cols
|
||||
|
||||
return self.getOffset() + (page) * self.rows * self.cols
|
||||
|
||||
def getQWORD(self, offset, asString=False):
|
||||
if offset + 8 > len(self.data):
|
||||
return None
|
||||
|
||||
b = bytearray(self.data[offset:offset+8])
|
||||
b = bytearray(self.data[offset:offset + 8])
|
||||
|
||||
d = ((b[7] << 56) | (b[6] << 48) | (b[5] << 40) | (b[4] << 32) | (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0])) & 0xFFFFFFFFFFFFFFFF
|
||||
d = ((b[7] << 56) | (b[6] << 48) | (b[5] << 40) | (b[4] << 32) | (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (
|
||||
b[0])) & 0xFFFFFFFFFFFFFFFF
|
||||
|
||||
if not asString:
|
||||
if not asString:
|
||||
return d
|
||||
|
||||
s = '{0:016X}'.format(d)
|
||||
|
||||
|
||||
return s
|
||||
|
||||
def getDWORD(self, offset, asString=False):
|
||||
if offset + 4 >= len(self.data):
|
||||
return None
|
||||
|
||||
b = bytearray(self.data[offset:offset+4])
|
||||
b = bytearray(self.data[offset:offset + 4])
|
||||
|
||||
d = ((b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0])) & 0xFFFFFFFF
|
||||
|
||||
if not asString:
|
||||
if not asString:
|
||||
return d
|
||||
|
||||
s = '{0:08X}'.format(d)
|
||||
|
||||
|
||||
return s
|
||||
|
||||
def getWORD(self, offset, asString=False):
|
||||
if offset + 2 > len(self.data):
|
||||
return None
|
||||
|
||||
b = bytearray(self.data[offset:offset+2])
|
||||
b = bytearray(self.data[offset:offset + 2])
|
||||
|
||||
d = ((b[1] << 8) | (b[0])) & 0xFFFF
|
||||
|
||||
if not asString:
|
||||
if not asString:
|
||||
return d
|
||||
|
||||
s = '{0:04X}'.format(d)
|
||||
|
||||
|
||||
return s
|
||||
|
||||
def getBYTE(self, offset, asString=False):
|
||||
if offset + 1 > len(self.data):
|
||||
return None
|
||||
|
||||
b = bytearray(self.data[offset:offset+1])
|
||||
b = bytearray(self.data[offset:offset + 1])
|
||||
|
||||
d = (b[0]) & 0xFF
|
||||
|
||||
if not asString:
|
||||
if not asString:
|
||||
return d
|
||||
|
||||
s = '{0:02X}'.format(d)
|
||||
|
||||
|
||||
return s
|
||||
|
||||
def getChar(self, offset):
|
||||
@ -199,6 +202,7 @@ class DataModel(Observer):
|
||||
def size(self):
|
||||
pass
|
||||
|
||||
|
||||
class FileDataModel(DataModel):
|
||||
def __init__(self, filename):
|
||||
self._filename = filename
|
||||
@ -237,7 +241,10 @@ class FileDataModel(DataModel):
|
||||
def size(self):
|
||||
return os.path.getsize(self._filename)
|
||||
|
||||
|
||||
import io
|
||||
|
||||
|
||||
class MyStringIO(io.StringIO, object):
|
||||
def __init__(self, data):
|
||||
self.raw = data
|
||||
@ -246,6 +253,7 @@ class MyStringIO(io.StringIO, object):
|
||||
def __len__(self):
|
||||
return len(self.raw)
|
||||
|
||||
|
||||
class MyByte(bytearray):
|
||||
def __init__(self, data):
|
||||
self.raw = data
|
||||
@ -275,6 +283,7 @@ class MyByte(bytearray):
|
||||
self._pointer += size
|
||||
return data
|
||||
|
||||
|
||||
class BufferDataModel(DataModel):
|
||||
def __init__(self, data, name):
|
||||
self._filename = name
|
||||
@ -291,13 +300,14 @@ class BufferDataModel(DataModel):
|
||||
def close(self):
|
||||
return
|
||||
|
||||
# def write(self, offset, stream):
|
||||
# self._mapped.seek(offset)
|
||||
# self._mapped.write(stream)
|
||||
# def write(self, offset, stream):
|
||||
# self._mapped.seek(offset)
|
||||
# self._mapped.write(stream)
|
||||
|
||||
def size(self):
|
||||
return len(self.data)
|
||||
|
||||
|
||||
class ApkModel(DataModel):
|
||||
def __init__(self, apkobj):
|
||||
print(apkobj)
|
||||
@ -323,6 +333,7 @@ class ApkModel(DataModel):
|
||||
def size(self):
|
||||
return len(self.data)
|
||||
|
||||
|
||||
class DexClassModel(DataModel):
|
||||
def __init__(self, current_class):
|
||||
self.current_class = current_class
|
||||
|
@ -27,14 +27,14 @@ class InstructionView(object):
|
||||
|
||||
def AddComment(self, cmt):
|
||||
self._Comments.append(cmt)
|
||||
|
||||
|
||||
def Load(self):
|
||||
if self.loaded:
|
||||
return
|
||||
|
||||
H = self.get_hex().split(' ')
|
||||
for i, h in enumerate(H):
|
||||
self._indexTable += [(i*3, len(h), h)]
|
||||
self._indexTable += [(i * 3, len(h), h)]
|
||||
|
||||
self._indexTable += [(MNEMONIC_COLUMN, len(self.get_name()), self.get_name())]
|
||||
|
||||
@ -151,7 +151,6 @@ class InstructionView(object):
|
||||
|
||||
return idx, 0
|
||||
|
||||
|
||||
def getSelectedToken(self, cx):
|
||||
for i, t in enumerate(self._indexTable):
|
||||
idx, length, value = t
|
||||
@ -209,8 +208,8 @@ class DisasmViewMode(ViewMode):
|
||||
for method in methods:
|
||||
mx = vm_analysis.get_method(method)
|
||||
for DVMBasicMethodBlockInstruction in method.get_instructions():
|
||||
#for DVMBasicMethodBlock in mx.basic_blocks.gets():
|
||||
# for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions():
|
||||
# for DVMBasicMethodBlock in mx.basic_blocks.gets():
|
||||
# for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions():
|
||||
ins = InstructionView(DVMBasicMethodBlockInstruction)
|
||||
self.CACHE_OPCODES.append(ins)
|
||||
self.CACHE_IDX_OPCODES[offset] = ins
|
||||
@ -246,7 +245,6 @@ class DisasmViewMode(ViewMode):
|
||||
ins.Load()
|
||||
self.OPCODES.append(ins)
|
||||
|
||||
|
||||
@property
|
||||
def fontWidth(self):
|
||||
return self._fontWidth
|
||||
@ -259,8 +257,8 @@ class DisasmViewMode(ViewMode):
|
||||
self.transformationEngine = engine
|
||||
|
||||
def resize(self, width, height):
|
||||
self.width = width - width%self.fontWidth
|
||||
self.height = height - height%self.fontHeight
|
||||
self.width = width - width % self.fontWidth
|
||||
self.height = height - height % self.fontHeight
|
||||
self.computeTextArea()
|
||||
self.qpix = self._getNewPixmap(self.width, self.height + self.SPACER)
|
||||
self.refresh = True
|
||||
@ -374,9 +372,8 @@ class DisasmViewMode(ViewMode):
|
||||
brush)
|
||||
qp.setOpacity(1)
|
||||
|
||||
|
||||
def drawBranch(self, qp):
|
||||
qp.fillRect(-50, 0, 50, self.ROWS * self.fontHeight, self.backgroundBrush)
|
||||
qp.fillRect(-50, 0, 50, self.ROWS * self.fontHeight, self.backgroundBrush)
|
||||
|
||||
def drawBranch2(self, qp):
|
||||
|
||||
@ -400,29 +397,30 @@ class DisasmViewMode(ViewMode):
|
||||
return
|
||||
|
||||
screenVA = self._getVA(self.dataModel.getOffset())
|
||||
if target > screenVA and target < self._getVA(self.dataModel.getOffset()) + tsize - self.OPCODES[-1].size:
|
||||
if target > screenVA and target < self._getVA(self.dataModel.getOffset()) + tsize - self.OPCODES[-1].size:
|
||||
# branch target is in screen
|
||||
|
||||
sz = 0
|
||||
for i, t in enumerate(self.OPCODES):
|
||||
sz += t.size
|
||||
if sz+self._getVA(self.dataModel.getOffset()) >= target:
|
||||
if sz + self._getVA(self.dataModel.getOffset()) >= target:
|
||||
break
|
||||
|
||||
qp.setPen(QtGui.QPen(QtGui.QColor(0, 192, 0), 1, QtCore.Qt.SolidLine))
|
||||
|
||||
# draw the three lines
|
||||
|
||||
qp.drawLine(-5, cursorY*self.fontHeight + self.fontHeight // 2, -30, cursorY*self.fontHeight + half)
|
||||
qp.drawLine(-5, cursorY * self.fontHeight + self.fontHeight // 2, -30, cursorY * self.fontHeight + half)
|
||||
|
||||
qp.drawLine(-30, cursorY*self.fontHeight + self.fontHeight // 2, -30, (i + 1)*self.fontHeight + half)
|
||||
qp.drawLine(-30, cursorY * self.fontHeight + self.fontHeight // 2, -30,
|
||||
(i + 1) * self.fontHeight + half)
|
||||
|
||||
qp.drawLine(-30, (i + 1)*self.fontHeight + half, -15, (i + 1)*self.fontHeight + half)
|
||||
qp.drawLine(-30, (i + 1) * self.fontHeight + half, -15, (i + 1) * self.fontHeight + half)
|
||||
|
||||
# draw arrow
|
||||
points = [QtCore.QPoint(-15, (i + 1)*self.fontHeight + half - 5),
|
||||
QtCore.QPoint(-15, (i + 1)*self.fontHeight + half + 5),
|
||||
QtCore.QPoint(-5, (i + 1)*self.fontHeight + half), ]
|
||||
points = [QtCore.QPoint(-15, (i + 1) * self.fontHeight + half - 5),
|
||||
QtCore.QPoint(-15, (i + 1) * self.fontHeight + half + 5),
|
||||
QtCore.QPoint(-5, (i + 1) * self.fontHeight + half), ]
|
||||
needle = QtGui.QPolygon(points)
|
||||
qp.setBrush(QtGui.QBrush(QtGui.QColor(0, 128, 0)))
|
||||
qp.drawPolygon(needle)
|
||||
@ -435,13 +433,14 @@ class DisasmViewMode(ViewMode):
|
||||
qp.setPen(QtGui.QPen(QtGui.QColor(0, 192, 0), 1, QtCore.Qt.DotLine))
|
||||
|
||||
# draw the two lines
|
||||
qp.drawLine(-5, cursorY*self.fontHeight + self.fontHeight // 2, -30, cursorY*self.fontHeight + half)
|
||||
qp.drawLine(-30, cursorY*self.fontHeight + self.fontHeight // 2, -30, (self.ROWS - 2)*self.fontHeight + half)
|
||||
qp.drawLine(-5, cursorY * self.fontHeight + self.fontHeight // 2, -30, cursorY * self.fontHeight + half)
|
||||
qp.drawLine(-30, cursorY * self.fontHeight + self.fontHeight // 2, -30,
|
||||
(self.ROWS - 2) * self.fontHeight + half)
|
||||
|
||||
# draw arrow
|
||||
points = [QtCore.QPoint(-25, (self.ROWS - 2)*self.fontHeight + half),
|
||||
QtCore.QPoint(-35, (self.ROWS - 2)*self.fontHeight + half),
|
||||
QtCore.QPoint(-30, (self.ROWS - 2)*self.fontHeight + 2*half), ]
|
||||
points = [QtCore.QPoint(-25, (self.ROWS - 2) * self.fontHeight + half),
|
||||
QtCore.QPoint(-35, (self.ROWS - 2) * self.fontHeight + half),
|
||||
QtCore.QPoint(-30, (self.ROWS - 2) * self.fontHeight + 2 * half), ]
|
||||
needle = QtGui.QPolygon(points)
|
||||
qp.setBrush(QtGui.QBrush(QtGui.QColor(0, 128, 0)))
|
||||
qp.drawPolygon(needle)
|
||||
@ -453,24 +452,22 @@ class DisasmViewMode(ViewMode):
|
||||
qp.setPen(QtGui.QPen(QtGui.QColor(0, 192, 0), 1, QtCore.Qt.DotLine))
|
||||
|
||||
# draw the two lines
|
||||
qp.drawLine(-5, cursorY*self.fontHeight + self.fontHeight // 2, -30, cursorY*self.fontHeight + half)
|
||||
qp.drawLine(-30, cursorY*self.fontHeight + self.fontHeight // 2, -30, (1)*self.fontHeight + half)
|
||||
qp.drawLine(-5, cursorY * self.fontHeight + self.fontHeight // 2, -30, cursorY * self.fontHeight + half)
|
||||
qp.drawLine(-30, cursorY * self.fontHeight + self.fontHeight // 2, -30, (1) * self.fontHeight + half)
|
||||
|
||||
# draw arrow
|
||||
points = [QtCore.QPoint(-25, (1)*self.fontHeight + half),
|
||||
QtCore.QPoint(-35, (1)*self.fontHeight + half),
|
||||
QtCore.QPoint(-30, (1)*self.fontHeight), ]
|
||||
points = [QtCore.QPoint(-25, (1) * self.fontHeight + half),
|
||||
QtCore.QPoint(-35, (1) * self.fontHeight + half),
|
||||
QtCore.QPoint(-30, (1) * self.fontHeight), ]
|
||||
needle = QtGui.QPolygon(points)
|
||||
qp.setBrush(QtGui.QBrush(QtGui.QColor(0, 128, 0)))
|
||||
qp.drawPolygon(needle)
|
||||
|
||||
|
||||
|
||||
def draw(self, refresh=False):
|
||||
if self.dataModel.getOffset() in self.Paints:
|
||||
self.refresh = False
|
||||
self.qpix = QtGui.QPixmap(self.Paints[self.dataModel.getOffset()])
|
||||
#print 'hit'
|
||||
# print 'hit'
|
||||
self.drawAdditionals()
|
||||
return
|
||||
|
||||
@ -478,27 +475,27 @@ class DisasmViewMode(ViewMode):
|
||||
qp = QtGui.QPainter()
|
||||
qp.begin(self.qpix)
|
||||
# viewport
|
||||
#qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
|
||||
# qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
|
||||
|
||||
#start = time()
|
||||
# start = time()
|
||||
self.drawTextMode(qp)
|
||||
#end = time() - start
|
||||
#print 'Time ' + str(end)
|
||||
# end = time() - start
|
||||
# print 'Time ' + str(end)
|
||||
self.refresh = False
|
||||
qp.end()
|
||||
|
||||
# self.Paints[self.dataModel.getOffset()] = QtGui.QPixmap(self.qpix)
|
||||
# self.Paints[self.dataModel.getOffset()] = QtGui.QPixmap(self.qpix)
|
||||
self.drawAdditionals()
|
||||
|
||||
def drawAdditionals(self):
|
||||
self.newPix = self._getNewPixmap(self.width, self.height + self.SPACER)
|
||||
qp = QtGui.QPainter()
|
||||
qp.begin(self.newPix)
|
||||
qp.setWindow(-50, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight)
|
||||
qp.setWindow(-50, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight)
|
||||
|
||||
qp.drawPixmap(0, 0, self.qpix)
|
||||
|
||||
#self.transformationEngine.decorateText()
|
||||
# self.transformationEngine.decorateText()
|
||||
|
||||
# highlight selected text
|
||||
self.selector.highlightText()
|
||||
@ -529,7 +526,6 @@ class DisasmViewMode(ViewMode):
|
||||
return self.plugin.hintDisasmVA(offset)
|
||||
return 0
|
||||
|
||||
|
||||
def _drawRow(self, qp, cemu, row, asm, offset=-1):
|
||||
print('DRAW AN INSTRUCTION', asm, row, asm.get_name(), len(asm.get_operands(offset)), hex(self.getPageOffset()))
|
||||
|
||||
@ -541,12 +537,12 @@ class DisasmViewMode(ViewMode):
|
||||
cemu.writeAt(0, row, hex_data)
|
||||
|
||||
# fill with spaces
|
||||
cemu.write((MNEMONIC_COLUMN - len(hex_data))*' ')
|
||||
cemu.write((MNEMONIC_COLUMN - len(hex_data)) * ' ')
|
||||
|
||||
# let's color some branch instr
|
||||
#if asm.isBranch():
|
||||
# if asm.isBranch():
|
||||
# qp.setPen(QtGui.QPen(QtGui.QColor(255, 80, 0)))
|
||||
#else:
|
||||
# else:
|
||||
qp.setPen(QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine))
|
||||
|
||||
mnemonic = asm.get_name()
|
||||
@ -577,7 +573,7 @@ class DisasmViewMode(ViewMode):
|
||||
cemu.write('; "{0}"'.format(' '.join(comments)))
|
||||
|
||||
def _write_operands(self, asm, qp, cemu, offset):
|
||||
qp.setPen(QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine))
|
||||
qp.setPen(QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine))
|
||||
|
||||
operands = asm.get_operands(offset)
|
||||
for operand in operands:
|
||||
@ -632,7 +628,7 @@ class DisasmViewMode(ViewMode):
|
||||
qp.save()
|
||||
if tok.type == 'REGISTER':
|
||||
qp.setPen(QtGui.QPen(QtGui.QColor('white')))
|
||||
|
||||
|
||||
if tok.type == 'NUMBER':
|
||||
qp.setPen(QtGui.QPen(QtGui.QColor('green')))
|
||||
|
||||
@ -647,12 +643,12 @@ class DisasmViewMode(ViewMode):
|
||||
def drawTextMode(self, qp):
|
||||
print('OFFSET', self.dataModel.getOffset())
|
||||
# draw background
|
||||
qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
|
||||
qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
|
||||
|
||||
# set text pen&font
|
||||
qp.setFont(self.font)
|
||||
qp.setPen(self.textPen)
|
||||
|
||||
|
||||
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
|
||||
|
||||
offset = 0
|
||||
@ -662,7 +658,6 @@ class DisasmViewMode(ViewMode):
|
||||
self._drawRow(qp, cemu, i, asm, offset)
|
||||
offset += asm.get_length()
|
||||
|
||||
|
||||
def _getRowInPage(self, offset):
|
||||
|
||||
offset -= self.dataModel.getOffset()
|
||||
@ -681,23 +676,23 @@ class DisasmViewMode(ViewMode):
|
||||
if i == row:
|
||||
return size
|
||||
|
||||
size += asm.get_length()
|
||||
size += asm.get_length()
|
||||
|
||||
return None
|
||||
|
||||
def goTo(self, offset):
|
||||
print("GOTO ", offset)
|
||||
|
||||
|
||||
tsize = sum([opcode.get_length() for opcode in self.OPCODES])
|
||||
|
||||
if offset < self.dataModel.getOffset() + tsize and offset > self.dataModel.getOffset():
|
||||
# if in current page, move cursor
|
||||
row = self._getRowInPage(offset)
|
||||
off_row = self._getOffsetOfRow(row)
|
||||
diff = offset - self.dataModel.getOffset() - off_row# self.OPCODES[row].size
|
||||
diff = offset - self.dataModel.getOffset() - off_row # self.OPCODES[row].size
|
||||
|
||||
if row is not None:
|
||||
self.cursor.moveAbsolute((diff)*3, row)
|
||||
self.cursor.moveAbsolute((diff) * 3, row)
|
||||
|
||||
self.draw(refresh=False)
|
||||
else:
|
||||
@ -707,15 +702,14 @@ class DisasmViewMode(ViewMode):
|
||||
self.cursor.moveAbsolute(0, 0)
|
||||
self.draw(refresh=True)
|
||||
|
||||
#TODO: getDisplayablePage() won't contain what we want to disasm. we will use dataModel
|
||||
# TODO: getDisplayablePage() won't contain what we want to disasm. we will use dataModel
|
||||
# in this view, getDisplayablePage will contain disasm text, because that is what is displayed
|
||||
|
||||
if self.widget:
|
||||
self.widget.update()
|
||||
|
||||
|
||||
def scrollPages(self, number, cachePix=None, pageOffset=None):
|
||||
self.scroll(0, -number*self.ROWS, cachePix=cachePix, pageOffset=pageOffset)
|
||||
self.scroll(0, -number * self.ROWS, cachePix=cachePix, pageOffset=pageOffset)
|
||||
|
||||
def scroll_v(self, dy, cachePix=None, pageOffset=None):
|
||||
print('scroll_v', dy, cachePix, pageOffset, hex(self.getCursorAbsolutePosition()))
|
||||
@ -745,7 +739,7 @@ class DisasmViewMode(ViewMode):
|
||||
current_offset = self.dataModel.getOffset()
|
||||
current_idx = self.CACHE_IDX_OPCODES_OFF[current_offset]
|
||||
print("IDX", current_idx, hex(current_offset))
|
||||
#start = self.CACHE_OPCODES[self.CACHE_IDX_OPCODES_OFF[self.getCursorAbsolutePosition()]-1]
|
||||
# start = self.CACHE_OPCODES[self.CACHE_IDX_OPCODES_OFF[self.getCursorAbsolutePosition()]-1]
|
||||
current_idx -= 1
|
||||
|
||||
newins = self.CACHE_OPCODES[current_idx]
|
||||
@ -754,7 +748,6 @@ class DisasmViewMode(ViewMode):
|
||||
self.dataModel.slide(self.OPCODES[0].get_length())
|
||||
del self.OPCODES[0]
|
||||
|
||||
|
||||
if dy >= 0:
|
||||
self.dataModel.slide(-newins.get_length())
|
||||
del self.OPCODES[len(self.OPCODES) - 1]
|
||||
@ -774,11 +767,11 @@ class DisasmViewMode(ViewMode):
|
||||
print('ROW TO DRAW', RowsToDraw)
|
||||
if len(RowsToDraw) < abs(dy):
|
||||
# maybe we couldn't draw dy rows (possible we reached the beginning of the data to early), recalculate dy
|
||||
dy = len(RowsToDraw)*dy/abs(dy)
|
||||
dy = len(RowsToDraw) * dy / abs(dy)
|
||||
factor = abs(dy)
|
||||
|
||||
if not cachePix:
|
||||
self.qpix.scroll(0, dy*self.fontHeight, self.qpix.rect())
|
||||
self.qpix.scroll(0, dy * self.fontHeight, self.qpix.rect())
|
||||
|
||||
qp = QtGui.QPainter()
|
||||
if cachePix:
|
||||
@ -791,10 +784,11 @@ class DisasmViewMode(ViewMode):
|
||||
|
||||
# erase rows that will disappear
|
||||
if dy < 0:
|
||||
qp.fillRect(0, (self.ROWS-factor)*self.fontHeight, self.fontWidth*self.COLUMNS, factor * self.fontHeight, self.backgroundBrush)
|
||||
qp.fillRect(0, (self.ROWS - factor) * self.fontHeight, self.fontWidth * self.COLUMNS,
|
||||
factor * self.fontHeight, self.backgroundBrush)
|
||||
|
||||
if dy > 0:
|
||||
qp.fillRect(0, 0, self.fontWidth*self.COLUMNS, factor * self.fontHeight, self.backgroundBrush)
|
||||
qp.fillRect(0, 0, self.fontWidth * self.COLUMNS, factor * self.fontHeight, self.backgroundBrush)
|
||||
|
||||
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
|
||||
|
||||
@ -806,12 +800,13 @@ class DisasmViewMode(ViewMode):
|
||||
print('')
|
||||
|
||||
def scroll(self, dx, dy, cachePix=None, pageOffset=None):
|
||||
print('scroll ', dx, dy, self.dataModel.inLimits((self.dataModel.getOffset() - dx)), 'offset', self.dataModel.getOffset())
|
||||
print('scroll ', dx, dy, self.dataModel.inLimits((self.dataModel.getOffset() - dx)), 'offset',
|
||||
self.dataModel.getOffset())
|
||||
if dx != 0:
|
||||
if self.dataModel.inLimits((self.dataModel.getOffset() - dx)):
|
||||
self.dataModel.slide(dx)
|
||||
self.draw(refresh=True)
|
||||
#self.scroll_h(dx)
|
||||
# self.scroll_h(dx)
|
||||
|
||||
if dy != 0:
|
||||
if dy > 0:
|
||||
@ -822,13 +817,12 @@ class DisasmViewMode(ViewMode):
|
||||
if dy < 0:
|
||||
tsize = sum([asm.get_length() for asm in self.OPCODES])
|
||||
|
||||
if self.dataModel.getOffset() + tsize == self.dataModel.getDataSize():
|
||||
if self.dataModel.getOffset() + tsize == self.dataModel.getDataSize():
|
||||
print('END')
|
||||
return
|
||||
|
||||
self.scroll_v(dy, cachePix, pageOffset)
|
||||
|
||||
|
||||
def moveCursor(self, direction):
|
||||
cursorX, cursorY = self.cursor.getPosition()
|
||||
|
||||
@ -847,14 +841,13 @@ class DisasmViewMode(ViewMode):
|
||||
self.cursor.moveAbsolute(idx, cursorY - 1)
|
||||
else:
|
||||
x, dy = asm.getNextCursor(cursorX, direction=Directions.Left)
|
||||
self.cursor.move(-(cursorX-x), dy)
|
||||
|
||||
self.cursor.move(-(cursorX - x), dy)
|
||||
|
||||
if direction == Directions.Right:
|
||||
asm = self.OPCODES[cursorY]
|
||||
x, dy = asm.getNextCursor(cursorX, direction=Directions.Right)
|
||||
|
||||
if cursorY == self.ROWS-1 and dy > 0:
|
||||
if cursorY == self.ROWS - 1 and dy > 0:
|
||||
self.scroll(0, -1)
|
||||
self.cursor.moveAbsolute(0, cursorY)
|
||||
|
||||
@ -862,10 +855,10 @@ class DisasmViewMode(ViewMode):
|
||||
if cursorY + dy >= len(self.OPCODES):
|
||||
dy = 0
|
||||
|
||||
self.cursor.move(x-cursorX, dy)
|
||||
self.cursor.move(x - cursorX, dy)
|
||||
|
||||
if direction == Directions.Down:
|
||||
if cursorY == self.ROWS-1:
|
||||
if cursorY == self.ROWS - 1:
|
||||
# move cursor to first token
|
||||
self.scroll(0, -1)
|
||||
self.cursor.moveAbsolute(0, cursorY)
|
||||
@ -893,14 +886,13 @@ class DisasmViewMode(ViewMode):
|
||||
if direction == Directions.Home:
|
||||
self.cursor.moveAbsolute(0, 0)
|
||||
|
||||
|
||||
if direction == Directions.CtrlHome:
|
||||
self.goTo(0)
|
||||
|
||||
if direction == Directions.CtrlEnd:
|
||||
self.dataModel.slideToLastPage()
|
||||
self.draw(refresh=True)
|
||||
self.cursor.moveAbsolute(self.COLUMNS-1, self.ROWS-1)
|
||||
self.cursor.moveAbsolute(self.COLUMNS - 1, self.ROWS - 1)
|
||||
|
||||
def _followBranch(self):
|
||||
cursorX, cursorY = self.cursor.getPosition()
|
||||
@ -931,7 +923,8 @@ class DisasmViewMode(ViewMode):
|
||||
if event.type() == QtCore.QEvent.KeyPress:
|
||||
|
||||
if modifiers == QtCore.Qt.ShiftModifier:
|
||||
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up, QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
|
||||
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up,
|
||||
QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
|
||||
if key in keys:
|
||||
self.startSelection()
|
||||
|
||||
@ -959,11 +952,11 @@ class DisasmViewMode(ViewMode):
|
||||
if key == QtCore.Qt.Key_Home:
|
||||
self.moveCursor(Directions.CtrlHome)
|
||||
self.addop((self.draw,))
|
||||
#self.draw()
|
||||
# self.draw()
|
||||
|
||||
return True
|
||||
|
||||
else:#elif modifiers == QtCore.Qt.NoModifier:
|
||||
else: # elif modifiers == QtCore.Qt.NoModifier:
|
||||
|
||||
if key == QtCore.Qt.Key_Escape:
|
||||
self.selector.resetSelections()
|
||||
@ -972,37 +965,37 @@ class DisasmViewMode(ViewMode):
|
||||
if key == QtCore.Qt.Key_Left:
|
||||
self.moveCursor(Directions.Left)
|
||||
self.addop((self.draw,))
|
||||
#self.draw()
|
||||
# self.draw()
|
||||
|
||||
if key == QtCore.Qt.Key_Right:
|
||||
self.moveCursor(Directions.Right)
|
||||
self.addop((self.draw,))
|
||||
#self.draw()
|
||||
|
||||
# self.draw()
|
||||
|
||||
if key == QtCore.Qt.Key_Down:
|
||||
self.moveCursor(Directions.Down)
|
||||
self.addop((self.draw,))
|
||||
#self.draw()
|
||||
|
||||
# self.draw()
|
||||
|
||||
if key == QtCore.Qt.Key_End:
|
||||
self.moveCursor(Directions.End)
|
||||
self.addop((self.draw,))
|
||||
#self.draw()
|
||||
|
||||
# self.draw()
|
||||
|
||||
if key == QtCore.Qt.Key_Home:
|
||||
self.moveCursor(Directions.Home)
|
||||
self.addop((self.draw,))
|
||||
#self.draw()
|
||||
# self.draw()
|
||||
|
||||
if key == QtCore.Qt.Key_Up:
|
||||
self.moveCursor(Directions.Up)
|
||||
self.addop((self.draw,))
|
||||
#self.draw()
|
||||
|
||||
# self.draw()
|
||||
|
||||
if key == QtCore.Qt.Key_PageDown:
|
||||
self.addop((self.scrollPages, 1))
|
||||
self.addop((self.draw,))
|
||||
|
||||
|
||||
if key == QtCore.Qt.Key_PageUp:
|
||||
self.addop((self.scrollPages, -1))
|
||||
self.addop((self.draw,))
|
||||
|
@ -35,12 +35,12 @@ class HexViewMode(ViewMode):
|
||||
|
||||
# text font
|
||||
self.font = themes['font']
|
||||
|
||||
|
||||
# font metrics. assume font is monospaced
|
||||
self.font.setKerning(False)
|
||||
self.font.setFixedPitch(True)
|
||||
fm = QtGui.QFontMetrics(self.font)
|
||||
self._fontWidth = fm.width('a')
|
||||
self._fontWidth = fm.width('a')
|
||||
self._fontHeight = fm.height()
|
||||
|
||||
self.Special = string.ascii_letters + string.digits + ' .;\':;=\"?-!()/\\_'
|
||||
@ -50,7 +50,7 @@ class HexViewMode(ViewMode):
|
||||
self.cursor = cursor
|
||||
|
||||
self.HexColumns = [1, 4, 8, 16, 32, 36, 40]
|
||||
self.idxHexColumns = 3 # 32 columns
|
||||
self.idxHexColumns = 3 # 32 columns
|
||||
|
||||
self.newPix = None
|
||||
self.Ops = []
|
||||
@ -69,7 +69,6 @@ class HexViewMode(ViewMode):
|
||||
def fontHeight(self):
|
||||
return self._fontHeight
|
||||
|
||||
|
||||
def setTransformationEngine(self, engine):
|
||||
self.transformationEngine = engine
|
||||
self.original_textdecorator = engine
|
||||
@ -78,7 +77,7 @@ class HexViewMode(ViewMode):
|
||||
return QtGui.QPixmap(width, height)
|
||||
|
||||
def getPixmap(self):
|
||||
#return self.qpix
|
||||
# return self.qpix
|
||||
|
||||
for t in self.Ops:
|
||||
if len(t) == 1:
|
||||
@ -114,7 +113,7 @@ class HexViewMode(ViewMode):
|
||||
|
||||
def getCursorAbsolutePosition(self):
|
||||
x, y = self.cursor.getPosition()
|
||||
return self.dataModel.getOffset() + y*self.COLUMNS + x
|
||||
return self.dataModel.getOffset() + y * self.COLUMNS + x
|
||||
|
||||
def computeTextArea(self):
|
||||
self.COLUMNS = self.HexColumns[self.idxHexColumns]
|
||||
@ -123,8 +122,8 @@ class HexViewMode(ViewMode):
|
||||
self.notify(self.ROWS, self.COLUMNS)
|
||||
|
||||
def resize(self, width, height):
|
||||
self.width = width - width%self.fontWidth
|
||||
self.height = height - height%self.fontHeight
|
||||
self.width = width - width % self.fontWidth
|
||||
self.height = height - height % self.fontHeight
|
||||
self.computeTextArea()
|
||||
self.qpix = self._getNewPixmap(self.width, self.height + self.SPACER)
|
||||
self.refresh = True
|
||||
@ -136,13 +135,12 @@ class HexViewMode(ViewMode):
|
||||
self.idxHexColumns += 1
|
||||
|
||||
# if screen is ont big enough, retry
|
||||
if self.HexColumns[self.idxHexColumns]*(3+1) + self.gap >= self.CON_COLUMNS:
|
||||
if self.HexColumns[self.idxHexColumns] * (3 + 1) + self.gap >= self.CON_COLUMNS:
|
||||
self.changeHexColumns()
|
||||
return
|
||||
|
||||
self.resize(self.width, self.height)
|
||||
|
||||
|
||||
def scroll(self, dx, dy):
|
||||
if dx != 0:
|
||||
if self.dataModel.inLimits((self.dataModel.getOffset() - dx)):
|
||||
@ -150,13 +148,13 @@ class HexViewMode(ViewMode):
|
||||
self.scroll_h(dx)
|
||||
|
||||
if dy != 0:
|
||||
if self.dataModel.inLimits((self.dataModel.getOffset() - dy*self.COLUMNS)):
|
||||
self.dataModel.slide(-dy*self.COLUMNS)
|
||||
if self.dataModel.inLimits((self.dataModel.getOffset() - dy * self.COLUMNS)):
|
||||
self.dataModel.slide(-dy * self.COLUMNS)
|
||||
self.scroll_v(dy)
|
||||
else:
|
||||
if dy <= 0:
|
||||
pass
|
||||
#self.dataModel.slideToLastPage()
|
||||
# self.dataModel.slideToLastPage()
|
||||
else:
|
||||
self.dataModel.slideToFirstPage()
|
||||
self.draw(refresh=True)
|
||||
@ -164,7 +162,7 @@ class HexViewMode(ViewMode):
|
||||
self.draw()
|
||||
|
||||
def scrollPages(self, number):
|
||||
self.scroll(0, -number*self.ROWS)
|
||||
self.scroll(0, -number * self.ROWS)
|
||||
|
||||
def drawAdditionals(self):
|
||||
self.newPix = self._getNewPixmap(self.width, self.height + self.SPACER)
|
||||
@ -172,7 +170,7 @@ class HexViewMode(ViewMode):
|
||||
qp.begin(self.newPix)
|
||||
qp.drawPixmap(0, 0, self.qpix)
|
||||
|
||||
#self.transformationEngine.decorateText()
|
||||
# self.transformationEngine.decorateText()
|
||||
|
||||
# highlight selected text
|
||||
self.selector.highlightText()
|
||||
@ -187,19 +185,20 @@ class HexViewMode(ViewMode):
|
||||
for i in range(self.COLUMNS // 4)[1:]:
|
||||
xw = i * 4 * 3 * self.fontWidth - 4
|
||||
qp.setPen(QtGui.QColor(0, 255, 0))
|
||||
qp.drawLine(xw, 0, xw, self.ROWS*self.fontHeight)
|
||||
|
||||
qp.drawLine(xw, 0, xw, self.ROWS * self.fontHeight)
|
||||
|
||||
qp.end()
|
||||
|
||||
|
||||
def scroll_h(self, dx):
|
||||
gap = self.gap
|
||||
|
||||
# hex part
|
||||
self.qpix.scroll(dx*3*self.fontWidth, 0, QtCore.QRect(0, 0, self.COLUMNS*3*self.fontWidth, self.ROWS*self.fontHeight + self.SPACER))
|
||||
self.qpix.scroll(dx * 3 * self.fontWidth, 0, QtCore.QRect(0, 0, self.COLUMNS * 3 * self.fontWidth,
|
||||
self.ROWS * self.fontHeight + self.SPACER))
|
||||
# text part
|
||||
self.qpix.scroll(dx*self.fontWidth, 0, QtCore.QRect((self.COLUMNS*3 + gap)*self.fontWidth , 0, self.COLUMNS*self.fontWidth, self.ROWS*self.fontHeight + self.SPACER))
|
||||
self.qpix.scroll(dx * self.fontWidth, 0,
|
||||
QtCore.QRect((self.COLUMNS * 3 + gap) * self.fontWidth, 0, self.COLUMNS * self.fontWidth,
|
||||
self.ROWS * self.fontHeight + self.SPACER))
|
||||
|
||||
qp = QtGui.QPainter()
|
||||
|
||||
@ -212,17 +211,21 @@ class HexViewMode(ViewMode):
|
||||
# There are some trails from the characters, when scrolling. trail == number of pixel to erase near the character
|
||||
trail = 5
|
||||
|
||||
textBegining = self.COLUMNS*3 + gap
|
||||
textBegining = self.COLUMNS * 3 + gap
|
||||
if dx < 0:
|
||||
# hex
|
||||
qp.fillRect((self.COLUMNS - 1*factor)*3*self.fontWidth, 0, factor * self.fontWidth * 3, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
qp.fillRect((self.COLUMNS - 1 * factor) * 3 * self.fontWidth, 0, factor * self.fontWidth * 3,
|
||||
self.ROWS * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
# text
|
||||
qp.fillRect((textBegining + self.COLUMNS - 1*factor)*self.fontWidth, 0, factor * self.fontWidth+trail, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
qp.fillRect((textBegining + self.COLUMNS - 1 * factor) * self.fontWidth, 0, factor * self.fontWidth + trail,
|
||||
self.ROWS * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
if dx > 0:
|
||||
# hex
|
||||
qp.fillRect(0, 0, factor * 3 * self.fontWidth, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
qp.fillRect(0, 0, factor * 3 * self.fontWidth, self.ROWS * self.fontHeight + self.SPACER,
|
||||
self.backgroundBrush)
|
||||
# text
|
||||
qp.fillRect(textBegining*self.fontWidth - trail, 0, factor * self.fontWidth + trail, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
qp.fillRect(textBegining * self.fontWidth - trail, 0, factor * self.fontWidth + trail,
|
||||
self.ROWS * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
|
||||
cemu = ConsoleEmulator(qp, self.ROWS, self.CON_COLUMNS)
|
||||
|
||||
@ -234,9 +237,9 @@ class HexViewMode(ViewMode):
|
||||
|
||||
if dx < 0:
|
||||
# cu (column) selectam coloana
|
||||
idx = (i+1)*(self.COLUMNS) - (column + 1)
|
||||
idx = (i + 1) * (self.COLUMNS) - (column + 1)
|
||||
if dx > 0:
|
||||
idx = (i)*(self.COLUMNS) + (column)
|
||||
idx = (i) * (self.COLUMNS) + (column)
|
||||
|
||||
if len(self.getDisplayablePage()) > idx:
|
||||
qp.setPen(self.transformationEngine.choosePen(idx))
|
||||
@ -252,11 +255,11 @@ class HexViewMode(ViewMode):
|
||||
hex_s = str(hex(c)[2:]).zfill(2) + ' '
|
||||
|
||||
if dx < 0:
|
||||
cemu.writeAt((self.COLUMNS - (column + 1))*3, i, hex_s, noBackgroudOnSpaces=True)
|
||||
cemu.writeAt((self.COLUMNS - (column + 1)) * 3, i, hex_s, noBackgroudOnSpaces=True)
|
||||
cemu.writeAt(textBegining + self.COLUMNS - (column + 1), i, self.cp437(c))
|
||||
|
||||
if dx > 0:
|
||||
cemu.writeAt((column)*3, i, hex_s, noBackgroudOnSpaces=True)
|
||||
cemu.writeAt((column) * 3, i, hex_s, noBackgroudOnSpaces=True)
|
||||
cemu.writeAt(textBegining + column, i, self.cp437(c))
|
||||
|
||||
qp.setBackgroundMode(0)
|
||||
@ -264,7 +267,7 @@ class HexViewMode(ViewMode):
|
||||
qp.end()
|
||||
|
||||
def scroll_v(self, dy):
|
||||
self.qpix.scroll(0, dy*self.fontHeight, self.qpix.rect())
|
||||
self.qpix.scroll(0, dy * self.fontHeight, self.qpix.rect())
|
||||
|
||||
qp = QtGui.QPainter()
|
||||
|
||||
@ -278,12 +281,12 @@ class HexViewMode(ViewMode):
|
||||
|
||||
if dy < 0:
|
||||
cemu.gotoXY(0, self.ROWS - factor)
|
||||
qp.fillRect(0, (self.ROWS-factor)*self.fontHeight, self.fontWidth*self.CON_COLUMNS, factor * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
qp.fillRect(0, (self.ROWS - factor) * self.fontHeight, self.fontWidth * self.CON_COLUMNS,
|
||||
factor * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
|
||||
if dy > 0:
|
||||
cemu.gotoXY(0, 0)
|
||||
qp.fillRect(0, 0, self.fontWidth*self.CON_COLUMNS, factor * self.fontHeight, self.backgroundBrush)
|
||||
|
||||
qp.fillRect(0, 0, self.fontWidth * self.CON_COLUMNS, factor * self.fontHeight, self.backgroundBrush)
|
||||
|
||||
page = self.transformationEngine.decorate()
|
||||
|
||||
@ -295,9 +298,9 @@ class HexViewMode(ViewMode):
|
||||
if dy < 0:
|
||||
# we write from top-down, so get index of the first row that will be displayed
|
||||
# this is why we have factor - row
|
||||
idx = i + (self.ROWS - (factor - row))*self.COLUMNS
|
||||
idx = i + (self.ROWS - (factor - row)) * self.COLUMNS
|
||||
if dy > 0:
|
||||
idx = i + (self.COLUMNS*row)
|
||||
idx = i + (self.COLUMNS * row)
|
||||
|
||||
qp.setPen(self.transformationEngine.choosePen(idx))
|
||||
|
||||
@ -321,14 +324,13 @@ class HexViewMode(ViewMode):
|
||||
# save hex position
|
||||
x, y = cemu.getXY()
|
||||
# write text
|
||||
cemu.writeAt(self.COLUMNS*3 + self.gap + (i%self.COLUMNS), y, self.cp437(c))
|
||||
cemu.writeAt(self.COLUMNS * 3 + self.gap + (i % self.COLUMNS), y, self.cp437(c))
|
||||
|
||||
# go back to hex chars
|
||||
cemu.gotoXY(x, y)
|
||||
|
||||
qp.setBackgroundMode(0)
|
||||
|
||||
|
||||
cemu.writeLn()
|
||||
qp.end()
|
||||
|
||||
@ -349,7 +351,8 @@ class HexViewMode(ViewMode):
|
||||
def drawTextMode(self, qp, row=0, howMany=1):
|
||||
|
||||
# draw background
|
||||
qp.fillRect(0, row * self.fontHeight, self.CON_COLUMNS * self.fontWidth, howMany * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
qp.fillRect(0, row * self.fontHeight, self.CON_COLUMNS * self.fontWidth,
|
||||
howMany * self.fontHeight + self.SPACER, self.backgroundBrush)
|
||||
|
||||
# set text pen&font
|
||||
qp.setFont(self.font)
|
||||
@ -361,11 +364,12 @@ class HexViewMode(ViewMode):
|
||||
|
||||
cemu.gotoXY(0, row)
|
||||
|
||||
for i, c in enumerate(self.getDisplayablePage()[row*self.COLUMNS:(row + howMany)*self.COLUMNS]): #TODO: does not apply all decorators
|
||||
for i, c in enumerate(self.getDisplayablePage()[row * self.COLUMNS:(
|
||||
row + howMany) * self.COLUMNS]): # TODO: does not apply all decorators
|
||||
|
||||
w = i + row*self.COLUMNS
|
||||
w = i + row * self.COLUMNS
|
||||
|
||||
if (w+1)%self.COLUMNS == 0:
|
||||
if (w + 1) % self.COLUMNS == 0:
|
||||
hex_s = str(hex(c)[2:]).zfill(2)
|
||||
else:
|
||||
hex_s = str(hex(c)[2:]).zfill(2) + ' '
|
||||
@ -381,16 +385,16 @@ class HexViewMode(ViewMode):
|
||||
# save hex position
|
||||
x, y = cemu.getXY()
|
||||
# write text
|
||||
cemu.writeAt(self.COLUMNS*3 + self.gap + (w%self.COLUMNS), y, self.cp437(c))
|
||||
cemu.writeAt(self.COLUMNS * 3 + self.gap + (w % self.COLUMNS), y, self.cp437(c))
|
||||
# go back to hex chars
|
||||
cemu.gotoXY(x, y)
|
||||
if (w+1)%self.COLUMNS == 0:
|
||||
if (w + 1) % self.COLUMNS == 0:
|
||||
cemu.writeLn()
|
||||
|
||||
qp.setBackgroundMode(0)
|
||||
|
||||
def moveCursor(self, direction):
|
||||
#TODO: have to move this, don't like it
|
||||
# TODO: have to move this, don't like it
|
||||
if self.isInEditMode():
|
||||
if self.highpart == False:
|
||||
self.highpart = True
|
||||
@ -402,31 +406,29 @@ class HexViewMode(ViewMode):
|
||||
if cursorY == 0:
|
||||
self.scroll(1, 0)
|
||||
else:
|
||||
self.cursor.moveAbsolute(self.COLUMNS-1, cursorY - 1)
|
||||
self.cursor.moveAbsolute(self.COLUMNS - 1, cursorY - 1)
|
||||
else:
|
||||
self.cursor.move(-1, 0)
|
||||
|
||||
|
||||
if direction == Directions.Right:
|
||||
if self.getCursorAbsolutePosition() + 1 >= self.dataModel.getDataSize():
|
||||
return
|
||||
|
||||
if cursorX == self.COLUMNS-1:
|
||||
if cursorY == self.ROWS-1:
|
||||
if cursorX == self.COLUMNS - 1:
|
||||
if cursorY == self.ROWS - 1:
|
||||
self.scroll(-1, 0)
|
||||
else:
|
||||
self.cursor.moveAbsolute(0, cursorY + 1)
|
||||
else:
|
||||
self.cursor.move(1, 0)
|
||||
|
||||
|
||||
if direction == Directions.Down:
|
||||
if self.getCursorAbsolutePosition() + self.COLUMNS >= self.dataModel.getDataSize():
|
||||
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize()-1)
|
||||
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize() - 1)
|
||||
self.cursor.moveAbsolute(x, y)
|
||||
return
|
||||
|
||||
if cursorY == self.ROWS-1:
|
||||
if cursorY == self.ROWS - 1:
|
||||
self.scroll(0, -1)
|
||||
else:
|
||||
self.cursor.move(0, 1)
|
||||
@ -439,11 +441,11 @@ class HexViewMode(ViewMode):
|
||||
|
||||
if direction == Directions.End:
|
||||
if self.dataModel.getDataSize() < self.getCursorAbsolutePosition() + self.ROWS * self.COLUMNS:
|
||||
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize()-1)
|
||||
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize() - 1)
|
||||
self.cursor.moveAbsolute(x, y)
|
||||
|
||||
else:
|
||||
self.cursor.moveAbsolute(self.COLUMNS-1, self.ROWS-1)
|
||||
self.cursor.moveAbsolute(self.COLUMNS - 1, self.ROWS - 1)
|
||||
|
||||
if direction == Directions.Home:
|
||||
self.cursor.moveAbsolute(0, 0)
|
||||
@ -458,8 +460,6 @@ class HexViewMode(ViewMode):
|
||||
self.draw(refresh=True)
|
||||
self.moveCursor(Directions.End)
|
||||
|
||||
|
||||
|
||||
def drawCursor(self, qp):
|
||||
qp.setBrush(QtGui.QColor(255, 255, 0))
|
||||
if self.isInEditMode():
|
||||
@ -469,7 +469,7 @@ class HexViewMode(ViewMode):
|
||||
|
||||
columns = self.HexColumns[self.idxHexColumns]
|
||||
if cursorX > columns:
|
||||
self.cursor.moveAbsolute(columns-1, cursorY)
|
||||
self.cursor.moveAbsolute(columns - 1, cursorY)
|
||||
|
||||
# get cursor position again, maybe it was moved
|
||||
cursorX, cursorY = self.cursor.getPosition()
|
||||
@ -478,41 +478,42 @@ class HexViewMode(ViewMode):
|
||||
if self.isInEditMode():
|
||||
qp.setOpacity(0.5)
|
||||
# cursor on text
|
||||
qp.drawRect((self.COLUMNS*3 + self.gap + cursorX)*self.fontWidth, cursorY*self.fontHeight+2, self.fontWidth, self.fontHeight)
|
||||
qp.drawRect((self.COLUMNS * 3 + self.gap + cursorX) * self.fontWidth, cursorY * self.fontHeight + 2,
|
||||
self.fontWidth, self.fontHeight)
|
||||
|
||||
# cursor on hex
|
||||
if not self.isInEditMode():
|
||||
qp.drawRect(cursorX*3*self.fontWidth, cursorY*self.fontHeight+2, 2*self.fontWidth, self.fontHeight)
|
||||
qp.drawRect(cursorX * 3 * self.fontWidth, cursorY * self.fontHeight + 2, 2 * self.fontWidth,
|
||||
self.fontHeight)
|
||||
else:
|
||||
if self.highpart:
|
||||
qp.drawRect(cursorX*3*self.fontWidth, cursorY*self.fontHeight+2, 1*self.fontWidth, self.fontHeight)
|
||||
qp.drawRect(cursorX * 3 * self.fontWidth, cursorY * self.fontHeight + 2, 1 * self.fontWidth,
|
||||
self.fontHeight)
|
||||
else:
|
||||
qp.drawRect(cursorX*3*self.fontWidth + self.fontWidth, cursorY*self.fontHeight+2, 1*self.fontWidth, self.fontHeight)
|
||||
qp.drawRect(cursorX * 3 * self.fontWidth + self.fontWidth, cursorY * self.fontHeight + 2,
|
||||
1 * self.fontWidth, self.fontHeight)
|
||||
|
||||
qp.setOpacity(1)
|
||||
|
||||
def keyFilter(self):
|
||||
return [
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Right),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Left),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Up),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Down),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_End),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Home),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Right),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Left),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Up),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Down),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_End),
|
||||
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Home),
|
||||
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Right),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Left),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Up),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Down),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_End),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Home),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageDown),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageUp)
|
||||
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Right),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Left),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Up),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Down),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_End),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Home),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageDown),
|
||||
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageUp)
|
||||
|
||||
|
||||
]
|
||||
|
||||
]
|
||||
|
||||
def anon(self, dx, dy):
|
||||
self.scroll(dx, dy)
|
||||
@ -532,7 +533,8 @@ class HexViewMode(ViewMode):
|
||||
|
||||
def handleEditMode(self, modifiers, key, event):
|
||||
|
||||
if str(event.text()).lower() in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']:
|
||||
if str(event.text()).lower() in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
|
||||
'f']:
|
||||
|
||||
offs = self.getCursorOffsetInPage()
|
||||
|
||||
@ -544,10 +546,9 @@ class HexViewMode(ViewMode):
|
||||
|
||||
# compute nibble
|
||||
if self.highpart:
|
||||
b = ((z << 4) | (b & 0x0F)) & 0xFF
|
||||
b = ((z << 4) | (b & 0x0F)) & 0xFF
|
||||
else:
|
||||
b = ((b & 0xF0) | (z & 0x0F)) & 0xFF
|
||||
|
||||
b = ((b & 0xF0) | (z & 0x0F)) & 0xFF
|
||||
|
||||
block = modifiers == QtCore.Qt.AltModifier and self.selector.getCurrentSelection()
|
||||
|
||||
@ -560,20 +561,24 @@ class HexViewMode(ViewMode):
|
||||
for x in range(u, v):
|
||||
b = self.dataModel.getBYTE(x)
|
||||
if self.highpart:
|
||||
b = ((z << 4) | (b & 0x0F)) & 0xFF
|
||||
b = ((z << 4) | (b & 0x0F)) & 0xFF
|
||||
else:
|
||||
b = ((b & 0xF0) | (z & 0x0F)) & 0xFF
|
||||
b = ((b & 0xF0) | (z & 0x0F)) & 0xFF
|
||||
|
||||
self.dataModel.setData_b(x, chr(b))
|
||||
else:
|
||||
self.dataModel.setData_b(self.dataModel.getOffset() + offs, chr(b))
|
||||
|
||||
if block:
|
||||
self.transformationEngine = RangePen(self.original_textdecorator, u, v, QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine), ignoreHighlights=True)
|
||||
self.transformationEngine = RangePen(self.original_textdecorator, u, v,
|
||||
QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine),
|
||||
ignoreHighlights=True)
|
||||
else:
|
||||
z = self.dataModel.getOffset() + offs
|
||||
#TODO: sa nu se repete, tre original_transformengine
|
||||
self.transformationEngine = RangePen(self.original_textdecorator, z, z + 0, QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine), ignoreHighlights=True)
|
||||
# TODO: sa nu se repete, tre original_transformengine
|
||||
self.transformationEngine = RangePen(self.original_textdecorator, z, z + 0,
|
||||
QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine),
|
||||
ignoreHighlights=True)
|
||||
|
||||
# se if we are at end of row, we must also redraw previous line
|
||||
highpart = self.highpart
|
||||
@ -597,8 +602,7 @@ class HexViewMode(ViewMode):
|
||||
else:
|
||||
self.draw(refresh=True, row=y, howMany=1)
|
||||
if y > old_y:
|
||||
self.draw(refresh=True, row=y-1, howMany=1)
|
||||
|
||||
self.draw(refresh=True, row=y - 1, howMany=1)
|
||||
|
||||
def handleKeyEvent(self, modifiers, key, event=None):
|
||||
if event.type() == QtCore.QEvent.KeyRelease:
|
||||
@ -609,7 +613,8 @@ class HexViewMode(ViewMode):
|
||||
if event.type() == QtCore.QEvent.KeyPress:
|
||||
|
||||
if modifiers == QtCore.Qt.ShiftModifier:
|
||||
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up, QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
|
||||
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up,
|
||||
QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
|
||||
if key in keys:
|
||||
self.startSelection()
|
||||
|
||||
@ -621,7 +626,6 @@ class HexViewMode(ViewMode):
|
||||
self.add_annotation(1)
|
||||
return True
|
||||
|
||||
|
||||
if modifiers == QtCore.Qt.ControlModifier:
|
||||
if key == QtCore.Qt.Key_A:
|
||||
self.add_annotation(2)
|
||||
@ -632,7 +636,6 @@ class HexViewMode(ViewMode):
|
||||
if key == QtCore.Qt.Key_Left:
|
||||
self.addop((self.scroll, 1, 0))
|
||||
|
||||
|
||||
if key == QtCore.Qt.Key_Down:
|
||||
self.addop((self.anon, 0, -1))
|
||||
|
||||
@ -649,7 +652,7 @@ class HexViewMode(ViewMode):
|
||||
|
||||
return True
|
||||
|
||||
else:#selif modifiers == QtCore.Qt.NoModifier:
|
||||
else: # selif modifiers == QtCore.Qt.NoModifier:
|
||||
|
||||
if key == QtCore.Qt.Key_Escape:
|
||||
self.selector.resetSelections()
|
||||
@ -691,7 +694,7 @@ class HexViewMode(ViewMode):
|
||||
|
||||
columns = self.HexColumns[self.idxHexColumns]
|
||||
if x > columns:
|
||||
self.cursor.moveAbsolute(columns-1, y)
|
||||
self.cursor.moveAbsolute(columns - 1, y)
|
||||
self.addop((self.draw,))
|
||||
|
||||
if self.isInEditMode():
|
||||
@ -720,10 +723,9 @@ class HexViewMode(ViewMode):
|
||||
for i in range(self.HexColumns[self.idxHexColumns]):
|
||||
s += '{0} '.format('{0:x}'.format(i).zfill(2))
|
||||
|
||||
s += self.gap*' ' + 'Text'
|
||||
s += self.gap * ' ' + 'Text'
|
||||
return s
|
||||
|
||||
|
||||
def annotationWindow(self):
|
||||
w = self.ann_w.treeWidget
|
||||
|
||||
@ -733,18 +735,18 @@ class HexViewMode(ViewMode):
|
||||
|
||||
self.ann_w.show()
|
||||
|
||||
|
||||
@QtCore.pyqtSlot("QItemSelection, QItemSelection")
|
||||
def selectionChanged(self, selected, deselected):
|
||||
|
||||
item = self.ann_w.treeWidget.currentItem()
|
||||
item = self.ann_w.treeWidget.currentItem()
|
||||
|
||||
if item:
|
||||
if item:
|
||||
offset = item.getOffset()
|
||||
size = item.getSize()
|
||||
u = offset
|
||||
v = offset + size
|
||||
self.selector.addSelection((u, v, QtGui.QBrush(QtGui.QColor(125, 255, 0)), 0.2), type=TextSelection.SelectionType.NORMAL)
|
||||
self.selector.addSelection((u, v, QtGui.QBrush(QtGui.QColor(125, 255, 0)), 0.2),
|
||||
type=TextSelection.SelectionType.NORMAL)
|
||||
self.goTo(u)
|
||||
|
||||
@QtCore.pyqtSlot("QTreeWidgetItem*, int")
|
||||
@ -753,7 +755,6 @@ class HexViewMode(ViewMode):
|
||||
ID_NAME = 0
|
||||
ID_DESCRIPTION = 4
|
||||
|
||||
|
||||
s = str(item.text(column))
|
||||
|
||||
if column == ID_NAME:
|
||||
@ -762,11 +763,11 @@ class HexViewMode(ViewMode):
|
||||
if column == ID_DESCRIPTION:
|
||||
item.setDescription(s)
|
||||
|
||||
|
||||
def add_annotation(self, mode):
|
||||
QtCore.QObject.connect(self.ann_w.treeWidget.selectionModel(), QtCore.SIGNAL('selectionChanged(QItemSelection, QItemSelection)'), self.selectionChanged)
|
||||
QtCore.QObject.connect(self.ann_w.treeWidget, QtCore.SIGNAL('itemChanged(QTreeWidgetItem*, int)'), self.itemChanged)
|
||||
|
||||
QtCore.QObject.connect(self.ann_w.treeWidget.selectionModel(),
|
||||
QtCore.SIGNAL('selectionChanged(QItemSelection, QItemSelection)'), self.selectionChanged)
|
||||
QtCore.QObject.connect(self.ann_w.treeWidget, QtCore.SIGNAL('itemChanged(QTreeWidgetItem*, int)'),
|
||||
self.itemChanged)
|
||||
|
||||
ID_NAME = 0
|
||||
ID_OFFSET = 1
|
||||
@ -790,19 +791,20 @@ class HexViewMode(ViewMode):
|
||||
opacity = 0.25
|
||||
|
||||
qcolor = QtGui.QColor(r, g, b)
|
||||
added = self.selector.addSelection((u, v, QtGui.QBrush(qcolor), opacity), type=TextSelection.SelectionType.PERMANENT)
|
||||
added = self.selector.addSelection((u, v, QtGui.QBrush(qcolor), opacity),
|
||||
type=TextSelection.SelectionType.PERMANENT)
|
||||
|
||||
# if not added:
|
||||
# return
|
||||
# if not added:
|
||||
# return
|
||||
|
||||
t = self.ann_w.treeWidget
|
||||
|
||||
row = AnnonItem(None, self.ann_w.treeWidget, qcolor.name())
|
||||
row.setFlags(QtCore.Qt.ItemIsSelectable |
|
||||
QtCore.Qt.ItemIsEnabled |
|
||||
QtCore.Qt.ItemIsEditable |
|
||||
QtCore.Qt.ItemIsDropEnabled |
|
||||
QtCore.Qt.ItemIsDragEnabled)
|
||||
QtCore.Qt.ItemIsEnabled |
|
||||
QtCore.Qt.ItemIsEditable |
|
||||
QtCore.Qt.ItemIsDropEnabled |
|
||||
QtCore.Qt.ItemIsDragEnabled)
|
||||
|
||||
t.setAcceptDrops(True)
|
||||
t.setDragEnabled(True)
|
||||
@ -814,14 +816,13 @@ class HexViewMode(ViewMode):
|
||||
t.setItemDelegateForColumn(3, delegate)
|
||||
t.setItemDelegateForColumn(5, delegate)
|
||||
|
||||
|
||||
row.setName(self.ann_w.newFieldName())
|
||||
row.setOffset(u)
|
||||
#row.setText(ID_NAME, 'field_0')
|
||||
#row.setText(ID_OFFSET, hex(u))
|
||||
# row.setText(ID_NAME, 'field_0')
|
||||
# row.setText(ID_OFFSET, hex(u))
|
||||
|
||||
size = v - u
|
||||
#row.setText(ID_SIZE, hex(size))
|
||||
# row.setText(ID_SIZE, hex(size))
|
||||
row.setSize(size)
|
||||
|
||||
value = ''
|
||||
@ -834,11 +835,10 @@ class HexViewMode(ViewMode):
|
||||
else:
|
||||
value = repr(str(self.dataModel.getStream(u, v)))
|
||||
|
||||
|
||||
#row.setText(ID_VALUE, value)
|
||||
# row.setText(ID_VALUE, value)
|
||||
row.setValue(value)
|
||||
|
||||
#cmb.setCurrentIndex(cmb.findData(w))
|
||||
# cmb.setCurrentIndex(cmb.findData(w))
|
||||
|
||||
if mode == 2:
|
||||
self.ann_w.treeWidget.addTopLevelItem(row)
|
||||
@ -855,15 +855,16 @@ class HexViewMode(ViewMode):
|
||||
|
||||
t.expandItem(row)
|
||||
|
||||
#cmb = QColorButton()
|
||||
#cmb.setColor(qcolor.name())
|
||||
#self.ann_w.treeWidget.setItemWidget(row, ID_COLOR, cmb)
|
||||
# cmb = QColorButton()
|
||||
# cmb.setColor(qcolor.name())
|
||||
# self.ann_w.treeWidget.setItemWidget(row, ID_COLOR, cmb)
|
||||
|
||||
self.ann_w.treeWidget.setItemWidget(row, ID_COLOR, row.cmb)
|
||||
|
||||
#self.ann_w.treeWidget.openPersistentEditor(row, 0)
|
||||
#self.ann_w.treeWidget.editItem(row, 0)
|
||||
#self.ann_w.treeWidget.editItem(row, 3)
|
||||
# self.ann_w.treeWidget.openPersistentEditor(row, 0)
|
||||
# self.ann_w.treeWidget.editItem(row, 0)
|
||||
# self.ann_w.treeWidget.editItem(row, 3)
|
||||
|
||||
|
||||
class NoEditDelegate(QtWidgets.QStyledItemDelegate):
|
||||
def __init__(self, parent=None):
|
||||
@ -872,6 +873,7 @@ class NoEditDelegate(QtWidgets.QStyledItemDelegate):
|
||||
def createEditor(self, parent, option, index):
|
||||
return None
|
||||
|
||||
|
||||
class AnnonItem(QtWidgets.QTreeWidgetItem):
|
||||
ID_NAME = 0
|
||||
ID_OFFSET = 1
|
||||
@ -880,7 +882,6 @@ class AnnonItem(QtWidgets.QTreeWidgetItem):
|
||||
ID_DESCRIPTION = 4
|
||||
ID_COLOR = 5
|
||||
|
||||
|
||||
def __init__(self, x, parent, color):
|
||||
super(AnnonItem, self).__init__(x)
|
||||
self._color = color
|
||||
@ -889,9 +890,7 @@ class AnnonItem(QtWidgets.QTreeWidgetItem):
|
||||
self.cmb = QColorButton()
|
||||
self.cmb.setColor(self._color)
|
||||
|
||||
#self._t_parent.setItemWidget(self, self.ID_COLOR, self.cmb)
|
||||
|
||||
|
||||
# self._t_parent.setItemWidget(self, self.ID_COLOR, self.cmb)
|
||||
|
||||
def setName(self, name):
|
||||
self._name = name
|
||||
@ -971,7 +970,7 @@ class QColorButton(QtWidgets.QPushButton):
|
||||
'''
|
||||
dlg = QtGui.QColorDialog(QtGui.QColor(self._color), None)
|
||||
|
||||
#if self._color:
|
||||
# if self._color:
|
||||
# dlg.setCurrentColor(QtGui.QColor(self._color))
|
||||
|
||||
if dlg.exec_():
|
||||
@ -983,6 +982,7 @@ class QColorButton(QtWidgets.QPushButton):
|
||||
|
||||
return super(QColorButton, self).mousePressEvent(e)
|
||||
|
||||
|
||||
class ComboBoxItem(QtWidgets.QComboBox):
|
||||
def __init__(self, item, column):
|
||||
super(ComboBoxItem, self).__init__()
|
||||
@ -990,9 +990,10 @@ class ComboBoxItem(QtWidgets.QComboBox):
|
||||
self.item = item
|
||||
self.column = column
|
||||
|
||||
class Annotation(QtWidgets.QDialog):
|
||||
|
||||
class Annotation(QtWidgets.QDialog):
|
||||
_fieldIdx = 0
|
||||
|
||||
def __init__(self, parent, view):
|
||||
super(Annotation, self).__init__(parent)
|
||||
|
||||
@ -1004,7 +1005,7 @@ class Annotation(QtWidgets.QDialog):
|
||||
root = os.path.dirname(sys.argv[0])
|
||||
self.ui = loadUi(os.path.join(CONF['data_prefix'], 'annotation.ui'), baseinstance=self)
|
||||
|
||||
# self.ei = ImportsEventFilter(plugin, self.ui.treeWidgetImports)
|
||||
# self.ei = ImportsEventFilter(plugin, self.ui.treeWidgetImports)
|
||||
|
||||
self.ei = treeEventFilter(view, self.ui.treeWidget)
|
||||
self.ui.treeWidget.installEventFilter(self.ei)
|
||||
@ -1015,15 +1016,14 @@ class Annotation(QtWidgets.QDialog):
|
||||
name = 'field_{}'.format(self._fieldIdx)
|
||||
self._fieldIdx += 1
|
||||
return name
|
||||
|
||||
def show(self):
|
||||
|
||||
def show(self):
|
||||
# TODO: remember position? resize plugin windows when parent resize?
|
||||
pwidth = self.parent.parent.size().width()
|
||||
pheight = self.parent.parent.size().height()
|
||||
|
||||
width = self.ui.treeWidget.size().width()+15
|
||||
height = self.ui.treeWidget.size().height()+15
|
||||
width = self.ui.treeWidget.size().width() + 15
|
||||
height = self.ui.treeWidget.size().height() + 15
|
||||
|
||||
self.setGeometry(pwidth - width - 15, pheight - height, width, height)
|
||||
self.setFixedSize(width, height)
|
||||
@ -1031,12 +1031,12 @@ class Annotation(QtWidgets.QDialog):
|
||||
self.oshow()
|
||||
|
||||
def initUI(self):
|
||||
|
||||
self.setWindowTitle('Annotations')
|
||||
self.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
|
||||
shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("Shift+/"), self, self.close, self.close)
|
||||
|
||||
|
||||
class treeEventFilter(QtCore.QObject):
|
||||
def __init__(self, view, widget):
|
||||
super(QtCore.QObject, self).__init__()
|
||||
@ -1046,13 +1046,12 @@ class treeEventFilter(QtCore.QObject):
|
||||
def eventFilter(self, watched, event):
|
||||
if event.type() == QtCore.QEvent.KeyPress:
|
||||
if event.key() == QtCore.Qt.Key_Delete:
|
||||
|
||||
# get RVA column from treeView
|
||||
|
||||
item = self.widget.currentItem()
|
||||
|
||||
offset = item.getOffset()#int(str(item.text(1)),0)
|
||||
size = item.getSize()#int(str(item.text(2)),0)
|
||||
offset = item.getOffset() # int(str(item.text(1)),0)
|
||||
size = item.getSize() # int(str(item.text(2)),0)
|
||||
u = offset
|
||||
v = offset + size
|
||||
|
||||
@ -1060,8 +1059,8 @@ class treeEventFilter(QtCore.QObject):
|
||||
# TODO: remove tree!
|
||||
|
||||
item.parent().removeChild(item)
|
||||
#self.widget.takeTopLevelItem(self.widget.indexOfTopLevelItem(item))
|
||||
#print item
|
||||
#rva = self.widget.indexFromItem(item, 1).data().toString()
|
||||
# self.widget.takeTopLevelItem(self.widget.indexOfTopLevelItem(item))
|
||||
# print item
|
||||
# rva = self.widget.indexFromItem(item, 1).data().toString()
|
||||
|
||||
return False
|
||||
|
@ -7,6 +7,7 @@ from . import TextSelection
|
||||
|
||||
from PyQt5 import QtGui, QtCore
|
||||
|
||||
|
||||
class SourceViewMode(ViewMode):
|
||||
def __init__(self, themes, width, height, data, cursor, widget=None):
|
||||
super(SourceViewMode, self).__init__()
|
||||
@ -34,7 +35,7 @@ class SourceViewMode(ViewMode):
|
||||
self.font.setKerning(False)
|
||||
self.font.setFixedPitch(True)
|
||||
fm = QtGui.QFontMetrics(self.font)
|
||||
self._fontWidth = fm.width('a')
|
||||
self._fontWidth = fm.width('a')
|
||||
self._fontHeight = fm.height()
|
||||
|
||||
self.textPen = QtGui.QPen(self.themes['pen'], 0, QtCore.Qt.SolidLine)
|
||||
@ -63,15 +64,15 @@ class SourceViewMode(ViewMode):
|
||||
return QtGui.QPixmap(width, height)
|
||||
|
||||
def resize(self, width, height):
|
||||
self.width = width - width%self.fontWidth
|
||||
self.height = height - height%self.fontHeight
|
||||
self.width = width - width % self.fontWidth
|
||||
self.height = height - height % self.fontHeight
|
||||
self.computeTextArea()
|
||||
self.qpix = self._getNewPixmap(self.width, self.height + self.SPACER)
|
||||
self.refresh = True
|
||||
|
||||
def computeTextArea(self):
|
||||
self.COLUMNS = self.width // self.fontWidth
|
||||
self.ROWS = self.height // self.fontHeight
|
||||
self.ROWS = self.height // self.fontHeight
|
||||
self.notify(self.ROWS, self.COLUMNS)
|
||||
|
||||
def getPixmap(self):
|
||||
@ -83,7 +84,7 @@ class SourceViewMode(ViewMode):
|
||||
t[0](*t[1:])
|
||||
|
||||
self.Ops = []
|
||||
|
||||
|
||||
if not self.newPix:
|
||||
self.draw()
|
||||
|
||||
@ -102,7 +103,7 @@ class SourceViewMode(ViewMode):
|
||||
if self.dataModel.getOffset() in self.Paints:
|
||||
self.refresh = False
|
||||
self.qpix = QtGui.QPixmap(self.Paints[self.dataModel.getOffset()])
|
||||
#print 'hit'
|
||||
# print 'hit'
|
||||
self.drawAdditionals()
|
||||
return
|
||||
|
||||
@ -119,11 +120,11 @@ class SourceViewMode(ViewMode):
|
||||
self.newPix = self._getNewPixmap(self.width, self.height + self.SPACER)
|
||||
qp = QtGui.QPainter()
|
||||
qp.begin(self.newPix)
|
||||
qp.setWindow(-50, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight)
|
||||
qp.setWindow(-50, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight)
|
||||
|
||||
qp.drawPixmap(0, 0, self.qpix)
|
||||
|
||||
#self.transformationEngine.decorateText()
|
||||
# self.transformationEngine.decorateText()
|
||||
|
||||
# highlight selected text
|
||||
self.selector.highlightText()
|
||||
@ -138,19 +139,19 @@ class SourceViewMode(ViewMode):
|
||||
qp.end()
|
||||
|
||||
def drawLine(self, qp):
|
||||
qp.fillRect(-50, 0, 50, self.ROWS * self.fontHeight, self.backgroundBrush)
|
||||
qp.fillRect(-50, 0, 50, self.ROWS * self.fontHeight, self.backgroundBrush)
|
||||
|
||||
def drawTextMode(self, qp):
|
||||
# draw background
|
||||
qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
|
||||
qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
|
||||
|
||||
# set text pen&font
|
||||
qp.setFont(self.font)
|
||||
qp.setPen(self.textPen)
|
||||
|
||||
|
||||
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
|
||||
#ast = self.dataModel.current_class.get_ast()
|
||||
#print ast
|
||||
# ast = self.dataModel.current_class.get_ast()
|
||||
# print ast
|
||||
|
||||
for i in range(self.ROWS):
|
||||
if i < len(self.LINES):
|
||||
@ -173,7 +174,7 @@ class SourceViewMode(ViewMode):
|
||||
qp.setBrush(QtGui.QColor(255, 255, 0))
|
||||
|
||||
qp.setOpacity(0.5)
|
||||
qp.drawRect(xstart*self.fontWidth, cursorY*self.fontHeight, width*self.fontWidth, self.fontHeight + 2)
|
||||
qp.drawRect(xstart * self.fontWidth, cursorY * self.fontHeight, width * self.fontWidth, self.fontHeight + 2)
|
||||
qp.setOpacity(1)
|
||||
|
||||
def handleKeyEvent(self, modifiers, key, event=None):
|
||||
|
@ -15,7 +15,7 @@ class CTextDecorator(object):
|
||||
greenPen = QtGui.QPen(QtGui.QColor(255, 255, 0))
|
||||
whitePen = QtGui.QPen(QtGui.QColor(255, 255, 255))
|
||||
|
||||
normalPen = QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine)
|
||||
normalPen = QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine)
|
||||
|
||||
MZbrush = QtGui.QBrush(QtGui.QColor(128, 0, 0))
|
||||
grayBrush = QtGui.QBrush(QtGui.QColor(128, 128, 128))
|
||||
@ -23,6 +23,7 @@ class CTextDecorator(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
class TextDecorator(CTextDecorator):
|
||||
def __init__(self, viewmode):
|
||||
self.operations = []
|
||||
@ -35,27 +36,37 @@ class TextDecorator(CTextDecorator):
|
||||
self.normalPen = QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine)
|
||||
|
||||
# if we want to generate T/F table
|
||||
self.Special = string.ascii_letters + string.digits + ' .;\':;=\"?-!()/\\_'
|
||||
self.Special = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, False, False, False, False, True, True,
|
||||
True, False, False, False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, False, True, False, True,
|
||||
False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True,
|
||||
True, True, True, False, True, False, False, True, False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True,
|
||||
True, True, True, True, True, True, True, True, True, True, True, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
|
||||
|
||||
self.Special = string.ascii_letters + string.digits + ' .;\':;=\"?-!()/\\_'
|
||||
self.Special = [False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, True, True,
|
||||
True, False, False, False, False, True, True,
|
||||
True, False, False, False, True, True, True, True, True, True, True, True, True, True, True,
|
||||
True, True, True, True, False, True, False, True,
|
||||
False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True,
|
||||
True, True, True, True, True, True, True, True,
|
||||
True, True, True, False, True, False, False, True, False, True, True, True, True, True, True,
|
||||
True, True, True, True, True, True, True, True, True,
|
||||
True, True, True, True, True, True, True, True, True, True, True, False, False, False, False,
|
||||
False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False,
|
||||
False, False, False, False, False, False, False, False, False, False, False, False, False,
|
||||
False, False, False, False]
|
||||
|
||||
def reset(self):
|
||||
self.penMap = {}
|
||||
self.brushMap = {}
|
||||
self.PenInterval = []
|
||||
|
||||
|
||||
def getDataModel(self):
|
||||
return self.dataModel
|
||||
|
||||
@ -76,7 +87,7 @@ class TextDecorator(CTextDecorator):
|
||||
return self.Special[ord(c)]
|
||||
|
||||
def getChar(self, idx):
|
||||
#self.page = self.getDataModel().getDisplayablePage()
|
||||
# self.page = self.getDataModel().getDisplayablePage()
|
||||
|
||||
|
||||
if idx < len(self.page):
|
||||
@ -84,24 +95,21 @@ class TextDecorator(CTextDecorator):
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def decorate(self, pageOffset=None):
|
||||
|
||||
|
||||
if pageOffset:
|
||||
self.page = self.viewmode.getDisplayablePage(pageOffset=pageOffset)
|
||||
else:
|
||||
else:
|
||||
self.page = self.viewmode.getDisplayablePage()
|
||||
|
||||
return self.page
|
||||
|
||||
|
||||
|
||||
def addPenInterval(self, a, b, pen, ignoreHighlights=True):
|
||||
self.PenInterval.append((a, b, pen, ignoreHighlights))
|
||||
|
||||
def choosePen(self, idx):
|
||||
key = self.dataModel.getOffset() + idx
|
||||
|
||||
|
||||
# if we do have a pen with that index, return it if it's different than default pen
|
||||
# otherwise, return the pen that was set in that interval
|
||||
# the priority here is de pen from other transformations, than interval pen
|
||||
@ -136,7 +144,6 @@ class PageDecorator(TextDecorator):
|
||||
def __init__(self, decorated):
|
||||
pass
|
||||
|
||||
|
||||
def reset(self):
|
||||
self.decorated.reset()
|
||||
|
||||
@ -156,6 +163,7 @@ class PageDecorator(TextDecorator):
|
||||
def getDataModel(self):
|
||||
return self.dataModel
|
||||
|
||||
|
||||
class HighlightASCII(PageDecorator):
|
||||
def __init__(self, decorated):
|
||||
self.dataModel = decorated.getDataModel()
|
||||
@ -164,8 +172,6 @@ class HighlightASCII(PageDecorator):
|
||||
super(HighlightASCII, self).__init__(decorated)
|
||||
self.dataModel = super(HighlightASCII, self).getDataModel()
|
||||
|
||||
|
||||
|
||||
def decorate(self, pageOffset=None):
|
||||
page = self.decorated.decorate(pageOffset)
|
||||
|
||||
@ -177,16 +183,13 @@ class HighlightASCII(PageDecorator):
|
||||
|
||||
Match = [(m.start(), m.end()) for m in re.finditer(b'([a-zA-Z0-9\\-\\\\.%*:/? _<>]){4,}', page)]
|
||||
for s, e in Match:
|
||||
for i in range(e-s):
|
||||
for i in range(e - s):
|
||||
idx = off + s + i
|
||||
if idx not in self.penMap:
|
||||
self.penMap[off + s + i] = self.redPen
|
||||
|
||||
|
||||
self.page = page
|
||||
return self.page
|
||||
|
||||
|
||||
|
||||
|
||||
class HighlightPrefix(PageDecorator):
|
||||
@ -207,15 +210,11 @@ class HighlightPrefix(PageDecorator):
|
||||
self.brushMap = self.decorated.brushMap
|
||||
self.penMap = self.decorated.penMap
|
||||
|
||||
|
||||
self.page = self.highliteWithPrefix(page, self.text, self.additionalLength, self.brush, self.pen)
|
||||
return self.page
|
||||
|
||||
|
||||
def highliteWithPrefix(self, page, text, additionalLength=0, brush=None, pen=None):
|
||||
|
||||
|
||||
|
||||
# todo: nu am gasit o metoda mai eleganta pentru a selecta toate aparitiile ale lui text
|
||||
# regexp nu merg, "bad re expression"
|
||||
lenText = len(text)
|
||||
@ -231,17 +230,16 @@ class HighlightPrefix(PageDecorator):
|
||||
M.append((idx, lenText + additionalLength))
|
||||
idx += lenText + additionalLength
|
||||
|
||||
|
||||
off = self.dataModel.getOffset()
|
||||
for start, length in M:
|
||||
|
||||
|
||||
for i in range(length):
|
||||
self.penMap[off + start + i] = pen
|
||||
self.brushMap[off + start + i] = brush
|
||||
|
||||
|
||||
return page
|
||||
|
||||
|
||||
class HighlightWideChar(PageDecorator):
|
||||
def __init__(self, decorated):
|
||||
super(HighlightWideChar, self).__init__(decorated)
|
||||
@ -249,7 +247,6 @@ class HighlightWideChar(PageDecorator):
|
||||
self.dataModel = decorated.getDataModel()
|
||||
self.decorated = decorated
|
||||
|
||||
|
||||
def decorate(self, pageOffset=None):
|
||||
self.page = self.decorated.decorate(pageOffset)
|
||||
|
||||
@ -257,28 +254,24 @@ class HighlightWideChar(PageDecorator):
|
||||
self.brushMap = self.decorated.brushMap
|
||||
self.penMap = self.decorated.penMap
|
||||
|
||||
|
||||
self.page = self.highliteWidechar2(self.page)
|
||||
return self.page
|
||||
|
||||
|
||||
|
||||
|
||||
def highliteWidechar2(self, page):
|
||||
|
||||
|
||||
pageStart = self.dataModel.getOffset()
|
||||
pageEnd = pageStart + len(page)
|
||||
pageEnd = pageStart + len(page)
|
||||
|
||||
touched = False
|
||||
#for s, e in self.Intervals:
|
||||
# for s, e in self.Intervals:
|
||||
# touched = True
|
||||
|
||||
if not touched:
|
||||
# expand
|
||||
Match = [(m.start(), m.end()) for m in re.finditer(r'([a-zA-Z0-9\-\\.%*:/? ]\x00){4,}', page)]
|
||||
for s, e in Match:
|
||||
for i in range(e-s):
|
||||
#print i
|
||||
for i in range(e - s):
|
||||
# print i
|
||||
self.penMap[pageStart + s + i] = QtGui.QPen(QtGui.QColor(255, 255, 0))
|
||||
|
||||
# get rid of '\x00'
|
||||
@ -287,12 +280,10 @@ class HighlightWideChar(PageDecorator):
|
||||
# copy string that has no zeros
|
||||
page[s:s + l] = string
|
||||
# fill with zeros the remaining space
|
||||
page[s + l: s + 2*l] = '\x00'*l
|
||||
|
||||
page[s + l: s + 2 * l] = '\x00' * l
|
||||
|
||||
return page
|
||||
|
||||
|
||||
### todo: other way to highlight widechar, should test and see which one is faster
|
||||
"""
|
||||
def _changeText(self, page, page_start, I):
|
||||
|
@ -7,11 +7,13 @@ from __future__ import division
|
||||
from builtins import object
|
||||
from PyQt5 import QtGui
|
||||
|
||||
|
||||
class SelectionType(object):
|
||||
NORMAL = 0
|
||||
PERMANENT = 1
|
||||
TEXTHIGHLIGHT = 2
|
||||
|
||||
|
||||
class Selection(object):
|
||||
def __init__(self, themes, viewMode):
|
||||
self.themes = themes
|
||||
@ -48,7 +50,6 @@ class Selection(object):
|
||||
|
||||
if type == SelectionType.NORMAL:
|
||||
if len(self.Selections) >= self.MAX_SELECTIONS:
|
||||
|
||||
self.Selections = []
|
||||
|
||||
self.Selections.append(t)
|
||||
@ -99,7 +100,7 @@ class Selection(object):
|
||||
self.drawSelection(qp, start, end)
|
||||
self.HighlightSelections = []
|
||||
|
||||
#draw current
|
||||
# draw current
|
||||
if self.selecting:
|
||||
self.drawSelection(qp, *self.getCurrentSelection())
|
||||
|
||||
@ -129,16 +130,16 @@ class Selection(object):
|
||||
# but currently, by design we could only have one NORMAL selection
|
||||
return u, v
|
||||
|
||||
#if self.last:
|
||||
# return self.last
|
||||
# if self.last:
|
||||
# return self.last
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def stopSelection(self):
|
||||
if self.selecting == True:
|
||||
u, v = self.getCurrentSelection()
|
||||
|
||||
self.addSelection((u, v, QtGui.QBrush(self.themes['selection']), 0.4) , type=SelectionType.NORMAL)
|
||||
self.addSelection((u, v, QtGui.QBrush(self.themes['selection']), 0.4), type=SelectionType.NORMAL)
|
||||
self.last = u, v
|
||||
|
||||
self.selecting = False
|
||||
@ -154,7 +155,7 @@ class Selection(object):
|
||||
if not t:
|
||||
# no selection
|
||||
return
|
||||
|
||||
|
||||
start, end = t
|
||||
|
||||
if start == end:
|
||||
@ -163,7 +164,6 @@ class Selection(object):
|
||||
text = dataModel.getStream(start, end)
|
||||
Exclude = [start]
|
||||
|
||||
|
||||
cols, rows = self.viewMode.getGeometry()
|
||||
|
||||
# find all occurrence
|
||||
@ -179,17 +179,17 @@ class Selection(object):
|
||||
M.append((idx, lenText))
|
||||
idx += lenText
|
||||
|
||||
|
||||
#Match = [(m.start(), m.end()) for m in re.finditer(bytes(text), bytes(page))]
|
||||
|
||||
# Match = [(m.start(), m.end()) for m in re.finditer(bytes(text), bytes(page))]
|
||||
|
||||
for start, end in M:
|
||||
#print start, end
|
||||
#self._makeSelection(qp, start, end, cols, rows)
|
||||
# print start, end
|
||||
# self._makeSelection(qp, start, end, cols, rows)
|
||||
off = dataModel.getOffset()
|
||||
if off+start not in Exclude:
|
||||
#self._makeSelection(off + start, off + start + end, brush=QtGui.QBrush(QtGui.QColor(125, 255, 0)))
|
||||
#self.viewMode.selector.addSelection((off+start, off + start + end, QtGui.QBrush(QtGui.QColor(125, 255, 0)), 0.4))
|
||||
self.addSelection((off+start, off + start + end, QtGui.QBrush(self.themes['selection']), 0.4), type=SelectionType.TEXTHIGHLIGHT)
|
||||
if off + start not in Exclude:
|
||||
# self._makeSelection(off + start, off + start + end, brush=QtGui.QBrush(QtGui.QColor(125, 255, 0)))
|
||||
# self.viewMode.selector.addSelection((off+start, off + start + end, QtGui.QBrush(QtGui.QColor(125, 255, 0)), 0.4))
|
||||
self.addSelection((off + start, off + start + end, QtGui.QBrush(self.themes['selection']), 0.4),
|
||||
type=SelectionType.TEXTHIGHLIGHT)
|
||||
|
||||
|
||||
class DefaultSelection(Selection):
|
||||
@ -221,18 +221,18 @@ class DefaultSelection(Selection):
|
||||
d1 = length
|
||||
else:
|
||||
d1 = end - off
|
||||
|
||||
|
||||
mark = True
|
||||
height = 14
|
||||
|
||||
qp.setOpacity(0.4)
|
||||
while mark:
|
||||
if d0 // cols == d1 // cols:
|
||||
qp.fillRect((d0%cols)*8, (d0 // cols) * height, (d1-d0) * 8, 1 * height, brush)
|
||||
qp.fillRect((d0 % cols) * 8, (d0 // cols) * height, (d1 - d0) * 8, 1 * height, brush)
|
||||
d0 += (d1 - d0)
|
||||
else:
|
||||
qp.fillRect((d0%cols)*8, (d0 // cols)*height, (cols - d0%cols)*8, 1*height, brush)
|
||||
d0 += (cols - d0%cols)
|
||||
else:
|
||||
qp.fillRect((d0 % cols) * 8, (d0 // cols) * height, (cols - d0 % cols) * 8, 1 * height, brush)
|
||||
d0 += (cols - d0 % cols)
|
||||
|
||||
if (d1 - d0 <= 0):
|
||||
mark = False
|
||||
@ -263,7 +263,7 @@ class DefaultSelection(Selection):
|
||||
d1 = length
|
||||
else:
|
||||
d1 = end - off
|
||||
|
||||
|
||||
mark = True
|
||||
height = self.viewMode.fontHeight
|
||||
width = self.viewMode.fontWidth
|
||||
@ -274,18 +274,18 @@ class DefaultSelection(Selection):
|
||||
|
||||
while mark:
|
||||
if d0 // cols == d1 // cols:
|
||||
qp.fillRect((d0%cols)*width, (d0 // cols)*height + offset, (d1-d0)*width, 1*height, brush)
|
||||
qp.fillRect((d0 % cols) * width, (d0 // cols) * height + offset, (d1 - d0) * width, 1 * height, brush)
|
||||
d0 += (d1 - d0)
|
||||
else:
|
||||
qp.fillRect((d0%cols)*width, (d0 // cols)*height + offset, (cols - d0%cols)*width, 1*height, brush)
|
||||
d0 += (cols - d0%cols)
|
||||
else:
|
||||
qp.fillRect((d0 % cols) * width, (d0 // cols) * height + offset, (cols - d0 % cols) * width, 1 * height,
|
||||
brush)
|
||||
d0 += (cols - d0 % cols)
|
||||
|
||||
if (d1 - d0 <= 0):
|
||||
mark = False
|
||||
qp.setOpacity(1)
|
||||
|
||||
|
||||
|
||||
class HexSelection(Selection):
|
||||
def __init__(self, themes, viewMode):
|
||||
super(HexSelection, self).__init__(themes, viewMode)
|
||||
@ -316,7 +316,7 @@ class HexSelection(Selection):
|
||||
d1 = length
|
||||
else:
|
||||
d1 = end - off
|
||||
|
||||
|
||||
mark = True
|
||||
height = self.viewMode.fontHeight
|
||||
width = self.viewMode.fontWidth
|
||||
@ -325,15 +325,19 @@ class HexSelection(Selection):
|
||||
while mark:
|
||||
if d0 // cols == d1 // cols:
|
||||
# +2 is an offset for letters
|
||||
qp.fillRect(3*(d0%cols)*width, (d0 // cols)*height+2, 3*(d1-d0)*width - width, 1*height, brush)
|
||||
qp.fillRect(3*cols*width + self.viewMode.gap*width + (d0%cols)*width, (d0 // cols)*height+2, (d1-d0)*width, 1*height, brush)
|
||||
qp.fillRect(3 * (d0 % cols) * width, (d0 // cols) * height + 2, 3 * (d1 - d0) * width - width,
|
||||
1 * height, brush)
|
||||
qp.fillRect(3 * cols * width + self.viewMode.gap * width + (d0 % cols) * width,
|
||||
(d0 // cols) * height + 2, (d1 - d0) * width, 1 * height, brush)
|
||||
|
||||
d0 += (d1 - d0)
|
||||
else:
|
||||
qp.fillRect(3*(d0%cols)*width, (d0 // cols)*height+2, 3*(cols - d0%cols)*width - width, 1*height, brush)
|
||||
qp.fillRect(3*cols*width + self.viewMode.gap*width + (d0%cols)*width, (d0 // cols)*height+2, (cols - d0%cols)*width, 1*height, brush)
|
||||
else:
|
||||
qp.fillRect(3 * (d0 % cols) * width, (d0 // cols) * height + 2, 3 * (cols - d0 % cols) * width - width,
|
||||
1 * height, brush)
|
||||
qp.fillRect(3 * cols * width + self.viewMode.gap * width + (d0 % cols) * width,
|
||||
(d0 // cols) * height + 2, (cols - d0 % cols) * width, 1 * height, brush)
|
||||
|
||||
d0 += (cols - d0%cols)
|
||||
d0 += (cols - d0 % cols)
|
||||
|
||||
if (d1 - d0 <= 0):
|
||||
mark = False
|
||||
@ -351,7 +355,7 @@ class DisasmSelection(Selection):
|
||||
|
||||
dataModel = self.viewMode.getDataModel()
|
||||
off = dataModel.getOffset()
|
||||
length = sum([o.size for o in self.viewMode.OPCODES]) # TODO: not nice!
|
||||
length = sum([o.size for o in self.viewMode.OPCODES]) # TODO: not nice!
|
||||
cols, rows = self.viewMode.getGeometry()
|
||||
|
||||
# return if out of view
|
||||
@ -370,7 +374,7 @@ class DisasmSelection(Selection):
|
||||
d1 = length
|
||||
else:
|
||||
d1 = end - off
|
||||
|
||||
|
||||
mark = True
|
||||
height = self.viewMode.fontHeight
|
||||
width = self.viewMode.fontWidth
|
||||
@ -383,17 +387,17 @@ class DisasmSelection(Selection):
|
||||
for i, asm in enumerate(self.viewMode.OPCODES):
|
||||
if size + asm.size > d0 and size <= d1:
|
||||
|
||||
# compute x offset
|
||||
x = d0-size
|
||||
if size > d0:
|
||||
x = 0
|
||||
# compute x offset
|
||||
x = d0 - size
|
||||
if size > d0:
|
||||
x = 0
|
||||
|
||||
# compute width
|
||||
w = asm.size
|
||||
if size + asm.size > d1:
|
||||
w = d1 - size
|
||||
# compute width
|
||||
w = asm.size
|
||||
if size + asm.size > d1:
|
||||
w = d1 - size
|
||||
|
||||
qp.fillRect(x*3*width, i*height + offset, (w-x)*3*width - width, 1*height, brush)
|
||||
qp.fillRect(x * 3 * width, i * height + offset, (w - x) * 3 * width - width, 1 * height, brush)
|
||||
|
||||
size += asm.size
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
from builtins import chr
|
||||
from builtins import object
|
||||
|
||||
|
||||
class Observable(object):
|
||||
def __init__(self):
|
||||
self.Callbacks = []
|
||||
@ -12,8 +14,8 @@ class Observable(object):
|
||||
for cbk in self.Callbacks:
|
||||
cbk.update_geometry(rows, cols)
|
||||
|
||||
class ViewMode(Observable, object):
|
||||
|
||||
class ViewMode(Observable, object):
|
||||
SPACER = 4
|
||||
|
||||
def __init__(self):
|
||||
@ -26,37 +28,37 @@ class ViewMode(Observable, object):
|
||||
http://svn.openmoko.org/trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatutils.cpp
|
||||
"""
|
||||
cp437ToUnicode = [0x0020, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001c, 0x001b, 0x007f, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x001a,
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
|
||||
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
|
||||
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x03bc, 0x03c4,
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0]
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001c, 0x001b, 0x007f, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x001a,
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
|
||||
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
|
||||
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x03bc, 0x03c4,
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0]
|
||||
|
||||
def cp437(self, c):
|
||||
return chr(self.cp437ToUnicode[c])
|
||||
@ -69,10 +71,10 @@ class ViewMode(Observable, object):
|
||||
NotImplementedError('method not implemented.')
|
||||
|
||||
def startSelection(self):
|
||||
NotImplementedError('method not implemented.')
|
||||
NotImplementedError('method not implemented.')
|
||||
|
||||
def stopSelection(self):
|
||||
NotImplementedError('method not implemented.')
|
||||
NotImplementedError('method not implemented.')
|
||||
|
||||
def draw(self, refresh=False):
|
||||
NotImplementedError('method not implemented.')
|
||||
@ -80,8 +82,8 @@ class ViewMode(Observable, object):
|
||||
# returns x,y cursor position in page
|
||||
def getCursorOffsetInPage(self):
|
||||
x, y = self.cursor.getPosition()
|
||||
return y*self.COLUMNS + x
|
||||
|
||||
return y * self.COLUMNS + x
|
||||
|
||||
def handleKeyPressEvent(self, modifier, key):
|
||||
raise Exception("not implemented")
|
||||
|
||||
@ -97,9 +99,9 @@ class ViewMode(Observable, object):
|
||||
dataOffset = self.dataModel.getOffset()
|
||||
cols, rows = self.getGeometry()
|
||||
if pageOffset:
|
||||
return bytearray(data[dataOffset:dataOffset + rows*cols*pageOffset])
|
||||
return bytearray(data[dataOffset:dataOffset + rows * cols * pageOffset])
|
||||
|
||||
return bytearray(data[dataOffset:dataOffset + rows*cols])
|
||||
return bytearray(data[dataOffset:dataOffset + rows * cols])
|
||||
|
||||
# moves cursor to offset in page, or moves to page
|
||||
def goTo(self, offset):
|
||||
@ -116,8 +118,7 @@ class ViewMode(Observable, object):
|
||||
self.cursor.moveAbsolute(0, 0)
|
||||
self.draw(refresh=True)
|
||||
|
||||
|
||||
#self.draw(refresh=False)
|
||||
# self.draw(refresh=False)
|
||||
if self.widget:
|
||||
self.widget.update()
|
||||
|
||||
|
@ -1,85 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>708</width>
|
||||
<height>513</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>691</width>
|
||||
<height>461</height>
|
||||
</rect>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>610</x>
|
||||
<y>480</y>
|
||||
<width>93</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>510</x>
|
||||
<y>480</y>
|
||||
<width>93</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>708</width>
|
||||
<height>513</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>691</width>
|
||||
<height>461</height>
|
||||
</rect>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>610</x>
|
||||
<y>480</y>
|
||||
<width>93</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>510</x>
|
||||
<y>480</y>
|
||||
<width>93</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -3,7 +3,6 @@ from androguard.gui.xrefwindow import XrefDialogMethod
|
||||
|
||||
|
||||
class APIWindow(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent=None, win=None, session=None):
|
||||
super(APIWindow, self).__init__(parent)
|
||||
self.mainwin = win
|
||||
@ -30,7 +29,6 @@ class APIWindow(QtWidgets.QWidget):
|
||||
|
||||
|
||||
class APIValueWindow(QtWidgets.QTreeView):
|
||||
|
||||
def __init__(self, parent=None, win=None, session=None):
|
||||
super(APIValueWindow, self).__init__(parent)
|
||||
self.mainwin = win
|
||||
@ -68,7 +66,7 @@ class APIValueWindow(QtWidgets.QTreeView):
|
||||
self.model.setData(self.model.index(
|
||||
row, 3, QtCore.QModelIndex()), digest)
|
||||
self.reverse_methods[method.get_name() + method.get_class_name() + method.get_descriptor()
|
||||
] = dx.get_method_analysis(method)
|
||||
] = dx.get_method_analysis(method)
|
||||
row += 1
|
||||
|
||||
self.proxyModel.setSourceModel(self.model)
|
||||
@ -91,6 +89,6 @@ class APIValueWindow(QtWidgets.QTreeView):
|
||||
parent=self.mainwin,
|
||||
win=self.mainwin,
|
||||
method_analysis=self.reverse_methods[self.model.item(row).text() +
|
||||
self.model.item(row, 1).text() +
|
||||
self.model.item(row, 1).text() +
|
||||
self.model.item(row, 2).text()])
|
||||
xwin.show()
|
||||
|
@ -15,8 +15,8 @@ from .BinViewMode import *
|
||||
from .DataModel import *
|
||||
from .Banners import *
|
||||
|
||||
|
||||
class SearchWindow(QtWidgets.QDialog):
|
||||
|
||||
def __init__(self, parent, plugin, searchable):
|
||||
super(SearchWindow, self).__init__(parent)
|
||||
self.searchable = searchable
|
||||
@ -35,8 +35,8 @@ class SearchWindow(QtWidgets.QDialog):
|
||||
def show(self):
|
||||
# TODO: remember position? resize plugin windows when parent resize?
|
||||
|
||||
width = self.ui.size().width()+15
|
||||
height = self.ui.size().height()+15
|
||||
width = self.ui.size().width() + 15
|
||||
height = self.ui.size().height() + 15
|
||||
|
||||
self.move((self.parent.width() - width) // 2, (self.parent.height() - height) // 2)
|
||||
self.ui.lineEdit.setText(self._lastText)
|
||||
@ -51,12 +51,12 @@ class SearchWindow(QtWidgets.QDialog):
|
||||
|
||||
self.ui.pushButton.clicked.connect(self.onClicked)
|
||||
|
||||
width = self.ui.size().width()+15
|
||||
height = self.ui.size().height()+15
|
||||
width = self.ui.size().width() + 15
|
||||
height = self.ui.size().height() + 15
|
||||
self.setFixedSize(width, height)
|
||||
|
||||
def onClicked(self):
|
||||
text = self.ui.lineEdit.text()
|
||||
text = self.ui.lineEdit.text()
|
||||
text = str(text)
|
||||
|
||||
hexstr = '0123456789abcdefABCDEF'
|
||||
@ -66,7 +66,8 @@ class SearchWindow(QtWidgets.QDialog):
|
||||
text = ''
|
||||
for t in T:
|
||||
if len(t) != 2:
|
||||
reply = QtWidgets.QMessageBox.warning(self, 'Qiew', "Hex string with errors.", QtWidgets.QMessageBox.Ok)
|
||||
reply = QtWidgets.QMessageBox.warning(self, 'Qiew', "Hex string with errors.",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
self.close()
|
||||
return
|
||||
|
||||
@ -74,11 +75,11 @@ class SearchWindow(QtWidgets.QDialog):
|
||||
o = int(t, 16)
|
||||
text += chr(o)
|
||||
else:
|
||||
reply = QtWidgets.QMessageBox.warning(self, 'Qiew', "Hex string with errors.", QtWidgets.QMessageBox.Ok)
|
||||
reply = QtWidgets.QMessageBox.warning(self, 'Qiew', "Hex string with errors.",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
self.close()
|
||||
return
|
||||
|
||||
|
||||
self._lastText = oldtext
|
||||
|
||||
else:
|
||||
@ -94,6 +95,7 @@ class SearchWindow(QtWidgets.QDialog):
|
||||
self.parent.viewMode.draw(refresh=True)
|
||||
self.close()
|
||||
|
||||
|
||||
class Observable(object):
|
||||
def __init__(self):
|
||||
self.Callbacks = []
|
||||
@ -111,6 +113,7 @@ class Observer(object):
|
||||
def changeViewMode(self, viewMode):
|
||||
self._viewMode = viewMode
|
||||
|
||||
|
||||
class Searchable(Observer):
|
||||
def __init__(self, dataModel, viewMode):
|
||||
self._viewMode = viewMode
|
||||
@ -126,14 +129,14 @@ class Searchable(Observer):
|
||||
idx = self._lastIdx + 1
|
||||
else:
|
||||
idx = start
|
||||
|
||||
|
||||
if idx > -1:
|
||||
self._search(data, text, idx)
|
||||
|
||||
@property
|
||||
def lastText(self):
|
||||
return self._lastText
|
||||
|
||||
|
||||
def previous(self, start=None):
|
||||
data = self._dataModel.getData()
|
||||
text = self._lastText
|
||||
@ -183,32 +186,31 @@ class Searchable(Observer):
|
||||
self._lastIdx = idx
|
||||
|
||||
if idx > -1:
|
||||
self._viewMode.selector.addSelection((idx, idx + len(text), QtGui.QBrush(QtGui.QColor(125, 0, 100)), 0.8) , type=TextSelection.SelectionType.NORMAL)
|
||||
self._viewMode.selector.addSelection((idx, idx + len(text), QtGui.QBrush(QtGui.QColor(125, 0, 100)), 0.8),
|
||||
type=TextSelection.SelectionType.NORMAL)
|
||||
self._viewMode.goTo(idx)
|
||||
|
||||
return idx
|
||||
|
||||
|
||||
def search(self, text):
|
||||
data = self._dataModel.getData()
|
||||
return self._search(data, text, 0)
|
||||
|
||||
|
||||
class binWidget(QtWidgets.QWidget, Observable):
|
||||
|
||||
scrolled = QtCore.pyqtSignal(int, name='scroll')
|
||||
|
||||
def __init__(self, parent, source, title):
|
||||
super(binWidget, self).__init__()
|
||||
Observable.__init__(self)
|
||||
self.parent = parent
|
||||
|
||||
|
||||
self.title = title
|
||||
self.active = False
|
||||
# offset for text window
|
||||
#self.data = mapped
|
||||
# self.data = mapped
|
||||
self.dataOffset = 0
|
||||
|
||||
|
||||
self.dataModel = source
|
||||
self.cursor = Cursor(0, 0)
|
||||
|
||||
@ -218,7 +220,7 @@ class binWidget(QtWidgets.QWidget, Observable):
|
||||
'background_cursor': QtGui.QColor(255, 255, 0),
|
||||
'selection': QtGui.QColor(125, 255, 0),
|
||||
'pen': QtGui.QColor(0xb5, 0x89, 0x00)
|
||||
}
|
||||
}
|
||||
|
||||
self.multipleViewModes = []
|
||||
for view_mode in self.dataModel.GetViews():
|
||||
@ -231,11 +233,9 @@ class binWidget(QtWidgets.QWidget, Observable):
|
||||
|
||||
self.viewMode = self.multipleViewModes[0]
|
||||
|
||||
|
||||
|
||||
self.Banners = Banners()
|
||||
|
||||
self.Banners.add(FileAddrBanner(self.themes, self.dataModel, self.viewMode))
|
||||
self.Banners.add(FileAddrBanner(self.themes, self.dataModel, self.viewMode))
|
||||
self.Banners.add(TopBanner(self.themes, self.dataModel, self.viewMode))
|
||||
self.Banners.add(BottomBanner(self.themes, self.dataModel, self.viewMode))
|
||||
|
||||
@ -243,7 +243,6 @@ class binWidget(QtWidgets.QWidget, Observable):
|
||||
self.offsetWindow_v = 0
|
||||
self.searchable = Searchable(self.dataModel, self.viewMode)
|
||||
|
||||
|
||||
self.initUI()
|
||||
|
||||
self.searchWindow = SearchWindow(self, None, self.searchable)
|
||||
@ -251,17 +250,17 @@ class binWidget(QtWidgets.QWidget, Observable):
|
||||
self.addHandler(self.searchable)
|
||||
self.addHandler(self.Banners)
|
||||
|
||||
self.notify(self.viewMode)
|
||||
self.notify(self.viewMode)
|
||||
|
||||
def enable(self):
|
||||
self.active = True
|
||||
|
||||
def disable(self):
|
||||
self.active = False
|
||||
|
||||
|
||||
def scroll_from_outside(self, i):
|
||||
#print 'slot-signal ' + str(i)
|
||||
#self.scroll_pdown = True
|
||||
# print 'slot-signal ' + str(i)
|
||||
# self.scroll_pdown = True
|
||||
self.update()
|
||||
|
||||
def initUI(self):
|
||||
@ -284,8 +283,8 @@ class binWidget(QtWidgets.QWidget, Observable):
|
||||
|
||||
# compute space ocupated by banners
|
||||
offsetLeft = self.offsetWindow_h + self.Banners.getLeftOffset()
|
||||
offsetBottom = self.offsetWindow_v + self.Banners.getBottomOffset() + self.Banners.getTopOffset()
|
||||
|
||||
offsetBottom = self.offsetWindow_v + self.Banners.getBottomOffset() + self.Banners.getTopOffset()
|
||||
|
||||
# resize window, substract space ocupated by banners
|
||||
self.viewMode.resize(self.size().width() - offsetLeft, self.size().height() - offsetBottom)
|
||||
|
||||
@ -293,28 +292,26 @@ class binWidget(QtWidgets.QWidget, Observable):
|
||||
def resizeEvent(self, e):
|
||||
self._resize()
|
||||
|
||||
|
||||
def paintEvent(self, e):
|
||||
qp = QtGui.QPainter()
|
||||
qp.begin(self)
|
||||
qp.setOpacity(1)
|
||||
|
||||
offsetLeft = self.offsetWindow_h + self.Banners.getLeftOffset()
|
||||
offsetBottom = self.offsetWindow_v + self.Banners.getTopOffset()
|
||||
offsetBottom = self.offsetWindow_v + self.Banners.getTopOffset()
|
||||
|
||||
#self.viewMode.draw2(qp, refresh=True)
|
||||
#start = time()
|
||||
# self.viewMode.draw2(qp, refresh=True)
|
||||
# start = time()
|
||||
qp.drawPixmap(offsetLeft, offsetBottom, self.viewMode.getPixmap())
|
||||
#print 'Draw ' + str(time() - start)
|
||||
# print 'Draw ' + str(time() - start)
|
||||
|
||||
self.Banners.draw(qp, self.offsetWindow_h, self.offsetWindow_v, self.size().height())
|
||||
|
||||
# qp.drawPixmap(self.offsetWindow_h, self.size().height() - 50, self.banner.getPixmap())
|
||||
# qp.drawPixmap(self.offsetWindow_h, self.size().height() - 50, self.banner.getPixmap())
|
||||
|
||||
# qp.drawPixmap(20, 0, self.filebanner.getPixmap())
|
||||
# qp.drawPixmap(20, 0, self.filebanner.getPixmap())
|
||||
qp.end()
|
||||
|
||||
|
||||
def eventFilter(self, watched, event):
|
||||
if not self.active:
|
||||
return False
|
||||
@ -325,9 +322,8 @@ class binWidget(QtWidgets.QWidget, Observable):
|
||||
if self.viewMode.handleKeyEvent(modifiers, key, event=event):
|
||||
self.update()
|
||||
|
||||
|
||||
if event.type() == QtCore.QEvent.KeyPress:
|
||||
#TODO: should we accept only certain keys ?
|
||||
if event.type() == QtCore.QEvent.KeyPress:
|
||||
# TODO: should we accept only certain keys ?
|
||||
key = event.key()
|
||||
modifiers = event.modifiers()
|
||||
if key == QtCore.Qt.Key_F2:
|
||||
@ -358,46 +354,44 @@ class binWidget(QtWidgets.QWidget, Observable):
|
||||
if self.viewMode.selector.getCurrentSelection():
|
||||
a, b = self.viewMode.selector.getCurrentSelection()
|
||||
|
||||
#print a, b
|
||||
# print a, b
|
||||
hx = ''
|
||||
for s in self.dataModel.getStream(a, b):
|
||||
hx += '{:02x}'.format(s)
|
||||
|
||||
pyperclip.copy(hx)
|
||||
del pyperclip
|
||||
#print pyperclip.paste()
|
||||
# print 'coppied'
|
||||
|
||||
# print pyperclip.paste()
|
||||
# print 'coppied'
|
||||
|
||||
if event.modifiers() & QtCore.Qt.ShiftModifier:
|
||||
if key == QtCore.Qt.Key_Insert:
|
||||
import re
|
||||
hx = pyperclip.paste()
|
||||
#print hx
|
||||
# print hx
|
||||
L = re.findall(r'.{1,2}', hx, re.DOTALL)
|
||||
|
||||
array = ''
|
||||
for s in L:
|
||||
array += chr(int(s, 16))
|
||||
|
||||
#print 'write '
|
||||
#print 'write'
|
||||
#print array
|
||||
# print 'write '
|
||||
# print 'write'
|
||||
# print array
|
||||
self.dataModel.write(0, array)
|
||||
self.viewMode.draw(True)
|
||||
del pyperclip
|
||||
#print array
|
||||
# print array
|
||||
|
||||
if key == QtCore.Qt.Key_F4:
|
||||
self.unp = WUnpack(self, None)
|
||||
self.unp.show()
|
||||
|
||||
|
||||
if key == QtCore.Qt.Key_F10:
|
||||
self.dataModel.flush()
|
||||
self.w = WHeaders(self, None)
|
||||
self.w.show()
|
||||
|
||||
|
||||
if not self.viewMode.isInEditMode():
|
||||
if key == QtCore.Qt.Key_Slash:
|
||||
self.searchWindow.show()
|
||||
@ -414,7 +408,6 @@ class binWidget(QtWidgets.QWidget, Observable):
|
||||
self.update()
|
||||
return True
|
||||
|
||||
|
||||
return False
|
||||
|
||||
def setTextViewport(self, qp):
|
||||
|
@ -3,11 +3,12 @@ from PyQt5 import QtGui
|
||||
|
||||
from androguard.core import androconf
|
||||
|
||||
|
||||
class Cursor(object):
|
||||
def __init__(self, x, y):
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
|
||||
def move(self, dx, dy):
|
||||
self.x += dx
|
||||
self.y += dy
|
||||
@ -19,9 +20,11 @@ class Cursor(object):
|
||||
def getPosition(self):
|
||||
return self.x, self.y
|
||||
|
||||
|
||||
def enum(**enums):
|
||||
return type('Enum', (), enums)
|
||||
|
||||
|
||||
Directions = enum(Left=1, Right=2, Up=3, Down=4, End=5, Home=6, CtrlEnd=7, CtrlHome=8)
|
||||
|
||||
|
||||
@ -34,7 +37,7 @@ class ConsoleEmulator(object):
|
||||
self._cols = cols
|
||||
|
||||
fm = QtGui.QFontMetrics(self.qp.font())
|
||||
self.fontWidth = fm.width('a')
|
||||
self.fontWidth = fm.width('a')
|
||||
self.fontHeight = fm.height()
|
||||
|
||||
def incrementPosition(self):
|
||||
@ -44,7 +47,6 @@ class ConsoleEmulator(object):
|
||||
self._x = 0
|
||||
self._y += 1
|
||||
|
||||
|
||||
def newLine(self):
|
||||
self.LF()
|
||||
self.CR()
|
||||
@ -74,7 +76,7 @@ class ConsoleEmulator(object):
|
||||
self.qp.setBackgroundMode(0)
|
||||
|
||||
self.qp.drawText(self._x * self.fontWidth, self.fontHeight + self._y * self.fontHeight, c)
|
||||
self.incrementPosition()
|
||||
self.incrementPosition()
|
||||
self.qp.setBackgroundMode(background)
|
||||
|
||||
def write_c(self, c, noBackgroudOnSpaces=False):
|
||||
@ -84,7 +86,7 @@ class ConsoleEmulator(object):
|
||||
self.qp.setBackgroundMode(0)
|
||||
|
||||
self.qp.drawText(self._x * self.fontWidth, self.fontHeight + self._y * self.fontHeight, c)
|
||||
self.incrementPosition()
|
||||
self.incrementPosition()
|
||||
self.qp.setBackgroundMode(background)
|
||||
|
||||
def getXY(self):
|
||||
@ -99,7 +101,7 @@ class ConsoleEmulator(object):
|
||||
self.write_c(c, noBackgroudOnSpaces)
|
||||
|
||||
def writeLn(self):
|
||||
if True:#self._validatePosition(self._x, self._y):
|
||||
if True: # self._validatePosition(self._x, self._y):
|
||||
self._y += 1
|
||||
self._x = 0
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
from __future__ import print_function
|
||||
from builtins import object
|
||||
class Signature(object):
|
||||
|
||||
|
||||
class Signature(object):
|
||||
def __init__(self, cls, method=None, descriptor=None):
|
||||
self.cls = cls
|
||||
self.class_components = self.cls.name.strip('L').strip(';').split('/')
|
||||
|
@ -49,14 +49,14 @@ class TabsWindow(QtWidgets.QTabWidget):
|
||||
self.clear()
|
||||
|
||||
def actioncloseOtherTabs(self):
|
||||
for i in range(self.currentIndex()-1, -1, -1):
|
||||
for i in range(self.currentIndex() - 1, -1, -1):
|
||||
self.removeTab(i)
|
||||
|
||||
for i in range(self.count(), self.currentIndex(), -1):
|
||||
self.removeTab(i)
|
||||
|
||||
def actioncloseLeftTabs(self):
|
||||
for i in range(self.currentIndex()-1, -1, -1):
|
||||
for i in range(self.currentIndex() - 1, -1, -1):
|
||||
self.removeTab(i)
|
||||
|
||||
def actioncloseRightTabs(self):
|
||||
@ -81,7 +81,6 @@ class TabsWindow(QtWidgets.QTabWidget):
|
||||
androconf.debug("Enable %s" % title)
|
||||
self.bin_windows[current_title].enable()
|
||||
|
||||
|
||||
def contextMenuEvent(self, event):
|
||||
menu = QtWidgets.QMenu(self)
|
||||
menu.addAction(self.closeAllTabs)
|
||||
@ -90,6 +89,7 @@ class TabsWindow(QtWidgets.QTabWidget):
|
||||
menu.addAction(self.closeRightTabs)
|
||||
menu.exec_(event.globalPos())
|
||||
|
||||
|
||||
class MainWindow(QtWidgets.QMainWindow):
|
||||
'''Main window:
|
||||
self.central: QTabWidget in center area
|
||||
@ -139,8 +139,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
def about(self):
|
||||
'''User clicked About menu. Display a Message box.'''
|
||||
QtWidgets.QMessageBox.about(self, "About Androguard GUI",
|
||||
"<p><b>Androguard GUI</b> is basically a GUI for Androguard :)." \
|
||||
"<br>Have fun !</p>")
|
||||
"<p><b>Androguard GUI</b> is basically a GUI for Androguard :)." \
|
||||
"<br>Have fun !</p>")
|
||||
|
||||
def setupSession(self):
|
||||
androconf.debug("Setup Session")
|
||||
@ -351,7 +351,6 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
|
||||
self.central.setCurrentWidget(bin_window)
|
||||
|
||||
|
||||
def openSourceWindow(self, current_class, method=None):
|
||||
'''Main function to open a decompile source window
|
||||
It checks if it already opened and open that tab,
|
||||
|
@ -3,7 +3,6 @@ from androguard.gui.xrefwindow import XrefDialogMethod
|
||||
|
||||
|
||||
class MethodsWindow(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent=None, win=None, session=None):
|
||||
super(MethodsWindow, self).__init__(parent)
|
||||
self.mainwin = win
|
||||
@ -30,7 +29,6 @@ class MethodsWindow(QtWidgets.QWidget):
|
||||
|
||||
|
||||
class MethodsValueWindow(QtWidgets.QTreeView):
|
||||
|
||||
def __init__(self, parent=None, win=None, session=None):
|
||||
super(MethodsValueWindow, self).__init__(parent)
|
||||
self.mainwin = win
|
||||
@ -70,7 +68,7 @@ class MethodsValueWindow(QtWidgets.QTreeView):
|
||||
self.model.setData(self.model.index(
|
||||
row, 4, QtCore.QModelIndex()), digest)
|
||||
self.reverse_methods[method.get_name() + method.get_class_name() + method.get_descriptor() + digest
|
||||
] = dx.get_method_analysis(method)
|
||||
] = dx.get_method_analysis(method)
|
||||
row += 1
|
||||
|
||||
self.proxyModel.setSourceModel(self.model)
|
||||
@ -93,7 +91,7 @@ class MethodsValueWindow(QtWidgets.QTreeView):
|
||||
parent=self.mainwin,
|
||||
win=self.mainwin,
|
||||
method_analysis=self.reverse_methods[self.model.item(row).text() +
|
||||
self.model.item(row, 1).text() +
|
||||
self.model.item(row, 2).text() +
|
||||
self.model.item(row, 1).text() +
|
||||
self.model.item(row, 2).text() +
|
||||
self.model.item(row, 4).text()])
|
||||
xwin.show()
|
||||
|
@ -3,7 +3,6 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class ResourcesWindow(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent=None, win=None, session=None):
|
||||
super(ResourcesWindow, self).__init__(parent)
|
||||
self.mainwin = win
|
||||
@ -30,7 +29,6 @@ class ResourcesWindow(QtWidgets.QWidget):
|
||||
|
||||
|
||||
class ResourcesValueWindow(QtWidgets.QTreeView):
|
||||
|
||||
def __init__(self, parent=None, win=None, session=None):
|
||||
super(ResourcesValueWindow, self).__init__(parent)
|
||||
self.mainwin = win
|
||||
|
@ -1,43 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>searchform</class>
|
||||
<widget class="QWidget" name="searchform">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>430</width>
|
||||
<height>116</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
<class>searchform</class>
|
||||
<widget class="QWidget" name="searchform">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>430</width>
|
||||
<height>116</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkHex">
|
||||
<property name="text">
|
||||
<string>hex</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkHex">
|
||||
<property name="text">
|
||||
<string>hex</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>lineEdit</tabstop>
|
||||
<tabstop>checkHex</tabstop>
|
||||
<tabstop>pushButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
<tabstops>
|
||||
<tabstop>lineEdit</tabstop>
|
||||
<tabstop>checkHex</tabstop>
|
||||
<tabstop>pushButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -6,10 +6,8 @@ from androguard.gui.helpers import class2func, method2func, classdot2func, class
|
||||
from androguard.gui.renamewindow import RenameDialog
|
||||
from androguard.gui.xrefwindow import XrefDialogMethod, XrefDialogField
|
||||
|
||||
|
||||
import pyperclip
|
||||
|
||||
|
||||
from pygments.formatters.html import HtmlFormatter
|
||||
from pygments.lexers import JavaLexer
|
||||
from pygments.styles import get_style_by_name
|
||||
@ -17,7 +15,6 @@ from pygments.styles import get_style_by_name
|
||||
from pygments.style import Style
|
||||
from pygments.token import Token, Comment, Name, Keyword, Generic, Number, Operator, String
|
||||
|
||||
|
||||
BINDINGS_NAMES = [
|
||||
'NAME_PACKAGE', 'NAME_PROTOTYPE', 'NAME_SUPERCLASS', 'NAME_INTERFACE',
|
||||
'NAME_FIELD', 'NAME_METHOD_PROTOTYPE', 'NAME_ARG', 'NAME_CLASS_ASSIGNMENT',
|
||||
@ -45,6 +42,7 @@ class SourceDocument(QtGui.QTextDocument):
|
||||
self.binding[cursor.position()] = t
|
||||
cursor.insertText(t[1])
|
||||
|
||||
|
||||
class PygmentsBlockUserData(QtGui.QTextBlockUserData):
|
||||
""" Storage for the user data associated with each line.
|
||||
"""
|
||||
@ -58,10 +56,11 @@ class PygmentsBlockUserData(QtGui.QTextBlockUserData):
|
||||
|
||||
def __repr__(self):
|
||||
attrs = ['syntax_stack']
|
||||
kwds = ', '.join([ '%s=%r' % (attr, getattr(self, attr))
|
||||
for attr in attrs ])
|
||||
kwds = ', '.join(['%s=%r' % (attr, getattr(self, attr))
|
||||
for attr in attrs])
|
||||
return 'PygmentsBlockUserData(%s)' % kwds
|
||||
|
||||
|
||||
BASE03 = '#002B36'
|
||||
BASE02 = '#073642'
|
||||
BASE01 = '#586E75'
|
||||
@ -79,18 +78,19 @@ BLUE = '#268BD2'
|
||||
CYAN = '#2AA198'
|
||||
GREEN = '#859900'
|
||||
|
||||
|
||||
class SolarizedStyle(Style):
|
||||
background_color = BASE03
|
||||
styles = {
|
||||
Keyword: GREEN,
|
||||
Keyword.Constant: ORANGE,
|
||||
Keyword.Declaration: BLUE,
|
||||
#Keyword.Namespace
|
||||
#Keyword.Pseudo
|
||||
# Keyword.Namespace
|
||||
# Keyword.Pseudo
|
||||
Keyword.Reserved: BLUE,
|
||||
Keyword.Type: RED,
|
||||
|
||||
#Name
|
||||
# Name
|
||||
Name.Attribute: BASE1,
|
||||
Name.Builtin: YELLOW,
|
||||
Name.Builtin.Pseudo: BLUE,
|
||||
@ -100,69 +100,70 @@ class SolarizedStyle(Style):
|
||||
Name.Entity: ORANGE,
|
||||
Name.Exception: ORANGE,
|
||||
Name.Function: BLUE,
|
||||
#Name.Label
|
||||
#Name.Namespace
|
||||
#Name.Other
|
||||
# Name.Label
|
||||
# Name.Namespace
|
||||
# Name.Other
|
||||
Name.Tag: BLUE,
|
||||
Name.Variable: BLUE,
|
||||
#Name.Variable.Class
|
||||
#Name.Variable.Global
|
||||
#Name.Variable.Instance
|
||||
# Name.Variable.Class
|
||||
# Name.Variable.Global
|
||||
# Name.Variable.Instance
|
||||
|
||||
#Literal
|
||||
#Literal.Date
|
||||
# Literal
|
||||
# Literal.Date
|
||||
String: CYAN,
|
||||
String.Backtick: BASE01,
|
||||
String.Char: CYAN,
|
||||
String.Doc: BASE1,
|
||||
#String.Double
|
||||
# String.Double
|
||||
String.Escape: ORANGE,
|
||||
String.Heredoc: BASE1,
|
||||
#String.Interpol
|
||||
#String.Other
|
||||
# String.Interpol
|
||||
# String.Other
|
||||
String.Regex: RED,
|
||||
#String.Single
|
||||
#String.Symbol
|
||||
# String.Single
|
||||
# String.Symbol
|
||||
Number: CYAN,
|
||||
#Number.Float
|
||||
#Number.Hex
|
||||
#Number.Integer
|
||||
#Number.Integer.Long
|
||||
#Number.Oct
|
||||
# Number.Float
|
||||
# Number.Hex
|
||||
# Number.Integer
|
||||
# Number.Integer.Long
|
||||
# Number.Oct
|
||||
|
||||
Operator: GREEN,
|
||||
#Operator.Word
|
||||
# Operator.Word
|
||||
|
||||
#Punctuation: ORANGE,
|
||||
# Punctuation: ORANGE,
|
||||
|
||||
Comment: BASE01,
|
||||
#Comment.Multiline
|
||||
# Comment.Multiline
|
||||
Comment.Preproc: GREEN,
|
||||
#Comment.Single
|
||||
# Comment.Single
|
||||
Comment.Special: GREEN,
|
||||
|
||||
#Generic
|
||||
# Generic
|
||||
Generic.Deleted: CYAN,
|
||||
Generic.Emph: 'italic',
|
||||
Generic.Error: RED,
|
||||
Generic.Heading: ORANGE,
|
||||
Generic.Inserted: GREEN,
|
||||
#Generic.Output
|
||||
#Generic.Prompt
|
||||
# Generic.Output
|
||||
# Generic.Prompt
|
||||
Generic.Strong: 'bold',
|
||||
Generic.Subheading: ORANGE,
|
||||
#Generic.Traceback
|
||||
# Generic.Traceback
|
||||
|
||||
Token: BASE1,
|
||||
Token.Other: ORANGE,
|
||||
}
|
||||
|
||||
|
||||
class MyHighlighter(QtGui.QSyntaxHighlighter):
|
||||
""" Syntax highlighter that uses Pygments for parsing. """
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
# 'QSyntaxHighlighter' interface
|
||||
#---------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def __init__(self, parent, lexer=None):
|
||||
super(MyHighlighter, self).__init__(parent)
|
||||
@ -195,14 +196,14 @@ class MyHighlighter(QtGui.QSyntaxHighlighter):
|
||||
# Clean up for the next go-round.
|
||||
del self._lexer._saved_state_stack
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
# 'PygmentsHighlighter' interface
|
||||
#---------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def set_style(self, style):
|
||||
""" Sets the style to the specified Pygments style.
|
||||
"""
|
||||
style = SolarizedStyle#get_style_by_name(style)
|
||||
style = SolarizedStyle # get_style_by_name(style)
|
||||
self._style = style
|
||||
self._clear_caches()
|
||||
|
||||
@ -217,9 +218,9 @@ class MyHighlighter(QtGui.QSyntaxHighlighter):
|
||||
self._style = None
|
||||
self._clear_caches()
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
# Protected interface
|
||||
#---------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _clear_caches(self):
|
||||
""" Clear caches for brushes and formats.
|
||||
@ -282,6 +283,7 @@ class MyHighlighter(QtGui.QSyntaxHighlighter):
|
||||
int(color[4:6], base=16))
|
||||
return qcolor
|
||||
|
||||
|
||||
class SourceWindow(QtWidgets.QTextEdit):
|
||||
'''Each tab is implemented as a Source Window class.
|
||||
Attributes:
|
||||
@ -315,7 +317,6 @@ class SourceWindow(QtWidgets.QTextEdit):
|
||||
self.setReadOnly(True)
|
||||
self.setStyleSheet("background: rgba(0,43,54,100%)")
|
||||
|
||||
|
||||
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.customContextMenuRequested.connect(self.CustomContextMenuHandler)
|
||||
|
||||
@ -327,11 +328,11 @@ class SourceWindow(QtWidgets.QTextEdit):
|
||||
TODO: implement it, because does not work for now.
|
||||
'''
|
||||
|
||||
#TODO: we need to find a way to scroll to the right place because
|
||||
# TODO: we need to find a way to scroll to the right place because
|
||||
# moving the cursor is not enough. Indeed if it is already in the window
|
||||
# it does not do nothing
|
||||
|
||||
#TODO: idea, highlight the method in the screen so we do not have to search for it
|
||||
# TODO: idea, highlight the method in the screen so we do not have to search for it
|
||||
|
||||
androconf.debug("Browsing to %s -> %s" % (self.current_class, method))
|
||||
|
||||
@ -366,14 +367,14 @@ class SourceWindow(QtWidgets.QTextEdit):
|
||||
|
||||
lines.extend(self.current_class.get_source_ext())
|
||||
|
||||
#TODO: delete doc when tab is closed? not deleted by "self" :(
|
||||
# TODO: delete doc when tab is closed? not deleted by "self" :(
|
||||
if hasattr(self, "doc"):
|
||||
del self.doc
|
||||
self.doc = SourceDocument(parent=self, lines=lines)
|
||||
self.setDocument(self.doc)
|
||||
|
||||
#No need to save hightlighter. highlighBlock will automatically be called
|
||||
#because we passed the QTextDocument to QSyntaxHighlighter constructor
|
||||
# No need to save hightlighter. highlighBlock will automatically be called
|
||||
# because we passed the QTextDocument to QSyntaxHighlighter constructor
|
||||
MyHighlighter(self.doc, lexer=JavaLexer())
|
||||
|
||||
def cursor_position_changed(self):
|
||||
@ -387,7 +388,7 @@ class SourceWindow(QtWidgets.QTextEdit):
|
||||
if len(cur.selectedText()) == 0:
|
||||
cur.select(QtGui.QTextCursor.WordUnderCursor)
|
||||
self.setTextCursor(cur)
|
||||
#androconf.debug("cursor: %s" % cur.selectedText())
|
||||
# androconf.debug("cursor: %s" % cur.selectedText())
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
'''Keyboard shortcuts'''
|
||||
@ -411,14 +412,14 @@ class SourceWindow(QtWidgets.QTextEdit):
|
||||
statusTip="List the references where this element is used",
|
||||
triggered=self.actionXref))
|
||||
menu.addAction(QtWidgets.QAction("&Goto",
|
||||
self,
|
||||
statusTip="Go to element definition",
|
||||
triggered=self.actionGoto))
|
||||
self,
|
||||
statusTip="Go to element definition",
|
||||
triggered=self.actionGoto))
|
||||
menu.addAction(
|
||||
QtWidgets.QAction("Rename...",
|
||||
self,
|
||||
statusTip="Rename an element (class, method, ...)",
|
||||
triggered=self.actionRename))
|
||||
self,
|
||||
statusTip="Rename an element (class, method, ...)",
|
||||
triggered=self.actionRename))
|
||||
menu.addAction(QtWidgets.QAction(
|
||||
"&Info",
|
||||
self,
|
||||
@ -432,10 +433,10 @@ class SourceWindow(QtWidgets.QTextEdit):
|
||||
"Reload sources (needed when renaming changed other tabs)",
|
||||
triggered=self.reload_java_sources))
|
||||
menu.addAction(QtWidgets.QAction("&Copy",
|
||||
self,
|
||||
shortcut=QtGui.QKeySequence.Copy,
|
||||
statusTip="Copy the current selection's contents to the clipboard",
|
||||
triggered=self.actionCopy))
|
||||
self,
|
||||
shortcut=QtGui.QKeySequence.Copy,
|
||||
statusTip="Copy the current selection's contents to the clipboard",
|
||||
triggered=self.actionCopy))
|
||||
menu.exec_(QtGui.QCursor.pos())
|
||||
|
||||
def actionXref(self):
|
||||
@ -518,17 +519,17 @@ class SourceWindow(QtWidgets.QTextEdit):
|
||||
self.mainwin.showStatus("No xref returned.")
|
||||
return
|
||||
|
||||
#elif t[0] == 'NAME_METHOD_INVOKE':
|
||||
# class_, method_ = t[2].split(' -> ')
|
||||
# if class_ == 'this':
|
||||
# class_ = self.current_class
|
||||
# else:
|
||||
# class_ = classdot2class(class_)
|
||||
#elif t[0] == 'NAME_PROTOTYPE':
|
||||
# class_ = classdot2class(t[2] + '.' + t[1])
|
||||
#else:
|
||||
# self.mainwin.showStatus("Xref not available. Info ok: '%s' but object not supported." % selection)
|
||||
# return
|
||||
# elif t[0] == 'NAME_METHOD_INVOKE':
|
||||
# class_, method_ = t[2].split(' -> ')
|
||||
# if class_ == 'this':
|
||||
# class_ = self.current_class
|
||||
# else:
|
||||
# class_ = classdot2class(class_)
|
||||
# elif t[0] == 'NAME_PROTOTYPE':
|
||||
# class_ = classdot2class(t[2] + '.' + t[1])
|
||||
# else:
|
||||
# self.mainwin.showStatus("Xref not available. Info ok: '%s' but object not supported." % selection)
|
||||
# return
|
||||
|
||||
def actionCopy(self):
|
||||
print('COPY')
|
||||
@ -723,12 +724,12 @@ class SourceWindow(QtWidgets.QTextEdit):
|
||||
self.mainwin.showStatus("Impossible to find the method")
|
||||
return
|
||||
|
||||
method_item.set_name(str(newname)) #unicode to ascii
|
||||
method_item.set_name(str(newname)) # unicode to ascii
|
||||
elif type_ == "CLASS":
|
||||
newname_class = classdot2class(package_ + '.' + newname)
|
||||
self.mainwin.showStatus("New name: %s" % newname_class)
|
||||
class_item = self.current_class #getattr(self.mainwin.d, classdot2func(class_))
|
||||
class_item.set_name(str(newname_class)) #unicode to ascii
|
||||
class_item = self.current_class # getattr(self.mainwin.d, classdot2func(class_))
|
||||
class_item.set_name(str(newname_class)) # unicode to ascii
|
||||
self.mainwin.updateDockWithTree()
|
||||
elif type_ == 'FIELD':
|
||||
if self.field_name_exist(newname):
|
||||
|
@ -3,7 +3,6 @@ from androguard.gui.xrefwindow import XrefDialogString
|
||||
|
||||
|
||||
class StringsWindow(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent=None, win=None, session=None):
|
||||
super(StringsWindow, self).__init__(parent)
|
||||
self.mainwin = win
|
||||
@ -30,7 +29,6 @@ class StringsWindow(QtWidgets.QWidget):
|
||||
|
||||
|
||||
class StringsValueWindow(QtWidgets.QTreeView):
|
||||
|
||||
def __init__(self, parent=None, win=None, session=None):
|
||||
super(StringsValueWindow, self).__init__(parent)
|
||||
self.mainwin = win
|
||||
@ -63,7 +61,7 @@ class StringsValueWindow(QtWidgets.QTreeView):
|
||||
self.model.setData(self.model.index(
|
||||
row, 3, QtCore.QModelIndex()), digest)
|
||||
self.reverse_strings[repr(strings_analysis[string_value].get_value()) + digest
|
||||
] = strings_analysis[string_value]
|
||||
] = strings_analysis[string_value]
|
||||
row += 1
|
||||
|
||||
self.proxyModel.setSourceModel(self.model)
|
||||
|
@ -7,8 +7,8 @@ from androguard.gui.xrefwindow import XrefDialogClass
|
||||
from androguard.gui.sourcewindow import SourceWindow
|
||||
from androguard.gui.helpers import classdot2class, Signature
|
||||
|
||||
|
||||
class HashableQTreeWidgetItem(QtWidgets.QTreeWidgetItem):
|
||||
|
||||
# TODO this is a pure workaround to have a hash method!
|
||||
# It seems that for python2 is __hash__ available
|
||||
# But not on python3
|
||||
@ -17,7 +17,6 @@ class HashableQTreeWidgetItem(QtWidgets.QTreeWidgetItem):
|
||||
|
||||
|
||||
class TreeWindow(QtWidgets.QTreeWidget):
|
||||
|
||||
def __init__(self, parent=None, win=None, session=None):
|
||||
super(TreeWindow, self).__init__(parent)
|
||||
self.itemDoubleClicked.connect(self.itemDoubleClickedHandler)
|
||||
@ -92,13 +91,13 @@ class TreeWindow(QtWidgets.QTreeWidget):
|
||||
statusTip="List the references where this element is used",
|
||||
triggered=self.actionXref)
|
||||
self.expandAct = QtWidgets.QAction("Expand",
|
||||
self,
|
||||
statusTip="Expand all the subtrees",
|
||||
triggered=self.actionExpand)
|
||||
self,
|
||||
statusTip="Expand all the subtrees",
|
||||
triggered=self.actionExpand)
|
||||
self.collapseAct = QtWidgets.QAction("Collapse",
|
||||
self,
|
||||
statusTip="Collapse all the subtrees",
|
||||
triggered=self.actionCollapse)
|
||||
self,
|
||||
statusTip="Collapse all the subtrees",
|
||||
triggered=self.actionCollapse)
|
||||
|
||||
def actionXref(self):
|
||||
item = self.currentItem()
|
||||
@ -126,7 +125,6 @@ class TreeWindow(QtWidgets.QTreeWidget):
|
||||
class_analysis=class_analysis)
|
||||
xwin.show()
|
||||
|
||||
|
||||
def expand_children(self, item):
|
||||
self.expandItem(item)
|
||||
for i in range(item.childCount()):
|
||||
|
@ -67,7 +67,6 @@ class XrefDialogClass(QtWidgets.QDialog):
|
||||
|
||||
|
||||
class XrefDialogMethod(QtWidgets.QDialog):
|
||||
|
||||
def __init__(self,
|
||||
parent=None,
|
||||
win=None,
|
||||
@ -108,7 +107,6 @@ class XrefDialogMethod(QtWidgets.QDialog):
|
||||
|
||||
|
||||
class XrefDialogField(QtWidgets.QDialog):
|
||||
|
||||
def __init__(self,
|
||||
parent=None,
|
||||
win=None,
|
||||
@ -153,7 +151,6 @@ class XrefDialogField(QtWidgets.QDialog):
|
||||
|
||||
|
||||
class XrefDialogString(QtWidgets.QDialog):
|
||||
|
||||
def __init__(self, parent=None, win=None, string_analysis=None):
|
||||
super(XrefDialogString, self).__init__(parent)
|
||||
self.string_analysis = string_analysis
|
||||
@ -248,12 +245,11 @@ class XrefDialog(QtWidgets.QDialog):
|
||||
method_ = xref_item[0].get_name()
|
||||
descriptor_ = xref_item[0].get_descriptor()
|
||||
xrefs.append(classmethod2display(class_, method_, descriptor_))
|
||||
# print xrefs
|
||||
# print xrefs
|
||||
return xrefs
|
||||
|
||||
|
||||
class XrefListView(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self,
|
||||
parent=None,
|
||||
win=None,
|
||||
@ -290,7 +286,6 @@ class XrefListView(QtWidgets.QWidget):
|
||||
|
||||
|
||||
class XrefValueWindow(QtWidgets.QTreeView):
|
||||
|
||||
def __init__(self, parent=None, win=None, xrefs=None, headers=None):
|
||||
super(XrefValueWindow, self).__init__(parent)
|
||||
self.parent = parent
|
||||
|
@ -1,4 +1,5 @@
|
||||
from future import standard_library
|
||||
|
||||
standard_library.install_aliases()
|
||||
from androguard.core import *
|
||||
from androguard.core.bytecode import *
|
||||
@ -11,6 +12,7 @@ from pickle import dump, load
|
||||
from androguard.core import androconf
|
||||
from androguard import session
|
||||
|
||||
|
||||
def init_print_colors():
|
||||
from IPython.utils import coloransi, io
|
||||
androconf.default_colors(coloransi.TermColors)
|
||||
@ -26,6 +28,7 @@ def get_default_session():
|
||||
CONF["SESSION"] = session.Session()
|
||||
return CONF["SESSION"]
|
||||
|
||||
|
||||
def save_session(l, filename):
|
||||
"""
|
||||
save your session !
|
||||
@ -138,7 +141,7 @@ def RunDecompiler(d, dx, decompiler, session=None):
|
||||
if decompiler == "dex2jad":
|
||||
d.set_decompiler(DecompilerDex2Jad(
|
||||
d, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"
|
||||
], androconf.CONF["PATH_JAD"],
|
||||
], androconf.CONF["PATH_JAD"],
|
||||
androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"]))
|
||||
elif decompiler == "dex2fernflower":
|
||||
d.set_decompiler(DecompilerDex2Fernflower(
|
||||
@ -147,7 +150,7 @@ def RunDecompiler(d, dx, decompiler, session=None):
|
||||
], androconf.CONF["PATH_FERNFLOWER"], androconf.CONF[
|
||||
"BIN_FERNFLOWER"
|
||||
], androconf.CONF["OPTIONS_FERNFLOWER"
|
||||
], androconf.CONF["TMP_DIRECTORY"]))
|
||||
], androconf.CONF["TMP_DIRECTORY"]))
|
||||
elif decompiler == "ded":
|
||||
d.set_decompiler(DecompilerDed(d, androconf.CONF["PATH_DED"],
|
||||
androconf.CONF["BIN_DED"],
|
||||
|
@ -3,6 +3,7 @@ Read and write ZIP files.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from future import standard_library
|
||||
|
||||
standard_library.install_aliases()
|
||||
from builtins import chr
|
||||
from builtins import map
|
||||
@ -15,14 +16,16 @@ import io
|
||||
import re
|
||||
|
||||
try:
|
||||
import zlib # We may need its compression method
|
||||
import zlib # We may need its compression method
|
||||
|
||||
crc32 = zlib.crc32
|
||||
except ImportError:
|
||||
zlib = None
|
||||
crc32 = binascii.crc32
|
||||
|
||||
__all__ = ["BadZipfile", "error", "ZIP_STORED", "ZIP_DEFLATED", "is_zipfile",
|
||||
"ZipInfo", "ZipFile", "PyZipFile", "LargeZipFile" ]
|
||||
"ZipInfo", "ZipFile", "PyZipFile", "LargeZipFile"]
|
||||
|
||||
|
||||
class BadZipfile(Exception):
|
||||
pass
|
||||
@ -34,7 +37,8 @@ class LargeZipFile(Exception):
|
||||
and those extensions are disabled.
|
||||
"""
|
||||
|
||||
error = BadZipfile # The exception raised by this module
|
||||
|
||||
error = BadZipfile # The exception raised by this module
|
||||
|
||||
ZIP64_LIMIT = (1 << 31) - 1
|
||||
ZIP_FILECOUNT_LIMIT = 1 << 16
|
||||
@ -138,14 +142,16 @@ _CD64_NUMBER_ENTRIES_TOTAL = 7
|
||||
_CD64_DIRECTORY_SIZE = 8
|
||||
_CD64_OFFSET_START_CENTDIR = 9
|
||||
|
||||
|
||||
def _check_zipfile(fp):
|
||||
try:
|
||||
if _EndRecData(fp):
|
||||
return True # file has correct magic number
|
||||
return True # file has correct magic number
|
||||
except IOError:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def is_zipfile(filename):
|
||||
"""Quickly see if a file is a ZIP file by checking the magic number.
|
||||
|
||||
@ -162,6 +168,7 @@ def is_zipfile(filename):
|
||||
pass
|
||||
return result
|
||||
|
||||
|
||||
def _EndRecData64(fpin, offset, endrec):
|
||||
"""
|
||||
Read the ZIP64 end-of-archive records and use that to update endrec
|
||||
@ -185,8 +192,8 @@ def _EndRecData64(fpin, offset, endrec):
|
||||
fpin.seek(offset - sizeEndCentDir64Locator - sizeEndCentDir64, 2)
|
||||
data = fpin.read(sizeEndCentDir64)
|
||||
sig, sz, create_version, read_version, disk_num, disk_dir, \
|
||||
dircount, dircount2, dirsize, diroffset = \
|
||||
struct.unpack(structEndArchive64, data)
|
||||
dircount, dircount2, dirsize, diroffset = \
|
||||
struct.unpack(structEndArchive64, data)
|
||||
if sig != stringEndArchive64:
|
||||
return endrec
|
||||
|
||||
@ -222,7 +229,7 @@ def _EndRecData(fpin):
|
||||
if data[0:4] == stringEndArchive and data[-2:] == "\000\000":
|
||||
# the signature is correct and there's no comment, unpack structure
|
||||
endrec = struct.unpack(structEndArchive, data)
|
||||
endrec=list(endrec)
|
||||
endrec = list(endrec)
|
||||
|
||||
# Append a blank comment and record start offset
|
||||
endrec.append("")
|
||||
@ -242,10 +249,10 @@ def _EndRecData(fpin):
|
||||
start = data.rfind(stringEndArchive)
|
||||
if start >= 0:
|
||||
# found the magic number; attempt to unpack and interpret
|
||||
recData = data[start:start+sizeEndCentDir]
|
||||
recData = data[start:start + sizeEndCentDir]
|
||||
endrec = list(struct.unpack(structEndArchive, recData))
|
||||
commentSize = endrec[_ECD_COMMENT_SIZE] #as claimed by the zip file
|
||||
comment = data[start+sizeEndCentDir:start+sizeEndCentDir+commentSize]
|
||||
commentSize = endrec[_ECD_COMMENT_SIZE] # as claimed by the zip file
|
||||
comment = data[start + sizeEndCentDir:start + sizeEndCentDir + commentSize]
|
||||
endrec.append(comment)
|
||||
endrec.append(maxCommentStart + start)
|
||||
|
||||
@ -257,33 +264,33 @@ def _EndRecData(fpin):
|
||||
return
|
||||
|
||||
|
||||
class ZipInfo (object):
|
||||
class ZipInfo(object):
|
||||
"""Class with attributes describing each file in the ZIP archive."""
|
||||
|
||||
__slots__ = (
|
||||
'orig_filename',
|
||||
'filename',
|
||||
'date_time',
|
||||
'compress_type',
|
||||
'comment',
|
||||
'extra',
|
||||
'create_system',
|
||||
'create_version',
|
||||
'extract_version',
|
||||
'reserved',
|
||||
'flag_bits',
|
||||
'volume',
|
||||
'internal_attr',
|
||||
'external_attr',
|
||||
'header_offset',
|
||||
'CRC',
|
||||
'compress_size',
|
||||
'file_size',
|
||||
'_raw_time',
|
||||
)
|
||||
'orig_filename',
|
||||
'filename',
|
||||
'date_time',
|
||||
'compress_type',
|
||||
'comment',
|
||||
'extra',
|
||||
'create_system',
|
||||
'create_version',
|
||||
'extract_version',
|
||||
'reserved',
|
||||
'flag_bits',
|
||||
'volume',
|
||||
'internal_attr',
|
||||
'external_attr',
|
||||
'header_offset',
|
||||
'CRC',
|
||||
'compress_size',
|
||||
'file_size',
|
||||
'_raw_time',
|
||||
)
|
||||
|
||||
def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)):
|
||||
self.orig_filename = filename # Original file name in archive
|
||||
def __init__(self, filename="NoName", date_time=(1980, 1, 1, 0, 0, 0)):
|
||||
self.orig_filename = filename # Original file name in archive
|
||||
|
||||
# Terminate the file name at the first null byte. Null bytes in file
|
||||
# names are used as tricks by viruses in archives.
|
||||
@ -296,24 +303,24 @@ class ZipInfo (object):
|
||||
if os.sep != "/" and os.sep in filename:
|
||||
filename = filename.replace(os.sep, "/")
|
||||
|
||||
self.filename = filename # Normalized file name
|
||||
self.date_time = date_time # year, month, day, hour, min, sec
|
||||
self.filename = filename # Normalized file name
|
||||
self.date_time = date_time # year, month, day, hour, min, sec
|
||||
# Standard values:
|
||||
self.compress_type = ZIP_STORED # Type of compression for the file
|
||||
self.comment = "" # Comment for each file
|
||||
self.extra = "" # ZIP extra data
|
||||
self.compress_type = ZIP_STORED # Type of compression for the file
|
||||
self.comment = "" # Comment for each file
|
||||
self.extra = "" # ZIP extra data
|
||||
if sys.platform == 'win32':
|
||||
self.create_system = 0 # System which created ZIP archive
|
||||
self.create_system = 0 # System which created ZIP archive
|
||||
else:
|
||||
# Assume everything else is unix-y
|
||||
self.create_system = 3 # System which created ZIP archive
|
||||
self.create_version = 20 # Version which created ZIP archive
|
||||
self.extract_version = 20 # Version needed to extract archive
|
||||
self.reserved = 0 # Must be zero
|
||||
self.flag_bits = 0 # ZIP flag bits
|
||||
self.volume = 0 # Volume number of file header
|
||||
self.internal_attr = 0 # Internal attributes
|
||||
self.external_attr = 0 # External file attributes
|
||||
self.create_system = 3 # System which created ZIP archive
|
||||
self.create_version = 20 # Version which created ZIP archive
|
||||
self.extract_version = 20 # Version needed to extract archive
|
||||
self.reserved = 0 # Must be zero
|
||||
self.flag_bits = 0 # ZIP flag bits
|
||||
self.volume = 0 # Volume number of file header
|
||||
self.internal_attr = 0 # Internal attributes
|
||||
self.external_attr = 0 # External file attributes
|
||||
# Other attributes are set by class ZipFile(object):
|
||||
# header_offset Byte offset to the file header
|
||||
# CRC CRC-32 of the uncompressed file
|
||||
@ -340,7 +347,7 @@ class ZipInfo (object):
|
||||
# fall back to the ZIP64 extension
|
||||
fmt = '<HHQQ'
|
||||
extra = extra + struct.pack(fmt,
|
||||
1, struct.calcsize(fmt)-4, file_size, compress_size)
|
||||
1, struct.calcsize(fmt) - 4, file_size, compress_size)
|
||||
file_size = 0xffffffff
|
||||
compress_size = 0xffffffff
|
||||
self.extract_version = max(45, self.extract_version)
|
||||
@ -348,10 +355,10 @@ class ZipInfo (object):
|
||||
|
||||
filename, flag_bits = self._encodeFilenameFlags()
|
||||
header = struct.pack(structFileHeader, stringFileHeader,
|
||||
self.extract_version, self.reserved, flag_bits,
|
||||
self.compress_type, dostime, dosdate, CRC,
|
||||
compress_size, file_size,
|
||||
len(filename), len(extra))
|
||||
self.extract_version, self.reserved, flag_bits,
|
||||
self.compress_type, dostime, dosdate, CRC,
|
||||
compress_size, file_size,
|
||||
len(filename), len(extra))
|
||||
return header + filename + extra
|
||||
|
||||
def _encodeFilenameFlags(self):
|
||||
@ -385,7 +392,7 @@ class ZipInfo (object):
|
||||
elif ln == 0:
|
||||
counts = ()
|
||||
else:
|
||||
raise RuntimeError("Corrupt extra field %s"%(ln,))
|
||||
raise RuntimeError("Corrupt extra field %s" % (ln,))
|
||||
|
||||
idx = 0
|
||||
|
||||
@ -401,9 +408,9 @@ class ZipInfo (object):
|
||||
if self.header_offset == 0xffffffff:
|
||||
old = self.header_offset
|
||||
self.header_offset = counts[idx]
|
||||
idx+=1
|
||||
idx += 1
|
||||
|
||||
extra = extra[ln+4:]
|
||||
extra = extra[ln + 4:]
|
||||
|
||||
|
||||
class _ZipDecrypter(object):
|
||||
@ -437,6 +444,7 @@ class _ZipDecrypter(object):
|
||||
crc = ((crc >> 1) & 0x7FFFFFFF)
|
||||
table[i] = crc
|
||||
return table
|
||||
|
||||
crctable = _GenerateCRCTable()
|
||||
|
||||
def _crc32(self, ch, crc):
|
||||
@ -460,11 +468,12 @@ class _ZipDecrypter(object):
|
||||
"""Decrypt a single character."""
|
||||
c = ord(c)
|
||||
k = self.key2 | 2
|
||||
c = c ^ (((k * (k^1)) >> 8) & 255)
|
||||
c = c ^ (((k * (k ^ 1)) >> 8) & 255)
|
||||
c = chr(c)
|
||||
self._UpdateKeys(c)
|
||||
return c
|
||||
|
||||
|
||||
class ZipExtFile(io.BufferedIOBase):
|
||||
"""File-like object for reading an archive member.
|
||||
Is returned by ZipFile.open().
|
||||
@ -624,7 +633,7 @@ class ZipExtFile(io.BufferedIOBase):
|
||||
data = ''.join(map(self._decrypter, data))
|
||||
|
||||
if self._compress_type == ZIP_STORED:
|
||||
self._update_crc(data, eof=(self._compress_left==0))
|
||||
self._update_crc(data, eof=(self._compress_left == 0))
|
||||
self._readbuffer = self._readbuffer[self._offset:] + data
|
||||
self._offset = 0
|
||||
else:
|
||||
@ -633,7 +642,7 @@ class ZipExtFile(io.BufferedIOBase):
|
||||
|
||||
# Handle unconsumed data.
|
||||
if (len(self._unconsumed) > 0 and n > len_readbuffer and
|
||||
self._compress_type == ZIP_DEFLATED):
|
||||
self._compress_type == ZIP_DEFLATED):
|
||||
data = self._decompressor.decompress(
|
||||
self._unconsumed,
|
||||
max(n - len_readbuffer, self.MIN_READ_SIZE)
|
||||
@ -654,7 +663,6 @@ class ZipExtFile(io.BufferedIOBase):
|
||||
return data
|
||||
|
||||
|
||||
|
||||
class ZipFile(object):
|
||||
""" Class with methods to open, read, write, close, list zip files.
|
||||
|
||||
@ -670,7 +678,7 @@ class ZipFile(object):
|
||||
|
||||
"""
|
||||
|
||||
fp = None # Set here since __del__ checks it
|
||||
fp = None # Set here since __del__ checks it
|
||||
|
||||
def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=False):
|
||||
"""Open the ZIP file with mode read "r", write "w" or append "a"."""
|
||||
@ -688,8 +696,8 @@ class ZipFile(object):
|
||||
self._allowZip64 = allowZip64
|
||||
self._didModify = False
|
||||
self.debug = 0 # Level of printing: 0 through 3
|
||||
self.NameToInfo = {} # Find file info given name
|
||||
self.filelist = [] # List of ZipInfo instances for archive
|
||||
self.NameToInfo = {} # Find file info given name
|
||||
self.filelist = [] # List of ZipInfo instances for archive
|
||||
self.compression = compression # Method of compression
|
||||
self.mode = key = mode.replace('b', '')[0]
|
||||
self.pwd = None
|
||||
@ -699,7 +707,7 @@ class ZipFile(object):
|
||||
if isinstance(file, basestring):
|
||||
self._filePassed = 0
|
||||
self.filename = file
|
||||
modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'}
|
||||
modeDict = {'r': 'rb', 'w': 'wb', 'a': 'r+b'}
|
||||
try:
|
||||
self.fp = open(file, modeDict[mode])
|
||||
except IOError:
|
||||
@ -766,9 +774,9 @@ class ZipFile(object):
|
||||
raise BadZipfile("File is not a zip file")
|
||||
if self.debug > 1:
|
||||
print(endrec)
|
||||
size_cd = endrec[_ECD_SIZE] # bytes in central directory
|
||||
offset_cd = endrec[_ECD_OFFSET] # offset of central directory
|
||||
self.comment = endrec[_ECD_COMMENT] # archive comment
|
||||
size_cd = endrec[_ECD_SIZE] # bytes in central directory
|
||||
offset_cd = endrec[_ECD_OFFSET] # offset of central directory
|
||||
self.comment = endrec[_ECD_COMMENT] # archive comment
|
||||
|
||||
# "concat" is zero, unless zip was concatenated to another file
|
||||
concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
|
||||
@ -799,13 +807,13 @@ class ZipFile(object):
|
||||
x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
|
||||
x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
|
||||
(x.create_version, x.create_system, x.extract_version, x.reserved,
|
||||
x.flag_bits, x.compress_type, t, d,
|
||||
x.CRC, x.compress_size, x.file_size) = centdir[1:12]
|
||||
x.flag_bits, x.compress_type, t, d,
|
||||
x.CRC, x.compress_size, x.file_size) = centdir[1:12]
|
||||
x.volume, x.internal_attr, x.external_attr = centdir[15:18]
|
||||
# Convert date/time code to (year, month, day, hour, min, sec)
|
||||
x._raw_time = t
|
||||
x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F,
|
||||
t>>11, (t>>5)&0x3F, (t&0x1F) * 2 )
|
||||
x.date_time = ((d >> 9) + 1980, (d >> 5) & 0xF, d & 0x1F,
|
||||
t >> 11, (t >> 5) & 0x3F, (t & 0x1F) * 2)
|
||||
|
||||
x._decodeExtra()
|
||||
x.header_offset = x.header_offset + concat
|
||||
@ -821,7 +829,6 @@ class ZipFile(object):
|
||||
if self.debug > 2:
|
||||
print("total", total)
|
||||
|
||||
|
||||
def namelist(self):
|
||||
"""Return a list of file names in the archive."""
|
||||
l = []
|
||||
@ -849,7 +856,7 @@ class ZipFile(object):
|
||||
# Read by chunks, to avoid an OverflowError or a
|
||||
# MemoryError with very large embedded files.
|
||||
f = self.open(zinfo.filename, "r")
|
||||
while f.read(chunk_size): # Check CRC-32
|
||||
while f.read(chunk_size): # Check CRC-32
|
||||
pass
|
||||
except BadZipfile:
|
||||
return zinfo.filename
|
||||
@ -907,7 +914,7 @@ class ZipFile(object):
|
||||
|
||||
if fname != zinfo.orig_filename:
|
||||
raise BadZipfile('File name in directory "%s" and header "%s" differ.' % (
|
||||
zinfo.orig_filename, fname))
|
||||
zinfo.orig_filename, fname))
|
||||
|
||||
# check for encrypted flag & handle password
|
||||
is_encrypted = zinfo.flag_bits & 0x1
|
||||
@ -917,7 +924,7 @@ class ZipFile(object):
|
||||
pwd = self.pwd
|
||||
if not pwd:
|
||||
raise RuntimeError("File %s is encrypted, " \
|
||||
"password required for extraction" % name)
|
||||
"password required for extraction" % name)
|
||||
|
||||
zd = _ZipDecrypter(pwd)
|
||||
# The first 12 bytes in the cypher stream is an encryption header
|
||||
@ -936,7 +943,7 @@ class ZipFile(object):
|
||||
if ord(h[11]) != check_byte:
|
||||
raise RuntimeError("Bad password for file", name)
|
||||
|
||||
return ZipExtFile(zef_file, mode, zinfo, zd)
|
||||
return ZipExtFile(zef_file, mode, zinfo, zd)
|
||||
|
||||
def extract(self, member, path=None, pwd=None):
|
||||
"""Extract a member from the archive to the current working directory,
|
||||
@ -1004,7 +1011,7 @@ class ZipFile(object):
|
||||
def _writecheck(self, zinfo):
|
||||
"""Check for errors before writing a file to the archive."""
|
||||
if zinfo.filename in self.NameToInfo:
|
||||
if self.debug: # Warning for duplicate names
|
||||
if self.debug: # Warning for duplicate names
|
||||
print("Duplicate name:", zinfo.filename)
|
||||
if self.mode not in ("w", "a"):
|
||||
raise RuntimeError('write() requires mode "w" or "a"')
|
||||
@ -1026,7 +1033,7 @@ class ZipFile(object):
|
||||
arcname."""
|
||||
if not self.fp:
|
||||
raise RuntimeError(
|
||||
"Attempt to write to ZIP archive that was already closed")
|
||||
"Attempt to write to ZIP archive that was already closed")
|
||||
|
||||
st = os.stat(filename)
|
||||
isdir = stat.S_ISDIR(st.st_mode)
|
||||
@ -1041,7 +1048,7 @@ class ZipFile(object):
|
||||
if isdir:
|
||||
arcname += '/'
|
||||
zinfo = ZipInfo(arcname, date_time)
|
||||
zinfo.external_attr = (st[0] & 0xFFFF) << 16 # Unix attributes
|
||||
zinfo.external_attr = (st[0] & 0xFFFF) << 16 # Unix attributes
|
||||
if compress_type is None:
|
||||
zinfo.compress_type = self.compression
|
||||
else:
|
||||
@ -1049,7 +1056,7 @@ class ZipFile(object):
|
||||
|
||||
zinfo.file_size = st.st_size
|
||||
zinfo.flag_bits = 0x00
|
||||
zinfo.header_offset = self.fp.tell() # Start of header bytes
|
||||
zinfo.header_offset = self.fp.tell() # Start of header bytes
|
||||
|
||||
self._writecheck(zinfo)
|
||||
self._didModify = True
|
||||
@ -1071,7 +1078,7 @@ class ZipFile(object):
|
||||
self.fp.write(zinfo.FileHeader())
|
||||
if zinfo.compress_type == ZIP_DEFLATED:
|
||||
cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
|
||||
zlib.DEFLATED, -15)
|
||||
zlib.DEFLATED, -15)
|
||||
else:
|
||||
cmpr = None
|
||||
while 1:
|
||||
@ -1094,10 +1101,10 @@ class ZipFile(object):
|
||||
zinfo.CRC = CRC
|
||||
zinfo.file_size = file_size
|
||||
# Seek backwards and write CRC and file sizes
|
||||
position = self.fp.tell() # Preserve current position in file
|
||||
position = self.fp.tell() # Preserve current position in file
|
||||
self.fp.seek(zinfo.header_offset + 14, 0)
|
||||
self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
|
||||
zinfo.file_size))
|
||||
zinfo.file_size))
|
||||
self.fp.seek(position, 0)
|
||||
self.filelist.append(zinfo)
|
||||
self.NameToInfo[zinfo.filename] = zinfo
|
||||
@ -1117,31 +1124,31 @@ class ZipFile(object):
|
||||
|
||||
if not self.fp:
|
||||
raise RuntimeError(
|
||||
"Attempt to write to ZIP archive that was already closed")
|
||||
"Attempt to write to ZIP archive that was already closed")
|
||||
|
||||
if compress_type is not None:
|
||||
zinfo.compress_type = compress_type
|
||||
|
||||
zinfo.file_size = len(bytes) # Uncompressed size
|
||||
zinfo.header_offset = self.fp.tell() # Start of header bytes
|
||||
zinfo.file_size = len(bytes) # Uncompressed size
|
||||
zinfo.header_offset = self.fp.tell() # Start of header bytes
|
||||
self._writecheck(zinfo)
|
||||
self._didModify = True
|
||||
zinfo.CRC = crc32(bytes) & 0xffffffff # CRC-32 checksum
|
||||
zinfo.CRC = crc32(bytes) & 0xffffffff # CRC-32 checksum
|
||||
if zinfo.compress_type == ZIP_DEFLATED:
|
||||
co = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
|
||||
zlib.DEFLATED, -15)
|
||||
zlib.DEFLATED, -15)
|
||||
bytes = co.compress(bytes) + co.flush()
|
||||
zinfo.compress_size = len(bytes) # Compressed size
|
||||
zinfo.compress_size = len(bytes) # Compressed size
|
||||
else:
|
||||
zinfo.compress_size = zinfo.file_size
|
||||
zinfo.header_offset = self.fp.tell() # Start of header bytes
|
||||
zinfo.header_offset = self.fp.tell() # Start of header bytes
|
||||
self.fp.write(zinfo.FileHeader())
|
||||
self.fp.write(bytes)
|
||||
self.fp.flush()
|
||||
if zinfo.flag_bits & 0x08:
|
||||
# Write CRC and file sizes after the file data
|
||||
self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
|
||||
zinfo.file_size))
|
||||
zinfo.file_size))
|
||||
self.filelist.append(zinfo)
|
||||
self.NameToInfo[zinfo.filename] = zinfo
|
||||
|
||||
@ -1155,10 +1162,10 @@ class ZipFile(object):
|
||||
if self.fp is None:
|
||||
return
|
||||
|
||||
if self.mode in ("w", "a") and self._didModify: # write ending records
|
||||
if self.mode in ("w", "a") and self._didModify: # write ending records
|
||||
count = 0
|
||||
pos1 = self.fp.tell()
|
||||
for zinfo in self.filelist: # write central directory
|
||||
for zinfo in self.filelist: # write central directory
|
||||
count = count + 1
|
||||
dt = zinfo.date_time
|
||||
dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
|
||||
@ -1184,8 +1191,8 @@ class ZipFile(object):
|
||||
if extra:
|
||||
# Append a ZIP64 field to the extra's
|
||||
extra_data = struct.pack(
|
||||
'<HH' + 'Q'*len(extra),
|
||||
1, 8*len(extra), *extra) + extra_data
|
||||
'<HH' + 'Q' * len(extra),
|
||||
1, 8 * len(extra), *extra) + extra_data
|
||||
|
||||
extract_version = max(45, zinfo.extract_version)
|
||||
create_version = max(45, zinfo.create_version)
|
||||
@ -1196,22 +1203,22 @@ class ZipFile(object):
|
||||
try:
|
||||
filename, flag_bits = zinfo._encodeFilenameFlags()
|
||||
centdir = struct.pack(structCentralDir,
|
||||
stringCentralDir, create_version,
|
||||
zinfo.create_system, extract_version, zinfo.reserved,
|
||||
flag_bits, zinfo.compress_type, dostime, dosdate,
|
||||
zinfo.CRC, compress_size, file_size,
|
||||
len(filename), len(extra_data), len(zinfo.comment),
|
||||
0, zinfo.internal_attr, zinfo.external_attr,
|
||||
header_offset)
|
||||
stringCentralDir, create_version,
|
||||
zinfo.create_system, extract_version, zinfo.reserved,
|
||||
flag_bits, zinfo.compress_type, dostime, dosdate,
|
||||
zinfo.CRC, compress_size, file_size,
|
||||
len(filename), len(extra_data), len(zinfo.comment),
|
||||
0, zinfo.internal_attr, zinfo.external_attr,
|
||||
header_offset)
|
||||
except DeprecationWarning:
|
||||
print((structCentralDir,
|
||||
stringCentralDir, create_version,
|
||||
zinfo.create_system, extract_version, zinfo.reserved,
|
||||
zinfo.flag_bits, zinfo.compress_type, dostime, dosdate,
|
||||
zinfo.CRC, compress_size, file_size,
|
||||
len(zinfo.filename), len(extra_data), len(zinfo.comment),
|
||||
0, zinfo.internal_attr, zinfo.external_attr,
|
||||
header_offset), file=sys.stderr)
|
||||
stringCentralDir, create_version,
|
||||
zinfo.create_system, extract_version, zinfo.reserved,
|
||||
zinfo.flag_bits, zinfo.compress_type, dostime, dosdate,
|
||||
zinfo.CRC, compress_size, file_size,
|
||||
len(zinfo.filename), len(extra_data), len(zinfo.comment),
|
||||
0, zinfo.internal_attr, zinfo.external_attr,
|
||||
header_offset), file=sys.stderr)
|
||||
raise
|
||||
self.fp.write(centdir)
|
||||
self.fp.write(filename)
|
||||
@ -1224,18 +1231,18 @@ class ZipFile(object):
|
||||
centDirSize = pos2 - pos1
|
||||
centDirOffset = pos1
|
||||
if (centDirCount >= ZIP_FILECOUNT_LIMIT or
|
||||
centDirOffset > ZIP64_LIMIT or
|
||||
centDirSize > ZIP64_LIMIT):
|
||||
centDirOffset > ZIP64_LIMIT or
|
||||
centDirSize > ZIP64_LIMIT):
|
||||
# Need to write the ZIP64 end-of-archive records
|
||||
zip64endrec = struct.pack(
|
||||
structEndArchive64, stringEndArchive64,
|
||||
44, 45, 45, 0, 0, centDirCount, centDirCount,
|
||||
centDirSize, centDirOffset)
|
||||
structEndArchive64, stringEndArchive64,
|
||||
44, 45, 45, 0, 0, centDirCount, centDirCount,
|
||||
centDirSize, centDirOffset)
|
||||
self.fp.write(zip64endrec)
|
||||
|
||||
zip64locrec = struct.pack(
|
||||
structEndArchive64Locator,
|
||||
stringEndArchive64Locator, 0, pos2, 1)
|
||||
structEndArchive64Locator,
|
||||
stringEndArchive64Locator, 0, pos2, 1)
|
||||
self.fp.write(zip64locrec)
|
||||
centDirCount = min(centDirCount, 0xFFFF)
|
||||
centDirSize = min(centDirSize, 0xFFFFFFFF)
|
||||
@ -1263,7 +1270,7 @@ class ZipFile(object):
|
||||
class PyZipFile(ZipFile):
|
||||
"""Class to create ZIP archives with Python library files and packages."""
|
||||
|
||||
def writepy(self, pathname, basename = ""):
|
||||
def writepy(self, pathname, basename=""):
|
||||
"""Add all files from "pathname" to the ZIP archive.
|
||||
|
||||
If pathname is a package directory, search the directory and
|
||||
@ -1302,7 +1309,7 @@ class PyZipFile(ZipFile):
|
||||
self.writepy(path, basename) # Recursive call
|
||||
elif ext == ".py":
|
||||
fname, arcname = self._get_codename(path[0:-3],
|
||||
basename)
|
||||
basename)
|
||||
if self.debug:
|
||||
print("Adding", arcname)
|
||||
self.write(fname, arcname)
|
||||
@ -1315,7 +1322,7 @@ class PyZipFile(ZipFile):
|
||||
root, ext = os.path.splitext(filename)
|
||||
if ext == ".py":
|
||||
fname, arcname = self._get_codename(path[0:-3],
|
||||
basename)
|
||||
basename)
|
||||
if self.debug:
|
||||
print("Adding", arcname)
|
||||
self.write(fname, arcname)
|
||||
@ -1334,14 +1341,14 @@ class PyZipFile(ZipFile):
|
||||
archive name, compiling if necessary. For example, given
|
||||
/python/lib/string, return (/python/lib/string.pyc, string).
|
||||
"""
|
||||
file_py = pathname + ".py"
|
||||
file_py = pathname + ".py"
|
||||
file_pyc = pathname + ".pyc"
|
||||
file_pyo = pathname + ".pyo"
|
||||
if os.path.isfile(file_pyo) and \
|
||||
os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime:
|
||||
fname = file_pyo # Use .pyo file
|
||||
os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime:
|
||||
fname = file_pyo # Use .pyo file
|
||||
elif not os.path.isfile(file_pyc) or \
|
||||
os.stat(file_pyc).st_mtime < os.stat(file_py).st_mtime:
|
||||
os.stat(file_pyc).st_mtime < os.stat(file_py).st_mtime:
|
||||
import py_compile
|
||||
if self.debug:
|
||||
print("Compiling", file_py)
|
||||
@ -1358,9 +1365,9 @@ class PyZipFile(ZipFile):
|
||||
return (fname, archivename)
|
||||
|
||||
|
||||
def main(args = None):
|
||||
def main(args=None):
|
||||
import textwrap
|
||||
USAGE=textwrap.dedent("""\
|
||||
USAGE = textwrap.dedent("""\
|
||||
Usage:
|
||||
zipfile.py -l zipfile.zip # Show listing of a zipfile
|
||||
zipfile.py -t zipfile.zip # Test if a zipfile is valid
|
||||
@ -1423,8 +1430,8 @@ def main(args = None):
|
||||
elif os.path.isdir(path):
|
||||
for nm in os.listdir(path):
|
||||
addToZip(zf,
|
||||
os.path.join(path, nm), os.path.join(zippath, nm))
|
||||
# else: ignore
|
||||
os.path.join(path, nm), os.path.join(zippath, nm))
|
||||
# else: ignore
|
||||
|
||||
zf = ZipFile(args[1], 'w', allowZip64=True)
|
||||
for src in args[2:]:
|
||||
@ -1432,5 +1439,6 @@ def main(args = None):
|
||||
|
||||
zf.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -10,12 +10,15 @@ from androguard.core.analysis.analysis import *
|
||||
from androguard.decompiler.decompiler import *
|
||||
from androguard import misc
|
||||
|
||||
|
||||
def Save(session, filename):
|
||||
misc.save_session(session, filename)
|
||||
|
||||
|
||||
def Load(filename):
|
||||
return misc.load_session(filename)
|
||||
|
||||
|
||||
class Session(object):
|
||||
def __init__(self, export_ipython=False):
|
||||
self.setupObjects()
|
||||
|
@ -10,7 +10,6 @@ from androguard.gui.mainwindow import MainWindow
|
||||
|
||||
from PyQt5 import QtWidgets, QtGui
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Androguard GUI")
|
||||
parser.add_argument("-d", "--debug", action="store_true", default=False)
|
||||
|
@ -1,6 +1,7 @@
|
||||
import unittest
|
||||
|
||||
import sys
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL)
|
||||
|
||||
@ -9,7 +10,6 @@ from androguard.core.analysis import analysis
|
||||
|
||||
|
||||
class AnalysisTest(unittest.TestCase):
|
||||
|
||||
def testDex(self):
|
||||
with open("examples/android/TestsAndroguard/bin/classes.dex",
|
||||
"rb") as fd:
|
||||
|
@ -1,6 +1,7 @@
|
||||
import unittest
|
||||
|
||||
import sys
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL)
|
||||
|
||||
@ -8,7 +9,6 @@ from androguard.core.bytecodes import apk
|
||||
|
||||
|
||||
class APKTest(unittest.TestCase):
|
||||
|
||||
def testAPK(self):
|
||||
with open("examples/android/TestsAndroguard/bin/TestActivity.apk",
|
||||
"rb") as fd:
|
||||
|
@ -1,13 +1,13 @@
|
||||
import unittest
|
||||
|
||||
import sys
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL)
|
||||
|
||||
from androguard.core.bytecodes import apk
|
||||
import collections
|
||||
|
||||
|
||||
TEST_APP_NAME = "TestsAndroguardApplication"
|
||||
TEST_ICONS = {
|
||||
120: "res/drawable-ldpi/icon.png",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import unittest
|
||||
|
||||
import sys
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL)
|
||||
|
||||
@ -8,7 +9,6 @@ from androguard.core.bytecodes import apk
|
||||
|
||||
|
||||
class AXMLTest(unittest.TestCase):
|
||||
|
||||
def testAXML(self):
|
||||
filenames = [
|
||||
"examples/axml/AndroidManifest-Chinese.xml",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import unittest
|
||||
|
||||
import sys
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL)
|
||||
|
||||
@ -8,7 +9,6 @@ from androguard.core.bytecodes import dvm
|
||||
|
||||
|
||||
class DexTest(unittest.TestCase):
|
||||
|
||||
def testDex(self):
|
||||
with open("examples/android/TestsAndroguard/bin/classes.dex",
|
||||
"rb") as fd:
|
||||
@ -32,7 +32,6 @@ class DexTest(unittest.TestCase):
|
||||
|
||||
|
||||
class InstructionTest(unittest.TestCase):
|
||||
|
||||
def testNOP(self):
|
||||
instruction = dvm.Instruction10x(None, bytearray(b"\x00\x00"))
|
||||
self.assertEqual(instruction.get_name(), "nop")
|
||||
|
@ -1,6 +1,7 @@
|
||||
import unittest
|
||||
|
||||
import sys
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL)
|
||||
|
||||
@ -8,7 +9,6 @@ from androguard import session
|
||||
|
||||
|
||||
class SessionTest(unittest.TestCase):
|
||||
|
||||
def testSessionDex(self):
|
||||
s = session.Session()
|
||||
with open("examples/android/TestsAndroguard/bin/classes.dex",
|
||||
|
Loading…
Reference in New Issue
Block a user