107 lines
2.1 KiB
Go
107 lines
2.1 KiB
Go
|
package captiveportal
|
||
|
|
||
|
import (
|
||
|
"net/http"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/pkg/errors"
|
||
|
)
|
||
|
|
||
|
type OS int
|
||
|
|
||
|
const (
|
||
|
OSUnknown OS = iota
|
||
|
OSAndroid
|
||
|
OSApple
|
||
|
OSWindows
|
||
|
OSLinux
|
||
|
)
|
||
|
|
||
|
type Matcher interface {
|
||
|
Match(r *http.Request) (bool, OS, error)
|
||
|
}
|
||
|
|
||
|
type MatchFunc func(r *http.Request) (bool, OS, error)
|
||
|
|
||
|
func (f MatchFunc) Match(r *http.Request) (bool, OS, error) {
|
||
|
return f(r)
|
||
|
}
|
||
|
|
||
|
func MatchAndroid(r *http.Request) (bool, error) {
|
||
|
// Samples
|
||
|
//
|
||
|
// https://www.google.com/generate_204
|
||
|
// http://connectivitycheck.gstatic.com/generate_204
|
||
|
// http://www.google.com/gen_204
|
||
|
// http://play.googleapis.com/generate_204
|
||
|
// http://connectivitycheck.gstatic.com/generate_204
|
||
|
// http://clients3.google.com/generate_204
|
||
|
// http://g.cn
|
||
|
matches := strings.Contains(r.URL.Path, "generate_204") ||
|
||
|
strings.Contains(r.URL.Path, "gen_204") ||
|
||
|
r.URL.Hostname() == "g.cn"
|
||
|
|
||
|
return matches, nil
|
||
|
}
|
||
|
|
||
|
func MatchApple(r *http.Request) (bool, error) {
|
||
|
// Samples
|
||
|
//
|
||
|
// http://www.apple.com/library/test/success.html
|
||
|
// http://captive.apple.com/hotspot-detect.html
|
||
|
hostname := r.URL.Hostname()
|
||
|
|
||
|
matches := hostname == "www.apple.com" ||
|
||
|
hostname == "captive.apple.com"
|
||
|
|
||
|
return matches, nil
|
||
|
}
|
||
|
|
||
|
func MatchLinux(r *http.Request) (bool, error) {
|
||
|
// Samples
|
||
|
//
|
||
|
// http://start.ubuntu.com/connectivity-check.html
|
||
|
// http://nmcheck.gnome.org/check_network_status.txt
|
||
|
hostname := r.URL.Hostname()
|
||
|
|
||
|
matches := hostname == "start.ubuntu.com" ||
|
||
|
hostname == "nmcheck.gnome.org"
|
||
|
|
||
|
return matches, nil
|
||
|
}
|
||
|
|
||
|
func MatchWindows(r *http.Request) (bool, error) {
|
||
|
// Samples
|
||
|
//
|
||
|
// http://www.msftncsi.com
|
||
|
// http://www.msftncsi.com/ncsi.txt
|
||
|
hostname := r.URL.Hostname()
|
||
|
|
||
|
matches := hostname == "www.msftncsi.com"
|
||
|
|
||
|
return matches, nil
|
||
|
}
|
||
|
|
||
|
// nolint: gochecknoglobals
|
||
|
var defaultMatchers = map[OS]func(r *http.Request) (bool, error){
|
||
|
OSAndroid: MatchAndroid,
|
||
|
OSApple: MatchApple,
|
||
|
OSWindows: MatchWindows,
|
||
|
OSLinux: MatchLinux,
|
||
|
}
|
||
|
|
||
|
func DefaultMatch(r *http.Request) (bool, OS, error) {
|
||
|
for os, match := range defaultMatchers {
|
||
|
matches, err := match(r)
|
||
|
if err != nil {
|
||
|
return false, OSUnknown, errors.WithStack(err)
|
||
|
}
|
||
|
|
||
|
if matches {
|
||
|
return matches, os, nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false, OSUnknown, nil
|
||
|
}
|