update
This commit is contained in:
parent
88a3fdf2bf
commit
35cf23e5ad
2
go.mod
2
go.mod
@ -29,6 +29,8 @@ require (
|
||||
b612.me/starmap v1.2.4 // indirect
|
||||
b612.me/starnet v0.1.8 // indirect
|
||||
b612.me/win32api v0.0.2 // indirect
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
|
||||
github.com/emersion/go-smtp v0.20.2 // indirect
|
||||
github.com/jlaffaye/ftp v0.1.0 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/pkg/sftp v1.13.4 // indirect
|
||||
|
4
go.sum
4
go.sum
@ -28,6 +28,10 @@ github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5 h1:m62nsMU279qRD9P
|
||||
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-smtp v0.20.2 h1:peX42Qnh5Q0q3vrAnRy43R/JwTnnv75AebxbkTL7Ia4=
|
||||
github.com/emersion/go-smtp v0.20.2/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
|
||||
github.com/goftp/file-driver v0.0.0-20180502053751-5d604a0fc0c9 h1:cC0Hbb+18DJ4i6ybqDybvj4wdIDS4vnD0QEci98PgM8=
|
||||
github.com/goftp/file-driver v0.0.0-20180502053751-5d604a0fc0c9/go.mod h1:GpOj6zuVBG3Inr9qjEnuVTgBlk2lZ1S9DcoFiXWyKss=
|
||||
github.com/goftp/server v0.0.0-20200708154336-f64f7c2d8a42 h1:JdOp2qR5PF4O75tzHeqrwnDDv8oHDptWyTbyYS4fD8E=
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"b612.me/starlog"
|
||||
"b612.me/staros"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"os/signal"
|
||||
@ -13,8 +14,10 @@ import (
|
||||
var s HttpServer
|
||||
|
||||
var daemon bool
|
||||
var hooks string
|
||||
|
||||
func init() {
|
||||
Cmd.Flags().StringVarP(&hooks, "hook", "H", "", "fileget hook for modify")
|
||||
Cmd.Flags().StringVarP(&s.port, "port", "p", "80", "监听端口")
|
||||
Cmd.Flags().StringVarP(&s.addr, "ip", "i", "0.0.0.0", "监听ip")
|
||||
Cmd.Flags().StringVarP(&s.envPath, "folder", "f", "./", "本地文件地址")
|
||||
@ -36,6 +39,24 @@ var Cmd = &cobra.Command{
|
||||
Short: "HTTP文件服务器(HTTP File Browser Server)",
|
||||
Long: `HTTP文件服务器(HTTP File Browser Server)`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if hooks != "" {
|
||||
if !staros.Exists(hooks) {
|
||||
starlog.Criticalln("hook file not exists")
|
||||
os.Exit(2)
|
||||
}
|
||||
data, err := os.ReadFile(hooks)
|
||||
if err != nil {
|
||||
starlog.Criticalln("read hook file error", err)
|
||||
os.Exit(3)
|
||||
}
|
||||
var hk []ServerHook
|
||||
err = json.Unmarshal(data, &hk)
|
||||
if err != nil {
|
||||
starlog.Errorln("Unmarshal hook Json Failed", err)
|
||||
os.Exit(4)
|
||||
}
|
||||
s.hooks = hk
|
||||
}
|
||||
apply, _ := cmd.Flags().GetBool("daeapplied")
|
||||
if daemon && !apply {
|
||||
nArgs := append(os.Args[1:], "--daeapplied")
|
||||
|
@ -217,6 +217,14 @@ func (h *HttpServer) FileType(name string) string {
|
||||
return mime
|
||||
}
|
||||
|
||||
func (h *HttpServer) GetExt(fullpath string) string {
|
||||
ext := filepath.Ext(filepath.Base(fullpath))
|
||||
if len(ext) == 0 || ext == "." {
|
||||
return ""
|
||||
}
|
||||
return ext[1:]
|
||||
}
|
||||
|
||||
func (h *HttpServer) MIME(fullpath string) string {
|
||||
ext := filepath.Ext(filepath.Base(fullpath))
|
||||
if len(ext) == 0 || ext == "." {
|
||||
|
@ -3,6 +3,7 @@ package httpserver
|
||||
import (
|
||||
"b612.me/starcrypto"
|
||||
"b612.me/starlog"
|
||||
"b612.me/starnet"
|
||||
"b612.me/staros"
|
||||
"context"
|
||||
_ "embed"
|
||||
@ -39,7 +40,16 @@ type HttpServerCfg struct {
|
||||
protectAuthPage []string
|
||||
disableMIME bool
|
||||
ctx context.Context
|
||||
hooks []ServerHook
|
||||
}
|
||||
|
||||
type ServerHook struct {
|
||||
MatchType []string `json:"match_type"`
|
||||
Url string `json:"url"`
|
||||
Timeout int `json:"timeout"`
|
||||
MaxHookLength int `json:"max_hook_length"`
|
||||
}
|
||||
|
||||
type HttpServer struct {
|
||||
HttpServerCfg
|
||||
}
|
||||
@ -267,6 +277,17 @@ var htmlTail = ` </tbody>
|
||||
</html>
|
||||
`
|
||||
|
||||
func WithHooks(hooks []ServerHook) HttpServerCfgs {
|
||||
return func(cfg *HttpServerCfg) {
|
||||
for k, v := range hooks {
|
||||
if v.MaxHookLength == 0 {
|
||||
hooks[k].MaxHookLength = 1024 * 1024
|
||||
}
|
||||
}
|
||||
cfg.hooks = hooks
|
||||
}
|
||||
}
|
||||
|
||||
func WithTLSCert(cert, key string) HttpServerCfgs {
|
||||
return func(cfg *HttpServerCfg) {
|
||||
cfg.key = key
|
||||
@ -505,6 +526,9 @@ func (h *HttpServer) BuildHeader(w http.ResponseWriter, r *http.Request, fullpat
|
||||
w.Header().Set("ETag", starcrypto.Md5Str([]byte(finfo.ModTime().String())))
|
||||
w.Header().Set("Last-Modified", strings.ReplaceAll(finfo.ModTime().UTC().Format("Mon, 2 Jan 2006 15:04:05 MST"), "UTC", "GMT"))
|
||||
if r.Method != "OPTIONS" {
|
||||
if _, ok := h.willHook(fullpath); ok {
|
||||
return nil
|
||||
}
|
||||
w.Header().Set("Content-Length", strconv.FormatInt(finfo.Size(), 10))
|
||||
start, end := h.CalcRange(r)
|
||||
if start != -1 {
|
||||
@ -521,6 +545,24 @@ func (h *HttpServer) BuildHeader(w http.ResponseWriter, r *http.Request, fullpat
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *HttpServer) willHook(fullpath string) (ServerHook, bool) {
|
||||
finfo, err := os.Stat(fullpath)
|
||||
if err != nil {
|
||||
return ServerHook{}, false
|
||||
}
|
||||
if finfo.Size() < 1024*1024*10 && len(h.hooks) > 0 {
|
||||
ext := h.GetExt(fullpath)
|
||||
for _, hk := range h.hooks {
|
||||
for _, e := range hk.MatchType {
|
||||
if e == ext {
|
||||
return hk, true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ServerHook{}, false
|
||||
}
|
||||
|
||||
func (h *HttpServer) ResponseGet(log *starlog.StarLogger, w http.ResponseWriter, r *http.Request, fullpath string) error {
|
||||
if staros.IsFolder(fullpath) {
|
||||
return h.getFolder(log, w, r, fullpath)
|
||||
@ -610,25 +652,62 @@ func (h *HttpServer) getFile(log *starlog.StarLogger, w http.ResponseWriter, r *
|
||||
}
|
||||
}()
|
||||
if startRange == -1 {
|
||||
w.WriteHeader(200)
|
||||
for {
|
||||
buf := make([]byte, 1048576)
|
||||
n, err := fp.Read(buf)
|
||||
if n != 0 {
|
||||
ns, err := w.Write(buf[0:n])
|
||||
transferData += ns
|
||||
hook, needCurl := h.willHook(fullpath)
|
||||
if !needCurl {
|
||||
w.WriteHeader(200)
|
||||
for {
|
||||
buf := make([]byte, 1048576)
|
||||
n, err := fp.Read(buf)
|
||||
if n != 0 {
|
||||
ns, err := w.Write(buf[0:n])
|
||||
transferData += ns
|
||||
if err != nil {
|
||||
log.Errorf("Transfer File %s to Remote Failed:%v\n", fullpath, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("Transfer File %s to Remote Failed:%v\n", fullpath, err)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
log.Errorln("Read File %s Failed:%v\n", fullpath, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
data, err := os.ReadFile(fullpath)
|
||||
if err != nil {
|
||||
w.WriteHeader(502)
|
||||
w.Write([]byte(`<html><title>B612 Http Server</title><body><h1 "style="text-align: center;">502 SERVER ERROR</h1><hr ></body></html>`))
|
||||
log.Errorf("Read File %s Failed:%v\n", fullpath, err)
|
||||
return err
|
||||
}
|
||||
b64 := base64.StdEncoding.EncodeToString(data)
|
||||
req, err := starnet.Curl(starnet.NewRequests(hook.Url, starnet.BuildPostForm(map[string]string{
|
||||
"data": b64,
|
||||
"ip": r.RemoteAddr,
|
||||
}),
|
||||
"POST",
|
||||
starnet.WithTimeout(time.Duration(hook.Timeout)*time.Millisecond)))
|
||||
if err != nil || len(req.RecvData) == 0 {
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(data)))
|
||||
w.WriteHeader(200)
|
||||
ns, err := w.Write(data)
|
||||
transferData += ns
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
log.Errorln("Read File %s Failed:%v\n", fullpath, err)
|
||||
log.Errorf("Transfer File %s to Remote Failed:%v\n", fullpath, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
w.WriteHeader(200)
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(req.RecvData)))
|
||||
ns, err := w.Write(req.RecvData)
|
||||
transferData += ns
|
||||
if err != nil {
|
||||
log.Errorf("Transfer File %s to Remote Failed:%v\n", fullpath, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
5
main.go
5
main.go
@ -22,6 +22,7 @@ import (
|
||||
"b612.me/apps/b612/net"
|
||||
"b612.me/apps/b612/rmt"
|
||||
"b612.me/apps/b612/search"
|
||||
"b612.me/apps/b612/smtpserver"
|
||||
"b612.me/apps/b612/socks5"
|
||||
"b612.me/apps/b612/split"
|
||||
"b612.me/apps/b612/tcping"
|
||||
@ -36,7 +37,7 @@ import (
|
||||
|
||||
var cmdRoot = &cobra.Command{
|
||||
Use: "b612",
|
||||
Version: "2.1.0",
|
||||
Version: "2.1.0.alpha",
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -44,7 +45,7 @@ func init() {
|
||||
cmdRoot.AddCommand(tcping.Cmd, uac.Cmd, httpserver.Cmd, httpreverse.Cmd,
|
||||
base64.Cmd, base85.Cmd, base91.Cmd, attach.Cmd, detach.Cmd, df.Cmd, dfinder.Cmd,
|
||||
ftp.Cmd, generate.Cmd, hash.Cmd, image.Cmd, merge.Cmd, search.Cmd, split.Cmd, vic.Cmd,
|
||||
calc.Cmd, net.Cmd, rmt.Cmds, rmt.Cmdc, keygen.Cmd, dns.Cmd, whois.Cmd, socks5.Cmd, httproxy.Cmd)
|
||||
calc.Cmd, net.Cmd, rmt.Cmds, rmt.Cmdc, keygen.Cmd, dns.Cmd, whois.Cmd, socks5.Cmd, httproxy.Cmd, smtpserver.Cmd)
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
130
smtpserver/smtp.go
Normal file
130
smtpserver/smtp.go
Normal file
@ -0,0 +1,130 @@
|
||||
package smtpserver
|
||||
|
||||
import (
|
||||
"b612.me/starlog"
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/mail"
|
||||
"os"
|
||||
|
||||
"github.com/emersion/go-smtp"
|
||||
)
|
||||
|
||||
var addr string
|
||||
var user, pass string
|
||||
var allowAnyuser bool
|
||||
var output string
|
||||
var domain string
|
||||
|
||||
var Cmd = &cobra.Command{
|
||||
Use: "smtp",
|
||||
Short: "smtp server",
|
||||
Long: "smtp server",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
run()
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
Cmd.Flags().StringVarP(&addr, "addr", "a", "0.0.0.0:25", "smtp server listen address")
|
||||
Cmd.Flags().StringVarP(&user, "user", "u", "admin", "smtp server username")
|
||||
Cmd.Flags().StringVarP(&pass, "pass", "p", "admin", "smtp server password")
|
||||
Cmd.Flags().BoolVarP(&allowAnyuser, "allow-anyuser", "A", false, "allow any user")
|
||||
Cmd.Flags().StringVarP(&output, "output", "o", "", "output mail to html")
|
||||
Cmd.Flags().StringVarP(&domain, "domain", "d", "localhost", "smtp server domain")
|
||||
}
|
||||
|
||||
type backend struct{}
|
||||
|
||||
func (bkd *backend) NewSession(c *smtp.Conn) (smtp.Session, error) {
|
||||
return &session{}, nil
|
||||
}
|
||||
|
||||
type session struct {
|
||||
username string
|
||||
password string
|
||||
to string
|
||||
}
|
||||
|
||||
func (s *session) AuthPlain(username, password string) error {
|
||||
s.username = username
|
||||
s.password = password
|
||||
starlog.Printf("username:%s,password:%s\n", username, password)
|
||||
if allowAnyuser {
|
||||
return nil
|
||||
} else {
|
||||
if username != user || password != pass {
|
||||
return smtp.ErrAuthFailed
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *session) Mail(from string, opts *smtp.MailOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *session) Rcpt(to string, opts *smtp.RcptOptions) error {
|
||||
s.to += to + ";"
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *session) Data(r io.Reader) error {
|
||||
mailData, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg, err := mail.ReadMessage(bytes.NewReader(mailData))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header := msg.Header
|
||||
subject := header.Get("Subject")
|
||||
cc := header.Get("Cc")
|
||||
bcc := header.Get("Bcc")
|
||||
from := header.Get("From") // 获取发件人
|
||||
starlog.Println("From:", from)
|
||||
starlog.Println("Subject:", subject)
|
||||
starlog.Println("Cc:", cc)
|
||||
starlog.Println("Bcc:", bcc)
|
||||
|
||||
// Read the body
|
||||
body, err := ioutil.ReadAll(msg.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
starlog.Println("Body:", string(body))
|
||||
if output != "" {
|
||||
path := output + "/" + subject + ".html"
|
||||
html := fmt.Sprintf(`<html><head><title>%s</title></head><body><h2>subject: %s</p><p>mali from: %s</p<p>mail to:%s</p>
|
||||
<p>cc:%s</p><p>bcc:%s</p><br /><p>%s</p></body></html>`, subject, subject, from, s.to, cc, bcc, string(body))
|
||||
os.WriteFile(path, []byte(html), 0644)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *session) Reset() {}
|
||||
|
||||
func (s *session) Logout() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func run() {
|
||||
flag.Parse()
|
||||
|
||||
s := smtp.NewServer(&backend{})
|
||||
|
||||
s.Addr = addr
|
||||
s.Domain = domain
|
||||
s.AllowInsecureAuth = true
|
||||
s.Debug = os.Stdout
|
||||
|
||||
starlog.Infoln("Starting SMTP server at", addr)
|
||||
starlog.Errorln(s.ListenAndServe())
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user