Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / cmd / auth / cookieauth / cookieauth.go
1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // cookieauth uses a “Netscape cookie file” to implement the GOAUTH protocol
6 // described in https://golang.org/issue/26232.
7 // It expects the location of the file as the first command-line argument.
8 //
9 // Example GOAUTH usage:
10 //      export GOAUTH="cookieauth $(git config --get http.cookieFile)"
11 //
12 // See http://www.cookiecentral.com/faq/#3.5 for a description of the Netscape
13 // cookie file format.
14 package main
15
16 import (
17         "bufio"
18         "fmt"
19         "io"
20         "log"
21         "net/http"
22         "net/http/cookiejar"
23         "net/url"
24         "os"
25         "strconv"
26         "strings"
27         "time"
28         "unicode"
29 )
30
31 func main() {
32         if len(os.Args) < 2 {
33                 fmt.Fprintf(os.Stderr, "usage: %s COOKIEFILE [URL]\n", os.Args[0])
34                 os.Exit(2)
35         }
36
37         log.SetPrefix("cookieauth: ")
38
39         f, err := os.Open(os.Args[1])
40         if err != nil {
41                 log.Fatalf("failed to read cookie file: %v\n", os.Args[1])
42                 os.Exit(1)
43         }
44         defer f.Close()
45
46         var (
47                 targetURL  *url.URL
48                 targetURLs = map[string]*url.URL{}
49         )
50         if len(os.Args) == 3 {
51                 targetURL, err = url.ParseRequestURI(os.Args[2])
52                 if err != nil {
53                         log.Fatalf("invalid request URI (%v): %q\n", err, os.Args[2])
54                 }
55                 targetURLs[targetURL.String()] = targetURL
56         } else if len(os.Args) > 3 {
57                 // Extra arguments were passed: maybe the protocol was expanded?
58                 // We don't know how to interpret the request, so ignore it.
59                 return
60         }
61
62         entries, err := parseCookieFile(f.Name(), f)
63         if err != nil {
64                 log.Fatalf("error reading cookie file: %v\n", f.Name())
65         }
66
67         jar, err := cookiejar.New(nil)
68         if err != nil {
69                 log.Fatalf("failed to initialize cookie jar: %v\n", err)
70         }
71
72         for _, e := range entries {
73                 u := &url.URL{
74                         Scheme: "https",
75                         Host:   e.Host,
76                         Path:   e.Cookie.Path,
77                 }
78
79                 if targetURL == nil {
80                         targetURLs[u.String()] = u
81                 }
82
83                 jar.SetCookies(u, []*http.Cookie{&e.Cookie})
84         }
85
86         for _, u := range targetURLs {
87                 req := &http.Request{URL: u, Header: make(http.Header)}
88                 for _, c := range jar.Cookies(req.URL) {
89                         req.AddCookie(c)
90                 }
91                 fmt.Printf("%s\n\n", u)
92                 req.Header.Write(os.Stdout)
93                 fmt.Println()
94         }
95 }
96
97 type Entry struct {
98         Host   string
99         Cookie http.Cookie
100 }
101
102 // parseCookieFile parses a Netscape cookie file as described in
103 // http://www.cookiecentral.com/faq/#3.5.
104 func parseCookieFile(name string, r io.Reader) ([]*Entry, error) {
105         var entries []*Entry
106         s := bufio.NewScanner(r)
107         line := 0
108         for s.Scan() {
109                 line++
110                 text := strings.TrimSpace(s.Text())
111                 if len(text) < 2 || (text[0] == '#' && unicode.IsSpace(rune(text[1]))) {
112                         continue
113                 }
114
115                 e, err := parseCookieLine(text)
116                 if err != nil {
117                         log.Printf("%s:%d: %v\n", name, line, err)
118                         continue
119                 }
120                 entries = append(entries, e)
121         }
122         return entries, s.Err()
123 }
124
125 func parseCookieLine(line string) (*Entry, error) {
126         f := strings.Fields(line)
127         if len(f) < 7 {
128                 return nil, fmt.Errorf("found %d columns; want 7", len(f))
129         }
130
131         e := new(Entry)
132         c := &e.Cookie
133
134         if domain := f[0]; strings.HasPrefix(domain, "#HttpOnly_") {
135                 c.HttpOnly = true
136                 e.Host = strings.TrimPrefix(domain[10:], ".")
137         } else {
138                 e.Host = strings.TrimPrefix(domain, ".")
139         }
140
141         isDomain, err := strconv.ParseBool(f[1])
142         if err != nil {
143                 return nil, fmt.Errorf("non-boolean domain flag: %v", err)
144         }
145         if isDomain {
146                 c.Domain = e.Host
147         }
148
149         c.Path = f[2]
150
151         c.Secure, err = strconv.ParseBool(f[3])
152         if err != nil {
153                 return nil, fmt.Errorf("non-boolean secure flag: %v", err)
154         }
155
156         expiration, err := strconv.ParseInt(f[4], 10, 64)
157         if err != nil {
158                 return nil, fmt.Errorf("malformed expiration: %v", err)
159         }
160         c.Expires = time.Unix(expiration, 0)
161
162         c.Name = f[5]
163         c.Value = f[6]
164
165         return e, nil
166 }