From 3f7614956a352b66d2d4a23a42af655e601d2ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AB=8F=E8=A8=AA=E5=AD=90?= Date: Wed, 10 May 2023 15:29:26 +0900 Subject: [PATCH] =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B32.?= =?UTF-8?q?0.0=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 15 + Makefile | 45 +++ README.md | 267 ++++++++++++++++- checkers.go | 16 ++ config.go | 90 ++++++ config.json | 2 +- install.sh | 80 ------ main.go | 269 +++--------------- makers.go | 39 +++ srv.go | 130 +++++++++ srv/freebsd/usr/local/etc/rc.d/urloli | 42 --- srv/linux/etc/init.d/urloli | 42 --- .../etc/nginx/sites-enabled/urloli-clear.conf | 40 --- .../etc/nginx/sites-enabled/urloli-dark.conf | 18 -- srv/linux/etc/runit/sv/urloli/run | 3 - srv/linux/etc/systemd/system/urloli.service | 11 - srv/openbsd/etc/acme-client.conf | 7 - srv/openbsd/etc/httpd-clear.conf | 24 -- srv/openbsd/etc/httpd-dark.conf | 8 - srv/openbsd/etc/rc.d/urloli | 10 - urloli.1 | 30 ++ view/footer.html | 2 +- 22 files changed, 670 insertions(+), 520 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 Makefile create mode 100644 checkers.go create mode 100644 config.go delete mode 100755 install.sh create mode 100644 makers.go create mode 100644 srv.go delete mode 100755 srv/freebsd/usr/local/etc/rc.d/urloli delete mode 100644 srv/linux/etc/init.d/urloli delete mode 100644 srv/linux/etc/nginx/sites-enabled/urloli-clear.conf delete mode 100644 srv/linux/etc/nginx/sites-enabled/urloli-dark.conf delete mode 100644 srv/linux/etc/runit/sv/urloli/run delete mode 100644 srv/linux/etc/systemd/system/urloli.service delete mode 100644 srv/openbsd/etc/acme-client.conf delete mode 100644 srv/openbsd/etc/httpd-clear.conf delete mode 100644 srv/openbsd/etc/httpd-dark.conf delete mode 100644 srv/openbsd/etc/rc.d/urloli create mode 100644 urloli.1 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c955e8a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# 2.0.0 +* Makefile化 +* ソースコードは複数ファイルに分ける +* コマンドラインからURL短熟 +* バージョンの表示 +* ヘルプの表示 +* manページ +* ポート番号はご自由に決める様にした(デフォルトは9910) + +# 1.0.0 +* PHPからGoに交換しました +* 今度からバージョンを付きます + +# それ以前 +* 色々 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f04b4aa --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +NAME=urloli +VERSION=2.0.0 +# Linux、Cruxの場合は必須。他のディストリビューションはどうでも良い +PREFIX=/usr +# FreeBSDとOpenBSD +#PREFIX=/usr/local +MANPREFIX=${PREFIX}/share/man +# LinuxとOpenBSD +CNFPREFIX=/etc +# FreeBSD +#CNFPREFIX=/usr/local/etc +CC=CGO_ENABLED=0 go build +# リリース。なし=デバッグ。 +RELEASE=-ldflags="-s -w" -buildvcs=false + +all: + ${CC} ${RELEASE} -o ${NAME} $< + +clean: + rm -f ${NAME} ${NAME}-${VERSION}.tar.gz + +dist: clean + mkdir -p ${NAME}${VERSION} + cp -R LICENSE.txt Makefile README.md CHANGELOG.md\ + view static logo.jpg\ + ${NAME}.1 *.go *.json ${NAME}-${VERSION} + tar -zcfv ${NAME}-${VERSION}.tar.gz ${NAME}-${VERSION} + rm -rf ${NAME}-${VERSION} + +install: all + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f ${NAME} ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}/bin/${NAME} + mkdir -p ${DESTDIR}${MANPREFIX}/man1 + sed "s/VERSION/${VERSION}/g" < ${NAME}.1 > ${DESTDIR}${MANPREFIX}/man1/${NAME}.1 + chmod 644 ${DESTDIR}${MANPREFIX}/man1/${NAME}.1 + mkdir -p ${DESTDIR}${CNFPREFIX}/${NAME} + chmod 755 ${DESTDIR}${CNFPREFIX}/${NAME} + +uninstall: + rm -f ${DESTDIOR}${PREFIX}/bin/${NAME}\ + ${DESTDIR}${MANPREFIX}/man1/${NAME}.1\ + ${DESTDIR}${CNFPREFIX}/${NAME} + +.PHONY: all options clean dist install uninstall diff --git a/README.md b/README.md index 93518a0..7a25af2 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,272 @@ クッソ小さいURL短縮作成ソフトだわ〜♡ ## インストールする方法 + +### 従属ソフト + +* Go 1.19以上 +* nginx又はOpenBSDのhttpd +* 良いOS (GNU/Linux、OpenBSD、又はFreeBSD) + +## インストールする方法 + +### 全部(opendoasを使わなければ、sudoをご利用、又はopendoasをインストールして下さい) + ```sh -chmod +x install.sh && doas ./install.sh domain.tld +make +doas make install ``` -## links.jsonファイルの中に +### OpenBSD + +```sh +nvim /etc/rc.d/urloli ``` -{ - "hogehoge": "https://076.moe" + +``` +#!/bin/ksh +# +# $OpenBSD: urloli.rc,v 1.4 2018/01/11 19:27:11 rpe Exp $ + +name="urloli" +daemon="/usr/local/bin/${name}" + +. /etc/rc.d/rc.subr + +rc_cmd $1 +``` + +```sh +nvim /etc/rc.conf.local +``` + +``` +relayd_flags= +pkg_scripts=urloli +``` + +```sh +rcctl enable urloli +rcctl start urloli +``` + +### FreeBSD + +```sh +nvim /usr/local/etc/rc.d/urloli +``` + +``` +#!/bin/sh + +# PROVIDE: urloli +# REQUIRE: NETWORKING SYSLOG +# KEYWORD: shutdown +# +# Add the following lines to /etc/rc.conf to enable urloli: +# +#urloli_enable="YES" + +. /etc/rc.subr + +name="urloli" +rcvar="urloli_enable" + +load_rc_config $name + +: ${urloli_enable:="NO"} +: ${urloli_facility:="daemon"} +: ${urloli_priority:="debug"} + +command="/usr/local/bin/${name}" +procname="/usr/local/bin/${name}" + +pidfile="/var/run/${name}.pid" + +start_cmd="${name}_start" + +urloli_start() { + for d in /var/db/urloli /var/log/urloli; do + if [ ! -e "$d" ]; then + mkdir "$d" + fi + done + /usr/sbin/daemon -S -l ${urloli_facility} -s ${urloli_priority} -T ${name} \ + -p ${pidfile} \ + /usr/bin/env -i \ + "PATH=/usr/local/bin:${PATH}" \ + $command +} + +run_rc_command "$1" +``` + +```sh +sysrc urloli_enable=YES +service start urloli +``` + +### Crux + +```sh +nvim /etc/rc.d/urloli +``` + +``` +#!/bin/sh +# +# /etc/rc.d/urloli: start/stop the urloli daemon +# + +SSD=/sbin/start-stop-daemon +NAME=urloli +PROG=/usr/bin/$NAME +PIOD=/run/$NAME.pid + +case $1 in +start) + $SSD --start --pidfile $PID --exec $PROG + ;; +stop) + $SSD --stop --retry 10 --pidfile $PID + ;; +restart) + $0 stop + $0 start + ;; +status) + $SSD --status --pidfile $PID + case $? in + 0) echo "$PROG は実行中。pid $(cat $PID)" ;; + 1) echo "$PROG は実行していませんが、pidファイルは「 $PID 」として存在しそう" ;; + 3) echo "$PROG は停止中" ;; + 4) echo "状況不明" ;; + esac + ;; +*) + echo "usage: $0 [start|sto@|restart|status]" + ;; +esac + +# End of file +``` + +### Devuan/Debian/Ubuntu/Arch/Artix/AlmaLinux等 + +```sh +nvim /etc/init.d/urloli +``` + +``` +#!/bin/sh +# +# chkconfig: 35 90 12 +# description: URL Loli server +# + +NAME=urloli +DESC=urloli +DAEMON=/usr/bin/$NAME + +start () { + echo "URLロリサーバーは開始中:\n" + /usr/bin/urloli -s 9910 &>/dev/null & + touch /var/lock/subsys/urloli + echo +} + +stop () { + echo "URLロリサーバーは終了中:\n" + pkill urloli + rm -f /var/lock/subsys/urloli + echo +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + restart|reload|condrestart) + stop + start + ;; + *) + echo $"Usage: $0 {start|stop|restart|status}" + exit 1 +esac +``` + +## ウェブサーバー + +### OpenBSD + +```sh +nvim /etc/relayd.conf +``` + +``` +table { IPADDRESS } + +http protocol "httpproxy" { + pass request quick header "Host" value "DOMAIN" forward to + block +} + +relay "proxy" { + listen on * port 443 tls + protocol "httpproxy" + + forward to * port 9910 } ``` -https://(ドメイン名)/hogehoge にアクセスすると、https://076.moe に移転されます。 +### その他 + +```sh +server { + server_name DOMAIN www.DOMAIN; + root /var/www/htdocs/urloli; + + access_log off; + error_log off; + + if ($host = www.DOMAIN) { + return 301 https://DOMAIN$request_uri; + } + + location /static { + try_files $uri $uri/ /static/$args; + } + + location / { + proxy_pass http://localhost:9910; + } + + listen [::]:443 ssl ipv6only=on; + listen 443 ssl; + ssl_certificate /etc/letsencrypt/live/DOMAIN/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/DOMAIN/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf +} + +server { + if ($host = DOMAIN) { + return 301 https://DOMAIN$request_uri; + } + + if ($host = www.DOMAIN) { + return 301 https://DOMAIN$request_uri; + } + + listen 80; + listen [::]:80; + server_name DOMAIN www.DOMAIN; + return 404; +} +``` diff --git a/checkers.go b/checkers.go new file mode 100644 index 0000000..d5859f8 --- /dev/null +++ b/checkers.go @@ -0,0 +1,16 @@ +package main + +import ( + "strings" + "unicode/utf8" +) + +// http://かhttps://で始まるかどうか +func checkprefix (url string) bool { + return strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") +} + +// URLは500文字以内かどうか +func checkcharlim (url string) bool { + return utf8.RuneCountInString(url) <= 500 +} diff --git a/config.go b/config.go new file mode 100644 index 0000000..2e0a640 --- /dev/null +++ b/config.go @@ -0,0 +1,90 @@ +package main + +import ( + "fmt" + "encoding/json" + "io/ioutil" + "runtime" + "os" + "errors" +) + +type Config struct { + configpath string + linkpath string + webpath string + domain string +} + +func geturl (url string, linkpath string, checkjson bool) (string, string) { + payload := getlinks(linkpath) + + for k := range payload { + if checkjson { + if url == payload[k] { + return url, k + } + } else { + if url == k { + return payload[k].(string), k + } + } + } + + return "", "" +} + +func getlinks (linkpath string) map[string]interface{} { + data, err := ioutil.ReadFile(linkpath) + if err != nil { + fmt.Println("links.jsonを開けられません: ", err) + } + + var payload map[string]interface{} + json.Unmarshal(data, &payload) + + return payload +} + +func getconf () (Config, error) { + var cnf Config + + prefix := "/usr" + if runtime.GOOS == "freebsd" || runtime.GOOS == "openbsd" { + prefix += "/local" + } + + cnf.configpath = "/etc/urloli/config.json" + cnf.linkpath = "/etc/urloli/links.json" + if runtime.GOOS == "freebsd" { + cnf.configpath = prefix + cnf.configpath + cnf.linkpath = prefix + cnf.linkpath + } + + data, err := ioutil.ReadFile(cnf.configpath) + if err != nil { + fmt.Println("config.jsonを開けられません: ", err) + return cnf, errors.New("コンフィグファイルは " + cnf.configpath + " に創作して下さい。") + } + + var payload map[string]interface{} + json.Unmarshal(data, &payload) + if payload["webpath"] == nil { + return cnf, errors.New("「webpath」の値が設置していません。") + } + if payload["domain"] == nil { + return cnf, errors.New("「domain」の値が設置していません。") + } + if _, err := os.Stat(payload["webpath"].(string)); err != nil { + fmt.Printf("%v\n", err) + return cnf, errors.New("mkdirコマンドを使って、 " + payload["webpath"].(string)) + } + if !checkprefix(payload["domain"].(string)) { + return cnf, errors.New("URLは「http://」又は「https://」で始める様にして下さい。") + } + cnf.webpath = payload["webpath"].(string) + cnf.domain = payload["domain"].(string) + payload = nil + + return cnf, nil +} diff --git a/config.json b/config.json index 4c389ed..0634c65 100644 --- a/config.json +++ b/config.json @@ -1,4 +1,4 @@ { "domain": "https://urlo.li", - "webpath": "/www/active/urlo.li" + "webpath": "/var/www/htdocs/urloli" } diff --git a/install.sh b/install.sh deleted file mode 100755 index 9f5507e..0000000 --- a/install.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/sh - -unamestr=$(uname) -domain="$1" - -case "$domain" in - *.i2p) network="i2p" ;; - *.onion) network="tor" ;; - *) network="www" ;; -esac - -if [ "$unamestr" = 'FreeBSD' ]; then - mkdir /usr/local/etc/urloli - cp -i links.sample.json /usr/local/etc/urloli/links.json - cp -i config.json /usr/local/etc/urloli/config.json - sed -i .orig "s/urlo\.li/$domain/g" /usr/local/etc/urloli/config.json - rm -rf /usr/local/etc/urloli/config.json.orig - go build -buildvcs=false -else - mkdir /etc/urloli - cp -i links.sample.json /etc/urloli/links.json - cp -i config.json /etc/urloli/config.json - sed -i "s/urlo\.li/$domain/g" /etc/urloli/config.json - go build -fi - -mv -i urloli /usr/local/bin - -if [ "$unamestr" = 'Linux' ]; then - platform=$(cat /etc/os-release | grep "^ID=") - if [ "$platform" = 'ID=debian' -o "$platform" = "ID=devuan" -o "$platform" = "ID=ubuntu" ]; then - apt update && apt install certbot - elif [ "$platform" = "ID=arch" -o "$platform" = "ID=artix" ]; then - pacman -S certbot - elif [ "$platform" = "ID=centos" -o "$platform" = "ID=rhel" ]; then - dnf install certbot - fi - if [ "$network" = 'www' ]; then - certbot certonly --webroot -d $domain -d www.$domain - cp -i srv/linux/etc/nginx/sites-enabled/urloli-clear.conf /etc/nginx/sites-enabled/urloli.conf - else - cp -i srv/linux/etc/nginx/sites-enabled/urloli-dark.conf /etc/nginx/sites-enabled/urloli.conf - fi - sed -i "s/urlo\.li/$domain/g" /etc/nginx/sites-enabled/urloli.conf - cp -i srv/linux/etc/init.d/urloli /etc/init.d - chmod +x /etc/init.d/urloli - /etc/init.d/urloli start -elif [ "$unamestr" = 'OpenBSD' ]; then - if [ "$network" = 'www' ]; then - cat /etc/acme-client.conf srv/openbsd/etc/acme-client.conf > /etc/acme-client.conf - sed -i "s/urlo\.li/$domain/g" /etc/acme-client.conf - cat /etc/httpd.conf srv/openbsd/etc/httpd-clear.conf > /etc/httpd.conf - else - cat /etc/httpd.conf srv/openbsd/etc/httpd-dark.conf > /etc/httpd.conf - fi - sed -i "s/urlo\.li/$domain/g" /etc/httpd.conf - rcctl restart httpd - if [ "$network" = 'www' ]; then - acme-client -v $domain - fi - cp -i srv/openbsd/etc/rc.d/urloli /etc/rc.d - chmod +x /etc/rc.d/urloli - rcctl start urloli -elif [ "$unamestr" = 'FreeBSD' ]; then - pkg install py39-certbot - if [ "$network" = 'www' ]; then - certbot certonly --webroot -d $domain -d www.$domain - cp -i srv/linux/etc/nginx/sites-enabled/urloli-clear.conf /usr/local/etc/nginx/sites-enabled/urloli.conf - else - cp -i srv/linux/etc/nginx/sites-enabled/urloli-dark.conf /usr/local/etc/nginx/sites-enabled/urloli.conf - fi - sed -i .orig "s/urlo\.li/$domain/g" /usr/local/etc/nginx/sites-enabled/urloli.conf - rm -rf /usr/local/etc/nginx/sites-enabled/urloli.conf.orig - cp -i srv/freebsd/usr/local/etc/rc.d/urloli /usr/local/etc/rc.d - chmod +x /usr/local/etc/rc.d/urloli - sysrc urloli_enable=YES - service start urloli -fi - -exit diff --git a/main.go b/main.go index be667ec..d7926ec 100644 --- a/main.go +++ b/main.go @@ -1,248 +1,61 @@ package main import ( - "text/template" "fmt" - "strings" - "net/http" - "crypto/rand" - "encoding/json" - "unicode/utf8" - "io/ioutil" "os" - "runtime" + "strconv" ) -var ( - linkpath string - configpath string - webpath string - payload map[string]interface{} -) +var version = "2.0.0" -func mkstring () string { - stringchars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" - newstring := "" - b := make([]byte, 5) - - // 乱数を生成 - if _, err := rand.Read(b); err != nil { - return "不明なエラー" - } - - // ランダムに取り出して文字列を生成 - for _, v := range b { - // index が stringchars の長さに収まるように調整 - newstring += string(stringchars[int(v)%len(stringchars)]) - } - - return newstring -} - -// http://かhttps://で始まるかどうか -func checkprefix (url string) bool { - if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { - return false - } - - return true -} - -// URLは500文字以内かどうか -func checkcharlim (url string) bool { - if utf8.RuneCountInString(url) > 500 { - return false - } - return true -} - -func geturl (url string, checkjson bool) string { - payload := getlinks() - - for k := range payload { - if checkjson { - if url == payload[k] { - return url - } - } else { - if url == k { - return payload[k].(string) - } - } - } - - return "" -} - -func insertjson (url string) string { - payload := getlinks() - - newstring := mkstring() - payload[newstring] = url - m, _ := json.Marshal(&payload) - payload = nil - ioutil.WriteFile(linkpath, m, os.ModePerm) - // fmt.Printf("%s\n", m) - - return newstring -} - -type Page struct { - Tit string - Err string - Url string - Dom string - Lan string -} - -func getlinks () map[string]interface{} { - data, err := ioutil.ReadFile(linkpath) - if err != nil { - fmt.Println("links.jsonを開けられません: ", err) - } - - var payload map[string]interface{} - json.Unmarshal(data, &payload) - - return payload -} - -func getconfig () map[string]interface{} { - data, err := ioutil.ReadFile(configpath) - if err != nil { - fmt.Println("config.jsonを開けられません: ", err) - } - - var payload map[string]interface{} - json.Unmarshal(data, &payload) - - return payload +func help () { + fmt.Println("使い方:"); + fmt.Println("urloli -v :バージョンを表示"); + fmt.Println("urloli -s [ポート番号] :ポート番号でウェブサーバーを実行(デフォルト=9910)"); + fmt.Println("urloli -h :ヘルプを表示"); + fmt.Println("urloli :コマンドラインでURLを短熟"); } func main () { - if runtime.GOOS == "freebsd" { - linkpath = "/usr/local/etc/urloli/links.json" - configpath = "/usr/local/etc/urloli/config.json" - } else { - linkpath = "/etc/urloli/links.json" - configpath = "/etc/urloli/config.json" + cnf, err := getconf() + if err != nil { + fmt.Println(err) + return } + args := os.Args - payload := getconfig() - domain := payload["domain"].(string) - webpath := payload["webpath"].(string) - - payload = nil - http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) - - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - cookie, err := r.Cookie("lang") - if err != nil { - http.SetCookie(w, &http.Cookie {Name: "lang", Value: "ja", MaxAge: 31536000, Path: "/"}) - http.Redirect(w, r, "/", http.StatusSeeOther) + if len(args) == 2 { + if args[1] == "-v" { + fmt.Println("urloli-" + version) return - } - - uri := r.URL.Path - query := r.URL.Query() - qnewurl := query.Get("newurl") - data := &Page{Tit: "トップ", Lan: cookie.Value} - if cookie.Value == "en" { - data = &Page{Tit: "Top", Lan: cookie.Value} - } - tmpl := template.Must(template.ParseFiles(webpath + "/view/index.html", webpath + "/view/header.html", webpath + "/view/footer.html")) - - if r.Method == "POST" { - err := r.ParseForm() - if err != nil { fmt.Println(err) } - if r.PostForm.Get("sosin") != "" { - if r.PostForm.Get("newadd") != "" { - addurl := r.PostForm.Get("newadd") - chkprx := checkprefix(addurl) - chklim := checkcharlim(addurl) - if !chkprx { - if cookie.Value == "ja" { - data = &Page{Tit: "不正なURL", Err: "URLは「http://」又は「https://」で始めます。", Lan: cookie.Value} - } else { - data = &Page{Tit: "Invalid URL", Err: "The URL should start with \"http://\" or \"https://\".", Lan: cookie.Value} - } - tmpl = template.Must(template.ParseFiles(webpath + "/view/404.html", webpath + "/view/header.html", webpath + "/view/footer.html")) - } - if !chklim { - if cookie.Value == "ja" { - data = &Page{Tit: "不正なURL", Err: "URLは500文字以内です。", Lan: cookie.Value} - } else { - data = &Page{Tit: "Invalid URL", Err: "The URL should be less than 500 characters.", Lan: cookie.Value} - } - data = &Page{Tit: "不正なURL", Err: ""} - tmpl = template.Must(template.ParseFiles(webpath + "/view/404.html", webpath + "/view/header.html", webpath + "/view/footer.html")) - } - - if chklim && chkprx { - chkfn := geturl(addurl, true) - if chkfn != "" { - http.Redirect(w, r, addurl, http.StatusSeeOther) - return - } else { - res := insertjson(addurl) - if cookie.Value == "ja" { - data = &Page{Tit: "短縮済み", Lan: cookie.Value, Url: res, Dom: domain} - } else { - data = &Page{Tit: "Shortened", Lan: cookie.Value, Url: res, Dom: domain} - } - tmpl = template.Must(template.ParseFiles(webpath + "/view/submitted.html", webpath + "/view/header.html", webpath + "/view/footer.html")) - } - } + } else if args[1] == "-s" { + serv(cnf, 9910) + } else if args[1] == "-h" { + help() + return + } else { + if checkprefix(args[1]) { + _, key := geturl(args[1], cnf.linkpath, true) + if (key != "") { + fmt.Println(cnf.domain + "/" + key) } else { - if cookie.Value == "ja" { - data = &Page{Tit: "未検出", Err: "URLをご入力下さい。", Lan: cookie.Value} - } else { - data = &Page{Tit: "Not found", Err: "Please enter a URL.", Lan: cookie.Value} - } - tmpl = template.Must(template.ParseFiles(webpath + "/view/404.html", webpath + "/view/header.html", webpath + "/view/footer.html")) + fmt.Println(cnf.domain + "/" + insertjson(args[1], cnf.linkpath)) } - } else if r.PostForm.Get("langchange") != "" { - if cookie.Value == "ja" { - http.SetCookie(w, &http.Cookie {Name: "lang", Value: "en"}) - } else { - http.SetCookie(w, &http.Cookie {Name: "lang", Value: "ja"}) - } - http.Redirect(w, r, "/", http.StatusSeeOther) + return + } else { + fmt.Println("URLは不正です。終了…") return } - } else { - if uri == "/" && qnewurl == "" { - tmpl = template.Must(template.ParseFiles(webpath + "/view/index.html", webpath + "/view/header.html", webpath + "/view/footer.html")) - } else if uri != "/" && qnewurl == "" { - red := geturl(uri[1:], false) - if red != "" { - http.Redirect(w, r, red, http.StatusSeeOther) - return - } else { - if cookie.Value == "ja" { - data = &Page{Tit: "未検出", Err: "このURLを見つけられませんでした。", Lan: cookie.Value} - } else { - data = &Page{Tit: "Not found", Err: "This URL could not be found.", Lan: cookie.Value} - } - tmpl = template.Must(template.ParseFiles(webpath + "/view/404.html", webpath + "/view/header.html", webpath + "/view/footer.html")) - } - } else if uri == "/" && qnewurl != "" { - data = &Page{Tit: "短縮済み", Url: qnewurl, Dom: domain} - tmpl = template.Must(template.ParseFiles(webpath + "/view/submitted.html", webpath + "/view/header.html", webpath + "/view/footer.html")) - } else { - if cookie.Value == "ja" { - data = &Page{Tit: "未検出", Err: "このURLを見つけられませんでした。", Lan: cookie.Value} - } else { - data = &Page{Tit: "Not found", Err: "This URL could not be found.", Lan: cookie.Value} - } - tmpl = template.Must(template.ParseFiles(webpath + "/view/404.html", webpath + "/view/header.html", webpath + "/view/footer.html")) - } } - - tmpl.Execute(w, data) - data = nil - }) - - fmt.Println("http://127.0.0.1:9910 でサーバーを実行中。終了するには、CTRL+Cを押して下さい。") - http.ListenAndServe(":9910", 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 { + serv(cnf, port) + } + } else { + help() + return + } } diff --git a/makers.go b/makers.go new file mode 100644 index 0000000..54c1759 --- /dev/null +++ b/makers.go @@ -0,0 +1,39 @@ +package main + +import ( + "crypto/rand" + "encoding/json" + "io/ioutil" + "os" +) + +func mkstring () string { + stringchars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" + newstring := "" + b := make([]byte, 5) + + // 乱数を生成 + if _, err := rand.Read(b); err != nil { + return "不明なエラー" + } + + // ランダムに取り出して文字列を生成 + for _, v := range b { + // index が stringchars の長さに収まるように調整 + newstring += string(stringchars[int(v)%len(stringchars)]) + } + + return newstring +} + +func insertjson (url string, linkpath string) string { + payload := getlinks(linkpath) + + newstring := mkstring() + payload[newstring] = url + m, _ := json.Marshal(&payload) + payload = nil + ioutil.WriteFile(linkpath, m, os.ModePerm) + + return newstring +} diff --git a/srv.go b/srv.go new file mode 100644 index 0000000..051f29e --- /dev/null +++ b/srv.go @@ -0,0 +1,130 @@ +package main + +import ( + "text/template" + "fmt" + "net/http" +) + +type Page struct { + Tit string + Err string + Url string + Dom string + Lan string +} + +func serv (cnf Config, port int) { + http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + cookie, err := r.Cookie("lang") + if err != nil { + http.SetCookie(w, &http.Cookie {Name: "lang", Value: "ja", MaxAge: 31536000, Path: "/"}) + http.Redirect(w, r, "/", http.StatusSeeOther) + return + } + + uri := r.URL.Path + query := r.URL.Query() + qnewurl := query.Get("newurl") + data := &Page{Tit: "トップ", Lan: cookie.Value} + if cookie.Value == "en" { + data = &Page{Tit: "Top", Lan: cookie.Value} + } + tmpl := template.Must(template.ParseFiles(cnf.webpath + "/view/index.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html")) + + if r.Method == "POST" { + err := r.ParseForm() + if err != nil { fmt.Println(err) } + if r.PostForm.Get("sosin") != "" { + if r.PostForm.Get("newadd") != "" { + addurl := r.PostForm.Get("newadd") + chkprx := checkprefix(addurl) + chklim := checkcharlim(addurl) + if !chkprx { + if cookie.Value == "ja" { + data = &Page{Tit: "不正なURL", Err: "URLは「http://」又は「https://」で始めます。", Lan: cookie.Value} + } else { + data = &Page{Tit: "Invalid URL", Err: "The URL should start with \"http://\" or \"https://\".", Lan: cookie.Value} + } + tmpl = template.Must(template.ParseFiles(cnf.webpath + "/view/404.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html")) + } + if !chklim { + if cookie.Value == "ja" { + data = &Page{Tit: "不正なURL", Err: "URLは500文字以内です。", Lan: cookie.Value} + } else { + data = &Page{Tit: "Invalid URL", Err: "The URL should be less than 500 characters.", Lan: cookie.Value} + } + data = &Page{Tit: "不正なURL", Err: ""} + tmpl = template.Must(template.ParseFiles(cnf.webpath + "/view/404.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html")) + } + + if chklim && chkprx { + chkfn, _ := geturl(addurl, cnf.linkpath, true) + if chkfn != "" { + http.Redirect(w, r, addurl, http.StatusSeeOther) + return + } else { + res := insertjson(addurl, cnf.linkpath) + if cookie.Value == "ja" { + data = &Page{Tit: "短縮済み", Lan: cookie.Value, Url: res, Dom: cnf.domain} + } else { + data = &Page{Tit: "Shortened", Lan: cookie.Value, Url: res, Dom: cnf.domain} + } + tmpl = template.Must(template.ParseFiles(cnf.webpath + "/view/submitted.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html")) + } + } + } else { + if cookie.Value == "ja" { + data = &Page{Tit: "未検出", Err: "URLをご入力下さい。", Lan: cookie.Value} + } else { + data = &Page{Tit: "Not found", Err: "Please enter a URL.", Lan: cookie.Value} + } + tmpl = template.Must(template.ParseFiles(cnf.webpath + "/view/404.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html")) + } + } else if r.PostForm.Get("langchange") != "" { + if cookie.Value == "ja" { + http.SetCookie(w, &http.Cookie {Name: "lang", Value: "en"}) + } else { + http.SetCookie(w, &http.Cookie {Name: "lang", Value: "ja"}) + } + http.Redirect(w, r, "/", http.StatusSeeOther) + return + } + } else { + if uri == "/" && qnewurl == "" { + tmpl = template.Must(template.ParseFiles(cnf.webpath + "/view/index.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html")) + } else if uri != "/" && qnewurl == "" { + red, _ := geturl(uri[1:], cnf.linkpath, false) + if red != "" { + http.Redirect(w, r, red, http.StatusSeeOther) + return + } else { + if cookie.Value == "ja" { + data = &Page{Tit: "未検出", Err: "このURLを見つけられませんでした。", Lan: cookie.Value} + } else { + data = &Page{Tit: "Not found", Err: "This URL could not be found.", Lan: cookie.Value} + } + tmpl = template.Must(template.ParseFiles(cnf.webpath + "/view/404.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html")) + } + } else if uri == "/" && qnewurl != "" { + data = &Page{Tit: "短縮済み", Url: qnewurl, Dom: cnf.domain} + tmpl = template.Must(template.ParseFiles(cnf.webpath + "/view/submitted.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html")) + } else { + if cookie.Value == "ja" { + data = &Page{Tit: "未検出", Err: "このURLを見つけられませんでした。", Lan: cookie.Value} + } else { + data = &Page{Tit: "Not found", Err: "This URL could not be found.", Lan: cookie.Value} + } + tmpl = template.Must(template.ParseFiles(cnf.webpath + "/view/404.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html")) + } + } + + tmpl.Execute(w, data) + data = nil + }) + + fmt.Println(fmt.Sprint("http://127.0.0.1:", port, " でサーバーを実行中。終了するには、CTRL+Cを押して下さい。")) + http.ListenAndServe(fmt.Sprint(":", port), nil) +} diff --git a/srv/freebsd/usr/local/etc/rc.d/urloli b/srv/freebsd/usr/local/etc/rc.d/urloli deleted file mode 100755 index aa0f8fb..0000000 --- a/srv/freebsd/usr/local/etc/rc.d/urloli +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh - -# PROVIDE: urloli -# REQUIRE: NETWORKING SYSLOG -# KEYWORD: shutdown -# -# Add the following lines to /etc/rc.conf to enable urloli: -# -#urloli_enable="YES" - -. /etc/rc.subr - -name="urloli" -rcvar="urloli_enable" - -load_rc_config $name - -: ${urloli_enable:="NO"} -: ${urloli_facility:="daemon"} -: ${urloli_priority:="debug"} - -command="/usr/local/bin/${name}" -procname="/usr/local/bin/${name}" - -pidfile="/var/run/${name}.pid" - -start_cmd="${name}_start" - -urloli_start() { - for d in /var/db/urloli /var/log/urloli; do - if [ ! -e "$d" ]; then - mkdir "$d" - fi - done - /usr/sbin/daemon -S -l ${urloli_facility} -s ${urloli_priority} -T ${name} \ - -p ${pidfile} \ - /usr/bin/env -i \ - "PATH=/usr/local/bin:${PATH}" \ - $command -} - -run_rc_command "$1" diff --git a/srv/linux/etc/init.d/urloli b/srv/linux/etc/init.d/urloli deleted file mode 100644 index ef00b19..0000000 --- a/srv/linux/etc/init.d/urloli +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh -# -# chkconfig: 35 90 12 -# description: URL Loli server -# - -NAME=urloli -DESC=urloli -DAEMON=/usr/local/bin/$NAME - -start () { - echo "URLロリサーバーの開始:\n" - sudo -u urloli /usr/local/bin/urloli &>/dev/null & - echo -} - -stop () { - echo "URLロリサーバーの終了: \n" - pkill urloli - echo -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? - ;; - restart|reload|condrestart) - stop - start - ;; - *) - echo $"Usage: $0 {start|stop|restart|status}" - exit 1 -esac - -exit 0 diff --git a/srv/linux/etc/nginx/sites-enabled/urloli-clear.conf b/srv/linux/etc/nginx/sites-enabled/urloli-clear.conf deleted file mode 100644 index 41cf790..0000000 --- a/srv/linux/etc/nginx/sites-enabled/urloli-clear.conf +++ /dev/null @@ -1,40 +0,0 @@ -server { - server_name urlo.li www.urlo.li; - root /www/active/urlo.li; - - access_log off; - error_log off; - - if ($host = www.urlo.li) { - return 301 https://urlo.li$request_uri; - } - - location /static { - try_files $uri $uri/ /static/$args; - } - - location / { - proxy_pass http://localhost:9910; - } - - listen [::]:443 ssl ipv6only=on; - listen 443 ssl; - ssl_certificate /etc/letsencrypt/live/urlo.li/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/urlo.li/privkey.pem; - include /etc/letsencrypt/options-ssl-nginx.conf -} - -server { - if ($host = urlo.li) { - return 301 https://urlo.li$request_uri; - } - - if ($host = www.urlo.li) { - return 301 https://urlo.li$request_uri; - } - - listen 80; - listen [::]:80; - server_name urlo.li www.urlo.li; - return 404; -} diff --git a/srv/linux/etc/nginx/sites-enabled/urloli-dark.conf b/srv/linux/etc/nginx/sites-enabled/urloli-dark.conf deleted file mode 100644 index 5596bbe..0000000 --- a/srv/linux/etc/nginx/sites-enabled/urloli-dark.conf +++ /dev/null @@ -1,18 +0,0 @@ -server { - server_name urlo.li; - root /www/active/urlo.li; - - access_log off; - error_log off; - - location /static { - try_files $uri $uri/ /static/$args; - } - - location / { - proxy_pass http://localhost:9910; - } - - listen 80; - listen [::]:80; -} diff --git a/srv/linux/etc/runit/sv/urloli/run b/srv/linux/etc/runit/sv/urloli/run deleted file mode 100644 index 818323b..0000000 --- a/srv/linux/etc/runit/sv/urloli/run +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -e -exec 2>&1 -exec chpst urloli diff --git a/srv/linux/etc/systemd/system/urloli.service b/srv/linux/etc/systemd/system/urloli.service deleted file mode 100644 index c27c47f..0000000 --- a/srv/linux/etc/systemd/system/urloli.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description="URLロリ" -Wants=network.target -Before=network.target -[Service] -Type=simple -ExecStart=/usr/local/bin/urloli -ExecStop=pkill urloli -[Install] -WantedBy=multi-user.target - diff --git a/srv/openbsd/etc/acme-client.conf b/srv/openbsd/etc/acme-client.conf deleted file mode 100644 index d2492ac..0000000 --- a/srv/openbsd/etc/acme-client.conf +++ /dev/null @@ -1,7 +0,0 @@ - -domain urlo.li { - alernative names { www.urlo.li } - domain key "/etc/ssl/private/urlo.li.key" - domain full chain certificate "/etc/ssl/urlo.li.fullchain.pem" - sign with letsencrypt -} diff --git a/srv/openbsd/etc/httpd-clear.conf b/srv/openbsd/etc/httpd-clear.conf deleted file mode 100644 index 1cb25a4..0000000 --- a/srv/openbsd/etc/httpd-clear.conf +++ /dev/null @@ -1,24 +0,0 @@ - -server "urlo.li" { - listen on $ext_addr port 80 - location "/.well-known/acme-challenge/*" { - root "/acme" - request strip 2 - } - block return 301 "https://$SERVER_NAME$REQUEST_URI" -} -server "urlo.li" { - listen on $ext_addr tls port 443 - tls { - certificate "/etc/letsencrypt/live/urlo.li/fullchain.pem" - key "/etc/letsencrypt/live/urlo.li/privkey.pem" - } - connection { max requests 500, timeout 3600 } - location "/*" { - fastcgi socket tcp 127.0.0.1 9910 - } - location "/.well-known/acme-challenge/*" { - root "/acme" - request strip 2 - } -} diff --git a/srv/openbsd/etc/httpd-dark.conf b/srv/openbsd/etc/httpd-dark.conf deleted file mode 100644 index fa16d79..0000000 --- a/srv/openbsd/etc/httpd-dark.conf +++ /dev/null @@ -1,8 +0,0 @@ - -server "urlo.li" { - listen on $ext_addr port 80 - connection { max requests 500, timeout 3600 } - location "/*" { - fastcgi socket tcp 127.0.0.1 9910 - } -} diff --git a/srv/openbsd/etc/rc.d/urloli b/srv/openbsd/etc/rc.d/urloli deleted file mode 100644 index 8d27f88..0000000 --- a/srv/openbsd/etc/rc.d/urloli +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/ksh -# -# $OpenBSD: urloli.rc,v 1.4 2018/01/11 19:27:11 rpe Exp $ - -name="urloli" -daemon="/usr/local/bin/${name}" - -. /etc/rc.d/rc.subr - -rc_cmd $1 diff --git a/urloli.1 b/urloli.1 new file mode 100644 index 0000000..c08169b --- /dev/null +++ b/urloli.1 @@ -0,0 +1,30 @@ +.TH URLロリ 1 urloli\-VERSION +.SH ソフト名 +URLロリ - クッソ小さいURL短縮作成ソフトだわ〜♡ +.SH 概要 +.B urloli +[\fI\,オプション\/\fR] [\fI\,ポート番号\/\fR] +.SH 説明 +.PP +URLロリはクッソ小さいURL短縮作成ソフトです。 +.TP +\fB\-v\fR +バージョンを表示 +.TP +\fB\-s [ポート番号]\fR +ポート番号でサーバーを開始(デフォルト=9910) +.TP +\fB\-h\fR +ヘルプを表示 +.SH 会話 +.PP +XMPP: xmpp:urloli@chat.xmpp.076.ne.jp?join +.br +IRC: irc.076.ne.jp/6697 #urloli +.br +メーリングリスト: (開発中) +.SH バグ報告 +.PP +バグは下記のURLまでご報告下さい: +.br +https://gitler.moe/suwako/urloli/issues diff --git a/view/footer.html b/view/footer.html index 8721c05..56a13a4 100644 --- a/view/footer.html +++ b/view/footer.html @@ -1,7 +1,7 @@ {{define "footer"}}