/
ccookies.go
148 lines (138 loc) · 3.57 KB
/
ccookies.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Package ccookies provides a quick way to decode cookies from chromium based
// browsers.
//
// Some functions cribbed from kooky.
package ccookies
//go:generate ./gen.sh
import (
"context"
"database/sql"
"errors"
"fmt"
"net/http"
"net/http/cookiejar"
"net/url"
"strings"
"github.com/kenshaw/ccookies/models"
"golang.org/x/net/publicsuffix"
)
/*
vivaldi 88.0.4324.99 sqlite_master:
CREATE TABLE cookies(
creation_utc INTEGER NOT NULL,
host_key TEXT NOT NULL,
name TEXT NOT NULL,
value TEXT NOT NULL,
path TEXT NOT NULL,
expires_utc INTEGER NOT NULL,
is_secure INTEGER NOT NULL,
is_httponly INTEGER NOT NULL,
last_access_utc INTEGER NOT NULL,
has_expires INTEGER NOT NULL DEFAULT 1,
is_persistent INTEGER NOT NULL DEFAULT 1,
priority INTEGER NOT NULL DEFAULT 1,
encrypted_value BLOB DEFAULT '',
samesite INTEGER NOT NULL DEFAULT -1,
source_scheme INTEGER NOT NULL DEFAULT 0,
source_port INTEGER NOT NULL DEFAULT -1,
is_same_party INTEGER NOT NULL DEFAULT 0,
UNIQUE (host_key, name, path)
)
*/
// ReadContext reads the cookies from the provided sqlite3 file on disk.
func ReadContext(ctx context.Context, file, host string) ([]*http.Cookie, error) {
// check sqlite driver
driver := driverName()
if driver == "" {
return nil, errors.New("code using ccookies must import a sqlite driver!")
}
// open database
db, err := sql.Open(driver, file)
if err != nil {
return nil, err
}
defer db.Close()
// query func and params
f := models.Cookies
if host != "" {
f, host = models.CookiesLikeHost, "%"+strings.TrimPrefix(host, "%")
}
// exec and convert
res, err := f(ctx, db, host)
if err != nil {
return nil, err
}
return models.Convert(res), nil
}
// Read reads the cookies from the provided sqlite3 file on disk.
func Read(file, host string) ([]*http.Cookie, error) {
return ReadContext(context.Background(), file, host)
}
// Jar builds a cookie jar for the url from provided cookies.
func Jar(u *url.URL, cookies ...*http.Cookie) (http.CookieJar, error) {
// build jar
jar, err := cookiejar.New(&cookiejar.Options{
PublicSuffixList: publicsuffix.List,
})
if err != nil {
return nil, err
}
jar.SetCookies(u, cookies)
return jar, nil
}
// ReadJar reads the cookies from the provided sqlite3 file for the provided
// url into a cookie jar usable with http.Client.
func ReadJar(file, urlstr string) (http.CookieJar, error) {
// read cookies
u, err := url.Parse(urlstr)
if err != nil {
return nil, err
}
switch strings.ToLower(u.Scheme) {
case "http", "https", "ws", "wss":
default:
return nil, fmt.Errorf("invalid url scheme %q", u.Scheme)
}
cookies, err := Read(file, u.Host)
if err != nil {
return nil, err
}
return Jar(u, cookies...)
}
// ReadJarFiltered reads the cookies from the provided sqlite3 file for the
// provided url into a cookie jar (usable with http.Client) consisting of of
// cookies passed through filter func f.
func ReadJarFiltered(file, urlstr string, f func(*http.Cookie) bool) (http.CookieJar, error) {
// read cookies
u, err := url.Parse(urlstr)
if err != nil {
return nil, err
}
switch strings.ToLower(u.Scheme) {
case "http", "https", "ws", "wss":
default:
return nil, fmt.Errorf("invalid url scheme %q", u.Scheme)
}
cookies, err := Read(file, u.Host)
if err != nil {
return nil, err
}
// filter
var c []*http.Cookie
for _, cookie := range cookies {
if f(cookie) {
c = append(c, cookie)
}
}
return Jar(u, c...)
}
// driverName returns the first sqlite3 driver name it encounters.
func driverName() string {
for _, n := range sql.Drivers() {
switch n {
case "sqlite3", "sqlite":
return n
}
}
return ""
}