package pass import ( "bytes" "fmt" ) type pgpassrow struct { hostname string port string database string username string password string } type PassDb struct { db []pgpassrow cache map[string]*pgpassrow } func Load(file string, master []byte) (*PassDb, error) { data, err := DecryptFile(master, file) if err != nil { return nil, err } lines := bytes.Split(data, []byte{'\n'}) var rows []pgpassrow for i, line := range lines { line = bytes.TrimRight(line, "\n\r \t") if len(line) == 0 || line[0] == byte('#') { continue } fields := bytes.Split(line, []byte{':'}) if len(fields) != 5 { return nil, fmt.Errorf("błąd w pliku hasłeł %s:%d: niewłaściwa liczba pól", file, i) } rows = append(rows, pgpassrow{ hostname: string(fields[0]), port: string(fields[1]), database: string(fields[2]), username: string(fields[3]), password: string(fields[4]), }) } return &PassDb{ db: rows, cache: make(map[string]*pgpassrow), }, nil } func match(value string, pattern string) bool { return pattern == "*" || pattern == value } func (self *PassDb) FindPassword(host string, port uint, database string, user string) string { myport := fmt.Sprintf("%d", port) key := fmt.Sprintf("%s:%s:%s:%s", host, myport, database, user) cached, ok := self.cache[key] if ok { return cached.password } // pierwszy pasujący do wzorca for i := range self.db { if match(host, self.db[i].hostname) && match(myport, self.db[i].port) && match(database, self.db[i].database) && match(user, self.db[i].username) { self.cache[key] = &self.db[i] return self.db[i].password } } return "" }