master
兔子 2 years ago
commit 1ea024e28f

2
.gitignore vendored

@ -0,0 +1,2 @@
bin
.idea

@ -0,0 +1,115 @@
package aes
import (
"errors"
"fmt"
"io"
"os"
"b612.me/starcrypto"
"b612.me/staros"
)
func EncodeStr(str string, key []byte) string {
if len(key) < 16 {
key = starcrypto.Md5(key)
} else {
key = key[:len(key)/16*16]
if len(key) > 32 {
key = key[:32]
}
}
ensdata := starcrypto.AesEncryptCFBNoBlock([]byte(str), key)
return starcrypto.Base91EncodeToString(ensdata)
}
func DecodeStr(str string, key []byte) string {
if len(key) < 16 {
key = starcrypto.Md5(key)
} else {
key = key[:len(key)/16*16]
}
strtmp := starcrypto.Base91DecodeString(str)
str = string(strtmp)
return string(starcrypto.AesDecryptCFBNoBlock([]byte(str), key))
}
func EncodeFile(fpath, out string, key []byte) error {
if len(key) < 16 {
key = starcrypto.Md5(key)
} else {
key = key[:len(key)/16*16]
}
if !staros.Exists(fpath) {
return errors.New("SrcFile Not Exists")
}
fpsrc, err := os.Open(fpath)
if err != nil {
return err
}
defer fpsrc.Close()
fpdst, err := os.Create(out)
if err != nil {
return err
}
defer fpdst.Close()
bufsize := 1024 * 1024 //1MB
stat, _ := fpsrc.Stat()
buf := make([]byte, bufsize)
var sumAll int64
for {
n, err := fpsrc.Read(buf)
if err != nil && err != io.EOF {
return err
}
fmt.Printf("已完成:%.2f%%\r", float64(sumAll)/float64(stat.Size())*100)
sumAll += int64(n)
encodeBytes := starcrypto.AesEncryptCFBNoBlock(buf[:n], key)
fpdst.Write(encodeBytes)
if err == io.EOF {
fmt.Print("已完成100% \n")
break
}
}
return nil
}
func DecodeFile(fpath, out string, key []byte) error {
if len(key) < 16 {
key = starcrypto.Md5(key)
} else {
key = key[:len(key)/16*16]
}
if !staros.Exists(fpath) {
return errors.New("SrcFile Not Exists")
}
fpsrc, err := os.Open(fpath)
if err != nil {
return err
}
defer fpsrc.Close()
fpdst, err := os.Create(out)
if err != nil {
return err
}
defer fpdst.Close()
bufsize := 1024 * 1024 //1MB
stat, _ := fpsrc.Stat()
buf := make([]byte, bufsize)
var sumAll int64
for {
n, err := fpsrc.Read(buf)
if err != nil && err != io.EOF {
return err
}
fmt.Printf("已完成:%.2f%%\r", float64(sumAll)/float64(stat.Size())*100)
sumAll += int64(n)
encodeBytes := starcrypto.AesDecryptCFBNoBlock(buf[:n], key)
fpdst.Write(encodeBytes)
if err == io.EOF {
fmt.Print("已完成100% \n")
break
}
}
return nil
}

@ -0,0 +1,20 @@
package aes
import (
"fmt"
"testing"
"b612.me/starcrypto"
)
func Test_EncodeStr(t *testing.T) {
//fmt.Println(EncodeStr("我喜欢你", "sakurasaiteruyogugugug"))
}
func Test_DecodeStr(t *testing.T) {
//fmt.Println(DecodeStr("Z_8aILbog@Kjm$P", "sakurasaiteruyogugugug"))
}
func Test_Base91(t *testing.T) {
fmt.Println(starcrypto.Base91EncodeToString([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}))
}

@ -0,0 +1,93 @@
package aes
import (
"encoding/hex"
"fmt"
"os"
"path/filepath"
"b612.me/starcrypto"
"b612.me/starlog"
"b612.me/staros"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "aes-cfb",
Short: "使用aes-cfb处理文件或字符串",
Long: "使用aes-cfb处理文件或字符串",
Run: func(this *cobra.Command, args []string) {
var err error
ok, _ := this.Flags().GetBool("file")
de, _ := this.Flags().GetBool("decode")
key, _ := this.Flags().GetString("key")
keyfile, _ := this.Flags().GetString("keyfile")
if len(key) == 0 && len(keyfile) == 0 {
starlog.Errorln("请指定指定Key或KeyFile")
os.Exit(1)
}
if len(key) != 0 && len(keyfile) != 0 {
starlog.Errorln("不能同时指定Key与KeyFile")
os.Exit(1)
}
if len(args) != 1 {
starlog.Criticalln("参数不足,请输入文件地址或字符串")
this.Help()
os.Exit(2)
}
var byteKey []byte
if len(key) != 0 {
byteKey = []byte(key)
} else {
if !staros.Exists(keyfile) {
starlog.Errorln("keyfile不存在", keyfile)
os.Exit(3)
}
fmt.Println("读取Key文件中……")
tmpstr, err := starcrypto.FileSum(keyfile, "sha256", func(ok float64) { fmt.Printf("完成读取%.2f\r", ok) })
if err != nil {
starlog.Errorln("keyfile读取失败", err)
os.Exit(4)
}
fmt.Println()
byteKey, _ = hex.DecodeString(tmpstr)
}
if ok {
path, _ := this.Flags().GetString("out")
if path == "" {
ext := filepath.Ext(args[0])
if ext != "" {
path = args[0][:len(args[0])-len(ext)] + ".aescfb" + ext
} else {
path = args[0] + ".aescfb"
}
}
if !de {
err = EncodeFile(args[0], path, byteKey)
} else {
err = DecodeFile(args[0], path, byteKey)
}
} else {
if !de {
data := EncodeStr(args[0], byteKey)
fmt.Println(data)
} else {
data := DecodeStr(args[0], byteKey)
fmt.Println(string(data))
}
}
if err != nil {
starlog.Criticalln(err)
return
}
},
}
func init() {
Cmd.Flags().BoolP("file", "f", false, "aes-cfb处理文件")
Cmd.Flags().StringP("out", "o", "", "文件加解密输出地址")
Cmd.Flags().StringP("key", "k", "", "加解密Key字符串")
Cmd.Flags().StringP("keyfile", "s", "", "加解密Key文件不能与key字符串同时选择")
Cmd.Flags().BoolP("decode", "d", false, "进行aes-cfb解码")
}

@ -0,0 +1,78 @@
package attach
import (
"io"
"os"
"b612.me/starlog"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "attach",
Short: "合并多个文件",
Long: "合并多个文件",
Run: func(this *cobra.Command, args []string) {
src, _ := this.Flags().GetStringArray("src")
out, _ := this.Flags().GetString("out")
if len(src) < 2 || out == "" {
starlog.Criticalln("请输入至少2个输入路径一个输出路径")
os.Exit(1)
}
os.Exit(runAttach(src, out))
},
}
func runAttach(src []string, out string) int {
fpOut, err := os.Create(out)
if err != nil {
starlog.Errorln("Err:无法创建输出文件!", err)
return 2
}
defer fpOut.Close()
for _, file := range src {
fpFile, err := os.OpenFile(file, os.O_RDONLY, 0644)
if err != nil {
starlog.Errorln("Err:Cannot Openfile:", err)
return 3
}
stats, err := fpFile.Stat()
if err != nil {
starlog.Errorln("Err:Cannot Get File Stats:", err)
return 4
}
if stats.Size() == 0 {
starlog.Warningf("文件:%s为空文件跳过\n", stats.Name())
continue
}
buf := make([]byte, 65535)
sumAll := 0
for {
n, err := fpFile.Read(buf)
if err != nil && err != io.EOF {
starlog.Errorln("Err:Error Occured While ReadFile:", err)
fpFile.Close()
return 5
}
sumAll += n
_, errW := fpOut.Write(buf[:n])
if errW != nil {
starlog.Errorln("Error While Write Data to OutFile", errW)
return 6
}
starlog.StdPrintf([]starlog.Attr{starlog.FgGreen}, "文件%s已完成%.2f%%\r", stats.Name(), (float64(sumAll) / float64(stats.Size()) * 100.0000))
if err == io.EOF {
starlog.StdPrintf([]starlog.Attr{starlog.FgGreen}, "文件:%v已完成100.00%% \n", stats.Name())
fpFile.Close()
break
}
}
}
starlog.StdPrintln([]starlog.Attr{starlog.FgGreen}, "Ok!文件合并完成")
return 0
}
func init() {
Cmd.Flags().StringArrayP("src", "s", []string{}, "源文件路径")
Cmd.Flags().StringP("out", "o", "", "输出文件路径")
}

@ -0,0 +1,68 @@
package base64
import (
"fmt"
"path/filepath"
"b612.me/starcrypto"
"b612.me/starlog"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "base64",
Short: "使用base64处理文件或字符串",
Long: "使用base64处理文件或字符串",
Run: func(this *cobra.Command, args []string) {
var err error
ok, _ := this.Flags().GetBool("file")
de, _ := this.Flags().GetBool("decode")
if len(args) != 1 {
starlog.Criticalln("参数不足,请输入文件地址或字符串")
this.Help()
return
}
shell := func(pect float64) {
if pect == 100 {
fmt.Println("已处理100.000000%")
} else {
fmt.Printf("已处理:%f%%\r", pect)
}
}
if ok {
path, _ := this.Flags().GetString("out")
if path == "" {
ext := filepath.Ext(args[0])
if ext != "" {
path = args[0][:len(args[0])-len(ext)] + ".b64" + ext
} else {
path = args[0] + ".b64"
}
}
if !de {
err = starcrypto.Base64EncodeFile(args[0], path, shell)
} else {
err = starcrypto.Base64DecodeFile(args[0], path, shell)
}
} else {
if !de {
data := starcrypto.Base64Encode([]byte(args[0]))
fmt.Println(data)
} else {
var data []byte
data, err = starcrypto.Base64Decode(args[0])
fmt.Println(string(data))
}
}
if err != nil {
starlog.Criticalln(err)
return
}
},
}
func init() {
Cmd.Flags().BoolP("file", "f", false, "base64处理文件")
Cmd.Flags().StringP("out", "o", "", "指定加解码输出地址")
Cmd.Flags().BoolP("decode", "d", false, "base64解码")
}

@ -0,0 +1,67 @@
package base85
import (
"fmt"
"path/filepath"
"b612.me/starcrypto"
"b612.me/starlog"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "base85",
Short: "使用base85处理文件或字符串",
Long: "使用base85处理文件或字符串",
Run: func(this *cobra.Command, args []string) {
var err error
ok, _ := this.Flags().GetBool("file")
de, _ := this.Flags().GetBool("decode")
if len(args) != 1 {
starlog.Criticalln("参数不足,请输入文件地址或字符串")
return
}
shell := func(pec float64) {
if pec == 100 {
fmt.Println("已处理100.000000%")
} else {
fmt.Printf("已处理:%f%%\r", pec)
}
}
if ok {
path, _ := this.Flags().GetString("out")
if path == "" {
ext := filepath.Ext(args[0])
if ext != "" {
path = args[0][:len(args[0])-len(ext)] + ".b85" + ext
} else {
path = args[0] + ".b85"
}
}
if !de {
err = starcrypto.Base85EncodeFile(args[0], path, shell)
} else {
err = starcrypto.Base85DecodeFile(args[0], path, shell)
}
} else {
if !de {
data := starcrypto.Base85Encode([]byte(args[0]))
fmt.Println(data)
} else {
var data []byte
data, err = starcrypto.Base85Decode(args[0])
fmt.Println(string(data))
}
}
if err != nil {
starlog.Criticalln(err)
return
}
},
}
func init() {
Cmd.Flags().BoolP("file", "f", false, "base85处理文件")
Cmd.Flags().StringP("out", "o", "", "指定加解码输出地址")
Cmd.Flags().BoolP("decode", "d", false, "base85解码")
}

@ -0,0 +1,35 @@
package base91
import (
"fmt"
"b612.me/starcrypto"
"b612.me/starlog"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "base91",
Short: "使用base91处理文件或字符串",
Long: "使用base91处理文件或字符串",
Run: func(this *cobra.Command, args []string) {
de, _ := this.Flags().GetBool("decode")
if len(args) != 1 {
starlog.Criticalln("参数不足,请输入文件地址或字符串")
return
}
if !de {
data := starcrypto.Base91EncodeToString([]byte(args[0]))
fmt.Println(data)
} else {
var data []byte
data = starcrypto.Base91DecodeString(args[0])
fmt.Println(string(data))
}
},
}
func init() {
Cmd.Flags().StringP("out", "o", "", "指定加解码输出地址")
Cmd.Flags().BoolP("decode", "d", false, "base91解码")
}

@ -0,0 +1,38 @@
mkdir bin
set GOOS=windows
set GOARCH=amd64
go build -o .\bin\b612_x86_64.exe -ldflags "-w -s" .
upx -9 .\bin\b612_x86_64.exe
set GOARCH=386
go build -o .\bin\b612_x86.exe -ldflags "-w -s" .
upx -9 .\bin\b612_x86.exe
set GOARCH=arm64
go build -o .\bin\b612_arm64.exe -ldflags "-w -s" .
upx -9 .\bin\b612_arm64.exe
set GOOS=linux
set GOARCH=amd64
go build -o .\bin\b612_x86_64 -ldflags "-w -s" .
upx -9 .\bin\b612_x86_64
set GOARCH=386
go build -o .\bin\b612_x86 -ldflags "-w -s" .
upx -9 .\bin\b612_x86
set GOARCH=arm64
go build -o .\bin\b612_arm64 -ldflags "-w -s" .
upx -9 .\bin\b612_arm64
set GOARCH=mips
go build -o .\bin\b612_mips -ldflags "-w -s" .
set GOARCH=mipsle
go build -o .\bin\b612_mipsle -ldflags "-w -s" .
set GOARCH=mips64
go build -o .\bin\b612_mips64 -ldflags "-w -s" .
set GOARCH=mips64le
go build -o .\bin\b612_mips64le -ldflags "-w -s" .
set GOOS=darwin
set GOARCH=amd64
go build -o .\bin\b612_darwin_x64 -ldflags "-w -s" .
upx -9 .\bin\b612_darwin_x64
set GOARCH=arm64
go build -o .\bin\b612_darwin_arm64 -ldflags "-w -s" .
upx -9 .\bin\b612_darwin_arm64

@ -0,0 +1,46 @@
package detach
import (
"b612.me/starcrypto"
"fmt"
"b612.me/starlog"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "detach",
Short: "分离两个文件",
Long: "分离两个文件",
Run: func(this *cobra.Command, args []string) {
var src, dst, out string
if len(args) == 3 {
src = args[0]
dst = args[1]
out = args[2]
} else {
src, _ = this.Flags().GetString("src")
dst, _ = this.Flags().GetString("dst")
out, _ = this.Flags().GetString("out")
}
num, _ := this.Flags().GetInt("num")
if src == "" || dst == "" {
starlog.Criticalln("ERROR PATH")
this.Help()
return
}
err := starcrypto.Detach(src, num, dst, out)
if err != nil {
starlog.Criticalln(err.Error)
} else {
fmt.Println("完成")
}
},
}
func init() {
Cmd.Flags().StringP("src", "s", "", "源文件路径")
Cmd.Flags().StringP("dst", "d", "", "目标文件路径1")
Cmd.Flags().StringP("out", "o", "", "目标文件路径2")
Cmd.Flags().IntP("num", "n", 0, "分割开始字节")
}

