package locals import ( "bytes" "crypto/sha256" "encoding/base64" "encoding/json" "errors" "fmt" "io/ioutil" "kkscrap-go/locals/gosodium/cryptobox" "net/http" "strings" "time" "github.com/dabory/abango-rest" e "github.com/dabory/abango-rest/etc" "github.com/go-xorm/xorm" "github.com/microcosm-cc/bluemonday" ) const ( // Tpf string = "dbr_" // TablePrefix //QueryComment QcWhere string = "-- @where" QcSubWhere string = "-- @subwhere" QcHaving string = "-- @having" QcOrder string = "-- @order" QcLimitOffset string = "-- @limitoffset" QcExtract string = "-- @extract:" QcClosed string = "-- @closed:" QcDelivery string = "-- @delivery:" QcBetweenDates string = "-- @between_dates" QcEnd string = "--" //QueryComment //QueryKeyword QkWhere string = "\nwhere true " // QkWhere string = "\nwhere 1 " QkHaving string = "\nhaving true " QkOrder string = "\norder by " QkLimit string = "\nlimit " QkOffset string = " offset " QkTmpOrder string = " order by is_sum desc, t_id asc " ) type AppApi struct { ApiUrl string GateToken string } // 0:Sso, 1:Dbu 매우 중요하다. var gAppApis [2]AppApi var ( SQL_DEBUG bool NORMAL_DEBUG bool ) var BlockNoCnt int // type GateTokenGetReq struct { // ClientId string // BeforeBase64 string // AppBase64 string // } func (y *SyncController) Init() error { var kPairStr string if abango.XConfig["IsLocalKeyPair"] != "Yes" { keypair, err := GuestKeyPairGet(abango.XConfig["SyncClientId"]) if err != nil { return e.ErrLog(e.FuncRun("03joau0u3qd", e.CurrFuncName()), err) } kPairStr = keypair fmt.Println("RemoteKeypair:", kPairStr) } else { kPairStr = abango.XConfig["LocalKeyPair"] fmt.Println("LocalKeyPair:", kPairStr) } keyPair, err := base64.StdEncoding.DecodeString(kPairStr) if err != nil { return e.ErrLog(e.FuncRun("joiuejcsoe: Decryption Failure-1 ", e.CurrFuncName()), err) } sKey, pKey, err := cryptobox.CryptoBoxGetSecretPublicKeyFrom(keyPair) if err != nil { return e.ErrLog(e.FuncRun("joiuejcsoe: Decryption Failure-2 ", e.CurrFuncName()), err) } decodedBytes, err := base64.StdEncoding.DecodeString(abango.XConfig["SyncBB64"]) if err != nil { return e.ErrLog(e.FuncRun("joiuejcsoe: Decryption Failure-3 ", e.CurrFuncName()), err) } //decrypt 문제는 여기서 memory error 가 난다. decryptedBytes, boxRet := cryptobox.CryptoBoxSealOpen(decodedBytes, pKey, sKey) if boxRet != 0 { return e.ErrLog(e.FuncRun("joiuejcsoe: Decryption Failure-4(Wrong BB64Key) ", e.CurrFuncName()), err) } vmc := &struct { Driver string Host string Port int Username string Database string Password string }{} if err := json.Unmarshal(decryptedBytes, vmc); err != nil { return e.ErrLog(e.FuncRun("joiuejcsoe: Decryption Failure-5 ", e.CurrFuncName()), err) } connStr := vmc.Username + ":" + vmc.Password + "@tcp(" + vmc.Host + ":" + e.NumToStr(vmc.Port) + ")/" + vmc.Database fmt.Println("connStr:", connStr) y.Scb.ConnString = connStr if y.Db, err = xorm.NewEngine(abango.XConfig["DbType"], connStr); err != nil { return e.ErrLog(e.FuncRun("309upajs3w: DBEngine Open Error ", e.CurrFuncName()), err) } var connHint string strArr := strings.Split(connStr, "@tcp") if len(strArr) == 2 { connHint = strArr[1] } else { return e.ErrLog(e.FuncRun("309upajs3w: connString format mismatch: "+strArr[1], e.CurrFuncName()), err) } y.Db.ShowSQL(false) y.Db.SetMaxOpenConns(100) y.Db.SetMaxIdleConns(20) y.Db.SetConnMaxLifetime(60 * time.Second) if _, err := y.Db.IsTableExist("aaa"); err == nil { e.OkLog("SyncDB connection in " + connHint) return nil } else { return e.ErrLog(e.FuncRun("93haoy93d: SyncDB connection Fail in "+connHint+": ", e.CurrFuncName()), err) } } func (t *PageVars) ChkPageVars(chk string) { if t.Query == "" { e.ChkLog(chk, "Query is empty") } if t.Fields == "" { e.ChkLog(chk, "Fields is empty") } if t.Asc == "" { e.ChkLog(chk, "Asc is empty") } if t.Desc == "" { e.ChkLog(chk, "Desc is empty") } if t.Limit == 0 { e.ChkLog(chk, "Limit is zero") } if t.Offset == 0 { e.ChkLog(chk, "Offset is zero") } e.ChkLog(chk+", PageVars value is", *t) return } type ( MemoryMap map[string]interface{} MapStore struct { store MemoryMap } ) func (c *MapStore) Get(key string) interface{} { return c.store[key] } func (c *MapStore) Set(key string, val interface{}) { if c.store == nil { c.store = make(MemoryMap) } c.store[key] = val } func DbrPasswd(password string, salt string) string { salt16 := DbrSaltBase(salt, 16) var passwordBytes = []byte(password) var sha256Hasher = sha256.New() passwordBytes = append(passwordBytes, salt16...) sha256Hasher.Write(passwordBytes) var hashedPasswordBytes = sha256Hasher.Sum(nil) var base64EncodedPasswordHash = base64.URLEncoding.EncodeToString(hashedPasswordBytes) return base64EncodedPasswordHash } func DbrHashedIndex(target string) string { //!!중요: salt는 16char에서만 작동된다. hash 값은 44 char나오지만 32char로 잘라서 쓴다. fmt.Println("hash_full_length:", DbrPasswd(target, "$$hashed_index$$")) return DbrPasswd(target, "$$hashed_index$$")[0:32] } func DbrCompare(hashedPassword, currPassword string, salt string) bool { // fmt.Println("salt:", salt) // fmt.Println("currPassword:", currPassword) var currPasswordHash = DbrPasswd(currPassword, salt) // fmt.Println("currPasswordHash:", currPasswordHash) // fmt.Println("hashedPassword:", hashedPassword) return hashedPassword == currPasswordHash } func DbrSaltBase(salt string, saltSize int) []byte { //어떤 사이즈라도 16byte의 Base64로 변경 tmp := []byte(salt) salt64 := base64.StdEncoding.EncodeToString(tmp) return []byte(salt64[4 : saltSize+4]) } func HasPickActPage(uri string, table string) bool { if table == "member" { if uri == "/"+table+"-pick" || uri == "/"+table+"-act" || uri == "/"+table+"-page" || uri == "/"+table+"-secured-pick" || uri == "/"+table+"-secured-page" || uri == "/"+table+"-secured-act" { return true } else { return false } } else { if uri == "/"+table+"-pick" || uri == "/"+table+"-act" || uri == "/"+table+"-page" { return true } else { return false } } } // func ByteIndex(ba *[]byte, bt byte, opt int) int { // if opt == 0 { //normal // for i := 0; i < len(*ba); i++ { // if (*ba)[i] == bt { // return i // } // } // } else if opt == 1 { //rerverse // for i := len(*ba) - 1; i > 0; i-- { // if (*ba)[i] == bt { // return i // } // } // } // return -1 // } func LastQry(qry xorm.Session) string { ret, _ := qry.LastSQL() fmt.Println("\n" + ret + "\n") return ret } func ShowQry(qry xorm.Session, qryName string) string { if SQL_DEBUG { ret, _ := qry.LastSQL() return e.LogStr("", "ShowQry===["+qryName+"]==="+"\n[ "+ret+" ]\n") } return "" } func ShowSql(sqlStr string, qryName string) string { if SQL_DEBUG { return e.LogStr("", "ShowSql===["+qryName+"]==="+"\n[ "+sqlStr+" ]\n") } return "" } // func ShowDebug(debugStr string, index string) string { // if NORMAL_DEBUG { // return e.LogStr("", "ShowDebug===["+index+"]==="+"\n[ "+debugStr+" ]\n") // } // return "" // } func QryDirName(qryName string) (string, string) { if !strings.Contains(qryName, "::") { return "queries/", qryName } else { q := strings.Split(qryName, "::") return "queries/themes/" + q[0] + "/", q[1] } } func StripHtml(cont string, max int) string { p := bluemonday.StripTagsPolicy() s := p.Sanitize(cont) if len(s) > max { return string([]rune(s)[:max]) } else { return s } } func Sanitize(cont string) string { p := bluemonday.UGCPolicy() return p.Sanitize(cont) } func AddStrIfNotExist(s *string, target string) { if !strings.Contains(*s, target) { *s += target } } func HttpResponseSimplePost(method string, apiurl string, jsBytes []byte) (retbody []byte, retsta int, reterr error) { response, err := http.Post(apiurl, "application/json", bytes.NewBuffer(jsBytes)) if err != nil { return nil, 0, errors.New(e.FuncRunErr("65rfg0csdew", "The HTTP request failed with error "+e.CurrFuncName()+err.Error())) } else { retbody, err = ioutil.ReadAll(response.Body) if err != nil { return nil, 0, errors.New(e.FuncRunErr("kjda89382", "ReadAll error "+e.CurrFuncName()+err.Error())) } } return retbody, response.StatusCode, nil } func HttpResponseWithGt(method string, apiurl string, jsBytes []byte, gateToken string) (retbody []byte, retsta int, reterr error) { reader := bytes.NewBuffer(jsBytes) req, err := http.NewRequest(method, apiurl, reader) if err != nil { return nil, 909, e.ErrLog(e.FuncRun("xcawrq3276fa-http.NewRequest "+apiurl, e.CurrFuncName()), err) } req.Header.Add("RemoteIp", "localhost") req.Header.Add("Referer", "http://localhost") req.Header.Add("GateToken", gateToken) req.Body = ioutil.NopCloser(bytes.NewReader(jsBytes)) // Client객체에서 Request 실행 client := &http.Client{ Timeout: time.Second * 20, //Otherwirse, it can cause crash without this line. Must Must. } // Normal is 10 but extend 20 on 1 Dec 2018 // fmt.Println(reflect.TypeOf(respo)) resp, err := client.Do(req) if err != nil { return nil, 909, e.ErrLog(e.FuncRun("wewer2354e-client.Do "+apiurl, e.CurrFuncName()), err) } defer resp.Body.Close() byteRtn, _ := ioutil.ReadAll(resp.Body) return byteRtn, resp.StatusCode, nil } func GuestGateTokenGet(appType int, pivotUrl string, ab64 string) (string, string, error) { if gAppApis[appType].GateToken == "" { req := &struct { AppType string AppBase64 string }{ AppType: "Main", AppBase64: ab64, } bodyBytes, _ := json.Marshal(req) apiUrl := pivotUrl + "/gate-token-get" msgBytes, staInt, err := HttpResponseSimplePost("POST", apiUrl, bodyBytes) // fmt.Println("apiUrl:", apiUrl) // fmt.Println("bodyBytes:", string(bodyBytes)) if err != nil { return "", "", e.ErrLog(e.FuncRun("45425fd34sd-The HTTP request "+apiUrl, e.CurrFuncName()), err) } if staInt != 200 { return "", "", errors.New(e.FuncRun("87ty344ra3-Request Fail "+string(msgBytes), e.CurrFuncName())) } ret := &struct { ApiUrl string GateToken string }{} if err := json.Unmarshal(msgBytes, ret); err != nil { return "", "", e.ErrLog(e.FuncRun("45425fd34sd-Json Format "+apiUrl, e.CurrFuncName()), err) } gAppApis[appType].ApiUrl = ret.ApiUrl gAppApis[appType].GateToken = ret.GateToken } else { fmt.Println("GateToken already is in the ARRAY") } // fmt.Println("gSsoApiUrl:", gSsoApiUrl) // fmt.Println("gSsoGateToken:", gSsoGateToken) return gAppApis[appType].ApiUrl, gAppApis[appType].GateToken, nil } func GuestEncryptGet(code string) (string, string, error) { appType := 1 //Dbupdate req := &struct { EncryptCode string }{ EncryptCode: code, } // 0:Sso, 1:Dbu pivotUrl, gateToken, err := GuestGateTokenGet(appType, abango.XConfig["DbuConnString"], abango.XConfig["DbuAppBase64"]) if err != nil { return "", "", e.ErrLog(e.FuncRun("23rfsr3qrase", e.CurrFuncName()), err) } ret := &struct { EncrypteKey string SaltKey string }{} bodyBytes, _ := json.Marshal(req) apiUrl := pivotUrl + "/encrypt-get" msgBytes, staInt, err := HttpResponseWithGt("POST", apiUrl, bodyBytes, gateToken) if err != nil { return "", "", e.ErrLog(e.FuncRun("1eadwrq34dxc-The HTTP request "+apiUrl, e.CurrFuncName()), err) } if staInt != 200 { gAppApis[appType].GateToken = "" // GateToke Expired 경우 Clear 한다. return "", "", errors.New(e.FuncRun("45faw3rfw-Request Fail "+string(msgBytes), e.CurrFuncName())) } if err := json.Unmarshal(msgBytes, ret); err != nil { return "", "", e.ErrLog(e.FuncRun("6756er345r3", e.CurrFuncName()), err) } return ret.EncrypteKey, ret.SaltKey, nil } func GuestAvailDbupdateGet(lastno string, isskipup string) ([]byte, error) { appType := 1 //Dbupdate req := &struct { DbupdateNo string IsSkipUpdate string }{ DbupdateNo: lastno, IsSkipUpdate: isskipup, } // 0:Sso, 1:Dbu pivotUrl, gateToken, err := GuestGateTokenGet(appType, abango.XConfig["DbuConnString"], abango.XConfig["DbuAppBase64"]) if err != nil { return nil, e.ErrLog(e.FuncRun("23rfsr3qrase", e.CurrFuncName()), err) } bodyBytes, _ := json.Marshal(req) apiUrl := pivotUrl + "/avail-dbupdate-get" msgBytes, staInt, err := HttpResponseWithGt("POST", apiUrl, bodyBytes, gateToken) if err != nil { return nil, e.ErrLog(e.FuncRun("1eadwrq34dxc-The HTTP request "+apiUrl, e.CurrFuncName()), err) } if staInt != 200 { gAppApis[appType].GateToken = "" // GateToke Expired 경우 Clear 한다. return nil, errors.New(e.FuncRun("0asfweijcvs-Request Fail "+string(msgBytes), e.CurrFuncName())) } return msgBytes, nil } func GuestKeyPairGet(clientId string) (string, error) { appType := 0 //Dbupdate req := &struct { ClientId string }{ ClientId: clientId, } // fmt.Println("clientId:", clientId) // 0:Sso, 1:Dbu pivotUrl, gateToken, err := GuestGateTokenGet(appType, abango.XConfig["SsoConnString"], abango.XConfig["SsoAppBase64"]) if err != nil { return "", e.ErrLog(e.FuncRun("23rfsr3qrase", e.CurrFuncName()), err) } ret := &struct { KeyPair string }{} bodyBytes, _ := json.Marshal(req) apiUrl := pivotUrl + "/key-pair-get" msgBytes, staInt, err := HttpResponseWithGt("POST", apiUrl, bodyBytes, gateToken) if err != nil { return "", e.ErrLog(e.FuncRun("1eadwrq34dxc-The HTTP request "+apiUrl, e.CurrFuncName()), err) } if staInt != 200 { gAppApis[appType].GateToken = "" // GateToke Expired 경우 Clear 한다. return "", errors.New(e.FuncRun("09665gsre3-Request Fail "+string(msgBytes), e.CurrFuncName())) } if err := json.Unmarshal(msgBytes, ret); err != nil { return "", e.ErrLog(e.FuncRun("9074tf32de", e.CurrFuncName()), err) } return ret.KeyPair, nil } func OneRowQuery(y *abango.Controller, sql string) (c1 string, c2 string, c3 string, err error) { page, err := y.Db.Query(sql) if err != nil { return "", "", "", errors.New(e.FuncRunErr("0hjnboisqow", e.CurrFuncName()+err.Error())) } if len(page) > 1 { return "", "", "", errors.New(e.FuncRunErr("0k1dt6j3d", e.CurrFuncName()+"Row Count > 1 ")) } for _, row := range page { c1 = string(row["c1"]) c2 = string(row["c2"]) c3 = string(row["c3"]) } return } func IsFirstOrderGet(y *abango.Controller, buyerId int) string { qry := fmt.Sprintf("select count(*) as c1 from dbr_sorder where buyer_id = %d ", buyerId) ordCnt, _, _, _ := OneRowQuery(y, qry) if ordCnt == "1" { return "1" } else { return "0" } } func TimeFormatGet(format string) string { rtn := "" if format == "" { rtn = "060102" } else if format == "YYMMDD" { rtn = "060102" } else if format == "YYYYMMDD" { rtn = "20060102" } else if format == "YY-MM-DD" { rtn = "06-01-02" } else if format == "YY.MM.DD" { rtn = "06.01.02" } else if format == "YYMM" { rtn = "0601" } else if format == "YY" { rtn = "06" } return rtn }