go-tg-screenshot-bot
110 строк · 2.3 Кб
1package xgb
2
3/*
4auth.go contains functions to facilitate the parsing of .Xauthority files.
5
6It is largely unmodified from the original XGB package that I forked.
7*/
8
9import (
10"encoding/binary"
11"errors"
12"io"
13"os"
14)
15
16// readAuthority reads the X authority file for the DISPLAY.
17// If hostname == "" or hostname == "localhost",
18// then use the system's hostname (as returned by os.Hostname) instead.
19func readAuthority(hostname, display string) (
20name string, data []byte, err error) {
21
22// b is a scratch buffer to use and should be at least 256 bytes long
23// (i.e. it should be able to hold a hostname).
24b := make([]byte, 256)
25
26// As per /usr/include/X11/Xauth.h.
27const familyLocal = 256
28const familyWild = 65535
29
30if len(hostname) == 0 || hostname == "localhost" {
31hostname, err = os.Hostname()
32if err != nil {
33return "", nil, err
34}
35}
36
37fname := os.Getenv("XAUTHORITY")
38if len(fname) == 0 {
39home := os.Getenv("HOME")
40if len(home) == 0 {
41err = errors.New("Xauthority not found: $XAUTHORITY, $HOME not set")
42return "", nil, err
43}
44fname = home + "/.Xauthority"
45}
46
47r, err := os.Open(fname)
48if err != nil {
49return "", nil, err
50}
51defer r.Close()
52
53for {
54var family uint16
55if err := binary.Read(r, binary.BigEndian, &family); err != nil {
56return "", nil, err
57}
58
59addr, err := getString(r, b)
60if err != nil {
61return "", nil, err
62}
63
64disp, err := getString(r, b)
65if err != nil {
66return "", nil, err
67}
68
69name0, err := getString(r, b)
70if err != nil {
71return "", nil, err
72}
73
74data0, err := getBytes(r, b)
75if err != nil {
76return "", nil, err
77}
78
79addrmatch := (family == familyWild) ||
80(family == familyLocal && addr == hostname)
81dispmatch := (disp == "") || (disp == display)
82
83if addrmatch && dispmatch {
84return name0, data0, nil
85}
86}
87panic("unreachable")
88}
89
90func getBytes(r io.Reader, b []byte) ([]byte, error) {
91var n uint16
92if err := binary.Read(r, binary.BigEndian, &n); err != nil {
93return nil, err
94} else if n > uint16(len(b)) {
95return nil, errors.New("bytes too long for buffer")
96}
97
98if _, err := io.ReadFull(r, b[0:n]); err != nil {
99return nil, err
100}
101return b[0:n], nil
102}
103
104func getString(r io.Reader, b []byte) (string, error) {
105b, err := getBytes(r, b)
106if err != nil {
107return "", err
108}
109return string(b), nil
110}
111