github.com/cs3org/reva/v2@v2.27.7/internal/http/services/owncloud/ocdav/webdav.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package ocdav 20 21 import ( 22 "fmt" 23 "net/http" 24 "path" 25 26 "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/errors" 27 "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind" 28 "github.com/cs3org/reva/v2/pkg/appctx" 29 ) 30 31 // Common Webdav methods. 32 // 33 // Unless otherwise noted, these are defined in RFC 4918 section 9. 34 const ( 35 MethodPropfind = "PROPFIND" 36 MethodLock = "LOCK" 37 MethodUnlock = "UNLOCK" 38 MethodProppatch = "PROPPATCH" 39 MethodMkcol = "MKCOL" 40 MethodMove = "MOVE" 41 MethodCopy = "COPY" 42 MethodReport = "REPORT" 43 ) 44 45 // WebDavHandler implements a dav endpoint 46 type WebDavHandler struct { 47 namespace string 48 useLoggedInUserNS bool 49 } 50 51 func (h *WebDavHandler) init(ns string, useLoggedInUserNS bool) error { 52 h.namespace = path.Join("/", ns) 53 h.useLoggedInUserNS = useLoggedInUserNS 54 return nil 55 } 56 57 // Handler handles requests 58 func (h *WebDavHandler) Handler(s *svc) http.Handler { 59 config := s.Config() 60 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 61 ns, newPath, err := s.ApplyLayout(r.Context(), h.namespace, h.useLoggedInUserNS, r.URL.Path) 62 if err != nil { 63 w.WriteHeader(http.StatusNotFound) 64 b, err := errors.Marshal(http.StatusNotFound, fmt.Sprintf("could not get storage for %s", r.URL.Path), "", "") 65 errors.HandleWebdavError(appctx.GetLogger(r.Context()), w, b, err) 66 return 67 } 68 r.URL.Path = newPath 69 70 // TODO initialize status with http.StatusBadRequest 71 // TODO initialize err with errors.ErrUnsupportedMethod 72 var status int // status 0 means the handler already sent the response 73 switch r.Method { 74 case MethodPropfind: 75 p := propfind.NewHandler(config.PublicURL, s.gatewaySelector, config) 76 p.HandlePathPropfind(w, r, ns) 77 case MethodLock: 78 status, err = s.handleLock(w, r, ns) 79 case MethodUnlock: 80 status, err = s.handleUnlock(w, r, ns) 81 case MethodProppatch: 82 status, err = s.handlePathProppatch(w, r, ns) 83 case MethodMkcol: 84 status, err = s.handlePathMkcol(w, r, ns) 85 case MethodMove: 86 s.handlePathMove(w, r, ns) 87 case MethodCopy: 88 s.handlePathCopy(w, r, ns) 89 case MethodReport: 90 s.handleReport(w, r, ns) 91 case http.MethodGet: 92 s.handlePathGet(w, r, ns) 93 case http.MethodPut: 94 s.handlePathPut(w, r, ns) 95 case http.MethodPost: 96 s.handlePathTusPost(w, r, ns) 97 case http.MethodOptions: 98 s.handleOptions(w, r) 99 case http.MethodHead: 100 s.handlePathHead(w, r, ns) 101 case http.MethodDelete: 102 status, err = s.handlePathDelete(w, r, ns) 103 default: 104 w.WriteHeader(http.StatusNotFound) 105 } 106 107 if status != 0 { // 0 means the handler already sent the response 108 w.WriteHeader(status) 109 if status != http.StatusNoContent { 110 var b []byte 111 if b, err = errors.Marshal(status, err.Error(), "", ""); err == nil { 112 _, err = w.Write(b) 113 } 114 } 115 } 116 if err != nil { 117 appctx.GetLogger(r.Context()).Error().Err(err).Msg(err.Error()) 118 } 119 }) 120 }