view go/server.go @ 16:b651aa41b9d4 default tip

hhsinfo method (server)
author pyon@macmini
date Mon, 15 Jul 2019 07:03:05 +0900
parents c262e17de9b1
children
line wrap: on
line source

/*
 server.go  : server-program.
 Version    : 1.6
 Last Change: 2019-07-15 Mon 06:34:42.

 install to: server_root/

 server_root/server
            + db/
            + release/
            + images/
*/
package main

import(
	"bufio"
	"crypto/aes"
	"crypto/cipher"
    "encoding/hex"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
    "net/http"
	"os"
    "path/filepath"
	"strings"
	"time"
)

type hhs struct {
    no string
	name string
    kana string
	addr string
	birth string
	sex string
}

func (h *hhs) String() string {
    s := []string{h.no, h.name, h.kana, h.addr, h.birth, h.sex}
    return strings.Join(s, ",")
}

func (h *hhs) SString() string {
    s := []string{h.no, h.name, h.kana}
    return strings.Join(s, ",")
}

var (
	version string
	server string
	port string
	server_root string
	logfile string
	not_ac bool
	wlfile string

	hdbfile string
	key string
    hhash map[string]hhs
)

func init() {
	version = "1.6"	// 1.6: hhs info version
	port = ":3910"
    server_root = filepath.Dir(os.Args[0])
	logfile = filepath.Join(server_root, "rsearcher.log")
	wlfile = filepath.Join(server_root, "rsearcher.whitelist")

	hdbfile = filepath.Join(server_root, "db", "hhs.db")
	key = "1234567890abcdef1234567890abcdef" // len = 32
    read_hhsdb()
}

func main() {

    flag.BoolVar(&not_ac, "d", false, "no access control ( for debug )")
	flag.Parse()

	// setting IP-Address & Port
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		log.Fatal(err)
	}
	for _, a := range addrs {
		if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if strings.HasPrefix(ipnet.IP.String(), "169.254") {
				continue
			}
			if ipnet.IP.To4() != nil {
				server = ipnet.IP.String() + port
			}
		}
	}

	// start Web-server
	fmt.Println("server start [", server, "] ( program version", version, ")")
	http.HandleFunc("/",        handler)
	http.HandleFunc("/upload/", upload_handler)
	http.HandleFunc("/mngdb/",  mngdb_handler)
	http.HandleFunc("/hinfo/",  hinfo_handler)
	http.HandleFunc("/hlist/",  hlist_handler)
	log.Fatal(http.ListenAndServe(server, nil))
}

/* 各種ハンドラ */
// 静的ファイル
func handler(w http.ResponseWriter, r *http.Request) {
	if !not_ac && !is_valid_host(r.RemoteAddr) {
		http.NotFound(w, r)
		return
	}

	file := filepath.Join(server_root, filepath.FromSlash(r.URL.Path))
	//img := r.URL.Query().Get("q")

	fmt.Println("[access]", r.RemoteAddr, "|", time.Now().Format("2006-01-02 15:04"), "|", file)
	//fmt.Println("--", img , "--")
	write_log("[access] " + r.RemoteAddr + " " + file)

	f, err := os.Open(file)
	if err != nil {
		http.NotFound(w, r)
		return
	}
	defer f.Close()

	fi, _ := f.Stat()

	w.Header().Set("Content-Type",   "rsearcher/octet-stream")
	w.Header().Set("Content-Length", fmt.Sprintf("%d", fi.Size()))
	io.Copy(w, f)
}

// アップローダ
func upload_handler(w http.ResponseWriter, r *http.Request) {
	if !not_ac && !is_valid_host(r.RemoteAddr) {
		http.NotFound(w, r)
		return
	}

	fmt.Println("[access]", r.RemoteAddr, "|", time.Now().Format("2006-01-02 15:04"), "|", "/upload")
	now := time.Now().Format("20060102_150405")
	file := filepath.Join(server_root, "upload", now)
	f, err := os.Create(file)
	if err != nil {
		http.NotFound(w, r)
		return
	}
	n, err := io.Copy(f, r.Body)
	if err != nil {
		http.NotFound(w, r)
		return
	}
	f.Close()
	w.Write([]byte(fmt.Sprintf("%d bytes are recieved.\n", n)))
}

// データベース保存
func mngdb_handler(w http.ResponseWriter, r *http.Request) {
	if !not_ac && !is_valid_host(r.RemoteAddr) {
		http.NotFound(w, r)
		return
	}

	fmt.Println("[access]", r.RemoteAddr, "|", time.Now().Format("2006-01-02 15:04" ), "|", "/mngdb")
	write_log("[access] " + r.RemoteAddr + "manage-db")

	db := r.URL.Path[len("/mngdb/"):]

	file := filepath.Join(server_root, "db", db)

	f, err := os.Create(file)
	if err != nil {
		http.NotFound(w, r)
		return
	}
	_, err = io.Copy(f, r.Body)
	if err != nil {
		http.NotFound(w, r)
		return
	}
	f.Close()
}

// 被保険者情報取得
func hinfo_handler(w http.ResponseWriter, r *http.Request) {
	if !not_ac && !is_valid_host(r.RemoteAddr) {
		http.NotFound(w, r)
		return
	}
	fmt.Println("[access]", r.RemoteAddr, "|", time.Now().Format("2006-01-02 15:04" ), "|", "/hinfo")
	write_log("[access] " + r.RemoteAddr + "hinfo")

	h := r.URL.Path[len("/hinfo/"):]
    hhs := hhash[h]

	w.Write([]byte(hhs.String()))
}

func hlist_handler(w http.ResponseWriter, r *http.Request) {
	if !not_ac && !is_valid_host(r.RemoteAddr) {
		http.NotFound(w, r)
		return
	}
	fmt.Println("[access]", r.RemoteAddr, "|", time.Now().Format("2006-01-02 15:04" ), "|", "/hlist")
	write_log("[access] " + r.RemoteAddr + "list")

	hlist := r.URL.Path[len("/hlist/"):]
    var s string
	for _, h := range strings.Split(hlist, ":") {
        hhs := hhash[h]
        s += hhs.SString() + "\n"
    }

	w.Write([]byte(s))
}

// ホワイトリスト判定
func is_valid_host(host string) bool {
	f, _ := os.Open(wlfile)
	defer f.Close()
	input := bufio.NewScanner(f)
	for input.Scan() {
		if input.Text() == host {
			return true
		}
	}
	return false
}

// 被保険者DB読み込み
func read_hhsdb() {
    hhash = make(map[string]hhs)
	pt := decrypto(key, hdbfile)
	for _, line := range strings.Split(pt, "\n") {
        c := strings.Split(line, ",")
        if len(c) == 6 {
            hhash[c[0]] = hhs{no: c[0], name: c[1], kana: c[2], addr: c[3], birth: c[4], sex: c[5]}
        }
    }
}

// 復号化
func decrypto( key, file string ) string {
	k, _ := hex.DecodeString(key)
	block, err := aes.NewCipher(k)
	if err != nil {
		panic( err )
	}
	ciphertext, err := ioutil.ReadFile(file)
	if err != nil {
		log.Fatal(err)
	}

	iv := ciphertext[ :aes.BlockSize ]
	plaintext := make([]byte, len(ciphertext[ aes.BlockSize: ]))
	stream := cipher.NewCTR(block, iv)
	stream.XORKeyStream(plaintext, ciphertext[ aes.BlockSize: ])

	return string(plaintext)
}

// ログ
func write_log(msg string) {
	f, err := os.OpenFile(logfile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	logger := log.New(f, "", log.LstdFlags)
	logger.Println(msg)
}