mirror of
https://github.com/cemu-project/idapython.git
synced 2024-11-26 20:00:24 +00:00
- Experimental: integrated Hex-Rays Decompiler bindings that were contributed by EiNSTeiN:
https://github.com/EiNSTeiN-/hexrays-python - Added '--with-hexrays' switch to the build script so it wrap Hex-Rays Decompiler API - Added one Hex-Rays decompiler sample: vds1.py
This commit is contained in:
parent
ce06fdd7d2
commit
db58b31711
@ -42,6 +42,9 @@ Make sure all the needed tools (compiler, swig) are on the PATH.
|
||||
swigsdk-versions/x.y/ - A supported version of the IDA SDK
|
||||
idapython/ - IDAPython source code
|
||||
|
||||
Note: To build with Hex-Rays decompiler support, please copy hexrays.hpp from
|
||||
the decompiler SDK folder into IDA's include folder (in the SDK).
|
||||
|
||||
2. On Mac OS X copy libida.dylib from the IDA install directory to
|
||||
swigsdk-versions/x.y/lib/x86_mac_gcc_32/
|
||||
and libida64.dylib to
|
||||
|
@ -1,5 +1,14 @@
|
||||
Please see http://code.google.com/p/idapython/source/list for a detailed list of changes.
|
||||
|
||||
Changes from version 1.5.6 to 1.5.7
|
||||
------------------------------------
|
||||
- Added '--with-hexrays' switch to the build script so it wrap Hex-Rays Decompiler API
|
||||
- Experimental: integrated Hex-Rays Decompiler bindings that were contributed by EiNSTeiN:
|
||||
https://github.com/EiNSTeiN-/hexrays-python
|
||||
- Added one Hex-Rays decompiler sample: vds1.py
|
||||
- Fixed small mismatch between SWIG define and CL defines (/DNO_OBSOLETE_FUNCS)
|
||||
- Use print_type2() instead of the deprecated function print_type()
|
||||
|
||||
Changes from version 1.5.5 to 1.5.6
|
||||
------------------------------------
|
||||
- IDA Pro 6.4 support
|
||||
|
79
build.py
79
build.py
@ -45,6 +45,10 @@ PYTHON_MINOR_VERSION = int(platform.python_version()[2])
|
||||
# Find Python headers
|
||||
PYTHON_INCLUDE_DIRECTORY = sysconfig.get_config_var('INCLUDEPY')
|
||||
|
||||
S_EA64 = 'ea64'
|
||||
S_WITH_HEXRAYS = 'with-hexrays'
|
||||
S_NO_OPT = 'no-opt'
|
||||
|
||||
# Swig command-line parameters
|
||||
SWIG_OPTIONS = '-modern -python -c++ -w451 -shadow -D__GNUC__ -DNO_OBSOLETE_FUNCS'
|
||||
|
||||
@ -61,6 +65,7 @@ COMMON_MACROS = [
|
||||
# Common includes for all compilations
|
||||
COMMON_INCLUDES = [ ".", "swig" ]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# List files for the binary distribution
|
||||
BINDIST_MANIFEST = [
|
||||
"README.txt",
|
||||
@ -104,6 +109,7 @@ BINDIST_MANIFEST = [
|
||||
"examples/ex_imports.py"
|
||||
]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# List files for the source distribution (appended to binary list)
|
||||
SRCDIST_MANIFEST = [
|
||||
"BUILDING.txt",
|
||||
@ -150,14 +156,31 @@ SRCDIST_MANIFEST = [
|
||||
"swig/xref.i",
|
||||
"swig/graph.i",
|
||||
"swig/fpro.i",
|
||||
"swig/hexrays.i",
|
||||
"tools/gendocs.py",
|
||||
]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def parse_options(args):
|
||||
"""Parse arguments and returned a dictionary of options"""
|
||||
|
||||
no_opt = '--' + S_NO_OPT in sys.argv
|
||||
ea64 = '--' + S_EA64 in sys.argv
|
||||
with_hexrays = '--' + S_WITH_HEXRAYS in sys.argv
|
||||
|
||||
return {
|
||||
S_EA64: ea64,
|
||||
S_WITH_HEXRAYS: with_hexrays,
|
||||
S_NO_OPT: no_opt
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class BuilderBase:
|
||||
""" Base class for builders """
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def compile(self, source, objectname=None, includes=[], macros=[]):
|
||||
"""
|
||||
Compile the source file
|
||||
@ -187,6 +210,7 @@ class BuilderBase:
|
||||
print cmdstring
|
||||
return os.system(cmdstring)
|
||||
|
||||
|
||||
def link(self, objects, outfile, libpaths=[], libraries=[], extra_parameters=None):
|
||||
""" Link the binary from objects and libraries """
|
||||
cmdstring = "%s %s %s" % (self.linker,
|
||||
@ -217,6 +241,7 @@ class BuilderBase:
|
||||
return macrostring
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class GCCBuilder(BuilderBase):
|
||||
""" Generic GCC compiler class """
|
||||
def __init__(self):
|
||||
@ -241,6 +266,7 @@ class GCCBuilder(BuilderBase):
|
||||
return "-o %s" % filename
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class MSVCBuilder(BuilderBase):
|
||||
""" Generic Visual C compiler class """
|
||||
def __init__(self):
|
||||
@ -266,7 +292,7 @@ class MSVCBuilder(BuilderBase):
|
||||
def linker_out_string(self, filename):
|
||||
return "/out:%s" % filename
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def build_distribution(manifest, distrootdir, ea64, nukeold):
|
||||
""" Create a distibution to a directory and a ZIP file """
|
||||
# (Re)create the output directory
|
||||
@ -307,7 +333,17 @@ def build_distribution(manifest, distrootdir, ea64, nukeold):
|
||||
zip.close()
|
||||
|
||||
|
||||
def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
||||
# -----------------------------------------------------------------------
|
||||
def build_plugin(
|
||||
platform,
|
||||
idasdkdir,
|
||||
plugin_name,
|
||||
options):
|
||||
|
||||
# Get the arguments
|
||||
ea64 = options[S_EA64]
|
||||
with_hexrays = options[S_WITH_HEXRAYS]
|
||||
|
||||
global SWIG_OPTIONS
|
||||
""" Build the plugin from the SWIG wrapper and plugin main source """
|
||||
# Path to the IDA SDK headers
|
||||
@ -334,7 +370,8 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
||||
ida_lib = "ida.lib"
|
||||
SWIG_OPTIONS += " -D__NT__ "
|
||||
extra_link_parameters = ""
|
||||
builder.compiler_parameters += " -Ox"
|
||||
if not options[S_NO_OPT]:
|
||||
builder.compiler_parameters += " -Ox"
|
||||
# Platform-specific settings for the Mac OS X build
|
||||
elif platform == "macosx":
|
||||
builder = GCCBuilder()
|
||||
@ -353,6 +390,11 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
||||
if ea64:
|
||||
platform_macros.append("__EA64__")
|
||||
|
||||
# Build with Hex-Rays decompiler
|
||||
if with_hexrays:
|
||||
platform_macros.append("WITH_HEXRAYS")
|
||||
SWIG_OPTIONS += ' -DWITH_HEXRAYS '
|
||||
|
||||
platform_macros.append("NDEBUG")
|
||||
|
||||
if not '--no-early-load' in sys.argv:
|
||||
@ -388,6 +430,7 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
||||
extra_link_parameters)
|
||||
assert res == 0, "Failed to link the plugin binary"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def detect_platform(ea64):
|
||||
# Detect the platform
|
||||
system = platform.system()
|
||||
@ -410,7 +453,9 @@ def detect_platform(ea64):
|
||||
|
||||
return (system, platform_string, plugin_name)
|
||||
|
||||
def build_binary_package(ea64, nukeold):
|
||||
# -----------------------------------------------------------------------
|
||||
def build_binary_package(options, nukeold):
|
||||
ea64 = options[S_EA64]
|
||||
system, platform_string, plugin_name = detect_platform(ea64)
|
||||
BINDISTDIR = "idapython-%d.%d.%d_ida%d.%d_py%d.%d_%s" % (VERSION_MAJOR,
|
||||
VERSION_MINOR,
|
||||
@ -421,7 +466,7 @@ def build_binary_package(ea64, nukeold):
|
||||
PYTHON_MINOR_VERSION,
|
||||
platform_string)
|
||||
# Build the plugin
|
||||
build_plugin(platform_string, IDA_SDK, plugin_name, ea64)
|
||||
build_plugin(platform_string, IDA_SDK, plugin_name, options)
|
||||
|
||||
# Build the binary distribution
|
||||
binmanifest = []
|
||||
@ -436,6 +481,7 @@ def build_binary_package(ea64, nukeold):
|
||||
build_distribution(binmanifest, BINDISTDIR, ea64, nukeold)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def build_source_package():
|
||||
""" Build a directory and a ZIP file with all the sources """
|
||||
SRCDISTDIR = "idapython-%d.%d.%d" % (VERSION_MAJOR,
|
||||
@ -448,6 +494,7 @@ def build_source_package():
|
||||
srcmanifest.extend([(x, "python") for x in "python/init.py", "python/idc.py", "python/idautils.py"])
|
||||
build_distribution(srcmanifest, SRCDISTDIR, ea64=False, nukeold=True)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def gen_docs(z = False):
|
||||
print "Generating documentation....."
|
||||
old_dir = os.getcwd()
|
||||
@ -494,6 +541,7 @@ def gen_docs(z = False):
|
||||
os.chdir(old_dir)
|
||||
return
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def usage():
|
||||
print """IDAPython build script.
|
||||
|
||||
@ -504,23 +552,36 @@ Available switches:
|
||||
Used with '--doc' switch. It will compress the generated documentation
|
||||
--ea64:
|
||||
Builds also the 64bit version of the plugin
|
||||
--with-hexrays:
|
||||
Build with the Hex-Rays Decompiler wrappings
|
||||
--no-early-load:
|
||||
The plugin will be compiled as normal plugin
|
||||
This switch disables processor, plugin and loader scripts
|
||||
"""
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def main():
|
||||
if '--help' in sys.argv:
|
||||
return usage()
|
||||
elif '--doc' in sys.argv:
|
||||
return gen_docs(z = '--zip' in sys.argv)
|
||||
|
||||
# Do 64-bit build?
|
||||
ea64 = '--ea64' in sys.argv
|
||||
build_binary_package(ea64=False, nukeold=True)
|
||||
# Parse options
|
||||
options = parse_options(sys.argv)
|
||||
ea64 = options[S_EA64]
|
||||
|
||||
# Always build the non __EA64__ version
|
||||
options[S_EA64] = False
|
||||
build_binary_package(options, nukeold=True)
|
||||
|
||||
# Rebuild package with __EA64__ if needed
|
||||
if ea64:
|
||||
build_binary_package(ea64=True, nukeold=False)
|
||||
options[S_EA64] = True
|
||||
build_binary_package(options, nukeold=False)
|
||||
|
||||
# Always build the source package
|
||||
build_source_package()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
27
examples/vds1.py
Normal file
27
examples/vds1.py
Normal file
@ -0,0 +1,27 @@
|
||||
import idaapi
|
||||
|
||||
def main():
|
||||
if not idaapi.init_hexrays_plugin():
|
||||
return False
|
||||
|
||||
print "Hex-rays version %s has been detected" % idaapi.get_hexrays_version()
|
||||
|
||||
f = idaapi.get_func(idaapi.get_screen_ea());
|
||||
if f is None:
|
||||
print "Please position the cursor within a function"
|
||||
return True
|
||||
|
||||
cfunc = idaapi.decompile(f);
|
||||
if cfunc is None:
|
||||
print "Failed to decompile!"
|
||||
return True
|
||||
|
||||
sv = cfunc.get_pseudocode();
|
||||
for i in xrange(0, sv.size()):
|
||||
line = idaapi.tag_remove(str(sv[i]));
|
||||
print line
|
||||
|
||||
return True
|
||||
|
||||
if main():
|
||||
idaapi.term_hexrays_plugin();
|
@ -97,7 +97,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>.\pywraps;..\..\include;\python27\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NO_OBSOLETE_FUNCS;_DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;USE_STANDARD_FILE_FUNCTIONS;VER_MAJOR=1;VER_MINOR=5;VER_PATCH=3;PLUGINFIX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WITH_HEXRAYS;NO_OBSOLETE_FUNCS;_DEBUG;__NT__;__IDP__;MAXSTR=1024;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;USE_STANDARD_FILE_FUNCTIONS;VER_MAJOR=1;VER_MINOR=5;VER_PATCH=3;PLUGINFIX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
@ -302,6 +302,7 @@
|
||||
</Bscmake>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<None Include="build.py" />
|
||||
<None Include="BUILDING.txt" />
|
||||
<None Include="CHANGES.txt" />
|
||||
<None Include="obj\x86_win_vc_32\idaapi.py" />
|
||||
@ -346,6 +347,7 @@
|
||||
<None Include="swig\funcs.i" />
|
||||
<None Include="swig\gdl.i" />
|
||||
<None Include="swig\graph.i" />
|
||||
<None Include="swig\hexrays.i" />
|
||||
<None Include="swig\ida.i" />
|
||||
<None Include="swig\idaapi.i" />
|
||||
<None Include="swig\idd.i" />
|
||||
|
@ -293,6 +293,12 @@
|
||||
<None Include="README.txt">
|
||||
<Filter>TEXT</Filter>
|
||||
</None>
|
||||
<None Include="swig\hexrays.i">
|
||||
<Filter>swig_i</Filter>
|
||||
</None>
|
||||
<None Include="build.py">
|
||||
<Filter>py</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="swig_i">
|
||||
|
3201
python.cpp
3201
python.cpp
File diff suppressed because it is too large
Load Diff
@ -709,6 +709,7 @@ def RunPythonStatement(stmt):
|
||||
#</pydoc>
|
||||
*/
|
||||
|
||||
/*
|
||||
//---------------------------------------------------------------------------
|
||||
// qstrvec_t wrapper
|
||||
//---------------------------------------------------------------------------
|
||||
@ -812,7 +813,7 @@ static bool qstrvec_t_remove(PyObject *self, size_t idx)
|
||||
sv->erase(sv->begin()+idx);
|
||||
return true;
|
||||
}
|
||||
|
||||
*/
|
||||
//---------------------------------------------------------------------------
|
||||
//</inline(py_idaapi)>
|
||||
|
||||
|
@ -207,72 +207,72 @@ class PyIdc_cvt_int64__(pyidc_cvt_helper__):
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# qstrvec_t clinked object
|
||||
class qstrvec_t(py_clinked_object_t):
|
||||
"""Class representing an qstrvec_t"""
|
||||
# class qstrvec_t(py_clinked_object_t):
|
||||
# """Class representing an qstrvec_t"""
|
||||
|
||||
def __init__(self, items=None):
|
||||
py_clinked_object_t.__init__(self)
|
||||
# Populate the list if needed
|
||||
if items:
|
||||
self.from_list(items)
|
||||
# def __init__(self, items=None):
|
||||
# py_clinked_object_t.__init__(self)
|
||||
# # Populate the list if needed
|
||||
# if items:
|
||||
# self.from_list(items)
|
||||
|
||||
def _create_clink(self):
|
||||
return _idaapi.qstrvec_t_create()
|
||||
# def _create_clink(self):
|
||||
# return _idaapi.qstrvec_t_create()
|
||||
|
||||
def _del_clink(self, lnk):
|
||||
return _idaapi.qstrvec_t_destroy(lnk)
|
||||
# def _del_clink(self, lnk):
|
||||
# return _idaapi.qstrvec_t_destroy(lnk)
|
||||
|
||||
def _get_clink_ptr(self):
|
||||
return _idaapi.qstrvec_t_get_clink_ptr(self)
|
||||
# def _get_clink_ptr(self):
|
||||
# return _idaapi.qstrvec_t_get_clink_ptr(self)
|
||||
|
||||
def assign(self, other):
|
||||
"""Copies the contents of 'other' to 'self'"""
|
||||
return _idaapi.qstrvec_t_assign(self, other)
|
||||
# def assign(self, other):
|
||||
# """Copies the contents of 'other' to 'self'"""
|
||||
# return _idaapi.qstrvec_t_assign(self, other)
|
||||
|
||||
def __setitem__(self, idx, s):
|
||||
"""Sets string at the given index"""
|
||||
return _idaapi.qstrvec_t_set(self, idx, s)
|
||||
# def __setitem__(self, idx, s):
|
||||
# """Sets string at the given index"""
|
||||
# return _idaapi.qstrvec_t_set(self, idx, s)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
"""Gets the string at the given index"""
|
||||
return _idaapi.qstrvec_t_get(self, idx)
|
||||
# def __getitem__(self, idx):
|
||||
# """Gets the string at the given index"""
|
||||
# return _idaapi.qstrvec_t_get(self, idx)
|
||||
|
||||
def __get_size(self):
|
||||
return _idaapi.qstrvec_t_size(self)
|
||||
# def __get_size(self):
|
||||
# return _idaapi.qstrvec_t_size(self)
|
||||
|
||||
size = property(__get_size)
|
||||
"""Returns the count of elements"""
|
||||
# size = property(__get_size)
|
||||
# """Returns the count of elements"""
|
||||
|
||||
def addressof(self, idx):
|
||||
"""Returns the address (as number) of the qstring at the given index"""
|
||||
return _idaapi.qstrvec_t_addressof(self, idx)
|
||||
# def addressof(self, idx):
|
||||
# """Returns the address (as number) of the qstring at the given index"""
|
||||
# return _idaapi.qstrvec_t_addressof(self, idx)
|
||||
|
||||
def add(self, s):
|
||||
"""Add a string to the vector"""
|
||||
return _idaapi.qstrvec_t_add(self, s)
|
||||
# def add(self, s):
|
||||
# """Add a string to the vector"""
|
||||
# return _idaapi.qstrvec_t_add(self, s)
|
||||
|
||||
|
||||
def from_list(self, lst):
|
||||
"""Populates the vector from a Python string list"""
|
||||
return _idaapi.qstrvec_t_from_list(self, lst)
|
||||
# def from_list(self, lst):
|
||||
# """Populates the vector from a Python string list"""
|
||||
# return _idaapi.qstrvec_t_from_list(self, lst)
|
||||
|
||||
|
||||
def clear(self, qclear=False):
|
||||
"""
|
||||
Clears all strings from the vector.
|
||||
@param qclear: Just reset the size but do not actually free the memory
|
||||
"""
|
||||
return _idaapi.qstrvec_t_clear(self, qclear)
|
||||
# def clear(self, qclear=False):
|
||||
# """
|
||||
# Clears all strings from the vector.
|
||||
# @param qclear: Just reset the size but do not actually free the memory
|
||||
# """
|
||||
# return _idaapi.qstrvec_t_clear(self, qclear)
|
||||
|
||||
|
||||
def insert(self, idx, s):
|
||||
"""Insert a string into the vector"""
|
||||
return _idaapi.qstrvec_t_insert(self, idx, s)
|
||||
# def insert(self, idx, s):
|
||||
# """Insert a string into the vector"""
|
||||
# return _idaapi.qstrvec_t_insert(self, idx, s)
|
||||
|
||||
|
||||
def remove(self, idx):
|
||||
"""Removes a string from the vector"""
|
||||
return _idaapi.qstrvec_t_remove(self, idx)
|
||||
# def remove(self, idx):
|
||||
# """Removes a string from the vector"""
|
||||
# return _idaapi.qstrvec_t_remove(self, idx)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class PyIdc_cvt_refclass__(pyidc_cvt_helper__):
|
||||
|
1111
swig/hexrays.i
Normal file
1111
swig/hexrays.i
Normal file
File diff suppressed because it is too large
Load Diff
103
swig/idaapi.i
103
swig/idaapi.i
@ -100,6 +100,9 @@ static PyObject *type##_get_clink_ptr(PyObject *self)
|
||||
#include "fpro.h"
|
||||
#include <map>
|
||||
#include "graph.hpp"
|
||||
#ifdef WITH_HEXRAYS
|
||||
#include "hexrays.hpp"
|
||||
#endif
|
||||
#include "pywraps.hpp"
|
||||
|
||||
//<code(py_idaapi)>
|
||||
@ -2308,72 +2311,72 @@ class PyIdc_cvt_int64__(pyidc_cvt_helper__):
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# qstrvec_t clinked object
|
||||
class qstrvec_t(py_clinked_object_t):
|
||||
"""Class representing an qstrvec_t"""
|
||||
# class qstrvec_t(py_clinked_object_t):
|
||||
# """Class representing an qstrvec_t"""
|
||||
|
||||
def __init__(self, items=None):
|
||||
py_clinked_object_t.__init__(self)
|
||||
# Populate the list if needed
|
||||
if items:
|
||||
self.from_list(items)
|
||||
# def __init__(self, items=None):
|
||||
# py_clinked_object_t.__init__(self)
|
||||
# # Populate the list if needed
|
||||
# if items:
|
||||
# self.from_list(items)
|
||||
|
||||
def _create_clink(self):
|
||||
return _idaapi.qstrvec_t_create()
|
||||
# def _create_clink(self):
|
||||
# return _idaapi.qstrvec_t_create()
|
||||
|
||||
def _del_clink(self, lnk):
|
||||
return _idaapi.qstrvec_t_destroy(lnk)
|
||||
# def _del_clink(self, lnk):
|
||||
# return _idaapi.qstrvec_t_destroy(lnk)
|
||||
|
||||
def _get_clink_ptr(self):
|
||||
return _idaapi.qstrvec_t_get_clink_ptr(self)
|
||||
# def _get_clink_ptr(self):
|
||||
# return _idaapi.qstrvec_t_get_clink_ptr(self)
|
||||
|
||||
def assign(self, other):
|
||||
"""Copies the contents of 'other' to 'self'"""
|
||||
return _idaapi.qstrvec_t_assign(self, other)
|
||||
# def assign(self, other):
|
||||
# """Copies the contents of 'other' to 'self'"""
|
||||
# return _idaapi.qstrvec_t_assign(self, other)
|
||||
|
||||
def __setitem__(self, idx, s):
|
||||
"""Sets string at the given index"""
|
||||
return _idaapi.qstrvec_t_set(self, idx, s)
|
||||
# def __setitem__(self, idx, s):
|
||||
# """Sets string at the given index"""
|
||||
# return _idaapi.qstrvec_t_set(self, idx, s)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
"""Gets the string at the given index"""
|
||||
return _idaapi.qstrvec_t_get(self, idx)
|
||||
# def __getitem__(self, idx):
|
||||
# """Gets the string at the given index"""
|
||||
# return _idaapi.qstrvec_t_get(self, idx)
|
||||
|
||||
def __get_size(self):
|
||||
return _idaapi.qstrvec_t_size(self)
|
||||
# def __get_size(self):
|
||||
# return _idaapi.qstrvec_t_size(self)
|
||||
|
||||
size = property(__get_size)
|
||||
"""Returns the count of elements"""
|
||||
# size = property(__get_size)
|
||||
# """Returns the count of elements"""
|
||||
|
||||
def addressof(self, idx):
|
||||
"""Returns the address (as number) of the qstring at the given index"""
|
||||
return _idaapi.qstrvec_t_addressof(self, idx)
|
||||
# def addressof(self, idx):
|
||||
# """Returns the address (as number) of the qstring at the given index"""
|
||||
# return _idaapi.qstrvec_t_addressof(self, idx)
|
||||
|
||||
def add(self, s):
|
||||
"""Add a string to the vector"""
|
||||
return _idaapi.qstrvec_t_add(self, s)
|
||||
# def add(self, s):
|
||||
# """Add a string to the vector"""
|
||||
# return _idaapi.qstrvec_t_add(self, s)
|
||||
|
||||
|
||||
def from_list(self, lst):
|
||||
"""Populates the vector from a Python string list"""
|
||||
return _idaapi.qstrvec_t_from_list(self, lst)
|
||||
# def from_list(self, lst):
|
||||
# """Populates the vector from a Python string list"""
|
||||
# return _idaapi.qstrvec_t_from_list(self, lst)
|
||||
|
||||
|
||||
def clear(self, qclear=False):
|
||||
"""
|
||||
Clears all strings from the vector.
|
||||
@param qclear: Just reset the size but do not actually free the memory
|
||||
"""
|
||||
return _idaapi.qstrvec_t_clear(self, qclear)
|
||||
# def clear(self, qclear=False):
|
||||
# """
|
||||
# Clears all strings from the vector.
|
||||
# @param qclear: Just reset the size but do not actually free the memory
|
||||
# """
|
||||
# return _idaapi.qstrvec_t_clear(self, qclear)
|
||||
|
||||
|
||||
def insert(self, idx, s):
|
||||
"""Insert a string into the vector"""
|
||||
return _idaapi.qstrvec_t_insert(self, idx, s)
|
||||
# def insert(self, idx, s):
|
||||
# """Insert a string into the vector"""
|
||||
# return _idaapi.qstrvec_t_insert(self, idx, s)
|
||||
|
||||
|
||||
def remove(self, idx):
|
||||
"""Removes a string from the vector"""
|
||||
return _idaapi.qstrvec_t_remove(self, idx)
|
||||
# def remove(self, idx):
|
||||
# """Removes a string from the vector"""
|
||||
# return _idaapi.qstrvec_t_remove(self, idx)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class PyIdc_cvt_refclass__(pyidc_cvt_helper__):
|
||||
@ -2677,6 +2680,9 @@ NW_REMOVE = 0x0010
|
||||
%include "fixup.i"
|
||||
%include "frame.i"
|
||||
%include "funcs.i"
|
||||
#ifdef WITH_HEXRAYS
|
||||
%include "hexrays.i"
|
||||
#endif
|
||||
|
||||
%inline %{
|
||||
|
||||
@ -2780,6 +2786,7 @@ def RunPythonStatement(stmt):
|
||||
#</pydoc>
|
||||
*/
|
||||
|
||||
/*
|
||||
//---------------------------------------------------------------------------
|
||||
// qstrvec_t wrapper
|
||||
//---------------------------------------------------------------------------
|
||||
@ -2883,7 +2890,7 @@ static bool qstrvec_t_remove(PyObject *self, size_t idx)
|
||||
sv->erase(sv->begin()+idx);
|
||||
return true;
|
||||
}
|
||||
|
||||
*/
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
235
swig/pro.i
235
swig/pro.i
@ -1,99 +1,136 @@
|
||||
%ignore wchar2char;
|
||||
%ignore hit_counter_t;
|
||||
%ignore reg_hit_counter;
|
||||
%ignore create_hit_counter;
|
||||
%ignore hit_counter_timer;
|
||||
%ignore print_all_counters;
|
||||
%ignore incrementer_t;
|
||||
%ignore reloc_info_t; // swig under mac chokes on this
|
||||
%ignore qstrvec_t;
|
||||
%ignore qmutex_create;
|
||||
%ignore qiterator;
|
||||
%ignore qrefcnt_t;
|
||||
%ignore qmutex_free;
|
||||
%ignore qmutex_lock;
|
||||
%ignore qmutex_t;
|
||||
%ignore qmutex_unlock;
|
||||
%ignore qsem_create;
|
||||
%ignore qsem_free;
|
||||
%ignore qsem_post;
|
||||
%ignore qsem_wait;
|
||||
%ignore qsemaphore_t;
|
||||
%ignore qthread_cb_t;
|
||||
%ignore qthread_create;
|
||||
%ignore qthread_free;
|
||||
%ignore qthread_join;
|
||||
%ignore qthread_kill;
|
||||
%ignore qthread_self;
|
||||
%ignore qthread_same;
|
||||
%ignore qthread_t;
|
||||
%ignore qhandle_t;
|
||||
%ignore qpipe_create;
|
||||
%ignore qpipe_read;
|
||||
%ignore qpipe_write;
|
||||
%ignore qpipe_close;
|
||||
%ignore qwait_for_handles;
|
||||
%ignore qstrlen;
|
||||
%ignore qstrcmp;
|
||||
%ignore qstrstr;
|
||||
%ignore qstrchr;
|
||||
%ignore qstrrchr;
|
||||
%ignore qstring;
|
||||
%ignore qvector;
|
||||
%ignore bytevec_t;
|
||||
%ignore reloc_info_t;
|
||||
%ignore relobj_t;
|
||||
%ignore wchar2char;
|
||||
%ignore u2cstr;
|
||||
%ignore c2ustr;
|
||||
%ignore base64_encode;
|
||||
%ignore base64_decode;
|
||||
%ignore utf8_unicode;
|
||||
%ignore win_utf2idb;
|
||||
%ignore char2oem;
|
||||
%ignore oem2char;
|
||||
%ignore set_codepages;
|
||||
%ignore get_codepages;
|
||||
%ignore convert_codepage;
|
||||
%ignore test_bit;
|
||||
%ignore set_bit;
|
||||
%ignore clear_bit;
|
||||
%ignore set_all_bits;
|
||||
%ignore clear_all_bits;
|
||||
%ignore interval::overlap;
|
||||
%ignore interval::includes;
|
||||
%ignore interval::contains;
|
||||
%ignore qrotl;
|
||||
%ignore qrotr;
|
||||
%ignore setflag;
|
||||
%ignore read2bytes;
|
||||
%ignore rotate_left;
|
||||
%ignore qswap;
|
||||
%ignore swap32;
|
||||
%ignore swap16;
|
||||
%ignore swap_value;
|
||||
%ignore qalloc_or_throw;
|
||||
%ignore qrealloc_or_throw;
|
||||
%ignore get_buffer_for_sysdir;
|
||||
%ignore get_buffer_for_winerr;
|
||||
%ignore call_atexits;
|
||||
%ignore launch_process_params_t;
|
||||
%ignore launch_process;
|
||||
%ignore term_process;
|
||||
%ignore get_process_exit_code;
|
||||
%ignore BELOW_NORMAL_PRIORITY_CLASS;
|
||||
%ignore parse_command_line;
|
||||
%ignore parse_command_line2;
|
||||
%rename (parse_command_line2) py_parse_command_line;
|
||||
%ignore qgetenv;
|
||||
%ignore qsetenv;
|
||||
%ignore qctime;
|
||||
%ignore qlocaltime;
|
||||
%ignore qstrftime;
|
||||
%ignore qstrftime64;
|
||||
%ignore qstrtok;
|
||||
%ignore qstrlwr;
|
||||
%ignore qstrupr;
|
||||
%include "pro.h"
|
||||
|
||||
SWIG_DECLARE_PY_CLINKED_OBJECT(qstrvec_t)
|
||||
//---------------------------------------------------------------------
|
||||
%typemap(out) uint64 {
|
||||
$result = PyLong_FromUnsignedLongLong((unsigned long long) $1);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
%typemap(in) uint64
|
||||
{
|
||||
uint64 $1_temp;
|
||||
if ( !PyW_GetNumber($input, &$1_temp) )
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Expected an uint64 type");
|
||||
return NULL;
|
||||
}
|
||||
$1 = $1_temp;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
%ignore wchar2char;
|
||||
%ignore hit_counter_t;
|
||||
%ignore reg_hit_counter;
|
||||
%ignore create_hit_counter;
|
||||
%ignore hit_counter_timer;
|
||||
%ignore print_all_counters;
|
||||
%ignore incrementer_t;
|
||||
%ignore reloc_info_t; // swig under mac chokes on this
|
||||
%ignore qmutex_create;
|
||||
%ignore qiterator;
|
||||
%ignore qmutex_free;
|
||||
%ignore qmutex_lock;
|
||||
%ignore qmutex_t;
|
||||
%ignore qmutex_unlock;
|
||||
%ignore qsem_create;
|
||||
%ignore qsem_free;
|
||||
%ignore qsem_post;
|
||||
%ignore qsem_wait;
|
||||
%ignore qsemaphore_t;
|
||||
%ignore qthread_cb_t;
|
||||
%ignore qthread_create;
|
||||
%ignore qthread_free;
|
||||
%ignore qthread_join;
|
||||
%ignore qthread_kill;
|
||||
%ignore qthread_self;
|
||||
%ignore qthread_same;
|
||||
%ignore qthread_t;
|
||||
%ignore qhandle_t;
|
||||
%ignore qpipe_create;
|
||||
%ignore qpipe_read;
|
||||
%ignore qpipe_write;
|
||||
%ignore qpipe_close;
|
||||
%ignore qwait_for_handles;
|
||||
%ignore qstrlen;
|
||||
%ignore qstrcmp;
|
||||
%ignore qstrstr;
|
||||
%ignore qstrchr;
|
||||
%ignore qstrrchr;
|
||||
%ignore bytevec_t;
|
||||
%ignore reloc_info_t;
|
||||
%ignore relobj_t;
|
||||
%ignore wchar2char;
|
||||
%ignore u2cstr;
|
||||
%ignore c2ustr;
|
||||
%ignore base64_encode;
|
||||
%ignore base64_decode;
|
||||
%ignore utf8_unicode;
|
||||
%ignore win_utf2idb;
|
||||
%ignore char2oem;
|
||||
%ignore oem2char;
|
||||
%ignore set_codepages;
|
||||
%ignore get_codepages;
|
||||
%ignore convert_codepage;
|
||||
%ignore test_bit;
|
||||
%ignore set_bit;
|
||||
%ignore clear_bit;
|
||||
%ignore set_all_bits;
|
||||
%ignore clear_all_bits;
|
||||
%ignore interval::overlap;
|
||||
%ignore interval::includes;
|
||||
%ignore interval::contains;
|
||||
%ignore qrotl;
|
||||
%ignore qrotr;
|
||||
%ignore setflag;
|
||||
%ignore read2bytes;
|
||||
%ignore rotate_left;
|
||||
%ignore qswap;
|
||||
%ignore swap32;
|
||||
%ignore swap16;
|
||||
%ignore swap_value;
|
||||
%ignore qalloc_or_throw;
|
||||
%ignore qrealloc_or_throw;
|
||||
%ignore get_buffer_for_sysdir;
|
||||
%ignore get_buffer_for_winerr;
|
||||
%ignore call_atexits;
|
||||
%ignore launch_process_params_t;
|
||||
%ignore launch_process;
|
||||
%ignore term_process;
|
||||
%ignore get_process_exit_code;
|
||||
%ignore BELOW_NORMAL_PRIORITY_CLASS;
|
||||
%ignore parse_command_line;
|
||||
%ignore parse_command_line2;
|
||||
%rename (parse_command_line2) py_parse_command_line;
|
||||
%ignore qgetenv;
|
||||
%ignore qsetenv;
|
||||
%ignore qctime;
|
||||
%ignore qlocaltime;
|
||||
%ignore qstrftime;
|
||||
%ignore qstrftime64;
|
||||
%ignore qstrtok;
|
||||
%ignore qstrlwr;
|
||||
%ignore qstrupr;
|
||||
%include "pro.h"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
%template(uvalvec_t) qvector<uval_t>; // vector of unsigned values
|
||||
%template(intvec_t) qvector<int>; // vector of integers
|
||||
%template(qstrvec_t) qvector<qstring>; // vector of strings
|
||||
%template(boolvec_t) qvector<bool>; // vector of bools
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
class qstring {
|
||||
public:
|
||||
const char *c_str() const { return self->c_str(); }
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// for obscure reasons swig can't get past this one on its own, it needs a dummy declaration.
|
||||
class strvec_t {
|
||||
public:
|
||||
qstring& at(int _idx) { return self->at(_idx).line; }
|
||||
size_t size() const { return self->size(); }
|
||||
};
|
||||
|
||||
class qtype {
|
||||
public:
|
||||
const uchar *c_str() const { return self->c_str(); }
|
||||
};
|
||||
|
274
swig/typeconv.i
274
swig/typeconv.i
@ -1,135 +1,145 @@
|
||||
// Convert an incoming Python list to a tid_t[] array
|
||||
%typemap(in) tid_t[ANY](tid_t temp[$1_dim0]) {
|
||||
int i, len;
|
||||
|
||||
if (!PySequence_Check($input))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError,"Expecting a sequence");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Cap the number of elements to copy */
|
||||
len = PySequence_Length($input) < $1_dim0 ? PySequence_Length($input) : $1_dim0;
|
||||
|
||||
for (i =0; i < len; i++)
|
||||
{
|
||||
PyObject *o = PySequence_GetItem($input,i);
|
||||
if (!PyLong_Check(o))
|
||||
{
|
||||
Py_XDECREF(o);
|
||||
PyErr_SetString(PyExc_ValueError,"Expecting a sequence of long integers");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
temp[i] = PyLong_AsUnsignedLong(o);
|
||||
Py_DECREF(o);
|
||||
}
|
||||
$1 = &temp[0];
|
||||
}
|
||||
|
||||
%define %cstring_output_maxstr_none(TYPEMAP, SIZE)
|
||||
%typemap (default) SIZE {
|
||||
$1 = MAXSTR;
|
||||
}
|
||||
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
|
||||
$1 = ($1_ltype) qalloc(MAXSTR+1);
|
||||
}
|
||||
%typemap(out) ssize_t {
|
||||
/* REMOVING ssize_t return value in $symname */
|
||||
}
|
||||
%typemap(argout) (TYPEMAP,SIZE) {
|
||||
if (result > 0)
|
||||
{
|
||||
resultobj = PyString_FromString($1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_INCREF(Py_None);
|
||||
resultobj = Py_None;
|
||||
}
|
||||
qfree($1);
|
||||
}
|
||||
%enddef
|
||||
|
||||
%define %cstring_bounded_output_none(TYPEMAP,MAX)
|
||||
%typemap(in, numinputs=0) TYPEMAP(char temp[MAX+1]) {
|
||||
$1 = ($1_ltype) temp;
|
||||
}
|
||||
%typemap(argout,fragment="t_output_helper") TYPEMAP {
|
||||
PyObject *o;
|
||||
$1[MAX] = 0;
|
||||
|
||||
if ($1 > 0)
|
||||
{
|
||||
o = PyString_FromString($1);
|
||||
}
|
||||
else
|
||||
{
|
||||
o = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
}
|
||||
$result = t_output_helper($result,o);
|
||||
}
|
||||
%enddef
|
||||
|
||||
%define %binary_output_or_none(TYPEMAP, SIZE)
|
||||
%typemap (default) SIZE {
|
||||
$1 = MAXSPECSIZE;
|
||||
}
|
||||
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
|
||||
$1 = (char *) qalloc(MAXSPECSIZE+1);
|
||||
}
|
||||
%typemap(out) ssize_t {
|
||||
/* REMOVING ssize_t return value in $symname */
|
||||
}
|
||||
%typemap(argout) (TYPEMAP,SIZE) {
|
||||
if (result > 0)
|
||||
{
|
||||
resultobj = PyString_FromStringAndSize((char *)$1, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_INCREF(Py_None);
|
||||
resultobj = Py_None;
|
||||
}
|
||||
qfree((void *)$1);
|
||||
}
|
||||
%enddef
|
||||
|
||||
%define %binary_output_with_size(TYPEMAP, SIZE)
|
||||
%typemap (default) SIZE {
|
||||
size_t ressize = MAXSPECSIZE;
|
||||
$1 = &ressize;
|
||||
}
|
||||
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
|
||||
$1 = (char *) qalloc(MAXSPECSIZE+1);
|
||||
}
|
||||
%typemap(out) ssize_t {
|
||||
/* REMOVING ssize_t return value in $symname */
|
||||
}
|
||||
%typemap(argout) (TYPEMAP,SIZE) {
|
||||
if (result)
|
||||
{
|
||||
resultobj = PyString_FromStringAndSize((char *)$1, *$2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_INCREF(Py_None);
|
||||
resultobj = Py_None;
|
||||
}
|
||||
qfree((void *)$1);
|
||||
}
|
||||
%enddef
|
||||
|
||||
// Check that the argument is a callable Python object
|
||||
%typemap(in) PyObject *pyfunc {
|
||||
if (!PyCallable_Check($input)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Expected a callable object");
|
||||
return NULL;
|
||||
}
|
||||
$1 = $input;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Convert an incoming Python list to a tid_t[] array
|
||||
%typemap(in) tid_t[ANY](tid_t temp[$1_dim0]) {
|
||||
int i, len;
|
||||
|
||||
if (!PySequence_Check($input))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError,"Expecting a sequence");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Cap the number of elements to copy */
|
||||
len = PySequence_Length($input) < $1_dim0 ? PySequence_Length($input) : $1_dim0;
|
||||
|
||||
for (i =0; i < len; i++)
|
||||
{
|
||||
PyObject *o = PySequence_GetItem($input,i);
|
||||
if (!PyLong_Check(o))
|
||||
{
|
||||
Py_XDECREF(o);
|
||||
PyErr_SetString(PyExc_ValueError,"Expecting a sequence of long integers");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
temp[i] = PyLong_AsUnsignedLong(o);
|
||||
Py_DECREF(o);
|
||||
}
|
||||
$1 = &temp[0];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
%define %cstring_output_maxstr_none(TYPEMAP, SIZE)
|
||||
|
||||
%typemap (default) SIZE {
|
||||
$1 = MAXSTR;
|
||||
}
|
||||
|
||||
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
|
||||
$1 = ($1_ltype) qalloc(MAXSTR+1);
|
||||
}
|
||||
|
||||
%typemap(out) ssize_t {
|
||||
/* REMOVING ssize_t return value in $symname */
|
||||
}
|
||||
|
||||
%typemap(argout) (TYPEMAP,SIZE) {
|
||||
if (result > 0)
|
||||
{
|
||||
resultobj = PyString_FromString($1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_INCREF(Py_None);
|
||||
resultobj = Py_None;
|
||||
}
|
||||
qfree($1);
|
||||
}
|
||||
%enddef
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
%define %cstring_bounded_output_none(TYPEMAP,MAX)
|
||||
%typemap(in, numinputs=0) TYPEMAP(char temp[MAX+1]) {
|
||||
$1 = ($1_ltype) temp;
|
||||
}
|
||||
%typemap(argout,fragment="t_output_helper") TYPEMAP {
|
||||
PyObject *o;
|
||||
$1[MAX] = 0;
|
||||
|
||||
if ($1 > 0)
|
||||
{
|
||||
o = PyString_FromString($1);
|
||||
}
|
||||
else
|
||||
{
|
||||
o = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
}
|
||||
$result = t_output_helper($result,o);
|
||||
}
|
||||
%enddef
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
%define %binary_output_or_none(TYPEMAP, SIZE)
|
||||
%typemap (default) SIZE {
|
||||
$1 = MAXSPECSIZE;
|
||||
}
|
||||
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
|
||||
$1 = (char *) qalloc(MAXSPECSIZE+1);
|
||||
}
|
||||
%typemap(out) ssize_t {
|
||||
/* REMOVING ssize_t return value in $symname */
|
||||
}
|
||||
%typemap(argout) (TYPEMAP,SIZE) {
|
||||
if (result > 0)
|
||||
{
|
||||
resultobj = PyString_FromStringAndSize((char *)$1, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_INCREF(Py_None);
|
||||
resultobj = Py_None;
|
||||
}
|
||||
qfree((void *)$1);
|
||||
}
|
||||
%enddef
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
%define %binary_output_with_size(TYPEMAP, SIZE)
|
||||
%typemap (default) SIZE {
|
||||
size_t ressize = MAXSPECSIZE;
|
||||
$1 = &ressize;
|
||||
}
|
||||
%typemap(in,numinputs=0) (TYPEMAP, SIZE) {
|
||||
$1 = (char *) qalloc(MAXSPECSIZE+1);
|
||||
}
|
||||
%typemap(out) ssize_t {
|
||||
/* REMOVING ssize_t return value in $symname */
|
||||
}
|
||||
%typemap(argout) (TYPEMAP,SIZE) {
|
||||
if (result)
|
||||
{
|
||||
resultobj = PyString_FromStringAndSize((char *)$1, *$2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_INCREF(Py_None);
|
||||
resultobj = Py_None;
|
||||
}
|
||||
qfree((void *)$1);
|
||||
}
|
||||
%enddef
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Check that the argument is a callable Python object
|
||||
%typemap(in) PyObject *pyfunc {
|
||||
if (!PyCallable_Check($input)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Expected a callable object");
|
||||
return NULL;
|
||||
}
|
||||
$1 = $input;
|
||||
}
|
||||
|
||||
// Convert ea_t
|
||||
%typemap(in) ea_t
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user