OSDN Git Service

[DO NOT MERGE] Fix vulnerability in MemoryIntArray - fix build file
[android-x86/frameworks-base.git] / tools / aapt / AaptAssets.h
1 //
2 // Copyright 2006 The Android Open Source Project
3 //
4 // Information about assets being operated on.
5 //
6 #ifndef __AAPT_ASSETS_H
7 #define __AAPT_ASSETS_H
8
9 #include <androidfw/AssetManager.h>
10 #include <androidfw/ResourceTypes.h>
11 #include <stdlib.h>
12 #include <set>
13 #include <utils/KeyedVector.h>
14 #include <utils/RefBase.h>
15 #include <utils/SortedVector.h>
16 #include <utils/String8.h>
17 #include <utils/Vector.h>
18
19 #include "AaptConfig.h"
20 #include "Bundle.h"
21 #include "ConfigDescription.h"
22 #include "SourcePos.h"
23 #include "ZipFile.h"
24
25 using namespace android;
26
27 extern const char * const gDefaultIgnoreAssets;
28 extern const char * gUserIgnoreAssets;
29
30 bool valid_symbol_name(const String8& str);
31
32 class AaptAssets;
33
34 enum {
35     AXIS_NONE = 0,
36     AXIS_MCC = 1,
37     AXIS_MNC,
38     AXIS_LOCALE,
39     AXIS_SCREENLAYOUTSIZE,
40     AXIS_SCREENLAYOUTLONG,
41     AXIS_ORIENTATION,
42     AXIS_UIMODETYPE,
43     AXIS_UIMODENIGHT,
44     AXIS_DENSITY,
45     AXIS_TOUCHSCREEN,
46     AXIS_KEYSHIDDEN,
47     AXIS_KEYBOARD,
48     AXIS_NAVHIDDEN,
49     AXIS_NAVIGATION,
50     AXIS_SCREENSIZE,
51     AXIS_SMALLESTSCREENWIDTHDP,
52     AXIS_SCREENWIDTHDP,
53     AXIS_SCREENHEIGHTDP,
54     AXIS_LAYOUTDIR,
55     AXIS_VERSION,
56
57     AXIS_START = AXIS_MCC,
58     AXIS_END = AXIS_VERSION,
59 };
60
61 struct AaptLocaleValue {
62      char language[4];
63      char region[4];
64      char script[4];
65      char variant[8];
66
67      AaptLocaleValue() {
68          memset(this, 0, sizeof(AaptLocaleValue));
69      }
70
71      // Initialize this AaptLocaleValue from a config string.
72      bool initFromFilterString(const String8& config);
73
74      int initFromDirName(const Vector<String8>& parts, const int startIndex);
75
76      // Initialize this AaptLocaleValue from a ResTable_config.
77      void initFromResTable(const ResTable_config& config);
78
79      void writeTo(ResTable_config* out) const;
80
81      int compare(const AaptLocaleValue& other) const {
82          return memcmp(this, &other, sizeof(AaptLocaleValue));
83      }
84
85      inline bool operator<(const AaptLocaleValue& o) const { return compare(o) < 0; }
86      inline bool operator<=(const AaptLocaleValue& o) const { return compare(o) <= 0; }
87      inline bool operator==(const AaptLocaleValue& o) const { return compare(o) == 0; }
88      inline bool operator!=(const AaptLocaleValue& o) const { return compare(o) != 0; }
89      inline bool operator>=(const AaptLocaleValue& o) const { return compare(o) >= 0; }
90      inline bool operator>(const AaptLocaleValue& o) const { return compare(o) > 0; }
91 private:
92      void setLanguage(const char* language);
93      void setRegion(const char* language);
94      void setScript(const char* script);
95      void setVariant(const char* variant);
96 };
97
98 /**
99  * This structure contains a specific variation of a single file out
100  * of all the variations it can have that we can have.
101  */
102 struct AaptGroupEntry
103 {
104 public:
105     AaptGroupEntry() {}
106     AaptGroupEntry(const ConfigDescription& config) : mParams(config) {}
107
108     bool initFromDirName(const char* dir, String8* resType);
109
110     inline const ConfigDescription& toParams() const { return mParams; }
111
112     inline int compare(const AaptGroupEntry& o) const { return mParams.compareLogical(o.mParams); }
113     inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
114     inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
115     inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
116     inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
117     inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
118     inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
119
120     String8 toString() const { return mParams.toString(); }
121     String8 toDirName(const String8& resType) const;
122
123     const String8 getVersionString() const { return AaptConfig::getVersion(mParams); }
124
125 private:
126     ConfigDescription mParams;
127 };
128
129 inline int compare_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
130 {
131     return lhs.compare(rhs);
132 }
133
134 inline int strictly_order_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
135 {
136     return compare_type(lhs, rhs) < 0;
137 }
138
139 class AaptGroup;
140 class FilePathStore;
141
142 /**
143  * A single asset file we know about.
144  */
145 class AaptFile : public RefBase
146 {
147 public:
148     AaptFile(const String8& sourceFile, const AaptGroupEntry& groupEntry,
149              const String8& resType)
150         : mGroupEntry(groupEntry)
151         , mResourceType(resType)
152         , mSourceFile(sourceFile)
153         , mData(NULL)
154         , mDataSize(0)
155         , mBufferSize(0)
156         , mCompression(ZipEntry::kCompressStored)
157         {
158             //printf("new AaptFile created %s\n", (const char*)sourceFile);
159         }
160     virtual ~AaptFile() {
161         free(mData);
162     }
163
164     const String8& getPath() const { return mPath; }
165     const AaptGroupEntry& getGroupEntry() const { return mGroupEntry; }
166
167     // Data API.  If there is data attached to the file,
168     // getSourceFile() is not used.
169     bool hasData() const { return mData != NULL; }
170     const void* getData() const { return mData; }
171     size_t getSize() const { return mDataSize; }
172     void* editData(size_t size);
173     void* editData(size_t* outSize = NULL);
174     void* editDataInRange(size_t offset, size_t size);
175     void* padData(size_t wordSize);
176     status_t writeData(const void* data, size_t size);
177     void clearData();
178
179     const String8& getResourceType() const { return mResourceType; }
180
181     // File API.  If the file does not hold raw data, this is
182     // a full path to a file on the filesystem that holds its data.
183     const String8& getSourceFile() const { return mSourceFile; }
184
185     String8 getPrintableSource() const;
186
187     // Desired compression method, as per utils/ZipEntry.h.  For example,
188     // no compression is ZipEntry::kCompressStored.
189     int getCompressionMethod() const { return mCompression; }
190     void setCompressionMethod(int c) { mCompression = c; }
191 private:
192     friend class AaptGroup;
193
194     String8 mPath;
195     AaptGroupEntry mGroupEntry;
196     String8 mResourceType;
197     String8 mSourceFile;
198     void* mData;
199     size_t mDataSize;
200     size_t mBufferSize;
201     int mCompression;
202 };
203
204 /**
205  * A group of related files (the same file, with different
206  * vendor/locale variations).
207  */
208 class AaptGroup : public RefBase
209 {
210 public:
211     AaptGroup(const String8& leaf, const String8& path)
212         : mLeaf(leaf), mPath(path) { }
213     virtual ~AaptGroup() { }
214
215     const String8& getLeaf() const { return mLeaf; }
216
217     // Returns the relative path after the AaptGroupEntry dirs.
218     const String8& getPath() const { return mPath; }
219
220     const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& getFiles() const
221         { return mFiles; }
222
223     status_t addFile(const sp<AaptFile>& file, const bool overwriteDuplicate=false);
224     void removeFile(size_t index);
225
226     void print(const String8& prefix) const;
227
228     String8 getPrintableSource() const;
229
230 private:
231     String8 mLeaf;
232     String8 mPath;
233
234     DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > mFiles;
235 };
236
237 /**
238  * A single directory of assets, which can contain files and other
239  * sub-directories.
240  */
241 class AaptDir : public RefBase
242 {
243 public:
244     AaptDir(const String8& leaf, const String8& path)
245         : mLeaf(leaf), mPath(path) { }
246     virtual ~AaptDir() { }
247
248     const String8& getLeaf() const { return mLeaf; }
249
250     const String8& getPath() const { return mPath; }
251
252     const DefaultKeyedVector<String8, sp<AaptGroup> >& getFiles() const { return mFiles; }
253     const DefaultKeyedVector<String8, sp<AaptDir> >& getDirs() const { return mDirs; }
254
255     virtual status_t addFile(const String8& name, const sp<AaptGroup>& file);
256
257     void removeFile(const String8& name);
258     void removeDir(const String8& name);
259
260     /*
261      * Perform some sanity checks on the names of files and directories here.
262      * In particular:
263      *  - Check for illegal chars in filenames.
264      *  - Check filename length.
265      *  - Check for presence of ".gz" and non-".gz" copies of same file.
266      *  - Check for multiple files whose names match in a case-insensitive
267      *    fashion (problematic for some systems).
268      *
269      * Comparing names against all other names is O(n^2).  We could speed
270      * it up some by sorting the entries and being smarter about what we
271      * compare against, but I'm not expecting to have enough files in a
272      * single directory to make a noticeable difference in speed.
273      *
274      * Note that sorting here is not enough to guarantee that the package
275      * contents are sorted -- subsequent updates can rearrange things.
276      */
277     status_t validate() const;
278
279     void print(const String8& prefix) const;
280
281     String8 getPrintableSource() const;
282
283 private:
284     friend class AaptAssets;
285
286     status_t addDir(const String8& name, const sp<AaptDir>& dir);
287     sp<AaptDir> makeDir(const String8& name);
288     status_t addLeafFile(const String8& leafName,
289                          const sp<AaptFile>& file,
290                          const bool overwrite=false);
291     virtual ssize_t slurpFullTree(Bundle* bundle,
292                                   const String8& srcDir,
293                                   const AaptGroupEntry& kind,
294                                   const String8& resType,
295                                   sp<FilePathStore>& fullResPaths,
296                                   const bool overwrite=false);
297
298     String8 mLeaf;
299     String8 mPath;
300
301     DefaultKeyedVector<String8, sp<AaptGroup> > mFiles;
302     DefaultKeyedVector<String8, sp<AaptDir> > mDirs;
303 };
304
305 /**
306  * All information we know about a particular symbol.
307  */
308 class AaptSymbolEntry
309 {
310 public:
311     AaptSymbolEntry()
312         : isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN)
313     {
314     }
315     AaptSymbolEntry(const String8& _name)
316         : name(_name), isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN)
317     {
318     }
319     AaptSymbolEntry(const AaptSymbolEntry& o)
320         : name(o.name), sourcePos(o.sourcePos), isPublic(o.isPublic)
321         , isJavaSymbol(o.isJavaSymbol), comment(o.comment), typeComment(o.typeComment)
322         , typeCode(o.typeCode), int32Val(o.int32Val), stringVal(o.stringVal)
323     {
324     }
325     AaptSymbolEntry operator=(const AaptSymbolEntry& o)
326     {
327         sourcePos = o.sourcePos;
328         isPublic = o.isPublic;
329         isJavaSymbol = o.isJavaSymbol;
330         comment = o.comment;
331         typeComment = o.typeComment;
332         typeCode = o.typeCode;
333         int32Val = o.int32Val;
334         stringVal = o.stringVal;
335         return *this;
336     }
337     
338     const String8 name;
339     
340     SourcePos sourcePos;
341     bool isPublic;
342     bool isJavaSymbol;
343     
344     String16 comment;
345     String16 typeComment;
346     
347     enum {
348         TYPE_UNKNOWN = 0,
349         TYPE_INT32,
350         TYPE_STRING
351     };
352     
353     int typeCode;
354     
355     // Value.  May be one of these.
356     int32_t int32Val;
357     String8 stringVal;
358 };
359
360 /**
361  * A group of related symbols (such as indices into a string block)
362  * that have been generated from the assets.
363  */
364 class AaptSymbols : public RefBase
365 {
366 public:
367     AaptSymbols() { }
368     virtual ~AaptSymbols() { }
369
370     status_t addSymbol(const String8& name, int32_t value, const SourcePos& pos) {
371         if (!check_valid_symbol_name(name, pos, "symbol")) {
372             return BAD_VALUE;
373         }
374         AaptSymbolEntry& sym = edit_symbol(name, &pos);
375         sym.typeCode = AaptSymbolEntry::TYPE_INT32;
376         sym.int32Val = value;
377         return NO_ERROR;
378     }
379
380     status_t addStringSymbol(const String8& name, const String8& value,
381             const SourcePos& pos) {
382         if (!check_valid_symbol_name(name, pos, "symbol")) {
383             return BAD_VALUE;
384         }
385         AaptSymbolEntry& sym = edit_symbol(name, &pos);
386         sym.typeCode = AaptSymbolEntry::TYPE_STRING;
387         sym.stringVal = value;
388         return NO_ERROR;
389     }
390
391     status_t makeSymbolPublic(const String8& name, const SourcePos& pos) {
392         if (!check_valid_symbol_name(name, pos, "symbol")) {
393             return BAD_VALUE;
394         }
395         AaptSymbolEntry& sym = edit_symbol(name, &pos);
396         sym.isPublic = true;
397         return NO_ERROR;
398     }
399
400     status_t makeSymbolJavaSymbol(const String8& name, const SourcePos& pos) {
401         if (!check_valid_symbol_name(name, pos, "symbol")) {
402             return BAD_VALUE;
403         }
404         AaptSymbolEntry& sym = edit_symbol(name, &pos);
405         sym.isJavaSymbol = true;
406         return NO_ERROR;
407     }
408
409     void appendComment(const String8& name, const String16& comment, const SourcePos& pos) {
410         if (comment.size() <= 0) {
411             return;
412         }
413         AaptSymbolEntry& sym = edit_symbol(name, &pos);
414         if (sym.comment.size() == 0) {
415             sym.comment = comment;
416         } else {
417             sym.comment.append(String16("\n"));
418             sym.comment.append(comment);
419         }
420     }
421
422     void appendTypeComment(const String8& name, const String16& comment) {
423         if (comment.size() <= 0) {
424             return;
425         }
426         AaptSymbolEntry& sym = edit_symbol(name, NULL);
427         if (sym.typeComment.size() == 0) {
428             sym.typeComment = comment;
429         } else {
430             sym.typeComment.append(String16("\n"));
431             sym.typeComment.append(comment);
432         }
433     }
434     
435     sp<AaptSymbols> addNestedSymbol(const String8& name, const SourcePos& pos) {
436         if (!check_valid_symbol_name(name, pos, "nested symbol")) {
437             return NULL;
438         }
439         
440         sp<AaptSymbols> sym = mNestedSymbols.valueFor(name);
441         if (sym == NULL) {
442             sym = new AaptSymbols();
443             mNestedSymbols.add(name, sym);
444         }
445
446         return sym;
447     }
448
449     status_t applyJavaSymbols(const sp<AaptSymbols>& javaSymbols);
450
451     const KeyedVector<String8, AaptSymbolEntry>& getSymbols() const
452         { return mSymbols; }
453     const DefaultKeyedVector<String8, sp<AaptSymbols> >& getNestedSymbols() const
454         { return mNestedSymbols; }
455
456     const String16& getComment(const String8& name) const
457         { return get_symbol(name).comment; }
458     const String16& getTypeComment(const String8& name) const
459         { return get_symbol(name).typeComment; }
460
461 private:
462     bool check_valid_symbol_name(const String8& symbol, const SourcePos& pos, const char* label) {
463         if (valid_symbol_name(symbol)) {
464             return true;
465         }
466         pos.error("invalid %s: '%s'\n", label, symbol.string());
467         return false;
468     }
469     AaptSymbolEntry& edit_symbol(const String8& symbol, const SourcePos* pos) {
470         ssize_t i = mSymbols.indexOfKey(symbol);
471         if (i < 0) {
472             i = mSymbols.add(symbol, AaptSymbolEntry(symbol));
473         }
474         AaptSymbolEntry& sym = mSymbols.editValueAt(i);
475         if (pos != NULL && sym.sourcePos.line < 0) {
476             sym.sourcePos = *pos;
477         }
478         return sym;
479     }
480     const AaptSymbolEntry& get_symbol(const String8& symbol) const {
481         ssize_t i = mSymbols.indexOfKey(symbol);
482         if (i >= 0) {
483             return mSymbols.valueAt(i);
484         }
485         return mDefSymbol;
486     }
487
488     KeyedVector<String8, AaptSymbolEntry>           mSymbols;
489     DefaultKeyedVector<String8, sp<AaptSymbols> >   mNestedSymbols;
490     AaptSymbolEntry                                 mDefSymbol;
491 };
492
493 class ResourceTypeSet : public RefBase,
494                         public KeyedVector<String8,sp<AaptGroup> >
495 {
496 public:
497     ResourceTypeSet();
498 };
499
500 // Storage for lists of fully qualified paths for
501 // resources encountered during slurping.
502 class FilePathStore : public RefBase,
503                       public Vector<String8>
504 {
505 public:
506     FilePathStore();
507 };
508
509 /**
510  * Asset hierarchy being operated on.
511  */
512 class AaptAssets : public AaptDir
513 {
514 public:
515     AaptAssets();
516     virtual ~AaptAssets() { delete mRes; }
517
518     const String8& getPackage() const { return mPackage; }
519     void setPackage(const String8& package) {
520         mPackage = package;
521         mSymbolsPrivatePackage = package;
522         mHavePrivateSymbols = false;
523     }
524
525     const SortedVector<AaptGroupEntry>& getGroupEntries() const;
526
527     virtual status_t addFile(const String8& name, const sp<AaptGroup>& file);
528
529     sp<AaptFile> addFile(const String8& filePath,
530                          const AaptGroupEntry& entry,
531                          const String8& srcDir,
532                          sp<AaptGroup>* outGroup,
533                          const String8& resType);
534
535     void addResource(const String8& leafName,
536                      const String8& path,
537                      const sp<AaptFile>& file,
538                      const String8& resType);
539
540     void addGroupEntry(const AaptGroupEntry& entry) { mGroupEntries.add(entry); }
541     
542     ssize_t slurpFromArgs(Bundle* bundle);
543
544     sp<AaptSymbols> getSymbolsFor(const String8& name);
545
546     sp<AaptSymbols> getJavaSymbolsFor(const String8& name);
547
548     status_t applyJavaSymbols();
549
550     const DefaultKeyedVector<String8, sp<AaptSymbols> >& getSymbols() const { return mSymbols; }
551
552     String8 getSymbolsPrivatePackage() const { return mSymbolsPrivatePackage; }
553     void setSymbolsPrivatePackage(const String8& pkg) {
554         mSymbolsPrivatePackage = pkg;
555         mHavePrivateSymbols = mSymbolsPrivatePackage != mPackage;
556     }
557
558     bool havePrivateSymbols() const { return mHavePrivateSymbols; }
559
560     bool isJavaSymbol(const AaptSymbolEntry& sym, bool includePrivate) const;
561
562     status_t buildIncludedResources(Bundle* bundle);
563     status_t addIncludedResources(const sp<AaptFile>& file);
564     const ResTable& getIncludedResources() const;
565     AssetManager& getAssetManager();
566
567     void print(const String8& prefix) const;
568
569     inline const Vector<sp<AaptDir> >& resDirs() const { return mResDirs; }
570     sp<AaptDir> resDir(const String8& name) const;
571
572     inline sp<AaptAssets> getOverlay() { return mOverlay; }
573     inline void setOverlay(sp<AaptAssets>& overlay) { mOverlay = overlay; }
574     
575     inline KeyedVector<String8, sp<ResourceTypeSet> >* getResources() { return mRes; }
576     inline void 
577         setResources(KeyedVector<String8, sp<ResourceTypeSet> >* res) { delete mRes; mRes = res; }
578
579     inline sp<FilePathStore>& getFullResPaths() { return mFullResPaths; }
580     inline void
581         setFullResPaths(sp<FilePathStore>& res) { mFullResPaths = res; }
582
583     inline sp<FilePathStore>& getFullAssetPaths() { return mFullAssetPaths; }
584     inline void
585         setFullAssetPaths(sp<FilePathStore>& res) { mFullAssetPaths = res; }
586
587 private:
588     virtual ssize_t slurpFullTree(Bundle* bundle,
589                                   const String8& srcDir,
590                                   const AaptGroupEntry& kind,
591                                   const String8& resType,
592                                   sp<FilePathStore>& fullResPaths,
593                                   const bool overwrite=false);
594
595     ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir);
596     ssize_t slurpResourceZip(Bundle* bundle, const char* filename);
597
598     status_t filter(Bundle* bundle);
599
600     String8 mPackage;
601     SortedVector<AaptGroupEntry> mGroupEntries;
602     DefaultKeyedVector<String8, sp<AaptSymbols> > mSymbols;
603     DefaultKeyedVector<String8, sp<AaptSymbols> > mJavaSymbols;
604     String8 mSymbolsPrivatePackage;
605     bool mHavePrivateSymbols;
606
607     Vector<sp<AaptDir> > mResDirs;
608
609     bool mChanged;
610
611     bool mHaveIncludedAssets;
612     AssetManager mIncludedAssets;
613
614     sp<AaptAssets> mOverlay;
615     KeyedVector<String8, sp<ResourceTypeSet> >* mRes;
616
617     sp<FilePathStore> mFullResPaths;
618     sp<FilePathStore> mFullAssetPaths;
619 };
620
621 #endif // __AAPT_ASSETS_H
622