binres.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:generate go run genarsc.go
  5. //go:generate stringer -output binres_string.go -type ResType,DataType
  6. // Package binres implements encoding and decoding of android binary resources.
  7. //
  8. // Binary resource structs support unmarshalling the binary output of aapt.
  9. // Implementations of marshalling for each struct must produce the exact input
  10. // sent to unmarshalling. This allows tests to validate each struct representation
  11. // of the binary format as follows:
  12. //
  13. // - unmarshal the output of aapt
  14. // - marshal the struct representation
  15. // - perform byte-to-byte comparison with aapt output per chunk header and body
  16. //
  17. // This process should strive to make structs idiomatic to make parsing xml text
  18. // into structs trivial.
  19. //
  20. // Once the struct representation is validated, tests for parsing xml text
  21. // into structs can become self-referential as the following holds true:
  22. //
  23. // - the unmarshalled input of aapt output is the only valid target
  24. // - the unmarshalled input of xml text may be compared to the unmarshalled
  25. // input of aapt output to identify errors, e.g. text-trims, wrong flags, etc
  26. //
  27. // This provides validation, byte-for-byte, for producing binary xml resources.
  28. //
  29. // It should be made clear that unmarshalling binary resources is currently only
  30. // in scope for proving that the BinaryMarshaler works correctly. Any other use
  31. // is currently out of scope.
  32. //
  33. // A simple view of binary xml document structure:
  34. //
  35. // XML
  36. // Pool
  37. // Map
  38. // Namespace
  39. // [...node]
  40. //
  41. // Additional resources:
  42. // https://android.googlesource.com/platform/frameworks/base/+/master/libs/androidfw/include/androidfw/ResourceTypes.h
  43. // https://justanapplication.wordpress.com/2011/09/13/ (a series of articles, increment date)
  44. package binres
  45. import (
  46. "encoding"
  47. "encoding/binary"
  48. "encoding/xml"
  49. "fmt"
  50. "io"
  51. "sort"
  52. "strconv"
  53. "strings"
  54. "unicode"
  55. )
  56. func errWrongType(have ResType, want ...ResType) error {
  57. return fmt.Errorf("wrong resource type %s, want one of %v", have, want)
  58. }
  59. type ResType uint16
  60. func (t ResType) IsSupported() bool {
  61. return t != ResNull
  62. }
  63. // explicitly defined for clarity and resolvability with apt source
  64. const (
  65. ResNull ResType = 0x0000
  66. ResStringPool ResType = 0x0001
  67. ResTable ResType = 0x0002
  68. ResXML ResType = 0x0003
  69. ResXMLStartNamespace ResType = 0x0100
  70. ResXMLEndNamespace ResType = 0x0101
  71. ResXMLStartElement ResType = 0x0102
  72. ResXMLEndElement ResType = 0x0103
  73. ResXMLCharData ResType = 0x0104
  74. ResXMLResourceMap ResType = 0x0180
  75. ResTablePackage ResType = 0x0200
  76. ResTableType ResType = 0x0201
  77. ResTableTypeSpec ResType = 0x0202
  78. ResTableLibrary ResType = 0x0203
  79. ResTableOverlayable ResType = 0x0204
  80. ResTableOverlayablePolicy ResType = 0x0205
  81. ResTableStagedAlias ResType = 0x0206
  82. )
  83. var (
  84. btou16 = binary.LittleEndian.Uint16
  85. btou32 = binary.LittleEndian.Uint32
  86. putu16 = binary.LittleEndian.PutUint16
  87. putu32 = binary.LittleEndian.PutUint32
  88. )
  89. // unmarshaler wraps BinaryUnmarshaler to provide byte size of decoded chunks.
  90. type unmarshaler interface {
  91. encoding.BinaryUnmarshaler
  92. // size returns the byte size unmarshalled after a call to
  93. // UnmarshalBinary, or otherwise zero.
  94. size() int
  95. }
  96. // chunkHeader appears at the front of every data chunk in a resource.
  97. type chunkHeader struct {
  98. // Type of data that follows this header.
  99. typ ResType
  100. // Advance slice index by this value to find its associated data, if any.
  101. headerByteSize uint16
  102. // This is the header size plus the size of any data associated with the chunk.
  103. // Advance slice index by this value to completely skip its contents, including
  104. // any child chunks. If this value is the same as headerByteSize, there is
  105. // no data associated with the chunk.
  106. byteSize uint32
  107. }
  108. // size implements unmarshaler.
  109. func (hdr chunkHeader) size() int { return int(hdr.byteSize) }
  110. func (hdr *chunkHeader) UnmarshalBinary(bin []byte) error {
  111. hdr.typ = ResType(btou16(bin))
  112. if !hdr.typ.IsSupported() {
  113. return fmt.Errorf("%s not supported", hdr.typ)
  114. }
  115. hdr.headerByteSize = btou16(bin[2:])
  116. hdr.byteSize = btou32(bin[4:])
  117. if len(bin) < int(hdr.byteSize) {
  118. return fmt.Errorf("too few bytes to unmarshal chunk body, have %v, need at-least %v", len(bin), hdr.byteSize)
  119. }
  120. return nil
  121. }
  122. func (hdr chunkHeader) MarshalBinary() ([]byte, error) {
  123. if !hdr.typ.IsSupported() {
  124. return nil, fmt.Errorf("%s not supported", hdr.typ)
  125. }
  126. bin := make([]byte, 8)
  127. putu16(bin, uint16(hdr.typ))
  128. putu16(bin[2:], hdr.headerByteSize)
  129. putu32(bin[4:], hdr.byteSize)
  130. return bin, nil
  131. }
  132. type XML struct {
  133. chunkHeader
  134. Pool *Pool
  135. Map *Map
  136. Namespace *Namespace
  137. Children []*Element
  138. // tmp field used when unmarshalling binary
  139. stack []*Element
  140. }
  141. // RawValueByName returns the original raw string value of first matching element attribute, or error if not exists.
  142. // Given <manifest package="VAL" ...> then RawValueByName("manifest", xml.Name{Local: "package"}) returns "VAL".
  143. func (bx *XML) RawValueByName(elname string, attrname xml.Name) (string, error) {
  144. elref, err := bx.Pool.RefByName(elname)
  145. if err != nil {
  146. return "", err
  147. }
  148. nref, err := bx.Pool.RefByName(attrname.Local)
  149. if err != nil {
  150. return "", err
  151. }
  152. nsref := PoolRef(NoEntry)
  153. if attrname.Space != "" {
  154. nsref, err = bx.Pool.RefByName(attrname.Space)
  155. if err != nil {
  156. return "", err
  157. }
  158. }
  159. for el := range bx.iterElements() {
  160. if el.Name == elref {
  161. for _, attr := range el.attrs {
  162. // TODO enforce TypedValue DataString constraint?
  163. if nsref == attr.NS && nref == attr.Name {
  164. return bx.Pool.strings[int(attr.RawValue)], nil
  165. }
  166. }
  167. }
  168. }
  169. return "", fmt.Errorf("no matching element %q for attribute %+v found", elname, attrname)
  170. }
  171. const (
  172. androidSchema = "http://schemas.android.com/apk/res/android"
  173. toolsSchema = "http://schemas.android.com/tools"
  174. )
  175. // skipSynthesize is set true for tests to avoid synthesis of additional nodes and attributes.
  176. var skipSynthesize bool
  177. // UnmarshalXML decodes an AndroidManifest.xml document returning type XML
  178. // containing decoded resources.
  179. func UnmarshalXML(r io.Reader, withIcon bool) (*XML, error) {
  180. tbl, err := OpenTable()
  181. if err != nil {
  182. return nil, err
  183. }
  184. lr := &lineReader{r: r}
  185. dec := xml.NewDecoder(lr)
  186. bx := new(XML)
  187. // temporary pool to resolve real poolref later
  188. pool := new(Pool)
  189. type ltoken struct {
  190. xml.Token
  191. line int
  192. }
  193. var q []ltoken
  194. for {
  195. line := lr.line(dec.InputOffset())
  196. tkn, err := dec.Token()
  197. if err != nil {
  198. if err == io.EOF {
  199. break
  200. }
  201. return nil, err
  202. }
  203. tkn = xml.CopyToken(tkn)
  204. switch tkn := tkn.(type) {
  205. case xml.StartElement:
  206. switch tkn.Name.Local {
  207. default:
  208. q = append(q, ltoken{tkn, line})
  209. case "uses-sdk":
  210. return nil, fmt.Errorf("manual declaration of uses-sdk in AndroidManifest.xml not supported")
  211. case "manifest":
  212. // synthesize additional attributes and nodes for use during encode.
  213. tkn.Attr = append(tkn.Attr,
  214. xml.Attr{
  215. Name: xml.Name{
  216. Space: "",
  217. Local: "platformBuildVersionCode",
  218. },
  219. Value: "16",
  220. },
  221. xml.Attr{
  222. Name: xml.Name{
  223. Space: "",
  224. Local: "platformBuildVersionName",
  225. },
  226. Value: "4.1.2-1425332",
  227. })
  228. q = append(q, ltoken{tkn, line})
  229. if !skipSynthesize {
  230. s := xml.StartElement{
  231. Name: xml.Name{
  232. Space: "",
  233. Local: "uses-sdk",
  234. },
  235. Attr: []xml.Attr{
  236. xml.Attr{
  237. Name: xml.Name{
  238. Space: androidSchema,
  239. Local: "minSdkVersion",
  240. },
  241. Value: fmt.Sprintf("%v", MinSDK),
  242. },
  243. },
  244. }
  245. e := xml.EndElement{Name: xml.Name{Local: "uses-sdk"}}
  246. q = append(q, ltoken{s, line}, ltoken{e, line})
  247. }
  248. case "application":
  249. if !skipSynthesize {
  250. for _, attr := range tkn.Attr {
  251. if attr.Name.Space == androidSchema && attr.Name.Local == "icon" {
  252. return nil, fmt.Errorf("manual declaration of android:icon in AndroidManifest.xml not supported")
  253. }
  254. }
  255. if withIcon {
  256. tkn.Attr = append(tkn.Attr,
  257. xml.Attr{
  258. Name: xml.Name{
  259. Space: androidSchema,
  260. Local: "icon",
  261. },
  262. Value: "@mipmap/icon",
  263. })
  264. }
  265. }
  266. q = append(q, ltoken{tkn, line})
  267. }
  268. default:
  269. q = append(q, ltoken{tkn, line})
  270. }
  271. }
  272. for _, ltkn := range q {
  273. tkn, line := ltkn.Token, ltkn.line
  274. switch tkn := tkn.(type) {
  275. case xml.StartElement:
  276. el := &Element{
  277. NodeHeader: NodeHeader{
  278. LineNumber: uint32(line),
  279. Comment: 0xFFFFFFFF,
  280. },
  281. NS: NoEntry,
  282. Name: pool.ref(tkn.Name.Local),
  283. }
  284. if len(bx.stack) == 0 {
  285. bx.Children = append(bx.Children, el)
  286. } else {
  287. n := len(bx.stack)
  288. var p *Element
  289. p, bx.stack = bx.stack[n-1], bx.stack[:n-1]
  290. p.Children = append(p.Children, el)
  291. bx.stack = append(bx.stack, p)
  292. }
  293. bx.stack = append(bx.stack, el)
  294. for _, attr := range tkn.Attr {
  295. if (attr.Name.Space == "xmlns" && attr.Name.Local == "tools") || attr.Name.Space == toolsSchema {
  296. continue // TODO can tbl be queried for schemas to determine validity instead?
  297. }
  298. if attr.Name.Space == "xmlns" && attr.Name.Local == "android" {
  299. if bx.Namespace != nil {
  300. return nil, fmt.Errorf("multiple declarations of xmlns:android encountered")
  301. }
  302. bx.Namespace = &Namespace{
  303. NodeHeader: NodeHeader{
  304. LineNumber: uint32(line),
  305. Comment: NoEntry,
  306. },
  307. prefix: 0,
  308. uri: 0,
  309. }
  310. continue
  311. }
  312. nattr := &Attribute{
  313. NS: pool.ref(attr.Name.Space),
  314. Name: pool.ref(attr.Name.Local),
  315. RawValue: NoEntry,
  316. }
  317. el.attrs = append(el.attrs, nattr)
  318. if attr.Name.Space == "" {
  319. nattr.NS = NoEntry
  320. // TODO it's unclear how to query these
  321. switch attr.Name.Local {
  322. case "platformBuildVersionCode":
  323. nattr.TypedValue.Type = DataIntDec
  324. i, err := strconv.Atoi(attr.Value)
  325. if err != nil {
  326. return nil, err
  327. }
  328. nattr.TypedValue.Value = uint32(i)
  329. default: // "package", "platformBuildVersionName", and any invalid
  330. nattr.RawValue = pool.ref(attr.Value)
  331. nattr.TypedValue.Type = DataString
  332. }
  333. } else {
  334. // get type spec and value data type
  335. ref, err := tbl.RefByName("attr/" + attr.Name.Local)
  336. if err != nil {
  337. return nil, err
  338. }
  339. nt, err := ref.Resolve(tbl)
  340. if err != nil {
  341. return nil, err
  342. }
  343. if len(nt.values) == 0 {
  344. panic("encountered empty values slice")
  345. }
  346. if len(nt.values) == 1 {
  347. val := nt.values[0]
  348. if val.data.Type != DataIntDec {
  349. panic("TODO only know how to handle DataIntDec type here")
  350. }
  351. t := DataType(val.data.Value)
  352. switch t {
  353. case DataString, DataAttribute, DataType(0x3e):
  354. // TODO identify 0x3e, in bootstrap.xml this is the native lib name
  355. nattr.RawValue = pool.ref(attr.Value)
  356. nattr.TypedValue.Type = DataString
  357. nattr.TypedValue.Value = uint32(nattr.RawValue)
  358. case DataIntBool, DataType(0x08):
  359. nattr.TypedValue.Type = DataIntBool
  360. switch attr.Value {
  361. case "true":
  362. nattr.TypedValue.Value = 0xFFFFFFFF
  363. case "false":
  364. nattr.TypedValue.Value = 0
  365. default:
  366. return nil, fmt.Errorf("invalid bool value %q", attr.Value)
  367. }
  368. case DataIntDec, DataFloat, DataFraction:
  369. // TODO DataFraction needs it's own case statement. minSdkVersion identifies as DataFraction
  370. // but has accepted input in the past such as android:minSdkVersion="L"
  371. // Other use-cases for DataFraction are currently unknown as applicable to manifest generation
  372. // but this provides minimum support for writing out minSdkVersion="15" correctly.
  373. nattr.TypedValue.Type = DataIntDec
  374. i, err := strconv.Atoi(attr.Value)
  375. if err != nil {
  376. return nil, err
  377. }
  378. nattr.TypedValue.Value = uint32(i)
  379. case DataReference:
  380. nattr.TypedValue.Type = DataReference
  381. dref, err := tbl.RefByName(attr.Value)
  382. if err != nil {
  383. if strings.HasPrefix(attr.Value, "@mipmap") {
  384. // firstDrawableId is a TableRef matching first entry of mipmap spec initialized by NewMipmapTable.
  385. // 7f is default package, 02 is mipmap spec, 0000 is first entry; e.g. R.drawable.icon
  386. // TODO resource table should generate ids as required.
  387. const firstDrawableId = 0x7f020000
  388. nattr.TypedValue.Value = firstDrawableId
  389. continue
  390. }
  391. return nil, err
  392. }
  393. nattr.TypedValue.Value = uint32(dref)
  394. default:
  395. return nil, fmt.Errorf("unhandled data type %0#2x: %s", uint8(t), t)
  396. }
  397. } else {
  398. // 0x01000000 is an unknown ref that doesn't point to anything, typically
  399. // located at the start of entry value lists, peek at last value to determine type.
  400. t := nt.values[len(nt.values)-1].data.Type
  401. switch t {
  402. case DataIntDec:
  403. for _, val := range nt.values {
  404. if val.name == 0x01000000 {
  405. continue
  406. }
  407. nr, err := val.name.Resolve(tbl)
  408. if err != nil {
  409. return nil, err
  410. }
  411. if attr.Value == nr.key.Resolve(tbl.pkgs[0].keyPool) { // TODO hard-coded pkg ref
  412. nattr.TypedValue = *val.data
  413. break
  414. }
  415. }
  416. case DataIntHex:
  417. nattr.TypedValue.Type = t
  418. for _, x := range strings.Split(attr.Value, "|") {
  419. for _, val := range nt.values {
  420. if val.name == 0x01000000 {
  421. continue
  422. }
  423. nr, err := val.name.Resolve(tbl)
  424. if err != nil {
  425. return nil, err
  426. }
  427. if x == nr.key.Resolve(tbl.pkgs[0].keyPool) { // TODO hard-coded pkg ref
  428. nattr.TypedValue.Value |= val.data.Value
  429. break
  430. }
  431. }
  432. }
  433. default:
  434. return nil, fmt.Errorf("unhandled data type for configuration %0#2x: %s", uint8(t), t)
  435. }
  436. }
  437. }
  438. }
  439. case xml.CharData:
  440. if s := poolTrim(string(tkn)); s != "" {
  441. cdt := &CharData{
  442. NodeHeader: NodeHeader{
  443. LineNumber: uint32(line),
  444. Comment: NoEntry,
  445. },
  446. RawData: pool.ref(s),
  447. }
  448. el := bx.stack[len(bx.stack)-1]
  449. if el.head == nil {
  450. el.head = cdt
  451. } else if el.tail == nil {
  452. el.tail = cdt
  453. } else {
  454. return nil, fmt.Errorf("element head and tail already contain chardata")
  455. }
  456. }
  457. case xml.EndElement:
  458. if tkn.Name.Local == "manifest" {
  459. bx.Namespace.end = &Namespace{
  460. NodeHeader: NodeHeader{
  461. LineNumber: uint32(line),
  462. Comment: NoEntry,
  463. },
  464. prefix: 0,
  465. uri: 0,
  466. }
  467. }
  468. n := len(bx.stack)
  469. var el *Element
  470. el, bx.stack = bx.stack[n-1], bx.stack[:n-1]
  471. if el.end != nil {
  472. return nil, fmt.Errorf("element end already exists")
  473. }
  474. el.end = &ElementEnd{
  475. NodeHeader: NodeHeader{
  476. LineNumber: uint32(line),
  477. Comment: NoEntry,
  478. },
  479. NS: el.NS,
  480. Name: el.Name,
  481. }
  482. case xml.Comment, xml.ProcInst:
  483. // discard
  484. default:
  485. panic(fmt.Errorf("unhandled token type: %T %+v", tkn, tkn))
  486. }
  487. }
  488. // pools appear to be sorted as follows:
  489. // * attribute names prefixed with android:
  490. // * "android", [schema-url], [empty-string]
  491. // * for each node:
  492. // * attribute names with no prefix
  493. // * node name
  494. // * attribute value if data type of name is DataString, DataAttribute, or 0x3e (an unknown)
  495. bx.Pool = new(Pool)
  496. var arecurse func(*Element)
  497. arecurse = func(el *Element) {
  498. for _, attr := range el.attrs {
  499. if attr.NS == NoEntry {
  500. continue
  501. }
  502. if attr.NS.Resolve(pool) == androidSchema {
  503. bx.Pool.strings = append(bx.Pool.strings, attr.Name.Resolve(pool))
  504. }
  505. }
  506. for _, child := range el.Children {
  507. arecurse(child)
  508. }
  509. }
  510. for _, el := range bx.Children {
  511. arecurse(el)
  512. }
  513. // TODO encoding/xml does not enforce namespace prefix and manifest encoding in aapt
  514. // appears to ignore all other prefixes. Inserting this manually is not strictly correct
  515. // for the general case, but the effort to do otherwise currently offers nothing.
  516. bx.Pool.strings = append(bx.Pool.strings, "android", androidSchema)
  517. // there always appears to be an empty string located after schema, even if one is
  518. // not present in manifest.
  519. bx.Pool.strings = append(bx.Pool.strings, "")
  520. var brecurse func(*Element)
  521. brecurse = func(el *Element) {
  522. for _, attr := range el.attrs {
  523. if attr.NS == NoEntry {
  524. bx.Pool.strings = append(bx.Pool.strings, attr.Name.Resolve(pool))
  525. }
  526. }
  527. bx.Pool.strings = append(bx.Pool.strings, el.Name.Resolve(pool))
  528. for _, attr := range el.attrs {
  529. if attr.RawValue != NoEntry {
  530. bx.Pool.strings = append(bx.Pool.strings, attr.RawValue.Resolve(pool))
  531. } else if attr.NS == NoEntry {
  532. bx.Pool.strings = append(bx.Pool.strings, fmt.Sprintf("%+v", attr.TypedValue.Value))
  533. }
  534. }
  535. if el.head != nil {
  536. bx.Pool.strings = append(bx.Pool.strings, el.head.RawData.Resolve(pool))
  537. }
  538. if el.tail != nil {
  539. bx.Pool.strings = append(bx.Pool.strings, el.tail.RawData.Resolve(pool))
  540. }
  541. for _, child := range el.Children {
  542. brecurse(child)
  543. }
  544. }
  545. for _, el := range bx.Children {
  546. brecurse(el)
  547. }
  548. // do not eliminate duplicates until the entire slice has been composed.
  549. // consider <activity android:label="label" .../>
  550. // all attribute names come first followed by values; in such a case, the value "label"
  551. // would be a reference to the same "android:label" in the string pool which will occur
  552. // within the beginning of the pool where other attr names are located.
  553. bx.Pool.strings = asSet(bx.Pool.strings)
  554. // TODO consider cases of multiple declarations of the same attr name that should return error
  555. // before ever reaching this point.
  556. bx.Map = new(Map)
  557. for _, s := range bx.Pool.strings {
  558. ref, err := tbl.RefByName("attr/" + s)
  559. if err != nil {
  560. break // break after first non-ref as all strings after are also non-refs.
  561. }
  562. bx.Map.rs = append(bx.Map.rs, ref)
  563. }
  564. // resolve tmp pool refs to final pool refs
  565. // TODO drop this in favor of sort directly on Table
  566. var resolve func(el *Element)
  567. resolve = func(el *Element) {
  568. if el.NS != NoEntry {
  569. el.NS = bx.Pool.ref(el.NS.Resolve(pool))
  570. el.end.NS = el.NS
  571. }
  572. el.Name = bx.Pool.ref(el.Name.Resolve(pool))
  573. el.end.Name = el.Name
  574. for _, attr := range el.attrs {
  575. if attr.NS != NoEntry {
  576. attr.NS = bx.Pool.ref(attr.NS.Resolve(pool))
  577. }
  578. attr.Name = bx.Pool.ref(attr.Name.Resolve(pool))
  579. if attr.RawValue != NoEntry {
  580. attr.RawValue = bx.Pool.ref(attr.RawValue.Resolve(pool))
  581. if attr.TypedValue.Type == DataString {
  582. attr.TypedValue.Value = uint32(attr.RawValue)
  583. }
  584. }
  585. }
  586. for _, child := range el.Children {
  587. resolve(child)
  588. }
  589. }
  590. for _, el := range bx.Children {
  591. resolve(el)
  592. }
  593. var asort func(*Element)
  594. asort = func(el *Element) {
  595. sort.Sort(byType(el.attrs))
  596. sort.Sort(byNamespace(el.attrs))
  597. sort.Sort(byName(el.attrs))
  598. for _, child := range el.Children {
  599. asort(child)
  600. }
  601. }
  602. for _, el := range bx.Children {
  603. asort(el)
  604. }
  605. for i, s := range bx.Pool.strings {
  606. switch s {
  607. case androidSchema:
  608. bx.Namespace.uri = PoolRef(i)
  609. bx.Namespace.end.uri = PoolRef(i)
  610. case "android":
  611. bx.Namespace.prefix = PoolRef(i)
  612. bx.Namespace.end.prefix = PoolRef(i)
  613. }
  614. }
  615. return bx, nil
  616. }
  617. // UnmarshalBinary decodes all resource chunks in buf returning any error encountered.
  618. func (bx *XML) UnmarshalBinary(buf []byte) error {
  619. if err := (&bx.chunkHeader).UnmarshalBinary(buf); err != nil {
  620. return err
  621. }
  622. buf = buf[8:]
  623. for len(buf) > 0 {
  624. k, err := bx.unmarshalBinaryKind(buf)
  625. if err != nil {
  626. return err
  627. }
  628. buf = buf[k.size():]
  629. }
  630. return nil
  631. }
  632. // unmarshalBinaryKind decodes and stores the first resource chunk of bin.
  633. // It returns the unmarshaler interface and any error encountered.
  634. // If k.size() < len(bin), subsequent chunks can be decoded at bin[k.size():].
  635. func (bx *XML) unmarshalBinaryKind(bin []byte) (k unmarshaler, err error) {
  636. k, err = bx.kind(ResType(btou16(bin)))
  637. if err != nil {
  638. return nil, err
  639. }
  640. if err = k.UnmarshalBinary(bin); err != nil {
  641. return nil, err
  642. }
  643. return k, nil
  644. }
  645. func (bx *XML) kind(t ResType) (unmarshaler, error) {
  646. switch t {
  647. case ResStringPool:
  648. if bx.Pool != nil {
  649. return nil, fmt.Errorf("pool already exists")
  650. }
  651. bx.Pool = new(Pool)
  652. return bx.Pool, nil
  653. case ResXMLResourceMap:
  654. if bx.Map != nil {
  655. return nil, fmt.Errorf("resource map already exists")
  656. }
  657. bx.Map = new(Map)
  658. return bx.Map, nil
  659. case ResXMLStartNamespace:
  660. if bx.Namespace != nil {
  661. return nil, fmt.Errorf("namespace start already exists")
  662. }
  663. bx.Namespace = new(Namespace)
  664. return bx.Namespace, nil
  665. case ResXMLEndNamespace:
  666. if bx.Namespace.end != nil {
  667. return nil, fmt.Errorf("namespace end already exists")
  668. }
  669. bx.Namespace.end = new(Namespace)
  670. return bx.Namespace.end, nil
  671. case ResXMLStartElement:
  672. el := new(Element)
  673. if len(bx.stack) == 0 {
  674. bx.Children = append(bx.Children, el)
  675. } else {
  676. n := len(bx.stack)
  677. var p *Element
  678. p, bx.stack = bx.stack[n-1], bx.stack[:n-1]
  679. p.Children = append(p.Children, el)
  680. bx.stack = append(bx.stack, p)
  681. }
  682. bx.stack = append(bx.stack, el)
  683. return el, nil
  684. case ResXMLEndElement:
  685. n := len(bx.stack)
  686. var el *Element
  687. el, bx.stack = bx.stack[n-1], bx.stack[:n-1]
  688. if el.end != nil {
  689. return nil, fmt.Errorf("element end already exists")
  690. }
  691. el.end = new(ElementEnd)
  692. return el.end, nil
  693. case ResXMLCharData: // TODO assure correctness
  694. cdt := new(CharData)
  695. el := bx.stack[len(bx.stack)-1]
  696. if el.head == nil {
  697. el.head = cdt
  698. } else if el.tail == nil {
  699. el.tail = cdt
  700. } else {
  701. return nil, fmt.Errorf("element head and tail already contain chardata")
  702. }
  703. return cdt, nil
  704. default:
  705. return nil, fmt.Errorf("unexpected type %s", t)
  706. }
  707. }
  708. func (bx *XML) MarshalBinary() ([]byte, error) {
  709. bx.typ = ResXML
  710. bx.headerByteSize = 8
  711. var (
  712. bin, b []byte
  713. err error
  714. )
  715. b, err = bx.chunkHeader.MarshalBinary()
  716. if err != nil {
  717. return nil, err
  718. }
  719. bin = append(bin, b...)
  720. b, err = bx.Pool.MarshalBinary()
  721. if err != nil {
  722. return nil, err
  723. }
  724. bin = append(bin, b...)
  725. b, err = bx.Map.MarshalBinary()
  726. if err != nil {
  727. return nil, err
  728. }
  729. bin = append(bin, b...)
  730. b, err = bx.Namespace.MarshalBinary()
  731. if err != nil {
  732. return nil, err
  733. }
  734. bin = append(bin, b...)
  735. for _, child := range bx.Children {
  736. if err := marshalRecurse(child, &bin); err != nil {
  737. return nil, err
  738. }
  739. }
  740. b, err = bx.Namespace.end.MarshalBinary()
  741. if err != nil {
  742. return nil, err
  743. }
  744. bin = append(bin, b...)
  745. putu32(bin[4:], uint32(len(bin)))
  746. return bin, nil
  747. }
  748. func marshalRecurse(el *Element, bin *[]byte) error {
  749. b, err := el.MarshalBinary()
  750. if err != nil {
  751. return err
  752. }
  753. *bin = append(*bin, b...)
  754. if el.head != nil {
  755. b, err := el.head.MarshalBinary()
  756. if err != nil {
  757. return err
  758. }
  759. *bin = append(*bin, b...)
  760. }
  761. for _, child := range el.Children {
  762. if err := marshalRecurse(child, bin); err != nil {
  763. return err
  764. }
  765. }
  766. b, err = el.end.MarshalBinary()
  767. if err != nil {
  768. return err
  769. }
  770. *bin = append(*bin, b...)
  771. return nil
  772. }
  773. func (bx *XML) iterElements() <-chan *Element {
  774. ch := make(chan *Element, 1)
  775. go func() {
  776. for _, el := range bx.Children {
  777. iterElementsRecurse(el, ch)
  778. }
  779. close(ch)
  780. }()
  781. return ch
  782. }
  783. func iterElementsRecurse(el *Element, ch chan *Element) {
  784. ch <- el
  785. for _, e := range el.Children {
  786. iterElementsRecurse(e, ch)
  787. }
  788. }
  789. // asSet returns a set from a slice of strings.
  790. func asSet(xs []string) []string {
  791. m := make(map[string]bool)
  792. fo := xs[:0]
  793. for _, x := range xs {
  794. if !m[x] {
  795. m[x] = true
  796. fo = append(fo, x)
  797. }
  798. }
  799. return fo
  800. }
  801. // poolTrim trims all but immediately surrounding space.
  802. // \n\t\tfoobar\n\t\t becomes \tfoobar\n
  803. func poolTrim(s string) string {
  804. var start, end int
  805. for i, r := range s {
  806. if !unicode.IsSpace(r) {
  807. if i != 0 {
  808. start = i - 1 // preserve preceding space
  809. }
  810. break
  811. }
  812. }
  813. for i := len(s) - 1; i >= 0; i-- {
  814. r := rune(s[i])
  815. if !unicode.IsSpace(r) {
  816. if i != len(s)-1 {
  817. end = i + 2
  818. }
  819. break
  820. }
  821. }
  822. if start == 0 && end == 0 {
  823. return "" // every char was a space
  824. }
  825. return s[start:end]
  826. }
  827. // byNamespace sorts attributes based on string pool position of namespace.
  828. // Given that "android" always proceeds "" in the pool, this results in the
  829. // correct ordering of attributes.
  830. type byNamespace []*Attribute
  831. func (a byNamespace) Len() int { return len(a) }
  832. func (a byNamespace) Less(i, j int) bool {
  833. return a[i].NS < a[j].NS
  834. }
  835. func (a byNamespace) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  836. // byType sorts attributes by the uint8 value of the type.
  837. type byType []*Attribute
  838. func (a byType) Len() int { return len(a) }
  839. func (a byType) Less(i, j int) bool {
  840. return a[i].TypedValue.Type < a[j].TypedValue.Type
  841. }
  842. func (a byType) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  843. // byName sorts attributes that have matching types based on string pool position of name.
  844. type byName []*Attribute
  845. func (a byName) Len() int { return len(a) }
  846. func (a byName) Less(i, j int) bool {
  847. return (a[i].TypedValue.Type == DataString || a[i].TypedValue.Type == DataIntDec) &&
  848. (a[j].TypedValue.Type == DataString || a[j].TypedValue.Type == DataIntDec) &&
  849. a[i].Name < a[j].Name
  850. }
  851. func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  852. type lineReader struct {
  853. off int64
  854. lines []int64
  855. r io.Reader
  856. }
  857. func (r *lineReader) Read(p []byte) (n int, err error) {
  858. n, err = r.r.Read(p)
  859. for i := 0; i < n; i++ {
  860. if p[i] == '\n' {
  861. r.lines = append(r.lines, r.off+int64(i))
  862. }
  863. }
  864. r.off += int64(n)
  865. return n, err
  866. }
  867. func (r *lineReader) line(pos int64) int {
  868. return sort.Search(len(r.lines), func(i int) bool {
  869. return pos < r.lines[i]
  870. }) + 1
  871. }