Documentation
¶
Overview ¶
Package kooky contains routines to reach into cookie stores for various browsers and retrieve the cookies.
Example (ChromeSimpleMacOS) ¶
package main
import (
"fmt"
"os"
"github.com/j178/kooky/browser/chrome"
)
// on macOS:
var cookieStorePath = "/Google/Chrome/Default/Cookies"
func main() {
// construct file path for the sqlite database containing the cookies
dir, _ := os.UserConfigDir() // on macOS: "/<USER>/Library/Application Support/"
cookieStoreFile := dir + cookieStorePath
// read the cookies from the file
// decryption is handled automatically
cookies, err := chrome.ReadCookies(cookieStoreFile)
if err != nil {
// TODO: handle the error
return
}
for _, cookie := range cookies {
fmt.Println(cookie)
}
}
Example (CookieJar) ¶
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/url"
"strings"
"github.com/j178/kooky"
_ "github.com/j178/kooky/browser/firefox"
)
func main() {
stores := kooky.FindCookieStores()
var s kooky.CookieStore
for _, store := range stores {
if store.Browser() != `firefox` || !store.IsDefaultProfile() {
continue
}
s = store
break
}
// jar := s
// only store cookies relevant for the target website in the cookie jar
jar, _ := s.SubJar(kooky.Domain(`github.com`))
u, _ := url.Parse(`https://github.com/settings/profile`)
var loggedIn bool
cookies := kooky.FilterCookies(jar.Cookies(u), kooky.Name(`logged_in`))
if len(cookies) > 0 {
loggedIn = true
}
if !loggedIn {
log.Fatal(`not logged in`)
}
client := http.Client{Jar: jar}
resp, _ := client.Get(u.String())
body, _ := io.ReadAll(resp.Body)
if !strings.Contains(string(body), `id="user_profile_name"`) {
fmt.Print("not ")
}
fmt.Println("logged in")
}
Output: logged in
Index ¶
- func ExportCookies[T Cookie | http.Cookie](w io.Writer, cookies []*T)
- func FilterCookie[T Cookie | http.Cookie](cookie *T, filters ...Filter) bool
- func FilterCookies[T Cookie | http.Cookie](cookies []*T, filters ...Filter) []*T
- func RegisterFinder(browser string, finder CookieStoreFinder)
- type Cookie
- type CookieStore
- type CookieStoreFinder
- type Filter
- func CreationAfter(u time.Time) Filter
- func CreationBefore(u time.Time) Filter
- func Domain(domain string) Filter
- func DomainContains(substr string) Filter
- func DomainHasPrefix(prefix string) Filter
- func DomainHasSuffix(suffix string) Filter
- func ExpiresAfter(u time.Time) Filter
- func ExpiresBefore(u time.Time) Filter
- func Name(name string) Filter
- func NameContains(substr string) Filter
- func NameHasPrefix(prefix string) Filter
- func NameHasSuffix(suffix string) Filter
- func Path(path string) Filter
- func PathContains(substr string) Filter
- func PathDepth(depth int) Filter
- func PathHasPrefix(prefix string) Filter
- func PathHasSuffix(suffix string) Filter
- type FilterFunc
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExportCookies ¶
ExportCookies() export "cookies" in the Netscape format.
curl, wget, ... use this format.
Example ¶
package main
import (
"net/http"
"os"
"github.com/j178/kooky"
)
var cookieFile = `cookies.txt`
func main() {
var cookies = []*kooky.Cookie{{Cookie: http.Cookie{Domain: `.test.com`, Name: `test`, Value: `dGVzdA==`}}}
file, err := os.OpenFile(cookieFile, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
// TODO: handle error
return
}
defer file.Close()
kooky.ExportCookies(file, cookies)
}
func FilterCookie ¶
FilterCookie() tells if a "cookie" passes all "filters".
func FilterCookies ¶
FilterCookies() applies "filters" in order to the "cookies".
Example ¶
package main
import (
"github.com/j178/kooky"
_ "github.com/j178/kooky/browser/all" // register cookiestore finders
)
var cookieName = `NID`
func main() {
cookies := kooky.ReadCookies() // automatic read
cookies = kooky.FilterCookies(
cookies,
kooky.Valid, // remove expired cookies
kooky.DomainContains(`google`), // cookie domain has to contain "google"
kooky.Name(cookieName), // cookie name is "NID"
kooky.Debug, // print cookies after applying previous filter
)
}
func RegisterFinder ¶
func RegisterFinder(browser string, finder CookieStoreFinder)
RegisterFinder() registers CookieStoreFinder enabling automatic finding of cookie stores with FindCookieStores() and ReadCookies().
RegisterFinder() is called by init() in the browser subdirectories.
Types ¶
type Cookie ¶
Cookie is the struct returned by functions in this package. Similar to http.Cookie.
func ReadCookies ¶
ReadCookies uses registered cookiestore finders to read cookies. Erroneous reads are skipped.
Register cookie store finders for all browsers like this:
import _ "github.com/j178/kooky/browser/all"
Or only a specific browser:
import _ "github.com/j178/kooky/browser/chrome"
Example (All) ¶
package main
import (
"fmt"
"github.com/j178/kooky"
_ "github.com/j178/kooky/browser/all" // This registers all cookiestore finders!
// _ "github.com/j178/kooky/browser/chrome" // load only the chrome cookiestore finder
)
func main() {
// try to find cookie stores in default locations and
// read the cookies from them.
// decryption is handled automatically.
cookies := kooky.ReadCookies()
for _, cookie := range cookies {
fmt.Println(cookie)
}
}
var _ struct{} // ignore this - for correct working of the documentation tool
type CookieStore ¶
type CookieStore interface {
http.CookieJar
SubJar(filters ...Filter) (http.CookieJar, error)
ReadCookies(...Filter) ([]*Cookie, error)
Browser() string
Profile() string
IsDefaultProfile() bool
FilePath() string
Close() error
}
CookieStore represents a file, directory, etc containing cookies.
Call CookieStore.Close() after using any of its methods.
func FindCookieStores ¶
func FindCookieStores(browsers ...string) []CookieStore
FindCookieStores tries to find cookie stores at default locations.
FindCookieStores() requires registered CookieStoreFinders.
Register cookie store finders for all browsers like this:
import _ "github.com/j178/kooky/browser/all"
Or only a specific browser:
import _ "github.com/j178/kooky/browser/chrome"
If browsers is empty, all registered browsers are searched. Otherwise, only the specified browsers are searched.
Example ¶
package main
import (
"fmt"
"github.com/j178/kooky"
_ "github.com/j178/kooky/browser/all"
)
func main() {
cookieStores := kooky.FindCookieStores()
for _, store := range cookieStores {
// CookieStore keeps files/databases open for repeated reads
// close those when no longer needed
defer store.Close()
var filters = []kooky.Filter{
kooky.Valid, // remove expired cookies
}
cookies, _ := store.ReadCookies(filters...)
for _, cookie := range cookies {
fmt.Printf(
"%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
store.Browser(),
store.Profile(),
store.FilePath(),
cookie.Domain,
cookie.Name,
cookie.Value,
cookie.Expires.Format(`2006.01.02 15:04:05`),
)
}
}
}
type CookieStoreFinder ¶
type CookieStoreFinder interface {
FindCookieStores() ([]CookieStore, error)
}
CookieStoreFinder tries to find cookie stores at default locations.
type Filter ¶
Filter is used for filtering cokies in ReadCookies() functions.
A cookie passes the Filter if Filter.Filter returns true.
Example (Regex) ¶
package main
import (
"fmt"
"net/http"
"regexp"
"github.com/j178/kooky"
)
// example regex matching base64 strings
var reBase64 = regexp.MustCompile(`^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$`)
func main() {
var cookies = []*kooky.Cookie{{Cookie: http.Cookie{Name: `test`, Value: `dGVzdA==`}}}
cookies = kooky.FilterCookies(
cookies,
ValueRegexMatch(reBase64), // filter cookies with the regex filter
// kooky.Debug, // print cookies after applying the regex filter
)
for _, cookie := range cookies {
fmt.Println(cookie.Value)
break // only first element
}
}
func ValueRegexMatch(re *regexp.Regexp) kooky.Filter {
return kooky.FilterFunc(func(cookie *kooky.Cookie) bool {
return cookie != nil && re != nil && re.Match([]byte(cookie.Value))
})
}
Output: dGVzdA==
var Debug Filter = FilterFunc(func(cookie *Cookie) bool { fmt.Printf("%+#v\n", cookie) return true })
Debug prints the cookie.
Position Debug after the filter you want to test.
var HTTPOnly Filter = FilterFunc(func(cookie *Cookie) bool { return cookie != nil && cookie.HttpOnly })
var Secure Filter = FilterFunc(func(cookie *Cookie) bool { return cookie != nil && cookie.Secure })
func CreationAfter ¶
func CreationBefore ¶
func DomainContains ¶
func DomainHasPrefix ¶
func DomainHasSuffix ¶
func ExpiresAfter ¶
func ExpiresBefore ¶
func NameContains ¶
func NameHasPrefix ¶
func NameHasSuffix ¶
func PathContains ¶
func PathHasPrefix ¶
func PathHasSuffix ¶
type FilterFunc ¶
func (FilterFunc) Filter ¶
func (f FilterFunc) Filter(c *Cookie) bool