0
|
1 /*
|
|
2 server.go : server-program.
|
16
|
3 Version : 1.6
|
|
4 Last Change: 2019-07-15 Mon 06:34:42.
|
0
|
5
|
|
6 install to: server_root/
|
|
7
|
|
8 server_root/server
|
|
9 + db/
|
|
10 + release/
|
|
11 + images/
|
|
12 */
|
|
13 package main
|
|
14
|
|
15 import(
|
14
|
16 "bufio"
|
16
|
17 "crypto/aes"
|
|
18 "crypto/cipher"
|
|
19 "encoding/hex"
|
14
|
20 "flag"
|
0
|
21 "fmt"
|
|
22 "io"
|
16
|
23 "io/ioutil"
|
0
|
24 "log"
|
|
25 "net"
|
|
26 "net/http"
|
|
27 "os"
|
14
|
28 "path/filepath"
|
15
|
29 "strings"
|
3
|
30 "time"
|
0
|
31 )
|
|
32
|
16
|
33 type hhs struct {
|
|
34 no string
|
|
35 name string
|
|
36 kana string
|
|
37 addr string
|
|
38 birth string
|
|
39 sex string
|
|
40 }
|
|
41
|
|
42 func (h *hhs) String() string {
|
|
43 s := []string{h.no, h.name, h.kana, h.addr, h.birth, h.sex}
|
|
44 return strings.Join(s, ",")
|
|
45 }
|
|
46
|
|
47 func (h *hhs) SString() string {
|
|
48 s := []string{h.no, h.name, h.kana}
|
|
49 return strings.Join(s, ",")
|
|
50 }
|
|
51
|
8
|
52 var (
|
|
53 version string
|
|
54 server string
|
16
|
55 port string
|
8
|
56 server_root string
|
|
57 logfile string
|
14
|
58 not_ac bool
|
|
59 wlfile string
|
16
|
60
|
|
61 hdbfile string
|
|
62 key string
|
|
63 hhash map[string]hhs
|
8
|
64 )
|
3
|
65
|
|
66 func init() {
|
16
|
67 version = "1.6" // 1.6: hhs info version
|
3
|
68 port = ":3910"
|
15
|
69 server_root = filepath.Dir(os.Args[0])
|
|
70 logfile = filepath.Join(server_root, "rsearcher.log")
|
16
|
71 wlfile = filepath.Join(server_root, "rsearcher.whitelist")
|
|
72
|
|
73 hdbfile = filepath.Join(server_root, "db", "hhs.db")
|
|
74 key = "1234567890abcdef1234567890abcdef" // len = 32
|
|
75 read_hhsdb()
|
3
|
76 }
|
|
77
|
0
|
78 func main() {
|
|
79
|
15
|
80 flag.BoolVar(¬_ac, "d", false, "no access control ( for debug )")
|
14
|
81 flag.Parse()
|
|
82
|
3
|
83 // setting IP-Address & Port
|
0
|
84 addrs, err := net.InterfaceAddrs()
|
|
85 if err != nil {
|
15
|
86 log.Fatal(err)
|
0
|
87 }
|
|
88 for _, a := range addrs {
|
15
|
89 if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
|
90 if strings.HasPrefix(ipnet.IP.String(), "169.254") {
|
|
91 continue
|
|
92 }
|
0
|
93 if ipnet.IP.To4() != nil {
|
|
94 server = ipnet.IP.String() + port
|
|
95 }
|
|
96 }
|
|
97 }
|
|
98
|
3
|
99 // start Web-server
|
15
|
100 fmt.Println("server start [", server, "] ( program version", version, ")")
|
16
|
101 http.HandleFunc("/", handler)
|
15
|
102 http.HandleFunc("/upload/", upload_handler)
|
16
|
103 http.HandleFunc("/mngdb/", mngdb_handler)
|
|
104 http.HandleFunc("/hinfo/", hinfo_handler)
|
|
105 http.HandleFunc("/hlist/", hlist_handler)
|
15
|
106 log.Fatal(http.ListenAndServe(server, nil))
|
0
|
107 }
|
|
108
|
16
|
109 /* 各種ハンドラ */
|
|
110 // 静的ファイル
|
15
|
111 func handler(w http.ResponseWriter, r *http.Request) {
|
|
112 if !not_ac && !is_valid_host(r.RemoteAddr) {
|
|
113 http.NotFound(w, r)
|
14
|
114 return
|
|
115 }
|
|
116
|
15
|
117 file := filepath.Join(server_root, filepath.FromSlash(r.URL.Path))
|
|
118 //img := r.URL.Query().Get("q")
|
8
|
119
|
15
|
120 fmt.Println("[access]", r.RemoteAddr, "|", time.Now().Format("2006-01-02 15:04"), "|", file)
|
|
121 //fmt.Println("--", img , "--")
|
|
122 write_log("[access] " + r.RemoteAddr + " " + file)
|
8
|
123
|
15
|
124 f, err := os.Open(file)
|
3
|
125 if err != nil {
|
15
|
126 http.NotFound(w, r)
|
3
|
127 return
|
|
128 }
|
|
129 defer f.Close()
|
8
|
130
|
|
131 fi, _ := f.Stat()
|
|
132
|
15
|
133 w.Header().Set("Content-Type", "rsearcher/octet-stream")
|
|
134 w.Header().Set("Content-Length", fmt.Sprintf("%d", fi.Size()))
|
|
135 io.Copy(w, f)
|
3
|
136 }
|
4
|
137
|
16
|
138 // アップローダ
|
15
|
139 func upload_handler(w http.ResponseWriter, r *http.Request) {
|
|
140 if !not_ac && !is_valid_host(r.RemoteAddr) {
|
|
141 http.NotFound(w, r)
|
14
|
142 return
|
|
143 }
|
|
144
|
15
|
145 fmt.Println("[access]", r.RemoteAddr, "|", time.Now().Format("2006-01-02 15:04"), "|", "/upload")
|
|
146 now := time.Now().Format("20060102_150405")
|
|
147 file := filepath.Join(server_root, "upload", now)
|
|
148 f, err := os.Create(file)
|
4
|
149 if err != nil {
|
15
|
150 http.NotFound(w, r)
|
4
|
151 return
|
|
152 }
|
15
|
153 n, err := io.Copy(f, r.Body)
|
4
|
154 if err != nil {
|
15
|
155 http.NotFound(w, r)
|
4
|
156 return
|
|
157 }
|
|
158 f.Close()
|
15
|
159 w.Write([]byte(fmt.Sprintf("%d bytes are recieved.\n", n)))
|
4
|
160 }
|
|
161
|
16
|
162 // データベース保存
|
15
|
163 func mngdb_handler(w http.ResponseWriter, r *http.Request) {
|
|
164 if !not_ac && !is_valid_host(r.RemoteAddr) {
|
|
165 http.NotFound(w, r)
|
14
|
166 return
|
|
167 }
|
|
168
|
15
|
169 fmt.Println("[access]", r.RemoteAddr, "|", time.Now().Format("2006-01-02 15:04" ), "|", "/mngdb")
|
|
170 write_log("[access] " + r.RemoteAddr + "manage-db")
|
16
|
171
|
15
|
172 db := r.URL.Path[len("/mngdb/"):]
|
12
|
173
|
15
|
174 file := filepath.Join(server_root, "db", db)
|
12
|
175
|
15
|
176 f, err := os.Create(file)
|
12
|
177 if err != nil {
|
15
|
178 http.NotFound(w, r)
|
12
|
179 return
|
|
180 }
|
15
|
181 _, err = io.Copy(f, r.Body)
|
12
|
182 if err != nil {
|
15
|
183 http.NotFound(w, r)
|
12
|
184 return
|
|
185 }
|
|
186 f.Close()
|
|
187 }
|
|
188
|
16
|
189 // 被保険者情報取得
|
|
190 func hinfo_handler(w http.ResponseWriter, r *http.Request) {
|
|
191 if !not_ac && !is_valid_host(r.RemoteAddr) {
|
|
192 http.NotFound(w, r)
|
|
193 return
|
|
194 }
|
|
195 fmt.Println("[access]", r.RemoteAddr, "|", time.Now().Format("2006-01-02 15:04" ), "|", "/hinfo")
|
|
196 write_log("[access] " + r.RemoteAddr + "hinfo")
|
|
197
|
|
198 h := r.URL.Path[len("/hinfo/"):]
|
|
199 hhs := hhash[h]
|
|
200
|
|
201 w.Write([]byte(hhs.String()))
|
|
202 }
|
|
203
|
|
204 func hlist_handler(w http.ResponseWriter, r *http.Request) {
|
|
205 if !not_ac && !is_valid_host(r.RemoteAddr) {
|
|
206 http.NotFound(w, r)
|
|
207 return
|
|
208 }
|
|
209 fmt.Println("[access]", r.RemoteAddr, "|", time.Now().Format("2006-01-02 15:04" ), "|", "/hlist")
|
|
210 write_log("[access] " + r.RemoteAddr + "list")
|
|
211
|
|
212 hlist := r.URL.Path[len("/hlist/"):]
|
|
213 var s string
|
|
214 for _, h := range strings.Split(hlist, ":") {
|
|
215 hhs := hhash[h]
|
|
216 s += hhs.SString() + "\n"
|
|
217 }
|
|
218
|
|
219 w.Write([]byte(s))
|
|
220 }
|
|
221
|
|
222 // ホワイトリスト判定
|
15
|
223 func is_valid_host(host string) bool {
|
|
224 f, _ := os.Open(wlfile)
|
14
|
225 defer f.Close()
|
15
|
226 input := bufio.NewScanner(f)
|
14
|
227 for input.Scan() {
|
|
228 if input.Text() == host {
|
|
229 return true
|
|
230 }
|
|
231 }
|
|
232 return false
|
|
233 }
|
|
234
|
16
|
235 // 被保険者DB読み込み
|
|
236 func read_hhsdb() {
|
|
237 hhash = make(map[string]hhs)
|
|
238 pt := decrypto(key, hdbfile)
|
|
239 for _, line := range strings.Split(pt, "\n") {
|
|
240 c := strings.Split(line, ",")
|
|
241 if len(c) == 6 {
|
|
242 hhash[c[0]] = hhs{no: c[0], name: c[1], kana: c[2], addr: c[3], birth: c[4], sex: c[5]}
|
|
243 }
|
|
244 }
|
|
245 }
|
|
246
|
|
247 // 復号化
|
|
248 func decrypto( key, file string ) string {
|
|
249 k, _ := hex.DecodeString(key)
|
|
250 block, err := aes.NewCipher(k)
|
|
251 if err != nil {
|
|
252 panic( err )
|
|
253 }
|
|
254 ciphertext, err := ioutil.ReadFile(file)
|
|
255 if err != nil {
|
|
256 log.Fatal(err)
|
|
257 }
|
|
258
|
|
259 iv := ciphertext[ :aes.BlockSize ]
|
|
260 plaintext := make([]byte, len(ciphertext[ aes.BlockSize: ]))
|
|
261 stream := cipher.NewCTR(block, iv)
|
|
262 stream.XORKeyStream(plaintext, ciphertext[ aes.BlockSize: ])
|
|
263
|
|
264 return string(plaintext)
|
|
265 }
|
|
266
|
|
267 // ログ
|
15
|
268 func write_log(msg string) {
|
|
269 f, err := os.OpenFile(logfile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
8
|
270 if err != nil {
|
15
|
271 log.Fatal(err)
|
8
|
272 }
|
|
273 defer f.Close()
|
|
274
|
15
|
275 logger := log.New(f, "", log.LstdFlags)
|
|
276 logger.Println(msg)
|
8
|
277 }
|
|
278
|