Skip to content

Commit

Permalink
magic number check/enforcement and spec version in show command [#27]
Browse files Browse the repository at this point in the history
  • Loading branch information
bdon committed Oct 27, 2022
1 parent 79c9f52 commit 6a77030
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 5 deletions.
17 changes: 15 additions & 2 deletions pmtiles/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"bytes"
"compress/gzip"
"encoding/binary"
"fmt"
)

type Compression uint8
Expand All @@ -30,6 +31,7 @@ const (
const HEADERV3_LEN_BYTES = 127

type HeaderV3 struct {
SpecVersion uint8
RootOffset uint64
RootLength uint64
MetadataOffset uint64
Expand Down Expand Up @@ -228,8 +230,19 @@ func serialize_header(header HeaderV3) []byte {
return b
}

func deserialize_header(d []byte) HeaderV3 {
func deserialize_header(d []byte) (HeaderV3, error) {
h := HeaderV3{}
magic_number := d[0:7]
if string(magic_number) != "PMTiles" {
return h, fmt.Errorf("Magic number not detected. Are you sure this is a PMTiles archive?")
}

spec_version := d[7]
if spec_version > uint8(3) {
return h, fmt.Errorf("Archive is spec version %d, but this program only supports version 3: upgrade your pmtiles program.", spec_version)
}

h.SpecVersion = spec_version
h.RootOffset = binary.LittleEndian.Uint64(d[8 : 8+8])
h.RootLength = binary.LittleEndian.Uint64(d[16 : 16+8])
h.MetadataOffset = binary.LittleEndian.Uint64(d[24 : 24+8])
Expand All @@ -255,7 +268,7 @@ func deserialize_header(d []byte) HeaderV3 {
h.CenterLonE7 = int32(binary.LittleEndian.Uint32(d[119 : 119+4]))
h.CenterLatE7 = int32(binary.LittleEndian.Uint32(d[123 : 123+4]))

return h
return h, nil
}

func build_roots_leaves(entries []EntryV3, leaf_size int) ([]byte, []byte, int) {
Expand Down
2 changes: 1 addition & 1 deletion pmtiles/directory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func TestHeaderRoundtrip(t *testing.T) {
header.CenterLonE7 = 3.1 * 10000000
header.CenterLatE7 = 3.2 * 10000000
b := serialize_header(header)
result := deserialize_header(b)
result, _ := deserialize_header(b)
if result.RootOffset != 1 {
t.Fatalf(`expected to be 1`)
}
Expand Down
6 changes: 5 additions & 1 deletion pmtiles/loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,11 @@ func (loop *Loop) Start() {
}

if is_root {
header := deserialize_header(b[0:HEADERV3_LEN_BYTES])
header, err := deserialize_header(b[0:HEADERV3_LEN_BYTES])
if err != nil {
loop.logger.Printf("parsing header failed: %v", err)
return
}

// populate the root first before header
root_entries := deserialize_entries(bytes.NewBuffer(b[header.RootOffset : header.RootOffset+header.RootLength]))
Expand Down
8 changes: 7 additions & 1 deletion pmtiles/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ func Show(logger *log.Logger, args []string) error {
}
r.Close()

header := deserialize_header(b[0:HEADERV3_LEN_BYTES])
header, err := deserialize_header(b[0:HEADERV3_LEN_BYTES])
if err != nil {
// check to see if it's a V2 file

return fmt.Errorf("Failed to read %s, %w", file, err)
}

if arg_z == "" {
var tile_type string
Expand All @@ -62,6 +67,7 @@ func Show(logger *log.Logger, args []string) error {
default:
tile_type = "Unknown"
}
fmt.Printf("pmtiles spec version: %d\n", header.SpecVersion)
fmt.Printf("total size: %s\n", humanize.Bytes(uint64(r.Size())))
fmt.Printf("tile type: %s\n", tile_type)
fmt.Printf("bounds: %f,%f %f,%f\n", float64(header.MinLonE7)/10000000, float64(header.MinLatE7)/10000000, float64(header.MaxLonE7)/10000000, float64(header.MaxLatE7)/10000000)
Expand Down

0 comments on commit 6a77030

Please sign in to comment.