Skip to content

Commit

Permalink
cmd/airliftd: adjust syntax highlight handling and resolve remaining …
Browse files Browse the repository at this point in the history
…issues
  • Loading branch information
moshee committed Jun 10, 2018
1 parent 0d173bf commit f52de5e
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 125 deletions.
2 changes: 1 addition & 1 deletion cmd/airliftd/bindata.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package main

import _ "airlift/cmd/airliftd/bindata_files"
import _ "ktkr.us/pkg/airlift/cmd/airliftd/bindata_files"
63 changes: 13 additions & 50 deletions cmd/airliftd/bindata_files/static.go

Large diffs are not rendered by default.

19 changes: 10 additions & 9 deletions cmd/airliftd/bindata_files/templates.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions cmd/airliftd/gen_version.bash
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ GIT_REV=$(git rev-list HEAD --count)
cat > version.go <<END
package main
import "time"
func init() {
VERSION = "$GIT_TAG (r$GIT_REV)"
MODTIME = time.Unix($(date +%s), 0)
}
END
127 changes: 98 additions & 29 deletions cmd/airliftd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (
"flag"
"fmt"
"html/template"
"io/ioutil"
"image/jpeg"
"io"
"io/ioutil"
"log"
"math"
"net/http"
Expand All @@ -32,7 +33,7 @@ import (
_ "net/http/pprof"

"ktkr.us/pkg/airlift/cache"
"airlift/config"
"ktkr.us/pkg/airlift/config"
"ktkr.us/pkg/airlift/contentdisposition"
"ktkr.us/pkg/airlift/thumb"
"ktkr.us/pkg/fmtutil"
Expand All @@ -44,7 +45,6 @@ import (
)

//go:generate bindata -skip=*.sw[nop] static templates
//go:generate ./gen_styles.sh

var (
appDir string // the place where all the stuff is stored
Expand All @@ -55,6 +55,9 @@ var (
// VERSION is the current version of the executable. It is overridden with
// build flags in the release process.
VERSION = "devel"

// MODTIME is the "last modified time" used for generated static assets.
MODTIME = time.Time{}
)

const (
Expand Down Expand Up @@ -106,10 +109,11 @@ func main() {
}

config.Default = config.Config{
Host: "",
Port: 60606,
HashLen: 4,
Directory: filepath.Join(appDir, "uploads"),
Host: "",
Port: 60606,
HashLen: 4,
Directory: filepath.Join(appDir, "uploads"),
SyntaxTheme: "trac",
}
if err := config.Init(filepath.Join(appDir, "config")); err != nil {
log.Fatal(err)
Expand Down Expand Up @@ -201,6 +205,7 @@ func main() {
Post("/-/config/size", checkLogin, getSizeLimitPrune).
Post("/-/config/age", checkLogin, getAgeLimitPrune).
Get("/-/config/overview", checkLogin, getConfigOverview).
Get("/-/theme/{name}.css", getThemeCSS).
Post("/upload/web", checkLogin, postFile).
Post("/upload/file", checkPassword, postFile).
Post("/oops", checkPassword, oops).
Expand All @@ -222,10 +227,10 @@ func main() {

func getConfig(g *gas.Gas) (int, gas.Outputter) {
data := &struct {
Conf *config.Config
NumUploads int
UploadsSize fmtutil.Bytes
ThumbsSize fmtutil.Bytes
Conf *config.Config
NumUploads int
UploadsSize fmtutil.Bytes
ThumbsSize fmtutil.Bytes
SyntaxThemes []string
}{
config.Get(),
Expand Down Expand Up @@ -363,13 +368,36 @@ func getLogout(g *gas.Gas) (int, gas.Outputter) {
return 302, out.Redirect("/-/login")
}

func getThemeCSS(g *gas.Gas) (int, gas.Outputter) {
buf := new(bytes.Buffer)
err := html.New().WriteCSS(buf, styles.Get(g.Arg("name")))
if err != nil {
log.Print(err)
return 500, out.Error(g, err)
}

r := bytes.NewReader(buf.Bytes())
http.ServeContent(g, g.Request, path.Base(g.Request.URL.Path), MODTIME, r)

return g.Stop()
}

func getFile(g *gas.Gas) (int, gas.Outputter) {
id := g.Arg("id")
file := fileCache.Get(id)
if file == "" {
return 404, out.Error(g, errors.New("ID not found"))
}

form := struct {
Raw bool `form:"raw"`
Formatted bool `form:"fmt"`
}{}

if err := g.UnmarshalForm(&form); err != nil {
return 400, out.Error(g, err)
}

conf := config.Get()
if conf.TwitterCardEnable && thumb.FormatSupported(filepath.Ext(file)) {
uas := g.UserAgents()
Expand Down Expand Up @@ -411,31 +439,72 @@ func getFile(g *gas.Gas) (int, gas.Outputter) {
// enable browser caching for resources behind TLS
g.Header().Set("Cache-Control", "public")

// Find lexer for file's extension
extension := strings.TrimLeft(filepath.Ext(file), ".")
lexer := lexers.Get(extension)
f, err := os.Open(file)
if err != nil {
return 500, out.Error(g, err)
}

defer f.Close()

if g.Request.URL.RawQuery == "raw" ||
strings.Contains(g.Request.UserAgent(), "curl") ||
strings.Contains(g.Request.UserAgent(), "wget") ||
!conf.SyntaxEnable ||
lexer == nil {
buf := make([]byte, 512)
_, err = io.ReadFull(f, buf)
if err != nil {
return 500, out.Error(g, err)
}

contentType := http.DetectContentType(buf)

if !strings.HasPrefix(contentType, "text/") {
http.ServeFile(g, g.Request, file)
return -1, nil
return g.Stop()
}

clientWantsRaw := form.Raw
uas := g.UserAgents()

// for no user-agent or command line client, default to raw
if len(uas) == 0 {
clientWantsRaw = !form.Formatted
}

for _, ua := range uas {
switch strings.ToLower(ua.Name) {
case "curl", "wget":
clientWantsRaw = !form.Formatted
}
}

// browser user-agents should get formatted. regardless, one can force
// either way with url param if it matters
if form.Raw || clientWantsRaw || !conf.SyntaxEnable {
http.ServeFile(g, g.Request, file)
return g.Stop()
}

// Find lexer for file
lexer := lexers.Analyse(string(buf))
if lexer == nil {
extension := strings.TrimLeft(filepath.Ext(file), ".")
lexer = lexers.Get(extension)
}

if lexer == nil {
http.ServeFile(g, g.Request, file)
return g.Stop()
}

lexer = chroma.Coalesce(lexer)

s := styles.Get(conf.SyntaxTheme)
if s == nil {
s = styles.Fallback
}

// Serve non-text files that slipped through, read text files to string
buffer, err := ioutil.ReadFile(file)
contentType := http.DetectContentType(buffer)
if !strings.Contains(contentType, "text/plain"){
http.ServeFile(g, g.Request, file)
return -1, nil
f.Seek(0, os.SEEK_SET)
buffer, err := ioutil.ReadAll(f)
if err != nil {
return 500, out.Error(g, err)
}
contents := string(buffer)

Expand All @@ -450,20 +519,20 @@ func getFile(g *gas.Gas) (int, gas.Outputter) {
if err != nil {
log.Print(err)
http.ServeFile(g, g.Request, file)
return -1, nil
return g.Stop()
}

// Render template
data := &struct {
SyntaxTheme string
HTML template.HTML
Filename string
HTML template.HTML
Filename string
}{
s.Name,
template.HTML(htmlBuffer.String()),
strings.SplitN(filepath.Base(file), ".", 2)[1],
}
return 200, out.HTML("syntax/content", &context{data})
return 200, out.HTML("syntax/layout-syntax", &context{data})
}

func postFile(g *gas.Gas) (int, gas.Outputter) {
Expand Down
2 changes: 1 addition & 1 deletion cmd/airliftd/static/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
var boxes = $$('.check-enable');
for (var i = 0, b; b = boxes[i]; i++) {
var hider = b.querySelector('.hider');
hider.hidee = b.querySelector('.hidee input');
hider.hidee = b.querySelector('.hidee input, .hidee select');
hider.addEventListener('click', function() {
if (this.checked) {
this.hidee.removeAttribute('disabled');
Expand Down
2 changes: 1 addition & 1 deletion cmd/airliftd/static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ input[type=checkbox]:checked:after {
text-align: center;
color: #f0f0f0;
}
input:focus {
input:focus, select:focus {
outline: none;
border: 2px solid #888;
margin: 7px -1px;
Expand Down
6 changes: 5 additions & 1 deletion cmd/airliftd/static/syntax.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@
height: 18px;
}

.chroma { -moz-tab-size: 2; -o-tab-size: 2; tab-size: 2 }
.chroma {
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
}
1 change: 0 additions & 1 deletion cmd/airliftd/static/syntax/.gitignore

This file was deleted.

32 changes: 16 additions & 16 deletions cmd/airliftd/templates/content/config.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,6 @@
<input type="checkbox" id="append-ext" name="append-ext"{{ if .Conf.AppendExt }} checked{{ end }}>
<label for="append-ext">Append File Extensions</label>
</div>
<div class="box check-enable">
<input type="checkbox" class="hider" name="syntax-enable"{{ if .Conf.SyntaxEnable }} checked{{ end }}>
<label for="syntax-enable">Syntax Highlighting</label>
<small>
<a href="https://xyproto.github.io/splash/docs/" target="_blank">View theme examples</a>
</small>
<div class="hidee">
<label for="syntax-theme">Syntax Theme</label>
<select id="syntax-theme" name="syntax-theme">
{{ range .SyntaxThemes }}
<option value="{{ . }}" {{ if eq . $.Data.Data.Conf.SyntaxTheme }} selected {{ end }} >{{ . }}</option>
{{ end }}
</select>
</div>
</div>
<div class="box check-enable">
<input type="checkbox" class="hider" id="enable-age-prune" name="enable-age-prune"{{ if .Conf.MaxAgeEnable }} checked{{ end }}>
<label for="enable-age-prune">Limit Upload Age</label>
Expand All @@ -59,13 +44,28 @@
</div>
</div>
<div class="box check-enable" data-tooltip="Enable to allow uploads to show Twitter Cards with file previews if applicable." data-tt-pos="left">
<input type="checkbox" class="hider" name="twitter-card"{{ if .Conf.TwitterCardEnable }} checked{{ end }}>
<input type="checkbox" class="hider" id="twitter-card" name="twitter-card"{{ if .Conf.TwitterCardEnable }} checked{{ end }}>
<label for="twitter-card">Enable Twitter Cards</label>
<div class="hidee">
<label for="twitter-handle">Twitter Handle</label>
<input type="text" id="twitter-handle" name="twitter-handle" value="{{ .Conf.TwitterHandle }}" required placeholder="@handle"{{ if not .Conf.TwitterCardEnable }} disabled{{ end }}>
</div>
</div>
<div class="box check-enable" data-tooltip="Enable to format code text files with syntax highlighting." data-tt-pos="left">
<input type="checkbox" class="hider" id="syntax-enable" name="syntax-enable"{{ if .Conf.SyntaxEnable }} checked{{ end }}>
<label for="syntax-enable">Syntax Highlighting</label>
<small>
<a href="https://xyproto.github.io/splash/docs/" target="_blank">View theme examples</a>
</small>
<div class="hidee">
<label for="syntax-theme">Syntax Theme</label>
<select id="syntax-theme" name="syntax-theme">
{{ range .SyntaxThemes }}
<option value="{{ . }}" {{ if eq . $.Data.Data.Conf.SyntaxTheme }} selected {{ end }} >{{ . }}</option>
{{ end }}
</select>
</div>
</div>
<div class="box" id="directory-box">
<label for="directory">Upload Directory</label>
<input type="text" id="directory" name="directory" value="{{ .Conf.Directory }}" placeholder="/home/user/uploads">
Expand Down
16 changes: 3 additions & 13 deletions cmd/airliftd/templates/content/syntax.tmpl
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
{{ define "title" }}{{ $.Data.Data.Filename }}{{ end }}

{{ define "content" }}
{{ with $.Data.Data }}
<html>
<head>
<title>{{ .Filename }}</title>
<link rel="stylesheet" href="/-/static/syntax.css">
<link rel="stylesheet" href="/-/static/syntax/{{ .SyntaxTheme }}.css">
</head>
<body class="syntax chroma">
<a href="?raw" class="raw">{{ .Filename }}<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg></a>
<main>{{ .HTML}}</main>
</body>
</html>
{{ end }}
<main>{{ $.Data.Data.HTML }}</main>
{{ end }}
13 changes: 13 additions & 0 deletions cmd/airliftd/templates/layout/layout.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,16 @@
</body>
</html>
{{ end }}

{{ define "layout-syntax" }}
<html>
<head>
<title>{{ block "title" . }}{{ end }}</title>
<link rel="stylesheet" href="/-/static/syntax.css">
<link rel="stylesheet" href="/-/theme/{{ .Data.Data.SyntaxTheme }}.css">
</head>
<body class="syntax chroma">
<a href="?raw=1" class="raw">{{ $.Data.Data.Filename }}<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg></a>
{{ block "content" . }}{{ end }}
</body>
{{ end }}
2 changes: 1 addition & 1 deletion cmd/airliftd/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"strings"
"time"

"airlift/config"
"ktkr.us/pkg/airlift/config"
"ktkr.us/pkg/fmtutil"
"ktkr.us/pkg/gas"
"ktkr.us/pkg/gas/auth"
Expand Down
4 changes: 2 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ type Config struct {
AppendExt bool `form:"append-ext"` // append extensions to returned file URLs
TwitterCardEnable bool `form:"twitter-card"` // enable Twitter Card preview for embeddable files
TwitterHandle string `form:"twitter-handle"`
SyntaxEnable bool `form:"syntax-enable"` // enable syntax highlighting for text files
SyntaxTheme string `form:"syntax-theme"` // Chroma syntax highlight theme
SyntaxEnable bool `form:"syntax-enable"` // enable syntax highlighting for text files
SyntaxTheme string `form:"syntax-theme"` // Chroma syntax highlight theme
}

// Secrets satisfies gas.User interface.
Expand Down

0 comments on commit f52de5e

Please sign in to comment.