github.com/jonasnick/go-ethereum@v0.7.12-0.20150216215225-22176f05d387/ethutil/package.go (about)

     1  package ethutil
     2  
     3  import (
     4  	"archive/zip"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"io/ioutil"
     9  	"strings"
    10  )
    11  
    12  // Manifest object
    13  //
    14  // The manifest object holds all the relevant information supplied with the
    15  // the manifest specified in the package
    16  type Manifest struct {
    17  	Entry         string
    18  	Height, Width int
    19  }
    20  
    21  // External package
    22  //
    23  // External package contains the main html file and manifest
    24  type ExtPackage struct {
    25  	EntryHtml string
    26  	Manifest  *Manifest
    27  }
    28  
    29  // Read file
    30  //
    31  // Read a given compressed file and returns the read bytes.
    32  // Returns an error otherwise
    33  func ReadFile(f *zip.File) ([]byte, error) {
    34  	rc, err := f.Open()
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  	defer rc.Close()
    39  
    40  	content, err := ioutil.ReadAll(rc)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	return content, nil
    46  }
    47  
    48  // Reads manifest
    49  //
    50  // Reads and returns a manifest object. Returns error otherwise
    51  func ReadManifest(m []byte) (*Manifest, error) {
    52  	var manifest Manifest
    53  
    54  	dec := json.NewDecoder(strings.NewReader(string(m)))
    55  	if err := dec.Decode(&manifest); err == io.EOF {
    56  	} else if err != nil {
    57  		return nil, err
    58  	}
    59  
    60  	return &manifest, nil
    61  }
    62  
    63  // Find file in archive
    64  //
    65  // Returns the index of the given file name if it exists. -1 if file not found
    66  func FindFileInArchive(fn string, files []*zip.File) (index int) {
    67  	index = -1
    68  	// Find the manifest first
    69  	for i, f := range files {
    70  		if f.Name == fn {
    71  			index = i
    72  		}
    73  	}
    74  
    75  	return
    76  }
    77  
    78  // Open package
    79  //
    80  // Opens a prepared ethereum package
    81  // Reads the manifest file and determines file contents and returns and
    82  // the external package.
    83  func OpenPackage(fn string) (*ExtPackage, error) {
    84  	r, err := zip.OpenReader(fn)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	defer r.Close()
    89  
    90  	manifestIndex := FindFileInArchive("manifest.json", r.File)
    91  
    92  	if manifestIndex < 0 {
    93  		return nil, fmt.Errorf("No manifest file found in archive")
    94  	}
    95  
    96  	f, err := ReadFile(r.File[manifestIndex])
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  
   101  	manifest, err := ReadManifest(f)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	if manifest.Entry == "" {
   107  		return nil, fmt.Errorf("Entry file specified but appears to be empty: %s", manifest.Entry)
   108  	}
   109  
   110  	entryIndex := FindFileInArchive(manifest.Entry, r.File)
   111  	if entryIndex < 0 {
   112  		return nil, fmt.Errorf("Entry file not found: '%s'", manifest.Entry)
   113  	}
   114  
   115  	f, err = ReadFile(r.File[entryIndex])
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  
   120  	extPackage := &ExtPackage{string(f), manifest}
   121  
   122  	return extPackage, nil
   123  }