Class: ApkResources
- Inherits:
-
Object
- Object
- ApkResources
- Defined in:
- lib/apktools/apkresources.rb
Overview
Class to parse an APK’s resources.arsc data and retrieve resource data associated with a given R.id value
Defined Under Namespace
Classes: ChunkHeader, Package, PackageHeader, ResType, ResTypeConfig, ResTypeEntry, ResTypeSpec, StringPool
Constant Summary collapse
- DEBUG =
:nodoc:
false
Instance Attribute Summary collapse
-
#package_header ⇒ Object
readonly
PackageHeader containing information about all the type and key strings in the package.
-
#packages ⇒ Object
readonly
Hash of Package chunks, keyed by package id.
-
#stringpool_main ⇒ Object
readonly
StringPool containing all value strings in the package.
Instance Method Summary collapse
-
#get_all_keys ⇒ Object
Return hash of all the key values in the file keyed by package id.
-
#get_all_strings ⇒ Object
Return array of all string values in the file.
-
#get_all_types ⇒ Object
Return hash of all the type values in the file keyed by package id.
-
#get_default_resource_value(res_id) ⇒ Object
Obtain the default value for a given resource id.
-
#get_resource_key(res_id, xml_format = false) ⇒ Object
Obtain the key value for a given resource id.
-
#get_resource_value(res_id) ⇒ Object
Obtain the value(s) for a given resource id.
-
#initialize(apk_file) ⇒ ApkResources
constructor
Create a new ApkResources instance from the specified
apk_file
.
Constructor Details
#initialize(apk_file) ⇒ ApkResources
Create a new ApkResources instance from the specified apk_file
This opens and parses the contents of the APK’s resources.arsc file.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/apktools/apkresources.rb', line 135 def initialize(apk_file) data = nil # Get resources.arsc from the APK file Zip::ZipFile.foreach(apk_file) do |f| if f.name.match(/resources.arsc/) data = f.get_input_stream.read end end # Parse the Table Chunk ## Header header_type = read_short(data, HEADER_START) header_size = read_short(data, HEADER_START+2) header_chunk_size = read_word(data, HEADER_START+4) header_package_count = read_word(data, HEADER_START+8) puts "Resource Package Count = #{header_package_count}" if DEBUG # Parse the StringPool Chunk ## Header startoffset_pool = HEADER_START + header_size puts "Parse Main StringPool Chunk" if DEBUG @stringpool_main = parse_stringpool(data, startoffset_pool) puts "#{@stringpool_main.values.length} strings found" if DEBUG # Parse the Package Chunk ## Header startoffset_package = startoffset_pool + @stringpool_main.header.chunk_size @packages = Hash.new() i = 0 while i < header_package_count package_element = parse_package(data, startoffset_package) puts "Package #{package_element.package_header.id}" if DEBUG startoffset_package = startoffset_package + package_element.package_header.header.chunk_size @packages[package_element.package_header.id] = package_element i += 1 end end |
Instance Attribute Details
#package_header ⇒ Object (readonly)
PackageHeader containing information about all the type and key strings in the package
124 125 126 |
# File 'lib/apktools/apkresources.rb', line 124 def package_header @package_header end |
#packages ⇒ Object (readonly)
Hash of Package chunks, keyed by package id
128 129 130 |
# File 'lib/apktools/apkresources.rb', line 128 def packages @packages end |
#stringpool_main ⇒ Object (readonly)
StringPool containing all value strings in the package
126 127 128 |
# File 'lib/apktools/apkresources.rb', line 126 def stringpool_main @stringpool_main end |
Instance Method Details
#get_all_keys ⇒ Object
Return hash of all the key values in the file keyed by package id
199 200 201 202 203 204 205 206 |
# File 'lib/apktools/apkresources.rb', line 199 def get_all_keys keys = Hash.new() @packages.each do |key, value| keys[key] = value.stringpool_keystrings.values end return keys end |
#get_all_strings ⇒ Object
Return array of all string values in the file
178 179 180 |
# File 'lib/apktools/apkresources.rb', line 178 def get_all_strings return @stringpool_main.values end |
#get_all_types ⇒ Object
Return hash of all the type values in the file keyed by package id
186 187 188 189 190 191 192 193 |
# File 'lib/apktools/apkresources.rb', line 186 def get_all_types types = Hash.new() @packages.each do |key, value| types[key] = value.stringpool_typestrings.values end return types end |
#get_default_resource_value(res_id) ⇒ Object
Obtain the default value for a given resource id
res_id: ID values of a resources as a FixNum or String representation (i.e. 0x7F060001)
Returns: The default ResTypeEntry to the given id, or nil if no default exists
260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/apktools/apkresources.rb', line 260 def get_default_resource_value(res_id) if res_id.is_a? String res_id = res_id.hex end entries = get_resource_value(res_id) if entries != nil default = ResTypeConfig.new(0, 0, 0, 0, 0, 0, 0, 0) default_entry = entries[default] return default_entry else return nil end end |
#get_resource_key(res_id, xml_format = false) ⇒ Object
Obtain the key value for a given resource id
res_id: ID value of a resource as a FixNum or String representation (i.e. 0x7F060001) xml_format: Optionally format return string for XML files.
If xml_format is true, return value will be @<type>/<key> If xml_format is false or missing, return value will be R.<type>.<key> If the resource id does not exist, return value will be nil
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/apktools/apkresources.rb', line 218 def get_resource_key(res_id, xml_format=false) if res_id.is_a? String res_id = res_id.hex end # R.id integers are a concatenation of package_id, type_id, and entry index res_package = (res_id >> 24) & 0xFF res_type = (res_id >> 16) & 0xFF res_index = res_id & 0xFFFF package_element = @packages[res_package] if package_element == nil # This is not a resource we can parse return nil end res_spec = package_element.type_data[res_type-1] if res_spec == nil puts "Could not find ResTypeSpec for #{res_package} #{res_type}" if DEBUG return nil end entry = res_spec.types.entries[res_index] if entry == nil # There is no entry in our table for this resource return nil end if xml_format return "@#{res_spec.id}/#{entry.values[0].key}" else return "R.#{res_spec.id}.#{entry.values[0].key}" end end |
#get_resource_value(res_id) ⇒ Object
Obtain the value(s) for a given resource id. A default resource is one defined in an unqualified directory.
res_id: ID value of a resource as a FixNum or String representation (i.e. 0x7F060001)
Returns: Hash of all entries matching this id, keyed by their matching ResTypeConfig or nil if the resource id cannot be found.
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/apktools/apkresources.rb', line 284 def get_resource_value(res_id) if res_id.is_a? String res_id = res_id.hex end # R.id integers are a concatenation of package_id, type_id, and entry index res_package = (res_id >> 24) & 0xFF res_type = (res_id >> 16) & 0xFF res_index = res_id & 0xFFFF package_element = @packages[res_package] if package_element == nil # This is not a resource we can parse return nil end res_spec = package_element.type_data[res_type-1] if res_spec == nil puts "Could not find ResTypeSpec for #{res_package} #{res_type}" if DEBUG return nil end entries = res_spec.types.entries[res_index] if entries == nil puts "Could not find #{res_spec.types.id} ResType chunk" if DEBUG return nil end return entries end |