func ParseFrontFQDNs(frontFQDNs string) (map[string]string, error) { fqdns := map[string]string{} if err := yaml.Unmarshal([]byte(frontFQDNs), fqdns); err != nil { return nil, err } return fqdns, nil }
// hasCustomChainedServer returns whether or not the config file at the specified // path includes a custom chained server or not. func hasCustomChainedServer(configPath, name string) bool { if !(strings.HasPrefix(name, "lantern") && strings.HasSuffix(name, ".yaml")) { log.Debugf("File name does not match") return false } bytes, err := ioutil.ReadFile(configPath) if err != nil { log.Errorf("Could not read file %v", err) return false } cfg := &Config{} err = yaml.Unmarshal(bytes, cfg) if err != nil { log.Errorf("Could not unmarshal config %v", err) return false } nc := len(cfg.Client.ChainedServers) log.Debugf("Found %v chained servers", nc) // The config will have more than one but fewer than 10 chained servers // if it has been given a custom config with a custom chained server // list return nc > 0 && nc < 10 }
// updateFrom creates a new Config by 'merging' the given yaml into this Config. // The masquerade sets, the collections of servers, and the trusted CAs in the // update yaml completely replace the ones in the original Config. func (updated *Config) updateFrom(updateBytes []byte) error { // XXX: does this need a mutex, along with everyone that uses the config? oldFrontedServers := updated.Client.FrontedServers oldChainedServers := updated.Client.ChainedServers oldMasqueradeSets := updated.Client.MasqueradeSets oldTrustedCAs := updated.TrustedCAs updated.Client.FrontedServers = []*client.FrontedServerInfo{} updated.Client.ChainedServers = map[string]*client.ChainedServerInfo{} updated.Client.MasqueradeSets = map[string][]*fronted.Masquerade{} updated.TrustedCAs = []*CA{} err := yaml.Unmarshal(updateBytes, updated) if err != nil { updated.Client.FrontedServers = oldFrontedServers updated.Client.ChainedServers = oldChainedServers updated.Client.MasqueradeSets = oldMasqueradeSets updated.TrustedCAs = oldTrustedCAs return fmt.Errorf("Unable to unmarshal YAML for update: %s", err) } // Deduplicate global proxiedsites if len(updated.ProxiedSites.Cloud) > 0 { wlDomains := make(map[string]bool) for _, domain := range updated.ProxiedSites.Cloud { wlDomains[domain] = true } updated.ProxiedSites.Cloud = make([]string, 0, len(wlDomains)) for domain, _ := range wlDomains { updated.ProxiedSites.Cloud = append(updated.ProxiedSites.Cloud, domain) } sort.Strings(updated.ProxiedSites.Cloud) } return nil }
// ReadSettingsFromFile reads PackagedSettings from the yaml file at the specified // path. func readSettingsFromFile(yamlPath string) (string, *PackagedSettings, error) { log.Debugf("Opening file at: %v", yamlPath) data, err := ioutil.ReadFile(yamlPath) if err != nil { // This will happen whenever there's no packaged settings, which is often log.Debugf("Error reading file %v", err) return "", &PackagedSettings{}, err } trimmed := strings.TrimSpace(string(data)) log.Debugf("Read bytes: %v", trimmed) if trimmed == "" { log.Debugf("Ignoring empty string") return "", &PackagedSettings{}, errors.New("Empty string") } var s PackagedSettings err = yaml.Unmarshal([]byte(trimmed), &s) if err != nil { log.Errorf("Could not read yaml: %v", err) return "", &PackagedSettings{}, err } return yamlPath, &s, nil }
func loadFallbacks() { if *fallbacksFile == "" { log.Error("Please specify a fallbacks file") flag.Usage() os.Exit(2) } fallbacksBytes, err := ioutil.ReadFile(*fallbacksFile) if err != nil { log.Fatalf("Unable to read fallbacks file at %s: %s", *fallbacksFile, err) } err = yaml.Unmarshal(fallbacksBytes, &fallbacks) if err != nil { log.Fatalf("Unable to unmarshal yaml from %v: %v", *fallbacksFile, err) } }
// Load loads the initial settings at startup, either from disk or using defaults. func LoadSettings(version, revisionDate, buildDate string) *Settings { log.Debug("Loading settings") // Create default settings that may or may not be overridden from an existing file // on disk. settings = &Settings{ AutoReport: true, AutoLaunch: true, ProxyAll: false, SystemProxy: true, } // Use settings from disk if they're available. if bytes, err := ioutil.ReadFile(path); err != nil { log.Debugf("Could not read file %v", err) } else if err := yaml.Unmarshal(bytes, settings); err != nil { log.Errorf("Could not load yaml %v", err) // Just keep going with the original settings not from disk. } else { log.Debugf("Loaded settings from %v", path) } if settings.AutoLaunch { launcher.CreateLaunchFile(settings.AutoLaunch) } // always override below 3 attributes as they are not meant to be persisted across versions settings.Version = version settings.BuildDate = buildDate settings.RevisionDate = revisionDate // Only configure the UI once. This will typically be the case in the normal // application flow, but tests might call Load twice, for example, which we // want to allow. once.Do(func() { err := settings.start() if err != nil { log.Errorf("Unable to register settings service: %q", err) return } go settings.read() }) return settings }
func (c *config) updateFrom(buf []byte) error { var err error var newCfg config // Attempt to parse configuration file. if err = yaml.Unmarshal(buf, &newCfg); err != nil { return err } // Making sure we can actually use this configuration. if len(newCfg.Client.FrontedServers) > 0 && len(newCfg.Client.MasqueradeSets) > 0 && len(newCfg.TrustedCAs) > 0 { if reflect.DeepEqual(newCfg, *c) { return errConfigurationUnchanged } *c = newCfg return nil } return errInvalidConfiguration }
func (m *Manager) reloadFromDisk() (bool, error) { cfg := m.EmptyConfig() fileInfo, err := os.Stat(m.FilePath) if err != nil { return false, fmt.Errorf("Unable to stat config file %s: %s", m.FilePath, err) } if m.fileInfo == fileInfo { log.Trace("Config unchanged on disk") return false, nil } bytes, err := ioutil.ReadFile(m.FilePath) if err != nil { return false, fmt.Errorf("Error reading config from %s: %s", m.FilePath, err) } err = yaml.Unmarshal(bytes, cfg) if err != nil { return false, fmt.Errorf("Error unmarshaling config yaml from %s: %s", m.FilePath, err) } if m.cfg != nil && m.cfg.GetVersion() != cfg.GetVersion() { log.Trace("Version mismatch on disk, overwriting what's on disk with current version") if err := m.writeToDisk(m.cfg); err != nil { log.Errorf("Unable to write to disk: %v", err) } return false, fmt.Errorf("Version of config on disk did not match expected. Expected %d, found %d", m.cfg.GetVersion(), cfg.GetVersion()) } if reflect.DeepEqual(m.cfg, cfg) { log.Trace("Config on disk is same as in memory, ignoring") return false, nil } log.Debugf("Configuration changed on disk, applying") m.setCfg(cfg) m.fileInfo = fileInfo return true, nil }
func (m *Manager) ServeHTTP(resp http.ResponseWriter, req *http.Request) { defer req.Body.Close() if len(req.URL.Path) < 2 { fail(resp, "Invalid path") } path := pathreflect.Parse(req.URL.Path[1:]) switch req.Method { case POST: body, err := ioutil.ReadAll(req.Body) if err != nil { log.Debugf("Error reading post to config server: %s", err) fail(resp, "Unable to read request body") return } err = m.Update(func(orig Config) error { defer func() { if r := recover(); r != nil { log.Errorf("Panic on updating %s: %s", path, r) } }() fragment, err := path.Get(orig) if err != nil { return fmt.Errorf("Unable to get current value at path %s: %s", path, err) } err = yaml.Unmarshal(body, fragment) if err != nil { return fmt.Errorf("Unable to unmarshal yaml fragment from body %s: %s", string(body), err) } return path.Set(orig, fragment) }) if err != nil { log.Debugf("Unable to update config: %s", err) fail(resp, "Unable to update config") return } case DELETE: err := m.Update(func(orig Config) error { defer func() { if r := recover(); r != nil { log.Errorf("Panic on clearing %s: %s", path, r) } }() return path.Clear(orig) }) if err != nil { log.Debugf("Unable to update config: %s", err) fail(resp, "Unable to update config") return } default: resp.WriteHeader(MethodNotAllowed) } }