From 892546343ab7824e30a4972aa4bc9c2e6d0df938 Mon Sep 17 00:00:00 2001 From: codeskyblue Date: Tue, 9 May 2017 17:10:58 +0800 Subject: [PATCH] fix parse apk panic --- Godeps/Godeps.json | 8 +- apk.go | 2 +- .../shogo82148/androidbinary/.travis.yml | 6 - .../shogo82148/androidbinary/LICENSE | 21 - .../shogo82148/androidbinary/README.md | 29 - .../shogo82148/androidbinary/common.go | 236 ----- .../shogo82148/androidbinary/table.go | 938 ------------------ .../shogo82148/androidbinary/xml.go | 237 ----- 8 files changed, 5 insertions(+), 1472 deletions(-) delete mode 100644 vendor/github.com/shogo82148/androidbinary/.travis.yml delete mode 100644 vendor/github.com/shogo82148/androidbinary/LICENSE delete mode 100644 vendor/github.com/shogo82148/androidbinary/README.md delete mode 100644 vendor/github.com/shogo82148/androidbinary/common.go delete mode 100644 vendor/github.com/shogo82148/androidbinary/table.go delete mode 100644 vendor/github.com/shogo82148/androidbinary/xml.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index c3db70c..65e7983 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -24,6 +24,10 @@ "ImportPath": "github.com/alecthomas/units", "Rev": "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a" }, + { + "ImportPath": "github.com/codeskyblue/androidbinary", + "Rev": "0bda65d9fce8f2fc20eef404a9231882894db9c6" + }, { "ImportPath": "github.com/codeskyblue/dockerignore", "Rev": "de82dee623d9207f906d327172149cba50427a88" @@ -74,10 +78,6 @@ "Comment": "v0.8.0-1-g839d9e9", "Rev": "839d9e913e063e28dfd0e6c7b7512793e0a48be9" }, - { - "ImportPath": "github.com/shogo82148/androidbinary", - "Rev": "eb4fe244aa607cf45019a08b0034255594d00962" - }, { "ImportPath": "golang.org/x/net/html", "Rev": "a625e3953219464fdd5611bb48bf87c927717295" diff --git a/apk.go b/apk.go index 7b61b42..bee1f49 100644 --- a/apk.go +++ b/apk.go @@ -13,8 +13,8 @@ import ( _ "image/jpeg" _ "image/png" + "github.com/codeskyblue/androidbinary" "github.com/pkg/errors" - "github.com/shogo82148/androidbinary" ) type ApkInfo struct { diff --git a/vendor/github.com/shogo82148/androidbinary/.travis.yml b/vendor/github.com/shogo82148/androidbinary/.travis.yml deleted file mode 100644 index 4ad09c4..0000000 --- a/vendor/github.com/shogo82148/androidbinary/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: go - -go: - - 1.0 - - 1.1 - - 1.2 diff --git a/vendor/github.com/shogo82148/androidbinary/LICENSE b/vendor/github.com/shogo82148/androidbinary/LICENSE deleted file mode 100644 index b19693d..0000000 --- a/vendor/github.com/shogo82148/androidbinary/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Ichinose Shogo - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/github.com/shogo82148/androidbinary/README.md b/vendor/github.com/shogo82148/androidbinary/README.md deleted file mode 100644 index 56f9cd2..0000000 --- a/vendor/github.com/shogo82148/androidbinary/README.md +++ /dev/null @@ -1,29 +0,0 @@ -androidbinary -===== - -[![Build Status](https://travis-ci.org/shogo82148/androidbinary.svg?branch=master)](https://travis-ci.org/shogo82148/androidbinary) - -Android binary file parser - -## Parse XML binary - -``` go -package main - -import ( - "fmt" - "github.com/shogo82148/androidbinary" - "os" -) - -func main() { - f, _ := os.Open("AndroidManifest") - xml, _ := androidbinary.NewXMLFile(f) - reader := xml.Reader() - // read XML from reader -} -``` - -## License - -This software is released under the MIT License, see LICENSE. diff --git a/vendor/github.com/shogo82148/androidbinary/common.go b/vendor/github.com/shogo82148/androidbinary/common.go deleted file mode 100644 index 02026bc..0000000 --- a/vendor/github.com/shogo82148/androidbinary/common.go +++ /dev/null @@ -1,236 +0,0 @@ -package androidbinary - -import ( - "bytes" - "encoding/binary" - "io" - "os" - "unicode/utf16" -) - -const ( - RES_NULL_TYPE = 0x0000 - RES_STRING_POOL_TYPE = 0x0001 - RES_TABLE_TYPE = 0x0002 - RES_XML_TYPE = 0x0003 - - // Chunk types in RES_XML_TYPE - RES_XML_FIRST_CHUNK_TYPE = 0x0100 - RES_XML_START_NAMESPACE_TYPE = 0x0100 - RES_XML_END_NAMESPACE_TYPE = 0x0101 - RES_XML_START_ELEMENT_TYPE = 0x0102 - RES_XML_END_ELEMENT_TYPE = 0x0103 - RES_XML_CDATA_TYPE = 0x0104 - RES_XML_LAST_CHUNK_TYPE = 0x017f - - // This contains a uint32_t array mapping strings in the string - // pool back to resource identifiers. It is optional. - RES_XML_RESOURCE_MAP_TYPE = 0x0180 - - // Chunk types in RES_TABLE_TYPE - RES_TABLE_PACKAGE_TYPE = 0x0200 - RES_TABLE_TYPE_TYPE = 0x0201 - RES_TABLE_TYPE_SPEC_TYPE = 0x0202 -) - -type ResChunkHeader struct { - Type uint16 - HeaderSize uint16 - Size uint32 -} - -const SORTED_FLAG = 1 << 0 -const UTF8_FLAG = 1 << 8 - -type ResStringPoolHeader struct { - Header ResChunkHeader - StringCount uint32 - StyleCount uint32 - Flags uint32 - StringStart uint32 - StylesStart uint32 -} - -type ResStringPool struct { - Header ResStringPoolHeader - Strings []string - Styles []string -} - -const NilResStringPoolRef = ResStringPoolRef(0xFFFFFFFF) - -type ResStringPoolRef uint32 - -const ( - TYPE_NULL = 0x00 - TYPE_REFERENCE = 0x01 - TYPE_ATTRIBUTE = 0x02 - TYPE_STRING = 0x03 - TYPE_FLOAT = 0x04 - TYPE_DIMENSION = 0x05 - TYPE_FRACTION = 0x06 - TYPE_FIRST_INT = 0x10 - TYPE_INT_DEC = 0x10 - TYPE_INT_HEX = 0x11 - TYPE_INT_BOOLEAN = 0x12 - TYPE_FIRST_COLOR_INT = 0x1c - TYPE_INT_COLOR_ARGB8 = 0x1c - TYPE_INT_COLOR_RGB8 = 0x1d - TYPE_INT_COLOR_ARGB4 = 0x1e - TYPE_INT_COLOR_RGB4 = 0x1f - TYPE_LAST_COLOR_INT = 0x1f - TYPE_LAST_INT = 0x1f -) - -type ResValue struct { - Size uint16 - Res0 uint8 - DataType uint8 - Data uint32 -} - -func (pool *ResStringPool) GetString(ref ResStringPoolRef) string { - return pool.Strings[int(ref)] -} - -func readStringPool(sr *io.SectionReader) (*ResStringPool, error) { - sp := new(ResStringPool) - if err := binary.Read(sr, binary.LittleEndian, &sp.Header); err != nil { - return nil, err - } - - stringStarts := make([]uint32, sp.Header.StringCount) - if err := binary.Read(sr, binary.LittleEndian, stringStarts); err != nil { - return nil, err - } - - styleStarts := make([]uint32, sp.Header.StyleCount) - if err := binary.Read(sr, binary.LittleEndian, styleStarts); err != nil { - return nil, err - } - - sp.Strings = make([]string, sp.Header.StringCount) - for i, start := range stringStarts { - var str string - var err error - sr.Seek(int64(sp.Header.StringStart+start), os.SEEK_SET) - if (sp.Header.Flags & UTF8_FLAG) == 0 { - str, err = readUTF16(sr) - } else { - str, err = readUTF8(sr) - } - if err != nil { - return nil, err - } - sp.Strings[i] = str - } - - sp.Styles = make([]string, sp.Header.StyleCount) - for i, start := range styleStarts { - var str string - var err error - sr.Seek(int64(sp.Header.StylesStart+start), os.SEEK_SET) - if (sp.Header.Flags & UTF8_FLAG) == 0 { - str, err = readUTF16(sr) - } else { - str, err = readUTF8(sr) - } - if err != nil { - return nil, err - } - sp.Styles[i] = str - } - - return sp, nil -} - -func readUTF16(sr *io.SectionReader) (string, error) { - // read lenth of string - size, err := readUTF16length(sr) - if err != nil { - return "", nil - } - - // read string value - buf := make([]uint16, size) - if err := binary.Read(sr, binary.LittleEndian, buf); err != nil { - return "", err - } - return string(utf16.Decode(buf)), nil -} - -func readUTF16length(sr *io.SectionReader) (int, error) { - var size int - var first, second uint16 - if err := binary.Read(sr, binary.LittleEndian, &first); err != nil { - return 0, err - } - if (first & 0x8000) != 0 { - if err := binary.Read(sr, binary.LittleEndian, &second); err != nil { - return 0, err - } - size = (int(first&0x7FFF) << 16) + int(second) - } else { - size = int(first) - } - return size, nil -} - -func readUTF8(sr *io.SectionReader) (string, error) { - // skip utf16 length - _, err := readUTF8length(sr) - if err != nil { - return "", err - } - - // read lenth of string - size, err := readUTF8length(sr) - if err != nil { - return "", err - } - - buf := make([]uint8, size) - if err := binary.Read(sr, binary.LittleEndian, buf); err != nil { - return "", err - } - return string(buf), nil -} - -func readUTF8length(sr *io.SectionReader) (int, error) { - var size int - var first, second uint8 - if err := binary.Read(sr, binary.LittleEndian, &first); err != nil { - return 0, err - } - if (first & 0x80) != 0 { - if err := binary.Read(sr, binary.LittleEndian, &second); err != nil { - return 0, err - } - size = (int(first&0x7F) << 8) + int(second) - } else { - size = int(first) - } - return size, nil -} - -func newZeroFilledReader(r io.Reader, actual int64, expected int64) (io.Reader, error) { - if actual >= expected { - // no need to fill - return r, nil - } - - // read `actual' bytes from r, and - buf := new(bytes.Buffer) - if _, err := io.CopyN(buf, r, actual); err != nil { - return nil, err - } - - // fill zero until `expected' bytes - for i := actual; i < expected; i++ { - if err := buf.WriteByte(0x00); err != nil { - return nil, err - } - } - - return buf, nil -} diff --git a/vendor/github.com/shogo82148/androidbinary/table.go b/vendor/github.com/shogo82148/androidbinary/table.go deleted file mode 100644 index d9b9c6f..0000000 --- a/vendor/github.com/shogo82148/androidbinary/table.go +++ /dev/null @@ -1,938 +0,0 @@ -package androidbinary - -import ( - "encoding/binary" - "fmt" - "io" - "os" - "unsafe" -) - -type ResId uint32 - -type TableFile struct { - stringPool *ResStringPool - tablePackages map[uint32]*TablePackage -} - -type ResTableHeader struct { - Header ResChunkHeader - PackageCount uint32 -} - -type ResTablePackage struct { - Header ResChunkHeader - Id uint32 - Name [128]uint16 - TypeStrings uint32 - LastPublicType uint32 - KeyStrings uint32 - LastPublicKey uint32 -} - -type TablePackage struct { - Header ResTablePackage - TypeStrings *ResStringPool - KeyStrings *ResStringPool - TableTypes []*TableType -} - -type ResTableType struct { - Header ResChunkHeader - Id uint8 - Res0 uint8 - Res1 uint16 - EntryCount uint32 - EntriesStart uint32 - Config ResTableConfig -} - -// ScreenLayout bits -const ( - MASK_SCREENSIZE = 0x0f - SCREENSIZE_ANY = 0x01 - SCREENSIZE_SMALL = 0x02 - SCREENSIZE_NORMAL = 0x03 - SCREENSIZE_LARGE = 0x04 - SCREENSIZE_XLARGE = 0x05 - - MASK_SCREENLONG = 0x30 - SHIFT_SCREENLONG = 4 - SCREENLONG_ANY = 0x00 - SCREENLONG_NO = 0x10 - SCREENLONG_YES = 0x20 - - MASK_LAYOUTDIR = 0xC0 - SHIFT_LAYOUTDIR = 6 - LAYOUTDIR_ANY = 0x00 - LAYOUTDIR_LTR = 0x40 - LAYOUTDIR_RTL = 0x80 -) - -// UIMode bits -const ( - MASK_UI_MODE_TYPE = 0x0f - UI_MODE_TYPE_ANY = 0x01 - UI_MODE_TYPE_NORMAL = 0x02 - UI_MODE_TYPE_DESK = 0x03 - UI_MODE_TYPE_CAR = 0x04 - - MASK_UI_MODE_NIGHT = 0x30 - SHIFT_UI_MODE_NIGHT = 4 - UI_MODE_NIGHT_ANY = 0x00 - UI_MODE_NIGHT_NO = 0x10 - UI_MODE_NIGHT_YES = 0x20 -) - -// input flags -const ( - MASK_KEYSHIDDEN = 0x03 - KEYSHIDDEN_ANY = 0x00 - KEYSHIDDEN_NO = 0x01 - KEYSHIDDEN_YES = 0x02 - KEYSHIDDEN_SOFT = 0x03 - - MASK_NAVHIDDEN = 0x0c - NAVHIDDEN_ANY = 0x00 - NAVHIDDEN_NO = 0x04 - NAVHIDDEN_YES = 0x08 -) - -type ResTableConfig struct { - Size uint32 - // imsi - Mcc uint16 - Mnc uint16 - - // locale - Language [2]uint8 - Country [2]uint8 - - // screen type - Orientation uint8 - Touchscreen uint8 - Density uint16 - - // inout - Keyboard uint8 - Navigation uint8 - InputFlags uint8 - InputPad0 uint8 - - // screen size - ScreenWidth uint16 - ScreenHeight uint16 - - // version - SDKVersion uint16 - MinorVersion uint16 - - // screen config - ScreenLayout uint8 - UIMode uint8 - SmallestScreenWidthDp uint16 - - // screen size dp - ScreenWidthDp uint16 - ScreenHeightDp uint16 -} - -type TableType struct { - Header *ResTableType - Entries []TableEntry -} - -type ResTableEntry struct { - Size uint16 - Flags uint16 - Key ResStringPoolRef -} - -type TableEntry struct { - Key *ResTableEntry - Value *ResValue - Flags uint32 -} - -type ResTableTypeSpec struct { - Header ResChunkHeader - Id uint8 - Res0 uint8 - Res1 uint16 - EntryCount uint32 -} - -func (id ResId) Package() int { - return int(id) >> 24 -} - -func (id ResId) Type() int { - return (int(id) >> 16) & 0xFF -} - -func (id ResId) Entry() int { - return int(id) & 0xFFFF -} - -func NewTableFile(r io.ReaderAt) (*TableFile, error) { - f := new(TableFile) - sr := io.NewSectionReader(r, 0, 1<<63-1) - - header := new(ResTableHeader) - binary.Read(sr, binary.LittleEndian, header) - f.tablePackages = make(map[uint32]*TablePackage) - - offset := int64(header.Header.HeaderSize) - for offset < int64(header.Header.Size) { - chunkHeader, err := f.readChunk(sr, offset) - if err != nil { - return nil, err - } - offset += int64(chunkHeader.Size) - } - return f, nil -} - -func (f *TableFile) findPackage(id int) *TablePackage { - return f.tablePackages[uint32(id)] -} - -func (p *TablePackage) findType(id int, config *ResTableConfig) *TableType { - var best *TableType - for _, t := range p.TableTypes { - if int(t.Header.Id) != id { - continue - } - if !t.Header.Config.Match(config) { - continue - } - if best == nil || t.Header.Config.IsBetterThan(&best.Header.Config, config) { - best = t - } - } - return best -} - -func (f *TableFile) GetResource(id ResId, config *ResTableConfig) (interface{}, error) { - p := f.findPackage(id.Package()) - t := p.findType(id.Type(), config) - e := t.Entries[id.Entry()] - v := e.Value - switch v.DataType { - case TYPE_NULL: - return nil, nil - case TYPE_STRING: - return f.GetString(ResStringPoolRef(v.Data)), nil - case TYPE_INT_DEC: - return v.Data, nil - case TYPE_INT_HEX: - return v.Data, nil - case TYPE_INT_BOOLEAN: - return v.Data != 0, nil - } - return v.Data, nil -} - -func (f *TableFile) GetString(ref ResStringPoolRef) string { - return f.stringPool.GetString(ref) -} - -func (f *TableFile) readChunk(r io.ReaderAt, offset int64) (*ResChunkHeader, error) { - sr := io.NewSectionReader(r, offset, 1<<63-1-offset) - chunkHeader := &ResChunkHeader{} - sr.Seek(0, os.SEEK_SET) - if err := binary.Read(sr, binary.LittleEndian, chunkHeader); err != nil { - return nil, err - } - - var err error - sr.Seek(0, os.SEEK_SET) - switch chunkHeader.Type { - case RES_STRING_POOL_TYPE: - f.stringPool, err = readStringPool(sr) - case RES_TABLE_PACKAGE_TYPE: - var tablePackage *TablePackage - tablePackage, err = readTablePackage(sr) - f.tablePackages[tablePackage.Header.Id] = tablePackage - } - if err != nil { - return nil, err - } - - return chunkHeader, nil -} - -func readTablePackage(sr *io.SectionReader) (*TablePackage, error) { - tablePackage := new(TablePackage) - header := new(ResTablePackage) - if err := binary.Read(sr, binary.LittleEndian, header); err != nil { - return nil, err - } - tablePackage.Header = *header - - srTypes := io.NewSectionReader(sr, int64(header.TypeStrings), int64(header.Header.Size-header.TypeStrings)) - if typeStrings, err := readStringPool(srTypes); err == nil { - tablePackage.TypeStrings = typeStrings - } else { - return nil, err - } - - srKeys := io.NewSectionReader(sr, int64(header.KeyStrings), int64(header.Header.Size-header.KeyStrings)) - if keyStrings, err := readStringPool(srKeys); err == nil { - tablePackage.KeyStrings = keyStrings - } else { - return nil, err - } - - offset := int64(header.Header.HeaderSize) - for offset < int64(header.Header.Size) { - chunkHeader := &ResChunkHeader{} - sr.Seek(offset, os.SEEK_SET) - if err := binary.Read(sr, binary.LittleEndian, chunkHeader); err != nil { - return nil, err - } - - var err error - chunkReader := io.NewSectionReader(sr, offset, int64(chunkHeader.Size)) - sr.Seek(offset, os.SEEK_SET) - switch chunkHeader.Type { - case RES_TABLE_TYPE_TYPE: - var tableType *TableType - tableType, err = readTableType(chunkHeader, chunkReader) - tablePackage.TableTypes = append(tablePackage.TableTypes, tableType) - case RES_TABLE_TYPE_SPEC_TYPE: - _, err = readTableTypeSpec(chunkReader) - } - if err != nil { - return nil, err - } - offset += int64(chunkHeader.Size) - } - - return tablePackage, nil -} - -func readTableType(chunkHeader *ResChunkHeader, sr *io.SectionReader) (*TableType, error) { - // TableType header may be omitted - header := new(ResTableType) - sr.Seek(0, os.SEEK_SET) - buf, err := newZeroFilledReader(sr, int64(chunkHeader.HeaderSize), int64(unsafe.Sizeof(*header))) - if err != nil { - return nil, err - } - if err := binary.Read(buf, binary.LittleEndian, header); err != nil { - return nil, err - } - - entryIndexes := make([]uint32, header.EntryCount) - sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET) - if err := binary.Read(sr, binary.LittleEndian, entryIndexes); err != nil { - return nil, err - } - - entries := make([]TableEntry, header.EntryCount) - for i, index := range entryIndexes { - if index == 0xFFFFFFFF { - continue - } - sr.Seek(int64(header.EntriesStart+index), os.SEEK_SET) - var key ResTableEntry - binary.Read(sr, binary.LittleEndian, &key) - entries[i].Key = &key - - var val ResValue - binary.Read(sr, binary.LittleEndian, &val) - entries[i].Value = &val - } - return &TableType{ - header, - entries, - }, nil -} - -func readTableTypeSpec(sr *io.SectionReader) ([]uint32, error) { - header := new(ResTableTypeSpec) - if err := binary.Read(sr, binary.LittleEndian, header); err != nil { - return nil, err - } - - flags := make([]uint32, header.EntryCount) - sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET) - if err := binary.Read(sr, binary.LittleEndian, flags); err != nil { - return nil, err - } - return flags, nil -} - -func (c *ResTableConfig) IsMoreSpecificThan(o *ResTableConfig) bool { - // imsi - if c.Mcc != o.Mcc { - if c.Mcc == 0 { - return false - } - if o.Mnc == 0 { - return true - } - } - if c.Mnc != o.Mnc { - if c.Mnc == 0 { - return false - } - if o.Mnc == 0 { - return true - } - } - - // locale - if c.Language[0] != o.Language[0] { - if c.Language[0] == 0 { - return false - } - if o.Language[0] == 0 { - return true - } - } - if c.Country[0] != o.Country[0] { - if c.Country[0] == 0 { - return false - } - if o.Country[0] == 0 { - return true - } - } - - // screen layout - if c.ScreenLayout != 0 || o.ScreenLayout != 0 { - if ((c.ScreenLayout ^ o.ScreenLayout) & MASK_LAYOUTDIR) != 0 { - if (c.ScreenLayout & MASK_LAYOUTDIR) == 0 { - return false - } - if (o.ScreenLayout & MASK_LAYOUTDIR) == 0 { - return true - } - } - } - - // smallest screen width dp - if c.SmallestScreenWidthDp != 0 || o.SmallestScreenWidthDp != 0 { - if c.SmallestScreenWidthDp != o.SmallestScreenWidthDp { - if c.SmallestScreenWidthDp == 0 { - return false - } - if o.SmallestScreenWidthDp == 0 { - return true - } - } - } - - // screen size dp - if c.ScreenWidthDp != 0 || o.ScreenWidthDp != 0 || - c.ScreenHeightDp != 0 || o.ScreenHeightDp != 0 { - if c.ScreenWidthDp != o.ScreenWidthDp { - if c.ScreenWidthDp == 0 { - return false - } - if o.ScreenWidthDp == 0 { - return true - } - } - if c.ScreenHeightDp != o.ScreenHeightDp { - if c.ScreenHeightDp == 0 { - return false - } - if o.ScreenHeightDp == 0 { - return true - } - } - } - - // screen layout - if c.ScreenLayout != 0 || o.ScreenLayout != 0 { - if ((c.ScreenLayout ^ o.ScreenLayout) & MASK_SCREENSIZE) != 0 { - if (c.ScreenLayout & MASK_SCREENSIZE) == 0 { - return false - } - if (o.ScreenLayout & MASK_SCREENSIZE) == 0 { - return true - } - } - if ((c.ScreenLayout ^ o.ScreenLayout) & MASK_SCREENLONG) != 0 { - if (c.ScreenLayout & MASK_SCREENLONG) == 0 { - return false - } - if (o.ScreenLayout & MASK_SCREENLONG) == 0 { - return true - } - } - } - - // orientation - if c.Orientation != o.Orientation { - if c.Orientation == 0 { - return false - } - if o.Orientation == 0 { - return true - } - } - - // uimode - if c.UIMode != 0 || o.UIMode != 0 { - diff := c.UIMode ^ o.UIMode - if (diff & MASK_UI_MODE_TYPE) != 0 { - if (c.UIMode & MASK_UI_MODE_TYPE) == 0 { - return false - } - if (o.UIMode & MASK_UI_MODE_TYPE) == 0 { - return true - } - } - if (diff & MASK_UI_MODE_NIGHT) != 0 { - if (c.UIMode & MASK_UI_MODE_NIGHT) == 0 { - return false - } - if (o.UIMode & MASK_UI_MODE_NIGHT) == 0 { - return true - } - } - } - - // touchscreen - if c.Touchscreen != o.Touchscreen { - if c.Touchscreen == 0 { - return false - } - if o.Touchscreen == 0 { - return true - } - } - - // input - if c.InputFlags != 0 || o.InputFlags != 0 { - myKeysHidden := c.InputFlags & MASK_KEYSHIDDEN - oKeysHidden := o.InputFlags & MASK_KEYSHIDDEN - if (myKeysHidden ^ oKeysHidden) != 0 { - if myKeysHidden == 0 { - return false - } - if oKeysHidden == 0 { - return true - } - } - myNavHidden := c.InputFlags & MASK_NAVHIDDEN - oNavHidden := o.InputFlags & MASK_NAVHIDDEN - if (myNavHidden ^ oNavHidden) != 0 { - if myNavHidden == 0 { - return false - } - if oNavHidden == 0 { - return true - } - } - } - - if c.Keyboard != o.Keyboard { - if c.Keyboard == 0 { - return false - } - if o.Keyboard == 0 { - return true - } - } - - if c.Navigation != o.Navigation { - if c.Navigation == 0 { - return false - } - if o.Navigation == 0 { - return true - } - } - - // screen size - if c.ScreenWidth != 0 || o.ScreenWidth != 0 || - c.ScreenHeight != 0 || o.ScreenHeight != 0 { - if c.ScreenWidth != o.ScreenWidth { - if c.ScreenWidth == 0 { - return false - } - if o.ScreenWidth == 0 { - return true - } - } - if c.ScreenHeight != o.ScreenHeight { - if c.ScreenHeight == 0 { - return false - } - if o.ScreenHeight == 0 { - return true - } - } - } - - //version - if c.SDKVersion != o.SDKVersion { - if c.SDKVersion == 0 { - return false - } - if o.SDKVersion == 0 { - return true - } - } - if c.MinorVersion != o.MinorVersion { - if c.MinorVersion == 0 { - return false - } - if o.MinorVersion == 0 { - return true - } - } - - return false -} - -func (c *ResTableConfig) IsBetterThan(o *ResTableConfig, r *ResTableConfig) bool { - if r == nil { - return c.IsMoreSpecificThan(o) - } - - // imsi - if c.Mcc != 0 || c.Mnc != 0 || o.Mcc != 0 || o.Mnc != 0 { - if c.Mcc != o.Mcc && r.Mcc != 0 { - return c.Mcc != 0 - } - if c.Mnc != o.Mnc && r.Mnc != 0 { - return c.Mnc != 0 - } - } - - // locale - if c.Language[0] != 0 || c.Country[0] != 0 || o.Language[0] != 0 || o.Country[0] != 0 { - if c.Language[0] != o.Language[0] && r.Language[0] != 0 { - return c.Language[0] != 0 - } - if c.Country[0] != o.Country[0] && r.Country[0] != 0 { - return c.Country[0] != 0 - } - } - - // screen layout - if c.ScreenLayout != 0 || o.ScreenLayout != 0 { - myLayoutdir := c.ScreenLayout & MASK_LAYOUTDIR - oLayoutdir := o.ScreenLayout & MASK_LAYOUTDIR - if (myLayoutdir^oLayoutdir) != 0 && (r.ScreenLayout&MASK_LAYOUTDIR) != 0 { - return myLayoutdir > oLayoutdir - } - } - - // smallest screen width dp - if c.SmallestScreenWidthDp != 0 || o.SmallestScreenWidthDp != 0 { - if c.SmallestScreenWidthDp != o.SmallestScreenWidthDp { - return c.SmallestScreenWidthDp > o.SmallestScreenWidthDp - } - } - - // screen size dp - if c.ScreenWidthDp != 0 || c.ScreenHeightDp != 0 || o.ScreenWidthDp != 0 || o.ScreenHeightDp != 0 { - myDelta := 0 - otherDelta := 0 - if r.ScreenWidthDp != 0 { - myDelta += int(r.ScreenWidthDp) - int(c.ScreenWidthDp) - otherDelta += int(r.ScreenWidthDp) - int(o.ScreenWidthDp) - } - if r.ScreenHeightDp != 0 { - myDelta += int(r.ScreenHeightDp) - int(c.ScreenHeightDp) - otherDelta += int(r.ScreenHeightDp) - int(o.ScreenHeightDp) - } - if myDelta != otherDelta { - return myDelta < otherDelta - } - } - - // screen layout - if c.ScreenLayout != 0 || o.ScreenLayout != 0 { - mySL := c.ScreenLayout & MASK_SCREENSIZE - oSL := o.ScreenLayout & MASK_SCREENSIZE - if (mySL^oSL) != 0 && (r.ScreenLayout&MASK_SCREENSIZE) != 0 { - fixedMySL := mySL - fixedOSL := oSL - if (r.ScreenLayout & MASK_SCREENSIZE) >= SCREENSIZE_NORMAL { - if fixedMySL == 0 { - fixedMySL = SCREENSIZE_NORMAL - } - if fixedOSL == 0 { - fixedOSL = SCREENSIZE_NORMAL - } - } - if fixedMySL == fixedOSL { - return mySL != 0 - } else { - return fixedMySL > fixedOSL - } - } - - if ((c.ScreenLayout^o.ScreenLayout)&MASK_SCREENLONG) != 0 && - (r.ScreenLayout&MASK_SCREENLONG) != 0 { - return (c.ScreenLayout & MASK_SCREENLONG) != 0 - } - } - - // orientation - if c.Orientation != o.Orientation && r.Orientation != 0 { - return c.Orientation != 0 - } - - // uimode - if c.UIMode != 0 || o.UIMode != 0 { - diff := c.UIMode ^ o.UIMode - if (diff&MASK_UI_MODE_TYPE) != 0 && (r.UIMode&MASK_UI_MODE_TYPE) != 0 { - return (c.UIMode & MASK_UI_MODE_TYPE) != 0 - } - if (diff&MASK_UI_MODE_NIGHT) != 0 && (r.UIMode&MASK_UI_MODE_NIGHT) != 0 { - return (c.UIMode & MASK_UI_MODE_NIGHT) != 0 - } - } - - // screen type - if c.Density != o.Density { - h := int(c.Density) - if h == 0 { - h = 160 - } - l := int(o.Density) - if l == 0 { - l = 160 - } - blmBigger := true - if l > h { - h, l = l, h - blmBigger = false - } - - reqValue := int(r.Density) - if reqValue == 0 { - reqValue = 160 - } - if reqValue >= h { - return blmBigger - } - if l >= reqValue { - return !blmBigger - } - if (2*l-reqValue)*h > reqValue*reqValue { - return !blmBigger - } else { - return blmBigger - } - } - if c.Touchscreen != o.Touchscreen && r.Touchscreen != 0 { - return c.Touchscreen != 0 - } - - // input - if c.InputFlags != 0 || o.InputFlags != 0 { - myKeysHidden := c.InputFlags & MASK_KEYSHIDDEN - oKeysHidden := o.InputFlags & MASK_KEYSHIDDEN - reqKeysHidden := r.InputFlags & MASK_KEYSHIDDEN - if myKeysHidden != oKeysHidden && reqKeysHidden != 0 { - switch { - case myKeysHidden == 0: - return false - case oKeysHidden == 0: - return true - case reqKeysHidden == myKeysHidden: - return true - case reqKeysHidden == oKeysHidden: - return false - } - } - myNavHidden := c.InputFlags & MASK_NAVHIDDEN - oNavHidden := o.InputFlags & MASK_NAVHIDDEN - reqNavHidden := r.InputFlags & MASK_NAVHIDDEN - if myNavHidden != oNavHidden && reqNavHidden != 0 { - switch { - case myNavHidden == 0: - return false - case oNavHidden == 0: - return true - } - } - } - if c.Keyboard != o.Keyboard && r.Keyboard != 0 { - return c.Keyboard != 0 - } - if c.Navigation != o.Navigation && r.Navigation != 0 { - return c.Navigation != 0 - } - - // screen size - if c.ScreenWidth != 0 || c.ScreenHeight != 0 || o.ScreenWidth != 0 || o.ScreenHeight != 0 { - myDelta := 0 - otherDelta := 0 - if r.ScreenWidth != 0 { - myDelta += int(r.ScreenWidth) - int(c.ScreenWidth) - otherDelta += int(r.ScreenWidth) - int(o.ScreenWidth) - } - if r.ScreenHeight != 0 { - myDelta += int(r.ScreenHeight) - int(c.ScreenHeight) - otherDelta += int(r.ScreenHeight) - int(o.ScreenHeight) - } - if myDelta != otherDelta { - return myDelta < otherDelta - } - } - - // version - if c.SDKVersion != 0 || c.SDKVersion != 0 || o.MinorVersion != 0 || o.MinorVersion != 0 { - if c.SDKVersion != o.SDKVersion && r.SDKVersion != 0 { - return c.SDKVersion > o.SDKVersion - } - if c.MinorVersion != o.MinorVersion && r.MinorVersion != 0 { - return c.MinorVersion != 0 - } - } - - return false -} - -func (c *ResTableConfig) Match(settings *ResTableConfig) bool { - // match imsi - if settings.Mcc == 0 { - if c.Mcc != 0 { - return false - } - } else { - if c.Mcc != 0 && c.Mcc != settings.Mcc { - return false - } - } - if settings.Mnc == 0 { - if c.Mnc != 0 { - return false - } - } else { - if c.Mnc != 0 && c.Mnc != settings.Mnc { - return false - } - } - - // match locale - if settings.Language[0] != 0 && c.Language[0] != 0 && - !(settings.Language[0] == c.Language[0] && settings.Language[1] == c.Language[1]) { - return false - } - if settings.Country[0] != 0 && c.Country[0] != 0 && - !(settings.Country[0] == c.Country[0] && settings.Country[1] == c.Country[1]) { - return false - } - - // screen layout - layoutDir := c.ScreenLayout & MASK_LAYOUTDIR - setLayoutDir := settings.ScreenLayout & MASK_LAYOUTDIR - if layoutDir != 0 && layoutDir != setLayoutDir { - return false - } - - screenSize := c.ScreenLayout & MASK_SCREENSIZE - setScreenSize := settings.ScreenLayout & MASK_SCREENSIZE - if screenSize != 0 && screenSize > setScreenSize { - return false - } - - screenLong := c.ScreenLayout & MASK_SCREENLONG - setScreenLong := settings.ScreenLayout & MASK_SCREENLONG - if screenLong != 0 && screenLong != setScreenLong { - return false - } - - // ui mode - uiModeType := c.UIMode & MASK_UI_MODE_TYPE - setUIModeType := settings.UIMode & MASK_UI_MODE_TYPE - if uiModeType != 0 && uiModeType != setUIModeType { - return false - } - - uiModeNight := c.UIMode & MASK_UI_MODE_NIGHT - setUIModeNight := settings.UIMode & MASK_UI_MODE_NIGHT - if uiModeNight != 0 && uiModeNight != setUIModeNight { - return false - } - - // smallest screen width dp - if c.SmallestScreenWidthDp != 0 && - c.SmallestScreenWidthDp > settings.SmallestScreenWidthDp { - return false - } - - // screen size dp - if c.ScreenWidthDp != 0 && - c.ScreenWidthDp > settings.ScreenWidthDp { - return false - } - if c.ScreenHeightDp != 0 && - c.ScreenHeightDp > settings.ScreenHeightDp { - return false - } - - // screen type - if c.Orientation != 0 && c.Orientation != settings.Orientation { - return false - } - if c.Touchscreen != 0 && c.Touchscreen != settings.Touchscreen { - return false - } - - // input - if c.InputFlags != 0 { - myKeysHidden := c.InputFlags & MASK_KEYSHIDDEN - oKeysHidden := settings.InputFlags & MASK_KEYSHIDDEN - if myKeysHidden != 0 && myKeysHidden != oKeysHidden { - if myKeysHidden != KEYSHIDDEN_NO || oKeysHidden != KEYSHIDDEN_SOFT { - return false - } - } - myNavHidden := c.InputFlags & MASK_NAVHIDDEN - oNavHidden := settings.InputFlags & MASK_NAVHIDDEN - if myNavHidden != 0 && myNavHidden != oNavHidden { - return false - } - } - if c.Keyboard != 0 && c.Keyboard != settings.Keyboard { - return false - } - if c.Navigation != 0 && c.Navigation != settings.Navigation { - return false - } - - // screen size - if c.ScreenWidth != 0 && - c.ScreenWidth > settings.ScreenWidth { - return false - } - if c.ScreenHeight != 0 && - c.ScreenHeight > settings.ScreenHeight { - return false - } - - // version - if settings.SDKVersion != 0 && c.SDKVersion != 0 && - c.SDKVersion > settings.SDKVersion { - return false - } - if settings.MinorVersion != 0 && c.MinorVersion != 0 && - c.MinorVersion != settings.MinorVersion { - return false - } - - return true -} - -func (c *ResTableConfig) Locale() string { - if c.Language[0] == 0 { - return "" - } - if c.Country[0] == 0 { - return fmt.Sprintf("%c%c", c.Language[0], c.Language[1]) - } - return fmt.Sprintf("%c%c-%c%c", c.Language[0], c.Language[1], c.Country[0], c.Country[1]) -} diff --git a/vendor/github.com/shogo82148/androidbinary/xml.go b/vendor/github.com/shogo82148/androidbinary/xml.go deleted file mode 100644 index b5aa745..0000000 --- a/vendor/github.com/shogo82148/androidbinary/xml.go +++ /dev/null @@ -1,237 +0,0 @@ -package androidbinary - -import ( - "bytes" - "encoding/binary" - "encoding/xml" - "fmt" - "io" - "os" -) - -type XMLFile struct { - stringPool *ResStringPool - resourceMap []uint32 - notPrecessedNS map[ResStringPoolRef]ResStringPoolRef - namespaces map[ResStringPoolRef]ResStringPoolRef - xmlBuffer bytes.Buffer -} - -type ResXMLTreeNode struct { - Header ResChunkHeader - LineNumber uint32 - Comment ResStringPoolRef -} - -type ResXMLTreeNamespaceExt struct { - Prefix ResStringPoolRef - Uri ResStringPoolRef -} - -type ResXMLTreeAttrExt struct { - NS ResStringPoolRef - Name ResStringPoolRef - AttributeStart uint16 - AttributeSize uint16 - AttributeCount uint16 - IdIndex uint16 - ClassIndex uint16 - StyleIndex uint16 -} - -type ResXMLTreeAttribute struct { - NS ResStringPoolRef - Name ResStringPoolRef - RawValue ResStringPoolRef - TypedValue ResValue -} - -type ResXMLTreeEndElementExt struct { - NS ResStringPoolRef - Name ResStringPoolRef -} - -func NewXMLFile(r io.ReaderAt) (*XMLFile, error) { - f := new(XMLFile) - sr := io.NewSectionReader(r, 0, 1<<63-1) - - fmt.Fprintf(&f.xmlBuffer, xml.Header) - - header := new(ResChunkHeader) - if err := binary.Read(sr, binary.LittleEndian, header); err != nil { - return nil, err - } - offset := int64(header.HeaderSize) - for offset < int64(header.Size) { - chunkHeader, err := f.readChunk(r, offset) - if err != nil { - return nil, err - } - offset += int64(chunkHeader.Size) - } - return f, nil -} - -func (f *XMLFile) Reader() *bytes.Reader { - return bytes.NewReader(f.xmlBuffer.Bytes()) -} - -func (f *XMLFile) readChunk(r io.ReaderAt, offset int64) (*ResChunkHeader, error) { - sr := io.NewSectionReader(r, offset, 1<<63-1-offset) - chunkHeader := &ResChunkHeader{} - sr.Seek(0, os.SEEK_SET) - if err := binary.Read(sr, binary.LittleEndian, chunkHeader); err != nil { - return nil, err - } - - var err error - sr.Seek(0, os.SEEK_SET) - switch chunkHeader.Type { - case RES_STRING_POOL_TYPE: - f.stringPool, err = readStringPool(sr) - case RES_XML_START_NAMESPACE_TYPE: - err = f.readStartNamespace(sr) - case RES_XML_END_NAMESPACE_TYPE: - err = f.readEndNamespace(sr) - case RES_XML_START_ELEMENT_TYPE: - err = f.readStartElement(sr) - case RES_XML_END_ELEMENT_TYPE: - err = f.readEndElement(sr) - } - if err != nil { - return nil, err - } - - return chunkHeader, nil -} - -func (f *XMLFile) GetString(ref ResStringPoolRef) string { - return f.stringPool.GetString(ref) -} - -func (f *XMLFile) readStartNamespace(sr *io.SectionReader) error { - header := new(ResXMLTreeNode) - if err := binary.Read(sr, binary.LittleEndian, header); err != nil { - return err - } - - sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET) - namespace := new(ResXMLTreeNamespaceExt) - if err := binary.Read(sr, binary.LittleEndian, namespace); err != nil { - return err - } - - if f.notPrecessedNS == nil { - f.notPrecessedNS = make(map[ResStringPoolRef]ResStringPoolRef) - } - f.notPrecessedNS[namespace.Uri] = namespace.Prefix - - if f.namespaces == nil { - f.namespaces = make(map[ResStringPoolRef]ResStringPoolRef) - } - f.namespaces[namespace.Uri] = namespace.Prefix - - return nil -} - -func (f *XMLFile) readEndNamespace(sr *io.SectionReader) error { - header := new(ResXMLTreeNode) - if err := binary.Read(sr, binary.LittleEndian, header); err != nil { - return err - } - - sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET) - namespace := new(ResXMLTreeNamespaceExt) - if err := binary.Read(sr, binary.LittleEndian, namespace); err != nil { - return err - } - delete(f.namespaces, namespace.Uri) - return nil -} - -func (f *XMLFile) addNamespacePrefix(ns, name ResStringPoolRef) string { - if ns != NilResStringPoolRef { - prefix := f.GetString(f.namespaces[ns]) - return fmt.Sprintf("%s:%s", prefix, f.GetString(name)) - } - return f.GetString(name) -} - -func (f *XMLFile) readStartElement(sr *io.SectionReader) error { - header := new(ResXMLTreeNode) - if err := binary.Read(sr, binary.LittleEndian, header); err != nil { - return err - } - - sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET) - ext := new(ResXMLTreeAttrExt) - if err := binary.Read(sr, binary.LittleEndian, ext); err != nil { - return nil - } - - fmt.Fprintf(&f.xmlBuffer, "<%s", f.addNamespacePrefix(ext.NS, ext.Name)) - - // output XML namespaces - if f.notPrecessedNS != nil { - for uri, prefix := range f.notPrecessedNS { - fmt.Fprintf(&f.xmlBuffer, " xmlns:%s=\"", f.GetString(prefix)) - xml.Escape(&f.xmlBuffer, []byte(f.GetString(uri))) - fmt.Fprint(&f.xmlBuffer, "\"") - } - f.notPrecessedNS = nil - } - - // process attributes - offset := int64(ext.AttributeStart + header.Header.HeaderSize) - for i := 0; i < int(ext.AttributeCount); i++ { - sr.Seek(offset, os.SEEK_SET) - attr := new(ResXMLTreeAttribute) - binary.Read(sr, binary.LittleEndian, attr) - - var value string - if attr.RawValue != NilResStringPoolRef { - value = f.GetString(attr.RawValue) - } else { - data := attr.TypedValue.Data - switch attr.TypedValue.DataType { - case TYPE_NULL: - value = "" - case TYPE_REFERENCE: - value = fmt.Sprintf("@0x%08X", data) - case TYPE_INT_DEC: - value = fmt.Sprintf("%d", data) - case TYPE_INT_HEX: - value = fmt.Sprintf("0x%08X", data) - case TYPE_INT_BOOLEAN: - if data != 0 { - value = "true" - } else { - value = "false" - } - default: - value = fmt.Sprintf("@0x%08X", data) - } - } - - fmt.Fprintf(&f.xmlBuffer, " %s=\"", f.addNamespacePrefix(attr.NS, attr.Name)) - xml.Escape(&f.xmlBuffer, []byte(value)) - fmt.Fprint(&f.xmlBuffer, "\"") - offset += int64(ext.AttributeSize) - } - fmt.Fprint(&f.xmlBuffer, ">") - return nil -} - -func (f *XMLFile) readEndElement(sr *io.SectionReader) error { - header := new(ResXMLTreeNode) - if err := binary.Read(sr, binary.LittleEndian, header); err != nil { - return err - } - sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET) - ext := new(ResXMLTreeEndElementExt) - if err := binary.Read(sr, binary.LittleEndian, ext); err != nil { - return err - } - fmt.Fprintf(&f.xmlBuffer, "", f.addNamespacePrefix(ext.NS, ext.Name)) - return nil -}