199 lines
5.1 KiB
Go
199 lines
5.1 KiB
Go
package zciyon
|
||
|
||
import (
|
||
"io"
|
||
"mime/multipart"
|
||
"net/http"
|
||
"regexp"
|
||
"strings"
|
||
)
|
||
|
||
const (
|
||
CIYPOST_ALLOW_TEXT = 0 //禁止任何html代码
|
||
CIYPOST_ALLOW_HTML = 1 //允许合法html代码,但不允许js脚本
|
||
CIYPOST_ALLOW_ALL = 2 //全部放行
|
||
)
|
||
|
||
type CiyPost struct {
|
||
kv map[string]any
|
||
W http.ResponseWriter
|
||
R *http.Request
|
||
err error
|
||
}
|
||
|
||
func NewCiyPost(w http.ResponseWriter, r *http.Request) *CiyPost {
|
||
post := &CiyPost{}
|
||
post.W = w
|
||
post.R = r
|
||
post.kv = map[string]any{}
|
||
if strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/form-data") {
|
||
err := r.ParseMultipartForm(1024 * 5) //1024 * 1024 * 1024 *
|
||
if err != nil {
|
||
post.err = err
|
||
} else {
|
||
for k, v := range r.Form {
|
||
post.kv[k] = v[0]
|
||
}
|
||
if r.MultipartForm != nil && r.MultipartForm.File != nil {
|
||
for k, files := range r.MultipartForm.File {
|
||
post.kv[k] = files[0]
|
||
}
|
||
}
|
||
}
|
||
} else if r.Method == "POST" {
|
||
body, err := io.ReadAll(r.Body)
|
||
if err != nil {
|
||
post.err = err
|
||
} else {
|
||
post.kv = Byte_JSON(body)
|
||
if len(post.kv) == 0 {
|
||
post.kv = map[string]any{"body": string(body)}
|
||
}
|
||
}
|
||
}
|
||
for k, v := range r.URL.Query() {
|
||
post.kv[k] = v[0]
|
||
}
|
||
if len(post.kv) == 0 {
|
||
post.kv[""] = r.URL.RawQuery
|
||
}
|
||
return post
|
||
}
|
||
|
||
func (thos *CiyPost) Is(key string) bool {
|
||
_, ok := thos.kv[key]
|
||
return ok
|
||
}
|
||
func (thos *CiyPost) Getany(key string) any {
|
||
return thos.kv[key]
|
||
}
|
||
func (thos *CiyPost) Getobj(key string) map[string]any {
|
||
if arr, ok := thos.kv[key].(map[string]any); ok {
|
||
return arr
|
||
}
|
||
return map[string]any{}
|
||
}
|
||
func (thos *CiyPost) Getint(key string, argdef ...int) int {
|
||
return Toint(thos.kv[key], argdef...)
|
||
}
|
||
func (thos *CiyPost) Getfloat(key string, argdef ...float64) float64 {
|
||
return Tofloat(thos.kv[key], argdef...)
|
||
}
|
||
func (thos *CiyPost) Getbool(key string, argdef ...bool) bool {
|
||
return Tobool(thos.kv[key], argdef...)
|
||
}
|
||
func (thos *CiyPost) Getdate(key string) int {
|
||
return Tostamp(Tostr(thos.kv[key]))
|
||
}
|
||
func (thos *CiyPost) GetIP() string {
|
||
xForwardedFor := thos.R.Header.Get("X-Forwarded-For")
|
||
if xForwardedFor != "" {
|
||
return strings.TrimSpace(strings.Split(xForwardedFor, ",")[0])
|
||
}
|
||
xRealIP := thos.R.Header.Get("X-Real-IP")
|
||
if xRealIP != "" {
|
||
return xRealIP
|
||
}
|
||
return thos.R.RemoteAddr
|
||
}
|
||
func (thos *CiyPost) IsWeixin() bool {
|
||
useragent := thos.R.Header.Get("HTTP_USER_AGENT")
|
||
useragent = strings.ToLower(useragent)
|
||
return strings.Contains(useragent, "micromessenger")
|
||
}
|
||
|
||
func (thos *CiyPost) Get(key string, args ...any) string {
|
||
allow := CIYPOST_ALLOW_TEXT
|
||
defval := ""
|
||
for _, arg := range args {
|
||
switch v := arg.(type) {
|
||
case int:
|
||
allow = v
|
||
case string:
|
||
defval = v
|
||
}
|
||
}
|
||
str := Tostr(thos.kv[key])
|
||
if allow == CIYPOST_ALLOW_TEXT {
|
||
str = strings.TrimSpace(thos.triptotext(str))
|
||
} else if allow == CIYPOST_ALLOW_HTML {
|
||
str = thos.triptohtml(str)
|
||
//str = template.HTMLEscapeString(str)
|
||
//str = template.JSEscapeString(str)
|
||
}
|
||
if str == "" {
|
||
return defval
|
||
}
|
||
return str
|
||
}
|
||
func (thos *CiyPost) Gets(key string, args ...any) []string {
|
||
allow := CIYPOST_ALLOW_TEXT
|
||
for _, arg := range args {
|
||
switch v := arg.(type) {
|
||
case int:
|
||
allow = v
|
||
}
|
||
}
|
||
switch v := thos.kv[key].(type) {
|
||
case []any:
|
||
strs := make([]string, len(v))
|
||
for i, s := range v {
|
||
str := Tostr(s)
|
||
if allow == CIYPOST_ALLOW_TEXT {
|
||
str = strings.TrimSpace(thos.triptotext(str))
|
||
} else if allow == CIYPOST_ALLOW_HTML {
|
||
str = thos.triptohtml(str)
|
||
}
|
||
strs[i] = str
|
||
}
|
||
return strs
|
||
}
|
||
return []string{""}
|
||
}
|
||
func (thos *CiyPost) Getfile(argkey ...string) *multipart.FileHeader {
|
||
key := ""
|
||
if len(argkey) > 0 {
|
||
key = argkey[0]
|
||
}
|
||
if key != "" {
|
||
switch v := thos.kv[key].(type) {
|
||
case *multipart.FileHeader:
|
||
return v
|
||
}
|
||
} else {
|
||
for _, kv := range thos.kv {
|
||
switch v := kv.(type) {
|
||
case *multipart.FileHeader:
|
||
return v
|
||
}
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
func (thos *CiyPost) triptotext(str string) string { //去掉所有html标签和控制字符
|
||
re, _ := regexp.Compile(`\<[\S\s]+?\>`) //标签小写
|
||
str = re.ReplaceAllStringFunc(str, strings.ToLower)
|
||
re, _ = regexp.Compile(`\<style[\S\s]+?\</style\>`) //删除style
|
||
str = re.ReplaceAllString(str, "")
|
||
re, _ = regexp.Compile(`\<script[\S\s]+?\</script\>`) //删除script
|
||
str = re.ReplaceAllString(str, "")
|
||
re, _ = regexp.Compile(`\<[\S\s]+?\>`) //删除标签
|
||
str = re.ReplaceAllString(str, "")
|
||
return str
|
||
}
|
||
func (thos *CiyPost) triptohtml(str string) string { //保留html标签和style属性。去掉所有事件、style、script
|
||
re, _ := regexp.Compile(`\<[\S\s]+?\>`) //标签小写
|
||
str = re.ReplaceAllStringFunc(str, strings.ToLower)
|
||
re, _ = regexp.Compile(`\<style[\S\s]+?\</style\>`) //删除style
|
||
str = re.ReplaceAllString(str, "")
|
||
re, _ = regexp.Compile(`\<script[\S\s]+?\</script\>`) //删除script
|
||
str = re.ReplaceAllString(str, "")
|
||
reOnEvent := regexp.MustCompile(` on\w+="[^"]*"`) //删除双引号事件
|
||
str = reOnEvent.ReplaceAllString(str, "")
|
||
reOnEvent2 := regexp.MustCompile(` on\w+='[^"]*'`) //删除单引号事件
|
||
str = reOnEvent2.ReplaceAllString(str, "")
|
||
reOnEvent3 := regexp.MustCompile(` on\w+=`) //破坏事件代码
|
||
str = reOnEvent3.ReplaceAllString(str, " ")
|
||
return str
|
||
}
|