@ -0,0 +1,116 @@
package df
import (
"b612.me/starlog"
"b612.me/staros"
"b612.me/wincmd/ntfs/mft"
"fmt"
"github.com/spf13/cobra"
"io/ioutil"
"math"
"os"
"path/filepath"
"sort"
"strings"
)
var Cmd = &cobra.Command{
Use: "df",
Short: "分析nfts磁盘文件占用",
Long: "分析nfts磁盘文件占用",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
os.Exit(folderSize("./"))
}
os.Exit(folderSize(args[0]))
},
}
func folderSize(path string) int {
fullPath, err := filepath.Abs(path)
if err != nil {
starlog.Criticalln("filepath not a vaild path", path, err)
return 1
}
vol := filepath.VolumeName(fullPath) + `\`
fmt.Println(vol)
if staros.IsFile(fullPath) {
fullPath = filepath.Dir(fullPath)
}
fmt.Println("consider folder is", fullPath)
folderLists, err := ioutil.ReadDir(fullPath)
if err != nil {
starlog.Criticalln("read folder failed", err)
return 2
}
targetFolders := make(map[string]uint64)
for _, v := range folderLists {
if v.IsDir() {
//fmt.Println(filepath.Join(fullPath, v.Name()))
targetFolders[filepath.Join(fullPath, v.Name())] = 0
}
}
fileLists, err := mft.GetFileListsByMft(vol)
if err != nil {
starlog.Errorln("read mft failed", err)
return 3
}
var totalSize uint64
var fc1, fc2 int
for _, v := range fileLists {
if strings.Contains(v.Path, fullPath) {
if v.IsDir {
fc2++
} else {
fc1++
}
totalSize += v.Aszie
}
for k, _ := range targetFolders {
if strings.Contains(v.Path, k) {
targetFolders[k] += v.Aszie
}
}
}
getSize := func(size uint64) string {
floatSize := float64(size)
var sizeC = []string{"byte", "KB", "MB", "GB", "TB"}
if floatSize < 1024 {
return ""
}
for i := 0; i < 4; i++ {
if floatSize/math.Pow(1024, float64(i+1)) < 1024 {
return fmt.Sprintf("%.4f%s", floatSize/math.Pow(1024, float64(i+1)), sizeC[i+1])
}
}
return ""
}
target := sortMapByValue(targetFolders)
for _, v := range target {
fmt.Printf("%-20s %-10d %s\n", v.Key, v.Value, getSize(v.Value))
}
fmt.Printf("%-20s %-10d %s\n", fullPath, totalSize, getSize(totalSize))
fmt.Println("file count:", fc1, "folder count:", fc2)
return 0
}
type Pair struct {
Key string
Value uint64
}
type PairList []Pair
func (p PairList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p PairList) Len() int { return len(p) }
func (p PairList) Less(i, j int) bool { return p[i].Value < p[j].Value }
func sortMapByValue(m map[string]uint64) PairList {
p := make(PairList, len(m))
i := 0
for k, v := range m {
p[i] = Pair{k, v}
i++
}
sort.Sort(p)
return p
}

@ -0,0 +1,113 @@
package dfinder
import (
"b612.me/starlog"
"b612.me/staros"
"b612.me/wincmd/ntfs/mft"
"fmt"
"github.com/spf13/cobra"
"math"
"os"
"path/filepath"
"regexp"
"strings"
)
var dfpath, dfreg, dfoutpath string
var dfonlyname, dfshow bool
func init() {
Cmd.Flags().StringVarP(&dfoutpath, "outpath", "o", "", "outpath")
Cmd.Flags().StringVarP(&dfpath, "path", "p", "./", "path you want to search")
Cmd.Flags().StringVarP(&dfreg, "regexp", "r", ".*", "search regexp")
Cmd.Flags().BoolVarP(&dfonlyname, "only-filter-name", "f", false, "only regexp for name not path")
Cmd.Flags().BoolVarP(&dfshow, "show", "s", true, "show on the stdout")
}
var Cmd = &cobra.Command{
Use: "dfinder",
Short: "查找nfts磁盘文件",
Long: "查找nfts磁盘文件",
Run: func(cmd *cobra.Command, args []string) {
os.Exit(fileFinder(dfpath, dfreg, dfonlyname, dfoutpath, dfshow))
},
}
func fileFinder(path string, reg string, onlyFilterName bool, outpath string, show bool) int {
fullPath, err := filepath.Abs(path)
if err != nil {
starlog.Criticalln("filepath not a vaild path", path, err)
return 1
}
vol := filepath.VolumeName(fullPath) + `\`
fmt.Println(vol)
if staros.IsFile(fullPath) {
fullPath = filepath.Dir(fullPath)
}
fmt.Println("consider folder is", fullPath)
fileLists, err := mft.GetFileListsByMftFn(vol, func(name string, isFolder bool) bool {
if isFolder {
return true
}
if onlyFilterName {
if matched, _ := regexp.MatchString(reg, name); matched {
return true
}
return false
}
return true
})
if err != nil {
starlog.Errorln("read mft failed", err)
return 3
}
getSize := func(size uint64) string {
floatSize := float64(size)
var sizeC = []string{"byte", "KB", "MB", "GB", "TB"}
if floatSize < 1024 {
return ""
}
for i := 0; i < 4; i++ {
if floatSize/math.Pow(1024, float64(i+1)) < 1024 {
return fmt.Sprintf("%.4f%s", floatSize/math.Pow(1024, float64(i+1)), sizeC[i+1])
}
}
return ""
}
fp := new(os.File)
if outpath != "" {
fp, err = os.Create(outpath)
if err != nil {
starlog.Criticalln(err)
} else {
defer fp.Close()
fp.WriteString(`名称,路径,大小,大小(格式化),修改时间,是否是文件夹` + "\n")
}
}
newReg := regexp.MustCompile(reg)
for _, v := range fileLists {
if !strings.Contains(v.Path, fullPath) {
continue
}
if onlyFilterName {
if show {
fmt.Printf("name:%-10s path:%-20s size:%-10s modTime:%v\n", v.Name, v.Path, getSize(v.Size), v.ModTime)
}
if fp != nil {
fp.WriteString(fmt.Sprintf("%s,%s,%v,%s,%v,%v\n", v.Name, v.Path, v.Size, getSize(v.Size), v.ModTime, v.IsDir))
}
} else {
if newReg.MatchString(v.Path) {
if show {
fmt.Printf("name:%-10s path:%-20s size:%-10s modTime:%v\n", v.Name, v.Path, getSize(v.Size), v.ModTime)
}
if fp != nil {
fp.WriteString(fmt.Sprintf("%s,%s,%v,%s,%v,%v\n", v.Name, v.Path, v.Size, getSize(v.Size), v.ModTime, v.IsDir))
}
}
}
}
return 0
}

@ -0,0 +1,50 @@
package ftp
import (
"log"
"path/filepath"
filedriver "github.com/goftp/file-driver"
"github.com/goftp/server"
"github.com/spf13/cobra"
)
var ports int
var username, pwd string
var path, ip string
// ftpCmd represents the ftp command
var Cmd = &cobra.Command{
Use: "ftp",
Short: `FTP文件服务器`,
Long: `FTP文件服务器`,
Run: func(cmd *cobra.Command, args []string) {
path, _ = filepath.Abs(path)
factory := &filedriver.FileDriverFactory{
RootPath: path,
Perm: server.NewSimplePerm("user", "group"),
}
opts := &server.ServerOpts{
Factory: factory,
Port: ports,
Hostname: ip,
Auth: &server.SimpleAuth{Name: username, Password: pwd},
}
log.Printf("Starting ftp server on %v:%v", opts.Hostname, opts.Port)
log.Printf("Username %v, Password %v", username, pwd)
server := server.NewServer(opts)
err := server.ListenAndServe()
if err != nil {
log.Fatal("Error starting server:", err)
}
},
}
func init() {
Cmd.Flags().IntVarP(&ports, "port", "p", 21, "监听端口")
Cmd.Flags().StringVarP(&ip, "ip", "i", "0.0.0.0", "监听地址")
Cmd.Flags().StringVarP(&username, "user", "u", "1", "用户名默认为1")
Cmd.Flags().StringVarP(&pwd, "pwd", "k", "1", "密码默认为1")
Cmd.Flags().StringVarP(&path, "folder", "f", "./", "本地文件地址")
}

@ -0,0 +1,95 @@
package generate
import (
"bufio"
"fmt"
"math/rand"
"os"
"time"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "generate",
Short: "生成随机文件",
Long: "生成指定大小的随机文件",
Run: func(this *cobra.Command, args []string) {
sum, _ := this.Flags().GetInt("sum")
num, _ := this.Flags().GetInt("num")
cap, _ := this.Flags().GetInt("cap")
if len(args) != 1 {
this.Help()
return
}
if num <= 0 {
fmt.Println("num不合法不应该小于1")
os.Exit(2)
}
if sum < 0 {
fmt.Println("sum不合法不应该小于0")
os.Exit(2)
}
if cap <= 0 {
fmt.Println("cap不合法不应该小于1")
os.Exit(2)
}
err := FillWithRandom(args[0], num, cap, sum, func(pect float64) {
fmt.Printf("文件已处理:%f%%\r", pect)
})
if err != nil {
fmt.Println("err:" + err.Error())
}
fmt.Println("文件已处理100.0000000%")
time.Sleep(time.Millisecond * 10)
},
}
func init() {
Cmd.Flags().IntP("sum", "s", 3, "随机的种子组数")
Cmd.Flags().IntP("num", "n", 1024, "生成的文件大小")
Cmd.Flags().IntP("cap", "c", 1048576, "bufcap大小")
Cmd.MarkFlagRequired("num")
}
// FillWithRandom 随机写filesize大小的文件每次buf大小为bufcap随机bufnum个字符
func FillWithRandom(filepath string, filesize int, bufcap int, bufnum int, shell func(float64)) error {
var buf [][]byte
var buftmp []byte
rand.Seed(time.Now().Unix())
if bufnum <= 0 {
bufnum = 1
}
if bufcap > filesize {
bufcap = filesize
}
myfile, err := os.Create(filepath)
if err != nil {
return err
}
defer myfile.Close()
writer := bufio.NewWriter(myfile)
for i := 0; i < bufnum; i++ {
buftmp = []byte{}
for j := 0; j < bufcap; j++ {
buftmp = append(buftmp, byte(rand.Intn(256)))
}
buf = append(buf, buftmp)
}
sum := 0
for {
if filesize-sum < bufcap {
writer.Write(buf[rand.Intn(bufnum)][0 : filesize-sum])
sum += filesize - sum
} else {
writer.Write(buf[rand.Intn(bufnum)])
sum += bufcap
}
go shell(float64(sum) / float64(filesize) * 100)
if sum >= filesize {
break
}
}
writer.Flush()
return nil
}

@ -0,0 +1,36 @@
module b612.me/apps/b612
go 1.19
require (
b612.me/notify v1.2.4
b612.me/starcrypto v0.0.2
b612.me/stario v0.0.8
b612.me/starlog v1.3.2
b612.me/staros v1.1.6
b612.me/starssh v0.0.2
b612.me/startext v0.0.0-20220314043758-22c6d5e5b1cd
b612.me/wincmd v0.0.2
github.com/goftp/file-driver v0.0.0-20180502053751-5d604a0fc0c9
github.com/goftp/server v0.0.0-20200708154336-f64f7c2d8a42
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/spf13/cobra v1.6.1
)
require (
b612.me/starmap v1.2.3 // indirect
b612.me/starnet v0.1.7 // indirect
b612.me/win32api v0.0.1 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // 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
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.0 // indirect
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 // indirect
golang.org/x/image v0.6.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/term v0.5.0 // indirect
golang.org/x/text v0.8.0 // indirect
)

108
go.sum

@ -0,0 +1,108 @@
b612.me/notify v1.2.4 h1:cjP80V9FeM+ib1DztZdykusakcbjNI4dAB1pXE8U6bo=
b612.me/notify v1.2.4/go.mod h1:SlCrG1kPRVhYUrIkwY/j0zAwCU4VeTHubcZoQXW8Anw=
b612.me/starcrypto v0.0.2 h1:aRf1HcqK8GqHYxLAhWfFC4W/EqQLEFNEmxsBu3wG30o=
b612.me/starcrypto v0.0.2/go.mod h1:hz0xRnfWNpYOlVrIPoGrQOWPibq4YiUZ7qN5tsQbzPo=
b612.me/stario v0.0.7/go.mod h1:or4ssWcxQSjMeu+hRKEgtp0X517b3zdlEOAms8Qscvw=
b612.me/stario v0.0.8 h1:kaA4pszAKLZJm2D9JmiuYSpgjTeE3VaO74vm+H0vBGM=
b612.me/stario v0.0.8/go.mod h1:or4ssWcxQSjMeu+hRKEgtp0X517b3zdlEOAms8Qscvw=
b612.me/starlog v1.3.2 h1:bFUJyZEpcOcBwPlzlhPBwlYxq7aDcR8pJNoaDk+SUNE=
b612.me/starlog v1.3.2/go.mod h1:bxSvBSzlJoLfrZJ5b9CJFuQaXjFi8PYUbGWitNO1FYA=
b612.me/starmap v1.2.3 h1:+ao++KgbSGMA4UzcHm/EXJoukbUudk8t5ac7rjwV9KA=
b612.me/starmap v1.2.3/go.mod h1:K+exTSWg8i/taoUyGR6DPW6Ja0k6aIdpcniqByOf4O0=
b612.me/starnet v0.1.7 h1:k3CUfYNRolC/xw5Ekus2NVWHlqeykSyAH8USGTPKA5o=
b612.me/starnet v0.1.7/go.mod h1:DNC4i/ezgVLlmxnquf8AeljsL4mQ5vAyxh8vGPQqsys=
b612.me/staros v1.1.6 h1:m3QaEmPyvPcJVomjWs8cDeauDYFNKv7cLHTiOHClKqM=
b612.me/staros v1.1.6/go.mod h1:O657LC3qag4VSsHNmt5RM8gKJvzoEGq8IF8WegcRgq0=
b612.me/starssh v0.0.2 h1:cYlrXjd7ZTesdZG+7XcoLsEEMROaeWMTYonScBLnvyY=
b612.me/starssh v0.0.2/go.mod h1:1gvG/GT5Y5EvOx9ZKnLFUa+wOX20HaqS1IuTnU7BOlk=
b612.me/startext v0.0.0-20220314043758-22c6d5e5b1cd h1:EsmnczYZhOV8JTxD/m0N0qBjfZN8JuLNrTJ6z3S8YqA=
b612.me/startext v0.0.0-20220314043758-22c6d5e5b1cd/go.mod h1:yKdeLQHZ3scqyjw1ZODCoL+hLmkOp2eu5riP4agraz8=
b612.me/win32api v0.0.1 h1:vLFB1xhO6pd9+zB2EyaapKB459Urv3v+C1YwgwOFEWo=
b612.me/win32api v0.0.1/go.mod h1:MHu0JBQjzxQ2yxpZPUBbn5un45o67eF5iWKa4Q9e0yE=
b612.me/wincmd v0.0.2 h1:Ub1WtelVT6a3vD4B6zDYo3UPO/t9ymnI3x1dQPJcrGw=
b612.me/wincmd v0.0.2/go.mod h1:bwpyCKfSDY8scSMo3Lrd0Qnqvpz7/CILL7oodfG0wgo=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
github.com/goftp/server v0.0.0-20200708154336-f64f7c2d8a42/go.mod h1:k/SS6VWkxY7dHPhoMQ8IdRu8L4lQtmGbhyXGg+vCnXE=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jlaffaye/ftp v0.1.0 h1:DLGExl5nBoSFoNshAUHwXAezXwXBvFdx7/qwhucWNSE=
github.com/jlaffaye/ftp v0.1.0/go.mod h1:hhq4G4crv+nW2qXtNYcuzLeOudG92Ps37HEKeg2e3lE=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/pkg/sftp v1.13.4 h1:Lb0RYJCmgUcBgZosfoi9Y9sbl6+LJgOIgk/2Y4YjMFg=
github.com/pkg/sftp v1.13.4/go.mod h1:LzqnAvaD5TWeNBsZpfKxSYn1MbjWwOsCIAFFJbpIsK8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s=
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/image v0.6.0 h1:bR8b5okrPI3g/gyZakLZHeWxAR8Dn5CyxXv1hLH5g/4=
golang.org/x/image v0.6.0/go.mod h1:MXLdDR43H7cDJq5GEGXEVeeNhPgi+YYEQ2pC1byI1x0=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

@ -0,0 +1,75 @@
package hash
import (
"b612.me/starcrypto"
"encoding/hex"
"fmt"
"os"
"b612.me/starlog"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "hash",
Short: "多种方法哈希值校验",
Long: "进行多种方法哈希值校验",
Run: func(this *cobra.Command, args []string) {
var cumethod, method []string
var result = make(map[string]string)
var err error
cumethod = []string{"md5", "crc32", "sha512", "sha384", "sha256", "sha224", "sha1"}
if ok, _ := this.Flags().GetBool("all"); ok {
method = cumethod
} else {
if len(args) == 0 {
this.Usage()
os.Exit(1)
}
for _, v := range cumethod {
if ok, _ := this.Flags().GetBool(v); ok {
method = append(method, v)
}
}
if len(method) == 0 {
method = append(method, "md5")
}
}
if ok, _ := this.Flags().GetBool("file"); ok {
result, err = starcrypto.FileSumAll(args[0], method, func(pect float64) {
if pect != 100.0 {
fmt.Printf("校验已完成:%f%%\r", pect)
} else {
fmt.Printf("校验已完成:%f%%\n", pect)
}
})
} else {
var bres map[string][]byte
bres, err = starcrypto.SumAll([]byte(args[0]), method)
if err == nil {
for k, v := range bres {
result[k] = hex.EncodeToString(v)
}
}
}
if err != nil {
starlog.Criticalln("错误:" + err.Error())
}
for _, v := range method {
fmt.Printf("%s%s\n", v, result[v])
}
},
}
func init() {
Cmd.Flags().BoolP("all", "a", false, "使用所有的校验方法")
Cmd.Flags().BoolP("file", "f", false, "对指定文件进行校验")
Cmd.Flags().BoolP("md5", "m", false, "进行MD5校验默认")
Cmd.Flags().BoolP("crc32", "c", false, "进行CRC32校验")
Cmd.Flags().BoolP("sha512", "s", false, "进行SHA512校验")
Cmd.Flags().Bool("sha384", false, "进行SHA384校验")
Cmd.Flags().Bool("sha256", false, "进行SHA256校验")
Cmd.Flags().Bool("sha224", false, "进行SHA224校验")
Cmd.Flags().Bool("sha1", false, "进行SHA1校验")
}

@ -0,0 +1,15 @@
[web1]
addr=0.0.0.0
port=9999
key=C:\\tech\b612.me.key
cert=C:\\tech\b612.me.cer
enablessl=true
reverse=/::https://www.b612.me
replace=www.b612.me::127.0.0.1:9999
inheader=Accept-Encoding::none
host=b612.me
authuser=b612
authpasswd=b612
whiteip=
blackip=
wanringpage=

@ -0,0 +1,92 @@
package httpreverse
import (
"b612.me/starlog"
"github.com/spf13/cobra"
"net/url"
"os"
"os/signal"
)
var remote, config string
var addr, key, cert, log string
var port int
var enablessl bool
var host string
func init() {
Cmd.Flags().StringVarP(&host, "host", "H", "", "host字段")
Cmd.Flags().StringVarP(&remote, "remote", "r", "", "反向代理地址")
Cmd.Flags().StringVarP(&config, "config", "C", "", "配置文件地址")
Cmd.Flags().StringVarP(&addr, "addr", "a", "0.0.0.0", "监听地址")
Cmd.Flags().StringVarP(&key, "key", "k", "", "ssl key地址")
Cmd.Flags().StringVarP(&cert, "cert", "c", "", "ssl 证书地址")
Cmd.Flags().StringVarP(&log, "log", "l", "", "log日志地址")
Cmd.Flags().BoolVarP(&enablessl, "enable-ssl", "s", false, "启用ssl")
Cmd.Flags().IntVarP(&port, "port", "p", 8080, "监听端口")
}
var Cmd = &cobra.Command{
Use: "hproxy",
Short: "Http Reverse Proxy(Http反向代理)",
Run: func(cmd *cobra.Command, args []string) {
if log != "" {
starlog.SetLogFile(log, starlog.Std, true)
}
if config != "" {
r, err := Parse(config)
if err != nil {
starlog.Errorln(err)
os.Exit(1)
}
go func() {
sig := make(chan os.Signal)
signal.Notify(sig, os.Kill, os.Interrupt)
starlog.Noticeln("Stop Due to Recv Siganl", <-sig)
r.Close()
}()
err = r.Run()
if err != nil {
starlog.Errorln("Http Reverse Proxy Exit Error", err)
os.Exit(2)
}
starlog.Infoln("Http Reverse Proxy Exit Normally")
return
}
if remote == "" {
starlog.Errorln("please enter the reverse url")
os.Exit(4)
}
u, err := url.Parse(remote)
if err != nil {
starlog.Errorln(err)
os.Exit(3)
}
reverse := ReverseConfig{
Name: "web",
Addr: addr,
Host: host,
ReverseURL: map[string]*url.URL{
"/": u,
},
Port: port,
UsingSSL: enablessl,
Key: key,
Cert: cert,
XForwardMode: 1,
}
go func() {
sig := make(chan os.Signal)
signal.Notify(sig, os.Kill, os.Interrupt)
starlog.Noticeln("Stop Due to Recv Siganl", <-sig)
reverse.Close()
}()
err = reverse.Run()
if err != nil {
starlog.Errorln("Http Reverse Proxy Exit Error", err)
os.Exit(2)
}
starlog.Infoln("Http Reverse Proxy Exit Normally")
return
},
}

@ -0,0 +1,84 @@
package httpreverse
import (
"strconv"
"strings"
)
func IPCIDR(ip string) (string, int, error) {
if !strings.Contains(ip, "/") {
return ip, 32, nil
}
tmp := strings.Split(ip, "/")
cidr, err := strconv.Atoi(tmp[1])
if err != nil {
return "", 0, err
}
intIp, err := IP2Int(tmp[0])
if err != nil {
return "", 0, err
}
ip, err = Int2IP(int((uint32(intIp) >> (32 - cidr)) << (32 - cidr)))
return ip, cidr, err
}
func IPEnd(ip string, cidr int) (string, error) {
intIp, err := IP2Int(ip)
if err != nil {
return "", err
}
ip, err = Int2IP(int(uint32(intIp) | ((uint32(4294967295) << cidr) >> cidr)))
return ip, err
}
func IPStart(ip string, cidr int) (string, error) {
intIp, err := IP2Int(ip)
if err != nil {
return "", err
}
ip, err = Int2IP(int((uint32(intIp) >> (32 - cidr)) << (32 - cidr)))
return ip, err
}
func IPInRange(cidrip, ip string) (bool, error) {
w, c, err := IPCIDR(cidrip)
if err != nil {
return false, err
}
f, _, err := IPCIDR(ip + "/" + strconv.Itoa(c))
if err != nil {
return false, err
}
return w == f, nil
}
func IPinRange2(startIP string, cidr int, ip string) (bool, error) {
f, _, err := IPCIDR(ip + "/" + strconv.Itoa(cidr))
if err != nil {
return false, err
}
return startIP == f, nil
}
func IP2Int(ipAddr string) (int, error) {
var ipNum uint32 = 0
ipFilter := strings.Split(ipAddr, ".")
for i := 0; i < len(ipFilter); i++ {
num, err := strconv.ParseUint(ipFilter[len(ipFilter)-1-i], 10, 32)
ipNum |= (uint32(num) << (8 * uint32(i)))
if err != nil {
return 0, err
}
}
return int(ipNum), nil
}
func Int2IP(intIP int) (string, error) {
var result string
var ip uint32
ip = uint32(intIP)
for i := 0; i < 4; i++ {
result += strconv.FormatUint(uint64(uint8(ip>>uint8((3-i)*8))), 10) + "."
}
return result[0 : len(result)-1], nil
}

@ -0,0 +1,174 @@
package httpreverse
import (
"b612.me/staros/sysconf"
"errors"
"io/ioutil"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"sync"
)
type ReverseConfig struct {
Name string
Addr string
ReverseURL map[string]*url.URL
Port int
UsingSSL bool
Key string
Cert string
Host string
InHeader [][2]string
OutHeader [][2]string
Cookie [][3]string //[3]string should contains path::key::value
ReplaceList [][2]string
ReplaceOnce bool
proxy map[string]*httputil.ReverseProxy
XForwardMode int //0=off 1=useremote 2=add
httpmux http.ServeMux
httpserver http.Server
basicAuthUser string
basicAuthPwd string
protectAuthPage []string
blackip map[string]int
whiteip map[string]int
warningpage string
warnpagedata []byte
}
type HttpReverseServer struct {
Config []*ReverseConfig
}
func Parse(path string) (HttpReverseServer, error) {
var res HttpReverseServer
ini := sysconf.NewIni()
err := ini.ParseFromFile(path)
if err != nil {
return res, err
}
for _, v := range ini.Data {
var ins = ReverseConfig{
Name: v.Name,
Host: v.Get("host"),
Addr: v.Get("addr"),
Port: v.Int("port"),
UsingSSL: v.Bool("enablessl"),
Key: v.Get("key"),
Cert: v.Get("cert"),
ReplaceOnce: v.Bool("replaceonce"),
XForwardMode: v.Int("xforwardmode"),
basicAuthUser: v.Get("authuser"),
basicAuthPwd: v.Get("authpasswd"),
warningpage: v.Get("warnpage"),
}
if ins.warningpage != "" {
data, err := ioutil.ReadFile(ins.warningpage)
if err != nil {
return res, err
}
ins.warnpagedata = data
}
ins.proxy = make(map[string]*httputil.ReverseProxy)
ins.ReverseURL = make(map[string]*url.URL)
for _, reverse := range v.GetAll("reverse") {
kv := strings.SplitN(reverse, "::", 2)
if len(kv) != 2 {
return res, errors.New("reverse settings not correct:" + reverse)
}
ins.ReverseURL[strings.TrimSpace(kv[0])], err = url.Parse(strings.TrimSpace(kv[1]))
if err != nil {
return res, err
}
}
for _, header := range v.GetAll("inheader") {
kv := strings.SplitN(header, "::", 2)
if len(kv) != 2 {
return res, errors.New("header settings not correct:" + header)
}
ins.InHeader = append(ins.InHeader, [2]string{strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1])})
}
for _, authpage := range v.GetAll("authpage") {
ins.protectAuthPage = append(ins.protectAuthPage, authpage)
}
ins.blackip = make(map[string]int)
for _, blackip := range v.GetAll("blackip") {
ip, cidr, err := IPCIDR(blackip)
if err != nil {
return res, err
}
ins.blackip[ip] = cidr
}
ins.whiteip = make(map[string]int)
for _, whiteip := range v.GetAll("whiteip") {
ip, cidr, err := IPCIDR(whiteip)
if err != nil {
return res, err
}
ins.whiteip[ip] = cidr
}
for _, header := range v.GetAll("outheader") {
kv := strings.SplitN(header, "::", 2)
if len(kv) != 2 {
return res, errors.New("header settings not correct:" + header)
}
ins.OutHeader = append(ins.OutHeader, [2]string{strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1])})
}
for _, cookie := range v.GetAll("cookie") {
kv := strings.SplitN(cookie, "::", 3)
if len(kv) != 3 {
return res, errors.New("cookie settings not correct:" + cookie)
}
ins.Cookie = append(ins.Cookie, [3]string{strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1]), strings.TrimSpace(kv[2])})
}
for _, replace := range v.GetAll("replace") {
kv := strings.SplitN(replace, "::", 2)
if len(kv) != 2 {
return res, errors.New("replace settings not correct:" + replace)
}
ins.ReplaceList = append(ins.ReplaceList, [2]string{strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1])})
}
res.Config = append(res.Config, &ins)
}
return res, nil
}
func (h *HttpReverseServer) Run() error {
var wg sync.WaitGroup
var mu sync.Mutex
var haveErr string
for _, v := range h.Config {
wg.Add(1)
go func(v *ReverseConfig) {
defer wg.Done()
err := v.Run()
if err != nil {
mu.Lock()
haveErr += err.Error() + "\n"
mu.Unlock()
}
}(v)
}
wg.Wait()
if haveErr != "" {
return errors.New(haveErr)
}
return nil
}
func (h *HttpReverseServer) Close() error {
var haveErr string
for _, v := range h.Config {
err := v.Close()
if err != nil {
haveErr += err.Error() + "\n"
}
}
if haveErr != "" {
return errors.New(haveErr)
}
return nil
}

@ -0,0 +1,23 @@
package httpreverse
import (
"fmt"
"testing"
)
func TestReverseParse(t *testing.T) {
data, err := Parse("./cfg.ini")
if err != nil {
t.Fatal(err)
}
fmt.Printf("%+v\n", data)
}
func TestReverse(t *testing.T) {
data, err := Parse("./cfg.ini")
if err != nil {
t.Fatal(err)
}
fmt.Printf("%+v\n", data)
data.Run()
}

@ -0,0 +1,262 @@
package httpreverse
import (
"b612.me/starlog"
"bytes"
"context"
"encoding/base64"
"fmt"
"io/ioutil"
"net/http"
"net/http/httputil"
"net/url"
"strconv"
"strings"
"time"
)
var version = "2.0.1"
func (h *ReverseConfig) Run() error {
err := h.init()
if err != nil {
return err
}
for key, proxy := range h.proxy {
h.httpmux.HandleFunc(key, func(writer http.ResponseWriter, request *http.Request) {
starlog.Infof("<%s> Req Path:%s Addr:%s UA:%s\n", h.Name, request.URL.Path, request.RemoteAddr, request.Header.Get("User-Agent"))
if !h.BasicAuth(writer, request) {
h.SetResponseHeader(writer)
return
}
if !h.filter(writer, request) {
h.SetResponseHeader(writer)
writer.WriteHeader(403)
if len(h.warnpagedata) != 0 {
writer.Write(h.warnpagedata)
return
}
writer.Write([]byte(`
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<center><h3>You Are Not Allowed to Access This Page</h3></center>
<center><h3>Please Contact Site Administrator For Help</h3></center>
<hr><center>B612 HTTP REVERSE SERVER</center>
</body>
</html>`))
return
}
proxy.ServeHTTP(writer, request)
})
}
h.httpserver = http.Server{
Addr: fmt.Sprintf("%s:%d", h.Addr, h.Port),
Handler: &h.httpmux,
}
starlog.Infoln(h.Name + " Listening on " + h.Addr + ":" + strconv.Itoa(h.Port))
if !h.UsingSSL {
if err := h.httpserver.ListenAndServe(); err != http.ErrServerClosed {
return err
}
return nil
}
if h.httpserver.ListenAndServeTLS(h.Cert, h.Key); err != http.ErrServerClosed {
return err
}
return nil
}
func (h *ReverseConfig) Close() error {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
return h.httpserver.Shutdown(ctx)
}
func (h *ReverseConfig) init() error {
h.proxy = make(map[string]*httputil.ReverseProxy)
for key, val := range h.ReverseURL {
h.proxy[key] = httputil.NewSingleHostReverseProxy(val)
h.proxy[key].ModifyResponse = h.ModifyResponse()
originalDirector := h.proxy[key].Director
h.proxy[key].Director = func(req *http.Request) {
originalDirector(req)
h.ModifyRequest(req, val)
}
}
return nil
}
func (h *ReverseConfig) SetResponseHeader(resp http.ResponseWriter) {
resp.Header().Set("X-Powered-By", "B612.ME")
resp.Header().Set("Server", "B612/"+version)
resp.Header().Set("X-Proxy", "B612 Reverse Proxy")
}
func (h *ReverseConfig) ModifyResponse() func(*http.Response) error {
return func(resp *http.Response) error {
for _, v := range h.OutHeader {
resp.Header.Set(v[0], v[1])
}
resp.Header.Del("X-Powered-By")
resp.Header.Del("Server")
resp.Header.Del("X-Proxy")
resp.Header.Set("X-Powered-By", "B612.ME")
resp.Header.Set("Server", "B612/"+version)
resp.Header.Set("X-Proxy", "B612 Reverse Proxy")
if len(h.ReplaceList) != 0 && resp.ContentLength <= 20*1024*1024 && strings.Contains(resp.Header.Get("Content-Type"), "text") {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
strBody := string(body)
replaceCount := -1
if h.ReplaceOnce {
replaceCount = 1
}
for _, v := range h.ReplaceList {
strBody = strings.Replace(strBody, v[0], v[1], replaceCount)
}
body = []byte(strBody)
resp.Body = ioutil.NopCloser(bytes.NewReader(body))
resp.ContentLength = int64(len(body))
resp.Header.Set("Content-Length", strconv.Itoa(len(body)))
}
return nil
}
}
func (h *ReverseConfig) ModifyRequest(req *http.Request, remote *url.URL) {
if h.XForwardMode == 1 {
req.Header.Set("X-Forwarded-For", strings.Split(req.RemoteAddr, ":")[0])
} else if h.XForwardMode == 2 {
xforward := strings.Split(strings.TrimSpace(req.Header.Get("X-Forwarded-For")), ",")
xforward = append(xforward, strings.Split(req.RemoteAddr, ":")[0])
req.Header.Set("X-Forwarded-For", strings.Join(xforward, ", "))
}
for _, v := range h.Cookie {
req.AddCookie(&http.Cookie{
Name: v[1],
Value: v[2],
Path: v[0],
})
}
host := h.Host
if host == "" {
host = remote.Host
}
targetQuery := remote.RawQuery
req.URL.Scheme = remote.Scheme
req.URL.Host = remote.Host
req.Host = host
req.URL.Path, req.URL.RawPath = joinURLPath(remote, req.URL)
if targetQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = targetQuery + req.URL.RawQuery
} else {
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
}
for _, v := range h.InHeader {
req.Header.Set(v[0], v[1])
}
}
func (h *ReverseConfig) GiveBasicAuth(w http.ResponseWriter) {
w.Header().Set("WWW-Authenticate", ` Basic realm="Please Enter Passwd"`)
w.WriteHeader(401)
w.Write([]byte(`
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>B612 HTTP SERVER</center>
</body>
</html>`))
}
func (h *ReverseConfig) BasicAuth(w http.ResponseWriter, r *http.Request) bool {
if h.basicAuthPwd != "" {
if len(h.protectAuthPage) != 0 {
for _, v := range h.protectAuthPage {
if !(strings.Index(r.URL.Path, v) == 0 || strings.Contains(r.URL.RawQuery, v)) {
return true
} else {
break
}
}
}
authHeader := strings.TrimSpace(r.Header.Get("Authorization"))
if len(authHeader) == 0 {
h.GiveBasicAuth(w)
return false
} else {
userAuth := base64.StdEncoding.EncodeToString([]byte(h.basicAuthUser + ":" + h.basicAuthPwd))
authStr := strings.Split(authHeader, " ")
if strings.TrimSpace(authStr[1]) != userAuth || strings.ToLower(strings.TrimSpace(authStr[0])) != "basic" {
h.GiveBasicAuth(w)
return false
}
}
}
return true
}
func (h *ReverseConfig) filter(w http.ResponseWriter, r *http.Request) bool {
if len(h.blackip) == 0 && len(h.whiteip) == 0 {
return true
}
if len(h.whiteip) != 0 {
if _, ok := h.whiteip[strings.Split(r.RemoteAddr, ":")[0]]; ok {
return true
}
for k, v := range h.whiteip {
if match, _ := IPinRange2(k, v, strings.Split(r.RemoteAddr, ":")[0]); match {
return true
}
}
return false
}
if _, ok := h.blackip[strings.Split(r.RemoteAddr, ":")[0]]; ok {
return false
}
for k, v := range h.blackip {
if match, _ := IPinRange2(k, v, strings.Split(r.RemoteAddr, ":")[0]); match {
return false
}
}
return true
}
func joinURLPath(a, b *url.URL) (path, rawpath string) {
if a.RawPath == "" && b.RawPath == "" {
return singleJoiningSlash(a.Path, b.Path), ""
}
// Same as singleJoiningSlash, but uses EscapedPath to determine
// whether a slash should be added
apath := a.EscapedPath()
bpath := b.EscapedPath()
aslash := strings.HasSuffix(apath, "/")
bslash := strings.HasPrefix(bpath, "/")
switch {
case aslash && bslash:
return a.Path + b.Path[1:], apath + bpath[1:]
case !aslash && !bslash:
return a.Path + "/" + b.Path, apath + "/" + bpath
}
return a.Path + b.Path, apath + bpath
}
func singleJoiningSlash(a, b string) string {
aslash := strings.HasSuffix(a, "/")
bslash := strings.HasPrefix(b, "/")
switch {
case aslash && bslash:
return a + b[1:]
case !aslash && !bslash:
return a + "/" + b
}
return a + b
}

@ -0,0 +1,73 @@
package httpserver
import (
"b612.me/starlog"
"b612.me/staros"
"context"
"github.com/spf13/cobra"
"os"
"os/signal"
"strings"
)
var s HttpServer
var daemon bool
func init() {
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", "./", "本地文件地址")
Cmd.Flags().StringVarP(&s.uploadFolder, "upload", "u", "", "文件上传文件夹路径")
Cmd.Flags().BoolVarP(&daemon, "daemon", "d", false, "以后台进程运行")
Cmd.Flags().StringVarP(&s.basicAuthUser, "auth", "a", "", "HTTP BASIC AUTH认证(用户名:密码)")
Cmd.Flags().StringVarP(&s.indexFile, "index", "n", "", "Index文件名如index.html")
Cmd.Flags().StringVarP(&s.logpath, "log", "l", "", "log地址")
Cmd.Flags().StringVarP(&s.cert, "ssl-cert", "c", "", "TLS证书路径")
Cmd.Flags().StringVarP(&s.key, "ssl-key", "k", "", "TLS密钥路径")
Cmd.Flags().BoolVarP(&s.disableMIME, "disablemime", "m", false, "停止解析MIME全部按下载文件处理")
Cmd.Flags().StringSliceVarP(&s.protectAuthPage, "protect-page", "P", []string{}, "Basic Auth 开启白名单")
Cmd.Flags().Bool("daeapplied", false, "")
Cmd.Flags().MarkHidden("daeapplied")
}
var Cmd = &cobra.Command{
Use: "http",
Short: "HTTP文件服务器(HTTP File Browser Server)",
Long: `HTTP文件服务器(HTTP File Browser Server)`,
Run: func(cmd *cobra.Command, args []string) {
apply, _ := cmd.Flags().GetBool("daeapplied")
if daemon && !apply {
nArgs := append(os.Args[1:], "--daeapplied")
pid, err := staros.Daemon(os.Args[0], nArgs...)
if err != nil {
starlog.Criticalln("Daemon Error:", err)
os.Exit(1)
}
starlog.StdPrintf([]starlog.Attr{starlog.FgGreen}, "Success,PID=%v\n", pid)
return
}
sig := make(chan os.Signal)
signal.Notify(sig, os.Kill, os.Interrupt)
ctx, fn := context.WithCancel(context.Background())
go func() {
starlog.Infoln("Recv Signal", <-sig)
fn()
}()
if s.basicAuthUser != "" {
tmp := strings.SplitN(s.basicAuthUser, ":", 2)
if len(tmp) != 2 {
starlog.Errorln("basic Auth should have user and password")
os.Exit(2)
}
s.basicAuthUser = strings.TrimSpace(tmp[0])
s.basicAuthPwd = tmp[1]
}
err := s.Run(ctx)
if err != nil {
starlog.Errorln("Http Server Closed by Errors", err)
os.Exit(1)
}
starlog.Infoln("Http Server Closed Normally")
},
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,467 @@
package httpserver
import (
"b612.me/starcrypto"
"b612.me/starlog"
"b612.me/staros"
"context"
"encoding/base64"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
)
var version = "2.0.0"
type HttpServerCfgs func(cfg *HttpServerCfg)
type HttpServerCfg struct {
basicAuthUser string
basicAuthPwd string
envPath string
uploadFolder string
logpath string
indexFile string
cert string
key string
addr string
port string
protectAuthPage []string
disableMIME bool
ctx context.Context
}
type HttpServer struct {
HttpServerCfg
}
func WithTLSCert(cert, key string) HttpServerCfgs {
return func(cfg *HttpServerCfg) {
cfg.key = key
cfg.cert = cert
}
}
func WithUploadFolder(path string) HttpServerCfgs {
return func(cfg *HttpServerCfg) {
cfg.uploadFolder = path
}
}
func NewHttpServer(addr, port, path string, opts ...HttpServerCfgs) *HttpServer {
var server = HttpServer{
HttpServerCfg: HttpServerCfg{
addr: addr,
port: port,
envPath: path,
},
}
for _, opt := range opts {
opt(&server.HttpServerCfg)
}
return &server
}
func (h *HttpServer) Run(ctx context.Context) error {
h.ctx = ctx
server := http.Server{
Addr: h.addr + ":" + h.port,
Handler: h,
}
go func() {
select {
case <-h.ctx.Done():
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
server.Shutdown(ctx)
}
}()
if h.logpath != "" {
starlog.SetLogFile(h.logpath, starlog.Std, true)
}
netcards, err := net.Interfaces()
if err == nil {
for _, v := range netcards {
if strings.Contains(v.Flags.String(), "up") {
addrs, err := v.Addrs()
if err == nil {
var ips []string
for _, ip := range addrs {
ips = append(ips, ip.String())
}
starlog.Noticef("Name:%s IP:%s MAC:%s\n", v.Name, strings.Join(ips, ","), v.HardwareAddr)
}
}
}
}
starlog.Infoln("Listening on " + h.addr + ":" + h.port)
if h.cert == "" {
if err := server.ListenAndServe(); err != http.ErrServerClosed {
return err
}
return nil
}
if err := server.ListenAndServeTLS(h.cert, h.key); err != http.ErrServerClosed {
return err
}
return nil
}
func (h *HttpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.Listen(w, r)
}
func (h *HttpServer) GiveBasicAuth(w http.ResponseWriter) {
w.Header().Set("WWW-Authenticate", ` Basic realm="Please Enter Passwd"`)
w.WriteHeader(401)
w.Write([]byte(`
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>B612 HTTP SERVER</center>
</body>
</html>`))
}
func (h *HttpServer) BasicAuth(log *starlog.StarLogger, w http.ResponseWriter, r *http.Request) bool {
if h.basicAuthPwd != "" {
if len(h.protectAuthPage) != 0 {
for _, v := range h.protectAuthPage {
if !(strings.Index(r.URL.Path, v) == 0 || strings.Contains(r.URL.RawQuery, v)) {
return true
} else {
break
}
}
}
authHeader := strings.TrimSpace(r.Header.Get("Authorization"))
if len(authHeader) == 0 {
log.Noticeln("No Authed! Get Path is", r.URL.Path, r.RemoteAddr)
h.GiveBasicAuth(w)
return false
} else {
userAuth := base64.StdEncoding.EncodeToString([]byte(h.basicAuthUser + ":" + h.basicAuthPwd))
authStr := strings.Split(authHeader, " ")
if strings.TrimSpace(authStr[1]) != userAuth || strings.ToLower(strings.TrimSpace(authStr[0])) != "basic" {
log.Noticeln("Auth Failed! Get Path is", r.URL.Path, r.RemoteAddr, "pwd enter is", authHeader)
h.GiveBasicAuth(w)
return false
}
log.Infof("Path %s Authoried by %s:%s\n", r.URL.Path, r.RemoteAddr, authHeader)
}
}
return true
}
func (h *HttpServer) SetUpload(w http.ResponseWriter, r *http.Request, path string) bool {
if h.uploadFolder != "" {
if len(r.URL.Query()["upload"]) != 0 {
w.Write([]byte(`<html><body><form id= "uploadForm" action= "/recv?upload=true" method= "post" enctype ="multipart/form-data">
<h1 >B612 File Upload Page </h1>
<p > <input type ="file" name="victorique" /></p>
<input type ="submit" value="上传"/>
</form>
<h2>Copyright@b612.me </h2></body></html>`))
return true
}
}
return false
}
func (h *HttpServer) Listen(w http.ResponseWriter, r *http.Request) {
log := starlog.Std.NewFlag()
w.Header().Set("X-Powered-By", "B612.ME")
w.Header().Set("Server", "B612/"+version)
if !h.BasicAuth(log, w, r) {
return
}
path := r.URL.Path
if h.uploadFolder != "" && path == "/recv" && len(r.URL.Query()["upload"]) != 0 {
h.uploadFile(w, r)
return
}
fullpath := filepath.Join(h.envPath, path)
if path == "/" && h.indexFile != "" {
if staros.Exists(filepath.Join(h.envPath, h.indexFile)) {
fullpath = filepath.Join(h.envPath, h.indexFile)
path = "/" + h.indexFile
}
}
log.Noticef("Start Method:%s Path:%s IP:%s\n", r.Method, path, r.RemoteAddr)
if h.SetUpload(w, r, path) {
return
}
switch r.Method {
case "OPTIONS", "HEAD":
err := h.BuildHeader(w, r, fullpath)
if err != nil {
log.Warningf("Finished Method:%s Path:%s IP:%s Err:%v\n", r.Method, path, r.RemoteAddr, err)
} else {
log.Infof("Finished Method:%s Path:%s IP:%s\n", r.Method, path, r.RemoteAddr)
}
case "GET":
err := h.BuildHeader(w, r, fullpath)
if err != nil {
log.Warningf("GET Header Build Failed Path:%s IP:%s Err:%v\n", path, r.RemoteAddr, err)
}
err = h.ResponseGet(log, w, r, fullpath)
if err != nil {
log.Warningf("Finished Method %s Path:%s IP:%s Err:%v\n", r.Method, path, r.RemoteAddr, err)
return
}
log.Infof("Finished Method:%s Path:%s IP:%s\n", r.Method, path, r.RemoteAddr)
default:
log.Warningf("Invalid Method %s Path:%s IP:%s\n", r.Method, path, r.RemoteAddr)
return
}
}
func (h *HttpServer) CalcRange(r *http.Request) (int64, int64) {
var rangeStart, rangeEnd int64
rangeStart, rangeEnd = -1, -1
for k, v := range r.Header {
if strings.ToLower(k) == "range" {
if strings.Contains(v[0], "bytes=") {
v[0] = strings.Replace(v[0], "bytes=", "", -1)
}
data := strings.Split(v[0], "-")
if len(data) == 0 {
break
}
rangeStart, _ = strconv.ParseInt(data[0], 10, 64)
if len(data) > 1 {
rangeEnd, _ = strconv.ParseInt(data[1], 10, 64)
}
//w.WriteHeader(206) //206 支持断点续传
break
}
}
return rangeStart, rangeEnd
}
func (h *HttpServer) BuildHeader(w http.ResponseWriter, r *http.Request, fullpath string) error {
if r.Method == "OPTIONS" {
w.Header().Set("Allow", "OPTIONS,GET,HEAD")
w.Header().Set("Content-Length", "0")
}
w.Header().Set("Date", strings.ReplaceAll(time.Now().UTC().Format("Mon, 2 Jan 2006 15:04:05 MST"), "UTC", "GMT"))
if staros.IsFolder(fullpath) {
return nil
}
mime := h.MIME(fullpath)
if h.disableMIME || mime == "" {
w.Header().Set("Content-Type", "application/download")
w.Header().Set("Content-Disposition", "attachment;filename="+filepath.Base(fullpath))
w.Header().Set("Content-Transfer-Encoding", "binary")
} else {
w.Header().Set("Content-Type", mime)
}
if staros.Exists(fullpath) {
finfo, err := os.Stat(fullpath)
if err != nil {
w.WriteHeader(502)
w.Write([]byte("Failed to Read " + fullpath + ",reason is " + err.Error()))
return err
}
w.Header().Set("Accept-Ranges", "bytes")
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" {
w.Header().Set("Content-Length", strconv.FormatInt(finfo.Size(), 10))
start, end := h.CalcRange(r)
if start != -1 {
if end == -1 {
w.Header().Set("Content-Range", `bytes `+strconv.FormatInt(start, 10)+"-"+strconv.FormatInt(finfo.Size(), 10)+"/"+strconv.FormatInt(finfo.Size(), 10))
//w.Header().Set("Content-Length", strconv.FormatInt(fpinfo.Size()-rangeStart, 10))
} else {
w.Header().Set("Content-Range", `bytes `+strconv.FormatInt(start, 10)+"-"+strconv.FormatInt(end, 10)+"/"+strconv.FormatInt(finfo.Size(), 10))
//w.Header().Set("Content-Length", strconv.FormatInt(1+rangeEnd-rangeStart, 10))
}
}
}
}
return nil
}
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)
}
return h.getFile(log, w, r, fullpath)
}
func (h *HttpServer) getFolder(log *starlog.StarLogger, w http.ResponseWriter, r *http.Request, fullpath string) error {
dir, err := ioutil.ReadDir(fullpath)
if err != nil {
log.Errorf("Read Folder %s failed:%v\n", fullpath, err)
w.WriteHeader(403)
if r.Method == "HEAD" {
return err
}
w.Write([]byte("<h1>Cannot Access!</h1>"))
}
if r.Method != "GET" {
return nil
}
w.Write([]byte("<html>\n<style>\np{margin: 2px auto}\n</style>\n<h1>B612 Http Server - " + version + "</h1>"))
if h.uploadFolder != "" {
w.Write([]byte("<a href=/b612?upload=true>Upload Web Page Is Openned!</a><br /><br />"))
}
w.Write([]byte("<hr /><pre>\n"))
if r.URL.Path != "/" {
w.Write([]byte(fmt.Sprintf("<p><a href='%s'>%s</a> %s</p>\n", r.URL.Path+"/..", "..", "上层文件夹")))
}
if r.URL.Path == "/" {
r.URL.Path = ""
} else if r.URL.Path[len(r.URL.Path)-1:] == "/" {
r.URL.Path = r.URL.Path[0 : len(r.URL.Path)-1]
}
for _, v := range dir {
if v.Name() != "." || v.Name() != ".." {
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"))))
} 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("</pre>\n</html>"))
return nil
}
func (h *HttpServer) getFile(log *starlog.StarLogger, w http.ResponseWriter, r *http.Request, fullpath string) error {
if !staros.Exists(fullpath) {
w.WriteHeader(404)
return errors.New("File Not Found! 404 ERROR")
}
//starlog.Debugln(r.Header)
startRange, endRange := h.CalcRange(r)
fp, err := os.Open(fullpath)
if err != nil {
log.Errorf("Failed to open file %s,reason:%v\n", r.URL.Path, err)
w.WriteHeader(502)
w.Write([]byte("<h1>502 SERVER ERROR</h1>"))
return err
}
defer fp.Close()
var transferData int
defer func() {
if transferData != 0 {
var tani string
tani = fmt.Sprintf("%v Byte", transferData)
if f64 := float64(transferData) / 1024; f64 > 1 {
tani = fmt.Sprintf("%v KB", f64)
if f64 = float64(f64) / 1024; f64 > 1 {
tani = fmt.Sprintf("%v MB", f64)
if f64 = float64(f64) / 1024; f64 > 1 {
tani = fmt.Sprintf("%v GB", f64)
}
}
}
log.Infof("Tranfered File %s %d bytes (%s) to remote %v\n", r.URL.Path,
transferData, tani, r.RemoteAddr)
}
}()
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
if err != nil {
log.Errorf("Transfer File %s to Remote Failed:%v\n", fullpath, err)
return err
}
}
if err != nil {
if err == io.EOF {
break
}
log.Errorln("Read File %s Failed:%v\n", fullpath, err)
return err
}
}
return nil
}
log.Debugf("206 transfer mode for %v %v\n", r.URL.Path, r.RemoteAddr)
w.WriteHeader(206)
fp.Seek(int64(startRange), 0)
count := startRange
for {
buf := make([]byte, 1048576)
n, err := fp.Read(buf)
if err != nil {
if err == io.EOF {
break
}
log.Errorf("Read File %s Failed:%v\n", r.URL.Path, err)
return err
}
if endRange == -1 {
ns, err := w.Write(buf[0:n])
transferData += ns
if err != nil {
log.Errorf("Transfer File %s to Remote Failed:%v\n", r.URL.Path, err)
return err
}
} else {
if count > endRange {
break
}
writeNum := n
if count+int64(n) > endRange {
writeNum = int(endRange - count + 1)
}
ns, err := w.Write(buf[0:writeNum])
transferData += ns
if err != nil {
log.Errorln("Transfer Error:", err)
return err
}
count += int64(n)
}
}
return nil
}
func (h *HttpServer) uploadFile(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
w.WriteHeader(200)
w.Write([]byte("USE POST METHOD!"))
return
}
r.ParseMultipartForm(10485760)
file, handler, err := r.FormFile("victorique")
if err != nil {
starlog.Errorf("Parse File From Form Failed:%v\n", err)
w.WriteHeader(502)
w.Write([]byte(err.Error()))
return
}
defer file.Close()
starlog.Noticef("Uploading %s From %s\n", handler.Filename, r.RemoteAddr)
os.MkdirAll(filepath.Join(h.envPath, h.uploadFolder), 0755)
f, err := os.OpenFile(filepath.Join(h.uploadFolder, handler.Filename), os.O_WRONLY|os.O_CREATE, 0755)
if err != nil {
starlog.Errorf("Open Local File %s Form %v Failed:%v\n", handler.Filename, r.RemoteAddr, err)
return
}
defer f.Close()
_, err = io.Copy(f, file)
if err != nil {
starlog.Errorf("Write File %s Form %v Failed:%v\n", handler.Filename, r.RemoteAddr, err)
return
}
starlog.Infof("Write File %s Form %v Finished\n", handler.Filename, r.RemoteAddr)
fmt.Fprintf(w, `<html><body><p>%v</p><h2><a href="/b612?upload=true">Return To Web Page</a></h2></body></html>`, handler.Header)
}

@ -0,0 +1,193 @@
package image
import (
"b612.me/staros"
"errors"
"image"
"io/ioutil"
"os"
"github.com/golang/freetype"
"github.com/nfnt/resize"
"image/color"
"image/draw"
_ "image/gif"
_ "image/jpeg"
"image/png"
_ "image/png"
)
func OpenImage(name string) (image.Image, error) {
if !staros.Exists(name) {
return nil, errors.New("File Not Exists")
}
fso, err := os.Open(name)
if err != nil {
return nil, err
}
img, _, err := image.Decode(fso)
if err != nil {
return nil, err
}
return img, nil
}
func MergePhoto(big, small image.Image, bigsize, smallsize uint, x, y int) image.Image {
big = resize.Resize(bigsize, bigsize, big, resize.Lanczos3)
small = resize.Resize(smallsize, smallsize, small, resize.Lanczos3)
offset := image.Pt(x, y)
b := big.Bounds()
nimg := image.NewRGBA(b)
draw.Draw(nimg, b, big, image.ZP, draw.Src)
draw.Draw(nimg, small.Bounds(), small, offset, draw.Over)
return nimg
}
func SavePhoto(path string, img image.Image) error {
imgf, err := os.Create(path)
if err != nil {
return err
}
defer imgf.Close()
return png.Encode(imgf, img)
}
func SetAlpha(img image.Image, alpha uint8) image.Image {
size := img.Bounds()
nimg := image.NewRGBA(size)
for x := 0; x < size.Dx(); x++ {
for y := 0; y < size.Dy(); y++ {
r, g, b, a := img.At(x, y).RGBA()
r = r >> 8
g = g >> 8
b = b >> 8
a = a >> 8
nimg.Set(x, y, color.NRGBA{uint8(r), uint8(g), uint8(b), alpha})
//nimg.Set(x, y, color.Alpha{alpha})
//nimg.Set(x, y, img.At(x, y))
}
}
return nimg
}
func AddText(text string, img image.Image, x, y int, dpi, size float64, colors color.RGBA, ttf string) (image.Image, error) {
if !staros.Exists(ttf) {
return nil, errors.New("File Not Exists")
}
fontbyte, err := ioutil.ReadFile(ttf)
if err != nil {
return nil, err
}
font, err := freetype.ParseFont(fontbyte)
if err != nil {
return nil, err
}
nimg, ok := img.(draw.Image)
if !ok {
size := img.Bounds()
nimg = image.NewRGBA(img.Bounds())
for x := 0; x < size.Dx(); x++ {
for y := 0; y < size.Dy(); y++ {
r, g, b, a := img.At(x, y).RGBA()
nimg.Set(x, y, color.NRGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
}
}
}
f := freetype.NewContext()
f.SetDPI(dpi)
f.SetFontSize(size)
f.SetFont(font)
f.SetClip(nimg.Bounds())
f.SetDst(nimg)
f.SetSrc(image.NewUniform(colors))
_, err = f.DrawString(text, freetype.Pt(x, y))
if err != nil {
return nil, err
}
return nimg, nil
}
type TextImg struct {
Text string
X int
Y int
Dpi float64
Size float64
Color color.NRGBA
}
type TextList struct {
List []TextImg
TTF []byte
}
func AddListTests(list TextList, img image.Image) (image.Image, error) {
font, err := freetype.ParseFont(list.TTF)
if err != nil {
return nil, err
}
nimg, ok := img.(draw.Image)
if !ok {
size := img.Bounds()
nimg = image.NewRGBA(img.Bounds())
for x := 0; x < size.Dx(); x++ {
for y := 0; y < size.Dy(); y++ {
r, g, b, a := img.At(x, y).RGBA()
nimg.Set(x, y, color.NRGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
}
}
}
for _, v := range list.List {
f := freetype.NewContext()
f.SetDPI(v.Dpi)
f.SetFontSize(v.Size)
f.SetFont(font)
f.SetClip(nimg.Bounds())
f.SetDst(nimg)
f.SetSrc(image.NewUniform(v.Color))
_, err = f.DrawString(v.Text, freetype.Pt(v.X, v.Y))
if err != nil {
return nil, err
}
}
return nimg, nil
}
func AddTexts(text string, img image.Image, x, y int, dpi, size float64, colors color.NRGBA, ttf string) (image.Image, error) {
if !staros.Exists(ttf) {
return nil, errors.New("File Not Exists")
}
fontbyte, err := ioutil.ReadFile(ttf)
if err != nil {
return nil, err
}
font, err := freetype.ParseFont(fontbyte)
if err != nil {
return nil, err
}
nimg, ok := img.(draw.Image)
if !ok {
size := img.Bounds()
nimg = image.NewRGBA(img.Bounds())
for x := 0; x < size.Dx(); x++ {
for y := 0; y < size.Dy(); y++ {
r, g, b, a := img.At(x, y).RGBA()
nimg.Set(x, y, color.NRGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
}
}
}
f := freetype.NewContext()
f.SetDPI(dpi)
f.SetFontSize(size)
f.SetFont(font)
f.SetClip(nimg.Bounds())
f.SetDst(nimg)
f.SetSrc(image.NewUniform(colors))
_, err = f.DrawString(text, freetype.Pt(x, y))
if err != nil {
return nil, err
}
return nimg, nil
}

@ -0,0 +1,82 @@
package image
import (
"fmt"
"image"
"b612.me/starlog"
"github.com/spf13/cobra"
)
func init() {
Cmd.AddCommand(imgMirrorCmd)
}
var Cmd = &cobra.Command{
Use: "image",
Short: "图像处理",
Long: "简单的图像处理工具",
Run: func(this *cobra.Command, args []string) {
this.Help()
},
}
var imgMirrorCmd = &cobra.Command{
Use: "mirror",
Short: "图像镜像翻转",
Long: "图像镜像翻转<水平>",
Run: func(this *cobra.Command, args []string) {
if len(args) == 0 {
starlog.Errorln("请指定需要转换的图像!")
return
}
for _, v := range args {
img, err := OpenImage(v)
if err != nil {
starlog.Errorln(err, v)
continue
}
size := img.Bounds()
nimg := image.NewRGBA(size)
for x := 0; x < size.Dx(); x++ {
for y := 0; y < size.Dy(); y++ {
nimg.Set(size.Dx()-x, y, img.At(x, y))
}
}
if err := SavePhoto(v, nimg); err != nil {
starlog.Errorln(err, v)
continue
} else {
fmt.Println(v, "转换已完成!")
}
}
fmt.Println("任务完成!")
},
}
var imgAlpha = &cobra.Command{
Use: "alpha",
Short: "设置透明度",
Long: "设置alpha通道透明度",
Run: func(this *cobra.Command, args []string) {
if len(args) == 0 {
starlog.Errorln("请指定需要转换的图像!")
return
}
for _, v := range args {
img, err := OpenImage(v)
if err != nil {
starlog.Errorln(err, v)
continue
}
img = SetAlpha(img, 4)
if err := SavePhoto(v, img); err != nil {
starlog.Errorln(err, v)
continue
} else {
fmt.Println(v, "转换已完成!")
}
}
fmt.Println("任务完成!")
},
}

@ -0,0 +1,39 @@
package main
import (
"b612.me/apps/b612/attach"
"b612.me/apps/b612/base64"
"b612.me/apps/b612/base85"
"b612.me/apps/b612/base91"
"b612.me/apps/b612/detach"
"b612.me/apps/b612/df"
"b612.me/apps/b612/dfinder"
"b612.me/apps/b612/ftp"
"b612.me/apps/b612/generate"
"b612.me/apps/b612/hash"
"b612.me/apps/b612/httpreverse"
"b612.me/apps/b612/httpserver"
"b612.me/apps/b612/image"
"b612.me/apps/b612/merge"
"b612.me/apps/b612/search"
"b612.me/apps/b612/split"
"b612.me/apps/b612/tcping"
"b612.me/apps/b612/uac"
"b612.me/apps/b612/vic"
"github.com/spf13/cobra"
)
var cmdRoot = &cobra.Command{
Use: "b612",
Version: "2.0.1",
}
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)
}
func main() {
cmdRoot.Execute()
}

@ -0,0 +1,46 @@
package merge
import (
"b612.me/starcrypto"
"fmt"
"b612.me/starlog"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "merge",
Short: "合并文件",
Long: "按路径自动合并分割的文件",
Run: func(this *cobra.Command, args []string) {
var src, dst string
if len(args) == 2 {
src = args[0]
dst = args[1]
} else {
src, _ = this.Flags().GetString("src")
dst, _ = this.Flags().GetString("dst")
}
if src == "" || dst == "" {
this.Help()
return
}
err := starcrypto.MergeFile(src, dst, func(pect float64) {
if pect == 100 {
fmt.Println("文件已处理100.000000%")
} else {
fmt.Printf("文件已处理:%f%%\r", pect)
}
})
if err != nil {
starlog.Errorln(err.Error)
}
},
}
func init() {
Cmd.Flags().StringP("src", "s", "", "源文件地址,用*替换文件数字")
Cmd.Flags().StringP("dst", "d", "", "目标文件地址")
}

@ -0,0 +1 @@
package net

@ -0,0 +1,213 @@
package net
import (
"b612.me/starlog"
"context"
"errors"
"fmt"
"io"
"net"
"sync"
"sync/atomic"
"time"
)
type NetForward struct {
LocalAddr string
LocalPort int
RemoteURI string
EnableTCP bool
EnableUDP bool
DialTimeout time.Duration
UDPTimeout time.Duration
stopCtx context.Context
stopFn context.CancelFunc
running int32
}
func (n *NetForward) Close() {
n.stopFn()
}
func (n *NetForward) Run() error {
if !atomic.CompareAndSwapInt32(&n.running, 0, 1) {
return errors.New("already running")
}
n.stopCtx, n.stopFn = context.WithCancel(context.Background())
if n.DialTimeout == 0 {
n.DialTimeout = time.Second * 10
}
var wg sync.WaitGroup
if n.EnableTCP {
wg.Add(1)
go func() {
defer wg.Done()
n.runTCP()
}()
}
if n.EnableUDP {
wg.Add(1)
go func() {
defer wg.Done()
n.runUDP()
}()
}
wg.Wait()
return nil
}
func (n *NetForward) runTCP() error {
listen, err := net.Listen("tcp", fmt.Sprintf("%s:%d", n.LocalAddr, n.LocalPort))
if err != nil {
starlog.Errorln("Listening On Tcp Failed:", err)
return err
}
go func() {
<-n.stopCtx.Done()
listen.Close()
}()
starlog.Infof("Listening TCP on %v\n", fmt.Sprintf("%s:%d", n.LocalAddr, n.LocalPort))
for {
conn, err := listen.Accept()
if err != nil {
continue
}
log := starlog.Std.NewFlag()
log.Infof("Accept New TCP Conn from %v\n", conn.RemoteAddr().String())
go func(conn net.Conn) {
rmt, err := net.DialTimeout("tcp", n.RemoteURI, n.DialTimeout)
if err != nil {
log.Errorf("Dial Remote %s Failed:%v\n", n.RemoteURI, err)
conn.Close()
return
}
log.Infof("Connect %s <==> %s\n", conn.RemoteAddr().String(), n.RemoteURI)
Copy(rmt, conn)
log.Noticef("Connection Closed %s <==> %s", conn.RemoteAddr().String(), n.RemoteURI)
}(conn)
}
}
type UDPConn struct {
net.Conn
listen *net.UDPConn
remoteAddr *net.UDPAddr
lastbeat int64
}
func (u UDPConn) Write(p []byte) (n int, err error) {
u.lastbeat = time.Now().Unix()
return u.Conn.Write(p)
}
func (u UDPConn) Read(p []byte) (n int, err error) {
u.lastbeat = time.Now().Unix()
return u.Conn.Read(p)
}
func (u UDPConn) Work() {
buf := make([]byte, 8192)
for {
count, err := u.Read(buf)
if err != nil {
u.Close()
u.lastbeat = 0
return
}
_, err = u.listen.Write(buf[0:count])
if err != nil {
u.lastbeat = 0
return
}
}
}
func (n *NetForward) runUDP() error {
var mu sync.RWMutex
udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%v", n.LocalAddr, n.LocalPort))
if err != nil {
return err
}
listen, err := net.ListenUDP("udp", udpAddr)
if err != nil {
return err
}
starlog.Infof("Listening UDP on %v\n", fmt.Sprintf("%s:%d", n.LocalAddr, n.LocalPort))
go func() {
<-n.stopCtx.Done()
listen.Close()
}()
udpMap := make(map[string]UDPConn)
go func() {
for {
select {
case <-n.stopCtx.Done():
return
case <-time.After(time.Second * 60):
mu.Lock()
for k, v := range udpMap {
if time.Now().Unix() > int64(n.UDPTimeout.Seconds())+v.lastbeat {
delete(udpMap, k)
starlog.Noticef("Connection Closed %s <==> %s", v.remoteAddr.String(), n.RemoteURI)
}
}
mu.Unlock()
}
}
}()
buf := make([]byte, 8192)
for {
count, rmt, err := listen.ReadFromUDP(buf)
if err != nil || rmt.String() == n.RemoteURI {
continue
}
go func(data []byte, rmt *net.UDPAddr) {
log := starlog.Std.NewFlag()
mu.Lock()
addr, ok := udpMap[rmt.String()]
if !ok {
log.Infof("Accept New UDP Conn from %v\n", rmt.String())
conn, err := net.Dial("udp", n.RemoteURI)
if err != nil {
log.Errorf("Dial Remote %s Failed:%v\n", n.RemoteURI, err)
mu.Unlock()
return
}
addr = UDPConn{
Conn: conn,
remoteAddr: rmt,
listen: listen,
lastbeat: time.Now().Unix(),
}
udpMap[rmt.String()] = addr
go addr.Work()
log.Infof("Connect %s <==> %s\n", rmt.String(), n.RemoteURI)
}
mu.Unlock()
_, err := addr.Write(data)
if err != nil {
mu.Lock()
addr.Close()
delete(udpMap, addr.remoteAddr.String())
mu.Unlock()
log.Noticef("Connection Closed %s <==> %s", rmt.String(), n.RemoteURI)
}
}(buf[0:count], rmt)
}
}
func Copy(dst, src net.Conn) {
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
io.Copy(dst, src)
}()
go func() {
defer wg.Done()
io.Copy(src, dst)
}()
wg.Wait()
dst.Close()
src.Close()
}

@ -0,0 +1,16 @@
package net
import "testing"
func TestForward(t *testing.T) {
var f = NetForward{
LocalAddr: "127.0.0.1",
LocalPort: 22232,
RemoteURI: "127.0.0.1:1127",
EnableTCP: true,
EnableUDP: true,
DialTimeout: 0,
UDPTimeout: 0,
}
f.Run()
}

@ -0,0 +1,27 @@
package net
import (
"net"
"sync"
)
type SimpleNatClient struct {
mu sync.RWMutex
cmdTCPConn net.Conn
cmdUDPConn *net.UDPAddr
ServiceTarget string
CmdTarget string
tcpAlived bool
}
func (s *SimpleNatClient) tcpCmdConn() net.Conn {
s.mu.RLock()
defer s.mu.RUnlock()
return s.cmdTCPConn
}
func (s *SimpleNatClient) tcpCmdConnAlived() bool {
s.mu.RLock()
defer s.mu.RUnlock()
return s.tcpAlived
}

@ -0,0 +1,138 @@
package net
import (
"b612.me/starlog"
"bytes"
"errors"
"fmt"
"io"
"net"
"strings"
"sync"
"time"
)
var MSG_CMD_HELLO = []byte{11, 27, 19, 96, 182, 18, 25, 150, 17, 39}
var MSG_NEW_CONN = []byte{0, 0, 0, 0, 255, 255, 255, 255, 11, 27}
var MSG_NEW_CONN_REQ = []byte{0, 0, 0, 0, 255, 255, 255, 255, 19, 96}
var MSG_CLOSE = []byte{255, 255, 0, 0, 255, 0, 0, 255, 255, 27}
var MSG_HEARTBEAT = []byte{6, 66, 66, 6, 6, 66, 6, 66, 11, 27}
type SimpleNatServer struct {
mu sync.RWMutex
cmdTCPConn net.Conn
cmdUDPConn *net.UDPAddr
listenTcp net.Listener
listenUDP *net.UDPConn
Addr string
Port int
lastTCPHeart int64
lastUDPHeart int64
Passwd string
DialTimeout int64
UDPTimeout int64
running int32
tcpConnPool chan net.Conn
tcpAlived bool
}
func (s *SimpleNatServer) getConnfromTCPPool() (net.Conn, error) {
select {
case conn := <-s.tcpConnPool:
return conn, nil
case <-time.After(time.Second * 10):
return nil, errors.New("no connection got")
}
}
func (s *SimpleNatServer) tcpCmdConn() net.Conn {
s.mu.RLock()
defer s.mu.RUnlock()
return s.cmdTCPConn
}
func (s *SimpleNatServer) tcpCmdConnAlived() bool {
s.mu.RLock()
defer s.mu.RUnlock()
return s.tcpAlived
}
func (s *SimpleNatServer) listenTCP() error {
var err error
s.tcpConnPool = make(chan net.Conn, 10)
s.listenTcp, err = net.Listen("tcp", fmt.Sprintf("%s:d", s.Addr, s.Port))
if err != nil {
starlog.Errorln("failed to listen tcp", err)
return err
}
for {
conn, err := s.listenTcp.Accept()
if err != nil {
continue
}
if s.tcpCmdConnAlived() {
go s.tcpClientServe(conn.(*net.TCPConn))
continue
}
go s.waitingForTCPCmd(conn.(*net.TCPConn))
}
return nil
}
func (s *SimpleNatServer) tcpClientServe(conn *net.TCPConn) {
if !s.tcpCmdConnAlived() {
conn.Close()
return
}
if strings.Split(conn.RemoteAddr().String(), ":")[0] == strings.Split(s.tcpCmdConn().RemoteAddr().String(), ":")[0] {
conn.SetReadDeadline(time.Now().Add(5 * time.Second))
cmdBuf := make([]byte, 10)
if _, err := io.ReadFull(conn, cmdBuf); err == nil {
conn.SetReadDeadline(time.Time{})
if bytes.Equal(cmdBuf, MSG_NEW_CONN) {
starlog.Noticef("Nat Server Recv New Client Conn From %v\n", conn.RemoteAddr().String())
s.tcpConnPool <- conn
return
}
}
conn.SetReadDeadline(time.Time{})
}
starlog.Noticef("Nat Server Recv New Side Conn From %v\n", conn.RemoteAddr().String())
_, err := s.tcpCmdConn().Write(MSG_NEW_CONN_REQ)
if err != nil {
s.mu.Lock()
s.cmdTCPConn.Close()
s.tcpAlived = false
s.mu.Unlock()
starlog.Errorf("Failed to Write CMD To Client:%v\n", err)
return
}
reverse, err := s.getConnfromTCPPool()
if err != nil {
starlog.Errorf("Nat Server Conn to %v Closed %v\n", conn.RemoteAddr(), err)
conn.Close()
return
}
starlog.Infof("Nat Server Conn %v<==>%v Connected\n", conn.RemoteAddr(), reverse.RemoteAddr())
Copy(reverse, conn)
starlog.Warningf("Nat Server Conn %v<==>%v Closed\n", conn.RemoteAddr(), reverse.RemoteAddr())
}
func (s *SimpleNatServer) waitingForTCPCmd(conn *net.TCPConn) {
conn.SetReadDeadline(time.Now().Add(time.Duration(s.DialTimeout) * time.Second))
cmdBuf := make([]byte, 10)
if _, err := io.ReadFull(conn, cmdBuf); err != nil {
conn.Close()
return
}
if bytes.Equal(cmdBuf, MSG_CMD_HELLO) {
s.mu.Lock()
s.cmdTCPConn = conn
s.tcpAlived = true
conn.SetKeepAlive(true)
conn.SetKeepAlivePeriod(time.Second * 20)
s.mu.Unlock()
}
}

@ -0,0 +1,69 @@
package rmt
import (
"b612.me/notify"
"b612.me/notify/starnotify"
"b612.me/starlog"
"fmt"
"github.com/spf13/cobra"
"os"
"strings"
"time"
)
var (
rmtRmt string
rmtCmd RmtCmd
)
func init() {
Cmdc.Flags().StringVarP(&rmtRmt, "remote", "r", "", "Remote Address")
Cmdc.Flags().StringVarP(&rmtPol, "protocol", "o", "tcp", "Remote protocol")
Cmdc.Flags().StringVarP(&rmtCmd.Cmd, "cmd", "c", "", "command")
Cmdc.Flags().StringVarP(&rmtCmd.WorkDir, "workdir", "w", "", "workdir")
Cmdc.Flags().StringSliceVarP(&rmtCmd.Env, "env", "e", []string{}, "env")
Cmdc.Flags().BoolVarP(&rmtCmd.Daemon, "daemon", "d", false, "daemon")
Cmdc.Flags().BoolVarP(&rmtCmd.Stream, "stream", "s", false, "stream")
Cmdc.Flags().StringVarP(&rmtListenPort, "port", "p", "5780", "Remote Port")
}
var Cmdc = &cobra.Command{
Use: "rmtc",
Short: "simple remote shell client",
Run: func(cmd *cobra.Command, args []string) {
if rmtRmt == "" {
starlog.Errorln("Please Enter Remote Path")
os.Exit(1)
}
err := starnotify.NewClient("c").Connect(rmtPol, fmt.Sprintf("%s:%s", rmtRmt, rmtListenPort))
if err != nil {
starlog.Errorln("Create Remote Failed", err)
os.Exit(2)
}
starnotify.C("c").SetLink("stream", RmtSteam)
defer starnotify.C("c").Stop()
cdata, err := starnotify.C("c").SendWaitObj("cmd", rmtCmd, time.Second*3600)
if err != nil {
starlog.Errorln("Got Answer Failed:", err)
os.Exit(3)
}
data, err := cdata.Value.ToInterface()
if err != nil {
starlog.Errorln("Decode FAILED:", err)
os.Exit(4)
}
rtnData, ok := data.(RmtCmdBack)
if !ok {
starlog.Errorln("Decode FAILED2:", err)
os.Exit(5)
}
fmt.Println("Return Pid:", rtnData.RetCode)
if !rmtCmd.Stream {
fmt.Println("Return OutPut\n", rtnData.OutPut)
}
},
}
func RmtSteam(msg *notify.Message) {
fmt.Println(strings.TrimSpace(msg.Value.MustToString()))
}

@ -0,0 +1,166 @@
package rmt
import (
"b612.me/notify"
"b612.me/notify/starnotify"
"b612.me/starlog"
"b612.me/staros"
"fmt"
"github.com/spf13/cobra"
"os"
"os/signal"
"runtime"
"strings"
"time"
)
type RmtCmd struct {
Env []string
WorkDir string
Cmd string
Daemon bool
Stream bool
}
type RmtCmdBack struct {
RetCode int
OutPut string
}
var (
rmtListenPort string
rmtPol string
)
func init() {
notify.RegisterName("remoteback", RmtCmdBack{})
notify.RegisterName("remotecmd", RmtCmd{})
Cmds.Flags().StringVarP(&rmtListenPort, "port", "p", "5780", "Listen Port")
Cmds.Flags().StringVarP(&rmtPol, "protocol", "o", "tcp", "Remote protocol")
}
var Cmds = &cobra.Command{
Use: "rmts",
Short: "simple remote shell server",
Run: func(cmd *cobra.Command, args []string) {
if rmtListenPort == "" {
starlog.Errorln("Please Enter Port")
os.Exit(1)
}
err := starnotify.NewServer("s").Listen(rmtPol, "0.0.0.0:"+rmtListenPort)
if err != nil {
starlog.Errorln("Create Listener Failed", err)
os.Exit(2)
}
starnotify.S("s").SetLink("cmd", ListenAndServe)
starlog.Infoln("Service Running")
stopSig := make(chan os.Signal)
signal.Notify(stopSig, os.Kill, os.Interrupt)
<-stopSig
starlog.Noticeln("Recv Stop Sig")
starnotify.S("s").Stop()
},
}
func ListenAndServe(msg *notify.Message) {
data, err := msg.Value.ToInterface()
if err != nil {
return
}
cmd, ok := data.(RmtCmd)
if !ok {
return
}
var sysName, sysArg string = "bash", "-c"
if runtime.GOOS == "windows" {
sysName = "cmd.exe"
sysArg = "/c"
}
if cmd.Cmd == "" {
msg.ReplyObj(RmtCmdBack{
RetCode: 255,
OutPut: "Please enter the command",
})
return
}
starlog.Noticef("Recv Command:%+v\n", cmd)
var myCmd *staros.StarCmd
myCmd, err = staros.Command(sysName, sysArg, cmd.Cmd)
if err != nil {
msg.ReplyObj(RmtCmdBack{
RetCode: 255,
OutPut: err.Error(),
})
return
}
if cmd.WorkDir != "" {
myCmd.CMD.Dir = cmd.WorkDir
}
if len(cmd.Env) > 0 {
myCmd.CMD.Env = cmd.Env
}
if cmd.Daemon {
err := myCmd.Release()
if err != nil {
msg.ReplyObj(RmtCmdBack{
RetCode: 254,
OutPut: err.Error(),
})
return
}
pid := myCmd.CMD.Process.Pid
msg.ReplyObj(RmtCmdBack{
RetCode: 0,
OutPut: fmt.Sprintf("Runned,PID is %d", pid),
})
return
}
err = myCmd.Start()
if err != nil {
msg.ReplyObj(RmtCmdBack{
RetCode: 254,
OutPut: err.Error(),
})
return
}
for myCmd.IsRunning() {
time.Sleep(time.Millisecond * 10)
if cmd.Stream {
std, err := myCmd.NowAllOutput()
if err != nil {
std += "\n" + err.Error()
}
std = strings.TrimSpace(std)
if len(std) == 0 {
continue
}
msg.ClientConn.Server().SendObj(msg.ClientConn, "stream", std)
}
}
time.Sleep(time.Millisecond * 50)
if !cmd.Stream {
std := myCmd.AllStdOut()
if myCmd.AllStdErr() != nil {
std += "\n" + myCmd.AllStdErr().Error()
}
msg.ReplyObj(RmtCmdBack{
RetCode: myCmd.ExitCode(),
OutPut: std,
})
} else {
std, err := myCmd.NowAllOutput()
if err != nil {
std += "\n" + err.Error()
}
msg.ClientConn.Server().SendObj(msg.ClientConn, "stream", std)
time.Sleep(time.Millisecond * 1000)
err = msg.ReplyObj(RmtCmdBack{
RetCode: myCmd.ExitCode(),
OutPut: "",
})
if err != nil {
starlog.Warningln("Reply failed:", err)
}
}
return
}

@ -0,0 +1,98 @@
package search
import (
"b612.me/stario"
"b612.me/starlog"
"b612.me/startext"
"bufio"
"fmt"
"github.com/spf13/cobra"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strings"
)
var stFolder string
var stNum, stMax, stMin int
var stautoGBK bool
func init() {
Cmd.Flags().StringVarP(&stFolder, "folder", "f", "./", "搜索的文件夹")
Cmd.Flags().IntVarP(&stNum, "thread-num", "n", 5, "并发搜寻协程数")
Cmd.Flags().BoolVarP(&stautoGBK, "autogbk", "g", true, "自动GBK识别")
Cmd.Flags().IntVar(&stMax, "max", 0, "行最大字数")
Cmd.Flags().IntVar(&stMin, "min", 0, "行最小字数")
}
var Cmd = &cobra.Command{
Use: "st",
Short: "搜索文件中特定字符串",
Long: "搜索文件中特定字符串",
Run: func(this *cobra.Command, args []string) {
if len(args) != 2 {
starlog.Errorln("应当传入两个参数,搜寻文件后缀和搜寻文本")
os.Exit(1)
}
err := searchText(stFolder, args[0], args[1], stNum, stautoGBK, stMax, stMin)
if err != nil {
os.Exit(2)
}
return
},
}
func searchText(folder string, filematch string, text string, thread int, autoGBK bool, max, min int) error {
data, err := ioutil.ReadDir(folder)
if err != nil {
starlog.Errorln("read folder failed", folder, err)
return err
}
wg := stario.NewWaitGroup(thread)
searchFn := func(filepath string, text string) {
//starlog.Debugln("searching", filepath, text)
defer wg.Done()
fp, err := os.Open(filepath)
if err != nil {
starlog.Errorln("open file failed", filepath, err)
return
}
defer fp.Close()
reader := bufio.NewReader(fp)
count := 0
for {
origin, err := reader.ReadString('\n')
count++
if stautoGBK && startext.IsGBK([]byte(origin)) {
originByte, _ := startext.GBK2UTF8([]byte(origin))
origin = string(originByte)
}
origin = strings.TrimSpace(origin)
if max != 0 && len(origin) > max {
continue
}
if min != 0 && len(origin) < min {
continue
}
if strings.Contains(origin, text) {
fmt.Printf("file:%s line:%d matched:%s\n", filepath, count, origin)
}
if err != nil {
break
}
}
}
for _, v := range data {
if v.IsDir() {
searchText(filepath.Join(folder, v.Name()), filematch, text, thread, autoGBK, stMax, stMin)
}
filepath := filepath.Join(folder, v.Name())
if matched, _ := regexp.MatchString(filematch, filepath); matched {
wg.Add(1)
go searchFn(filepath, text)
}
}
wg.Wait()
return nil
}

@ -0,0 +1,26 @@
package sftp
import (
"b612.me/starssh"
"os"
"path"
"path/filepath"
)
func TransferFile(s *starssh.StarSSH, local, remote string, isPull, fullname bool) error {
if !fullname && !isPull {
s.ShellOne("mkdir -p " + remote)
remote = remote + "/" + filepath.Base(local)
}
if !fullname && isPull {
os.MkdirAll(local, 0755)
local = filepath.Join(local, path.Base(remote))
}
if fullname && isPull {
os.MkdirAll(filepath.Dir(local), 0755)
}
if fullname && !isPull {
os.MkdirAll(path.Dir(remote), 0755)
}
return nil
}

@ -0,0 +1,60 @@
package split
import (
"b612.me/starcrypto"
"fmt"
"strconv"
"b612.me/starlog"
"b612.me/staros"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "split",
Short: "分割文件",
Long: "按字节或文件数分割文件",
Run: func(this *cobra.Command, args []string) {
var src, dst string
var num int
if len(args) == 3 {
src = args[0]
dst = args[1]
num, _ = strconv.Atoi(args[2])
} else {
src, _ = this.Flags().GetString("src")
dst, _ = this.Flags().GetString("dst")
num, _ = this.Flags().GetInt("num")
}
if !staros.Exists(src) {
starlog.Errorln("源文件不存在")
this.Help()
return
}
if num == 0 {
starlog.Errorln("参数num不合法", "red")
this.Help()
return
}
ok, _ := this.Flags().GetBool("byte")
err := starcrypto.SplitFile(src, dst, num, !ok, func(pect float64) {
if pect == 100 {
fmt.Println("文件已处理100.000000%")
} else {
fmt.Printf("文件已处理:%f%%\r", pect)
}
})
if err != nil {
starlog.Errorln(err.Error)
}
},
}
func init() {
Cmd.Flags().StringP("src", "s", "", "源文件地址")
Cmd.Flags().StringP("dst", "d", "./split*.vicque", "目标文件地址,用*替换文件数字")
Cmd.Flags().BoolP("byte", "b", false, "按byte分割")
Cmd.Flags().IntP("num", "n", 0, "分割数/byte数")
}

@ -0,0 +1,174 @@
package tcping
import (
"fmt"
"github.com/spf13/cobra"
"os"
"os/signal"
"strconv"
"syscall"
"time"
)
var (
counter int
timeout string
interval string
sigs chan os.Signal
httpMode bool
httpHead bool
httpPost bool
httpUA string
permanent bool
dnsServer []string
)
var Cmd = &cobra.Command{
Use: "tcping",
Short: "tcp/http ping",
Long: "使用进行Tcp或Http协议进行ping探测",
Example: `
1. ping over tcp
> tcping google.com
2. ping over tcp with custom port
> tcping google.com 443
3. ping over http
> tcping -H google.com
4. ping with URI schema
> tcping http://hui.lu
`,
Run: func(cmd *cobra.Command, args []string) {
sigs = make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
if permanent && counter != 4 {
fmt.Println("不能同时指定-t与-c请检查您的输入")
return
}
if permanent {
counter = 0
}
if len(args) != 2 && len(args) != 1 {
cmd.Usage()
return
}
host := args[0]
var (
err error
port int
schema string
)
if len(args) == 2 {
port, err = strconv.Atoi(args[1])
if err != nil {
fmt.Println("端口应当为Int类型")
cmd.Usage()
return
}
schema = TCP.String()
} else {
var matched bool
schema, host, port, matched = CheckURI(host)
if !matched {
fmt.Println("不是一个合法的URI")
cmd.Usage()
return
}
}
var timeoutDuration time.Duration
if res, err := strconv.Atoi(timeout); err == nil {
timeoutDuration = time.Duration(res) * time.Millisecond
} else {
timeoutDuration, err = time.ParseDuration(timeout)
if err != nil {
fmt.Println("parse timeout failed", err)
cmd.Usage()
return
}
}
var intervalDuration time.Duration
if res, err := strconv.Atoi(interval); err == nil {
intervalDuration = time.Duration(res) * time.Millisecond
} else {
intervalDuration, err = time.ParseDuration(interval)
if err != nil {
fmt.Println("parse interval failed", err)
cmd.Usage()
return
}
}
var protocol Protocol
if httpMode {
protocol = HTTP
} else {
protocol, err = NewProtocol(schema)
if err != nil {
fmt.Println(err)
cmd.Usage()
return
}
}
if len(dnsServer) != 0 {
UseCustomeDNS(dnsServer)
}
parseHost := FormatIP(host)
target := Target{
Timeout: timeoutDuration,
Interval: intervalDuration,
Host: parseHost,
Port: port,
Counter: counter,
Protocol: protocol,
}
var pinger Pinger
switch protocol {
case TCP:
pinger = NewTCPing()
case HTTP, HTTPS:
var httpMethod string
switch {
case httpHead:
httpMethod = "HEAD"
case httpPost:
httpMethod = "POST"
default:
httpMethod = "GET"
}
pinger = NewHTTPing(httpMethod)
default:
fmt.Printf("schema: %s not support\n", schema)
cmd.Usage()
return
}
pinger.SetTarget(&target)
pingerDone := pinger.Start()
select {
case <-pingerDone:
break
case <-sigs:
break
}
fmt.Println(pinger.Result())
},
}
func init() {
Cmd.Flags().IntVarP(&counter, "counter", "c", 4, "ping的次数")
Cmd.Flags().BoolVarP(&permanent, "permanent", "t", false, "一直ping下去")
Cmd.Flags().StringVarP(&timeout, "timeout", "T", "1s", `超时时间, 单位为 "ns", "us" (or "µs"), "ms", "s", "m", "h"`)
Cmd.Flags().StringVarP(&interval, "interval", "I", "1s", `ping间隔时间, 单位为 "ns", "us" (or "µs"), "ms", "s", "m", "h"`)
Cmd.Flags().BoolVarP(&httpMode, "http", "H", false, `Use "HTTP" mode. will ignore URI Schema, force to http`)
Cmd.Flags().BoolVar(&httpHead, "head", false, `使用http head模式`)
Cmd.Flags().BoolVar(&httpPost, "post", false, `使用http post模式`)
Cmd.Flags().StringVar(&httpUA, "user-agent", "victorique/tcping", `自定义UA`)
Cmd.Flags().StringArrayVarP(&dnsServer, "dns-server", "D", nil, `使用自定义DNS服务器`)
}

@ -0,0 +1,17 @@
package tcping
import "net"
// GetIP ...
func GetIP(hostname string) string {
addrs, err := net.LookupIP(hostname)
if err != nil {
return ""
}
for _, addr := range addrs {
if ipv4 := addr.To4(); ipv4 != nil {
return ipv4.String()
}
}
return ""
}

@ -0,0 +1,120 @@
package tcping
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/httptrace"
"time"
)
// HTTPing ...
type HTTPing struct {
target *Target
done chan struct{}
result *Result
Method string
}
var _ Pinger = (*HTTPing)(nil)
// NewHTTPing return new HTTPing
func NewHTTPing(method string) *HTTPing {
return &HTTPing{
done: make(chan struct{}),
Method: method,
}
}
// SetTarget ...
func (ping *HTTPing) SetTarget(target *Target) {
ping.target = target
if ping.result == nil {
ping.result = &Result{Target: target}
}
}
// Start ping
func (ping *HTTPing) Start() <-chan struct{} {
go func() {
t := time.NewTicker(ping.target.Interval)
defer t.Stop()
for {
select {
case <-t.C:
if ping.result.Counter >= ping.target.Counter && ping.target.Counter != 0 {
ping.Stop()
return
}
duration, resp, remoteAddr, err := ping.ping()
ping.result.Counter++
if err != nil {
fmt.Printf("Ping %s - failed: %s\n", ping.target, err)
} else {
defer resp.Body.Close()
length, _ := io.Copy(ioutil.Discard, resp.Body)
fmt.Printf("Ping %s(%s) - %s is open - time=%s method=%s status=%d bytes=%d\n", ping.target, remoteAddr, ping.target.Protocol, duration, ping.Method, resp.StatusCode, length)
if ping.result.MinDuration == 0 {
ping.result.MinDuration = duration
}
if ping.result.MaxDuration == 0 {
ping.result.MaxDuration = duration
}
ping.result.SuccessCounter++
if duration > ping.result.MaxDuration {
ping.result.MaxDuration = duration
} else if duration < ping.result.MinDuration {
ping.result.MinDuration = duration
}
ping.result.TotalDuration += duration
}
case <-ping.done:
return
}
}
}()
return ping.done
}
// Result return ping result
func (ping *HTTPing) Result() *Result {
return ping.result
}
// Stop the tcping
func (ping *HTTPing) Stop() {
ping.done <- struct{}{}
}
func (ping HTTPing) ping() (time.Duration, *http.Response, string, error) {
var resp *http.Response
var body io.Reader
if ping.Method == "POST" {
body = bytes.NewBufferString("{}")
}
req, err := http.NewRequest(ping.Method, ping.target.String(), body)
req.Header.Set(http.CanonicalHeaderKey("User-Agent"), "tcping")
if err != nil {
return 0, nil, "", err
}
var remoteAddr string
trace := &httptrace.ClientTrace{
ConnectStart: func(network, addr string) {
remoteAddr = addr
},
}
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
duration, errIfce := timeIt(func() interface{} {
client := http.Client{Timeout: ping.target.Timeout}
resp, err = client.Do(req)
return err
})
if errIfce != nil {
err := errIfce.(error)
return 0, nil, "", err
}
return time.Duration(duration), resp, remoteAddr, nil
}

@ -0,0 +1,149 @@
package tcping
import (
"bytes"
"fmt"
"html/template"
"regexp"
"strconv"
"strings"
"time"
)
// Protocol ...
type Protocol int
func (protocol Protocol) String() string {
switch protocol {
case TCP:
return "tcp"
case HTTP:
return "http"
case HTTPS:
return "https"
}
return "unkown"
}
const (
// TCP is tcp protocol
TCP Protocol = iota
// HTTP is http protocol
HTTP
// HTTPS is https protocol
HTTPS
)
// NewProtocol convert protocol stirng to Protocol
func NewProtocol(protocol string) (Protocol, error) {
switch strings.ToLower(protocol) {
case TCP.String():
return TCP, nil
case HTTP.String():
return HTTP, nil
case HTTPS.String():
return HTTPS, nil
}
return 0, fmt.Errorf("protocol %s not support", protocol)
}
// Target is a ping
type Target struct {
Protocol Protocol
Host string
Port int
Counter int
Interval time.Duration
Timeout time.Duration
}
func (target Target) String() string {
return fmt.Sprintf("%s://%s:%d", target.Protocol, target.Host, target.Port)
}
// Pinger is a ping interface
type Pinger interface {
Start() <-chan struct{}
Stop()
Result() *Result
SetTarget(target *Target)
}
// Ping is a ping interface
type Ping interface {
Start() <-chan struct{}
Host() string
Port() int
Protocol() Protocol
Counter() int
Stop()
Result() Result
}
// Result ...
type Result struct {
Counter int
SuccessCounter int
Target *Target
MinDuration time.Duration
MaxDuration time.Duration
TotalDuration time.Duration
}
// Avg return the average time of ping
func (result Result) Avg() time.Duration {
if result.SuccessCounter == 0 {
return 0
}
return result.TotalDuration / time.Duration(result.SuccessCounter)
}
// Failed return failed counter
func (result Result) Failed() int {
return result.Counter - result.SuccessCounter
}
func (result Result) String() string {
const resultTpl = `
Ping statistics {{.Target}}
{{.Counter}} probes sent.
{{.SuccessCounter}} successful, {{.Failed}} failed.
Approximate trip times:
Minimum = {{.MinDuration}}, Maximum = {{.MaxDuration}}, Average = {{.Avg}}`
t := template.Must(template.New("result").Parse(resultTpl))
res := bytes.NewBufferString("")
t.Execute(res, result)
return res.String()
}
// CheckURI check uri
func CheckURI(uri string) (schema, host string, port int, matched bool) {
const reExp = `^((?P<schema>((ht|f)tp(s?))|tcp)\://)?((([a-zA-Z0-9_\-]+\.)+[a-zA-Z]{2,})|((?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)((\.?\d)\.)){4})|(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9]))(:([0-9]+))?(/[a-zA-Z0-9\-\._\?\,\'/\\\+&amp;%\$#\=~]*)?$`
pattern := regexp.MustCompile(reExp)
res := pattern.FindStringSubmatch(uri)
if len(res) == 0 {
return
}
matched = true
schema = res[2]
if schema == "" {
schema = "tcp"
}
host = res[6]
if res[17] == "" {
if schema == HTTPS.String() {
port = 443
} else {
port = 80
}
} else {
port, _ = strconv.Atoi(res[17])
}
return
}

@ -0,0 +1,102 @@
package tcping
import (
"fmt"
"net"
"time"
)
// TCPing ...
type TCPing struct {
target *Target
done chan struct{}
result *Result
}
var _ Pinger = (*TCPing)(nil)
// NewTCPing return a new TCPing
func NewTCPing() *TCPing {
tcping := TCPing{
done: make(chan struct{}),
}
return &tcping
}
// SetTarget set target for TCPing
func (tcping *TCPing) SetTarget(target *Target) {
tcping.target = target
if tcping.result == nil {
tcping.result = &Result{Target: target}
}
}
// Result return the result
func (tcping TCPing) Result() *Result {
return tcping.result
}
// Start a tcping
func (tcping TCPing) Start() <-chan struct{} {
go func() {
t := time.NewTicker(tcping.target.Interval)
defer t.Stop()
for {
select {
case <-t.C:
if tcping.result.Counter >= tcping.target.Counter && tcping.target.Counter != 0 {
tcping.Stop()
return
}
duration, remoteAddr, err := tcping.ping()
tcping.result.Counter++
if err != nil {
fmt.Printf("Ping %s - failed: %s\n", tcping.target, err)
} else {
fmt.Printf("Ping %s(%s) - Connected - time=%s\n", tcping.target, remoteAddr, duration)
if tcping.result.MinDuration == 0 {
tcping.result.MinDuration = duration
}
if tcping.result.MaxDuration == 0 {
tcping.result.MaxDuration = duration
}
tcping.result.SuccessCounter++
if duration > tcping.result.MaxDuration {
tcping.result.MaxDuration = duration
} else if duration < tcping.result.MinDuration {
tcping.result.MinDuration = duration
}
tcping.result.TotalDuration += duration
}
case <-tcping.done:
return
}
}
}()
return tcping.done
}
// Stop the tcping
func (tcping *TCPing) Stop() {
tcping.done <- struct{}{}
}
func (tcping TCPing) ping() (time.Duration, net.Addr, error) {
var remoteAddr net.Addr
duration, errIfce := timeIt(func() interface{} {
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", tcping.target.Host, tcping.target.Port), tcping.target.Timeout)
if err != nil {
return err
}
remoteAddr = conn.RemoteAddr()
conn.Close()
return nil
})
if errIfce != nil {
err := errIfce.(error)
return 0, remoteAddr, err
}
return time.Duration(duration), remoteAddr, nil
}

@ -0,0 +1,51 @@
package tcping
import (
"context"
"fmt"
"net"
"strings"
"time"
)
func timeIt(f func() interface{}) (int64, interface{}) {
startAt := time.Now()
res := f()
endAt := time.Now()
return endAt.UnixNano() - startAt.UnixNano(), res
}
// UseCustomeDNS will set the dns to default DNS resolver for global
func UseCustomeDNS(dns []string) {
resolver := net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (conn net.Conn, err error) {
for _, addr := range dns {
if conn, err = net.Dial("udp", addr+":53"); err != nil {
continue
} else {
return conn, nil
}
}
return
},
}
net.DefaultResolver = &resolver
}
// FormatIP - trim spaces and format IP
//
// IP - the provided IP
//
// string - return "" if the input is neither valid IPv4 nor valid IPv6
// return IPv4 in format like "192.168.9.1"
// return IPv6 in format like "[2002:ac1f:91c5:1::bd59]"
func FormatIP(IP string) string {
host := strings.Trim(IP, "[ ]")
if parseIP := net.ParseIP(host); parseIP != nil && parseIP.To4() == nil {
host = fmt.Sprintf("[%s]", host)
}
return host
}

