예제 #1
0
 /**
  * read encoding len. see Stringpool.cpp ENCODE_LENGTH
  *
  * @param in
  * @return
  * @throws IOException
  */
 private static int readLen16(TellableInputStream in) throws IOException {
   int len = 0;
   int i = in.readUShort();
   if ((i & 0x8000) != 0) {
     len |= (i & 0x7fff) << 15;
     len += in.readUShort();
   } else {
     len = i;
   }
   return len;
 }
예제 #2
0
 /**
  * read encoding len. see Stringpool.cpp ENCODE_LENGTH
  *
  * @param in
  * @return
  * @throws IOException
  */
 private static int readLen(TellableInputStream in) throws IOException {
   int len = 0;
   int i = in.read();
   if ((i & 0x80) != 0) {
     // read one more byte.
     len |= (i & 0x7f) << 7;
     len += in.read();
   } else {
     len = i;
   }
   return len;
 }
예제 #3
0
  /**
   * read String pool, for apk binary xml file and resource table.
   *
   * @param in
   * @param stringPoolHeader
   * @return
   * @throws IOException
   */
  public static StringPool readStringPool(TellableInputStream in, StringPoolHeader stringPoolHeader)
      throws IOException {

    long beginPos = in.tell();
    long[] offsets = new long[(int) stringPoolHeader.stringCount];
    // read strings offset
    if (stringPoolHeader.stringCount > 0) {
      for (int idx = 0; idx < stringPoolHeader.stringCount; idx++) {
        offsets[idx] = in.readUInt();
      }
    }
    // read flag
    boolean sorted = (stringPoolHeader.flags & StringPoolHeader.SORTED_FLAG) != 0;
    StringEncoding stringEncoding =
        (stringPoolHeader.flags & StringPoolHeader.UTF8_FLAG) != 0
            ? StringEncoding.UTF8
            : StringEncoding.UTF16;

    // read strings. the head and metas have 28 bytes
    long stringPos = beginPos + stringPoolHeader.stringsStart - stringPoolHeader.headerSize;
    in.advanceIfNotRearch(stringPos);

    StringPoolEntry[] entries = new StringPoolEntry[offsets.length];
    for (int i = 0; i < offsets.length; i++) {
      entries[i] = new StringPoolEntry(i, stringPos + offsets[i]);
    }
    Arrays.sort(entries);

    String lastStr = null;
    long lastOffset = -1;
    StringPool stringPool = new StringPool((int) stringPoolHeader.stringCount);
    for (StringPoolEntry entry : entries) {
      if (entry.getOffset() == lastOffset) {
        stringPool.set(entry.getIdx(), lastStr);
        continue;
      }

      in.advanceIfNotRearch(entry.getOffset());
      lastOffset = entry.getOffset();
      String str = ParseUtils.readString(in, stringEncoding);
      lastStr = str;
      stringPool.set(entry.getIdx(), str);
    }

    // read styles
    if (stringPoolHeader.styleCount > 0) {
      // now we just skip it
    }

    in.advanceIfNotRearch(beginPos + stringPoolHeader.chunkSize - stringPoolHeader.headerSize);

    return stringPool;
  }
예제 #4
0
 private static String getDemension(TellableInputStream in) throws IOException {
   long l = in.readUInt();
   short unit = (short) (l & 0xff);
   String unitStr;
   switch (unit) {
     case ResValue.ResDataCOMPLEX.UNIT_MM:
       unitStr = "mm";
       break;
     case ResValue.ResDataCOMPLEX.UNIT_PX:
       unitStr = "px";
       break;
     case ResValue.ResDataCOMPLEX.UNIT_DIP:
       unitStr = "dp";
       break;
     case ResValue.ResDataCOMPLEX.UNIT_SP:
       unitStr = "sp";
       break;
     case ResValue.ResDataCOMPLEX.UNIT_PT:
       unitStr = "pt";
       break;
     case ResValue.ResDataCOMPLEX.UNIT_IN:
       unitStr = "in";
       break;
     default:
       unitStr = "unknow unit:0x" + Integer.toHexString(unit);
   }
   return (l >> 8) + unitStr;
 }
