1fb726d48Sopenharmony_ci// Copyright (C) 2022 Huawei Device Co., Ltd.
2fb726d48Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
3fb726d48Sopenharmony_ci// you may not use this file except in compliance with the License.
4fb726d48Sopenharmony_ci// You may obtain a copy of the License at
5fb726d48Sopenharmony_ci//
6fb726d48Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
7fb726d48Sopenharmony_ci//
8fb726d48Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
9fb726d48Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
10fb726d48Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11fb726d48Sopenharmony_ci// See the License for the specific language governing permissions and
12fb726d48Sopenharmony_ci// limitations under the License.
13fb726d48Sopenharmony_ci
14fb726d48Sopenharmony_cipackage main
15fb726d48Sopenharmony_ci
16fb726d48Sopenharmony_ci//遇到报错请在当前目录下执行这个命令: go mod download golang.org/x/text
17fb726d48Sopenharmony_ciimport (
18fb726d48Sopenharmony_ci	"bufio"
19fb726d48Sopenharmony_ci	"bytes"
20fb726d48Sopenharmony_ci	"crypto"
21fb726d48Sopenharmony_ci	"crypto/rand"
22fb726d48Sopenharmony_ci	"crypto/rsa"
23fb726d48Sopenharmony_ci	"crypto/sha512"
24fb726d48Sopenharmony_ci	"crypto/tls"
25fb726d48Sopenharmony_ci	"crypto/x509"
26fb726d48Sopenharmony_ci	"crypto/x509/pkix"
27fb726d48Sopenharmony_ci	"encoding/base64"
28fb726d48Sopenharmony_ci	"encoding/json"
29fb726d48Sopenharmony_ci	"encoding/pem"
30fb726d48Sopenharmony_ci	"flag"
31fb726d48Sopenharmony_ci	"fmt"
32fb726d48Sopenharmony_ci	"io"
33fb726d48Sopenharmony_ci	"io/fs"
34fb726d48Sopenharmony_ci	"log"
35fb726d48Sopenharmony_ci	"math/big"
36fb726d48Sopenharmony_ci	"mime"
37fb726d48Sopenharmony_ci	"net"
38fb726d48Sopenharmony_ci	"net/http"
39fb726d48Sopenharmony_ci	"net/http/cookiejar"
40fb726d48Sopenharmony_ci	"os"
41fb726d48Sopenharmony_ci	"os/exec"
42fb726d48Sopenharmony_ci	"path"
43fb726d48Sopenharmony_ci	"path/filepath"
44fb726d48Sopenharmony_ci	"regexp"
45fb726d48Sopenharmony_ci	"runtime"
46fb726d48Sopenharmony_ci	"strconv"
47fb726d48Sopenharmony_ci	"strings"
48fb726d48Sopenharmony_ci	"sync"
49fb726d48Sopenharmony_ci	"time"
50fb726d48Sopenharmony_ci)
51fb726d48Sopenharmony_ci
52fb726d48Sopenharmony_ciconst HttpPort = 9000
53fb726d48Sopenharmony_ci
54fb726d48Sopenharmony_civar exPath string
55fb726d48Sopenharmony_civar serveInfo string
56fb726d48Sopenharmony_civar msgPublishData MsgPublishData
57fb726d48Sopenharmony_civar hdcPublicKey string
58fb726d48Sopenharmony_civar hdcPrivateKey *rsa.PrivateKey
59fb726d48Sopenharmony_ci
60fb726d48Sopenharmony_ci// CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
61fb726d48Sopenharmony_ci// CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
62fb726d48Sopenharmony_cifunc cors(fs http.Handler, version string) http.HandlerFunc {
63fb726d48Sopenharmony_ci	return func(w http.ResponseWriter, r *http.Request) {
64fb726d48Sopenharmony_ci		// return if you do not want the FileServer handle a specific request
65fb726d48Sopenharmony_ci		r.Header.Add("Cross-Origin-Opener-Policy", "same-origin")
66fb726d48Sopenharmony_ci		r.Header.Add("Cross-Origin-Embedder-Policy", "require-corp")
67fb726d48Sopenharmony_ci		w.Header().Add("Cross-Origin-Opener-Policy", "same-origin")
68fb726d48Sopenharmony_ci		w.Header().Add("Cross-Origin-Embedder-Policy", "require-corp")
69fb726d48Sopenharmony_ci		w.Header().Set("Access-Control-Allow-Origin", "*")
70fb726d48Sopenharmony_ci		w.Header().Set("Access-Control-Allow-Credentials", "true")
71fb726d48Sopenharmony_ci		w.Header().Set("Access-Control-Allow-Headers", "x-requested-with, authorization, blade-auth") //*
72fb726d48Sopenharmony_ci		w.Header().Set("Access-Control-Allow-Methods", "*")                                           //*
73fb726d48Sopenharmony_ci		w.Header().Set("Access-Control-Max-Age", "3600")
74fb726d48Sopenharmony_ci		w.Header().Set("data-version", version)
75fb726d48Sopenharmony_ci		w.Header().Set("Cache-Control", "no-cache")
76fb726d48Sopenharmony_ci		w.Header().Set("Pragma", "no-cache")
77fb726d48Sopenharmony_ci		fs.ServeHTTP(w, r)
78fb726d48Sopenharmony_ci	}
79fb726d48Sopenharmony_ci}
80fb726d48Sopenharmony_ci
81fb726d48Sopenharmony_cifunc exist(path string) bool {
82fb726d48Sopenharmony_ci	_, err := os.Stat(path)
83fb726d48Sopenharmony_ci	if err != nil {
84fb726d48Sopenharmony_ci		if os.IsExist(err) {
85fb726d48Sopenharmony_ci			return true
86fb726d48Sopenharmony_ci		}
87fb726d48Sopenharmony_ci		return false
88fb726d48Sopenharmony_ci	}
89fb726d48Sopenharmony_ci	return true
90fb726d48Sopenharmony_ci}
91fb726d48Sopenharmony_ci
92fb726d48Sopenharmony_cifunc genSSL() {
93fb726d48Sopenharmony_ci	if exist("cert/keyFile.key") || exist("cert/certFile.pem") {
94fb726d48Sopenharmony_ci		fmt.Println("keyFile.key exists")
95fb726d48Sopenharmony_ci		return
96fb726d48Sopenharmony_ci	}
97fb726d48Sopenharmony_ci	max := new(big.Int).Lsh(big.NewInt(1), 128)
98fb726d48Sopenharmony_ci	serialNumber, _ := rand.Int(rand.Reader, max)
99fb726d48Sopenharmony_ci	subject := pkix.Name{
100fb726d48Sopenharmony_ci		Organization:       []string{"www.smartperf.com"},
101fb726d48Sopenharmony_ci		OrganizationalUnit: []string{"ITs"},
102fb726d48Sopenharmony_ci		CommonName:         "www.smartperf.com",
103fb726d48Sopenharmony_ci	}
104fb726d48Sopenharmony_ci	certificate509 := x509.Certificate{
105fb726d48Sopenharmony_ci		SerialNumber: serialNumber,
106fb726d48Sopenharmony_ci		Subject:      subject,
107fb726d48Sopenharmony_ci		NotBefore:    time.Now(),
108fb726d48Sopenharmony_ci		NotAfter:     time.Now().AddDate(10, 0, 0),
109fb726d48Sopenharmony_ci		KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
110fb726d48Sopenharmony_ci		ExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
111fb726d48Sopenharmony_ci		IPAddresses:  []net.IP{net.ParseIP("127.0.0.1")},
112fb726d48Sopenharmony_ci	}
113fb726d48Sopenharmony_ci	chekDir("cert")
114fb726d48Sopenharmony_ci	pk, _ := rsa.GenerateKey(rand.Reader, 1024)
115fb726d48Sopenharmony_ci	derBytes, _ := x509.CreateCertificate(rand.Reader, &certificate509, &certificate509, &pk.PublicKey, pk)
116fb726d48Sopenharmony_ci	certOut, _ := os.Create("cert/certFile.pem")
117fb726d48Sopenharmony_ci	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
118fb726d48Sopenharmony_ci	certOut.Close()
119fb726d48Sopenharmony_ci	keyOut, _ := os.Create("cert/keyFile.key")
120fb726d48Sopenharmony_ci	pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(pk)})
121fb726d48Sopenharmony_ci	keyOut.Close()
122fb726d48Sopenharmony_ci}
123fb726d48Sopenharmony_ci
124fb726d48Sopenharmony_cifunc genRsa() {
125fb726d48Sopenharmony_ci	// generate hdc private key
126fb726d48Sopenharmony_ci	privateKey, err := rsa.GenerateKey(rand.Reader, 3072)
127fb726d48Sopenharmony_ci	if err != nil {
128fb726d48Sopenharmony_ci		fmt.Println("Generate hdc rsa private key failed")
129fb726d48Sopenharmony_ci		return
130fb726d48Sopenharmony_ci	}
131fb726d48Sopenharmony_ci	hdcPrivateKey = privateKey
132fb726d48Sopenharmony_ci
133fb726d48Sopenharmony_ci	// generate hdc public key
134fb726d48Sopenharmony_ci	publicKey := &privateKey.PublicKey
135fb726d48Sopenharmony_ci	pkixPublicKey, err := x509.MarshalPKIXPublicKey(publicKey)
136fb726d48Sopenharmony_ci	if err != nil {
137fb726d48Sopenharmony_ci		fmt.Println(err)
138fb726d48Sopenharmony_ci		return
139fb726d48Sopenharmony_ci	}
140fb726d48Sopenharmony_ci	publicKeyBlock := &pem.Block{
141fb726d48Sopenharmony_ci		Type: "PUBLIC KEY",
142fb726d48Sopenharmony_ci
143fb726d48Sopenharmony_ci		Bytes: pkixPublicKey,
144fb726d48Sopenharmony_ci	}
145fb726d48Sopenharmony_ci	hdcPublicKey = string(pem.EncodeToMemory(publicKeyBlock))
146fb726d48Sopenharmony_ci}
147fb726d48Sopenharmony_ci
148fb726d48Sopenharmony_cifunc main() {
149fb726d48Sopenharmony_ci	port := HttpPort
150fb726d48Sopenharmony_ci	isOpen := 1
151fb726d48Sopenharmony_ci	flag.IntVar(&port, "p", HttpPort, "The port number used")
152fb726d48Sopenharmony_ci	flag.IntVar(&isOpen, "o", 1, "Whether to immediately open the website in your browser; 1 is true; 0 is false")
153fb726d48Sopenharmony_ci	flag.Parse()
154fb726d48Sopenharmony_ci	if isOpen < 0 || isOpen > 1 {
155fb726d48Sopenharmony_ci		fmt.Println("Error: -o must be 0 or 1")
156fb726d48Sopenharmony_ci		return
157fb726d48Sopenharmony_ci	}
158fb726d48Sopenharmony_ci	checkPort(port)
159fb726d48Sopenharmony_ci	genSSL()
160fb726d48Sopenharmony_ci	genRsa()
161fb726d48Sopenharmony_ci	exPath = getCurrentAbPath()
162fb726d48Sopenharmony_ci	fmt.Println(exPath)
163fb726d48Sopenharmony_ci	go func() {
164fb726d48Sopenharmony_ci		version := ""
165fb726d48Sopenharmony_ci		readVersion, versionErr := os.ReadFile(exPath + "/version.txt")
166fb726d48Sopenharmony_ci		if versionErr != nil {
167fb726d48Sopenharmony_ci			version = ""
168fb726d48Sopenharmony_ci		} else {
169fb726d48Sopenharmony_ci			version = string(readVersion)
170fb726d48Sopenharmony_ci		}
171fb726d48Sopenharmony_ci		readReqServerConfig()
172fb726d48Sopenharmony_ci		mux := http.NewServeMux()
173fb726d48Sopenharmony_ci		mime.TypeByExtension(".js")
174fb726d48Sopenharmony_ci		mime.AddExtensionType(".js", "application/javascript")
175fb726d48Sopenharmony_ci		log.Println(mime.TypeByExtension(".js"))
176fb726d48Sopenharmony_ci		mux.HandleFunc("/logger", consoleHandler)
177fb726d48Sopenharmony_ci		mux.Handle("/application/upload/", http.StripPrefix("/application/upload/", http.FileServer(http.Dir(filepath.FromSlash(exPath+"/upload")))))
178fb726d48Sopenharmony_ci		mux.HandleFunc("/application/download-file", downloadHandler)
179fb726d48Sopenharmony_ci		mux.HandleFunc("/application/serverInfo", serverInfo)
180fb726d48Sopenharmony_ci		mux.HandleFunc("/application/hdcPublicKey", getHdcPublicKey)
181fb726d48Sopenharmony_ci		mux.HandleFunc("/application/encryptHdcMsg", encryptHdcMsg)
182fb726d48Sopenharmony_ci		mux.HandleFunc("/application/signatureHdcMsg", signatureHdcMsg)
183fb726d48Sopenharmony_ci		mux.HandleFunc("/application/messagePublish", getMsgPublish)
184fb726d48Sopenharmony_ci		fs := http.FileServer(http.Dir(exPath + "/"))
185fb726d48Sopenharmony_ci		mux.Handle("/application/", http.StripPrefix("/application/", cors(fs, version)))
186fb726d48Sopenharmony_ci		go func() {
187fb726d48Sopenharmony_ci			ser := &http.Server{
188fb726d48Sopenharmony_ci				Addr:    fmt.Sprintf(":%d", port),
189fb726d48Sopenharmony_ci				Handler: mux,
190fb726d48Sopenharmony_ci			}
191fb726d48Sopenharmony_ci			log.Println(fmt.Sprintf("HTTPS[%d]服务启动", port))
192fb726d48Sopenharmony_ci			err := ser.ListenAndServeTLS("cert/certFile.pem", "cert/keyFile.key")
193fb726d48Sopenharmony_ci			CheckErr(err)
194fb726d48Sopenharmony_ci		}()
195fb726d48Sopenharmony_ci		go func() {
196fb726d48Sopenharmony_ci			ser := &http.Server{
197fb726d48Sopenharmony_ci				Addr:    fmt.Sprintf(":%d", port+1),
198fb726d48Sopenharmony_ci				Handler: mux,
199fb726d48Sopenharmony_ci			}
200fb726d48Sopenharmony_ci			log.Println(fmt.Sprintf("HTTP[%d]服务启动", port))
201fb726d48Sopenharmony_ci			err := ser.ListenAndServe()
202fb726d48Sopenharmony_ci			CheckErr(err)
203fb726d48Sopenharmony_ci		}()
204fb726d48Sopenharmony_ci		if isOpen == 1 {
205fb726d48Sopenharmony_ci			open(fmt.Sprintf("https://localhost:%d/application", port))
206fb726d48Sopenharmony_ci		}
207fb726d48Sopenharmony_ci	}()
208fb726d48Sopenharmony_ci	select {}
209fb726d48Sopenharmony_ci}
210fb726d48Sopenharmony_ci
211fb726d48Sopenharmony_cifunc getPidByPort(portNumber int) int {
212fb726d48Sopenharmony_ci	resPid := -1
213fb726d48Sopenharmony_ci	var out bytes.Buffer
214fb726d48Sopenharmony_ci	cmdRes := exec.Command("cmd", "/c", fmt.Sprintf("netstat -ano -p tcp | findstr %d", portNumber))
215fb726d48Sopenharmony_ci	cmdRes.Stdout = &out
216fb726d48Sopenharmony_ci	cmdRes.Run()
217fb726d48Sopenharmony_ci	cmdResStr := out.String()
218fb726d48Sopenharmony_ci	findStr := regexp.MustCompile(`\s\d+\s`).FindAllString(cmdResStr, -1)
219fb726d48Sopenharmony_ci	if len(findStr) > 0 {
220fb726d48Sopenharmony_ci		pid, err := strconv.Atoi(strings.TrimSpace(findStr[0]))
221fb726d48Sopenharmony_ci		if err != nil {
222fb726d48Sopenharmony_ci			resPid = -1
223fb726d48Sopenharmony_ci		} else {
224fb726d48Sopenharmony_ci			resPid = pid
225fb726d48Sopenharmony_ci		}
226fb726d48Sopenharmony_ci	}
227fb726d48Sopenharmony_ci	return resPid
228fb726d48Sopenharmony_ci}
229fb726d48Sopenharmony_ci
230fb726d48Sopenharmony_citype LoggerReq struct {
231fb726d48Sopenharmony_ci	FileName string `json:"fileName"`
232fb726d48Sopenharmony_ci	FileSize string `json:"fileSize"`
233fb726d48Sopenharmony_ci}
234fb726d48Sopenharmony_ci
235fb726d48Sopenharmony_cifunc consoleHandler(w http.ResponseWriter, r *http.Request) {
236fb726d48Sopenharmony_ci	chekDir(exPath + "/logger")
237fb726d48Sopenharmony_ci	var now = time.Now()
238fb726d48Sopenharmony_ci	var fileName = fmt.Sprintf("%d-%d-%d", now.Year(), now.Month(), now.Day())
239fb726d48Sopenharmony_ci	dst, err := os.OpenFile(exPath+"/logger/"+fileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND|os.O_SYNC, 0666)
240fb726d48Sopenharmony_ci	CheckErr(err)
241fb726d48Sopenharmony_ci	contentType := r.Header["Content-Type"]
242fb726d48Sopenharmony_ci	if len(contentType) > 0 {
243fb726d48Sopenharmony_ci		contentTypeName := contentType[0]
244fb726d48Sopenharmony_ci		if strings.HasPrefix(contentTypeName, "application/json") {
245fb726d48Sopenharmony_ci			decoder := json.NewDecoder(r.Body)
246fb726d48Sopenharmony_ci			var req LoggerReq
247fb726d48Sopenharmony_ci			decoder.Decode(&req)
248fb726d48Sopenharmony_ci			dst.WriteString(fmt.Sprintf("%s %s (%s M)\n", now.Format("2006-01-02 15:04:05"), req.FileName, req.FileSize))
249fb726d48Sopenharmony_ci			fmt.Fprintf(w, fmt.Sprintf("日志写入成功%s", exPath))
250fb726d48Sopenharmony_ci		}
251fb726d48Sopenharmony_ci	}
252fb726d48Sopenharmony_ci}
253fb726d48Sopenharmony_ci
254fb726d48Sopenharmony_cifunc serverInfo(w http.ResponseWriter, r *http.Request) {
255fb726d48Sopenharmony_ci	w.Header().Set("Access-Control-Allow-Origin", "*")
256fb726d48Sopenharmony_ci	w.Header().Set("request_info", serveInfo)
257fb726d48Sopenharmony_ci	w.WriteHeader(200)
258fb726d48Sopenharmony_ci}
259fb726d48Sopenharmony_ci
260fb726d48Sopenharmony_cifunc getHdcPublicKey(w http.ResponseWriter, r *http.Request) {
261fb726d48Sopenharmony_ci	w.Header().Set("Access-Control-Allow-Origin", "*")
262fb726d48Sopenharmony_ci	w.Header().Set("Content-Type", "text/json")
263fb726d48Sopenharmony_ci	resp(&w)(true, 0, "success", map[string]interface{}{
264fb726d48Sopenharmony_ci		"publicKey": hdcPublicKey,
265fb726d48Sopenharmony_ci	})
266fb726d48Sopenharmony_ci}
267fb726d48Sopenharmony_ci
268fb726d48Sopenharmony_cifunc encryptHdcMsg(w http.ResponseWriter, r *http.Request) {
269fb726d48Sopenharmony_ci	w.Header().Set("Access-Control-Allow-Origin", "*")
270fb726d48Sopenharmony_ci	w.Header().Set("Content-Type", "text/json")
271fb726d48Sopenharmony_ci	hdcMsg := r.URL.Query().Get("message")
272fb726d48Sopenharmony_ci	if len(hdcMsg) == 0 {
273fb726d48Sopenharmony_ci		resp(&w)(false, -1, "Invalid message", nil)
274fb726d48Sopenharmony_ci		return
275fb726d48Sopenharmony_ci	}
276fb726d48Sopenharmony_ci	signatures, err := rsa.SignPKCS1v15(nil, hdcPrivateKey, crypto.Hash(0), []byte(hdcMsg))
277fb726d48Sopenharmony_ci	if err != nil {
278fb726d48Sopenharmony_ci		resp(&w)(false, -1, "sign failed", nil)
279fb726d48Sopenharmony_ci	} else {
280fb726d48Sopenharmony_ci		resp(&w)(true, 0, "success", map[string]interface{}{
281fb726d48Sopenharmony_ci			"signatures": base64.StdEncoding.EncodeToString(signatures),
282fb726d48Sopenharmony_ci		})
283fb726d48Sopenharmony_ci	}
284fb726d48Sopenharmony_ci}
285fb726d48Sopenharmony_ci
286fb726d48Sopenharmony_cifunc signatureHdcMsg(w http.ResponseWriter, r *http.Request) {
287fb726d48Sopenharmony_ci	w.Header().Set("Access-Control-Allow-Origin", "*")
288fb726d48Sopenharmony_ci	w.Header().Set("Content-Type", "text/json")
289fb726d48Sopenharmony_ci	hdcMsg := r.URL.Query().Get("message")
290fb726d48Sopenharmony_ci	if len(hdcMsg) == 0 {
291fb726d48Sopenharmony_ci		resp(&w)(false, -1, "Invalid message", nil)
292fb726d48Sopenharmony_ci		return
293fb726d48Sopenharmony_ci	}
294fb726d48Sopenharmony_ci	hashed := sha512.Sum512([]byte(hdcMsg))
295fb726d48Sopenharmony_ci	signatures, err := rsa.SignPKCS1v15(nil, hdcPrivateKey, crypto.SHA512, hashed[:])
296fb726d48Sopenharmony_ci	if err != nil {
297fb726d48Sopenharmony_ci		resp(&w)(false, -1, "sign failed", nil)
298fb726d48Sopenharmony_ci	} else {
299fb726d48Sopenharmony_ci		resp(&w)(true, 0, "success", map[string]interface{}{
300fb726d48Sopenharmony_ci			"signatures": base64.StdEncoding.EncodeToString(signatures),
301fb726d48Sopenharmony_ci		})
302fb726d48Sopenharmony_ci	}
303fb726d48Sopenharmony_ci}
304fb726d48Sopenharmony_ci
305fb726d48Sopenharmony_cifunc parseMsgPublishFile() {
306fb726d48Sopenharmony_ci	defer func() {
307fb726d48Sopenharmony_ci		if r := recover(); r != nil {
308fb726d48Sopenharmony_ci			fmt.Printf("parseMsgPublishFile happen panic, content is %+v\n", r)
309fb726d48Sopenharmony_ci		}
310fb726d48Sopenharmony_ci	}()
311fb726d48Sopenharmony_ci	msgPublishData.Mux.Lock()
312fb726d48Sopenharmony_ci	defer msgPublishData.Mux.Unlock()
313fb726d48Sopenharmony_ci	exist, err := PathExists(msgPublishData.FilePath)
314fb726d48Sopenharmony_ci	if err != nil || !exist {
315fb726d48Sopenharmony_ci		return
316fb726d48Sopenharmony_ci	}
317fb726d48Sopenharmony_ci	buf, err := os.ReadFile(msgPublishData.FilePath)
318fb726d48Sopenharmony_ci	if err != nil {
319fb726d48Sopenharmony_ci		fmt.Println("read fail", err)
320fb726d48Sopenharmony_ci		return
321fb726d48Sopenharmony_ci	}
322fb726d48Sopenharmony_ci	msgPublishData.Msg = string(buf)
323fb726d48Sopenharmony_ci}
324fb726d48Sopenharmony_ci
325fb726d48Sopenharmony_cifunc getMsgPublish(w http.ResponseWriter, r *http.Request) {
326fb726d48Sopenharmony_ci	w.Header().Set("Access-Control-Allow-Origin", "*")
327fb726d48Sopenharmony_ci	w.Header().Set("Content-Type", "text/json")
328fb726d48Sopenharmony_ci	msgPublishData.Mux.RLock()
329fb726d48Sopenharmony_ci	data := msgPublishData.Msg
330fb726d48Sopenharmony_ci	msgPublishData.Mux.RUnlock()
331fb726d48Sopenharmony_ci	if len(data) == 0 {
332fb726d48Sopenharmony_ci		resp(&w)(false, -1, "msg failed", nil)
333fb726d48Sopenharmony_ci	} else {
334fb726d48Sopenharmony_ci		resp(&w)(true, 0, "success", map[string]interface{}{
335fb726d48Sopenharmony_ci			"data": data,
336fb726d48Sopenharmony_ci		})
337fb726d48Sopenharmony_ci	}
338fb726d48Sopenharmony_ci}
339fb726d48Sopenharmony_ci
340fb726d48Sopenharmony_citype ServerConfig struct {
341fb726d48Sopenharmony_ci	ServeInfo      string `json:"ServeInfo"`
342fb726d48Sopenharmony_ci	MsgPublishFile string `json:"MsgPublishFile"`
343fb726d48Sopenharmony_ci}
344fb726d48Sopenharmony_ci
345fb726d48Sopenharmony_citype MsgPublishData struct {
346fb726d48Sopenharmony_ci	FilePath string
347fb726d48Sopenharmony_ci	Msg      string
348fb726d48Sopenharmony_ci	Mux      sync.RWMutex
349fb726d48Sopenharmony_ci}
350fb726d48Sopenharmony_ci
351fb726d48Sopenharmony_cifunc loopUpdateMsgPublishData() {
352fb726d48Sopenharmony_ci	loopTime := 5 * time.Minute
353fb726d48Sopenharmony_ci	timer := time.NewTimer(5 * time.Second)
354fb726d48Sopenharmony_ci	for {
355fb726d48Sopenharmony_ci		select {
356fb726d48Sopenharmony_ci		case <-timer.C:
357fb726d48Sopenharmony_ci			parseMsgPublishFile()
358fb726d48Sopenharmony_ci		}
359fb726d48Sopenharmony_ci		timer.Reset(loopTime)
360fb726d48Sopenharmony_ci	}
361fb726d48Sopenharmony_ci}
362fb726d48Sopenharmony_ci
363fb726d48Sopenharmony_cifunc readReqServerConfig() {
364fb726d48Sopenharmony_ci	serverConfigBuffer, err := os.ReadFile(exPath + "/server-config.json")
365fb726d48Sopenharmony_ci	if err != nil {
366fb726d48Sopenharmony_ci		return
367fb726d48Sopenharmony_ci	}
368fb726d48Sopenharmony_ci	var sc ServerConfig
369fb726d48Sopenharmony_ci	err = json.Unmarshal(serverConfigBuffer, &sc)
370fb726d48Sopenharmony_ci	if err != nil {
371fb726d48Sopenharmony_ci		return
372fb726d48Sopenharmony_ci	}
373fb726d48Sopenharmony_ci	serveInfo = sc.ServeInfo
374fb726d48Sopenharmony_ci	msgPublishData.Mux.Lock()
375fb726d48Sopenharmony_ci	msgPublishData.FilePath = sc.MsgPublishFile
376fb726d48Sopenharmony_ci	msgPublishData.Mux.Unlock()
377fb726d48Sopenharmony_ci	go loopUpdateMsgPublishData()
378fb726d48Sopenharmony_ci}
379fb726d48Sopenharmony_ci
380fb726d48Sopenharmony_cifunc mapToJson(m map[string]interface{}) (string, error) {
381fb726d48Sopenharmony_ci	marshal, err := json.Marshal(m)
382fb726d48Sopenharmony_ci	if err != nil {
383fb726d48Sopenharmony_ci		return "", err
384fb726d48Sopenharmony_ci	}
385fb726d48Sopenharmony_ci	var str = string(marshal)
386fb726d48Sopenharmony_ci	return str, nil
387fb726d48Sopenharmony_ci}
388fb726d48Sopenharmony_cifunc jsonToMap(str string) (map[string]interface{}, error) {
389fb726d48Sopenharmony_ci	var m = make(map[string]interface{})
390fb726d48Sopenharmony_ci	err := json.Unmarshal([]byte(str), &m)
391fb726d48Sopenharmony_ci	if err != nil {
392fb726d48Sopenharmony_ci		return nil, err
393fb726d48Sopenharmony_ci	}
394fb726d48Sopenharmony_ci	return m, nil
395fb726d48Sopenharmony_ci}
396fb726d48Sopenharmony_ci
397fb726d48Sopenharmony_ci// MkDir 创建目录
398fb726d48Sopenharmony_cifunc MkDir(path string) {
399fb726d48Sopenharmony_ci	dir := path[0:strings.LastIndex(path, string(os.PathSeparator))] //从文件路径获取目录
400fb726d48Sopenharmony_ci	if _, err := os.Stat(dir); err != nil {                          //如果目录不存在,创建目录
401fb726d48Sopenharmony_ci		os.MkdirAll(dir, os.ModePerm)
402fb726d48Sopenharmony_ci	}
403fb726d48Sopenharmony_ci}
404fb726d48Sopenharmony_ci
405fb726d48Sopenharmony_cifunc resp(w *http.ResponseWriter) func(bool, int, string, map[string]interface{}) {
406fb726d48Sopenharmony_ci	return func(success bool, code int, msg string, obj map[string]interface{}) {
407fb726d48Sopenharmony_ci		toJson, err := mapToJson(map[string]interface{}{
408fb726d48Sopenharmony_ci			"success": success,
409fb726d48Sopenharmony_ci			"code":    code,
410fb726d48Sopenharmony_ci			"msg":     msg,
411fb726d48Sopenharmony_ci			"data":    obj,
412fb726d48Sopenharmony_ci		})
413fb726d48Sopenharmony_ci		if err != nil {
414fb726d48Sopenharmony_ci			errRes, _ := mapToJson(map[string]interface{}{
415fb726d48Sopenharmony_ci				"success": false,
416fb726d48Sopenharmony_ci				"code":    -1,
417fb726d48Sopenharmony_ci				"msg":     err.Error(),
418fb726d48Sopenharmony_ci			})
419fb726d48Sopenharmony_ci			fmt.Fprintf(*w, errRes)
420fb726d48Sopenharmony_ci		} else {
421fb726d48Sopenharmony_ci			fmt.Fprintf(*w, toJson)
422fb726d48Sopenharmony_ci		}
423fb726d48Sopenharmony_ci	}
424fb726d48Sopenharmony_ci}
425fb726d48Sopenharmony_ci
426fb726d48Sopenharmony_cifunc get(url string) (*http.Response, error) {
427fb726d48Sopenharmony_ci	jar, _ := cookiejar.New(nil)
428fb726d48Sopenharmony_ci	c := &http.Client{
429fb726d48Sopenharmony_ci		Transport:     &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
430fb726d48Sopenharmony_ci		CheckRedirect: nil,
431fb726d48Sopenharmony_ci		Jar:           jar,
432fb726d48Sopenharmony_ci		Timeout:       time.Duration(3600) * time.Second,
433fb726d48Sopenharmony_ci	}
434fb726d48Sopenharmony_ci	return c.Get(url)
435fb726d48Sopenharmony_ci}
436fb726d48Sopenharmony_ci
437fb726d48Sopenharmony_cifunc clearOverdueFile() {
438fb726d48Sopenharmony_ci	MkDir(filepath.FromSlash(fmt.Sprintf("./upload/")))
439fb726d48Sopenharmony_ci	now := time.Now()
440fb726d48Sopenharmony_ci	loc, err := time.LoadLocation("Asia/Shanghai")
441fb726d48Sopenharmony_ci	if err != nil {
442fb726d48Sopenharmony_ci		return
443fb726d48Sopenharmony_ci	}
444fb726d48Sopenharmony_ci	var checkDue = func(fileName string) bool {
445fb726d48Sopenharmony_ci		f := getSuffixByUrl(fileName)
446fb726d48Sopenharmony_ci		parseTime, err := time.ParseInLocation("20060102150405000", f.fileName, loc)
447fb726d48Sopenharmony_ci		if err != nil {
448fb726d48Sopenharmony_ci			return false
449fb726d48Sopenharmony_ci		}
450fb726d48Sopenharmony_ci		sub := now.Sub(parseTime)
451fb726d48Sopenharmony_ci		if sub.Minutes() > 60 { //bigger than 60 min flag due
452fb726d48Sopenharmony_ci			return true
453fb726d48Sopenharmony_ci		}
454fb726d48Sopenharmony_ci		return false
455fb726d48Sopenharmony_ci	}
456fb726d48Sopenharmony_ci	slash := filepath.FromSlash(fmt.Sprintf("./upload/"))
457fb726d48Sopenharmony_ci	filepath.WalkDir(slash, func(path string, d fs.DirEntry, err error) error {
458fb726d48Sopenharmony_ci		if checkDue(d.Name()) {
459fb726d48Sopenharmony_ci			fmt.Println(now, "delete->", path, d.Name(), err)
460fb726d48Sopenharmony_ci			os.Remove(path)
461fb726d48Sopenharmony_ci		}
462fb726d48Sopenharmony_ci		return nil
463fb726d48Sopenharmony_ci	})
464fb726d48Sopenharmony_ci}
465fb726d48Sopenharmony_cifunc getSuffixByUrl(u string) struct {
466fb726d48Sopenharmony_ci	fileName string
467fb726d48Sopenharmony_ci	suffix   string
468fb726d48Sopenharmony_ci} {
469fb726d48Sopenharmony_ci	lastIndex := strings.LastIndex(u, "/")
470fb726d48Sopenharmony_ci	var f string
471fb726d48Sopenharmony_ci	if lastIndex != -1 {
472fb726d48Sopenharmony_ci		f = u[lastIndex:]
473fb726d48Sopenharmony_ci	} else {
474fb726d48Sopenharmony_ci		f = u
475fb726d48Sopenharmony_ci	}
476fb726d48Sopenharmony_ci	index := strings.LastIndex(f, ".")
477fb726d48Sopenharmony_ci	if index != -1 {
478fb726d48Sopenharmony_ci		return struct {
479fb726d48Sopenharmony_ci			fileName string
480fb726d48Sopenharmony_ci			suffix   string
481fb726d48Sopenharmony_ci		}{
482fb726d48Sopenharmony_ci			f[0:index],
483fb726d48Sopenharmony_ci			f[index:],
484fb726d48Sopenharmony_ci		}
485fb726d48Sopenharmony_ci	} else {
486fb726d48Sopenharmony_ci		return struct {
487fb726d48Sopenharmony_ci			fileName string
488fb726d48Sopenharmony_ci			suffix   string
489fb726d48Sopenharmony_ci		}{
490fb726d48Sopenharmony_ci			f,
491fb726d48Sopenharmony_ci			"",
492fb726d48Sopenharmony_ci		}
493fb726d48Sopenharmony_ci	}
494fb726d48Sopenharmony_ci}
495fb726d48Sopenharmony_ci
496fb726d48Sopenharmony_cifunc downloadHandler(w http.ResponseWriter, r *http.Request) {
497fb726d48Sopenharmony_ci	w.Header().Set("content-type", "text/json")
498fb726d48Sopenharmony_ci	clearOverdueFile()
499fb726d48Sopenharmony_ci	contentType := r.Header["Content-Type"]
500fb726d48Sopenharmony_ci	if len(contentType) > 0 {
501fb726d48Sopenharmony_ci		contentTypeName := contentType[0]
502fb726d48Sopenharmony_ci		if strings.HasPrefix(contentTypeName, "application/x-www-form-urlencoded") {
503fb726d48Sopenharmony_ci			url := r.PostFormValue("url")
504fb726d48Sopenharmony_ci			res, err := get(url)
505fb726d48Sopenharmony_ci			if err != nil {
506fb726d48Sopenharmony_ci				resp(&w)(false, -1, err.Error(), nil)
507fb726d48Sopenharmony_ci				return
508fb726d48Sopenharmony_ci			}
509fb726d48Sopenharmony_ci			pth := filepath.FromSlash(fmt.Sprintf("/upload/%s%s", time.Now().Format("20060102150405000"), getSuffixByUrl(url).suffix))
510fb726d48Sopenharmony_ci			MkDir("." + pth)
511fb726d48Sopenharmony_ci			create, err := os.Create("." + pth)
512fb726d48Sopenharmony_ci			if err != nil {
513fb726d48Sopenharmony_ci				resp(&w)(false, -1, err.Error(), nil)
514fb726d48Sopenharmony_ci				return
515fb726d48Sopenharmony_ci			}
516fb726d48Sopenharmony_ci			written, err := io.Copy(create, res.Body)
517fb726d48Sopenharmony_ci			if err != nil {
518fb726d48Sopenharmony_ci				resp(&w)(false, -1, err.Error(), nil)
519fb726d48Sopenharmony_ci				return
520fb726d48Sopenharmony_ci			}
521fb726d48Sopenharmony_ci			fmt.Println(url, written)
522fb726d48Sopenharmony_ci			pth = "/application" + pth
523fb726d48Sopenharmony_ci			resp(&w)(true, 0, "success", map[string]interface{}{
524fb726d48Sopenharmony_ci				"url":  pth,
525fb726d48Sopenharmony_ci				"size": written,
526fb726d48Sopenharmony_ci			})
527fb726d48Sopenharmony_ci			return
528fb726d48Sopenharmony_ci		}
529fb726d48Sopenharmony_ci	}
530fb726d48Sopenharmony_ci	resp(&w)(false, -1, "请求方式错误", nil)
531fb726d48Sopenharmony_ci}
532fb726d48Sopenharmony_ci
533fb726d48Sopenharmony_cifunc SplitLines(s string) []string {
534fb726d48Sopenharmony_ci	var lines []string
535fb726d48Sopenharmony_ci	sc := bufio.NewScanner(strings.NewReader(s))
536fb726d48Sopenharmony_ci	for sc.Scan() {
537fb726d48Sopenharmony_ci		lines = append(lines, sc.Text())
538fb726d48Sopenharmony_ci	}
539fb726d48Sopenharmony_ci	return lines
540fb726d48Sopenharmony_ci}
541fb726d48Sopenharmony_ci
542fb726d48Sopenharmony_cifunc readFileFirstLine(path string) string {
543fb726d48Sopenharmony_ci	file, err := os.Open(path)
544fb726d48Sopenharmony_ci	if err != nil {
545fb726d48Sopenharmony_ci		return ""
546fb726d48Sopenharmony_ci	}
547fb726d48Sopenharmony_ci	defer file.Close()
548fb726d48Sopenharmony_ci
549fb726d48Sopenharmony_ci	readFile := bufio.NewReader(file)
550fb726d48Sopenharmony_ci	line, readErr := readFile.ReadString('\n')
551fb726d48Sopenharmony_ci	if readErr != nil || io.EOF == err {
552fb726d48Sopenharmony_ci		return ""
553fb726d48Sopenharmony_ci	}
554fb726d48Sopenharmony_ci	return line
555fb726d48Sopenharmony_ci}
556fb726d48Sopenharmony_ci
557fb726d48Sopenharmony_cifunc PathExists(path string) (bool, error) {
558fb726d48Sopenharmony_ci	_, err := os.Stat(path)
559fb726d48Sopenharmony_ci	if err == nil {
560fb726d48Sopenharmony_ci		return true, nil
561fb726d48Sopenharmony_ci	}
562fb726d48Sopenharmony_ci	if os.IsNotExist(err) {
563fb726d48Sopenharmony_ci		return false, nil
564fb726d48Sopenharmony_ci	}
565fb726d48Sopenharmony_ci	return false, err
566fb726d48Sopenharmony_ci}
567fb726d48Sopenharmony_ci
568fb726d48Sopenharmony_cifunc chekDir(path string) {
569fb726d48Sopenharmony_ci	_, err := os.Stat(path)
570fb726d48Sopenharmony_ci	if err != nil {
571fb726d48Sopenharmony_ci		err := os.Mkdir(path, os.ModePerm)
572fb726d48Sopenharmony_ci		if err != nil {
573fb726d48Sopenharmony_ci			fmt.Printf("mkdir failed![%v]\n", err)
574fb726d48Sopenharmony_ci		} else {
575fb726d48Sopenharmony_ci			fmt.Printf("mkdir success!\n")
576fb726d48Sopenharmony_ci		}
577fb726d48Sopenharmony_ci	}
578fb726d48Sopenharmony_ci}
579fb726d48Sopenharmony_cifunc CheckErr(err error) {
580fb726d48Sopenharmony_ci	if err != nil {
581fb726d48Sopenharmony_ci		log.Panicln(err)
582fb726d48Sopenharmony_ci	}
583fb726d48Sopenharmony_ci}
584fb726d48Sopenharmony_ci
585fb726d48Sopenharmony_cifunc open(url string) error {
586fb726d48Sopenharmony_ci	if isWindows() {
587fb726d48Sopenharmony_ci		return openUrlWindows(url)
588fb726d48Sopenharmony_ci	} else if isDarwin() {
589fb726d48Sopenharmony_ci		return openUrlDarwin(url)
590fb726d48Sopenharmony_ci	} else {
591fb726d48Sopenharmony_ci		return openUrlOther(url)
592fb726d48Sopenharmony_ci	}
593fb726d48Sopenharmony_ci}
594fb726d48Sopenharmony_ci
595fb726d48Sopenharmony_cifunc openUrlWindows(url string) error {
596fb726d48Sopenharmony_ci	cmd := "cmd"
597fb726d48Sopenharmony_ci	args := []string{"/c", "start", url}
598fb726d48Sopenharmony_ci	return exec.Command(cmd, args...).Start()
599fb726d48Sopenharmony_ci}
600fb726d48Sopenharmony_cifunc openUrlDarwin(url string) error {
601fb726d48Sopenharmony_ci	var cmd = "open"
602fb726d48Sopenharmony_ci	var args = []string{url}
603fb726d48Sopenharmony_ci	return exec.Command(cmd, args...).Start()
604fb726d48Sopenharmony_ci}
605fb726d48Sopenharmony_cifunc openUrlOther(url string) error {
606fb726d48Sopenharmony_ci	var cmd = "xdg-open"
607fb726d48Sopenharmony_ci	var args = []string{url}
608fb726d48Sopenharmony_ci	return exec.Command(cmd, args...).Start()
609fb726d48Sopenharmony_ci}
610fb726d48Sopenharmony_ci
611fb726d48Sopenharmony_cifunc isWindows() bool {
612fb726d48Sopenharmony_ci	return runtime.GOOS == "windows"
613fb726d48Sopenharmony_ci}
614fb726d48Sopenharmony_cifunc isDarwin() bool {
615fb726d48Sopenharmony_ci	return runtime.GOOS == "darwin"
616fb726d48Sopenharmony_ci}
617fb726d48Sopenharmony_ci
618fb726d48Sopenharmony_cifunc getCurrentAbPath() string {
619fb726d48Sopenharmony_ci	dir := getExecutePath()
620fb726d48Sopenharmony_ci	tmpDir, _ := filepath.EvalSymlinks(os.TempDir())
621fb726d48Sopenharmony_ci	if strings.Contains(dir, tmpDir) {
622fb726d48Sopenharmony_ci		return getCallerPath()
623fb726d48Sopenharmony_ci	}
624fb726d48Sopenharmony_ci	return dir
625fb726d48Sopenharmony_ci}
626fb726d48Sopenharmony_ci
627fb726d48Sopenharmony_cifunc getCallerPath() string {
628fb726d48Sopenharmony_ci	var pth string
629fb726d48Sopenharmony_ci	_, fName, _, ok := runtime.Caller(0)
630fb726d48Sopenharmony_ci	if ok {
631fb726d48Sopenharmony_ci		pth = path.Dir(fName)
632fb726d48Sopenharmony_ci	}
633fb726d48Sopenharmony_ci	return pth
634fb726d48Sopenharmony_ci}
635fb726d48Sopenharmony_cifunc getExecutePath() string {
636fb726d48Sopenharmony_ci	pth, err := os.Executable()
637fb726d48Sopenharmony_ci	if err != nil {
638fb726d48Sopenharmony_ci		log.Fatal(err)
639fb726d48Sopenharmony_ci	}
640fb726d48Sopenharmony_ci	res, _ := filepath.EvalSymlinks(filepath.Dir(pth))
641fb726d48Sopenharmony_ci	return res
642fb726d48Sopenharmony_ci}
643fb726d48Sopenharmony_ci
644fb726d48Sopenharmony_cifunc checkPort(port int) {
645fb726d48Sopenharmony_ci	if isWindows() {
646fb726d48Sopenharmony_ci		pid := getPidByPort(port)
647fb726d48Sopenharmony_ci		if pid != -1 {
648fb726d48Sopenharmony_ci			res := exec.Command("cmd", "/c", fmt.Sprintf("taskkill /F /PID %d /T", pid))
649fb726d48Sopenharmony_ci			res.Run()
650fb726d48Sopenharmony_ci		}
651fb726d48Sopenharmony_ci	}
652fb726d48Sopenharmony_ci}
653