@ -0,0 +1,54 @@
//go:build windows
// +build windows
package uac
import (
"b612.me/starlog"
"github.com/spf13/cobra"
"os"
"path/filepath"
)
var fpath string
var fargs string
var workdir string
var showWindow bool
func init() {
Cmd.Flags().StringVarP(&fpath, "path", "p", "", "filepath/文件路径")
Cmd.Flags().StringVarP(&fargs, "args", "a", "", "args use space to split/参数,空格分隔")
Cmd.Flags().StringVarP(&workdir, "workdir", "d", "./", "workdir path")
Cmd.Flags().BoolVarP(&showWindow, "hide-window", "w", false, "hide the window show")
}
var Cmd = &cobra.Command{
Use: "uac",
Short: "run process with administrator permission",
Example: "vtqe uac 'c:\\program.exe arg1 arg2'",
Version: "2.0.0",
Run: func(cmd *cobra.Command, args []string) {
showWindow = !showWindow
workdir, _ = filepath.Abs(workdir)
if fpath == "" && len(args) == 0 {
starlog.Errorln("Please enter a filepath")
os.Exit(1)
}
if fpath != "" {
err := RunAsUacSimple(fpath, fargs, workdir, showWindow)
if err != nil {
starlog.Errorln("StartAsUac Failed", err)
os.Exit(2)
}
return
}
if len(args) > 0 {
err := RunAsUac(args[0], workdir, showWindow)
if err != nil {
starlog.Errorln("StartAsUac Failed", err)
os.Exit(2)
}
return
}
},
}

