func (c *Client) getFile(docID int) error {
	if _, found := c.lookupTable[strconv.Itoa(docID)]; !found {
		return errors.New("invalid document ID")
	}
	filename := path.Join(c.directory, c.lookupTable[strconv.Itoa(docID)])
	if _, err := os.Stat(filename); err == nil {
		return nil
	}
	content, err := c.server.GetFile(docID)
	if err != nil {
		return err
	}
	outfile, err := os.Create(filename)
	if err != nil {
		return err
	}
	outfile.Write(content)
	return nil
}
getFile fetches the file with `docID`, if that file cannot be found on the
local disk.
package client
import (
	"crypto/sha256"
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"search/prototype/indexer"
	"search/prototype/server"
	"search/prototype/util"
	"sort"
	"strconv"
	"strings"
)
type Client struct {
	directory     string                       
	server        *server.Server               
	indexer       *indexer.SecureIndexBuilder  
	lookupTable   map[string]string            
	reverseLookup map[string]string            
}
func CreateClient(s *server.Server, clientNum int, directory string) *Client {
	c := new(Client)
	c.server = s
	h := sha256.New()
	h.Write([]byte(strconv.Itoa(clientNum)))
	serverKeyHalf := s.GetKeyHalf(clientNum)
	ms := util.XorBytes(h.Sum(nil), serverKeyHalf, len(serverKeyHalf))
	c.indexer = indexer.CreateSecureIndexBuilder(sha256.New, ms, s.GetSalts(), s.GetSize())
	c.lookupTable = make(map[string]string)
	c.reverseLookup = make(map[string]string)
	if tableContent, found := s.ReadLookupTable(); found {
		json.Unmarshal(tableContent, &c.lookupTable)
		for key, value := range c.lookupTable {
			c.reverseLookup[value] = key
		}
	}
	c.directory = directory
	if _, err := os.Stat(directory); os.IsNotExist(err) {
		if os.Mkdir(directory, 0777) != nil {
			panic("cannot create the client directory")
		}
	}
	return c
}
func (c *Client) AddFile(filename string) error {
	_, file := path.Split(filename)
	if _, found := c.reverseLookup[file]; found {
		return errors.New("file already exists")
	}
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	docID, err := c.server.AddFile(content)
	if err != nil {
		return err
	}
	c.lookupTable[strconv.Itoa(docID)] = file
	c.reverseLookup[file] = strconv.Itoa(docID)
	table, err := json.Marshal(c.lookupTable)
	if err != nil {
		return err
	}
	c.server.WriteLookupTable(table)
	infile, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer infile.Close()
	si := c.indexer.BuildSecureIndex(docID, infile, len(content))
	err = c.server.WriteIndex(si)
	if err != nil {
		return err
	}
	outfile, err := os.Create(path.Join(c.directory, file))
	if err != nil {
		return err
	}
	defer outfile.Close()
	infile.Seek(0, 0)
	io.Copy(outfile, infile)
	return nil
}