|
@@ -0,0 +1,123 @@
|
|
|
|
|
+package ethutil
|
|
|
|
|
+
|
|
|
|
|
+import (
|
|
|
|
|
+ "archive/zip"
|
|
|
|
|
+ "encoding/json"
|
|
|
|
|
+ "fmt"
|
|
|
|
|
+ "io"
|
|
|
|
|
+ "io/ioutil"
|
|
|
|
|
+ "strings"
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+// Manifest object
|
|
|
|
|
+//
|
|
|
|
|
+// The manifest object holds all the relevant information supplied with the
|
|
|
|
|
+// the manifest specified in the package
|
|
|
|
|
+type Manifest struct {
|
|
|
|
|
+ Entry string
|
|
|
|
|
+ Height, Width int
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// External package
|
|
|
|
|
+//
|
|
|
|
|
+// External package contains the main html file and manifest
|
|
|
|
|
+type ExtPackage struct {
|
|
|
|
|
+ EntryHtml string
|
|
|
|
|
+ Manifest *Manifest
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Read file
|
|
|
|
|
+//
|
|
|
|
|
+// Read a given compressed file and returns the read bytes.
|
|
|
|
|
+// Returns an error otherwise
|
|
|
|
|
+func ReadFile(f *zip.File) ([]byte, error) {
|
|
|
|
|
+ rc, err := f.Open()
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
|
|
+ defer rc.Close()
|
|
|
|
|
+
|
|
|
|
|
+ content, err := ioutil.ReadAll(rc)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return content, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Reads manifest
|
|
|
|
|
+//
|
|
|
|
|
+// Reads and returns a manifest object. Returns error otherwise
|
|
|
|
|
+func ReadManifest(m []byte) (*Manifest, error) {
|
|
|
|
|
+ var manifest Manifest
|
|
|
|
|
+
|
|
|
|
|
+ dec := json.NewDecoder(strings.NewReader(string(m)))
|
|
|
|
|
+ if err := dec.Decode(&manifest); err == io.EOF {
|
|
|
|
|
+ } else if err != nil {
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return &manifest, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Find file in archive
|
|
|
|
|
+//
|
|
|
|
|
+// Returns the index of the given file name if it exists. -1 if file not found
|
|
|
|
|
+func FindFileInArchive(fn string, files []*zip.File) (index int) {
|
|
|
|
|
+ index = -1
|
|
|
|
|
+ // Find the manifest first
|
|
|
|
|
+ for i, f := range files {
|
|
|
|
|
+ if f.Name == fn {
|
|
|
|
|
+ index = i
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Open package
|
|
|
|
|
+//
|
|
|
|
|
+// Opens a prepared ethereum package
|
|
|
|
|
+// Reads the manifest file and determines file contents and returns and
|
|
|
|
|
+// the external package.
|
|
|
|
|
+func OpenPackage(fn string) (*ExtPackage, error) {
|
|
|
|
|
+ r, err := zip.OpenReader(fn)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
|
|
+ defer r.Close()
|
|
|
|
|
+
|
|
|
|
|
+ manifestIndex := FindFileInArchive("manifest.json", r.File)
|
|
|
|
|
+
|
|
|
|
|
+ if manifestIndex < 0 {
|
|
|
|
|
+ return nil, fmt.Errorf("No manifest file found in archive")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ f, err := ReadFile(r.File[manifestIndex])
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ manifest, err := ReadManifest(f)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if manifest.Entry == "" {
|
|
|
|
|
+ return nil, fmt.Errorf("Entry file specified but appears to be empty: %s", manifest.Entry)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ entryIndex := FindFileInArchive(manifest.Entry, r.File)
|
|
|
|
|
+ if entryIndex < 0 {
|
|
|
|
|
+ return nil, fmt.Errorf("Entry file not found: '%s'", manifest.Entry)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ f, err = ReadFile(r.File[entryIndex])
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ extPackage := &ExtPackage{string(f), manifest}
|
|
|
|
|
+
|
|
|
|
|
+ return extPackage, nil
|
|
|
|
|
+}
|