diff --git a/lib/config/config.go b/lib/config/config.go index 67c6f1400..6a5dea818 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -12,7 +12,6 @@ import ( "fmt" "io" "math/rand" - "net/url" "os" "path/filepath" "reflect" @@ -21,7 +20,6 @@ import ( "strconv" "strings" - "github.com/syncthing/syncthing/lib/osutil" "github.com/syncthing/syncthing/lib/protocol" "golang.org/x/crypto/bcrypt" ) @@ -94,270 +92,6 @@ func (cfg Configuration) Copy() Configuration { return newCfg } -type FolderConfiguration struct { - ID string `xml:"id,attr" json:"id"` - RawPath string `xml:"path,attr" json:"path"` - Devices []FolderDeviceConfiguration `xml:"device" json:"devices"` - ReadOnly bool `xml:"ro,attr" json:"readOnly"` - RescanIntervalS int `xml:"rescanIntervalS,attr" json:"rescanIntervalS"` - IgnorePerms bool `xml:"ignorePerms,attr" json:"ignorePerms"` - AutoNormalize bool `xml:"autoNormalize,attr" json:"autoNormalize"` - MinDiskFreePct float64 `xml:"minDiskFreePct" json:"minDiskFreePct"` - Versioning VersioningConfiguration `xml:"versioning" json:"versioning"` - Copiers int `xml:"copiers" json:"copiers"` // This defines how many files are handled concurrently. - Pullers int `xml:"pullers" json:"pullers"` // Defines how many blocks are fetched at the same time, possibly between separate copier routines. - Hashers int `xml:"hashers" json:"hashers"` // Less than one sets the value to the number of cores. These are CPU bound due to hashing. - Order PullOrder `xml:"order" json:"order"` - IgnoreDelete bool `xml:"ignoreDelete" json:"ignoreDelete"` - ScanProgressIntervalS int `xml:"scanProgressIntervalS" json:"scanProgressIntervalS"` // Set to a negative value to disable. Value of 0 will get replaced with value of 2 (default value) - PullerSleepS int `xml:"pullerSleepS" json:"pullerSleepS"` - PullerPauseS int `xml:"pullerPauseS" json:"pullerPauseS"` - MaxConflicts int `xml:"maxConflicts" json:"maxConflicts"` - - Invalid string `xml:"-" json:"invalid"` // Set at runtime when there is an error, not saved -} - -func (f FolderConfiguration) Copy() FolderConfiguration { - c := f - c.Devices = make([]FolderDeviceConfiguration, len(f.Devices)) - copy(c.Devices, f.Devices) - return c -} - -func (f FolderConfiguration) Path() string { - // This is intentionally not a pointer method, because things like - // cfg.Folders["default"].Path() should be valid. - - // Attempt tilde expansion; leave unchanged in case of error - if path, err := osutil.ExpandTilde(f.RawPath); err == nil { - f.RawPath = path - } - - // Attempt absolutification; leave unchanged in case of error - if !filepath.IsAbs(f.RawPath) { - // Abs() looks like a fairly expensive syscall on Windows, while - // IsAbs() is a whole bunch of string mangling. I think IsAbs() may be - // somewhat faster in the general case, hence the outer if... - if path, err := filepath.Abs(f.RawPath); err == nil { - f.RawPath = path - } - } - - // Attempt to enable long filename support on Windows. We may still not - // have an absolute path here if the previous steps failed. - if runtime.GOOS == "windows" && filepath.IsAbs(f.RawPath) && !strings.HasPrefix(f.RawPath, `\\`) { - return `\\?\` + f.RawPath - } - - return f.RawPath -} - -func (f *FolderConfiguration) CreateMarker() error { - if !f.HasMarker() { - marker := filepath.Join(f.Path(), ".stfolder") - fd, err := os.Create(marker) - if err != nil { - return err - } - fd.Close() - osutil.HideFile(marker) - } - - return nil -} - -func (f *FolderConfiguration) HasMarker() bool { - _, err := os.Stat(filepath.Join(f.Path(), ".stfolder")) - if err != nil { - return false - } - return true -} - -func (f *FolderConfiguration) DeviceIDs() []protocol.DeviceID { - deviceIDs := make([]protocol.DeviceID, len(f.Devices)) - for i, n := range f.Devices { - deviceIDs[i] = n.DeviceID - } - return deviceIDs -} - -type VersioningConfiguration struct { - Type string `xml:"type,attr" json:"type"` - Params map[string]string `json:"params"` -} - -type InternalVersioningConfiguration struct { - Type string `xml:"type,attr,omitempty"` - Params []InternalParam `xml:"param"` -} - -type InternalParam struct { - Key string `xml:"key,attr"` - Val string `xml:"val,attr"` -} - -func (c *VersioningConfiguration) MarshalXML(e *xml.Encoder, start xml.StartElement) error { - var tmp InternalVersioningConfiguration - tmp.Type = c.Type - for k, v := range c.Params { - tmp.Params = append(tmp.Params, InternalParam{k, v}) - } - - return e.EncodeElement(tmp, start) - -} - -func (c *VersioningConfiguration) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { - var tmp InternalVersioningConfiguration - err := d.DecodeElement(&tmp, &start) - if err != nil { - return err - } - - c.Type = tmp.Type - c.Params = make(map[string]string, len(tmp.Params)) - for _, p := range tmp.Params { - c.Params[p.Key] = p.Val - } - return nil -} - -type DeviceConfiguration struct { - DeviceID protocol.DeviceID `xml:"id,attr" json:"deviceID"` - Name string `xml:"name,attr,omitempty" json:"name"` - Addresses []string `xml:"address,omitempty" json:"addresses"` - Compression protocol.Compression `xml:"compression,attr" json:"compression"` - CertName string `xml:"certName,attr,omitempty" json:"certName"` - Introducer bool `xml:"introducer,attr" json:"introducer"` -} - -func (orig DeviceConfiguration) Copy() DeviceConfiguration { - c := orig - c.Addresses = make([]string, len(orig.Addresses)) - copy(c.Addresses, orig.Addresses) - return c -} - -type FolderDeviceConfiguration struct { - DeviceID protocol.DeviceID `xml:"id,attr" json:"deviceID"` -} - -type OptionsConfiguration struct { - ListenAddress []string `xml:"listenAddress" json:"listenAddress" default:"tcp://0.0.0.0:22000"` - GlobalAnnServers []string `xml:"globalAnnounceServer" json:"globalAnnounceServers" json:"globalAnnounceServer" default:"default"` - GlobalAnnEnabled bool `xml:"globalAnnounceEnabled" json:"globalAnnounceEnabled" default:"true"` - LocalAnnEnabled bool `xml:"localAnnounceEnabled" json:"localAnnounceEnabled" default:"true"` - LocalAnnPort int `xml:"localAnnouncePort" json:"localAnnouncePort" default:"21027"` - LocalAnnMCAddr string `xml:"localAnnounceMCAddr" json:"localAnnounceMCAddr" default:"[ff12::8384]:21027"` - RelayServers []string `xml:"relayServer" json:"relayServers" default:"dynamic+https://relays.syncthing.net/endpoint"` - MaxSendKbps int `xml:"maxSendKbps" json:"maxSendKbps"` - MaxRecvKbps int `xml:"maxRecvKbps" json:"maxRecvKbps"` - ReconnectIntervalS int `xml:"reconnectionIntervalS" json:"reconnectionIntervalS" default:"60"` - RelaysEnabled bool `xml:"relaysEnabled" json:"relaysEnabled" default:"true"` - RelayReconnectIntervalM int `xml:"relayReconnectIntervalM" json:"relayReconnectIntervalM" default:"10"` - RelayWithoutGlobalAnn bool `xml:"relayWithoutGlobalAnn" json:"relayWithoutGlobalAnn" default:"false"` - StartBrowser bool `xml:"startBrowser" json:"startBrowser" default:"true"` - UPnPEnabled bool `xml:"upnpEnabled" json:"upnpEnabled" default:"true"` - UPnPLeaseM int `xml:"upnpLeaseMinutes" json:"upnpLeaseMinutes" default:"60"` - UPnPRenewalM int `xml:"upnpRenewalMinutes" json:"upnpRenewalMinutes" default:"30"` - UPnPTimeoutS int `xml:"upnpTimeoutSeconds" json:"upnpTimeoutSeconds" default:"10"` - URAccepted int `xml:"urAccepted" json:"urAccepted"` // Accepted usage reporting version; 0 for off (undecided), -1 for off (permanently) - URUniqueID string `xml:"urUniqueID" json:"urUniqueId"` // Unique ID for reporting purposes, regenerated when UR is turned on. - URURL string `xml:"urURL" json:"urURL" default:"https://data.syncthing.net/newdata"` - URPostInsecurely bool `xml:"urPostInsecurely" json:"urPostInsecurely" default:"false"` // For testing - URInitialDelayS int `xml:"urInitialDelayS" json:"urInitialDelayS" default:"1800"` - RestartOnWakeup bool `xml:"restartOnWakeup" json:"restartOnWakeup" default:"true"` - AutoUpgradeIntervalH int `xml:"autoUpgradeIntervalH" json:"autoUpgradeIntervalH" default:"12"` // 0 for off - KeepTemporariesH int `xml:"keepTemporariesH" json:"keepTemporariesH" default:"24"` // 0 for off - CacheIgnoredFiles bool `xml:"cacheIgnoredFiles" json:"cacheIgnoredFiles" default:"true"` - ProgressUpdateIntervalS int `xml:"progressUpdateIntervalS" json:"progressUpdateIntervalS" default:"5"` - SymlinksEnabled bool `xml:"symlinksEnabled" json:"symlinksEnabled" default:"true"` - LimitBandwidthInLan bool `xml:"limitBandwidthInLan" json:"limitBandwidthInLan" default:"false"` - DatabaseBlockCacheMiB int `xml:"databaseBlockCacheMiB" json:"databaseBlockCacheMiB" default:"0"` - MinHomeDiskFreePct float64 `xml:"minHomeDiskFreePct" json:"minHomeDiskFreePct" default:"1"` - ReleasesURL string `xml:"releasesURL" json:"releasesURL" default:"https://api.github.com/repos/syncthing/syncthing/releases?per_page=30"` - AlwaysLocalNets []string `xml:"alwaysLocalNet" json:"alwaysLocalNets"` -} - -func (orig OptionsConfiguration) Copy() OptionsConfiguration { - c := orig - c.ListenAddress = make([]string, len(orig.ListenAddress)) - copy(c.ListenAddress, orig.ListenAddress) - c.GlobalAnnServers = make([]string, len(orig.GlobalAnnServers)) - copy(c.GlobalAnnServers, orig.GlobalAnnServers) - return c -} - -type GUIConfiguration struct { - Enabled bool `xml:"enabled,attr" json:"enabled" default:"true"` - RawAddress string `xml:"address" json:"address" default:"127.0.0.1:8384"` - User string `xml:"user,omitempty" json:"user"` - Password string `xml:"password,omitempty" json:"password"` - RawUseTLS bool `xml:"tls,attr" json:"useTLS"` - RawAPIKey string `xml:"apikey,omitempty" json:"apiKey"` -} - -func (c GUIConfiguration) Address() string { - if override := os.Getenv("STGUIADDRESS"); override != "" { - // This value may be of the form "scheme://address:port" or just - // "address:port". We need to chop off the scheme. We try to parse it as - // an URL if it contains a slash. If that fails, return it as is and let - // some other error handling handle it. - - if strings.Contains(override, "/") { - url, err := url.Parse(override) - if err != nil { - return override - } - return url.Host - } - - return override - } - - return c.RawAddress -} - -func (c GUIConfiguration) UseTLS() bool { - if override := os.Getenv("STGUIADDRESS"); override != "" { - return strings.HasPrefix(override, "https:") - } - return c.RawUseTLS -} - -func (c GUIConfiguration) URL() string { - u := url.URL{ - Scheme: "http", - Host: c.Address(), - Path: "/", - } - - if c.UseTLS() { - u.Scheme = "https" - } - - if strings.HasPrefix(u.Host, ":") { - // Empty host, i.e. ":port", use IPv4 localhost - u.Host = "127.0.0.1" + u.Host - } else if strings.HasPrefix(u.Host, "0.0.0.0:") { - // IPv4 all zeroes host, convert to IPv4 localhost - u.Host = "127.0.0.1" + u.Host[7:] - } else if strings.HasPrefix(u.Host, "[::]:") { - // IPv6 all zeroes host, convert to IPv6 localhost - u.Host = "[::1]" + u.Host[4:] - } - - return u.String() -} - -func (c GUIConfiguration) APIKey() string { - if override := os.Getenv("STGUIAPIKEY"); override != "" { - return override - } - return c.RawAPIKey -} - func New(myID protocol.DeviceID) Configuration { var cfg Configuration cfg.Version = CurrentVersion @@ -811,30 +545,6 @@ loop: return devices[0:count] } -type DeviceConfigurationList []DeviceConfiguration - -func (l DeviceConfigurationList) Less(a, b int) bool { - return l[a].DeviceID.Compare(l[b].DeviceID) == -1 -} -func (l DeviceConfigurationList) Swap(a, b int) { - l[a], l[b] = l[b], l[a] -} -func (l DeviceConfigurationList) Len() int { - return len(l) -} - -type FolderDeviceConfigurationList []FolderDeviceConfiguration - -func (l FolderDeviceConfigurationList) Less(a, b int) bool { - return l[a].DeviceID.Compare(l[b].DeviceID) == -1 -} -func (l FolderDeviceConfigurationList) Swap(a, b int) { - l[a], l[b] = l[b], l[a] -} -func (l FolderDeviceConfigurationList) Len() int { - return len(l) -} - // randomCharset contains the characters that can make up a randomString(). const randomCharset = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" @@ -847,57 +557,3 @@ func randomString(l int) string { } return string(bs) } - -type PullOrder int - -const ( - OrderRandom PullOrder = iota // default is random - OrderAlphabetic - OrderSmallestFirst - OrderLargestFirst - OrderOldestFirst - OrderNewestFirst -) - -func (o PullOrder) String() string { - switch o { - case OrderRandom: - return "random" - case OrderAlphabetic: - return "alphabetic" - case OrderSmallestFirst: - return "smallestFirst" - case OrderLargestFirst: - return "largestFirst" - case OrderOldestFirst: - return "oldestFirst" - case OrderNewestFirst: - return "newestFirst" - default: - return "unknown" - } -} - -func (o PullOrder) MarshalText() ([]byte, error) { - return []byte(o.String()), nil -} - -func (o *PullOrder) UnmarshalText(bs []byte) error { - switch string(bs) { - case "random": - *o = OrderRandom - case "alphabetic": - *o = OrderAlphabetic - case "smallestFirst": - *o = OrderSmallestFirst - case "largestFirst": - *o = OrderLargestFirst - case "oldestFirst": - *o = OrderOldestFirst - case "newestFirst": - *o = OrderNewestFirst - default: - *o = OrderRandom - } - return nil -} diff --git a/lib/config/deviceconfiguration.go b/lib/config/deviceconfiguration.go new file mode 100644 index 000000000..cc479d546 --- /dev/null +++ b/lib/config/deviceconfiguration.go @@ -0,0 +1,39 @@ +// Copyright (C) 2014 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. + +package config + +import "github.com/syncthing/syncthing/lib/protocol" + +type DeviceConfiguration struct { + DeviceID protocol.DeviceID `xml:"id,attr" json:"deviceID"` + Name string `xml:"name,attr,omitempty" json:"name"` + Addresses []string `xml:"address,omitempty" json:"addresses"` + Compression protocol.Compression `xml:"compression,attr" json:"compression"` + CertName string `xml:"certName,attr,omitempty" json:"certName"` + Introducer bool `xml:"introducer,attr" json:"introducer"` +} + +func (orig DeviceConfiguration) Copy() DeviceConfiguration { + c := orig + c.Addresses = make([]string, len(orig.Addresses)) + copy(c.Addresses, orig.Addresses) + return c +} + +type DeviceConfigurationList []DeviceConfiguration + +func (l DeviceConfigurationList) Less(a, b int) bool { + return l[a].DeviceID.Compare(l[b].DeviceID) == -1 +} + +func (l DeviceConfigurationList) Swap(a, b int) { + l[a], l[b] = l[b], l[a] +} + +func (l DeviceConfigurationList) Len() int { + return len(l) +} diff --git a/lib/config/folderconfiguration.go b/lib/config/folderconfiguration.go new file mode 100644 index 000000000..23562717e --- /dev/null +++ b/lib/config/folderconfiguration.go @@ -0,0 +1,123 @@ +// Copyright (C) 2014 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. + +package config + +import ( + "os" + "path/filepath" + "runtime" + "strings" + + "github.com/syncthing/syncthing/lib/osutil" + "github.com/syncthing/syncthing/lib/protocol" +) + +type FolderConfiguration struct { + ID string `xml:"id,attr" json:"id"` + RawPath string `xml:"path,attr" json:"path"` + Devices []FolderDeviceConfiguration `xml:"device" json:"devices"` + ReadOnly bool `xml:"ro,attr" json:"readOnly"` + RescanIntervalS int `xml:"rescanIntervalS,attr" json:"rescanIntervalS"` + IgnorePerms bool `xml:"ignorePerms,attr" json:"ignorePerms"` + AutoNormalize bool `xml:"autoNormalize,attr" json:"autoNormalize"` + MinDiskFreePct float64 `xml:"minDiskFreePct" json:"minDiskFreePct"` + Versioning VersioningConfiguration `xml:"versioning" json:"versioning"` + Copiers int `xml:"copiers" json:"copiers"` // This defines how many files are handled concurrently. + Pullers int `xml:"pullers" json:"pullers"` // Defines how many blocks are fetched at the same time, possibly between separate copier routines. + Hashers int `xml:"hashers" json:"hashers"` // Less than one sets the value to the number of cores. These are CPU bound due to hashing. + Order PullOrder `xml:"order" json:"order"` + IgnoreDelete bool `xml:"ignoreDelete" json:"ignoreDelete"` + ScanProgressIntervalS int `xml:"scanProgressIntervalS" json:"scanProgressIntervalS"` // Set to a negative value to disable. Value of 0 will get replaced with value of 2 (default value) + PullerSleepS int `xml:"pullerSleepS" json:"pullerSleepS"` + PullerPauseS int `xml:"pullerPauseS" json:"pullerPauseS"` + MaxConflicts int `xml:"maxConflicts" json:"maxConflicts"` + + Invalid string `xml:"-" json:"invalid"` // Set at runtime when there is an error, not saved +} + +type FolderDeviceConfiguration struct { + DeviceID protocol.DeviceID `xml:"id,attr" json:"deviceID"` +} + +func (f FolderConfiguration) Copy() FolderConfiguration { + c := f + c.Devices = make([]FolderDeviceConfiguration, len(f.Devices)) + copy(c.Devices, f.Devices) + return c +} + +func (f FolderConfiguration) Path() string { + // This is intentionally not a pointer method, because things like + // cfg.Folders["default"].Path() should be valid. + + // Attempt tilde expansion; leave unchanged in case of error + if path, err := osutil.ExpandTilde(f.RawPath); err == nil { + f.RawPath = path + } + + // Attempt absolutification; leave unchanged in case of error + if !filepath.IsAbs(f.RawPath) { + // Abs() looks like a fairly expensive syscall on Windows, while + // IsAbs() is a whole bunch of string mangling. I think IsAbs() may be + // somewhat faster in the general case, hence the outer if... + if path, err := filepath.Abs(f.RawPath); err == nil { + f.RawPath = path + } + } + + // Attempt to enable long filename support on Windows. We may still not + // have an absolute path here if the previous steps failed. + if runtime.GOOS == "windows" && filepath.IsAbs(f.RawPath) && !strings.HasPrefix(f.RawPath, `\\`) { + return `\\?\` + f.RawPath + } + + return f.RawPath +} + +func (f *FolderConfiguration) CreateMarker() error { + if !f.HasMarker() { + marker := filepath.Join(f.Path(), ".stfolder") + fd, err := os.Create(marker) + if err != nil { + return err + } + fd.Close() + osutil.HideFile(marker) + } + + return nil +} + +func (f *FolderConfiguration) HasMarker() bool { + _, err := os.Stat(filepath.Join(f.Path(), ".stfolder")) + if err != nil { + return false + } + return true +} + +func (f *FolderConfiguration) DeviceIDs() []protocol.DeviceID { + deviceIDs := make([]protocol.DeviceID, len(f.Devices)) + for i, n := range f.Devices { + deviceIDs[i] = n.DeviceID + } + return deviceIDs +} + +type FolderDeviceConfigurationList []FolderDeviceConfiguration + +func (l FolderDeviceConfigurationList) Less(a, b int) bool { + return l[a].DeviceID.Compare(l[b].DeviceID) == -1 +} + +func (l FolderDeviceConfigurationList) Swap(a, b int) { + l[a], l[b] = l[b], l[a] +} + +func (l FolderDeviceConfigurationList) Len() int { + return len(l) +} diff --git a/lib/config/guiconfiguration.go b/lib/config/guiconfiguration.go new file mode 100644 index 000000000..a2cdd3ab9 --- /dev/null +++ b/lib/config/guiconfiguration.go @@ -0,0 +1,82 @@ +// Copyright (C) 2014 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. + +package config + +import ( + "net/url" + "os" + "strings" +) + +type GUIConfiguration struct { + Enabled bool `xml:"enabled,attr" json:"enabled" default:"true"` + RawAddress string `xml:"address" json:"address" default:"127.0.0.1:8384"` + User string `xml:"user,omitempty" json:"user"` + Password string `xml:"password,omitempty" json:"password"` + RawUseTLS bool `xml:"tls,attr" json:"useTLS"` + RawAPIKey string `xml:"apikey,omitempty" json:"apiKey"` +} + +func (c GUIConfiguration) Address() string { + if override := os.Getenv("STGUIADDRESS"); override != "" { + // This value may be of the form "scheme://address:port" or just + // "address:port". We need to chop off the scheme. We try to parse it as + // an URL if it contains a slash. If that fails, return it as is and let + // some other error handling handle it. + + if strings.Contains(override, "/") { + url, err := url.Parse(override) + if err != nil { + return override + } + return url.Host + } + + return override + } + + return c.RawAddress +} + +func (c GUIConfiguration) UseTLS() bool { + if override := os.Getenv("STGUIADDRESS"); override != "" { + return strings.HasPrefix(override, "https:") + } + return c.RawUseTLS +} + +func (c GUIConfiguration) URL() string { + u := url.URL{ + Scheme: "http", + Host: c.Address(), + Path: "/", + } + + if c.UseTLS() { + u.Scheme = "https" + } + + if strings.HasPrefix(u.Host, ":") { + // Empty host, i.e. ":port", use IPv4 localhost + u.Host = "127.0.0.1" + u.Host + } else if strings.HasPrefix(u.Host, "0.0.0.0:") { + // IPv4 all zeroes host, convert to IPv4 localhost + u.Host = "127.0.0.1" + u.Host[7:] + } else if strings.HasPrefix(u.Host, "[::]:") { + // IPv6 all zeroes host, convert to IPv6 localhost + u.Host = "[::1]" + u.Host[4:] + } + + return u.String() +} + +func (c GUIConfiguration) APIKey() string { + if override := os.Getenv("STGUIAPIKEY"); override != "" { + return override + } + return c.RawAPIKey +} diff --git a/lib/config/optionsconfiguration.go b/lib/config/optionsconfiguration.go new file mode 100644 index 000000000..317bda5df --- /dev/null +++ b/lib/config/optionsconfiguration.go @@ -0,0 +1,53 @@ +// Copyright (C) 2014 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. + +package config + +type OptionsConfiguration struct { + ListenAddress []string `xml:"listenAddress" json:"listenAddress" default:"tcp://0.0.0.0:22000"` + GlobalAnnServers []string `xml:"globalAnnounceServer" json:"globalAnnounceServers" json:"globalAnnounceServer" default:"default"` + GlobalAnnEnabled bool `xml:"globalAnnounceEnabled" json:"globalAnnounceEnabled" default:"true"` + LocalAnnEnabled bool `xml:"localAnnounceEnabled" json:"localAnnounceEnabled" default:"true"` + LocalAnnPort int `xml:"localAnnouncePort" json:"localAnnouncePort" default:"21027"` + LocalAnnMCAddr string `xml:"localAnnounceMCAddr" json:"localAnnounceMCAddr" default:"[ff12::8384]:21027"` + RelayServers []string `xml:"relayServer" json:"relayServers" default:"dynamic+https://relays.syncthing.net/endpoint"` + MaxSendKbps int `xml:"maxSendKbps" json:"maxSendKbps"` + MaxRecvKbps int `xml:"maxRecvKbps" json:"maxRecvKbps"` + ReconnectIntervalS int `xml:"reconnectionIntervalS" json:"reconnectionIntervalS" default:"60"` + RelaysEnabled bool `xml:"relaysEnabled" json:"relaysEnabled" default:"true"` + RelayReconnectIntervalM int `xml:"relayReconnectIntervalM" json:"relayReconnectIntervalM" default:"10"` + RelayWithoutGlobalAnn bool `xml:"relayWithoutGlobalAnn" json:"relayWithoutGlobalAnn" default:"false"` + StartBrowser bool `xml:"startBrowser" json:"startBrowser" default:"true"` + UPnPEnabled bool `xml:"upnpEnabled" json:"upnpEnabled" default:"true"` + UPnPLeaseM int `xml:"upnpLeaseMinutes" json:"upnpLeaseMinutes" default:"60"` + UPnPRenewalM int `xml:"upnpRenewalMinutes" json:"upnpRenewalMinutes" default:"30"` + UPnPTimeoutS int `xml:"upnpTimeoutSeconds" json:"upnpTimeoutSeconds" default:"10"` + URAccepted int `xml:"urAccepted" json:"urAccepted"` // Accepted usage reporting version; 0 for off (undecided), -1 for off (permanently) + URUniqueID string `xml:"urUniqueID" json:"urUniqueId"` // Unique ID for reporting purposes, regenerated when UR is turned on. + URURL string `xml:"urURL" json:"urURL" default:"https://data.syncthing.net/newdata"` + URPostInsecurely bool `xml:"urPostInsecurely" json:"urPostInsecurely" default:"false"` // For testing + URInitialDelayS int `xml:"urInitialDelayS" json:"urInitialDelayS" default:"1800"` + RestartOnWakeup bool `xml:"restartOnWakeup" json:"restartOnWakeup" default:"true"` + AutoUpgradeIntervalH int `xml:"autoUpgradeIntervalH" json:"autoUpgradeIntervalH" default:"12"` // 0 for off + KeepTemporariesH int `xml:"keepTemporariesH" json:"keepTemporariesH" default:"24"` // 0 for off + CacheIgnoredFiles bool `xml:"cacheIgnoredFiles" json:"cacheIgnoredFiles" default:"true"` + ProgressUpdateIntervalS int `xml:"progressUpdateIntervalS" json:"progressUpdateIntervalS" default:"5"` + SymlinksEnabled bool `xml:"symlinksEnabled" json:"symlinksEnabled" default:"true"` + LimitBandwidthInLan bool `xml:"limitBandwidthInLan" json:"limitBandwidthInLan" default:"false"` + DatabaseBlockCacheMiB int `xml:"databaseBlockCacheMiB" json:"databaseBlockCacheMiB" default:"0"` + MinHomeDiskFreePct float64 `xml:"minHomeDiskFreePct" json:"minHomeDiskFreePct" default:"1"` + ReleasesURL string `xml:"releasesURL" json:"releasesURL" default:"https://api.github.com/repos/syncthing/syncthing/releases?per_page=30"` + AlwaysLocalNets []string `xml:"alwaysLocalNet" json:"alwaysLocalNets"` +} + +func (orig OptionsConfiguration) Copy() OptionsConfiguration { + c := orig + c.ListenAddress = make([]string, len(orig.ListenAddress)) + copy(c.ListenAddress, orig.ListenAddress) + c.GlobalAnnServers = make([]string, len(orig.GlobalAnnServers)) + copy(c.GlobalAnnServers, orig.GlobalAnnServers) + return c +} diff --git a/lib/config/pulorder.go b/lib/config/pulorder.go new file mode 100644 index 000000000..310dc3533 --- /dev/null +++ b/lib/config/pulorder.go @@ -0,0 +1,61 @@ +// Copyright (C) 2014 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. + +package config + +type PullOrder int + +const ( + OrderRandom PullOrder = iota // default is random + OrderAlphabetic + OrderSmallestFirst + OrderLargestFirst + OrderOldestFirst + OrderNewestFirst +) + +func (o PullOrder) String() string { + switch o { + case OrderRandom: + return "random" + case OrderAlphabetic: + return "alphabetic" + case OrderSmallestFirst: + return "smallestFirst" + case OrderLargestFirst: + return "largestFirst" + case OrderOldestFirst: + return "oldestFirst" + case OrderNewestFirst: + return "newestFirst" + default: + return "unknown" + } +} + +func (o PullOrder) MarshalText() ([]byte, error) { + return []byte(o.String()), nil +} + +func (o *PullOrder) UnmarshalText(bs []byte) error { + switch string(bs) { + case "random": + *o = OrderRandom + case "alphabetic": + *o = OrderAlphabetic + case "smallestFirst": + *o = OrderSmallestFirst + case "largestFirst": + *o = OrderLargestFirst + case "oldestFirst": + *o = OrderOldestFirst + case "newestFirst": + *o = OrderNewestFirst + default: + *o = OrderRandom + } + return nil +} diff --git a/lib/config/versioningconfiguration.go b/lib/config/versioningconfiguration.go new file mode 100644 index 000000000..a8a886c90 --- /dev/null +++ b/lib/config/versioningconfiguration.go @@ -0,0 +1,50 @@ +// Copyright (C) 2014 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. + +package config + +import "encoding/xml" + +type VersioningConfiguration struct { + Type string `xml:"type,attr" json:"type"` + Params map[string]string `json:"params"` +} + +type InternalVersioningConfiguration struct { + Type string `xml:"type,attr,omitempty"` + Params []InternalParam `xml:"param"` +} + +type InternalParam struct { + Key string `xml:"key,attr"` + Val string `xml:"val,attr"` +} + +func (c *VersioningConfiguration) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + var tmp InternalVersioningConfiguration + tmp.Type = c.Type + for k, v := range c.Params { + tmp.Params = append(tmp.Params, InternalParam{k, v}) + } + + return e.EncodeElement(tmp, start) + +} + +func (c *VersioningConfiguration) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var tmp InternalVersioningConfiguration + err := d.DecodeElement(&tmp, &start) + if err != nil { + return err + } + + c.Type = tmp.Type + c.Params = make(map[string]string, len(tmp.Params)) + for _, p := range tmp.Params { + c.Params[p.Key] = p.Val + } + return nil +}