-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathcookiestxt.go
111 lines (96 loc) · 2.55 KB
/
cookiestxt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright 2017 Meng Zhuo.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// Package cookiestxt implement parser of cookies txt format that commonly supported by
// curl / wget / aria2c / chrome / firefox
//
// see http://www.cookiecentral.com/faq/#3.5 for more detail
package cookiestxt
import (
"bufio"
"fmt"
"io"
"net/http"
"strconv"
"strings"
"time"
)
const (
// http://www.cookiecentral.com/faq/#3.5
// The domain that created AND that can read the variable.
domainIdx = iota
// A TRUE/FALSE value indicating if all machines within a given domain can access the variable. This value is set automatically by the browser, depending on the value you set for domain.
flagIdx
// The path within the domain that the variable is valid for.
pathIdx
// A TRUE/FALSE value indicating if a secure connection with the domain is needed to access the variable.
secureIdx
// The UNIX time that the variable will expire on. UNIX time is defined as the number of seconds since Jan 1, 1970 00:00:00 GMT.
expirationIdx
// The name of the variable.
nameIdx
// The value of the variable.
valueIdx
)
const (
httpOnlyPrefix = "#HttpOnly_"
fieldsCount = 7
)
// Parse cookie txt file format from input stream
func Parse(rd io.Reader) (cl []*http.Cookie, err error) {
scanner := bufio.NewScanner(rd)
var line int
for scanner.Scan() {
line++
trimed := strings.TrimSpace(scanner.Text())
if len(trimed) < fieldsCount {
continue
}
if trimed[0] == '#' && !strings.HasPrefix(trimed, httpOnlyPrefix) {
// comment
continue
}
var c *http.Cookie
c, err = ParseLine(scanner.Text())
if err != nil {
return cl, fmt.Errorf("cookiestxt line:%d, err:%s", line, err)
}
cl = append(cl, c)
line++
}
err = scanner.Err()
return
}
// ParseLine parse single cookie from one line
func ParseLine(raw string) (c *http.Cookie, err error) {
f := strings.Fields(raw)
if len(f) == fieldsCount-1 {
f = append(f, "")
} else if len(f) < fieldsCount {
err = fmt.Errorf("expecting fields=7, got=%d", len(f))
return
}
c = &http.Cookie{
Raw: raw,
Name: f[nameIdx],
Value: f[valueIdx],
Path: f[pathIdx],
MaxAge: 0,
Secure: parseBool(f[secureIdx]),
}
var ts int64
ts, err = strconv.ParseInt(f[expirationIdx], 10, 64)
if err != nil {
return
}
c.Expires = time.Unix(ts, 0)
c.Domain = f[domainIdx]
if strings.HasPrefix(c.Domain, httpOnlyPrefix) {
c.HttpOnly = true
c.Domain = c.Domain[len(httpOnlyPrefix):]
}
return
}
func parseBool(input string) bool {
return input == "TRUE"
}