add flags and DexString cmp
This commit is contained in:
parent
9788d77b74
commit
625420c5f6
3 changed files with 108 additions and 4 deletions
|
|
@ -1,8 +1,8 @@
|
|||
//! Representation of an apk.
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::{Class, Error, Result};
|
||||
use androscalpel_serializer::{ClassDefItem, DexFileReader, TypeList, NO_INDEX};
|
||||
use crate::{Class, DexString, Error, Result};
|
||||
use androscalpel_serializer::*;
|
||||
|
||||
/// Represent an apk.
|
||||
#[pyclass]
|
||||
|
|
@ -37,7 +37,7 @@ impl Apk {
|
|||
dex.get_type_ids().len()
|
||||
)))?
|
||||
.descriptor_idx;
|
||||
let name = dex.get_string(name_idx)?.into();
|
||||
let name: DexString = dex.get_string(name_idx)?.into();
|
||||
let superclass = if class_item.class_idx == NO_INDEX.0 {
|
||||
None
|
||||
} else {
|
||||
|
|
@ -75,11 +75,41 @@ impl Apk {
|
|||
} else {
|
||||
Some(dex.get_string(class_item.source_file_idx)?.into())
|
||||
};
|
||||
let is_public = (class_item.access_flags & ACC_PUBLIC) != 0;
|
||||
let is_final = (class_item.access_flags & ACC_FINAL) != 0;
|
||||
let is_interface = (class_item.access_flags & ACC_INTERFACE) != 0;
|
||||
let is_abstract = (class_item.access_flags & ACC_ABSTRACT) != 0;
|
||||
let is_synthetic = (class_item.access_flags & ACC_SYNTHETIC) != 0;
|
||||
let is_annotation = (class_item.access_flags & ACC_ANNOTATION) != 0;
|
||||
let is_enum = (class_item.access_flags & ACC_ENUM) != 0;
|
||||
if (class_item.access_flags
|
||||
& !(ACC_PUBLIC
|
||||
| ACC_FINAL
|
||||
| ACC_INTERFACE
|
||||
| ACC_ABSTRACT
|
||||
| ACC_SYNTHETIC
|
||||
| ACC_ANNOTATION
|
||||
| ACC_ENUM))
|
||||
!= 0
|
||||
{
|
||||
println!(
|
||||
"Unexpected flags found in class_def_item.access_flags for {}: 0x{:x}",
|
||||
<&DexString as Into<String>>::into(&name),
|
||||
class_item.access_flags
|
||||
); // TODO: better logging
|
||||
}
|
||||
self.classes.push(Class {
|
||||
name,
|
||||
superclass,
|
||||
interfaces,
|
||||
source_file,
|
||||
is_public,
|
||||
is_final,
|
||||
is_interface,
|
||||
is_abstract,
|
||||
is_synthetic,
|
||||
is_annotation,
|
||||
is_enum,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,41 @@ use crate::DexString;
|
|||
#[pyclass]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Class {
|
||||
/// Type name, format described at
|
||||
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||
#[pyo3(get, set)]
|
||||
pub name: DexString,
|
||||
// pub access_flags: // TODO
|
||||
/// If the class is visible everywhere
|
||||
#[pyo3(get, set)]
|
||||
pub is_public: bool, // TODO: is it possible to not be public non a non inner class?
|
||||
/// If the class is subclassable
|
||||
#[pyo3(get, set)]
|
||||
pub is_final: bool,
|
||||
/// If the class is a 'multipy-implementable abstract class' AKA an interface
|
||||
#[pyo3(get, set)]
|
||||
pub is_interface: bool,
|
||||
/// If the class is instanciable
|
||||
#[pyo3(get, set)]
|
||||
pub is_abstract: bool,
|
||||
/// If the class is not directly defined in the source code
|
||||
#[pyo3(get, set)]
|
||||
pub is_synthetic: bool,
|
||||
/// If the class is an annotation
|
||||
#[pyo3(get, set)]
|
||||
pub is_annotation: bool,
|
||||
/// If the class is an enum
|
||||
#[pyo3(get, set)]
|
||||
pub is_enum: bool,
|
||||
/// Name of the superclass, format described at
|
||||
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||
#[pyo3(get, set)]
|
||||
pub superclass: Option<DexString>,
|
||||
/// List of the interfaces that class implement, format of the interfaces
|
||||
/// name is discribed at
|
||||
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||
#[pyo3(get, set)]
|
||||
pub interfaces: Vec<DexString>,
|
||||
/// Name of the source file where this class is defined.
|
||||
#[pyo3(get, set)]
|
||||
pub source_file: Option<DexString>,
|
||||
// pub annotations: Option<()> // TODO
|
||||
|
|
@ -32,6 +60,13 @@ impl Class {
|
|||
superclass: None,
|
||||
interfaces: vec![],
|
||||
source_file: None,
|
||||
is_public: true,
|
||||
is_final: false,
|
||||
is_interface: false,
|
||||
is_abstract: false,
|
||||
is_synthetic: false,
|
||||
is_annotation: false,
|
||||
is_enum: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use pyo3::class::basic::CompareOp;
|
||||
use pyo3::exceptions::PyValueError;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
|
|
@ -93,11 +94,49 @@ impl From<DexString> for String {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&str> for DexString {
|
||||
fn from(string: &str) -> Self {
|
||||
Self(string.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for DexString {
|
||||
fn from(string: String) -> Self {
|
||||
Self(string.as_str().into())
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl DexString {
|
||||
#[new]
|
||||
pub fn new(s: &str) -> Self {
|
||||
s.into()
|
||||
}
|
||||
|
||||
/// Return the binary mutf-8 encoded string (minus the trailling 0)
|
||||
pub fn get_bytes(&self) -> &[u8] {
|
||||
&self.0.data
|
||||
}
|
||||
|
||||
/// Return the 'utf-16' size of the string (number of unicode code point, ie its lenght in 'java-land')
|
||||
pub fn get_utf16_size(&self) -> u32 {
|
||||
self.0.utf16_size.0
|
||||
}
|
||||
|
||||
pub fn __str__(&self) -> String {
|
||||
self.into()
|
||||
}
|
||||
|
||||
fn __richcmp__(&self, other: &PyAny, op: CompareOp, py: Python<'_>) -> PyResult<PyObject> {
|
||||
let other: Self = other
|
||||
.extract()
|
||||
.or(<String as FromPyObject>::extract(other).map(|string| string.into()))?;
|
||||
match op {
|
||||
CompareOp::Eq => Ok((self == &other).into_py(py)),
|
||||
_ => Ok(py.NotImplemented()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __repr__(&self) -> String {
|
||||
self.into()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue