Implement the propfind method in tank.

This commit is contained in:
zicla 2019-04-21 00:57:22 +08:00
parent 50c025bd09
commit 74ee6c1bba
4 changed files with 78 additions and 66 deletions

View File

@ -168,6 +168,7 @@ func (pn *PropfindProps) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement)
} }
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propfind // http://www.webdav.org/specs/rfc4918.html#ELEMENT_propfind
// <!ELEMENT propfind ( propname | (allprop, include?) | prop ) >
type Propfind struct { type Propfind struct {
XMLName ixml.Name `xml:"DAV: propfind"` XMLName ixml.Name `xml:"DAV: propfind"`
Allprop *struct{} `xml:"DAV: allprop"` Allprop *struct{} `xml:"DAV: allprop"`
@ -177,9 +178,9 @@ type Propfind struct {
} }
//从request中读出需要的属性。比如getcontentlength 大小 creationdate 创建时间 //从request中读出需要的属性。比如getcontentlength 大小 creationdate 创建时间
func ReadPropfind(r io.Reader) (pf Propfind, status int, err error) { func ReadPropfind(r io.Reader) (propfind Propfind, status int, err error) {
c := CountingReader{r: r} c := CountingReader{r: r}
if err = ixml.NewDecoder(&c).Decode(&pf); err != nil { if err = ixml.NewDecoder(&c).Decode(&propfind); err != nil {
if err == io.EOF { if err == io.EOF {
if c.n == 0 { if c.n == 0 {
// An empty body means to propfind allprop. // An empty body means to propfind allprop.
@ -191,19 +192,19 @@ func ReadPropfind(r io.Reader) (pf Propfind, status int, err error) {
return Propfind{}, http.StatusBadRequest, err return Propfind{}, http.StatusBadRequest, err
} }
if pf.Allprop == nil && pf.Include != nil { if propfind.Allprop == nil && propfind.Include != nil {
return Propfind{}, http.StatusBadRequest, errInvalidPropfind return Propfind{}, http.StatusBadRequest, errInvalidPropfind
} }
if pf.Allprop != nil && (pf.Prop != nil || pf.Propname != nil) { if propfind.Allprop != nil && (propfind.Prop != nil || propfind.Propname != nil) {
return Propfind{}, http.StatusBadRequest, errInvalidPropfind return Propfind{}, http.StatusBadRequest, errInvalidPropfind
} }
if pf.Prop != nil && pf.Propname != nil { if propfind.Prop != nil && propfind.Propname != nil {
return Propfind{}, http.StatusBadRequest, errInvalidPropfind return Propfind{}, http.StatusBadRequest, errInvalidPropfind
} }
if pf.Propname == nil && pf.Allprop == nil && pf.Prop == nil { if propfind.Propname == nil && propfind.Allprop == nil && propfind.Prop == nil {
return Propfind{}, http.StatusBadRequest, errInvalidPropfind return Propfind{}, http.StatusBadRequest, errInvalidPropfind
} }
return pf, 0, nil return propfind, 0, nil
} }
// Property represents a single DAV resource property as defined in RFC 4918. // Property represents a single DAV resource property as defined in RFC 4918.

View File

@ -58,6 +58,53 @@ func (this *DavService) PropNames(matter *Matter) []xml.Name {
} }
//从一个matter中获取其 []dav.Propstat
func (this *DavService) PropstatsFromXmlNames(matter *Matter, xmlNames []xml.Name) []dav.Propstat {
propstats := make([]dav.Propstat, 0)
var properties []dav.Property
for _, xmlName := range xmlNames {
//TODO: deadprops尚未考虑
// Otherwise, it must either be a live property or we don't know it.
if liveProp := LivePropMap[xmlName]; liveProp.findFn != nil && (liveProp.dir || !matter.Dir) {
innerXML := liveProp.findFn(matter)
properties = append(properties, dav.Property{
XMLName: xmlName,
InnerXML: []byte(innerXML),
})
} else {
this.logger.Info("%s的%s无法完成", matter.Path, xmlName.Local)
}
}
if len(properties) == 0 {
this.PanicBadRequest("请求的属性项无法解析!")
}
okPropstat := dav.Propstat{Status: http.StatusOK, Props: properties}
propstats = append(propstats, okPropstat)
return propstats
}
//从一个matter中获取所有的propsNames
func (this *DavService) AllPropXmlNames(matter *Matter) []xml.Name {
pnames := make([]xml.Name, 0)
for pn, prop := range LivePropMap {
if prop.findFn != nil && (prop.dir || !matter.Dir) {
pnames = append(pnames, pn)
}
}
return pnames
}
//从一个matter中获取其 []dav.Propstat //从一个matter中获取其 []dav.Propstat
func (this *DavService) Propstats(matter *Matter, propfind dav.Propfind) []dav.Propstat { func (this *DavService) Propstats(matter *Matter, propfind dav.Propfind) []dav.Propstat {
@ -66,34 +113,14 @@ func (this *DavService) Propstats(matter *Matter, propfind dav.Propfind) []dav.P
if propfind.Propname != nil { if propfind.Propname != nil {
this.PanicBadRequest("propfind.Propname != nil 尚未处理") this.PanicBadRequest("propfind.Propname != nil 尚未处理")
} else if propfind.Allprop != nil { } else if propfind.Allprop != nil {
this.PanicBadRequest("propfind.Allprop != nil 尚未处理")
//TODO: 如果include中还有内容那么包含进去。
xmlNames := this.AllPropXmlNames(matter)
propstats = this.PropstatsFromXmlNames(matter, xmlNames)
} else { } else {
propstats = this.PropstatsFromXmlNames(matter, propfind.Prop)
var properties []dav.Property
for _, prop := range propfind.Prop {
//TODO: deadprops尚未考虑
// Otherwise, it must either be a live property or we don't know it.
if liveProp := LivePropMap[prop]; liveProp.findFn != nil && (liveProp.dir || !matter.Dir) {
innerXML := liveProp.findFn(matter)
properties = append(properties, dav.Property{
XMLName: prop,
InnerXML: []byte(innerXML),
})
} else {
//TODO: 某一项请求的prop没有对应的结果
}
}
if len(properties) == 0 {
this.PanicBadRequest("请求的属性项无法解析!")
}
okPropstat := dav.Propstat{Status: http.StatusOK, Props: properties}
propstats = append(propstats, okPropstat)
} }
return propstats return propstats
@ -108,19 +135,28 @@ func (this *DavService) HandlePropfind(writer http.ResponseWriter, request *http
//获取请求者 //获取请求者
user := this.checkUser(writer, request) user := this.checkUser(writer, request)
//找寻请求的目录
matter := this.matterDao.checkByUserUuidAndPath(user.Uuid, subPath)
//读取请求参数。按照用户的参数请求返回内容。 //读取请求参数。按照用户的参数请求返回内容。
propfind, _, err := dav.ReadPropfind(request.Body) propfind, _, err := dav.ReadPropfind(request.Body)
this.PanicError(err) this.PanicError(err)
//寻找符合条件的matter. //寻找符合条件的matter.
matters := this.matterDao.ListByUserUuidAndPath(user.Uuid, subPath) var matter *Matter
//如果是空或者/就是请求根目录
if subPath == "" || subPath == "/" {
matter = NewRootMatter(user)
} else {
matter = this.matterDao.checkByUserUuidAndPath(user.Uuid, subPath)
}
matters := this.matterDao.List(matter.Uuid, user.Uuid, nil)
if len(matters) == 0 { if len(matters) == 0 {
this.PanicNotFound("%s不存在", subPath) this.PanicNotFound("%s不存在", subPath)
} }
//将当前的matter添加到头部
matters = append([]*Matter{matter}, matters...)
//准备一个输出结果的Writer //准备一个输出结果的Writer
multiStatusWriter := dav.MultiStatusWriter{Writer: writer} multiStatusWriter := dav.MultiStatusWriter{Writer: writer}
@ -140,6 +176,6 @@ func (this *DavService) HandlePropfind(writer http.ResponseWriter, request *http
err = multiStatusWriter.Close() err = multiStatusWriter.Close()
this.PanicError(err) this.PanicError(err)
fmt.Printf("%v %v \n", matter.Name, propfind.Prop) fmt.Printf("%v %v \n", subPath, propfind.Prop)
} }

View File

@ -132,31 +132,6 @@ func (this *MatterDao) ListByUserUuidAndPuuidAndDirAndName(userUuid string, puui
return matters return matters
} }
//获取某个用户的某个文件夹下的某个名字的文件(或文件夹)列表
func (this *MatterDao) ListByUserUuidAndPath(userUuid string, path string) []*Matter {
var wp = &WherePair{}
if userUuid == "" {
this.PanicBadRequest("userUuid必填")
}
if path == "" {
this.PanicBadRequest("path必填")
}
wp = wp.And(&WherePair{Query: "user_uuid = ?", Args: []interface{}{userUuid}})
wp = wp.And(&WherePair{Query: "path = ?", Args: []interface{}{path}})
var matters []*Matter
db := CONTEXT.DB.Model(&Matter{}).Where(wp.Query, wp.Args...).Find(&matters)
this.PanicError(db.Error)
return matters
}
//获取某个文件夹下所有的文件和子文件 //获取某个文件夹下所有的文件和子文件
func (this *MatterDao) List(puuid string, userUuid string, sortArray []OrderPair) []*Matter { func (this *MatterDao) List(puuid string, userUuid string, sortArray []OrderPair) []*Matter {
var matters []*Matter var matters []*Matter

View File

@ -29,13 +29,11 @@ func (Matter) TableName() string {
return TABLE_PREFIX + "matter" return TABLE_PREFIX + "matter"
} }
// 获取该Matter的绝对路径。path代表的是相对路径。 // 获取该Matter的绝对路径。path代表的是相对路径。
func (this *Matter) AbsolutePath() string { func (this *Matter) AbsolutePath() string {
return GetUserFileRootDir(this.Username) + this.Path return GetUserFileRootDir(this.Username) + this.Path
} }
// 获取该Matter的MimeType // 获取该Matter的MimeType
func (this *Matter) MimeType() string { func (this *Matter) MimeType() string {
return GetMimeType(GetExtension(this.Name)) return GetMimeType(GetExtension(this.Name))
@ -50,6 +48,8 @@ func NewRootMatter(user *User) *Matter {
matter.Username = user.Username matter.Username = user.Username
matter.Dir = true matter.Dir = true
matter.Path = "" matter.Path = ""
matter.CreateTime = user.CreateTime
matter.UpdateTime = user.UpdateTime
return matter return matter
} }