func main() { flag.Parse() file := *flagConfigFile if !filepath.IsAbs(file) { file = filepath.Join(osutil.CamliConfigDir(), file) } config, err := serverconfig.Load(file) if err != nil { exitFailure("Could not load server config: %v", err) } ws := webserver.New() baseURL := ws.BaseURL() { cert, key := config.OptionalString("TLSCertFile", ""), config.OptionalString("TLSKeyFile", "") if (cert != "") != (key != "") { exitFailure("TLSCertFile and TLSKeyFile must both be either present or absent") } if cert != "" { ws.SetTLS(cert, key) } } err = config.InstallHandlers(ws, baseURL) if err != nil { exitFailure("Error parsing config: %v", err) } ws.Listen() if config.UIPath != "" { uiURL := ws.BaseURL() + config.UIPath log.Printf("UI available at %s", uiURL) if runtime.GOOS == "windows" { // Might be double-clicking an icon with no shell window? // Just open the URL for them. osutil.OpenURL(uiURL) } } ws.Serve() }
func doInit() { blobDir := path.Join(osutil.CamliConfigDir(), "keyblobs") os.Mkdir(osutil.CamliConfigDir(), 0700) os.Mkdir(blobDir, 0700) keyId := *flagGpgKey if keyId == "" { keyId = os.Getenv("GPGKEY") } if keyId == "" { // TODO: run and parse gpg --list-secret-keys and see if there's just one and suggest that? Or show // a list of them? log.Fatalf("Initialization requires your public GPG key. Set --gpgkey=<pubid> or set $GPGKEY in your environment. Run gpg --list-secret-keys to find their key IDs.") } if os.Getenv("GPG_AGENT_INFO") == "" { log.Printf("No GPG_AGENT_INFO found in environment; you should setup gnupg-agent. camput will be annoying otherwise.") } // TODO: use same command-line flag as the jsonsign package. // unify them into a shared package just for gpg-related stuff? keyBytes, err := exec.Command("gpg", "--export", "--armor", keyId).Output() if err != nil { log.Fatalf("Error running gpg to export public key: %v", err) } hash := sha1.New() hash.Write(keyBytes) bref := blobref.FromHash("sha1", hash) keyBlobPath := path.Join(blobDir, bref.String()+".camli") if err = ioutil.WriteFile(keyBlobPath, keyBytes, 0644); err != nil { log.Fatalf("Error writing public key blob to %q: %v", keyBlobPath, err) } if ok, err := jsonsign.VerifyPublicKeyFile(keyBlobPath, keyId); !ok { log.Fatalf("Error verifying public key at %q: %v", keyBlobPath, err) } log.Printf("Your Camlistore identity (your GPG public key's blobref) is: %s", bref.String()) _, err = os.Stat(client.ConfigFilePath()) if err == nil { log.Fatalf("Config file %q already exists; quitting without touching it.", client.ConfigFilePath()) } if f, err := os.OpenFile(client.ConfigFilePath(), os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600); err == nil { defer f.Close() m := make(map[string]interface{}) m["publicKeyBlobref"] = bref.String() blobPut := make([]map[string]string, 1) blobPut[0] = map[string]string{ "alias": "local", "host": "http://localhost:3179/", "password": "******", } m["blobPut"] = blobPut blobGet := make([]map[string]string, 2) blobGet[0] = map[string]string{ "alias": "keyblobs", "path": "$HOME/.camli/keyblobs", } blobGet[1] = map[string]string{ "alias": "local", "host": "http://localhost:3179/", "password": "******", } m["blobGet"] = blobGet jsonBytes, err := json.MarshalIndent(m, "", " ") if err != nil { log.Fatalf("JSON serialization error: %v", err) } _, err = f.Write(jsonBytes) if err != nil { log.Fatalf("Error writing to %q: %v", client.ConfigFilePath(), err) } log.Printf("Wrote %q; modify as necessary.", client.ConfigFilePath()) } }
func ConfigFilePath() string { return filepath.Join(osutil.CamliConfigDir(), "config") }
func NewConfigDirFetcher() *DirFetcher { configDir := filepath.Join(osutil.CamliConfigDir(), "keyblobs") return NewSimpleDirectoryFetcher(configDir) }
func main() { flag.Parse() configPath := *flagConfigFile if !filepath.IsAbs(configPath) { configPath = filepath.Join(osutil.CamliConfigDir(), configPath) } f, err := os.Open(configPath) if err != nil { exitFailure("error opening %s: %v", configPath, err) } defer f.Close() dj := json.NewDecoder(f) rootjson := make(map[string]interface{}) if err = dj.Decode(&rootjson); err != nil { extra := "" if serr, ok := err.(*json.SyntaxError); ok { if _, serr := f.Seek(0, os.SEEK_SET); serr != nil { log.Fatalf("seek error: %v", serr) } line, col, highlight := errorutil.HighlightBytePosition(f, serr.Offset) extra = fmt.Sprintf(":\nError at line %d, column %d (file offset %d):\n%s", line, col, serr.Offset, highlight) } exitFailure("error parsing JSON object in config file %s%s\n%v", osutil.UserServerConfigPath(), extra, err) } if err := jsonconfig.EvaluateExpressions(rootjson); err != nil { exitFailure("error expanding JSON config expressions in %s: %v", configPath, err) } ws := webserver.New() baseURL := ws.BaseURL() // Root configuration config := jsonconfig.Obj(rootjson) { cert, key := config.OptionalString("TLSCertFile", ""), config.OptionalString("TLSKeyFile", "") if (cert != "") != (key != "") { exitFailure("TLSCertFile and TLSKeyFile must both be either present or absent") } if cert != "" { ws.SetTLS(cert, key) } } auth.AccessPassword = config.OptionalString("password", "") if url := config.OptionalString("baseURL", ""); url != "" { baseURL = url } prefixes := config.RequiredObject("prefixes") if err := config.Validate(); err != nil { exitFailure("configuration error in root object's keys in %s: %v", configPath, err) } hl := &handlerLoader{ ws: ws, baseURL: baseURL, config: make(map[string]*handlerConfig), handler: make(map[string]interface{}), } for prefix, vei := range prefixes { if !strings.HasPrefix(prefix, "/") { exitFailure("prefix %q doesn't start with /", prefix) } if !strings.HasSuffix(prefix, "/") { exitFailure("prefix %q doesn't end with /", prefix) } pmap, ok := vei.(map[string]interface{}) if !ok { exitFailure("prefix %q value isn't an object", prefix) } pconf := jsonconfig.Obj(pmap) handlerType := pconf.RequiredString("handler") handlerArgs := pconf.OptionalObject("handlerArgs") if err := pconf.Validate(); err != nil { exitFailure("configuration error in prefix %s: %v", prefix, err) } h := &handlerConfig{ prefix: prefix, htype: handlerType, conf: handlerArgs, } hl.config[prefix] = h } hl.setupAll() ws.Serve() }