@ -0,0 +1,75 @@
//go:build windows
package uac
import (
"b612.me/wincmd"
"strings"
)
func RunAsUacSimple(fpath string, cmdArgs string, workDir string, showWindow bool) error {
intShow := 0
if showWindow {
intShow = 1
}
return wincmd.StartProcess(fpath, cmdArgs, workDir, true, intShow)
}
func RunAsUac(cmdLine, workDir string, showWindow bool) error {
intShow := 0
if showWindow {
intShow = 1
}
fpath, args := getPathArgsFromString(cmdLine)
return wincmd.StartProcess(fpath, strings.Join(args, " "), workDir, true, intShow)
}
func getPathArgsFromString(cmdLine string) (string, []string) {
var fpath string
var cmdArgs []string
var markStart rune = -1
var tmp []rune
var lastRune rune
cmdLine = strings.TrimSpace(cmdLine)
for k, v := range cmdLine {
if v == ' ' || v == '"' || v == '\'' {
if k == 0 {
markStart = v
continue
}
if markStart == v && v == lastRune {
continue
}
if lastRune != '\\' {
lastRune = v
if 0 == markStart {
markStart = v
continue
} else if markStart == v || markStart == -1 {
markStart = 0
if v == ' ' {
markStart = v
}
if fpath == "" {
fpath = string(tmp)
} else {
cmdArgs = append(cmdArgs, string(tmp))
}
tmp = []rune{}
continue
}
}
}
lastRune = v
tmp = append(tmp, v)
}
if len(tmp) != 0 {
if fpath == "" {
fpath = string(tmp)
} else {
cmdArgs = append(cmdArgs, string(tmp))
}
}
return fpath, cmdArgs
}

