mirror of
https://code.rocketnine.space/tslocum/gmitohtml.git
synced 2024-11-14 19:06:44 +01:00
Add option to allow local file access
This commit is contained in:
parent
11183c0c63
commit
e2232a8dc8
5 changed files with 51 additions and 10 deletions
|
@ -1,5 +1,6 @@
|
|||
1.0.1:
|
||||
- Display navigation bar in pages
|
||||
- Add option to allow local file access
|
||||
|
||||
1.0.0:
|
||||
- Initial release
|
||||
|
|
|
@ -19,6 +19,14 @@ openssl req -x509 -out localhost.crt -keyout localhost.key \
|
|||
Files `localhost.crt` and `localhost.key` are generated. Rename these files to
|
||||
match the domain where the certificate will be used.
|
||||
|
||||
## Allow file:// access
|
||||
|
||||
By default, local files are not served by gmitohtml. When executed with the
|
||||
`--allow-file` argument, local files may be accessed via `file://`.
|
||||
|
||||
For example, to view `/home/dioscuri/sites/gemlog/index.gmi`, navigate to
|
||||
`file:///home/dioscuri/sites/gemlog/index.gmi`.
|
||||
|
||||
# Example config.yaml
|
||||
|
||||
```yaml
|
||||
|
|
4
main.go
4
main.go
|
@ -33,9 +33,11 @@ func openBrowser(url string) {
|
|||
|
||||
func main() {
|
||||
var view bool
|
||||
var allowFile bool
|
||||
var daemon string
|
||||
var configFile string
|
||||
flag.BoolVar(&view, "view", false, "open web browser")
|
||||
flag.BoolVar(&allowFile, "allow-file", false, "allow local file access via file://")
|
||||
flag.StringVar(&daemon, "daemon", "", "start daemon on specified address")
|
||||
flag.StringVar(&configFile, "config", "", "path to configuration file")
|
||||
// TODO option to include response header in page
|
||||
|
@ -76,7 +78,7 @@ func main() {
|
|||
}
|
||||
|
||||
if daemon != "" {
|
||||
err := gmitohtml.StartDaemon(daemon)
|
||||
err := gmitohtml.StartDaemon(daemon, allowFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -22,6 +22,11 @@ func rewriteURL(u string, loc *url.URL) string {
|
|||
if daemonAddress != "" {
|
||||
if strings.HasPrefix(u, "gemini://") {
|
||||
return "http://" + daemonAddress + "/gemini/" + u[9:]
|
||||
} else if strings.HasPrefix(u, "file://") {
|
||||
if !allowFileAccess {
|
||||
return "http://" + daemonAddress + "/?FileAccessNotAllowed"
|
||||
}
|
||||
return "http://" + daemonAddress + "/file/" + u[7:]
|
||||
} else if strings.Contains(u, "://") {
|
||||
return u
|
||||
} else if loc != nil && len(u) > 0 && !strings.HasPrefix(u, "//") {
|
||||
|
|
|
@ -11,13 +11,17 @@ import (
|
|||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var lastRequestTime = time.Now().Unix()
|
||||
|
||||
var clientCerts = make(map[string]tls.Certificate)
|
||||
var (
|
||||
clientCerts = make(map[string]tls.Certificate)
|
||||
allowFileAccess bool
|
||||
)
|
||||
|
||||
// ErrInvalidCertificate is the error returned when an invalid certificate is provided.
|
||||
var ErrInvalidCertificate = errors.New("invalid certificate")
|
||||
|
@ -165,12 +169,17 @@ func handleRequest(writer http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
|
||||
pathSplit := strings.Split(request.URL.Path, "/")
|
||||
if len(pathSplit) < 2 || pathSplit[1] != "gemini" {
|
||||
if len(pathSplit) < 2 || (pathSplit[1] != "gemini" && (!allowFileAccess || pathSplit[1] != "file")) {
|
||||
writer.Write([]byte("Error: invalid protocol, only Gemini is supported"))
|
||||
return
|
||||
}
|
||||
|
||||
u, err := url.ParseRequestURI("gemini://" + strings.Join(pathSplit[2:], "/"))
|
||||
scheme := "gemini://"
|
||||
if pathSplit[1] == "file" {
|
||||
scheme = "file://"
|
||||
}
|
||||
|
||||
u, err := url.ParseRequestURI(scheme + strings.Join(pathSplit[2:], "/"))
|
||||
if err != nil {
|
||||
writer.Write([]byte("Error: invalid URL"))
|
||||
return
|
||||
|
@ -186,11 +195,26 @@ func handleRequest(writer http.ResponseWriter, request *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
header, data, err := fetch(u.String())
|
||||
var header []byte
|
||||
var data []byte
|
||||
if scheme == "gemini://" {
|
||||
header, data, err = fetch(u.String())
|
||||
if err != nil {
|
||||
fmt.Fprintf(writer, "Error: failed to fetch %s: %s", u, err)
|
||||
return
|
||||
}
|
||||
} else if allowFileAccess && scheme == "file://" {
|
||||
header = []byte("20 text/gemini; charset=utf-8")
|
||||
data, err = ioutil.ReadFile(path.Join("/", strings.Join(pathSplit[2:], "/")))
|
||||
if err != nil {
|
||||
fmt.Fprintf(writer, "Error: failed to read file %s: %s", u, err)
|
||||
return
|
||||
}
|
||||
data = Convert(data, u.String())
|
||||
} else {
|
||||
writer.Write([]byte("Error: invalid URL"))
|
||||
return
|
||||
}
|
||||
|
||||
if len(header) > 0 && header[0] == '3' {
|
||||
split := bytes.SplitN(header, []byte(" "), 2)
|
||||
|
@ -219,10 +243,11 @@ func handleAssets(writer http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
|
||||
// StartDaemon starts the page conversion daemon.
|
||||
func StartDaemon(address string) error {
|
||||
loadAssets()
|
||||
|
||||
func StartDaemon(address string, allowFile bool) error {
|
||||
daemonAddress = address
|
||||
allowFileAccess = allowFile
|
||||
|
||||
loadAssets()
|
||||
|
||||
handler := http.NewServeMux()
|
||||
handler.HandleFunc("/assets/style.css", handleAssets)
|
||||
|
|
Loading…
Reference in a new issue