mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 04:02:26 -05:00 
			
		
		
		
	* start moving to bun * changing more stuff * more * and yet more * tests passing * seems stable now * more big changes * small fix * little fixes
		
			
				
	
	
		
			110 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Package pgpassfile is a parser PostgreSQL .pgpass files.
 | |
| package pgpassfile
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"io"
 | |
| 	"os"
 | |
| 	"regexp"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| // Entry represents a line in a PG passfile.
 | |
| type Entry struct {
 | |
| 	Hostname string
 | |
| 	Port     string
 | |
| 	Database string
 | |
| 	Username string
 | |
| 	Password string
 | |
| }
 | |
| 
 | |
| // Passfile is the in memory data structure representing a PG passfile.
 | |
| type Passfile struct {
 | |
| 	Entries []*Entry
 | |
| }
 | |
| 
 | |
| // ReadPassfile reads the file at path and parses it into a Passfile.
 | |
| func ReadPassfile(path string) (*Passfile, error) {
 | |
| 	f, err := os.Open(path)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer f.Close()
 | |
| 
 | |
| 	return ParsePassfile(f)
 | |
| }
 | |
| 
 | |
| // ParsePassfile reads r and parses it into a Passfile.
 | |
| func ParsePassfile(r io.Reader) (*Passfile, error) {
 | |
| 	passfile := &Passfile{}
 | |
| 
 | |
| 	scanner := bufio.NewScanner(r)
 | |
| 	for scanner.Scan() {
 | |
| 		entry := parseLine(scanner.Text())
 | |
| 		if entry != nil {
 | |
| 			passfile.Entries = append(passfile.Entries, entry)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return passfile, scanner.Err()
 | |
| }
 | |
| 
 | |
| // Match (not colons or escaped colon or escaped backslash)+. Essentially gives a split on unescaped
 | |
| // colon.
 | |
| var colonSplitterRegexp = regexp.MustCompile("(([^:]|(\\:)))+")
 | |
| 
 | |
| // var colonSplitterRegexp = regexp.MustCompile("((?:[^:]|(?:\\:)|(?:\\\\))+)")
 | |
| 
 | |
| // parseLine parses a line into an *Entry. It returns nil on comment lines or any other unparsable
 | |
| // line.
 | |
| func parseLine(line string) *Entry {
 | |
| 	const (
 | |
| 		tmpBackslash = "\r"
 | |
| 		tmpColon     = "\n"
 | |
| 	)
 | |
| 
 | |
| 	line = strings.TrimSpace(line)
 | |
| 
 | |
| 	if strings.HasPrefix(line, "#") {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	line = strings.Replace(line, `\\`, tmpBackslash, -1)
 | |
| 	line = strings.Replace(line, `\:`, tmpColon, -1)
 | |
| 
 | |
| 	parts := strings.Split(line, ":")
 | |
| 	if len(parts) != 5 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	// Unescape escaped colons and backslashes
 | |
| 	for i := range parts {
 | |
| 		parts[i] = strings.Replace(parts[i], tmpBackslash, `\`, -1)
 | |
| 		parts[i] = strings.Replace(parts[i], tmpColon, `:`, -1)
 | |
| 	}
 | |
| 
 | |
| 	return &Entry{
 | |
| 		Hostname: parts[0],
 | |
| 		Port:     parts[1],
 | |
| 		Database: parts[2],
 | |
| 		Username: parts[3],
 | |
| 		Password: parts[4],
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // FindPassword finds the password for the provided hostname, port, database, and username. For a
 | |
| // Unix domain socket hostname must be set to "localhost". An empty string will be returned if no
 | |
| // match is found.
 | |
| //
 | |
| // See https://www.postgresql.org/docs/current/libpq-pgpass.html for more password file information.
 | |
| func (pf *Passfile) FindPassword(hostname, port, database, username string) (password string) {
 | |
| 	for _, e := range pf.Entries {
 | |
| 		if (e.Hostname == "*" || e.Hostname == hostname) &&
 | |
| 			(e.Port == "*" || e.Port == port) &&
 | |
| 			(e.Database == "*" || e.Database == database) &&
 | |
| 			(e.Username == "*" || e.Username == username) {
 | |
| 			return e.Password
 | |
| 		}
 | |
| 	}
 | |
| 	return ""
 | |
| }
 |