package com.bytezone.diskbrowser.applefile; import com.bytezone.diskbrowser.HexFormatter; public class StoredVariables extends AbstractFile { public StoredVariables (String name, byte[] buffer) { super (name, buffer); } public String getText () { StringBuilder text = new StringBuilder (); String strValue = null; int intValue = 0; // double doubleValue = 0.0; int strPtr = buffer.length; text.append ("File length : " + HexFormatter.format4 (buffer.length)); int totalLength = HexFormatter.intValue (buffer[0], buffer[1]); text.append ("\nTotal length : " + HexFormatter.format4 (totalLength)); int varLength = HexFormatter.intValue (buffer[2], buffer[3]); text.append ("\nVar length : " + HexFormatter.format4 (varLength)); text.append ("\n\n"); // list simple variables int ptr = 5; while (ptr < varLength + 5) { String variableName = getVariableName (buffer[ptr], buffer[ptr + 1]); text.append (variableName); char suffix = variableName.charAt (variableName.length () - 1); if (suffix == '$') { int strLength = HexFormatter.intValue (buffer[ptr + 2]); strPtr -= strLength; strValue = HexFormatter.getString (buffer, strPtr, strLength); text.append (" = " + strValue); } else if (suffix == '%') { intValue = HexFormatter.intValue (buffer[ptr + 3], buffer[ptr + 2]); if ((buffer[ptr + 2] & 0x80) > 0) intValue -= 65536; text.append (" = " + intValue); } else { if (hasValue (ptr + 2)) { String value = HexFormatter.floatValue (buffer, ptr + 2) + ""; if (value.endsWith (".0")) text.append (" = " + value.substring (0, value.length () - 2)); else text.append (" = " + value); } } text.append ("\n"); ptr += 7; } listArrays (text, ptr, totalLength, strPtr); return text.toString (); } private String getVariableName (byte b1, byte b2) { char c1, c2, suffix; if ((b1 & 0x80) > 0) // integer { c1 = (char) (b1 & 0x7F); c2 = (char) (b2 & 0x7F); suffix = '%'; } else if ((b2 & 0x80) > 0) // string { c1 = (char) b1; c2 = (char) (b2 & 0x7F); suffix = '$'; } else { c1 = (char) b1; c2 = (char) b2; suffix = ' '; } StringBuffer variableName = new StringBuffer (); variableName.append (c1); if (c2 > 32) variableName.append (c2); if (suffix != ' ') variableName.append (suffix); return variableName.toString (); } private String getDimensionText (int[] values) { StringBuilder text = new StringBuilder ("("); for (int i = 0; i < values.length; i++) { text.append (values[i]); if (i < values.length - 1) text.append (','); } return text.append (')').toString (); } private void listArrays (StringBuilder text, int ptr, int totalLength, int strPtr) { while (ptr < totalLength + 5) { String variableName = getVariableName (buffer[ptr], buffer[ptr + 1]); text.append ("\n"); int offset = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]); int dimensions = HexFormatter.intValue (buffer[ptr + 4]); int[] dimensionSizes = new int[dimensions]; int totalElements = 0; for (int i = 0; i < dimensions; i++) { int p = i * 2 + 5 + ptr; int elements = HexFormatter.intValue (buffer[p + 1], buffer[p]); dimensionSizes[dimensions - i - 1] = elements - 1; if (totalElements == 0) totalElements = elements; else totalElements *= elements; } int headerSize = 5 + dimensions * 2; int elementSize = (offset - headerSize) / totalElements; int p = ptr + headerSize; int[] values = new int[dimensions]; for (int i = 0; i < values.length; i++) values[i] = 0; out: while (true) { text.append (variableName + " " + getDimensionText (values) + " = "); if (elementSize == 2) { int intValue = HexFormatter.intValue (buffer[p + 1], buffer[p]); if ((buffer[p] & 0x80) > 0) intValue -= 65536; text.append (intValue + "\n"); } else if (elementSize == 3) { int strLength = HexFormatter.intValue (buffer[p]); if (strLength > 0) { strPtr -= strLength; text.append (HexFormatter.getString (buffer, strPtr, strLength)); } text.append ("\n"); } else if (elementSize == 5) { if (hasValue (p)) text.append (HexFormatter.floatValue (buffer, p)); text.append ("\n"); } p += elementSize; int cp = 0; while (++values[cp] > dimensionSizes[cp]) { values[cp++] = 0; if (cp >= values.length) break out; } } ptr += offset; } } private boolean hasValue (int p) { for (int i = 0; i < 5; i++) if (buffer[p + i] != 0) return true; return false; } public String getHexDump () { StringBuffer text = new StringBuffer (); text.append ("File length : " + HexFormatter.format4 (buffer.length)); int totalLength = HexFormatter.intValue (buffer[0], buffer[1]); text.append ("\nTotal length : " + HexFormatter.format4 (totalLength)); int varLength = HexFormatter.intValue (buffer[2], buffer[3]); text.append ("\nVar length : " + HexFormatter.format4 (varLength)); int unknown = HexFormatter.intValue (buffer[4]); text.append ("\nUnknown : " + HexFormatter.format2 (unknown)); text.append ("\n\n"); int ptr = 5; text.append ("Simple variables : \n\n"); while (ptr < varLength + 5) { text.append (HexFormatter.format (buffer, ptr, 7, false, 0) + "\n"); ptr += 7; } text.append ("\nArrays : \n\n"); while (ptr < totalLength + 5) { int offset = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]); int dimensions = HexFormatter.intValue (buffer[ptr + 4]); int[] dimensionSizes = new int[dimensions]; int totalElements = 0; for (int i = 0; i < dimensions; i++) { int p = i * 2 + 5 + ptr; int elements = HexFormatter.intValue (buffer[p + 1], buffer[p]); dimensionSizes[dimensions - i - 1] = elements; if (totalElements == 0) totalElements = elements; else totalElements *= elements; } int headerSize = 5 + dimensions * 2; text.append (HexFormatter.format (buffer, ptr, headerSize, false, 0) + "\n\n"); text.append (HexFormatter.format (buffer, ptr + headerSize, offset - headerSize, false, 0) + "\n\n"); ptr += offset; } text.append ("Strings : \n\n"); int length = buffer.length - ptr; text.append (HexFormatter.format (buffer, ptr, length, false, 0) + "\n\n"); return text.toString (); } }