diff --git a/example/main.go b/example/main.go
index 63ff95e..c3e8b98 100644
--- a/example/main.go
+++ b/example/main.go
@@ -4,8 +4,8 @@ import (
"fmt"
"git.diulo.com/mogfee/protoc-gen-kit/example/service"
"git.diulo.com/mogfee/protoc-gen-kit/middleware"
+ "git.diulo.com/mogfee/protoc-gen-kit/pkg/xjson"
user "git.diulo.com/mogfee/protoc-gen-kit/proto/v1"
- "git.diulo.com/mogfee/protoc-gen-kit/xjson"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"os"
diff --git a/example/service/service.go b/example/service/service.go
index 8416d1a..eff09f5 100644
--- a/example/service/service.go
+++ b/example/service/service.go
@@ -3,8 +3,8 @@ package service
import (
"context"
"encoding/json"
+ "git.diulo.com/mogfee/protoc-gen-kit/pkg/xerrors"
user "git.diulo.com/mogfee/protoc-gen-kit/proto/v1"
- "git.diulo.com/mogfee/protoc-gen-kit/xerrors"
)
type UserService struct {
diff --git a/go.mod b/go.mod
index 57cdf93..1be180e 100644
--- a/go.mod
+++ b/go.mod
@@ -3,12 +3,16 @@ module git.diulo.com/mogfee/protoc-gen-kit
go 1.18
require (
+ git.diulo.com/mogfee/go-common v0.0.0-20230301071202-cc79129d6a24
+ github.com/PuerkitoBio/goquery v1.8.1
github.com/envoyproxy/protoc-gen-validate v0.1.0
- github.com/gin-gonic/gin v1.8.1
+ github.com/gin-gonic/gin v1.9.0
github.com/go-playground/form v3.1.4+incompatible
github.com/golang/protobuf v1.5.2
github.com/gorilla/mux v1.8.0
+ github.com/mojocn/base64Captcha v1.3.5
github.com/nsqio/go-nsq v1.1.0
+ github.com/pkg/errors v0.9.1
github.com/robfig/cron v1.2.0
github.com/sirupsen/logrus v1.9.0
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013
@@ -17,23 +21,31 @@ require (
)
require (
+ github.com/andybalholm/cascadia v1.3.1 // indirect
+ github.com/bytedance/sonic v1.8.0 // indirect
+ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
- github.com/go-playground/locales v0.14.0 // indirect
- github.com/go-playground/universal-translator v0.18.0 // indirect
- github.com/go-playground/validator/v10 v10.10.0 // indirect
- github.com/goccy/go-json v0.9.7 // indirect
+ github.com/go-playground/locales v0.14.1 // indirect
+ github.com/go-playground/universal-translator v0.18.1 // indirect
+ github.com/go-playground/validator/v10 v10.11.2 // indirect
+ github.com/goccy/go-json v0.10.0 // indirect
+ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
+ github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
- github.com/mattn/go-isatty v0.0.14 // indirect
+ github.com/mattn/go-isatty v0.0.17 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
- github.com/pelletier/go-toml/v2 v2.0.1 // indirect
- github.com/ugorji/go/codec v1.2.7 // indirect
- golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
- golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
- golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
- golang.org/x/text v0.4.0 // indirect
+ github.com/pelletier/go-toml/v2 v2.0.6 // indirect
+ github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+ github.com/ugorji/go/codec v1.2.9 // indirect
+ golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
+ golang.org/x/crypto v0.5.0 // indirect
+ golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 // indirect
+ golang.org/x/net v0.7.0 // indirect
+ golang.org/x/sys v0.5.0 // indirect
+ golang.org/x/text v0.7.0 // indirect
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
- gopkg.in/yaml.v2 v2.4.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index 0af434b..fa4d714 100644
--- a/go.sum
+++ b/go.sum
@@ -1,8 +1,19 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+git.diulo.com/mogfee/go-common v0.0.0-20230301071202-cc79129d6a24 h1:fL1oF18chI61PjnQCBy4549A5j6isNKN3gyOnNP7bLM=
+git.diulo.com/mogfee/go-common v0.0.0-20230301071202-cc79129d6a24/go.mod h1:Q3SH0klnjQIvM57Fi95URevaFXIhsb7DZa+ZcNEU88M=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
+github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
+github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
+github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
+github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
+github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
+github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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=
@@ -11,20 +22,21 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrp
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
-github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
-github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
-github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
+github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/form v3.1.4+incompatible h1:lvKiHVxE2WvzDIoyMnWcjyiBxKt2+uFJyZcPYWsLnjI=
github.com/go-playground/form v3.1.4+incompatible/go.mod h1:lhcKXfTuhRtIZCIKUeJ0b5F207aeQCPbZU09ScKjwWg=
-github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
-github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
-github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
-github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
-github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
-github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
-github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM=
-github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
+github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
+github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
+github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+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/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -51,84 +63,105 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
-github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4PfoagaA0=
+github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY=
github.com/nsqio/go-nsq v1.1.0 h1:PQg+xxiUjA7V+TLdXw7nVrJ5Jbl3sN86EhGCQj4+FYE=
github.com/nsqio/go-nsq v1.1.0/go.mod h1:vKq36oyeVXgsS5Q8YEO7WghqidAVXQlcFxzQbQTuDEY=
-github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU=
-github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
-github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
+github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
+github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
-github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
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/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
-github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
-github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
+github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
-golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
+golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 h1:TbGuee8sSq15Iguxu4deQ7+Bqq/d2rsQejGcEtADAMQ=
+golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+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-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
+golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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/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.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+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/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@@ -154,16 +187,12 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
diff --git a/middleware/jwt.go b/middleware/jwt.go
index 749f448..b822cab 100644
--- a/middleware/jwt.go
+++ b/middleware/jwt.go
@@ -2,18 +2,23 @@ package middleware
import (
"context"
- "git.diulo.com/mogfee/protoc-gen-kit/xuser"
+ "git.diulo.com/mogfee/protoc-gen-kit/pkg/xuser"
"google.golang.org/grpc/metadata"
)
-func JWT(authKey string) Middleware {
+type ValidateUser interface {
+ ValidateUser(string) (int64, error)
+}
+
+func JWT(validate ValidateUser) Middleware {
return func(handler Handler) Handler {
return func(ctx context.Context, a any) (any, error) {
var token string
if md, ok := metadata.FromIncomingContext(ctx); ok {
token = md.Get("token")[0]
}
- userId, err := xuser.ValidateUser(ctx.Value(token).(string))
+
+ userId, err := validate.ValidateUser(ctx.Value(token).(string))
if err != nil {
return nil, err
}
diff --git a/middleware/logger.go b/middleware/logger.go
index 86b113d..bd3d03d 100644
--- a/middleware/logger.go
+++ b/middleware/logger.go
@@ -2,8 +2,7 @@ package middleware
import (
"context"
- "fmt"
- "git.diulo.com/mogfee/protoc-gen-kit/xlog"
+ "git.diulo.com/mogfee/protoc-gen-kit/pkg/xlog"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/metadata"
"time"
@@ -15,7 +14,6 @@ func Logger(serverName string, log *logrus.Logger) Middleware {
})
return func(handler Handler) Handler {
return func(ctx context.Context, a any) (any, error) {
- fmt.Println("add_log")
st := time.Now()
entry := baseEntry.WithFields(logrus.Fields{
"used_time": time.Since(st),
diff --git a/middleware/validate.go b/middleware/validate.go
index 192ee3c..21bd185 100644
--- a/middleware/validate.go
+++ b/middleware/validate.go
@@ -2,14 +2,11 @@ package middleware
import (
"context"
- "fmt"
)
func Validate() Middleware {
return func(handler Handler) Handler {
return func(ctx context.Context, a any) (any, error) {
- fmt.Println("validate")
- fmt.Println(ctx.Value("user-id"))
if r, ok := a.(interface {
Validate() error
}); ok {
diff --git a/pkg/captcha/captcha.go b/pkg/captcha/captcha.go
new file mode 100644
index 0000000..12e741d
--- /dev/null
+++ b/pkg/captcha/captcha.go
@@ -0,0 +1,32 @@
+package captcha
+
+import (
+ "github.com/mojocn/base64Captcha"
+)
+
+func GetCaptcha() (string, string) {
+ //config struct for Character
+ //字符,公式,验证码配置
+ var configC = base64Captcha.ConfigCharacter{
+ Height: 30,
+ Width: 80,
+ //const CaptchaModeNumber:数字,CaptchaModeAlphabet:字母,CaptchaModeArithmetic:算术,CaptchaModeNumberAlphabet:数字字母混合.
+ Mode: base64Captcha.CaptchaModeNumber,
+ ComplexOfNoiseText: base64Captcha.CaptchaComplexLower,
+ ComplexOfNoiseDot: base64Captcha.CaptchaComplexLower,
+ IsUseSimpleFont: true,
+ IsShowHollowLine: false,
+ IsShowNoiseDot: false,
+ IsShowNoiseText: false,
+ IsShowSlimeLine: false,
+ IsShowSineLine: false,
+ CaptchaLen: 4,
+ }
+ idKeyC, capC := base64Captcha.GenerateCaptcha("", configC)
+ base64stringC := base64Captcha.CaptchaWriteToBase64Encoding(capC)
+ return idKeyC, base64stringC
+}
+
+func Verify(idKey, verifyValue string) bool {
+ return base64Captcha.VerifyCaptcha(idKey, verifyValue)
+}
diff --git a/pkg/consumer/consumer.go b/pkg/consumer/consumer.go
new file mode 100644
index 0000000..53c5251
--- /dev/null
+++ b/pkg/consumer/consumer.go
@@ -0,0 +1,72 @@
+package consumer
+
+import (
+ "github.com/nsqio/go-nsq"
+ "sync"
+)
+
+type baseConsumerService struct {
+ consumers []*BaseConsumer
+}
+
+func New() *baseConsumerService {
+ return &baseConsumerService{
+ consumers: []*BaseConsumer{},
+ }
+}
+func (s *baseConsumerService) Register(b *BaseConsumer) {
+ s.consumers = append(s.consumers, b)
+}
+func (s *baseConsumerService) Run() error {
+ for _, v := range s.consumers {
+ if err := v.Run(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (s *baseConsumerService) Stop() error {
+ for _, v := range s.consumers {
+ if err := v.Stop(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+type BaseConsumer struct {
+ host, topic, consumerChan string
+ wg *sync.WaitGroup
+ consumer *nsq.Consumer
+}
+
+func (s *BaseConsumer) Stop() error {
+ s.consumer.Stop()
+ s.wg.Wait()
+ return nil
+}
+func (s *BaseConsumer) Run() error {
+ return s.consumer.ConnectToNSQD(s.host)
+}
+
+func NewBaseConsumer(host, topic, consumerChan string, fun func(msg *nsq.Message) error) *BaseConsumer {
+ resp := &BaseConsumer{
+ wg: &sync.WaitGroup{},
+ consumer: nil,
+ host: host,
+ topic: topic,
+ consumerChan: consumerChan,
+ }
+ consumer, err := nsq.NewConsumer(topic, consumerChan, nsq.NewConfig())
+ if err != nil {
+ panic(err)
+ }
+ consumer.AddHandler(nsq.HandlerFunc(func(msg *nsq.Message) error {
+ resp.wg.Add(1)
+ defer resp.wg.Done()
+ return fun(msg)
+ }))
+ resp.consumer = consumer
+ return resp
+}
diff --git a/pkg/php_session_decoder/common.go b/pkg/php_session_decoder/common.go
new file mode 100644
index 0000000..061e750
--- /dev/null
+++ b/pkg/php_session_decoder/common.go
@@ -0,0 +1,7 @@
+package php_session_decoder
+
+import "git.diulo.com/mogfee/go-common/php_session_decoder/php_serialize"
+
+const SEPARATOR_VALUE_NAME rune = '|'
+
+type PhpSession map[string]php_serialize.PhpValue
diff --git a/pkg/php_session_decoder/decoder.go b/pkg/php_session_decoder/decoder.go
new file mode 100644
index 0000000..1b72bae
--- /dev/null
+++ b/pkg/php_session_decoder/decoder.go
@@ -0,0 +1,66 @@
+package php_session_decoder
+
+import (
+ "bytes"
+ "git.diulo.com/mogfee/go-common/php_session_decoder/php_serialize"
+ "io"
+ "strings"
+)
+
+type PhpDecoder struct {
+ source *strings.Reader
+ decoder *php_serialize.UnSerializer
+}
+
+func NewPhpDecoder(phpSession string) *PhpDecoder {
+ decoder := &PhpDecoder{
+ source: strings.NewReader(phpSession),
+ decoder: php_serialize.NewUnSerializer(""),
+ }
+ decoder.decoder.SetReader(decoder.source)
+ return decoder
+}
+
+func (self *PhpDecoder) SetSerializedDecodeFunc(f php_serialize.SerializedDecodeFunc) {
+ self.decoder.SetSerializedDecodeFunc(f)
+}
+
+func (self *PhpDecoder) Decode() (PhpSession, error) {
+ var (
+ name string
+ err error
+ value php_serialize.PhpValue
+ )
+ res := make(PhpSession)
+
+ for {
+ if name, err = self.readName(); err != nil {
+ break
+ }
+ if value, err = self.decoder.Decode(); err != nil {
+ break
+ }
+ res[name] = value
+ }
+
+ if err == io.EOF {
+ err = nil
+ }
+ return res, err
+}
+
+func (self *PhpDecoder) readName() (string, error) {
+ var (
+ token rune
+ err error
+ )
+ buf := bytes.NewBuffer([]byte{})
+ for {
+ if token, _, err = self.source.ReadRune(); err != nil || token == SEPARATOR_VALUE_NAME {
+ break
+ } else {
+ buf.WriteRune(token)
+ }
+ }
+ return buf.String(), err
+}
diff --git a/pkg/php_session_decoder/encoder.go b/pkg/php_session_decoder/encoder.go
new file mode 100644
index 0000000..fe2d3dc
--- /dev/null
+++ b/pkg/php_session_decoder/encoder.go
@@ -0,0 +1,46 @@
+package php_session_decoder
+
+import (
+ "bytes"
+ "fmt"
+ "git.diulo.com/mogfee/go-common/php_session_decoder/php_serialize"
+)
+
+type PhpEncoder struct {
+ data PhpSession
+ encoder *php_serialize.Serializer
+}
+
+func NewPhpEncoder(data PhpSession) *PhpEncoder {
+ return &PhpEncoder{
+ data: data,
+ encoder: php_serialize.NewSerializer(),
+ }
+}
+
+func (self *PhpEncoder) SetSerializedEncodeFunc(f php_serialize.SerializedEncodeFunc) {
+ self.encoder.SetSerializedEncodeFunc(f)
+}
+
+func (self *PhpEncoder) Encode() (string, error) {
+ if self.data == nil {
+ return "", nil
+ }
+ var (
+ err error
+ val string
+ )
+ buf := bytes.NewBuffer([]byte{})
+
+ for k, v := range self.data {
+ buf.WriteString(k)
+ buf.WriteRune(SEPARATOR_VALUE_NAME)
+ if val, err = self.encoder.Encode(v); err != nil {
+ err = fmt.Errorf("php_session: error during encode value for %q: %v", k, err)
+ break
+ }
+ buf.WriteString(val)
+ }
+
+ return buf.String(), err
+}
diff --git a/pkg/php_session_decoder/php_serialize/common.go b/pkg/php_session_decoder/php_serialize/common.go
new file mode 100644
index 0000000..e5dd462
--- /dev/null
+++ b/pkg/php_session_decoder/php_serialize/common.go
@@ -0,0 +1,189 @@
+package php_serialize
+
+const (
+ TOKEN_NULL rune = 'N'
+ TOKEN_BOOL rune = 'b'
+ TOKEN_INT rune = 'i'
+ TOKEN_FLOAT rune = 'd'
+ TOKEN_STRING rune = 's'
+ TOKEN_ARRAY rune = 'a'
+ TOKEN_OBJECT rune = 'O'
+ TOKEN_OBJECT_SERIALIZED rune = 'C'
+ TOKEN_REFERENCE rune = 'R'
+ TOKEN_REFERENCE_OBJECT rune = 'r'
+ TOKEN_SPL_ARRAY rune = 'x'
+ TOKEN_SPL_ARRAY_MEMBERS rune = 'm'
+
+ SEPARATOR_VALUE_TYPE rune = ':'
+ SEPARATOR_VALUES rune = ';'
+
+ DELIMITER_STRING_LEFT rune = '"'
+ DELIMITER_STRING_RIGHT rune = '"'
+ DELIMITER_OBJECT_LEFT rune = '{'
+ DELIMITER_OBJECT_RIGHT rune = '}'
+
+ FORMATTER_FLOAT byte = 'g'
+ FORMATTER_PRECISION int = 17
+)
+
+var (
+ debugMode = false
+)
+
+func Debug(value bool) {
+ debugMode = value
+}
+
+func NewPhpObject(className string) *PhpObject {
+ return &PhpObject{
+ className: className,
+ members: PhpArray{},
+ }
+}
+
+type SerializedDecodeFunc func(string) (PhpValue, error)
+
+type SerializedEncodeFunc func(PhpValue) (string, error)
+
+type PhpValue interface{}
+
+type PhpArray map[PhpValue]PhpValue
+
+type PhpSlice []PhpValue
+
+type PhpObject struct {
+ className string
+ members PhpArray
+}
+
+func (self *PhpObject) GetClassName() string {
+ return self.className
+}
+
+func (self *PhpObject) SetClassName(name string) *PhpObject {
+ self.className = name
+ return self
+}
+
+func (self *PhpObject) GetMembers() PhpArray {
+ return self.members
+}
+
+func (self *PhpObject) SetMembers(members PhpArray) *PhpObject {
+ self.members = members
+ return self
+}
+
+func (self *PhpObject) GetPrivate(name string) (v PhpValue, ok bool) {
+ v, ok = self.members["\x00"+self.className+"\x00"+name]
+ return
+}
+
+func (self *PhpObject) SetPrivate(name string, value PhpValue) *PhpObject {
+ self.members["\x00"+self.className+"\x00"+name] = value
+ return self
+}
+
+func (self *PhpObject) GetProtected(name string) (v PhpValue, ok bool) {
+ v, ok = self.members["\x00*\x00"+name]
+ return
+}
+
+func (self *PhpObject) SetProtected(name string, value PhpValue) *PhpObject {
+ self.members["\x00*\x00"+name] = value
+ return self
+}
+
+func (self *PhpObject) GetPublic(name string) (v PhpValue, ok bool) {
+ v, ok = self.members[name]
+ return
+}
+
+func (self *PhpObject) SetPublic(name string, value PhpValue) *PhpObject {
+ self.members[name] = value
+ return self
+}
+
+func NewPhpObjectSerialized(className string) *PhpObjectSerialized {
+ return &PhpObjectSerialized{
+ className: className,
+ }
+}
+
+type PhpObjectSerialized struct {
+ className string
+ data string
+ value PhpValue
+}
+
+func (self *PhpObjectSerialized) GetClassName() string {
+ return self.className
+}
+
+func (self *PhpObjectSerialized) SetClassName(name string) *PhpObjectSerialized {
+ self.className = name
+ return self
+}
+
+func (self *PhpObjectSerialized) GetData() string {
+ return self.data
+}
+
+func (self *PhpObjectSerialized) SetData(data string) *PhpObjectSerialized {
+ self.data = data
+ return self
+}
+
+func (self *PhpObjectSerialized) GetValue() PhpValue {
+ return self.value
+}
+
+func (self *PhpObjectSerialized) SetValue(value PhpValue) *PhpObjectSerialized {
+ self.value = value
+ return self
+}
+
+func NewPhpSplArray(array, properties PhpValue) *PhpSplArray {
+ if array == nil {
+ array = make(PhpArray)
+ }
+
+ if properties == nil {
+ properties = make(PhpArray)
+ }
+
+ return &PhpSplArray{
+ array: array,
+ properties: properties,
+ }
+}
+
+type PhpSplArray struct {
+ flags int
+ array PhpValue
+ properties PhpValue
+}
+
+func (self *PhpSplArray) GetFlags() int {
+ return self.flags
+}
+
+func (self *PhpSplArray) SetFlags(value int) {
+ self.flags = value
+}
+
+func (self *PhpSplArray) GetArray() PhpValue {
+ return self.array
+}
+
+func (self *PhpSplArray) SetArray(value PhpValue) {
+ self.array = value
+}
+
+func (self *PhpSplArray) GetProperties() PhpValue {
+ return self.properties
+}
+
+func (self *PhpSplArray) SetProperties(value PhpValue) {
+ self.properties = value
+}
diff --git a/pkg/php_session_decoder/php_serialize/common_helper.go b/pkg/php_session_decoder/php_serialize/common_helper.go
new file mode 100644
index 0000000..9e95356
--- /dev/null
+++ b/pkg/php_session_decoder/php_serialize/common_helper.go
@@ -0,0 +1,91 @@
+package php_serialize
+
+import (
+ "strconv"
+)
+
+func PhpValueString(p PhpValue) (res string) {
+ res, _ = p.(string)
+ return
+}
+
+func PhpValueBool(p PhpValue) (res bool) {
+ switch v := p.(type) {
+ case bool:
+ res = v
+ case string:
+ res, _ = strconv.ParseBool(v)
+ }
+ return
+}
+
+func PhpValueInt(p PhpValue) (res int) {
+ switch intVal := p.(type) {
+ case int:
+ res = intVal
+ case int8:
+ res = int(intVal)
+ case int16:
+ res = int(intVal)
+ case int32:
+ res = int(intVal)
+ case int64:
+ res = int(intVal)
+ case uint:
+ res = int(intVal)
+ case uint8:
+ res = int(intVal)
+ case uint16:
+ res = int(intVal)
+ case uint32:
+ res = int(intVal)
+ case uint64:
+ res = int(intVal)
+ case string:
+ str, _ := p.(string)
+ res, _ = strconv.Atoi(str)
+ }
+ return
+}
+
+func PhpValueInt64(p PhpValue) (res int64) {
+ switch v := p.(type) {
+ case int64:
+ res = v
+ default:
+ res = int64(PhpValueInt(v))
+ }
+ return
+}
+
+func PhpValueUInt(p PhpValue) (res uint) {
+ switch v := p.(type) {
+ case uint:
+ res = v
+ default:
+ res = uint(PhpValueInt(v))
+ }
+ return
+}
+
+func PhpValueUInt64(p PhpValue) (res uint64) {
+ switch v := p.(type) {
+ case uint64:
+ res = v
+ default:
+ res = uint64(PhpValueInt(v))
+ }
+ return
+}
+
+func PhpValueFloat64(p PhpValue) (res float64) {
+ switch v := p.(type) {
+ case float64:
+ res = v
+ case string:
+ res, _ = strconv.ParseFloat(v, 64)
+ default:
+ return float64(PhpValueInt(p))
+ }
+ return
+}
diff --git a/pkg/php_session_decoder/php_serialize/serialize.go b/pkg/php_session_decoder/php_serialize/serialize.go
new file mode 100644
index 0000000..bb1c673
--- /dev/null
+++ b/pkg/php_session_decoder/php_serialize/serialize.go
@@ -0,0 +1,264 @@
+package php_serialize
+
+import (
+ "bytes"
+ "fmt"
+ "strconv"
+)
+
+func Serialize(v PhpValue) (string, error) {
+ encoder := NewSerializer()
+ encoder.SetSerializedEncodeFunc(SerializedEncodeFunc(Serialize))
+ return encoder.Encode(v)
+}
+
+type Serializer struct {
+ lastErr error
+ encodeFunc SerializedEncodeFunc
+}
+
+func NewSerializer() *Serializer {
+ return &Serializer{}
+}
+
+func (self *Serializer) SetSerializedEncodeFunc(f SerializedEncodeFunc) {
+ self.encodeFunc = f
+}
+
+func (self *Serializer) Encode(v PhpValue) (string, error) {
+ var value bytes.Buffer
+
+ switch t := v.(type) {
+ default:
+ self.saveError(fmt.Errorf("php_serialize: Unknown type %T with value %#v", t, v))
+ case nil:
+ value = self.encodeNull()
+ case bool:
+ value = self.encodeBool(v)
+ case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
+ value = self.encodeNumber(v)
+ case string:
+ value = self.encodeString(v, DELIMITER_STRING_LEFT, DELIMITER_STRING_RIGHT, true)
+ case PhpArray, map[PhpValue]PhpValue, PhpSlice:
+ value = self.encodeArray(v, true)
+ case *PhpObject:
+ value = self.encodeObject(v)
+ case *PhpObjectSerialized:
+ value = self.encodeSerialized(v)
+ case *PhpSplArray:
+ value = self.encodeSplArray(v)
+ }
+
+ return value.String(), self.lastErr
+}
+
+func (self *Serializer) encodeNull() (buffer bytes.Buffer) {
+ buffer.WriteRune(TOKEN_NULL)
+ buffer.WriteRune(SEPARATOR_VALUES)
+ return
+}
+
+func (self *Serializer) encodeBool(v PhpValue) (buffer bytes.Buffer) {
+ buffer.WriteRune(TOKEN_BOOL)
+ buffer.WriteRune(SEPARATOR_VALUE_TYPE)
+
+ if bVal, ok := v.(bool); ok && bVal {
+ buffer.WriteString("1")
+ } else {
+ buffer.WriteString("0")
+ }
+
+ buffer.WriteRune(SEPARATOR_VALUES)
+ return
+}
+
+func (self *Serializer) encodeNumber(v PhpValue) (buffer bytes.Buffer) {
+ var val string
+
+ isFloat := false
+
+ switch intVal := v.(type) {
+ default:
+ val = "0"
+ case int:
+ val = strconv.FormatInt(int64(intVal), 10)
+ case int8:
+ val = strconv.FormatInt(int64(intVal), 10)
+ case int16:
+ val = strconv.FormatInt(int64(intVal), 10)
+ case int32:
+ val = strconv.FormatInt(int64(intVal), 10)
+ case int64:
+ val = strconv.FormatInt(int64(intVal), 10)
+ case uint:
+ val = strconv.FormatUint(uint64(intVal), 10)
+ case uint8:
+ val = strconv.FormatUint(uint64(intVal), 10)
+ case uint16:
+ val = strconv.FormatUint(uint64(intVal), 10)
+ case uint32:
+ val = strconv.FormatUint(uint64(intVal), 10)
+ case uint64:
+ val = strconv.FormatUint(uint64(intVal), 10)
+ // PHP has precision = 17 by default
+ case float32:
+ val = strconv.FormatFloat(float64(intVal), FORMATTER_FLOAT, FORMATTER_PRECISION, 32)
+ isFloat = true
+ case float64:
+ val = strconv.FormatFloat(float64(intVal), FORMATTER_FLOAT, FORMATTER_PRECISION, 64)
+ isFloat = true
+ }
+
+ if isFloat {
+ buffer.WriteRune(TOKEN_FLOAT)
+ } else {
+ buffer.WriteRune(TOKEN_INT)
+ }
+
+ buffer.WriteRune(SEPARATOR_VALUE_TYPE)
+ buffer.WriteString(val)
+ buffer.WriteRune(SEPARATOR_VALUES)
+
+ return
+}
+
+func (self *Serializer) encodeString(v PhpValue, left, right rune, isFinal bool) (buffer bytes.Buffer) {
+ val, _ := v.(string)
+
+ if isFinal {
+ buffer.WriteRune(TOKEN_STRING)
+ }
+
+ buffer.WriteString(self.prepareLen(len(val)))
+ buffer.WriteRune(left)
+ buffer.WriteString(val)
+ buffer.WriteRune(right)
+
+ if isFinal {
+ buffer.WriteRune(SEPARATOR_VALUES)
+ }
+
+ return
+}
+
+func (self *Serializer) encodeArray(v PhpValue, isFinal bool) (buffer bytes.Buffer) {
+ var (
+ arrLen int
+ s string
+ )
+
+ if isFinal {
+ buffer.WriteRune(TOKEN_ARRAY)
+ }
+
+ switch arrVal := v.(type) {
+ case PhpArray:
+ arrLen = len(arrVal)
+ buffer.WriteString(self.prepareLen(arrLen))
+ buffer.WriteRune(DELIMITER_OBJECT_LEFT)
+
+ for k, v := range arrVal {
+ s, _ = self.Encode(k)
+ buffer.WriteString(s)
+ s, _ = self.Encode(v)
+ buffer.WriteString(s)
+ }
+
+ case map[PhpValue]PhpValue:
+ arrLen = len(arrVal)
+
+ buffer.WriteString(self.prepareLen(arrLen))
+ buffer.WriteRune(DELIMITER_OBJECT_LEFT)
+
+ for k, v := range arrVal {
+ s, _ = self.Encode(k)
+ buffer.WriteString(s)
+ s, _ = self.Encode(v)
+ buffer.WriteString(s)
+ }
+ case PhpSlice:
+ arrLen = len(arrVal)
+
+ buffer.WriteString(self.prepareLen(arrLen))
+ buffer.WriteRune(DELIMITER_OBJECT_LEFT)
+
+ for k, v := range arrVal {
+ s, _ = self.Encode(k)
+ buffer.WriteString(s)
+ s, _ = self.Encode(v)
+ buffer.WriteString(s)
+ }
+ }
+
+ buffer.WriteRune(DELIMITER_OBJECT_RIGHT)
+
+ return
+}
+
+func (self *Serializer) encodeObject(v PhpValue) (buffer bytes.Buffer) {
+ obj, _ := v.(*PhpObject)
+ buffer.WriteRune(TOKEN_OBJECT)
+ buffer.WriteString(self.prepareClassName(obj.className))
+ encoded := self.encodeArray(obj.members, false)
+ buffer.WriteString(encoded.String())
+ return
+}
+
+func (self *Serializer) encodeSerialized(v PhpValue) (buffer bytes.Buffer) {
+ var serialized string
+
+ obj, _ := v.(*PhpObjectSerialized)
+ buffer.WriteRune(TOKEN_OBJECT_SERIALIZED)
+ buffer.WriteString(self.prepareClassName(obj.className))
+
+ if self.encodeFunc == nil {
+ serialized = obj.GetData()
+ } else {
+ var err error
+ if serialized, err = self.encodeFunc(obj.GetValue()); err != nil {
+ self.saveError(err)
+ }
+ }
+
+ encoded := self.encodeString(serialized, DELIMITER_OBJECT_LEFT, DELIMITER_OBJECT_RIGHT, false)
+ buffer.WriteString(encoded.String())
+ return
+}
+
+func (self *Serializer) encodeSplArray(v PhpValue) bytes.Buffer {
+ var buffer bytes.Buffer
+ obj, _ := v.(*PhpSplArray)
+
+ buffer.WriteRune(TOKEN_SPL_ARRAY)
+ buffer.WriteRune(SEPARATOR_VALUE_TYPE)
+
+ encoded := self.encodeNumber(obj.flags)
+ buffer.WriteString(encoded.String())
+
+ data, _ := self.Encode(obj.array)
+ buffer.WriteString(data)
+
+ buffer.WriteRune(SEPARATOR_VALUES)
+ buffer.WriteRune(TOKEN_SPL_ARRAY_MEMBERS)
+ buffer.WriteRune(SEPARATOR_VALUE_TYPE)
+
+ data, _ = self.Encode(obj.properties)
+ buffer.WriteString(data)
+
+ return buffer
+}
+
+func (self *Serializer) prepareLen(l int) string {
+ return string(SEPARATOR_VALUE_TYPE) + strconv.Itoa(l) + string(SEPARATOR_VALUE_TYPE)
+}
+
+func (self *Serializer) prepareClassName(name string) string {
+ encoded := self.encodeString(name, DELIMITER_STRING_LEFT, DELIMITER_STRING_RIGHT, false)
+ return encoded.String()
+}
+
+func (self *Serializer) saveError(err error) {
+ if self.lastErr == nil {
+ self.lastErr = err
+ }
+}
diff --git a/pkg/php_session_decoder/php_serialize/unserialize.go b/pkg/php_session_decoder/php_serialize/unserialize.go
new file mode 100644
index 0000000..9ef3340
--- /dev/null
+++ b/pkg/php_session_decoder/php_serialize/unserialize.go
@@ -0,0 +1,315 @@
+package php_serialize
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "strconv"
+ "strings"
+)
+
+const UNSERIALIZABLE_OBJECT_MAX_LEN = 10 * 1024 * 1024 * 1024
+
+func UnSerialize(s string) (PhpValue, error) {
+ decoder := NewUnSerializer(s)
+ decoder.SetSerializedDecodeFunc(SerializedDecodeFunc(UnSerialize))
+ return decoder.Decode()
+}
+
+type UnSerializer struct {
+ source string
+ r *strings.Reader
+ lastErr error
+ decodeFunc SerializedDecodeFunc
+}
+
+func NewUnSerializer(data string) *UnSerializer {
+ return &UnSerializer{
+ source: data,
+ }
+}
+
+func (self *UnSerializer) SetReader(r *strings.Reader) {
+ self.r = r
+}
+
+func (self *UnSerializer) SetSerializedDecodeFunc(f SerializedDecodeFunc) {
+ self.decodeFunc = f
+}
+
+func (self *UnSerializer) Decode() (PhpValue, error) {
+ if self.r == nil {
+ self.r = strings.NewReader(self.source)
+ }
+
+ var value PhpValue
+
+ if token, _, err := self.r.ReadRune(); err == nil {
+ switch token {
+ default:
+ self.saveError(fmt.Errorf("php_serialize: Unknown token %#U", token))
+ case TOKEN_NULL:
+ value = self.decodeNull()
+ case TOKEN_BOOL:
+ value = self.decodeBool()
+ case TOKEN_INT:
+ value = self.decodeNumber(false)
+ case TOKEN_FLOAT:
+ value = self.decodeNumber(true)
+ case TOKEN_STRING:
+ value = self.decodeString(DELIMITER_STRING_LEFT, DELIMITER_STRING_RIGHT, true)
+ case TOKEN_ARRAY:
+ value = self.decodeArray()
+ case TOKEN_OBJECT:
+ value = self.decodeObject()
+ case TOKEN_OBJECT_SERIALIZED:
+ value = self.decodeSerialized()
+ case TOKEN_REFERENCE, TOKEN_REFERENCE_OBJECT:
+ value = self.decodeReference()
+ case TOKEN_SPL_ARRAY:
+ value = self.decodeSplArray()
+
+ }
+ }
+
+ return value, self.lastErr
+}
+
+func (self *UnSerializer) decodeNull() PhpValue {
+ self.expect(SEPARATOR_VALUES)
+ return nil
+}
+
+func (self *UnSerializer) decodeBool() PhpValue {
+ var (
+ raw rune
+ err error
+ )
+ self.expect(SEPARATOR_VALUE_TYPE)
+
+ if raw, _, err = self.r.ReadRune(); err != nil {
+ self.saveError(fmt.Errorf("php_serialize: Error while reading bool value: %v", err))
+ }
+
+ self.expect(SEPARATOR_VALUES)
+ return raw == '1'
+}
+
+func (self *UnSerializer) decodeNumber(isFloat bool) PhpValue {
+ var (
+ raw string
+ err error
+ val PhpValue
+ )
+ self.expect(SEPARATOR_VALUE_TYPE)
+
+ if raw, err = self.readUntil(SEPARATOR_VALUES); err != nil {
+ self.saveError(fmt.Errorf("php_serialize: Error while reading number value: %v", err))
+ } else {
+ if isFloat {
+ if val, err = strconv.ParseFloat(raw, 64); err != nil {
+ self.saveError(fmt.Errorf("php_serialize: Unable to convert %s to float: %v", raw, err))
+ }
+ } else {
+ if val, err = strconv.Atoi(raw); err != nil {
+ self.saveError(fmt.Errorf("php_serialize: Unable to convert %s to int: %v", raw, err))
+ }
+ }
+ }
+
+ return val
+}
+
+func (self *UnSerializer) decodeString(left, right rune, isFinal bool) PhpValue {
+ var (
+ err error
+ val PhpValue
+ strLen int
+ readLen int
+ )
+
+ strLen = self.readLen()
+ self.expect(left)
+
+ if strLen > 0 {
+ buf := make([]byte, strLen)
+ if readLen, err = self.r.Read(buf); err != nil {
+ self.saveError(fmt.Errorf("php_serialize: Error while reading string value: %v", err))
+ } else {
+ if readLen != strLen {
+ self.saveError(fmt.Errorf("php_serialize: Unable to read string. Expected %d but have got %d bytes", strLen, readLen))
+ } else {
+ val = string(buf)
+ }
+ }
+ }
+
+ self.expect(right)
+ if isFinal {
+ self.expect(SEPARATOR_VALUES)
+ }
+ return val
+}
+
+func (self *UnSerializer) decodeArray() PhpValue {
+ var arrLen int
+ val := make(PhpArray)
+
+ arrLen = self.readLen()
+ self.expect(DELIMITER_OBJECT_LEFT)
+
+ for i := 0; i < arrLen; i++ {
+ k, errKey := self.Decode()
+ v, errVal := self.Decode()
+
+ if errKey == nil && errVal == nil {
+ val[k] = v
+ /*switch t := k.(type) {
+ default:
+ self.saveError(fmt.Errorf("php_serialize: Unexpected key type %T", t))
+ case string:
+ stringKey, _ := k.(string)
+ val[stringKey] = v
+ case int:
+ intKey, _ := k.(int)
+ val[strconv.Itoa(intKey)] = v
+ }*/
+ } else {
+ self.saveError(fmt.Errorf("php_serialize: Error while reading key or(and) value of array"))
+ }
+ }
+
+ self.expect(DELIMITER_OBJECT_RIGHT)
+ return val
+}
+
+func (self *UnSerializer) decodeObject() PhpValue {
+ val := &PhpObject{
+ className: self.readClassName(),
+ }
+
+ rawMembers := self.decodeArray()
+ val.members, _ = rawMembers.(PhpArray)
+
+ return val
+}
+
+func (self *UnSerializer) decodeSerialized() PhpValue {
+ val := &PhpObjectSerialized{
+ className: self.readClassName(),
+ }
+
+ rawData := self.decodeString(DELIMITER_OBJECT_LEFT, DELIMITER_OBJECT_RIGHT, false)
+ val.data, _ = rawData.(string)
+
+ if self.decodeFunc != nil && val.data != "" {
+ var err error
+ if val.value, err = self.decodeFunc(val.data); err != nil {
+ self.saveError(err)
+ }
+ }
+
+ return val
+}
+
+func (self *UnSerializer) decodeReference() PhpValue {
+ self.expect(SEPARATOR_VALUE_TYPE)
+ if _, err := self.readUntil(SEPARATOR_VALUES); err != nil {
+ self.saveError(fmt.Errorf("php_serialize: Error while reading reference value: %v", err))
+ }
+ return nil
+}
+
+func (self *UnSerializer) expect(expected rune) {
+ if token, _, err := self.r.ReadRune(); err != nil {
+ self.saveError(fmt.Errorf("php_serialize: Error while reading expected rune %#U: %v", expected, err))
+ } else if token != expected {
+ if debugMode {
+ log.Printf("php_serialize: source\n%s\n", self.source)
+ log.Printf("php_serialize: reader info\n%#v\n", self.r)
+ }
+ self.saveError(fmt.Errorf("php_serialize: Expected %#U but have got %#U", expected, token))
+ }
+}
+
+func (self *UnSerializer) readUntil(stop rune) (string, error) {
+ var (
+ token rune
+ err error
+ )
+ buf := bytes.NewBuffer([]byte{})
+
+ for {
+ if token, _, err = self.r.ReadRune(); err != nil || token == stop {
+ break
+ } else {
+ buf.WriteRune(token)
+ }
+ }
+
+ return buf.String(), err
+}
+
+func (self *UnSerializer) readLen() int {
+ var (
+ raw string
+ err error
+ val int
+ )
+ self.expect(SEPARATOR_VALUE_TYPE)
+
+ if raw, err = self.readUntil(SEPARATOR_VALUE_TYPE); err != nil {
+ self.saveError(fmt.Errorf("php_serialize: Error while reading lenght of value: %v", err))
+ } else {
+ if val, err = strconv.Atoi(raw); err != nil {
+ self.saveError(fmt.Errorf("php_serialize: Unable to convert %s to int: %v", raw, err))
+ } else if val > UNSERIALIZABLE_OBJECT_MAX_LEN {
+ self.saveError(fmt.Errorf("php_serialize: Unserializable object length looks too big(%d). If you are sure you wanna unserialise it, please increase UNSERIALIZABLE_OBJECT_MAX_LEN const", val))
+ val = 0
+ }
+ }
+ return val
+}
+
+func (self *UnSerializer) readClassName() (res string) {
+ rawClass := self.decodeString(DELIMITER_STRING_LEFT, DELIMITER_STRING_RIGHT, false)
+ res, _ = rawClass.(string)
+ return
+}
+
+func (self *UnSerializer) saveError(err error) {
+ if self.lastErr == nil {
+ self.lastErr = err
+ }
+}
+
+func (self *UnSerializer) decodeSplArray() PhpValue {
+ var err error
+ val := &PhpSplArray{}
+
+ self.expect(SEPARATOR_VALUE_TYPE)
+ self.expect(TOKEN_INT)
+
+ flags := self.decodeNumber(false)
+ if flags == nil {
+ self.saveError(fmt.Errorf("php_serialize: Unable to read flags of SplArray"))
+ return nil
+ }
+ val.flags = PhpValueInt(flags)
+
+ if val.array, err = self.Decode(); err != nil {
+ self.saveError(fmt.Errorf("php_serialize: Can't parse SplArray: %v", err))
+ return nil
+ }
+
+ self.expect(SEPARATOR_VALUES)
+ self.expect(TOKEN_SPL_ARRAY_MEMBERS)
+ self.expect(SEPARATOR_VALUE_TYPE)
+
+ if val.properties, err = self.Decode(); err != nil {
+ self.saveError(fmt.Errorf("php_serialize: Can't parse properties of SplArray: %v", err))
+ return nil
+ }
+
+ return val
+}
diff --git a/pkg/point/point.go b/pkg/point/point.go
new file mode 100644
index 0000000..f62c176
--- /dev/null
+++ b/pkg/point/point.go
@@ -0,0 +1,26 @@
+package point
+
+func PointLevel(point int64) int32 {
+ if point <= 50 {
+ return 1
+ }
+ if point > 50 && point <= 200 {
+ return 2
+ }
+ if point > 200 && point <= 500 {
+ return 3
+ }
+ if point > 500 && point <= 1000 {
+ return 4
+ }
+ if point > 1000 && point <= 2500 {
+ return 5
+ }
+ if point > 2500 && point <= 5000 {
+ return 6
+ }
+ if point > 5000 && point <= 8000 {
+ return 7
+ }
+ return 8
+}
diff --git a/pkg/transurl/transurl.go b/pkg/transurl/transurl.go
new file mode 100644
index 0000000..85f00a0
--- /dev/null
+++ b/pkg/transurl/transurl.go
@@ -0,0 +1,48 @@
+package transurl
+
+var urlMap = map[string]string{
+ "/beijing": "/question-list/alatest/1",
+ "/shanghai": "/question-list/alatest/2",
+ "/guangzhou": "/question-list/alatest/54",
+ "/shenzhen": "/question-list/alatest/55",
+ "/chengdu": "/question-list/alatest/63",
+ "/xi'an": "/question-list/alatest/64",
+ "/hangzhou": "/question-list/alatest/59",
+ "/qingdao": "/question-list/alatest/65",
+ "/dalian": "/question-list/alatest/69",
+ "/suzhou": "/question-list/alatest/67",
+ "/nanjing": "/question-list/alatest/68",
+ "/arts-entertainment": "/question-list/alatest/34",
+ "/business-jobs": "/question-list/alatest/3",
+ "/culture": "/question-list/alatest/4",
+ "/falimy-kids": "/question-list/alatest/45",
+ "/food": "/question-list/alatest/35",
+ "/general": "/question-list/alatest/36",
+ "/health-safety": "/question-list/alatest/39",
+ "/housing": "/question-list/alatest/49",
+ "/lifestyle": "/question-list/alatest/1058",
+ "/money-banking": "/question-list/alatest/1059",
+ "/relationships": "/question-list/alatest/53",
+ "/shopping": "/question-list/alatest/41",
+ "/sports": "/question-list/alatest/95",
+ "/teaching-learning": "/question-list/alatest/43",
+ "/transport-travel": "/question-list/alatest/47",
+ "/visa-legalities": "/question-list/alatest/48",
+ "/web-technology": "/question-list/alatest/44",
+}
+
+func GetLonUrl(src string) string {
+ if v, ok := urlMap[src]; ok {
+ return v
+ }
+ return src
+}
+
+func GetShortUrl(dst string) string {
+ for src, dt := range urlMap {
+ if dt == dst {
+ return src
+ }
+ }
+ return dst
+}
diff --git a/pkg/xarray/xarray.go b/pkg/xarray/xarray.go
new file mode 100644
index 0000000..5e3a58b
--- /dev/null
+++ b/pkg/xarray/xarray.go
@@ -0,0 +1,53 @@
+package xarray
+
+import (
+ "reflect"
+ "strings"
+)
+
+func ToSlice(slice interface{}) []interface{} {
+ s := reflect.ValueOf(slice)
+ if s.Kind() != reflect.Slice {
+ panic("InterfaceSlice() given a non-slice type")
+ }
+
+ ret := make([]interface{}, s.Len())
+
+ for i := 0; i < s.Len(); i++ {
+ ret[i] = s.Index(i).Interface()
+ }
+
+ return ret
+}
+
+func ToCountMap(strArr []string) map[string]int64 {
+ mps := make(map[string]int64)
+ for _, v := range strArr {
+ mps[strings.ToLower(v)]++
+ }
+ return mps
+}
+
+func InArray(need interface{}, list []interface{}) bool {
+ for _, v := range list {
+ if need == v {
+ return true
+ }
+ }
+ return false
+}
+func UniqArray(list []int64) []int64 {
+ result := make([]int64, 0)
+ if len(list) == 0 {
+ return result
+ }
+ mp := make(map[int64]bool)
+ for _, v := range list {
+ if mp[v] {
+ continue
+ }
+ result = append(result, v)
+ mp[v] = true
+ }
+ return result
+}
diff --git a/xerrors/errors.go b/pkg/xerrors/errors.go
similarity index 100%
rename from xerrors/errors.go
rename to pkg/xerrors/errors.go
diff --git a/xerrors/types.go b/pkg/xerrors/types.go
similarity index 100%
rename from xerrors/types.go
rename to pkg/xerrors/types.go
diff --git a/pkg/xhttp/xhttp.go b/pkg/xhttp/xhttp.go
new file mode 100644
index 0000000..15d27d0
--- /dev/null
+++ b/pkg/xhttp/xhttp.go
@@ -0,0 +1,189 @@
+package xhttp
+
+import (
+ "crypto/tls"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+)
+
+const timeout = time.Second * 120
+
+func Request(method string, reqUrl string, postData string, header http.Header) (string, error) {
+ var res string
+ transport := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+ }
+ client := &http.Client{
+ Transport: transport,
+ Timeout: timeout,
+ }
+ var ioreader io.Reader
+ if postData != "" {
+ ioreader = strings.NewReader(postData)
+ }
+ req, err := http.NewRequest(method, reqUrl, ioreader)
+ if err != nil {
+ return res, err
+ }
+ if header != nil {
+ req.Header = header
+ }
+
+ resp, err := client.Do(req)
+ if err != nil {
+ return res, err
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode == 200 {
+ byt, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return res, err
+ }
+ return string(byt), nil
+ } else {
+ return res, fmt.Errorf("code:%d message:%s", resp.StatusCode, resp.Status)
+ }
+}
+func Get(reqUrl string, timeout time.Duration) (string, error) {
+ var res string
+ transport := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+ }
+ client := &http.Client{
+ Transport: transport,
+ Timeout: timeout,
+ }
+ req, err := http.NewRequest("GET", reqUrl, nil)
+ if err != nil {
+ return res, err
+ }
+ resp, err := client.Do(req)
+ if err != nil {
+ return res, err
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode == 200 {
+ byt, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return res, err
+ }
+ return string(byt), nil
+ } else {
+ return res, fmt.Errorf("code:%d message:%s", resp.StatusCode, resp.Status)
+ }
+}
+func fetcher(method, u, post string, headers map[string]string, timeout int64) (*[]byte, error) {
+ transport := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+ }
+ client := &http.Client{
+ Transport: transport,
+ Timeout: time.Second * time.Duration(timeout),
+ }
+ req, err := http.NewRequest(method, u, strings.NewReader(post))
+ if err != nil {
+ return nil, err
+ }
+ for k, v := range headers {
+ req.Header.Add(k, v)
+ }
+ resp, err := client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ if resp.StatusCode != http.StatusOK {
+ return nil, fmt.Errorf("FetchUrl status:%s", resp.Status)
+ }
+ return &body, err
+}
+
+func PostForm(u, post string, headers map[string]string) (*[]byte, error) {
+ if headers == nil {
+ headers = make(map[string]string)
+ }
+ headers["Content-Type"] = "application/x-www-form-urlencoded"
+ return fetcher("POST", u, post, headers, 60)
+}
+
+func PostJson(u, post string, headers map[string]string) (*[]byte, error) {
+ if headers == nil {
+ headers = make(map[string]string)
+ }
+
+ headers["Content-Type"] = "application/json;charset=UTF-8"
+ fmt.Printf("%+v\n", post)
+ fmt.Printf("%+v\n", headers)
+ return fetcher("POST", u, post, headers, 60)
+}
+
+func GetWithHeader(u string, headers map[string]string) (*[]byte, error) {
+ if headers == nil {
+ headers = make(map[string]string)
+ }
+ return fetcher("GET", u, "", headers, 60)
+}
+
+type apiRes struct {
+ Status int64 `json:"status"`
+}
+
+func SenEmail(u string, data map[string]string) error {
+ fmt.Println(u)
+ postByte, _ := json.Marshal(data)
+ fmt.Printf("%s\n", postByte)
+ values := url.Values{}
+ for k, v := range data {
+ values.Add(k, v)
+ }
+ fmt.Println(data)
+ res, err := PostForm(u, values.Encode(), nil)
+ if err != nil {
+ return err
+ }
+ fmt.Printf("%s\n", *res)
+ result := apiRes{}
+ if err := json.Unmarshal(*res, &result); err != nil {
+ return err
+ }
+ if result.Status != 200 {
+ return errors.New(string(*res))
+ }
+ return nil
+}
+
+type shotResp struct {
+ Code int64 `json:"code"`
+ Info string `json:"info"`
+ Message string `json:"message"`
+}
+
+func ShotUrl(u string) (string, error) {
+ values := url.Values{}
+ values.Add("long_url", u)
+ res, err := PostForm(`https://echinajobs.cn/add`, values.Encode(), nil)
+ if err != nil {
+ return "", err
+ }
+ result := shotResp{}
+ if err := json.Unmarshal(*res, &result); err != nil {
+ return "", err
+ }
+ if result.Code != 200 {
+ return "", errors.New(string(*res))
+ }
+ return result.Info, nil
+}
diff --git a/pkg/xip/xip.go b/pkg/xip/xip.go
new file mode 100644
index 0000000..c538628
--- /dev/null
+++ b/pkg/xip/xip.go
@@ -0,0 +1,13 @@
+package xip
+
+import (
+ "context"
+ "github.com/gin-gonic/gin"
+)
+
+func GetIpFromContext(ctx context.Context) string {
+ if v, ok := ctx.(*gin.Context); ok {
+ return v.ClientIP()
+ }
+ return ""
+}
diff --git a/xjson/xjson.go b/pkg/xjson/xjson.go
similarity index 91%
rename from xjson/xjson.go
rename to pkg/xjson/xjson.go
index 0ae55e2..7c7db34 100644
--- a/xjson/xjson.go
+++ b/pkg/xjson/xjson.go
@@ -8,6 +8,14 @@ import (
"reflect"
)
+func MustMarshal(data any) string {
+ b, err := json.Marshal(data)
+ if err != nil {
+ return ""
+ }
+ return string(b)
+}
+
var (
// MarshalOptions is a configurable JSON format marshaller.
MarshalOptions = protojson.MarshalOptions{
diff --git a/xlog/xlog.go b/pkg/xlog/xlog.go
similarity index 100%
rename from xlog/xlog.go
rename to pkg/xlog/xlog.go
diff --git a/pkg/xmath/math.go b/pkg/xmath/math.go
new file mode 100644
index 0000000..20eb547
--- /dev/null
+++ b/pkg/xmath/math.go
@@ -0,0 +1,77 @@
+package xmath
+
+import (
+ "fmt"
+ //"github.com/shopspring/decimal"
+ "math"
+ "math/rand"
+ "strconv"
+ "strings"
+)
+
+// 小数点后 n 位 - 四舍五入
+func RoundedFixed(val float64, n int) float64 {
+ shift := math.Pow(10, float64(n))
+ fv := 0.0000000001 + val //对浮点数产生.xxx999999999 计算不准进行处理
+ return math.Floor(fv*shift+.5) / shift
+}
+
+// 小数点后 n 位 - 舍去
+func TruncRound(val float64, n int) float64 {
+ floatStr := fmt.Sprintf("%."+strconv.Itoa(n+1)+"f", val)
+ temp := strings.Split(floatStr, ".")
+ var newFloat string
+ if len(temp) < 2 || n >= len(temp[1]) {
+ newFloat = floatStr
+ } else {
+ newFloat = temp[0] + "." + temp[1][:n]
+ }
+ inst, _ := strconv.ParseFloat(newFloat, 64)
+ return inst
+}
+
+// RandInt64 随机范围取值
+func RandInt64(min, max int64) int64 {
+ if min >= max || min == 0 || max == 0 {
+ return max
+ }
+ return rand.Int63n(max-min) + min
+}
+func FloatWithoutRightDot(n float64) string {
+ s := fmt.Sprintf("%.2f", n)
+ ss := strings.Split(s, ".")
+ ss1 := strings.TrimRight(ss[1], "0")
+ if ss1 == "" {
+ return ss[0]
+ } else {
+ return fmt.Sprintf("%s.%s", ss[0], ss1)
+ }
+}
+
+func NumberFormat(str string) string {
+ length := len(str)
+ if length < 4 {
+ return str
+ }
+ arr := strings.Split(str, ".") //用小数点符号分割字符串,为数组接收
+ length1 := len(arr[0])
+ if length1 < 4 {
+ return str
+ }
+ count := (length1 - 1) / 3
+ for i := 0; i < count; i++ {
+ arr[0] = arr[0][:length1-(i+1)*3] + "," + arr[0][length1-(i+1)*3:]
+ }
+ return strings.Join(arr, ".") //将一系列字符串连接为一个字符串,之间用sep来分隔。
+}
+
+func ConvertInt64(s string) int64 {
+ v, _ := strconv.ParseInt(s, 10, 64)
+ return v
+}
+
+//
+//func Round(f float64, n int32) float64 {
+// v, _ := decimal.NewFromFloat(f).Round(n).Float64()
+// return v
+//}
diff --git a/pkg/xmd5/md5.go b/pkg/xmd5/md5.go
new file mode 100644
index 0000000..22026fb
--- /dev/null
+++ b/pkg/xmd5/md5.go
@@ -0,0 +1,12 @@
+package xmd5
+
+import (
+ "crypto/md5"
+ "encoding/hex"
+)
+
+func MD5(str string) string {
+ s := md5.New()
+ s.Write([]byte(str))
+ return hex.EncodeToString(s.Sum(nil))
+}
diff --git a/pkg/xpage/xpage.go b/pkg/xpage/xpage.go
new file mode 100644
index 0000000..0c3cab2
--- /dev/null
+++ b/pkg/xpage/xpage.go
@@ -0,0 +1,8 @@
+package xpage
+
+func GetPageOffset(page int32, size int32) int {
+ if page < 1 {
+ page = 1
+ }
+ return int((page - 1) * size)
+}
diff --git a/pkg/xredis/xredis.go b/pkg/xredis/xredis.go
new file mode 100644
index 0000000..dceb8ca
--- /dev/null
+++ b/pkg/xredis/xredis.go
@@ -0,0 +1,59 @@
+package xredis
+
+//
+//import (
+// "context"
+// "encoding/json"
+// "fmt"
+// "github.com/go-redis/redis/v8"
+// "github.com/pkg/errors"
+// "time"
+//)
+//
+//var redisClient *redis.Client
+//
+//func Init(host, password string, db int) error {
+// redisClient = redis.NewClient(&redis.Options{
+// Network: "tcp",
+// Addr: host,
+// Password: password,
+// DB: db,
+// })
+// return redisClient.Ping(context.Background()).Err()
+//}
+//
+//func Client() *redis.Client {
+// return redisClient
+//}
+//
+//func GetData[T any](ctx context.Context, key string, fn func() (T, error), dur time.Duration) (T, error) {
+// var result T
+// res := redisClient.Get(ctx, key).Val()
+// if res != "" {
+// err := json.Unmarshal([]byte(res), &result)
+// if err == nil {
+// return result, nil
+// }
+// }
+// r, err := fn()
+// if err != nil {
+// return result, err
+// }
+// if b, err := json.Marshal(r); err == nil {
+// redisClient.Set(ctx, key, string(b), dur)
+// }
+// return r, nil
+//}
+//func Lock[T any](ctx context.Context, key string, fn func() (T, error)) (T, error) {
+// var res T
+// lockKey := fmt.Sprintf("lock:%s", key)
+// ok, err := redisClient.SetNX(ctx, lockKey, 1, time.Second*20).Result()
+// if err != nil {
+// return res, errors.Wrap(err, "")
+// }
+// if !ok {
+// return res, errors.Wrap(errors.New(fmt.Sprintf("lock %s exists", lockKey)), "")
+// }
+// defer redisClient.Del(ctx, lockKey)
+// return fn()
+//}
diff --git a/pkg/xredis/xredis_test.go b/pkg/xredis/xredis_test.go
new file mode 100644
index 0000000..d93be3c
--- /dev/null
+++ b/pkg/xredis/xredis_test.go
@@ -0,0 +1,28 @@
+package xredis
+
+import (
+ "context"
+ "fmt"
+ "testing"
+ "time"
+)
+
+type Res struct {
+ Name string
+}
+
+func TestGetData(t *testing.T) {
+ _ = Init("localhost:6379", "", 1)
+ res, err := GetData(context.Background(), "userId1212", func() (*Res, error) {
+ fmt.Println("from db")
+ in := &Res{
+ Name: "ttt",
+ }
+ return in, nil
+ }, time.Second*50)
+
+ if err != nil {
+ t.Error(err)
+ }
+ fmt.Printf("%+v\n", res)
+}
diff --git a/response/response.go b/pkg/xresponse/xresponse.go
similarity index 93%
rename from response/response.go
rename to pkg/xresponse/xresponse.go
index a13ac7f..df73a36 100644
--- a/response/response.go
+++ b/pkg/xresponse/xresponse.go
@@ -1,9 +1,9 @@
-package response
+package xresponse
import (
"encoding/json"
- "git.diulo.com/mogfee/protoc-gen-kit/xerrors"
- "git.diulo.com/mogfee/protoc-gen-kit/xstring"
+ "git.diulo.com/mogfee/protoc-gen-kit/pkg/xerrors"
+ "git.diulo.com/mogfee/protoc-gen-kit/pkg/xstring"
"github.com/gin-gonic/gin"
"github.com/go-playground/form"
"net/http"
diff --git a/xserver/consumer.go b/pkg/xserver/consumer.go
similarity index 100%
rename from xserver/consumer.go
rename to pkg/xserver/consumer.go
diff --git a/xserver/cron.go b/pkg/xserver/cron.go
similarity index 100%
rename from xserver/cron.go
rename to pkg/xserver/cron.go
diff --git a/xserver/http.go b/pkg/xserver/http.go
similarity index 100%
rename from xserver/http.go
rename to pkg/xserver/http.go
diff --git a/xserver/xserver.go b/pkg/xserver/xserver.go
similarity index 100%
rename from xserver/xserver.go
rename to pkg/xserver/xserver.go
diff --git a/pkg/xstring/stringx.go b/pkg/xstring/stringx.go
new file mode 100644
index 0000000..f8aba13
--- /dev/null
+++ b/pkg/xstring/stringx.go
@@ -0,0 +1,656 @@
+package xstring
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "github.com/PuerkitoBio/goquery"
+ "github.com/pkg/errors"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "unicode"
+)
+
+func TableFieldNames(obj any) ([]string, string) {
+ v := reflect.TypeOf(obj)
+ cols := []string{}
+ primary := ""
+ for i := 0; i < v.NumField(); i++ {
+ cols = append(cols, v.Field(i).Tag.Get("db"))
+ if primary == "" {
+ primary = v.Field(i).Tag.Get("primaryKey")
+ }
+ }
+ return cols, primary
+}
+
+func Remove[T string](cols []T, key T) []T {
+ arr := make([]T, 0)
+ for _, v := range cols {
+ if key != v {
+ arr = append(arr, v)
+ }
+ }
+ return arr
+}
+
+func NamedSql(cls []string) string {
+ str := []string{}
+ for _, v := range cls {
+ str = append(str, fmt.Sprintf("%s=:%s", v, v))
+ }
+ return strings.Join(str, ",")
+}
+
+func StripTags(content string) string {
+ re := regexp.MustCompile(`<(.|\n)*?>`)
+ return re.ReplaceAllString(content, "")
+}
+func SubString(str string, begin, length int) string {
+ rs := []rune(str)
+ lth := len(rs)
+ if begin < 0 {
+ begin = 0
+ }
+ if begin >= lth {
+ begin = lth
+ }
+ end := begin + length
+
+ if end > lth {
+ end = lth
+ }
+ return string(rs[begin:end])
+}
+func Nl2br(str string) string {
+ return strings.Join(strings.Split(strings.Join(strings.Split(str, "\r"), "
"), "\n"), "
")
+}
+
+func Serialize(value interface{}) ([]byte, error) {
+
+ if value == nil {
+ return MarshalNil(), nil
+ }
+
+ t := reflect.TypeOf(value)
+ switch t.Kind() {
+ case reflect.Bool:
+ return MarshalBool(value.(bool)), nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+ reflect.Float32, reflect.Float64:
+ return MarshalNumber(value), nil
+ case reflect.String:
+ return MarshalString(value.(string)), nil
+ case reflect.Map:
+ return MarshalMap(value)
+ case reflect.Slice:
+ return MarshalSlice(value)
+ default:
+ return nil, fmt.Errorf("Marshal: Unknown type %T with value %#v", t, value)
+ }
+}
+
+func MarshalNil() []byte {
+ return []byte("N;")
+}
+
+func MarshalBool(value bool) []byte {
+ if value {
+ return []byte("b:1;")
+ }
+
+ return []byte("b:0;")
+}
+
+func MarshalNumber(value interface{}) []byte {
+ var val string
+
+ isFloat := false
+
+ switch value.(type) {
+ default:
+ val = "0"
+ case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
+ val, _ = NumericalToString(value)
+ case float32, float64:
+ val, _ = NumericalToString(value)
+ isFloat = true
+ }
+
+ if isFloat {
+ return []byte("d:" + val + ";")
+
+ } else {
+ return []byte("i:" + val + ";")
+ }
+}
+func NumericalValue(value reflect.Value) (float64, bool) {
+ switch value.Type().Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return float64(value.Int()), true
+
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return float64(value.Uint()), true
+
+ case reflect.Float32, reflect.Float64:
+ return value.Float(), true
+
+ default:
+ return 0, false
+ }
+}
+func MarshalString(value string) []byte {
+ return []byte(fmt.Sprintf("s:%d:\"%s\";", len(value), value))
+}
+func LessValue(a, b reflect.Value) bool {
+ aValue, aNumerical := NumericalValue(a)
+ bValue, bNumerical := NumericalValue(b)
+
+ if aNumerical && bNumerical {
+ return aValue < bValue
+ }
+
+ if !aNumerical && !bNumerical {
+ // In theory this should mean they are both strings. In reality
+ // they could be any other type and the String() representation
+ // will be something like "" if it is not a string. Since
+ // distinct values of non-strings still return the same value
+ // here that's what makes the ordering undefined.
+ return strings.Compare(a.String(), b.String()) < 0
+ }
+
+ // Numerical values are always treated as less than other types
+ // (including strings that might represent numbers themselves). The
+ // inverse is also true.
+ return aNumerical && !bNumerical
+}
+
+func MarshalMap(value interface{}) ([]byte, error) {
+
+ s := reflect.ValueOf(value)
+
+ mapKeys := s.MapKeys()
+ sort.Slice(mapKeys, func(i, j int) bool {
+ return LessValue(mapKeys[i], mapKeys[j])
+ })
+
+ var buffer bytes.Buffer
+ for _, mapKey := range mapKeys {
+ m, err := Serialize(mapKey.Interface())
+ if err != nil {
+ return nil, err
+ }
+
+ buffer.Write(m)
+
+ m, err = Serialize(s.MapIndex(mapKey).Interface())
+ if err != nil {
+ return nil, err
+ }
+
+ buffer.Write(m)
+ }
+
+ return []byte(fmt.Sprintf("a:%d:{%s}", s.Len(), buffer.String())), nil
+}
+
+func MarshalSlice(value interface{}) ([]byte, error) {
+ s := reflect.ValueOf(value)
+
+ var buffer bytes.Buffer
+ for i := 0; i < s.Len(); i++ {
+ m, err := Serialize(i)
+ if err != nil {
+ return nil, err
+ }
+
+ buffer.Write(m)
+
+ m, err = Serialize(s.Index(i).Interface())
+ if err != nil {
+ return nil, err
+ }
+
+ buffer.Write(m)
+ }
+
+ return []byte(fmt.Sprintf("a:%d:{%s}", s.Len(), buffer.String())), nil
+}
+
+const UNSERIALIZABLE_OBJECT_MAX_LEN = int64(10 * 1024 * 1024 * 1024)
+
+func UnSerialize(data []byte) (interface{}, error) {
+ reader := bytes.NewReader(data)
+ return unMarshalByReader(reader)
+}
+
+func UnSerializeBind(data []byte, post any) error {
+ reader := bytes.NewReader(data)
+ b, err := unMarshalByReader(reader)
+ if err != nil {
+ return errors.Wrap(err, "")
+ }
+ bb, err := json.Marshal(b)
+ if err != nil {
+ return errors.Wrap(err, "")
+ }
+ err = json.Unmarshal(bb, post)
+ return errors.Wrap(err, "")
+}
+
+func unMarshalByReader(reader *bytes.Reader) (interface{}, error) {
+
+ for {
+
+ if token, _, err := reader.ReadRune(); err == nil {
+ switch token {
+ default:
+ return nil, fmt.Errorf("UnMarshal: Unknown token %#U", token)
+ case 'N':
+ return unMarshalNil(reader)
+ case 'b':
+ return unMarshalBool(reader)
+ case 'i':
+ return unMarshalNumber(reader, false)
+ case 'd':
+ return unMarshalNumber(reader, true)
+ case 's':
+ return unMarshalString(reader, true)
+ case 'a':
+ return unMarshalArray(reader)
+ // case 'O':
+
+ // case 'C':
+
+ // case 'R', 'r':
+
+ // case 'x':
+
+ }
+ }
+ }
+
+}
+
+func unMarshalNil(reader *bytes.Reader) (interface{}, error) {
+ _ = expect(reader, ';')
+
+ return nil, nil
+}
+
+func unMarshalBool(reader *bytes.Reader) (interface{}, error) {
+ var (
+ raw rune
+ err error
+ )
+ err = expect(reader, ':')
+ if err != nil {
+ return nil, err
+ }
+
+ if raw, _, err = reader.ReadRune(); err != nil {
+ return nil, fmt.Errorf("UnMarshal: Error while reading bool value: %v", err)
+ }
+
+ err = expect(reader, ';')
+ if err != nil {
+ return nil, err
+ }
+ return raw == '1', nil
+}
+
+func unMarshalNumber(reader *bytes.Reader, isFloat bool) (interface{}, error) {
+ var (
+ raw string
+ err error
+ val interface{}
+ )
+ err = expect(reader, ':')
+ if err != nil {
+ return nil, err
+ }
+
+ if raw, err = readUntil(reader, ';'); err != nil {
+ return nil, fmt.Errorf("UnMarshal: Error while reading number value: %v", err)
+ } else {
+ if isFloat {
+ if val, err = strconv.ParseFloat(raw, 64); err != nil {
+ return nil, fmt.Errorf("UnMarshal: Unable to convert %s to float: %v", raw, err)
+ }
+ } else {
+ if val, err = strconv.Atoi(raw); err != nil {
+ return nil, fmt.Errorf("UnMarshal: Unable to convert %s to int: %v", raw, err)
+ }
+ }
+ }
+
+ return val, nil
+}
+
+func unMarshalString(reader *bytes.Reader, isFinal bool) (interface{}, error) {
+ var (
+ err error
+ val interface{}
+ strLen int
+ readLen int
+ )
+
+ strLen, err = readLength(reader)
+ if err != nil {
+ return nil, err
+ }
+ err = expect(reader, '"')
+ if err != nil {
+ return nil, err
+ }
+
+ if strLen > 0 {
+ buf := make([]byte, strLen)
+ if readLen, err = reader.Read(buf); err != nil {
+ return nil, fmt.Errorf("UnMarshal: Error while reading string value: %v", err)
+ } else {
+ if readLen != strLen {
+ return nil, fmt.Errorf("UnMarshal: Unable to read string. Expected %d but have got %d bytes", strLen, readLen)
+ } else {
+ val = string(buf)
+ }
+ }
+ }
+
+ err = expect(reader, '"')
+ if err != nil {
+ return nil, err
+ }
+ if isFinal {
+ err = expect(reader, ';')
+ if err != nil {
+ return nil, err
+ }
+ }
+ return val, nil
+}
+
+func unMarshalArray(reader *bytes.Reader) (interface{}, error) {
+ var arrLen int
+ var err error
+ val := make(map[string]interface{})
+
+ arrLen, err = readLength(reader)
+
+ if err != nil {
+ return nil, err
+ }
+ err = expect(reader, '{')
+ if err != nil {
+ return nil, err
+ }
+ indexLen := 0
+ for i := 0; i < arrLen; i++ {
+ k, err := unMarshalByReader(reader)
+ if err != nil {
+ return nil, err
+ }
+ v, err := unMarshalByReader(reader)
+ if err != nil {
+ return nil, err
+ }
+
+ // if errKey == nil && errVal == nil {
+ // val[k] = v
+ switch t := k.(type) {
+ default:
+ return nil, fmt.Errorf("UnMarshal: Unexpected key type %T", t)
+ case string:
+ stringKey, _ := k.(string)
+ val[stringKey] = v
+ case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
+ // intKey, _ := k.(int)
+ // val[strconv.Itoa(intKey)] = v
+ stringKey, _ := NumericalToString(k)
+ val[stringKey] = v
+
+ // stringI, _ := utils.NumericalToString(i)
+ if i == k {
+ indexLen++
+ }
+
+ }
+ // } else {
+ // return nil, fmt.Errorf("UnMarshal: Error while reading key or(and) value of array")
+ // }
+ }
+
+ err = expect(reader, '}')
+ if err != nil {
+ return nil, err
+ }
+
+ if indexLen == arrLen {
+ var slice []interface{}
+ for _, row := range val {
+ slice = append(slice, row)
+ }
+ return slice, nil
+ }
+
+ return val, nil
+}
+
+func expect(reader *bytes.Reader, expected rune) error {
+ if token, _, err := reader.ReadRune(); err != nil {
+ return fmt.Errorf("UnMarshal: Error while reading expected rune %#U: %v", expected, err)
+ } else if token != expected {
+ return fmt.Errorf("UnMarshal: Expected %#U but have got %#U", expected, token)
+ }
+ return nil
+}
+
+func readUntil(reader *bytes.Reader, stop rune) (string, error) {
+ var (
+ token rune
+ err error
+ )
+ buf := bytes.NewBuffer([]byte{})
+
+ for {
+ if token, _, err = reader.ReadRune(); err != nil || token == stop {
+ break
+ } else {
+ buf.WriteRune(token)
+ }
+ }
+
+ return buf.String(), err
+}
+
+func readLength(reader *bytes.Reader) (int, error) {
+ var (
+ raw string
+ err error
+ val int
+ )
+ err = expect(reader, ':')
+ if err != nil {
+ return 0, err
+ }
+
+ if raw, err = readUntil(reader, ':'); err != nil {
+ return 0, fmt.Errorf("UnMarshal: Error while reading lenght of value: %v", err)
+ } else {
+ if val, err = strconv.Atoi(raw); err != nil {
+ return 0, fmt.Errorf("UnMarshal: Unable to convert %s to int: %v", raw, err)
+ } else if int64(val) > UNSERIALIZABLE_OBJECT_MAX_LEN {
+ return 0, fmt.Errorf("UnMarshal: Unserializable object length looks too big(%d). If you are sure you wanna unserialise it, please increase UNSERIALIZABLE_OBJECT_MAX_LEN const", val)
+ }
+ }
+ return val, nil
+}
+
+func NumericalToString(value interface{}) (string, bool) {
+ var val string
+
+ switch intVal := value.(type) {
+ default:
+ return "0", false
+ case int:
+ val = strconv.FormatInt(int64(intVal), 10)
+ case int8:
+ val = strconv.FormatInt(int64(intVal), 10)
+ case int16:
+ val = strconv.FormatInt(int64(intVal), 10)
+ case int32:
+ val = strconv.FormatInt(int64(intVal), 10)
+ case int64:
+ val = strconv.FormatInt(int64(intVal), 10)
+ case uint:
+ val = strconv.FormatUint(uint64(intVal), 10)
+ case uint8:
+ val = strconv.FormatUint(uint64(intVal), 10)
+ case uint16:
+ val = strconv.FormatUint(uint64(intVal), 10)
+ case uint32:
+ val = strconv.FormatUint(uint64(intVal), 10)
+ case uint64:
+ val = strconv.FormatUint(intVal, 10)
+ case float32:
+ val = strconv.FormatFloat(float64(intVal), 'f', -1, 32)
+ case float64:
+ val = strconv.FormatFloat(intVal, 'f', -1, 64)
+ }
+ return val, true
+}
+
+//func StrToArr(str string) []string {
+// re := regexp.MustCompile(`<(.|\n)*?>`)
+// str = re.ReplaceAllString(str, " ")
+// str = strings.ReplaceAll(str, `"`, "")
+// str = strings.ReplaceAll(str, `'`, "")
+// str = strings.ReplaceAll(str, "`", "")
+// str = strings.ReplaceAll(str, ",", "")
+// str = strings.ReplaceAll(str, " ", "")
+// newStr := []string{}
+// tmp := ""
+// for i := 0; i < len(str); {
+// r, n := utf8.DecodeRuneInString(str[i:])
+// if n == 3 {
+// tmp = ""
+// newStr = append(newStr, string(r))
+// } else {
+//
+// if string(r) == " " {
+// newStr = append(newStr, tmp)
+// tmp = ""
+// } else if string(r) != "\n" {
+// tmp = fmt.Sprintf("%s%c", tmp, r)
+// }
+// }
+// i += n
+// }
+// if tmp != "" {
+// newStr = append(newStr, tmp)
+// tmp = ""
+// }
+// newStr1 := make([]string, 0)
+// for _, v := range newStr {
+// if strings.TrimSpace(v) == "" {
+// continue
+// }
+// newStr1 = append(newStr1, strings.TrimSpace(v))
+// }
+// return newStr1
+//}
+
+//func StrToUrl(str string) string {
+// strs := []string{}
+// for _, v := range StrToArr(str) {
+// fmt.Println(v)
+// }
+//
+// return strings.Join(strs, "-")
+//}
+
+func Base64Encode(s string) string {
+ return base64.StdEncoding.EncodeToString([]byte(s))
+}
+
+func Base64Decode(s string) (string, error) {
+ b, err := base64.StdEncoding.DecodeString(s)
+ if err != nil {
+ return "", errors.Wrap(err, "")
+ }
+ return string(b), nil
+}
+
+func HtmlToText(body string) ([]string, error) {
+ body = strings.ReplaceAll(body, " ", " ")
+ ss := "<(.|\\n)*?>"
+ body = regexp.MustCompile(ss).ReplaceAllString(body, " ")
+ doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))
+ if err != nil {
+ return nil, errors.Wrap(err, "")
+ }
+ defer doc.Clone()
+ v := doc.Text()
+ var hzRegexp = regexp.MustCompile("^[a-zA-Z0-9\u4e00-\u9fa5]$")
+ var zwReg = regexp.MustCompile("^[\u4e00-\u9fa5]$")
+ strn := ""
+ ars := []string{}
+ for _, c := range v {
+ filter := false
+ if hzRegexp.MatchString(string(c)) {
+ if zwReg.MatchString(string(c)) {
+ strn += string(c)
+ filter = true
+ } else {
+ strn += string(c)
+ }
+ } else {
+ filter = true
+ }
+ fmt.Println(strn)
+ if filter && strn != "" {
+ ars = append(ars, strn)
+ strn = ""
+ }
+ }
+ if strn != "" {
+ ars = append(ars, strn)
+ }
+ return ars, nil
+}
+func ContentText(body string) string {
+ doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))
+ if err != nil {
+ return err.Error()
+ }
+ defer doc.Clone()
+ return doc.Text()
+}
+func GetPicture(pic string) string {
+ if pic == "" {
+ return "/sites/default/files/imagecache/ic50x50/avatar_selection/o2QQW.jpg.png"
+ }
+ if !strings.HasPrefix(pic, "/") {
+ return "/" + pic
+ }
+ return pic
+}
+
+func Ucfirst(str string) string {
+ for i, v := range str {
+ return string(unicode.ToUpper(v)) + str[i+1:]
+ }
+ return ""
+}
+
+func Lcfirst(str string) string {
+ for i, v := range str {
+ return string(unicode.ToLower(v)) + str[i+1:]
+ }
+ return ""
+}
diff --git a/pkg/xtime/xtime.go b/pkg/xtime/xtime.go
new file mode 100644
index 0000000..071aec0
--- /dev/null
+++ b/pkg/xtime/xtime.go
@@ -0,0 +1,69 @@
+package xtime
+
+import (
+ "fmt"
+ "strings"
+ "time"
+)
+
+const DefaultTimeLayout = "2006-01-02 15:04:05"
+
+func LeaTime(t int64) string {
+ leaSeconds := time.Now().Unix() - t
+ mps := []struct {
+ Seconds int64
+ Title string
+ }{
+ {31536000, "years"},
+ {604800, "weeks"},
+ {86400, "days"},
+ {3600, "hours"},
+ {60, "min"},
+ {1, "sec"},
+ }
+ res := []string{}
+ for _, v := range mps {
+ if leaSeconds > v.Seconds {
+ if len(res) == 2 {
+ break
+ }
+ n := leaSeconds / v.Seconds
+ tt := v.Title
+ if n == 1 {
+ tt = strings.TrimRight(v.Title, "s")
+ }
+ res = append(res, fmt.Sprintf("%d %s", n, tt))
+ leaSeconds -= v.Seconds * n
+ }
+ }
+ return strings.Join(res, " ")
+}
+
+func UnixToTime(unix int64) time.Time {
+ return time.Unix(unix, 0)
+}
+func ParseTime(day string, layout string) int64 {
+ if day == "" {
+ return 0
+ }
+ t, err := time.ParseInLocation(layout, day, time.Local)
+ if err != nil {
+ fmt.Println(err)
+ return 0
+ }
+ return t.Unix()
+}
+
+const DefaultLayout = "2006-01-02 15:04:05"
+
+func TimeTodayMinAndMax(ctime time.Time) (min, max time.Time) {
+ start, _ := time.ParseInLocation(DefaultLayout, ctime.Format("2006-01-02")+" 00:00:00", time.Local)
+ end, _ := time.ParseInLocation(DefaultLayout, ctime.Format("2006-01-02")+" 23:59:59", time.Local)
+ return start, end
+}
+func UnixToStr(t int64) string {
+ if t == 0 {
+ return ""
+ }
+ return UnixToTime(t).Format(DefaultTimeLayout)
+}
diff --git a/pkg/xtime/xtime_test.go b/pkg/xtime/xtime_test.go
new file mode 100644
index 0000000..9f4049a
--- /dev/null
+++ b/pkg/xtime/xtime_test.go
@@ -0,0 +1,10 @@
+package xtime
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestLeaTime(t *testing.T) {
+ fmt.Println(LeaTime(1651812894))
+}
diff --git a/pkg/xuser/xuser.go b/pkg/xuser/xuser.go
new file mode 100644
index 0000000..01aa571
--- /dev/null
+++ b/pkg/xuser/xuser.go
@@ -0,0 +1,31 @@
+package xuser
+
+import (
+ "context"
+ "github.com/gin-gonic/gin"
+)
+
+func GetUserFromContext(ctx context.Context) string {
+ v := ctx.Value("username")
+ if v == nil {
+ return ""
+ }
+ return v.(string)
+}
+func SetContextUser(ctx *gin.Context, username string) {
+ ctx.Set("username", username)
+ //return context.WithValue(ctx, requestUserIdKey{}, username)
+}
+
+type userIdKey struct {
+}
+
+func WithContext(ctx context.Context, userId int64) context.Context {
+ return context.WithValue(ctx, userIdKey{}, userId)
+}
+func FromContext(ctx context.Context) int64 {
+ if v, ok := ctx.Value(userIdKey{}).(int64); ok {
+ return v
+ }
+ return 0
+}
diff --git a/proto/v1/user.gin.go b/proto/v1/user.gin.go
index f8a9d7c..1f44f88 100644
--- a/proto/v1/user.gin.go
+++ b/proto/v1/user.gin.go
@@ -3,8 +3,8 @@ package user
import (
"context"
"git.diulo.com/mogfee/protoc-gen-kit/middleware"
- "git.diulo.com/mogfee/protoc-gen-kit/response"
- "git.diulo.com/mogfee/protoc-gen-kit/xerrors"
+ "git.diulo.com/mogfee/protoc-gen-kit/pkg/xerrors"
+ "git.diulo.com/mogfee/protoc-gen-kit/pkg/xresponse"
"github.com/gin-gonic/gin"
)
@@ -15,7 +15,7 @@ func RegisterUserHandler(app *gin.Engine, srv UserServer, m ...middleware.Middle
func httpListHandler(srv UserServer, m ...middleware.Middleware) func(c *gin.Context) {
return func(c *gin.Context) {
var post LoginRequest
- resp := response.New(c)
+ resp := xresponse.New(c)
if err := resp.BindQuery(&post); err != nil {
resp.Error(err)
return
@@ -38,7 +38,7 @@ func httpListHandler(srv UserServer, m ...middleware.Middleware) func(c *gin.Con
func httpLoginHandler(srv UserServer, m ...middleware.Middleware) func(c *gin.Context) {
return func(c *gin.Context) {
var post LoginRequest
- resp := response.New(c)
+ resp := xresponse.New(c)
if err := resp.BindJSON(&post); err != nil {
resp.Error(err)
return
diff --git a/xstring/xstring.go b/xstring/xstring.go
deleted file mode 100644
index 0b89969..0000000
--- a/xstring/xstring.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package xstring
-
-import "unicode"
-
-func Ucfirst(str string) string {
- for i, v := range str {
- return string(unicode.ToUpper(v)) + str[i+1:]
- }
- return ""
-}
-
-func Lcfirst(str string) string {
- for i, v := range str {
- return string(unicode.ToLower(v)) + str[i+1:]
- }
- return ""
-}
diff --git a/xuser/xuser.go b/xuser/xuser.go
deleted file mode 100644
index 6a0dc14..0000000
--- a/xuser/xuser.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package xuser
-
-import "context"
-
-func ValidateUser(token string) (int64, error) {
- return 1, nil
-}
-
-type userIdKey struct {
-}
-
-func WithContext(ctx context.Context, userId int64) context.Context {
- return context.WithValue(ctx, userIdKey{}, userId)
-}
-func FromContext(ctx context.Context) int64 {
- if v, ok := ctx.Value(userIdKey{}).(int64); ok {
- return v
- }
- return 0
-}