Better explain what is happening in this file
This commit is contained in:
parent
2e0496c1f9
commit
8dfd494eaf
107
parser/parser.go
107
parser/parser.go
|
@ -450,48 +450,66 @@ func (f *ConfigurationFile) parseTextFile(path string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses a properties file and updates the values within it to match those that
|
// parsePropertiesFile parses a properties file and updates the values within it
|
||||||
// are passed. Writes the file once completed.
|
// to match those that are passed. Once completed the new file is written to the
|
||||||
|
// disk. This will cause comments not present at the head of the file to be
|
||||||
|
// removed unfortunately.
|
||||||
|
//
|
||||||
|
// Any UTF-8 value will be written back to the disk as their escaped value rather
|
||||||
|
// than the raw value There is no winning with this logic. This fixes a bug where
|
||||||
|
// users with hand rolled UTF-8 escape sequences would have all sorts of pain in
|
||||||
|
// their configurations because we were writing the UTF-8 literal characters which
|
||||||
|
// their games could not actually handle.
|
||||||
|
//
|
||||||
|
// However, by adding this fix to only store the escaped UTF-8 sequence we
|
||||||
|
// unwittingly introduced a "regression" that causes _other_ games to have issues
|
||||||
|
// because they can only handle the unescaped representations. I cannot think of
|
||||||
|
// a simple approach to this problem that doesn't just lead to more complicated
|
||||||
|
// cases and problems.
|
||||||
|
//
|
||||||
|
// So, if your game cannot handle parsing UTF-8 sequences that are escaped into
|
||||||
|
// the string, well, sucks. There are fewer of those games than there are games
|
||||||
|
// that have issues parsing the raw UTF-8 sequence into a string? Also how does
|
||||||
|
// one really know what the user intended at this point? We'd need to know if
|
||||||
|
// the value was escaped or not to begin with before setting it, which I suppose
|
||||||
|
// can work but jesus that is going to be some annoyingly complicated logic?
|
||||||
|
//
|
||||||
|
// @see https://github.com/pterodactyl/panel/issues/2308 (original)
|
||||||
|
// @see https://github.com/pterodactyl/panel/issues/3009 ("bug" introduced as result)
|
||||||
func (f *ConfigurationFile) parsePropertiesFile(path string) error {
|
func (f *ConfigurationFile) parsePropertiesFile(path string) error {
|
||||||
// Open the file.
|
|
||||||
f2, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var s strings.Builder
|
var s strings.Builder
|
||||||
|
// Open the file and attempt to load any comments that currenty exist at the start
|
||||||
// Get any header comments from the file.
|
// of the file. This is kind of a hack, but should work for a majority of users for
|
||||||
scanner := bufio.NewScanner(f2)
|
// the time being.
|
||||||
for scanner.Scan() {
|
if fd, err := os.Open(path); err != nil {
|
||||||
text := scanner.Text()
|
return errors.Wrap(err, "parser: could not open file for reading")
|
||||||
if len(text) > 0 && text[0] != '#' {
|
} else {
|
||||||
break
|
scanner := bufio.NewScanner(fd)
|
||||||
|
// Scan until we hit a line that is not a comment that actually has content
|
||||||
|
// on it. Keep appending the comments until that time.
|
||||||
|
for scanner.Scan() {
|
||||||
|
text := scanner.Text()
|
||||||
|
if len(text) > 0 && text[0] != '#' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
s.WriteString(text + "\n")
|
||||||
|
}
|
||||||
|
_ = fd.Close()
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return errors.WithStackIf(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.WriteString(text)
|
|
||||||
s.WriteString("\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the file.
|
|
||||||
_ = f2.Close()
|
|
||||||
|
|
||||||
// Handle any scanner errors.
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode the properties file.
|
|
||||||
p, err := properties.LoadFile(path, properties.UTF8)
|
p, err := properties.LoadFile(path, properties.UTF8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrap(err, "parser: could not load properties file for configuration update")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace any values that need to be replaced.
|
// Replace any values that need to be replaced.
|
||||||
for _, replace := range f.Replace {
|
for _, replace := range f.Replace {
|
||||||
data, err := f.LookupConfigurationValue(replace)
|
data, err := f.LookupConfigurationValue(replace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrap(err, "parser: failed to lookup configuration value")
|
||||||
}
|
}
|
||||||
|
|
||||||
v, ok := p.Get(replace.Match)
|
v, ok := p.Get(replace.Match)
|
||||||
|
@ -503,7 +521,7 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, _, err := p.Set(replace.Match, data); err != nil {
|
if _, _, err := p.Set(replace.Match, data); err != nil {
|
||||||
return err
|
return errors.Wrap(err, "parser: failed to set replacement value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,30 +531,11 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// This escape is intentional!
|
||||||
s.WriteString(key)
|
|
||||||
s.WriteByte('=')
|
|
||||||
// There is no winning with this logic. This fixes a bug where users with hand
|
|
||||||
// rolled UTF-8 escape sequences would have all sorts of pain in their configurations
|
|
||||||
// because we were writing the UTF-8 literal characters which their games could
|
|
||||||
// not actually handle.
|
|
||||||
//
|
//
|
||||||
// However, by adding this fix to only store the escaped UTF-8 sequence we unwittingly
|
// See the docblock for this function for more details, do not change this
|
||||||
// introduced a "regression" that causes _other_ games to have issues because they
|
// or you'll cause a flood of new issue reports no one wants to deal with.
|
||||||
// can only handle the unescaped representations. I cannot think of a simple approach
|
s.WriteString(key + "=" + strings.Trim(strconv.QuoteToASCII(value), "\"") + "\n")
|
||||||
// to this problem that doesn't just lead to more complicated cases and problems.
|
|
||||||
//
|
|
||||||
// So, if your game cannot handle parsing UTF-8 sequences that are escaped into
|
|
||||||
// the string, well, sucks. There are fewer of those games than there are games
|
|
||||||
// that have issues parsing the raw UTF-8 sequence into a string? Also how does one
|
|
||||||
// really know what the user intended at this point? We'd need to know if the value
|
|
||||||
// was escaped or not to begin with before setting it, which I suppose can work but
|
|
||||||
// jesus that is going to be some annoyingly complicated logic?
|
|
||||||
//
|
|
||||||
// @see https://github.com/pterodactyl/panel/issues/2308 (original)
|
|
||||||
// @see https://github.com/pterodactyl/panel/issues/3009 ("bug" introduced as result)
|
|
||||||
s.WriteString(strings.Trim(strconv.QuoteToASCII(value), `"`))
|
|
||||||
s.WriteString("\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the file for writing.
|
// Open the file for writing.
|
||||||
|
@ -548,7 +547,7 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error {
|
||||||
|
|
||||||
// Write the data to the file.
|
// Write the data to the file.
|
||||||
if _, err := w.Write([]byte(s.String())); err != nil {
|
if _, err := w.Write([]byte(s.String())); err != nil {
|
||||||
return err
|
return errors.Wrap(err, "parser: failed to write properties file to disk")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue
Block a user