locations.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package dav_ipfs
  2. import (
  3. "encoding/xml"
  4. "github.com/kpmy/mipfs/ipfs_api"
  5. "github.com/kpmy/ypk/dom"
  6. "github.com/kpmy/ypk/fn"
  7. . "github.com/kpmy/ypk/tc"
  8. "golang.org/x/net/webdav"
  9. "os"
  10. "strconv"
  11. "strings"
  12. "time"
  13. )
  14. type loc struct {
  15. ch *chain
  16. props dom.Element
  17. }
  18. func (l *loc) Name() string {
  19. return l.ch.name
  20. }
  21. func (l *loc) Size() int64 {
  22. return int64(l.ch.UnixLsObject.Size)
  23. }
  24. func (l *loc) Mode() os.FileMode {
  25. if l.ch.Type == "Directory" {
  26. return os.ModeDir
  27. } else if l.ch.Type == "File" {
  28. return 0
  29. }
  30. panic(100)
  31. }
  32. func (l *loc) ModTime() (ret time.Time) {
  33. ret = time.Now()
  34. if !fn.IsNil(l.props) {
  35. if ts := l.props.Attr("modified"); ts != "" {
  36. if sec, err := strconv.ParseInt(ts, 10, 64); err == nil {
  37. ret = time.Unix(sec, 0)
  38. }
  39. }
  40. }
  41. return
  42. }
  43. func (l *loc) IsDir() bool {
  44. return true
  45. }
  46. func (l *loc) Sys() interface{} {
  47. Halt(100)
  48. return nil
  49. }
  50. func (l *loc) Close() error {
  51. return nil
  52. }
  53. func (l *loc) Read(p []byte) (n int, err error) {
  54. return 0, webdav.ErrForbidden
  55. }
  56. func (l *loc) Seek(offset int64, whence int) (int64, error) {
  57. return 0, webdav.ErrForbidden
  58. }
  59. const DetailedPropsLimit = 64
  60. func (l *loc) Readdir(count int) (ret []os.FileInfo, err error) {
  61. ls, _ := ipfs_api.Shell().FileList(l.ch.Hash)
  62. for _, lo := range ls.Links {
  63. switch lo.Type {
  64. case "File":
  65. fallthrough
  66. case "Directory":
  67. if !strings.HasPrefix(lo.Name, "*") {
  68. filepath := l.ch.Hash + "/" + lo.Name
  69. tail := newChain(l.ch.clone(), filepath).tail()
  70. var fi os.FileInfo
  71. if tail.IsDir() {
  72. _l := &loc{ch: tail}
  73. if len(ls.Links) <= DetailedPropsLimit {
  74. _l.readPropsModel()
  75. }
  76. fi = _l
  77. } else {
  78. _f := &file{ch: tail}
  79. if len(ls.Links) <= DetailedPropsLimit {
  80. _f.readPropsModel()
  81. }
  82. fi = _f
  83. }
  84. ret = append(ret, fi)
  85. }
  86. default:
  87. Halt(100)
  88. }
  89. }
  90. return
  91. }
  92. func (l *loc) Stat() (os.FileInfo, error) {
  93. return l, nil
  94. }
  95. func (l *loc) Write(p []byte) (n int, err error) {
  96. return 0, webdav.ErrForbidden
  97. }
  98. func (l *loc) readPropsModel() {
  99. ls, _ := ipfs_api.Shell().FileList(l.ch.Hash)
  100. pm := propLinksMap(ls)
  101. if p, ok := pm["*"]; ok {
  102. rd, _ := ipfs_api.Shell().CacheCat(p.Hash)
  103. if el, err := dom.Decode(rd); err == nil {
  104. l.props = el.Model()
  105. } else {
  106. Halt(99)
  107. }
  108. } else {
  109. l.props = newPropsModel()
  110. }
  111. }
  112. func (l *loc) readPropsObject() (props map[xml.Name]dom.Element, err error) {
  113. l.readPropsModel()
  114. props = make(map[xml.Name]dom.Element)
  115. props = readProps(l.props)
  116. return
  117. }
  118. func (l *loc) writePropsObject(props map[xml.Name]dom.Element) {
  119. el := writeProps(props)
  120. propHash, _ := ipfs_api.Shell().Add(dom.EncodeWithHeader(el))
  121. for tail := l.ch; tail != nil; tail = tail.up {
  122. if tail.Hash == l.ch.Hash {
  123. tail.Hash, _ = ipfs_api.Shell().PatchLink(tail.Hash, "*", propHash, false)
  124. } else {
  125. tail.Hash, _ = ipfs_api.Shell().PatchLink(tail.Hash, tail.down.name, tail.down.Hash, false)
  126. }
  127. }
  128. head := l.ch.head()
  129. head.link.update(head.Hash)
  130. }
  131. func (l *loc) DeadProps() (ret map[xml.Name]webdav.Property, err error) {
  132. //log.Println("loc props get")
  133. pm, _ := l.readPropsObject()
  134. ret = props2webdav(pm)
  135. //log.Println(ret)
  136. return
  137. }
  138. func (l *loc) Patch(patch []webdav.Proppatch) (ret []webdav.Propstat, err error) {
  139. //log.Println("loc prop patch", patch)
  140. pe, _ := l.readPropsObject()
  141. ret = propsPatch(pe, patch)
  142. //log.Println("loc file props", pe)
  143. l.writePropsObject(pe)
  144. return
  145. }