quickshare/server/apis/file_info.go
hekk 61a1c93f0f !1 Merge back to master
Merge pull request !1 from dev branch
2018-05-27 21:32:55 +08:00

234 lines
5.5 KiB
Go

package apis
import (
"fmt"
"math/rand"
"net/http"
"path/filepath"
"strconv"
"time"
)
import (
"quickshare/server/libs/fileidx"
"quickshare/server/libs/httputil"
"quickshare/server/libs/httpworker"
)
func (srv *SrvShare) FileInfoHandler(res http.ResponseWriter, req *http.Request) {
tokenStr := srv.Http.GetCookie(req.Cookies(), srv.Conf.KeyToken)
if !srv.Walls.PassIpLimit(GetRemoteIp(req.RemoteAddr)) ||
!srv.Walls.PassLoginCheck(tokenStr, req) {
srv.Http.Fill(httputil.Err429, res)
return
}
todo := func(res http.ResponseWriter, req *http.Request) interface{} { return httputil.Err404 }
switch req.Method {
case http.MethodGet:
todo = srv.List
case http.MethodDelete:
todo = srv.Del
case http.MethodPatch:
act := req.FormValue(srv.Conf.KeyAct)
switch act {
case srv.Conf.ActShadowId:
todo = srv.ShadowId
case srv.Conf.ActPublishId:
todo = srv.PublishId
case srv.Conf.ActSetDownLimit:
todo = srv.SetDownLimit
case srv.Conf.ActAddLocalFiles:
todo = srv.AddLocalFiles
default:
srv.Http.Fill(httputil.Err404, res)
return
}
default:
srv.Http.Fill(httputil.Err404, res)
return
}
ack := make(chan error, 1)
ok := srv.WorkerPool.Put(&httpworker.Task{
Ack: ack,
Do: srv.Wrap(todo),
Res: res,
Req: req,
})
if !ok {
srv.Http.Fill(httputil.Err503, res)
}
execErr := srv.WorkerPool.IsInTime(ack, time.Duration(srv.Conf.Timeout)*time.Millisecond)
if srv.Err.IsErr(execErr) {
srv.Http.Fill(httputil.Err500, res)
}
}
type ResInfos struct {
List []*fileidx.FileInfo
}
func (srv *SrvShare) List(res http.ResponseWriter, req *http.Request) interface{} {
if !srv.Walls.PassOpLimit(srv.Conf.AllUsers, srv.Conf.OpIdGetFInfo) {
return httputil.Err429
}
return srv.list()
}
func (srv *SrvShare) list() interface{} {
infos := make([]*fileidx.FileInfo, 0)
for _, info := range srv.Index.List() {
infos = append(infos, info)
}
return &ResInfos{List: infos}
}
func (srv *SrvShare) Del(res http.ResponseWriter, req *http.Request) interface{} {
shareId := req.FormValue(srv.Conf.KeyShareId)
if !srv.Walls.PassOpLimit(shareId, srv.Conf.OpIdDelFInfo) {
return httputil.Err504
}
return srv.del(shareId)
}
func (srv *SrvShare) del(shareId string) interface{} {
if !srv.IsValidShareId(shareId) {
return httputil.Err400
}
fileInfo, found := srv.Index.Get(shareId)
if !found {
return httputil.Err404
}
srv.Index.Del(shareId)
fullPath := filepath.Join(srv.Conf.PathLocal, fileInfo.PathLocal)
if !srv.Fs.DelFile(fullPath) {
// TODO: may log file name because file not exist or delete is not authenticated
return httputil.Err500
}
return httputil.Ok200
}
func (srv *SrvShare) ShadowId(res http.ResponseWriter, req *http.Request) interface{} {
if !srv.Walls.PassOpLimit(srv.Conf.AllUsers, srv.Conf.OpIdOpFInfo) {
return httputil.Err429
}
shareId := req.FormValue(srv.Conf.KeyShareId)
return srv.shadowId(shareId)
}
func (srv *SrvShare) shadowId(shareId string) interface{} {
if !srv.IsValidShareId(shareId) {
return httputil.Err400
}
info, found := srv.Index.Get(shareId)
if !found {
return httputil.Err404
}
secretId := srv.Encryptor.Encrypt(
[]byte(fmt.Sprintf("%s%s", info.PathLocal, genPwd())),
)
if !srv.Index.SetId(info.Id, secretId) {
return httputil.Err412
}
return &ShareInfo{ShareId: secretId}
}
func (srv *SrvShare) PublishId(res http.ResponseWriter, req *http.Request) interface{} {
if !srv.Walls.PassOpLimit(srv.Conf.AllUsers, srv.Conf.OpIdOpFInfo) {
return httputil.Err429
}
shareId := req.FormValue(srv.Conf.KeyShareId)
return srv.publishId(shareId)
}
func (srv *SrvShare) publishId(shareId string) interface{} {
if !srv.IsValidShareId(shareId) {
return httputil.Err400
}
info, found := srv.Index.Get(shareId)
if !found {
return httputil.Err404
}
publicId := srv.Encryptor.Encrypt([]byte(info.PathLocal))
if !srv.Index.SetId(info.Id, publicId) {
return httputil.Err412
}
return &ShareInfo{ShareId: publicId}
}
func (srv *SrvShare) SetDownLimit(res http.ResponseWriter, req *http.Request) interface{} {
if !srv.Walls.PassOpLimit(srv.Conf.AllUsers, srv.Conf.OpIdOpFInfo) {
return httputil.Err429
}
shareId := req.FormValue(srv.Conf.KeyShareId)
downLimit64, downLimitParseErr := strconv.ParseInt(req.FormValue(srv.Conf.KeyDownLimit), 10, 32)
downLimit := int(downLimit64)
if srv.Err.IsErr(downLimitParseErr) {
return httputil.Err400
}
return srv.setDownLimit(shareId, downLimit)
}
func (srv *SrvShare) setDownLimit(shareId string, downLimit int) interface{} {
if !srv.IsValidShareId(shareId) || !srv.IsValidDownLimit(downLimit) {
return httputil.Err400
}
if !srv.Index.SetDownLimit(shareId, downLimit) {
return httputil.Err404
}
return httputil.Ok200
}
func (srv *SrvShare) AddLocalFiles(res http.ResponseWriter, req *http.Request) interface{} {
return srv.AddLocalFilesImp()
}
func (srv *SrvShare) AddLocalFilesImp() interface{} {
infos, err := srv.Fs.Readdir(srv.Conf.PathLocal, srv.Conf.LocalFileLimit)
if srv.Err.IsErr(err) {
panic(fmt.Sprintf("fail to readdir: %v", err))
}
for _, info := range infos {
info.DownLimit = srv.Conf.DownLimit
info.State = fileidx.StateDone
info.PathLocal = info.PathLocal
info.Id = srv.Encryptor.Encrypt([]byte(info.PathLocal))
addRet := srv.Index.Add(info)
switch {
case addRet == 0 || addRet == -1:
// TODO: return files not added
continue
case addRet == 1:
break
default:
return httputil.Err500
}
}
return httputil.Ok200
}
func genPwd() string {
return fmt.Sprintf("%d%d%d%d", rand.Intn(10), rand.Intn(10), rand.Intn(10), rand.Intn(10))
}