common.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. package android_binary
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "io"
  6. "unicode/utf16"
  7. )
  8. // ChunkType is a type of a resource chunk.
  9. type ChunkType uint16
  10. // Chunk types.
  11. const (
  12. ResNullChunkType ChunkType = 0x0000
  13. ResStringPoolChunkType ChunkType = 0x0001
  14. ResTableChunkType ChunkType = 0x0002
  15. ResXMLChunkType ChunkType = 0x0003
  16. // Chunk types in RES_XML_TYPE
  17. ResXMLFirstChunkType ChunkType = 0x0100
  18. ResXMLStartNamespaceType ChunkType = 0x0100
  19. ResXMLEndNamespaceType ChunkType = 0x0101
  20. ResXMLStartElementType ChunkType = 0x0102
  21. ResXMLEndElementType ChunkType = 0x0103
  22. ResXMLCDataType ChunkType = 0x0104
  23. ResXMLLastChunkType ChunkType = 0x017f
  24. // This contains a uint32_t array mapping strings in the string
  25. // pool back to resource identifiers. It is optional.
  26. ResXMLResourceMapType ChunkType = 0x0180
  27. // Chunk types in RES_TABLE_TYPE
  28. ResTablePackageType ChunkType = 0x0200
  29. ResTableTypeType ChunkType = 0x0201
  30. ResTableTypeSpecType ChunkType = 0x0202
  31. )
  32. // ResChunkHeader is a header of a resource chunk.
  33. type ResChunkHeader struct {
  34. Type ChunkType
  35. HeaderSize uint16
  36. Size uint32
  37. }
  38. // Flags are flags for string pool header.
  39. type Flags uint32
  40. // the values of Flags.
  41. const (
  42. SortedFlag Flags = 1 << 0
  43. UTF8Flag Flags = 1 << 8
  44. )
  45. // ResStringPoolHeader is a chunk header of string pool.
  46. type ResStringPoolHeader struct {
  47. Header ResChunkHeader
  48. StringCount uint32
  49. StyleCount uint32
  50. Flags Flags
  51. StringStart uint32
  52. StylesStart uint32
  53. }
  54. // ResStringPoolSpan is a span of style information associated with
  55. // a string in the pool.
  56. type ResStringPoolSpan struct {
  57. FirstChar, LastChar uint32
  58. }
  59. // ResStringPool is a string pool resource.
  60. type ResStringPool struct {
  61. Header ResStringPoolHeader
  62. Strings []string
  63. Styles []ResStringPoolSpan
  64. }
  65. // NilResStringPoolRef is nil reference for string pool.
  66. const NilResStringPoolRef = ResStringPoolRef(0xFFFFFFFF)
  67. // ResStringPoolRef is a type representing a reference to a string.
  68. type ResStringPoolRef uint32
  69. // DataType is a type of the data value.
  70. type DataType uint8
  71. // The constants for DataType
  72. const (
  73. TypeNull DataType = 0x00
  74. TypeReference DataType = 0x01
  75. TypeAttribute DataType = 0x02
  76. TypeString DataType = 0x03
  77. TypeFloat DataType = 0x04
  78. TypeDemention DataType = 0x05
  79. TypeFraction DataType = 0x06
  80. TypeFirstInt DataType = 0x10
  81. TypeIntDec DataType = 0x10
  82. TypeIntHex DataType = 0x11
  83. TypeIntBoolean DataType = 0x12
  84. TypeFirstColorInt DataType = 0x1c
  85. TypeIntColorARGB8 DataType = 0x1c
  86. TypeIntColorRGB8 DataType = 0x1d
  87. TypeIntColorARGB4 DataType = 0x1e
  88. TypeIntColorRGB4 DataType = 0x1f
  89. TypeLastColorInt DataType = 0x1f
  90. TypeLastInt DataType = 0x1f
  91. )
  92. // ResValue is a representation of a value in a resource
  93. type ResValue struct {
  94. Size uint16
  95. Res0 uint8
  96. DataType DataType
  97. Data uint32
  98. }
  99. // GetString returns a string referenced by ref.
  100. func (pool *ResStringPool) GetString(ref ResStringPoolRef) string {
  101. return pool.Strings[int(ref)]
  102. }
  103. func readStringPool(sr *io.SectionReader) (*ResStringPool, error) {
  104. sp := new(ResStringPool)
  105. if err := binary.Read(sr, binary.LittleEndian, &sp.Header); err != nil {
  106. return nil, err
  107. }
  108. stringStarts := make([]uint32, sp.Header.StringCount)
  109. if err := binary.Read(sr, binary.LittleEndian, stringStarts); err != nil {
  110. return nil, err
  111. }
  112. styleStarts := make([]uint32, sp.Header.StyleCount)
  113. if err := binary.Read(sr, binary.LittleEndian, styleStarts); err != nil {
  114. return nil, err
  115. }
  116. sp.Strings = make([]string, sp.Header.StringCount)
  117. for i, start := range stringStarts {
  118. var str string
  119. var err error
  120. if _, err := sr.Seek(int64(sp.Header.StringStart+start), io.SeekStart); err != nil {
  121. return nil, err
  122. }
  123. if (sp.Header.Flags & UTF8Flag) == 0 {
  124. str, err = readUTF16(sr)
  125. } else {
  126. str, err = readUTF8(sr)
  127. }
  128. if err != nil {
  129. return nil, err
  130. }
  131. sp.Strings[i] = str
  132. }
  133. sp.Styles = make([]ResStringPoolSpan, sp.Header.StyleCount)
  134. for i, start := range styleStarts {
  135. if _, err := sr.Seek(int64(sp.Header.StylesStart+start), io.SeekStart); err != nil {
  136. return nil, err
  137. }
  138. if err := binary.Read(sr, binary.LittleEndian, &sp.Styles[i]); err != nil {
  139. return nil, err
  140. }
  141. }
  142. return sp, nil
  143. }
  144. func readUTF16(sr *io.SectionReader) (string, error) {
  145. // read length of string
  146. size, err := readUTF16length(sr)
  147. if err != nil {
  148. return "", err
  149. }
  150. // read string value
  151. buf := make([]uint16, size)
  152. if err := binary.Read(sr, binary.LittleEndian, buf); err != nil {
  153. return "", err
  154. }
  155. return string(utf16.Decode(buf)), nil
  156. }
  157. func readUTF16length(sr *io.SectionReader) (int, error) {
  158. var size int
  159. var first, second uint16
  160. if err := binary.Read(sr, binary.LittleEndian, &first); err != nil {
  161. return 0, err
  162. }
  163. if (first & 0x8000) != 0 {
  164. if err := binary.Read(sr, binary.LittleEndian, &second); err != nil {
  165. return 0, err
  166. }
  167. size = (int(first&0x7FFF) << 16) + int(second)
  168. } else {
  169. size = int(first)
  170. }
  171. return size, nil
  172. }
  173. func readUTF8(sr *io.SectionReader) (string, error) {
  174. // skip utf16 length
  175. _, err := readUTF8length(sr)
  176. if err != nil {
  177. return "", err
  178. }
  179. // read lenth of string
  180. size, err := readUTF8length(sr)
  181. if err != nil {
  182. return "", err
  183. }
  184. buf := make([]uint8, size)
  185. if err := binary.Read(sr, binary.LittleEndian, buf); err != nil {
  186. return "", err
  187. }
  188. return string(buf), nil
  189. }
  190. func readUTF8length(sr *io.SectionReader) (int, error) {
  191. var size int
  192. var first, second uint8
  193. if err := binary.Read(sr, binary.LittleEndian, &first); err != nil {
  194. return 0, err
  195. }
  196. if (first & 0x80) != 0 {
  197. if err := binary.Read(sr, binary.LittleEndian, &second); err != nil {
  198. return 0, err
  199. }
  200. size = (int(first&0x7F) << 8) + int(second)
  201. } else {
  202. size = int(first)
  203. }
  204. return size, nil
  205. }
  206. func newZeroFilledReader(r io.Reader, actual int64, expected int64) (io.Reader, error) {
  207. if actual >= expected {
  208. // no need to fill
  209. return r, nil
  210. }
  211. // read `actual' bytes from r, and
  212. buf := new(bytes.Buffer)
  213. if _, err := io.CopyN(buf, r, actual); err != nil {
  214. return nil, err
  215. }
  216. // fill zero until `expected' bytes
  217. for i := actual; i < expected; i++ {
  218. if err := buf.WriteByte(0x00); err != nil {
  219. return nil, err
  220. }
  221. }
  222. return buf, nil
  223. }