バージョン2.0.0に

このコミットが含まれているのは:
守矢諏訪子 2023-05-10 15:29:26 +09:00
コミット 3f7614956a
22個のファイルの変更670行の追加520行の削除

15
CHANGELOG.md ノーマルファイル
ファイルの表示

@ -0,0 +1,15 @@
# 2.0.0
* Makefile化
* ソースコードは複数ファイルに分ける
* コマンドラインからURL短熟
* バージョンの表示
* ヘルプの表示
* manページ
* ポート番号はご自由に決める様にした(デフォルトは9910)
# 1.0.0
* PHPからGoに交換しました
* 今度からバージョンを付きます
# それ以前
* 色々

45
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

267
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 <urloli> { IPADDRESS }
http protocol "httpproxy" {
pass request quick header "Host" value "DOMAIN" forward to <urloli>
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;
}
```

16
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
}

90
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
}

ファイルの表示

@ -1,4 +1,4 @@
{
"domain": "https://urlo.li",
"webpath": "/www/active/urlo.li"
"webpath": "/var/www/htdocs/urloli"
}

ファイルの表示

@ -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

269
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> コマンドラインで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
}
}

39
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
}

130
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)
}

ファイルの表示

@ -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"

ファイルの表示

@ -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

ファイルの表示

@ -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;
}

ファイルの表示

@ -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;
}

ファイルの表示

@ -1,3 +0,0 @@
#!/bin/sh -e
exec 2>&1
exec chpst urloli

ファイルの表示

@ -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

ファイルの表示

@ -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
}

ファイルの表示

@ -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
}
}

ファイルの表示

@ -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
}
}

ファイルの表示

@ -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

30
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

ファイルの表示

@ -1,7 +1,7 @@
{{define "footer"}}
</div>
<p class="footer">
<a href="https://gitler.moe/suwako/urloli.go"><img src="/static/git.png" alt="Git" /></a> |
<a href="https://gitler.moe/suwako/urloli"><img src="/static/git.png" alt="Git" /></a> |
<a href="https://076.moe/"></a>
</p>
</body>