2023-05-10 22:47:27 +09:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"text/template"
|
|
|
|
|
"fmt"
|
|
|
|
|
"net/http"
|
2023-05-12 13:50:25 +09:00
|
|
|
|
"strings"
|
2023-06-23 18:09:23 +09:00
|
|
|
|
"strconv"
|
|
|
|
|
"time"
|
2023-05-12 13:50:25 +09:00
|
|
|
|
"os"
|
2023-05-14 11:37:15 +09:00
|
|
|
|
"encoding/json"
|
2023-07-17 01:02:37 +09:00
|
|
|
|
"gitler.moe/suwako/goliblocale"
|
2023-05-10 22:47:27 +09:00
|
|
|
|
)
|
|
|
|
|
|
2023-05-14 11:37:15 +09:00
|
|
|
|
type (
|
|
|
|
|
Page struct {
|
2023-07-17 01:02:37 +09:00
|
|
|
|
Err, Lan, Ver, Ves, Url, Body string
|
|
|
|
|
i18n map[string]string
|
2023-06-23 18:09:23 +09:00
|
|
|
|
Ext []Exist // 既に存在する場合
|
2023-05-14 11:37:15 +09:00
|
|
|
|
}
|
2023-06-27 13:48:35 +09:00
|
|
|
|
Stat struct { // APIのみ
|
2023-06-23 18:09:23 +09:00
|
|
|
|
Url, Ver string
|
|
|
|
|
}
|
|
|
|
|
Exist struct {
|
|
|
|
|
Date, Url string
|
2023-05-14 11:37:15 +09:00
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2023-07-17 01:02:37 +09:00
|
|
|
|
func (p Page) T (key string) string {
|
|
|
|
|
return p.i18n[key]
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-17 02:09:39 +09:00
|
|
|
|
// 言語設定、デフォルト=ja
|
2023-05-14 11:37:15 +09:00
|
|
|
|
func initloc (r *http.Request) string {
|
2023-07-17 02:09:39 +09:00
|
|
|
|
supportedLanguages := map[string]bool{
|
|
|
|
|
"ja": true,
|
|
|
|
|
"en": true,
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-14 11:37:15 +09:00
|
|
|
|
cookie, err := r.Cookie("lang")
|
2023-07-17 02:09:39 +09:00
|
|
|
|
if err != nil {
|
|
|
|
|
return "ja"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if _, ok := supportedLanguages[cookie.Value]; ok {
|
|
|
|
|
return cookie.Value
|
|
|
|
|
} else {
|
|
|
|
|
return "ja"
|
2023-06-23 18:09:23 +09:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func tspath (p string) string {
|
|
|
|
|
pc := strings.Split(p, "/")
|
|
|
|
|
|
|
|
|
|
for i := len(pc) - 1; i >= 0; i-- {
|
|
|
|
|
if _, err := strconv.Atoi(pc[i]); err == nil {
|
|
|
|
|
return pc[i]
|
|
|
|
|
}
|
2023-05-14 11:37:15 +09:00
|
|
|
|
}
|
2023-06-23 18:09:23 +09:00
|
|
|
|
|
|
|
|
|
return ""
|
2023-05-10 22:47:27 +09:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-27 13:48:35 +09:00
|
|
|
|
// ホームページ
|
2023-06-23 12:48:13 +09:00
|
|
|
|
func siteHandler (cnf Config) func (http.ResponseWriter, *http.Request) {
|
|
|
|
|
return func (w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
ftmpl := []string{cnf.webpath + "/view/index.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html"}
|
|
|
|
|
data := &Page{Ver: version, Ves: strings.ReplaceAll(version, ".", "")}
|
|
|
|
|
|
|
|
|
|
lang := initloc(r)
|
|
|
|
|
data.Lan = lang
|
2023-07-17 01:02:37 +09:00
|
|
|
|
|
|
|
|
|
i18n, err := goliblocale.GetLocale("locale/" + lang)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println("liblocaleエラー:%v", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
data.i18n = i18n
|
2023-06-23 12:48:13 +09:00
|
|
|
|
ftmpl[0] = cnf.webpath + "/view/index.html"
|
|
|
|
|
tmpl := template.Must(template.ParseFiles(ftmpl[0], ftmpl[1], ftmpl[2]))
|
|
|
|
|
|
|
|
|
|
if r.Method == "POST" {
|
|
|
|
|
err := r.ParseForm()
|
2023-06-23 18:09:23 +09:00
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err)
|
|
|
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-06-23 12:48:13 +09:00
|
|
|
|
|
2023-07-17 01:02:37 +09:00
|
|
|
|
// 言語変更
|
|
|
|
|
if lang := r.PostFormValue("lang"); lang != "" {
|
|
|
|
|
http.SetCookie(w, &http.Cookie{Name: "lang", Value: lang, MaxAge: 31536000, Path: "/"})
|
2023-06-23 12:48:13 +09:00
|
|
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 18:09:23 +09:00
|
|
|
|
var exist []string
|
|
|
|
|
|
2023-06-23 12:48:13 +09:00
|
|
|
|
if r.PostForm.Get("hozonsite") != "" {
|
|
|
|
|
url := r.PostForm.Get("hozonsite")
|
|
|
|
|
// HTTPかHTTPSじゃない場合
|
|
|
|
|
if !checkprefix(url) {
|
2023-07-17 01:02:37 +09:00
|
|
|
|
data.Err = i18n["errfuseiurl"]
|
2023-06-23 12:48:13 +09:00
|
|
|
|
ftmpl[0] = cnf.webpath + "/view/404.html"
|
|
|
|
|
} else {
|
2023-06-23 18:09:23 +09:00
|
|
|
|
eurl := stripurl(url)
|
|
|
|
|
exist = checkexist(eurl, cnf.datapath)
|
|
|
|
|
if len(exist) == 0 || r.PostForm.Get("agree") == "1" {
|
|
|
|
|
path := mkdirs(eurl, cnf.datapath)
|
|
|
|
|
getpage(url, path)
|
|
|
|
|
scanpage(path, eurl, cnf.datapath)
|
|
|
|
|
http.Redirect(w, r, cnf.domain + strings.Replace(path, cnf.datapath, "", 1), http.StatusSeeOther)
|
|
|
|
|
} else if len(exist) > 0 {
|
|
|
|
|
ftmpl[0] = cnf.webpath + "/view/check.html"
|
|
|
|
|
data.Url = url
|
|
|
|
|
var existing []Exist
|
|
|
|
|
e := Exist{}
|
|
|
|
|
for _, ex := range exist {
|
|
|
|
|
ti, err := strconv.ParseInt(tspath(ex), 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err)
|
|
|
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t := time.Unix(ti, 0)
|
|
|
|
|
e.Date = t.Format("2006年01月02日 15:04:05")
|
|
|
|
|
e.Url = strings.Replace(ex, cnf.datapath, cnf.domain, 1)
|
|
|
|
|
existing = append(existing, e)
|
|
|
|
|
}
|
|
|
|
|
data.Ext = existing
|
|
|
|
|
} else {
|
2023-07-17 01:02:37 +09:00
|
|
|
|
data.Err = i18n["errfusei"]
|
2023-06-23 18:09:23 +09:00
|
|
|
|
ftmpl[0] = cnf.webpath + "/view/404.html"
|
|
|
|
|
}
|
2023-06-23 12:48:13 +09:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tmpl = template.Must(template.ParseFiles(ftmpl[0], ftmpl[1], ftmpl[2]))
|
|
|
|
|
tmpl.Execute(w, data)
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-10 22:47:27 +09:00
|
|
|
|
|
2023-06-27 13:48:35 +09:00
|
|
|
|
// /api TODO
|
2023-06-23 12:48:13 +09:00
|
|
|
|
func apiHandler (cnf Config) func (http.ResponseWriter, *http.Request) {
|
|
|
|
|
return func (w http.ResponseWriter, r *http.Request) {
|
2023-05-14 11:37:15 +09:00
|
|
|
|
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
|
|
|
|
w.WriteHeader(200)
|
|
|
|
|
buf, _ := json.MarshalIndent(&Stat{Url: cnf.domain, Ver: version}, "", " ")
|
|
|
|
|
_, _ = w.Write(buf)
|
2023-06-23 12:48:13 +09:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-14 11:37:15 +09:00
|
|
|
|
|
2023-06-27 13:48:35 +09:00
|
|
|
|
// /archive
|
2023-06-23 12:48:13 +09:00
|
|
|
|
func archiveHandler (cnf Config) func (http.ResponseWriter, *http.Request) {
|
|
|
|
|
return func (w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
ftmpl := []string{cnf.webpath + "/view/index.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html"}
|
|
|
|
|
data := &Page{Ver: version, Ves: strings.ReplaceAll(version, ".", "")}
|
2023-05-14 11:37:15 +09:00
|
|
|
|
lang := initloc(r)
|
2023-05-19 11:53:02 +09:00
|
|
|
|
data.Lan = lang
|
2023-07-17 01:02:37 +09:00
|
|
|
|
|
|
|
|
|
i18n, err := goliblocale.GetLocale("locale/" + lang)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println("liblocaleエラー:%v", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
data.i18n = i18n
|
2023-05-12 13:50:25 +09:00
|
|
|
|
ftmpl[0] = cnf.webpath + "/view/index.html"
|
2023-05-10 22:47:27 +09:00
|
|
|
|
tmpl := template.Must(template.ParseFiles(ftmpl[0], ftmpl[1], ftmpl[2]))
|
2023-06-23 12:48:13 +09:00
|
|
|
|
path := strings.TrimPrefix(r.URL.Path, "/archive/")
|
|
|
|
|
|
|
|
|
|
if strings.Contains(path, "/static/") {
|
|
|
|
|
if !strings.HasSuffix(path, ".css") && !strings.HasSuffix(path, ".png") && !strings.HasSuffix(path, ".jpeg") && !strings.HasSuffix(path, ".jpg") && !strings.HasSuffix(path, ".webm") && !strings.HasSuffix(path, ".gif") && !strings.HasSuffix(path, ".js") {
|
|
|
|
|
http.NotFound(w, r)
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-05-10 22:47:27 +09:00
|
|
|
|
|
2023-06-23 12:48:13 +09:00
|
|
|
|
fpath := cnf.datapath + "/archive/" + path
|
|
|
|
|
http.ServeFile(w, r, fpath)
|
|
|
|
|
} else {
|
|
|
|
|
pth := r.URL.Path
|
2023-05-19 11:53:02 +09:00
|
|
|
|
if !strings.HasSuffix(pth, "/") && !strings.HasSuffix(pth, "index.html") {
|
|
|
|
|
pth += "/index.html"
|
|
|
|
|
} else if strings.HasSuffix(pth, "/") && !strings.HasSuffix(pth, "index.html") {
|
|
|
|
|
pth += "index.html"
|
|
|
|
|
}
|
2023-05-14 11:37:15 +09:00
|
|
|
|
|
2023-06-23 18:09:23 +09:00
|
|
|
|
file := cnf.datapath + pth
|
|
|
|
|
if _, err := os.Stat(file); os.IsNotExist(err) {
|
|
|
|
|
http.Redirect(w, r, "/404", http.StatusSeeOther)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bdy, err := os.ReadFile(file)
|
2023-05-19 11:53:02 +09:00
|
|
|
|
if err != nil {
|
|
|
|
|
http.Redirect(w, r, "/404", http.StatusSeeOther)
|
2023-05-10 22:47:27 +09:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-19 11:53:02 +09:00
|
|
|
|
data.Body = string(bdy)
|
|
|
|
|
tmpl = template.Must(template.ParseFiles(cnf.webpath + "/view/archive.html"))
|
|
|
|
|
tmpl.Execute(w, data)
|
|
|
|
|
data = nil
|
2023-05-10 22:47:27 +09:00
|
|
|
|
}
|
2023-06-23 12:48:13 +09:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-10 22:47:27 +09:00
|
|
|
|
|
2023-06-27 13:48:35 +09:00
|
|
|
|
// サーバー
|
2023-06-23 12:48:13 +09:00
|
|
|
|
func serv (cnf Config, port int) {
|
|
|
|
|
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
|
|
|
|
|
|
|
|
|
http.HandleFunc("/api/", apiHandler(cnf))
|
|
|
|
|
http.HandleFunc("/archive/", archiveHandler(cnf))
|
|
|
|
|
http.HandleFunc("/", siteHandler(cnf))
|
2023-05-10 22:47:27 +09:00
|
|
|
|
|
2023-07-17 02:00:40 +09:00
|
|
|
|
fmt.Println(fmt.Sprint("http://" + cnf.ip + ":", port, " でサーバーを実行中。終了するには、CTRL+Cを押して下さい。"))
|
|
|
|
|
http.ListenAndServe(fmt.Sprint(cnf.ip + ":", port), nil)
|
2023-05-10 22:47:27 +09:00
|
|
|
|
}
|