/* Copyright Ghink Network Studio Website: https://www.ghink.net */ package main import ( "net/http" "log" "strings" "time" "encoding/json" "fmt" "io/ioutil" "os" "io" "crypto/sha256" "encoding/hex" "path" ) var WorkPath,DataPath string var NodeList,Database,Dataread []map[string]string var Loger *log.Logger var ch chan bool func responseICON(w http.ResponseWriter,r *http.Request) { w.Header().Set("Location","https://resource.ghink.net/public/img/logo/ghink.png") w.WriteHeader(301) } func responseError(w http.ResponseWriter,r *http.Request,httpCode int,info string,errorCode int) { w.Header().Set("Content-Type","application/json") w.WriteHeader(httpCode) type returnError struct{ HttpCode int `json:"httpCode"` Info string `json:"info"` ErrorCode int `json:"errorCode"` } returnInfo:=returnError{httpCode,info,errorCode} b,_:=json.Marshal(returnInfo) w.Write(b) } func responseWiKi(w http.ResponseWriter,r *http.Request) { w.Header().Set("Content-Type","application/json") w.WriteHeader(200) type returnWiki struct{ HttpCode int `json:"httpCode"` Wiki string `json:"wiki"` } returnInfo:=returnWiki{200,"https://gitee.com/ghink/gmclapi/wikis"} b,_:=json.Marshal(returnInfo) w.Write(b) } func responseOfficial(w http.ResponseWriter,r *http.Request,value []string) { paths:="" for _,arg := range value{ paths=paths+"/"+arg } if paths=="" || paths=="/"{ responseError(w,r,400,"Please offer more params",10005) }else{ switcher:=true for _,arg := range Database{ if arg["path"]==paths{ address:=determineNode(arg["hash"],path.Base(arg["path"])) w.Header().Set("Location",address) w.WriteHeader(302) switcher=false break } } if switcher==true{ responseError(w,r,404,"Cannot find file",10003) } } } func responseFile(w http.ResponseWriter,r *http.Request,value []string) { fileName:=value[0] path:=DataPath for _,arg := range value[1:]{ path=path+"/"+arg } if path==DataPath{ responseError(w,r,403,"Directory listing is not allowed",10002) }else{ b,err:=ioutil.ReadFile(path) if err != nil { if find := strings.Contains(err.Error(),"The system cannot find"); find{ responseError(w,r,404,"Cannot find file",10003) }else if s,_:=os.Stat(path); s.IsDir(){ responseError(w,r,403,"Directory listing is not allowed",10002) }else{ responseError(w,r,500,"The file exists but cannot be read",10004) logIn("[Page Thread]","Read the file ",path," failed in data dir! Error info: ",err.Error()) } }else{ w.Header().Set("Content-Disposition","attachment;filename="+fileName) w.Header().Set("Content-Type","application/octet-stream") w.Write(b) } } } func pageService(w http.ResponseWriter,r *http.Request) { ts := time.Now().Unix() logIn("[Page Thread]","Got requests from ",r.RemoteAddr,", address is ",r.URL.RequestURI()) w.Header().Set("Server","GMCLAPI (Alpha 1.0.0)") w.Header().Set("Engine","Panda (Alpha 1.0.0)") w.Header().Set("Stamp",fmt.Sprint(ts)) addr:=r.URL.RequestURI() value:=strings.Split(addr,"/") pathType:=value[1] value=value[2:] if addr=="/"{ responseWiKi(w,r) }else{ switch pathType { case "favicon.ico": responseICON(w,r) case "file": responseFile(w,r,value) case "official": responseOfficial(w,r,value) /* case "bmclapi": responseBMCLAPI(w,r,value) case "default": responseDefault(w,r,value) case "gmclapi": responseDefault(w,r,value) */ default: responseError(w,r,405,"Unspported choice for requests loading",10001) } } } func databaseService() { for { defer recover() file,err:=os.OpenFile(WorkPath+"/database.db",os.O_RDONLY,0600) defer file.Close() if err != nil { panic(err) } bytes,err:=ioutil.ReadAll(file) if err != nil { panic(err) } err=json.Unmarshal(bytes,&Database) if err != nil { panic(err) } time.Sleep(time.Duration(10)*time.Second) } } func nodeService() { } func determineNode(hash string,fileName string) string { return "http://127.0.0.1:8000/file/"+fileName+"/"+hash } func syncService() { for { } } func hashFile(path string) string { file,err:=os.Open(path) defer file.Close() if err != nil { logIn("[Hash Thread]","Failed to calc hash of the file ",path,"! Error info: ",err.Error()) } hash:=sha256.New() if _,err := io.Copy(hash,file); err != nil { logIn("[Hash Thread]","Failed to calc hash of the file ",path,"! Error info: ",err.Error()) } sum:=hash.Sum(nil) return hex.EncodeToString(sum) } func logIn(text ...string) { result:="" for _,arg := range text { result+=arg } log.Print(result) Loger.Print(result) } func init() { WorkPath="gmclapi/" DataPath=WorkPath+"data/" err:=os.MkdirAll(WorkPath, os.ModePerm) if err != nil { panic(err) } err=os.MkdirAll(DataPath, os.ModePerm) if err != nil { panic(err) } if _,err:=os.Stat(WorkPath+"database.db"); os.IsNotExist(err){ database,err:=os.OpenFile(WorkPath+"database.db", os.O_WRONLY|os.O_CREATE, 0666) database.Write([]byte("[]")) if err != nil { panic(err) } defer database.Close() } file,err:=os.OpenFile(WorkPath+"/database.db", os.O_RDONLY,0600) defer file.Close() if err != nil { panic(err) } bytes,err:=ioutil.ReadAll(file) if err != nil { panic(err) } err=json.Unmarshal(bytes,&Database) if err != nil { panic(err) } } func main() { logFile,err:=os.OpenFile(WorkPath+"logs.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) if err != nil { panic(err) } defer logFile.Close() Loger=log.New(logFile,"",log.LstdFlags|log.Lshortfile) http.HandleFunc("/", pageService) go http.ListenAndServe("127.0.0.1:8000", nil) go syncService() go databaseService() /* go nodeService() go consoleService() */ for { } } /* 10001 Unspported choice for requests loading 10002 Directory listing is not allowed 10003 Cannot find file 10004 The file exists but cannot be read 10005 Please offer more params */