|
|
@ -10,6 +10,7 @@ import (
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"io/ioutil"
|
|
|
|
|
|
|
|
"math"
|
|
|
|
"net"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"os"
|
|
|
@ -19,7 +20,7 @@ import (
|
|
|
|
"time"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
var version = "2.0.0"
|
|
|
|
var version = "2.0.1"
|
|
|
|
|
|
|
|
|
|
|
|
type HttpServerCfgs func(cfg *HttpServerCfg)
|
|
|
|
type HttpServerCfgs func(cfg *HttpServerCfg)
|
|
|
|
|
|
|
|
|
|
|
@ -42,6 +43,135 @@ type HttpServer struct {
|
|
|
|
HttpServerCfg
|
|
|
|
HttpServerCfg
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var htmlTitle string = `<!DOCTYPE html>
|
|
|
|
|
|
|
|
<html lang="zh_CN">
|
|
|
|
|
|
|
|
<head>
|
|
|
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
|
|
|
<title>B612 Http Server %s</title>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
|
|
* {
|
|
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
body {
|
|
|
|
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
|
|
|
font-family: Arial, sans-serif;
|
|
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.container {
|
|
|
|
|
|
|
|
max-width: 960px;
|
|
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
|
|
padding: 24px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
h1 {
|
|
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
table {
|
|
|
|
|
|
|
|
width: 100%%;
|
|
|
|
|
|
|
|
border-collapse: collapse;
|
|
|
|
|
|
|
|
margin-top: 24px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
th,
|
|
|
|
|
|
|
|
td {
|
|
|
|
|
|
|
|
padding: 12px;
|
|
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
|
|
border-bottom: 1px solid #ddd;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
th:hover {
|
|
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
background-color: #ddd;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.filename {
|
|
|
|
|
|
|
|
color: #007bff;
|
|
|
|
|
|
|
|
text-decoration: underline;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.filetype {
|
|
|
|
|
|
|
|
text-transform: uppercase;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@media screen and (max-width: 600px) {
|
|
|
|
|
|
|
|
table {
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
|
|
|
<div class="container">
|
|
|
|
|
|
|
|
<h1>B612 Http Server - %s</h1>
|
|
|
|
|
|
|
|
<hr /><pre><h2> %s </h2></pre>%s
|
|
|
|
|
|
|
|
<table>
|
|
|
|
|
|
|
|
<thead>
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
|
|
<th onclick="sortTable(0)">Name</th>
|
|
|
|
|
|
|
|
<th onclick="sortTable(1)">Modified</th>
|
|
|
|
|
|
|
|
<th onclick="sortTable(2)">Size</th>
|
|
|
|
|
|
|
|
<th onclick="sortTable(3)">Type</th>
|
|
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
|
|
<tbody>`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var htmlTail = ` </tbody>
|
|
|
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
|
|
function sortTable(n) {
|
|
|
|
|
|
|
|
const table = document.querySelector('table');
|
|
|
|
|
|
|
|
const rows = table.rows;
|
|
|
|
|
|
|
|
let switching = true;
|
|
|
|
|
|
|
|
let shouldSwitch = false;
|
|
|
|
|
|
|
|
let direction = 'asc';
|
|
|
|
|
|
|
|
let switchcount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (switching) {
|
|
|
|
|
|
|
|
switching = false;
|
|
|
|
|
|
|
|
let i;
|
|
|
|
|
|
|
|
for (i = 1; i < rows.length - 1; i++) {
|
|
|
|
|
|
|
|
shouldSwitch = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const x = rows[i].getElementsByTagName("td")[n];
|
|
|
|
|
|
|
|
const y = rows[i + 1].getElementsByTagName("td")[n];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (direction === 'asc') {
|
|
|
|
|
|
|
|
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
|
|
|
|
|
|
|
|
shouldSwitch = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (direction === 'desc') {
|
|
|
|
|
|
|
|
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
|
|
|
|
|
|
|
|
shouldSwitch = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (shouldSwitch) {
|
|
|
|
|
|
|
|
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
|
|
|
|
|
|
|
|
switching = true;
|
|
|
|
|
|
|
|
switchcount++;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (switchcount === 0 && direction === 'asc') {
|
|
|
|
|
|
|
|
direction = 'desc';
|
|
|
|
|
|
|
|
switching = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
</body>
|
|
|
|
|
|
|
|
</html>
|
|
|
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
|
|
func WithTLSCert(cert, key string) HttpServerCfgs {
|
|
|
|
func WithTLSCert(cert, key string) HttpServerCfgs {
|
|
|
|
return func(cfg *HttpServerCfg) {
|
|
|
|
return func(cfg *HttpServerCfg) {
|
|
|
|
cfg.key = key
|
|
|
|
cfg.key = key
|
|
|
@ -310,13 +440,18 @@ func (h *HttpServer) getFolder(log *starlog.StarLogger, w http.ResponseWriter, r
|
|
|
|
if r.Method != "GET" {
|
|
|
|
if r.Method != "GET" {
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
w.Write([]byte("<html>\n<style>\np{margin: 2px auto}\n</style>\n<h1>B612 Http Server - " + version + "</h1>"))
|
|
|
|
var upload string
|
|
|
|
if h.uploadFolder != "" {
|
|
|
|
if h.uploadFolder != "" {
|
|
|
|
w.Write([]byte("<a href=/b612?upload=true>Upload Web Page Is Openned!</a><br /><br />"))
|
|
|
|
upload = `<a href=/b612?upload=true>Upload Web Page Is Openned!</a>`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
w.Write([]byte("<hr /><pre>\n"))
|
|
|
|
w.Write([]byte(fmt.Sprintf(htmlTitle, r.URL.Path, version, r.URL.Path, upload)))
|
|
|
|
if r.URL.Path != "/" {
|
|
|
|
if r.URL.Path != "/" {
|
|
|
|
w.Write([]byte(fmt.Sprintf("<p><a href='%s'>%s</a> %s</p>\n", r.URL.Path+"/..", "..", "上层文件夹")))
|
|
|
|
p := r.URL.Path
|
|
|
|
|
|
|
|
if p[len(p)-1:] != "/" {
|
|
|
|
|
|
|
|
p += "/"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
w.Write([]byte(fmt.Sprintf(`<tr><td><a class="filename" href="%s">%s</a></td><td>%s</td><td>%s</td><td class="filetype">%s</td></tr>`,
|
|
|
|
|
|
|
|
p+"..", "..", "-", "-", "上层文件夹")))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if r.URL.Path == "/" {
|
|
|
|
if r.URL.Path == "/" {
|
|
|
|
r.URL.Path = ""
|
|
|
|
r.URL.Path = ""
|
|
|
@ -327,13 +462,15 @@ func (h *HttpServer) getFolder(log *starlog.StarLogger, w http.ResponseWriter, r
|
|
|
|
for _, v := range dir {
|
|
|
|
for _, v := range dir {
|
|
|
|
if v.Name() != "." || v.Name() != ".." {
|
|
|
|
if v.Name() != "." || v.Name() != ".." {
|
|
|
|
if !v.IsDir() {
|
|
|
|
if !v.IsDir() {
|
|
|
|
w.Write([]byte(fmt.Sprintf("<p><a href='%s'>%s</a> %d %s</p>\n", r.URL.Path+"/"+v.Name(), v.Name(), int(v.Size()), v.ModTime().Format("2006-01-02 15:04:05"))))
|
|
|
|
w.Write([]byte(fmt.Sprintf(`<tr><td><a class="filename" href="%s">%s</a></td><td>%s</td><td>%s</td><td class="filetype">%s</td></tr>`,
|
|
|
|
|
|
|
|
r.URL.Path+"/"+v.Name(), v.Name(), v.ModTime().Format("2006-01-02 15:04:05"), fmt.Sprintf("%d (%s)", v.Size(), h.trimSize(v.Size())), h.FileType(v.Name()))))
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
w.Write([]byte(fmt.Sprintf("<p><a href='%s'>%s</a> %s %s</p>\n", r.URL.Path+"/"+v.Name(), v.Name(), "文件夹", v.ModTime().Format("2006-01-02 15:04:05"))))
|
|
|
|
w.Write([]byte(fmt.Sprintf(`<tr><td><a class="filename" href="%s">%s</a></td><td>%s</td><td>%s</td><td class="filetype">%s</td></tr>`,
|
|
|
|
|
|
|
|
r.URL.Path+"/"+v.Name(), v.Name(), v.ModTime().Format("2006-01-02 15:04:05"), "-", "文件夹")))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
w.Write([]byte("</pre>\n</html>"))
|
|
|
|
w.Write([]byte(htmlTail))
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -434,6 +571,21 @@ func (h *HttpServer) getFile(log *starlog.StarLogger, w http.ResponseWriter, r *
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (h *HttpServer) trimSize(size int64) string {
|
|
|
|
|
|
|
|
var tani string
|
|
|
|
|
|
|
|
tani = fmt.Sprintf("%v Byte", size)
|
|
|
|
|
|
|
|
if f64 := float64(size) / 1024; f64 > 1 {
|
|
|
|
|
|
|
|
tani = fmt.Sprintf("%.3f KB", math.Trunc(f64*1e3+0.5)*1e-3)
|
|
|
|
|
|
|
|
if f64 = float64(f64) / 1024; f64 > 1 {
|
|
|
|
|
|
|
|
tani = fmt.Sprintf("%.3f MB", math.Trunc(f64*1e3+0.5)*1e-3)
|
|
|
|
|
|
|
|
if f64 = float64(f64) / 1024; f64 > 1 {
|
|
|
|
|
|
|
|
tani = fmt.Sprintf("%.3f GB", math.Trunc(f64*1e3+0.5)*1e-3)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return tani
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (h *HttpServer) uploadFile(w http.ResponseWriter, r *http.Request) {
|
|
|
|
func (h *HttpServer) uploadFile(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if r.Method != "POST" {
|
|
|
|
if r.Method != "POST" {
|
|
|
|
w.WriteHeader(200)
|
|
|
|
w.WriteHeader(200)
|
|
|
|