341 lines
7.8 KiB
Go
341 lines
7.8 KiB
Go
// Copyright (C) 2021-2023 Leonid Maslakov.
|
|
|
|
// This file is part of Lenpaste.
|
|
|
|
// Lenpaste is free software: you can redistribute it
|
|
// and/or modify it under the terms of the
|
|
// GNU Affero Public License as published by the
|
|
// Free Software Foundation, either version 3 of the License,
|
|
// or (at your option) any later version.
|
|
|
|
// Lenpaste is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
// or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU Affero Public License for more details.
|
|
|
|
// You should have received a copy of the GNU Affero Public License along with Lenpaste.
|
|
// If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package web
|
|
|
|
import (
|
|
"embed"
|
|
"git.lcomrade.su/root/lenpaste/internal/config"
|
|
"git.lcomrade.su/root/lenpaste/internal/logger"
|
|
"git.lcomrade.su/root/lenpaste/internal/netshare"
|
|
"git.lcomrade.su/root/lenpaste/internal/storage"
|
|
chromaLexers "github.com/alecthomas/chroma/v2/lexers"
|
|
"html/template"
|
|
"net/http"
|
|
"strings"
|
|
textTemplate "text/template"
|
|
)
|
|
|
|
//go:embed data/*
|
|
var embFS embed.FS
|
|
|
|
type Data struct {
|
|
DB storage.DB
|
|
Log logger.Logger
|
|
|
|
RateLimitNew *netshare.RateLimitSystem
|
|
RateLimitGet *netshare.RateLimitSystem
|
|
|
|
Lexers *[]string
|
|
Locales Locales
|
|
LocalesList LocalesList
|
|
Themes Themes
|
|
ThemesList ThemesList
|
|
|
|
StyleCSS *textTemplate.Template
|
|
ErrorPage *template.Template
|
|
Main *template.Template
|
|
MainJS *[]byte
|
|
HistoryJS *textTemplate.Template
|
|
CodeJS *textTemplate.Template
|
|
PastePage *template.Template
|
|
PasteJS *textTemplate.Template
|
|
PasteContinue *template.Template
|
|
Settings *template.Template
|
|
About *template.Template
|
|
TermsOfUse *template.Template
|
|
Authors *template.Template
|
|
License *template.Template
|
|
SourceCodePage *template.Template
|
|
|
|
Docs *template.Template
|
|
DocsApiV1 *template.Template
|
|
DocsApiLibs *template.Template
|
|
|
|
EmbeddedPage *template.Template
|
|
EmbeddedHelpPage *template.Template
|
|
|
|
Version *string
|
|
|
|
TitleMaxLen *int
|
|
BodyMaxLen *int
|
|
MaxLifeTime *int64
|
|
|
|
ServerAbout *string
|
|
ServerRules *string
|
|
ServerTermsExist *bool
|
|
ServerTermsOfUse *string
|
|
|
|
AdminName *string
|
|
AdminMail *string
|
|
|
|
RobotsDisallow *bool
|
|
|
|
LenPasswdFile *string
|
|
|
|
UiDefaultLifeTime *string
|
|
UiDefaultTheme *string
|
|
}
|
|
|
|
func Load(db storage.DB, cfg config.Config) (*Data, error) {
|
|
var data Data
|
|
var err error
|
|
|
|
// Setup base info
|
|
data.DB = db
|
|
data.Log = cfg.Log
|
|
|
|
data.RateLimitNew = cfg.RateLimitNew
|
|
data.RateLimitGet = cfg.RateLimitGet
|
|
|
|
data.Version = &cfg.Version
|
|
|
|
data.TitleMaxLen = &cfg.TitleMaxLen
|
|
data.BodyMaxLen = &cfg.BodyMaxLen
|
|
data.MaxLifeTime = &cfg.MaxLifeTime
|
|
data.UiDefaultLifeTime = &cfg.UiDefaultLifetime
|
|
data.UiDefaultTheme = &cfg.UiDefaultTheme
|
|
data.LenPasswdFile = &cfg.LenPasswdFile
|
|
|
|
data.ServerAbout = &cfg.ServerAbout
|
|
data.ServerRules = &cfg.ServerRules
|
|
data.ServerTermsOfUse = &cfg.ServerTermsOfUse
|
|
|
|
serverTermsExist := false
|
|
if cfg.ServerTermsOfUse != "" {
|
|
serverTermsExist = true
|
|
}
|
|
data.ServerTermsExist = &serverTermsExist
|
|
|
|
data.AdminName = &cfg.AdminName
|
|
data.AdminMail = &cfg.AdminMail
|
|
|
|
data.RobotsDisallow = &cfg.RobotsDisallow
|
|
|
|
// Get Chroma lexers
|
|
lexers := chromaLexers.Names(false)
|
|
data.Lexers = &lexers
|
|
|
|
// Load locales
|
|
data.Locales, data.LocalesList, err = loadLocales(embFS, "data/locale")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Load themes
|
|
data.Themes, data.ThemesList, err = loadThemes(cfg.UiThemesDir, data.LocalesList, data.UiDefaultTheme)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// style.css file
|
|
data.StyleCSS, err = textTemplate.ParseFS(embFS, "data/style.css")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// main.tmpl
|
|
data.Main, err = template.ParseFS(embFS, "data/base.tmpl", "data/main.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// main.js
|
|
mainJS, err := embFS.ReadFile("data/main.js")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
data.MainJS = &mainJS
|
|
|
|
// history.js
|
|
data.HistoryJS, err = textTemplate.ParseFS(embFS, "data/history.js")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// code.js
|
|
data.CodeJS, err = textTemplate.ParseFS(embFS, "data/code.js")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// paste.tmpl
|
|
data.PastePage, err = template.ParseFS(embFS, "data/base.tmpl", "data/paste.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// paste.js
|
|
data.PasteJS, err = textTemplate.ParseFS(embFS, "data/paste.js")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// paste_continue.tmpl
|
|
data.PasteContinue, err = template.ParseFS(embFS, "data/base.tmpl", "data/paste_continue.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// settings.tmpl
|
|
data.Settings, err = template.ParseFS(embFS, "data/base.tmpl", "data/settings.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// about.tmpl
|
|
data.About, err = template.ParseFS(embFS, "data/base.tmpl", "data/about.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// terms.tmpl
|
|
data.TermsOfUse, err = template.ParseFS(embFS, "data/base.tmpl", "data/terms.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// authors.tmpl
|
|
data.Authors, err = template.ParseFS(embFS, "data/base.tmpl", "data/authors.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// license.tmpl
|
|
data.License, err = template.ParseFS(embFS, "data/base.tmpl", "data/license.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// source_code.tmpl
|
|
data.SourceCodePage, err = template.ParseFS(embFS, "data/base.tmpl", "data/source_code.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// docs.tmpl
|
|
data.Docs, err = template.ParseFS(embFS, "data/base.tmpl", "data/docs.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// docs_apiv1.tmpl
|
|
data.DocsApiV1, err = template.ParseFS(embFS, "data/base.tmpl", "data/docs_apiv1.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// docs_api_libs.tmpl
|
|
data.DocsApiLibs, err = template.ParseFS(embFS, "data/base.tmpl", "data/docs_api_libs.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// error.tmpl
|
|
data.ErrorPage, err = template.ParseFS(embFS, "data/base.tmpl", "data/error.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// emb.tmpl
|
|
data.EmbeddedPage, err = template.ParseFS(embFS, "data/emb.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// emb_help.tmpl
|
|
data.EmbeddedHelpPage, err = template.ParseFS(embFS, "data/base.tmpl", "data/emb_help.tmpl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &data, nil
|
|
}
|
|
|
|
func (data *Data) Handler(rw http.ResponseWriter, req *http.Request) {
|
|
// Process request
|
|
var err error
|
|
|
|
switch req.URL.Path {
|
|
// Search engines
|
|
case "/robots.txt":
|
|
err = data.robotsTxtHand(rw, req)
|
|
case "/sitemap.xml":
|
|
err = data.sitemapHand(rw, req)
|
|
// Resources
|
|
case "/style.css":
|
|
err = data.styleCSSHand(rw, req)
|
|
case "/main.js":
|
|
err = data.mainJSHand(rw, req)
|
|
case "/history.js":
|
|
err = data.historyJSHand(rw, req)
|
|
case "/code.js":
|
|
err = data.codeJSHand(rw, req)
|
|
case "/paste.js":
|
|
err = data.pasteJSHand(rw, req)
|
|
case "/about":
|
|
err = data.aboutHand(rw, req)
|
|
case "/about/authors":
|
|
err = data.authorsHand(rw, req)
|
|
case "/about/license":
|
|
err = data.licenseHand(rw, req)
|
|
case "/about/source_code":
|
|
err = data.sourceCodePageHand(rw, req)
|
|
case "/docs":
|
|
err = data.docsHand(rw, req)
|
|
case "/docs/apiv1":
|
|
err = data.docsApiV1Hand(rw, req)
|
|
case "/docs/api_libs":
|
|
err = data.docsApiLibsHand(rw, req)
|
|
// Pages
|
|
case "/":
|
|
err = data.newPasteHand(rw, req)
|
|
case "/settings":
|
|
err = data.settingsHand(rw, req)
|
|
case "/terms":
|
|
err = data.termsOfUseHand(rw, req)
|
|
// Else
|
|
default:
|
|
if strings.HasPrefix(req.URL.Path, "/dl/") {
|
|
err = data.dlHand(rw, req)
|
|
|
|
} else if strings.HasPrefix(req.URL.Path, "/emb/") {
|
|
err = data.embeddedHand(rw, req)
|
|
|
|
} else if strings.HasPrefix(req.URL.Path, "/emb_help/") {
|
|
err = data.embeddedHelpHand(rw, req)
|
|
|
|
} else {
|
|
err = data.getPasteHand(rw, req)
|
|
}
|
|
}
|
|
|
|
// Log
|
|
if err == nil {
|
|
data.Log.HttpRequest(req, 200)
|
|
|
|
} else {
|
|
code, err := data.writeError(rw, req, err)
|
|
if err != nil {
|
|
data.Log.HttpError(req, err)
|
|
} else {
|
|
data.Log.HttpRequest(req, code)
|
|
}
|
|
}
|
|
}
|