예제 #5
0
 /**
  * method to read resource value RGB/ARGB type.
  *
  * @return
  */
 public static String readRGBs(TellableInputStream in, int strLen) throws IOException {
   long l = in.readUInt();
   StringBuilder sb = new StringBuilder();
   for (int i = strLen / 2 - 1; i >= 0; i--) {
     sb.append(Integer.toHexString((int) ((l >> i * 8) & 0xff)));
   }
   return sb.toString();
 }
예제 #6
0
 /**
  * read utf-16 encoding str, use zero char to end str.
  *
  * @param in
  * @param strLen
  * @return
  * @throws IOException
  */
 public static String readStringUTF16(TellableInputStream in, int strLen) throws IOException {
   String str = in.readStringUTF16(strLen);
   for (int i = 0; i < str.length(); i++) {
     char c = str.charAt(i);
     if (c == 0) {
       return str.substring(0, i);
     }
   }
   return str;
 }
예제 #7
0
  /**
   * read res value, convert from different types to string.
   *
   * @param in
   * @param stringPool
   * @return
   * @throws IOException
   */
  public static ResValue readResValue(
      TellableInputStream in,
      StringPool stringPool,
      ResourceTable resourceTable,
      boolean isStyle,
      Locale locale)
      throws IOException {
    ResValue resValue = new ResValue();
    resValue.size = in.readUShort();
    resValue.res0 = in.readUByte();
    resValue.dataType = in.readUByte();

    switch (resValue.dataType) {
      case ResValue.ResType.INT_DEC:
      case ResValue.ResType.INT_HEX:
        resValue.data = String.valueOf(in.readInt());
        break;
      case ResValue.ResType.STRING:
        int strRef = in.readInt();
        if (strRef > 0) {
          resValue.data = stringPool.get(strRef);
        }
        break;
      case ResValue.ResType.REFERENCE:
        long resourceId = in.readUInt();
        resValue.data = getResourceByid(resourceId, isStyle, resourceTable, locale);
        break;
      case ResValue.ResType.INT_BOOLEAN:
        resValue.data = String.valueOf(in.readInt() != 0);
        break;
      case ResValue.ResType.NULL:
        resValue.data = "";
        break;
      case ResValue.ResType.INT_COLOR_RGB8:
      case ResValue.ResType.INT_COLOR_RGB4:
        resValue.data = readRGBs(in, 6);
        break;
      case ResValue.ResType.INT_COLOR_ARGB8:
      case ResValue.ResType.INT_COLOR_ARGB4:
        resValue.data = readRGBs(in, 8);
        break;
      case ResValue.ResType.DIMENSION:
        resValue.data = getDemension(in);
        break;
      case ResValue.ResType.FRACTION:
        resValue.data = getFraction(in);
        break;
      default:
        resValue.data = "{" + resValue.dataType + ":" + in.readUInt() + "}";
    }
    return resValue;
  }
예제 #8
0
  /** read string from input stream. if get EOF before read enough data, throw IOException. */
  public static String readString(TellableInputStream in, StringEncoding encoding)
      throws IOException {
    if (encoding == StringEncoding.UTF8) {
      //  The lengths are encoded in the same way as for the 16-bit format
      // but using 8-bit rather than 16-bit integers.
      int strLen = readLen(in);
      int bytesLen = readLen(in);
      byte[] bytes = in.readBytes(bytesLen);
      String str = new String(bytes, "UTF-8");
      // zero
      int trailling = in.readUByte();
      return str;

    } else {
      // The length is encoded as either one or two 16-bit integers as per the commentRef...
      int strLen = readLen16(in);
      String str = in.readStringUTF16(strLen);
      // zero
      int trailling = in.readUShort();
      return str;
    }
  }
예제 #9
0
 private static String getFraction(TellableInputStream in) throws IOException {
   long l = in.readUInt();
   // The low-order 4 bits of the data value specify the type of the fraction
   short type = (short) (l & 0xf);
   String pstr;
   switch (type) {
     case ResValue.ResDataCOMPLEX.UNIT_FRACTION:
       pstr = "%";
       break;
     case ResValue.ResDataCOMPLEX.UNIT_FRACTION_PARENT:
       pstr = "%p";
       break;
     default:
       pstr = "unknow type:0x" + Integer.toHexString(type);
   }
   float value = Float.intBitsToFloat((int) (l >> 4));
   return value + pstr;
 }