新しいルールに従い

このコミットが含まれているのは:
守矢諏訪子 2024-04-08 21:56:34 +09:00
コミット 3f760a4b5d
6個のファイルの変更283行の追加189行の削除

ファイルの表示

@ -1,5 +1,6 @@
# 1.1.1
* 静的ファイルの修正
* 新しいルールに従い
# 1.1.0
* 言語はliblocale化

ファイルの表示

@ -13,9 +13,9 @@ type Config struct {
configpath, webpath, datapath, domain, ip string
}
func getconf () (Config, error) {
var cnf Config
var cnf Config
func getconf () (Config, error) {
// バイナリ、データ、及びFreeBSDとNetBSDの場合、コンフィグ
prefix := "/usr"
// BSDだけはただの/usrではない
@ -40,7 +40,9 @@ func getconf () (Config, error) {
data, err := ioutil.ReadFile(cnf.configpath)
if err != nil {
fmt.Println("confif.jsonを開けられません", err)
return cnf, errors.New("コンフィグファイルは " + cnf.configpath + " に創作して下さい。")
return cnf, errors.New(
"コンフィグファイルは " + cnf.configpath + " に創作して下さい。",
)
}
var payload map[string]interface{}
@ -56,7 +58,9 @@ func getconf () (Config, error) {
}
if _, err := os.Stat(payload["webpath"].(string)); err != nil {
fmt.Printf("%v\n", err)
return cnf, errors.New("mkdiorコマンドをつかって、 " + payload["webpath"].(string))
return cnf, errors.New(
"mkdiorコマンドをつかって、 " + payload["webpath"].(string),
)
}
cnf.webpath = payload["webpath"].(string) // データパス
cnf.domain = payload["domain"].(string) // ドメイン名

113
main.go
ファイルの表示

@ -7,65 +7,98 @@ import (
"strconv"
)
var version = "1.1.0"
var sofname = "hozonsite"
var version = "1.1.1"
func help () {
fmt.Println("使い方:");
fmt.Println("hozonsite -v :バージョンを表示");
fmt.Println("hozonsite -s [ポート番号] ポート番号でウェブサーバーを実行(デフォルト9920)");
fmt.Println("hozonsite -h :ヘルプを表示");
fmt.Println("hozonsite <URL> :コマンドラインでウェブサイトを保存");
func help() {
fmt.Println("使い方:")
fmt.Println(sofname + " -v :バージョンを表示")
fmt.Println(
sofname +
" -s [ポート番号] ポート番号でウェブサーバーを実行(デフォルト9920)",
)
fmt.Println(sofname + " -h :ヘルプを表示")
fmt.Println(sofname + " <URL> :コマンドラインでウェブサイトを保存")
}
func main () {
cnf, err := getconf() // コンフィグファイル
func saveurlcmd(url string, cnf Config) {
// 結局HTTPかHTTPSじゃないわね…
if !checkprefix(url) {
fmt.Println("URLは不正です。終了…")
return
}
// パラメートルの文字(?、=等)を削除
eurl := stripurl(url)
// 既に/usr/local/share/hozonsite/archiveに存在するかどうか
exist := checkexist(eurl, cnf.datapath)
// 既に存在したら、使う
var confirm string
// あ、既に存在する
if len(exist) > 0 {
fmt.Println("このページが既に保存されているみたいです。")
fmt.Println("本当に手続きましょうか? [y/N]")
// 既に存在するページのURLを表示
for _, ex := range exist {
fmt.Println(strings.Replace(ex, cnf.datapath, cnf.domain, 1))
}
fmt.Scanf("%s", &confirm)
}
// 存在しない OR 「本当に手続きましょうか?」でYを入力した場合
if len(exist) == 0 || confirm == "y" || confirm == "Y" {
path := mkdirs(eurl, cnf.datapath)
// ページをダウンロード
getpage(url, path)
// 色々の必須な編集
scanpage(path, eurl, cnf.datapath)
// 新しいURLを表示
fmt.Println(cnf.domain + strings.Replace(path, cnf.datapath, "", 1))
}
}
func main() {
// コンフィグファイル
cnf, err := getconf()
if err != nil {
fmt.Println(err)
return
}
args := os.Args // コマンドラインのパラメートル
// コマンドラインのパラメートル
args := os.Args
if len(args) == 2 {
if args[1] == "-v" { // バージョンを表示
fmt.Println("hozonsite-" + version)
// バージョンを表示
if args[1] == "-v" {
fmt.Println(sofname + "-" + version)
return
} else if args[1] == "-s" { // :9920でウェブサーバーを実行
serv(cnf, 9920)
} else if args[1] == "-h" { // ヘルプを表示
help()
return
} else { // コマンドラインでウェブサイトを保存
if checkprefix(args[1]) { // プロトコールはあってるかどうか
eurl := stripurl(args[1]) // パラメートルの文字(?、=等)を削除
exist := checkexist(eurl, cnf.datapath) // 既に/usr/share/hozonsite/archiveに存在するかどうか
var confirm string // 既に存在したら、使う
if len(exist) > 0 { // あ、既に存在する
fmt.Println("このページが既に保存されているみたいです。")
fmt.Println("本当に手続きましょうか? [y/N]")
for _, ex := range exist { // 既に存在するページのURLを表示
fmt.Println(strings.Replace(ex, cnf.datapath, cnf.domain, 1))
}
fmt.Scanf("%s", &confirm)
}
if len(exist) == 0 || confirm == "y" || confirm == "Y" { // 存在しない OR 「本当に手続きましょうか?」でYを入力した場合
path := mkdirs(eurl, cnf.datapath)
getpage(args[1], path) // ページをダウンロード
scanpage(path, eurl, cnf.datapath) // 色々の必須な編集
fmt.Println(cnf.domain + strings.Replace(path, cnf.datapath, "", 1)) // 新しいURLを表示
}
return
} else { // 結局HTTPかHTTPSじゃないわね…
fmt.Println("URLは不正です。終了…")
return
}
} else {
// コマンドラインでウェブサイトを保存
saveurlcmd(args[1], cnf)
return
}
} else if len(args) == 3 && args[1] == "-s" { // 好みなポート番号でウェブサーバーを実行
if port, err := strconv.Atoi(args[2]); err != nil { // でも、数字じゃないかもしん
} else if len(args) == 3 && args[1] == "-s" {
// 好みなポート番号でウェブサーバーを実行
// でも、数字じゃないかもしん
if port, err := strconv.Atoi(args[2]); err != nil {
fmt.Printf("%qは数字ではありません。\n", args[2])
return
} else { // OK、実行しよ〜
} else {
// OK、実行しよ〜
serv(cnf, port)
}
} else { // パラメートルは不明の場合、ヘルプを表示
} else {
// パラメートルは不明の場合、ヘルプを表示
help()
return
}

ファイルの表示

@ -10,7 +10,9 @@ import (
// HTTPかHTTPSの確認
func checkprefix (url string) bool {
return strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://")
return strings.HasPrefix(
url, "http://") || strings.HasPrefix(url, "https://",
)
}
// ページは既に存在するの?

ファイルの表示

@ -15,37 +15,46 @@ import (
func scanpage (path string, domain string, thisdomain string) error {
// 先に保存したページを読み込む
fn, err := os.ReadFile(path + "/index.html")
if err != nil {
return err
}
if err != nil { return err }
// 要らないタグを削除
var script = regexp.MustCompile(`(<script.*</script>)`).ReplaceAllString(string(fn), "")
var noscript = regexp.MustCompile(`(<noscript.*</noscript>)`).ReplaceAllString(string(script), "")
var audio = regexp.MustCompile(`(<audio.*</audio>)`).ReplaceAllString(string(noscript), "")
var video = regexp.MustCompile(`(<video.*</video>)`).ReplaceAllString(string(audio), "")
var iframe = regexp.MustCompile(`(<iframe.*</iframe>)`).ReplaceAllString(string(video), "")
var script = regexp.MustCompile(
`(<script.*</script>)`).ReplaceAllString(string(fn), "",
)
var noscript = regexp.MustCompile(
`(<noscript.*</noscript>)`).ReplaceAllString(string(script), "",
)
var audio = regexp.MustCompile(
`(<audio.*</audio>)`).ReplaceAllString(string(noscript), "",
)
var video = regexp.MustCompile(
`(<video.*</video>)`).ReplaceAllString(string(audio), "",
)
var iframe = regexp.MustCompile(
`(<iframe.*</iframe>)`).ReplaceAllString(string(video), "",
)
// 追加ダウンロード+ローカル化
var ass = regexp.MustCompile(`(<img.*src=['"]|<meta.*content=['"]|<link.*href=['"])(.*\.)(png|webp|jpg|jpeg|gif|css|js|ico|svg|ttf|woff2)(\?[^'"]*)?`)
var ass = regexp.MustCompile(
// ルールに違反けど、長いからしょうがない・・・
`(<img.*src=['"]|<meta.*content=['"]|<link.*href=['"])(.*\.)(png|webp|jpg|jpeg|gif|css|js|ico|svg|ttf|woff2)(\?[^'"]*)?`,
)
// 必要であれば、ページ内のURLを修正
spath := "static/"
if !strings.HasSuffix(path, "/") {
spath = "/" + spath
}
if !strings.HasSuffix(path, "/") { spath = "/" + spath }
spath = path + spath
// また、追加ダウンロードのファイルに上記のフォルダを創作
err = os.Mkdir(spath, 0755)
if err != nil {
return err
}
if err != nil { return err }
repmap := make(map[string]string)
for _, cssx := range ass.FindAllString(iframe, -1) {
// ページ内のURLを受け取る
s := regexp.MustCompile(`(.*src=['"]|.*content=['"]|.*href=['"])`).Split(cssx, -1)
s := regexp.MustCompile(
`(.*src=['"]|.*content=['"]|.*href=['"])`).Split(cssx, -1,
)
ss := regexp.MustCompile(`(['"].*)`).Split(s[1], -1)
ogurl := ss[0] // 変わる前に元のURLを保存して
@ -60,43 +69,36 @@ func scanpage (path string, domain string, thisdomain string) error {
filename := fss[len(fss)-1]
// httpかhttpsで始まる場合
if strings.HasPrefix(ss[0], "http://") || strings.HasPrefix(ss[0], "https://") {
if strings.HasPrefix(ss[0], "http://") ||
strings.HasPrefix(ss[0], "https://") {
assdom = fss[2]
}
// フォルダの創作
asspath := path + "/static/" + assdom
err = os.MkdirAll(asspath, 0755)
if err != nil { // 出来なければ、死ね
return err
}
// 出来なければ、死ね
if err != nil { return err }
if filename == "" { // ファイル名がなければ、次に値にスキップしてね
continue
}
// ファイル名がなければ、次に値にスキップしてね
if filename == "" { continue }
if strings.HasPrefix(ss[0], "http://") || strings.HasPrefix(ss[0], "https://") { // httpかhttpsで始まったら、ダウンロードだけしよう
// httpかhttpsで始まったら、ダウンロードだけしよう
if strings.HasPrefix(ss[0], "http://") ||
strings.HasPrefix(ss[0], "https://") {
err = dlres(ss[0], filepath.Join(asspath, filename))
if err != nil { // 出来なければ、死ね
return err
}
} else { // ローカルファイルなら、ちょっと変更は必要となるかしら
if err != nil { return err }
} else {
// ローカルファイルなら、ちょっと変更は必要となるかしら
u, err := url.Parse(domain)
if err != nil { // 出来なければ、死ね
return err
}
if err != nil { return err }
rel, err := url.Parse(ss[0])
if err != nil { // 出来なければ、死ね
return err
}
if err != nil { return err }
af := u.ResolveReference(rel).String()
err = dlres(af, filepath.Join(asspath, filename))
if err != nil { // 出来なければ、死ね
return err
}
if err != nil { return err }
}
repmap[ogurl] = filepath.Join("/static", assdom, filename)
@ -104,7 +106,7 @@ func scanpage (path string, domain string, thisdomain string) error {
repmap[ogurl] = filepath.Join("/static", filename)
}
if err != nil { // 出来なければ、死ね
if err != nil {
fmt.Println(err)
return errors.New("ダウンロードに失敗:")
}
@ -118,12 +120,13 @@ func scanpage (path string, domain string, thisdomain string) error {
// index.htmlファイルを更新する
err = os.WriteFile(path + "/index.html", []byte(iframe), 0644)
if err != nil { // 出来なければ、死ね
if err != nil {
fmt.Println(err)
return errors.New("書込に失敗")
}
return nil // エラーが出なかったから、返すのは不要
// エラーが出なかったから、返すのは不要
return nil
}
// 画像、JS、CSS等ファイルのURLでパラメートルがある場合
@ -141,12 +144,11 @@ func stripver (durl string) string {
func dlres (durl string, dest string) error {
// ダウンロード
res, err := http.Get(durl)
if err != nil {
return err
}
if err != nil { return err }
defer res.Body.Close()
dest = stripver(dest) // URLでパラメートルがあれば、消す
// URLでパラメートルがあれば、消す
dest = stripver(dest)
// MIMEタイプを確認
ct := res.Header.Get("Content-Type")
@ -159,16 +161,12 @@ func dlres (durl string, dest string) error {
// ファイルを作成
f, err := os.Create(dest)
if err != nil {
return err
}
if err != nil { return err }
defer f.Close()
// ファイルを書き込む
_, err = io.Copy(f, res.Body)
if err != nil {
return err
}
if err != nil { return err }
return nil
}

242
srv.go
ファイルの表示

@ -26,6 +26,9 @@ type (
}
)
var ftmpl []string
var data *Page
func (p Page) T (key string) string {
return p.i18n[key]
}
@ -61,18 +64,114 @@ func tspath (p string) string {
return ""
}
func handleStatic(path string, cnf Config, w http.ResponseWriter, r *http.Request) {
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
}
fpath := cnf.datapath + "/archive/" + path
http.ServeFile(w, r, fpath)
}
func handlePost(w http.ResponseWriter, r *http.Request, cnf Config) {
err := r.ParseForm()
if err != nil {
fmt.Println(err)
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
// 言語変更
if lang := r.PostFormValue("lang"); lang != "" {
http.SetCookie(
w,
&http.Cookie{Name: "lang", Value: lang, MaxAge: 31536000, Path: "/"},
)
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
var exist []string
langu := initloc(r)
i18n, err := goliblocale.GetLocale(cnf.webpath + "/locale/" + langu)
if err != nil {
fmt.Printf("liblocaleエラー%v", err)
return
}
if r.PostForm.Get("hozonsite") == "" {
data.Err = i18n["errfusei"]
ftmpl[0] = cnf.webpath + "/view/404.html"
return
}
url := r.PostForm.Get("hozonsite")
// HTTPかHTTPSじゃない場合
if !checkprefix(url) {
data.Err = i18n["errfuseiurl"]
ftmpl[0] = cnf.webpath + "/view/404.html"
return
}
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,
)
return
}
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
}
// ホームページ
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, ".", "")}
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
i18n, err := goliblocale.GetLocale(cnf.webpath + "/locale/" + lang)
if err != nil {
fmt.Println("liblocaleエラー%v", err)
fmt.Printf("liblocaleエラー%v", err)
return
}
data.i18n = i18n
@ -80,61 +179,7 @@ func siteHandler (cnf Config) func (http.ResponseWriter, *http.Request) {
tmpl := template.Must(template.ParseFiles(ftmpl[0], ftmpl[1], ftmpl[2]))
if r.Method == "POST" {
err := r.ParseForm()
if err != nil {
fmt.Println(err)
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
// 言語変更
if lang := r.PostFormValue("lang"); lang != "" {
http.SetCookie(w, &http.Cookie{Name: "lang", Value: lang, MaxAge: 31536000, Path: "/"})
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
var exist []string
if r.PostForm.Get("hozonsite") != "" {
url := r.PostForm.Get("hozonsite")
// HTTPかHTTPSじゃない場合
if !checkprefix(url) {
data.Err = i18n["errfuseiurl"]
ftmpl[0] = cnf.webpath + "/view/404.html"
} else {
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 {
data.Err = i18n["errfusei"]
ftmpl[0] = cnf.webpath + "/view/404.html"
}
}
}
handlePost(w, r, cnf)
}
tmpl = template.Must(template.ParseFiles(ftmpl[0], ftmpl[1], ftmpl[2]))
@ -155,14 +200,18 @@ func apiHandler (cnf Config) func (http.ResponseWriter, *http.Request) {
// /archive
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"}
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
i18n, err := goliblocale.GetLocale(cnf.webpath + "/locale/" + lang)
if err != nil {
fmt.Println("liblocaleエラー%v", err)
fmt.Printf("liblocaleエラー%v", err)
return
}
data.i18n = i18n
@ -171,49 +220,56 @@ func archiveHandler (cnf Config) func (http.ResponseWriter, *http.Request) {
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
}
fpath := cnf.datapath + "/archive/" + path
http.ServeFile(w, r, fpath)
} else {
pth := r.URL.Path
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"
}
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)
if err != nil {
http.Redirect(w, r, "/404", http.StatusSeeOther)
return
}
data.Body = string(bdy)
tmpl = template.Must(template.ParseFiles(cnf.webpath + "/view/archive.html"))
tmpl.Execute(w, data)
data = nil
handleStatic(path, cnf, w, r)
return
}
pth := r.URL.Path
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"
}
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)
if err != nil {
http.Redirect(w, r, "/404", http.StatusSeeOther)
return
}
data.Body = string(bdy)
tmpl = template.Must(
template.ParseFiles(cnf.webpath + "/view/archive.html"),
)
tmpl.Execute(w, data)
data = nil
}
}
// サーバー
func serv (cnf Config, port int) {
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(cnf.webpath + "/static"))))
http.Handle(
"/static/",
http.StripPrefix("/static/",
http.FileServer(http.Dir(cnf.webpath + "/static"))),
)
http.HandleFunc("/api/", apiHandler(cnf))
http.HandleFunc("/archive/", archiveHandler(cnf))
http.HandleFunc("/", siteHandler(cnf))
fmt.Println(fmt.Sprint("http://" + cnf.ip + ":", port, " でサーバーを実行中。終了するには、CTRL+Cを押して下さい。"))
fmt.Println(fmt.Sprint(
"http://" + cnf.ip + ":",
port,
" でサーバーを実行中。終了するには、CTRL+Cを押して下さい。"),
)
http.ListenAndServe(fmt.Sprint(cnf.ip + ":", port), nil)
}