diff --git a/fmp/fmp_const.go b/fmp/fmp_const.go index f5d4551..f109777 100644 --- a/fmp/fmp_const.go +++ b/fmp/fmp_const.go @@ -21,6 +21,7 @@ const ( FMP_CHUNK_SIMPLE_KEY_VALUE FMP_CHUNK_LONG_KEY_VALUE FMP_CHUNK_PATH_PUSH + FMP_CHUNK_PATH_PUSH_LONG FMP_CHUNK_PATH_POP FMP_CHUNK_NOOP ) diff --git a/fmp/fmp_debug.go b/fmp/fmp_debug.go index 6b93a0d..536e170 100644 --- a/fmp/fmp_debug.go +++ b/fmp/fmp_debug.go @@ -6,7 +6,7 @@ import ( ) func debug(str string, args ...interface{}) { - fmt.Printf(str+"\n", args...) + // fmt.Printf(str+"\n", args...) } func (f *FmpFile) ToDebugFile(fname string) { diff --git a/fmp/fmp_file.go b/fmp/fmp_file.go index cbccc0c..61152dc 100644 --- a/fmp/fmp_file.go +++ b/fmp/fmp_file.go @@ -40,7 +40,6 @@ func OpenFile(path string) (*FmpFile, error) { ctx.FileSize = uint(info.Size()) ctx.numSectors = uint64((ctx.FileSize / sectorSize) - 1) ctx.Sectors = make([]*FmpSector, 0) - currentPath := make([]uint64, 0) ctx.stream.Seek(2*sectorSize, io.SeekStart) for { @@ -55,7 +54,7 @@ func OpenFile(path string) (*FmpFile, error) { ctx.Sectors = append(ctx.Sectors, sector) if sector.ID != 0 { - err = sector.processChunks(ctx.Dictionary, ¤tPath) + err = sector.processChunks(ctx.Dictionary) if err != nil { return nil, err } diff --git a/fmp/fmp_sector.go b/fmp/fmp_sector.go index 68648a0..c8c611c 100644 --- a/fmp/fmp_sector.go +++ b/fmp/fmp_sector.go @@ -2,6 +2,7 @@ package fmp import ( "encoding/hex" + "fmt" "io" ) @@ -48,41 +49,48 @@ func (sect *FmpSector) readChunks() error { return nil } -func (sect *FmpSector) processChunks(dict *FmpDict, currentPath *[]uint64) error { +func (sect *FmpSector) processChunks(dict *FmpDict) error { err := sect.readChunks() if err != nil { return err } + currentPath := make([]uint64, 0) for _, chunk := range sect.Chunks { switch chunk.Type { - case FMP_CHUNK_PATH_PUSH: - *currentPath = append(*currentPath, uint64(chunk.Value[0])) + case FMP_CHUNK_PATH_PUSH, FMP_CHUNK_PATH_PUSH_LONG: + currentPath = append(currentPath, parseVarUint64(chunk.Value)) + + s := "" + for _, ent := range currentPath { + s += fmt.Sprintf("%v. ", ent) + } + debug("path: %s", s) case FMP_CHUNK_PATH_POP: - if len(*currentPath) > 0 { - *currentPath = (*currentPath)[:len(*currentPath)-1] + if len(currentPath) > 0 { + currentPath = (currentPath)[:len(currentPath)-1] } case FMP_CHUNK_SIMPLE_DATA: - dict.set(*currentPath, chunk.Value) + dict.SetValue(currentPath, chunk.Value) case FMP_CHUNK_SEGMENTED_DATA: // Todo: take index into account - dict.set( - *currentPath, - append(dict.getValue(*currentPath), chunk.Value...), + dict.SetValue( + currentPath, + append(dict.GetValue(currentPath), chunk.Value...), ) case FMP_CHUNK_SIMPLE_KEY_VALUE: - dict.set( - append(*currentPath, uint64(chunk.Key)), + dict.SetValue( + append(currentPath, uint64(chunk.Key)), chunk.Value, ) case FMP_CHUNK_LONG_KEY_VALUE: - dict.set( - append(*currentPath, uint64(chunk.Key)), // todo: ?? + dict.SetValue( + append(currentPath, uint64(chunk.Key)), // todo: ?? chunk.Value, ) @@ -235,7 +243,7 @@ func (sect *FmpSector) readChunk(payload []byte) (*FmpChunk, error) { case 0x38: valueLength := uint64(payload[1]) chunk.Length = 2 + valueLength - chunk.Type = FMP_CHUNK_PATH_PUSH + chunk.Type = FMP_CHUNK_PATH_PUSH_LONG chunk.Value = payload[2:chunk.Length] case 0x3D, 0x40: diff --git a/fmp/fmp_table.go b/fmp/fmp_table.go index 2e6f290..3338925 100644 --- a/fmp/fmp_table.go +++ b/fmp/fmp_table.go @@ -2,46 +2,16 @@ package fmp func (ctx *FmpFile) Tables() []*FmpTable { tables := make([]*FmpTable, 0) + ent := ctx.Dictionary.GetEntry([]uint64{3, 16, 5}) - for key, ent := range *ctx.Dictionary { - if key != 3 { + for path, tableEnt := range *ent.Children { + if path < 128 { continue } - debug("Found a 3") - - for key, ent = range *ent.Children { - if key != 16 { - continue - } - debug("Found a 3.16") - - for key, ent = range *ent.Children { - if key != 5 { - continue - } - debug("Found a 3.16.5") - - for tablePath := range *ent.Children { - if key >= 128 { - continue - } - - // Found a table! - debug("Found a table at 3.16.5.%d", tablePath) - } - } - } + name := decodeByteSeq(tableEnt.Children.GetValue([]uint64{16})) + table := &FmpTable{ID: path, Name: name} + tables = append(tables, table) } - // metaDict := ctx.Dictionary.get([]uint64{4, 1, 7}) - // if metaDict == nil { - // return tables - // } - // for _, meta := range *metaDict.Children { - // name := decodeByteSeq(meta.Children.get([]uint64{16}).Value) - // table := &FmpTable{Name: name} - // tables = append(tables, table) - // } - return tables } diff --git a/fmp/fmp_test.go b/fmp/fmp_test.go index a4440c0..58413a4 100644 --- a/fmp/fmp_test.go +++ b/fmp/fmp_test.go @@ -29,14 +29,16 @@ func TestTables(t *testing.T) { } tables := f.Tables() - if len(tables) != 1 || tables[0].Name != "Untitled" { - tablesString := "" - for i, table := range tables { - tablesString += table.Name - if i < len(tables)-1 { - tablesString += ", " - } + expected := "WayDomains, WayProcesses, Untitled" + tablesString := "" + for i, table := range tables { + tablesString += table.Name + if i < len(tables)-1 { + tablesString += ", " } - t.Errorf("expected tables to be 'Untitled', got '%s'", tablesString) + } + + if tablesString != expected { + t.Errorf("expected tables to be '%s', got '%s'", expected, tablesString) } } diff --git a/fmp/fmp_type.go b/fmp/fmp_type.go index 714f681..401f232 100644 --- a/fmp/fmp_type.go +++ b/fmp/fmp_type.go @@ -47,10 +47,11 @@ type FmpDictEntry struct { } type FmpTable struct { + ID uint64 Name string } -func (dict *FmpDict) get(path []uint64) *FmpDictEntry { +func (dict *FmpDict) GetEntry(path []uint64) *FmpDictEntry { for i, key := range path { _, ok := (*dict)[key] if !ok { @@ -61,20 +62,23 @@ func (dict *FmpDict) get(path []uint64) *FmpDictEntry { return (*dict)[key] } else { dict = (*dict)[key].Children + if dict == nil { + return nil + } } } return nil } -func (dict *FmpDict) getValue(path []uint64) []byte { - ent := dict.get(path) +func (dict *FmpDict) GetValue(path []uint64) []byte { + ent := dict.GetEntry(path) if ent != nil { return ent.Value } return nil } -func (dict *FmpDict) set(path []uint64, value []byte) { +func (dict *FmpDict) SetValue(path []uint64, value []byte) { for i, key := range path { _, ok := (*dict)[key] if !ok {