@ -0,0 +1,12 @@
//go:build !windows
package uac
import "github.com/spf13/cobra"
var Cmd = &cobra.Command{
Use: "uac",
Short: "run process with administrator permission",
Example: "vtqe uac 'c:\\program.exe arg1 arg2'",
Hidden: true,
}

@ -0,0 +1,93 @@
package vic
import (
"b612.me/starcrypto"
"fmt"
"os"
"regexp"
"b612.me/starlog"
"github.com/spf13/cobra"
)
var Cmd = &cobra.Command{
Use: "vicque",
Short: "嵐を乗り越えて",
Long: "あの子の未来を照らし出せ",
Run: func(this *cobra.Command, args []string) {
var err error
ok, _ := this.Flags().GetBool("file")
de, _ := this.Flags().GetBool("decode")
pwd, _ := this.Flags().GetString("key")
rep, _ := this.Flags().GetBool("replace")
ext, _ := this.Flags().GetBool("extension")
if len(args) != 2 || args[1] != "sakura" {
starlog.Errorln("ヴィクトリカだけが使えるよ")
return
}
shell := func(pect float64) {
if pect == 100 {
fmt.Println("已处理100.000000%")
} else {
fmt.Printf("已处理:%f%%\r", pect)
}
}
if ok {
path, _ := this.Flags().GetString("path")
if !de {
err = starcrypto.VicqueEncodeV1File(args[0], path, pwd, shell)
if err == nil {
if rep {
os.Remove(args[0])
os.Rename(path, args[0])
path = args[0]
}
if ext {
os.Rename(path, path+".victorique")
}
}
} else {
err = starcrypto.VicqueDecodeV1File(args[0], path, pwd, shell)
if err == nil {
if rep {
os.Remove(args[0])
os.Rename(path, args[0])
path = args[0]
}
if ext {
reg := regexp.MustCompile(`(.*?)\.victorique$`)
if reg.MatchString(path) {
paths := reg.FindStringSubmatch(path)
os.Rename(path, paths[1])
}
}
}
}
} else {
if !de {
data := starcrypto.VicqueEncodeV1([]byte(args[0]), pwd)
fmt.Println(data)
fmt.Println(starcrypto.Base64Encode(data))
} else {
var data []byte
src, _ := starcrypto.Base64Decode(args[0])
data = starcrypto.VicqueDecodeV1(src, pwd)
fmt.Println(string(data))
}
}
if err != nil {
starlog.Errorln(err)
return
}
},
}
func init() {
Cmd.Flags().BoolP("file", "f", false, "VICQUE处理文件")
Cmd.Flags().StringP("path", "p", "./v64.encode", "指定处理地址,默认为./v64.encode")
Cmd.Flags().BoolP("decode", "d", false, "VICQUE解码")
Cmd.Flags().StringP("key", "k", "", "密钥")
Cmd.Flags().BoolP("replace", "r", false, "覆盖原文件")
Cmd.Flags().BoolP("extension", "e", false, "添加/取消.victorique后缀")
Cmd.MarkFlagRequired("key")
}
Loading…
Cancel
Save