Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
3.4 KiB
137 lines
3.4 KiB
// Package webbrowser provides a simple API for opening web pages on your |
|
// default browser. |
|
package webbrowser |
|
|
|
import ( |
|
"errors" |
|
"fmt" |
|
"net/url" |
|
"os" |
|
"os/exec" |
|
"runtime" |
|
"strings" |
|
) |
|
|
|
var ( |
|
ErrCantOpenBrowser = errors.New("webbrowser: can't open browser") |
|
ErrNoCandidates = errors.New("webbrowser: no browser candidate found for your OS") |
|
) |
|
|
|
// Candidates contains a list of registered `Browser`s that will be tried with Open. |
|
var Candidates []Browser |
|
|
|
type Browser interface { |
|
// Command returns a ready to be used Cmd that will open an URL. |
|
Command(string) (*exec.Cmd, error) |
|
// Open tries to open a URL in your default browser. NOTE: This may cause |
|
// your program to hang until the browser process is closed in some OSes, |
|
// see https://github.com/toqueteos/webbrowser/issues/4. |
|
Open(string) error |
|
} |
|
|
|
// Open tries to open a URL in your default browser ensuring you have a display |
|
// set up and not running this from SSH. NOTE: This may cause your program to |
|
// hang until the browser process is closed in some OSes, see |
|
// https://github.com/toqueteos/webbrowser/issues/4. |
|
func Open(s string) (err error) { |
|
if len(Candidates) == 0 { |
|
return ErrNoCandidates |
|
} |
|
|
|
// Try to determine if there's a display available (only linux) and we |
|
// aren't on a terminal (all but windows). |
|
switch runtime.GOOS { |
|
case "linux": |
|
// No display, no need to open a browser. Lynx users **MAY** have |
|
// something to say about this. |
|
if os.Getenv("DISPLAY") == "" { |
|
return fmt.Errorf("webbrowser: tried to open %q, no screen found", s) |
|
} |
|
fallthrough |
|
case "darwin": |
|
// Check SSH env vars. |
|
if os.Getenv("SSH_CLIENT") != "" || os.Getenv("SSH_TTY") != "" { |
|
return fmt.Errorf("webbrowser: tried to open %q, but you are running a shell session", s) |
|
} |
|
} |
|
|
|
// Try all candidates |
|
for _, candidate := range Candidates { |
|
err := candidate.Open(s) |
|
if err == nil { |
|
return nil |
|
} |
|
} |
|
|
|
return ErrCantOpenBrowser |
|
} |
|
|
|
func init() { |
|
// Register the default Browser for current OS, if it exists. |
|
if os, ok := osCommand[runtime.GOOS]; ok { |
|
Candidates = append(Candidates, browserCommand{os.cmd, os.args}) |
|
} |
|
} |
|
|
|
var ( |
|
osCommand = map[string]*browserCommand{ |
|
"android": &browserCommand{"xdg-open", nil}, |
|
"darwin": &browserCommand{"open", nil}, |
|
"freebsd": &browserCommand{"xdg-open", nil}, |
|
"linux": &browserCommand{"xdg-open", nil}, |
|
"netbsd": &browserCommand{"xdg-open", nil}, |
|
"openbsd": &browserCommand{"xdg-open", nil}, // It may be open instead |
|
"windows": &browserCommand{"cmd", []string{"/c", "start"}}, |
|
} |
|
winSchemes = [3]string{"https", "http", "file"} |
|
) |
|
|
|
type browserCommand struct { |
|
cmd string |
|
args []string |
|
} |
|
|
|
func (b browserCommand) Command(s string) (*exec.Cmd, error) { |
|
u, err := url.Parse(s) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
validUrl := ensureValidURL(u) |
|
|
|
b.args = append(b.args, validUrl) |
|
|
|
return exec.Command(b.cmd, b.args...), nil |
|
} |
|
|
|
func (b browserCommand) Open(s string) error { |
|
cmd, err := b.Command(s) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
return cmd.Run() |
|
} |
|
|
|
func ensureScheme(u *url.URL) { |
|
for _, s := range winSchemes { |
|
if u.Scheme == s { |
|
return |
|
} |
|
} |
|
u.Scheme = "http" |
|
} |
|
|
|
func ensureValidURL(u *url.URL) string { |
|
// Enforce a scheme (windows requires scheme to be set to work properly). |
|
ensureScheme(u) |
|
s := u.String() |
|
|
|
// Escape characters not allowed by cmd/bash |
|
switch runtime.GOOS { |
|
case "windows": |
|
s = strings.Replace(s, "&", `^&`, -1) |
|
} |
|
|
|
return s |
|
}
|
|
|