Merge pull request #9542 from 2403905/bump-reva-only-latest

[full-ci]  Bump reva latest plus PR reva#4750
This commit is contained in:
Michael Barz
2024-07-08 10:02:39 +02:00
committed by GitHub
25 changed files with 165 additions and 131 deletions

2
go.mod
View File

@@ -15,7 +15,7 @@ require (
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/coreos/go-oidc/v3 v3.10.0
github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781
github.com/cs3org/reva/v2 v2.20.1-0.20240626105341-178ea2306cde
github.com/cs3org/reva/v2 v2.20.1-0.20240705133657-2b682c603c75
github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
github.com/egirna/icap-client v0.1.1

4
go.sum
View File

@@ -1024,8 +1024,8 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c=
github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME=
github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 h1:BUdwkIlf8IS2FasrrPg8gGPHQPOrQ18MS1Oew2tmGtY=
github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/reva/v2 v2.20.1-0.20240626105341-178ea2306cde h1:N9LYCUnWBAxzI8hPymSG2VHN6MBxqCTuwNbaODAuvCk=
github.com/cs3org/reva/v2 v2.20.1-0.20240626105341-178ea2306cde/go.mod h1:Rb2XnhpGKnH7k6WBFZlMygbyBxW6ma09Z4Uk+ro0v+A=
github.com/cs3org/reva/v2 v2.20.1-0.20240705133657-2b682c603c75 h1:GdjSpSzDdH0qwamzJCwf3hCoveVB5IIWmt2l79LKWTA=
github.com/cs3org/reva/v2 v2.20.1-0.20240705133657-2b682c603c75/go.mod h1:Rb2XnhpGKnH7k6WBFZlMygbyBxW6ma09Z4Uk+ro0v+A=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=

View File

@@ -163,13 +163,13 @@ Feature: dav-versions
Then the HTTP status code should be "200"
And the following headers should be set
| header | value |
| Content-Disposition | attachment; filename*=UTF-8''"textfile0.txt"; filename="textfile0.txt" |
| Content-Disposition | attachment; filename*=UTF-8''textfile0.txt; filename="textfile0.txt" |
And the downloaded content should be "version 1"
When user "Alice" downloads the version of file "textfile0.txt" with the index "2"
Then the HTTP status code should be "200"
And the following headers should be set
| header | value |
| Content-Disposition | attachment; filename*=UTF-8''"textfile0.txt"; filename="textfile0.txt" |
| Content-Disposition | attachment; filename*=UTF-8''textfile0.txt; filename="textfile0.txt" |
And the downloaded content should be "uploaded content"
@skipOnStorage:ceph @skipOnStorage:scality
@@ -182,13 +182,13 @@ Feature: dav-versions
Then the HTTP status code should be "200"
And the following headers should be set
| header | value |
| Content-Disposition | attachment; filename*=UTF-8''"textfile0.txt"; filename="textfile0.txt" |
| Content-Disposition | attachment; filename*=UTF-8''textfile0.txt; filename="textfile0.txt" |
And the downloaded content should be "version 2"
When user "Alice" downloads the version of file "textfile0.txt" with the index "2"
Then the HTTP status code should be "200"
And the following headers should be set
| header | value |
| Content-Disposition | attachment; filename*=UTF-8''"textfile0.txt"; filename="textfile0.txt" |
| Content-Disposition | attachment; filename*=UTF-8''textfile0.txt; filename="textfile0.txt" |
And the downloaded content should be "uploaded content"

View File

@@ -270,7 +270,7 @@ Feature: download file
Then the HTTP status code should be "200"
And the following headers should be set
| header | value |
| Content-Disposition | attachment; filename*=UTF-8''"<file-name>"; filename="<file-name>" |
| Content-Disposition | attachment; filename*=UTF-8''<encoded-file-name>; filename="<file-name>" |
| Content-Security-Policy | child-src 'self'; connect-src 'self'; default-src 'none'; font-src 'self'; frame-ancestors 'self'; frame-src 'self' blob: https://embed.diagrams.net/; img-src 'self' data: blob:; manifest-src 'self'; media-src 'self'; object-src 'self' blob:; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' |
| X-Content-Type-Options | nosniff |
| X-Frame-Options | SAMEORIGIN |
@@ -279,16 +279,16 @@ Feature: download file
| X-XSS-Protection | 1; mode=block |
And the downloaded content should be "test file"
Examples:
| dav-path-version | file-name |
| old | textfile.txt |
| old | comma,.txt |
| old | 'quote'single'.txt |
| new | textfile.txt |
| new | comma,.txt |
| new | 'quote'single'.txt |
| spaces | textfile.txt |
| spaces | comma,.txt |
| spaces | 'quote'single'.txt |
| dav-path-version | file-name | encoded-file-name |
| old | textfile.txt | textfile.txt |
| old | comma,.txt | comma%2C.txt |
| old | 'quote'single'.txt | %27quote%27single%27.txt |
| new | textfile.txt | textfile.txt |
| new | comma,.txt | comma%2C.txt |
| new | 'quote'single'.txt | %27quote%27single%27.txt |
| spaces | textfile.txt | textfile.txt |
| spaces | comma,.txt | comma%2C.txt |
| spaces | 'quote'single'.txt | %27quote%27single%27.txt |
@smokeTest @issue-8361 @skipOnReva
Scenario Outline: downloading a file should serve security headers (file with doubel quotes)
@@ -298,7 +298,7 @@ Feature: download file
Then the HTTP status code should be "200"
And the following headers should be set
| header | value |
| Content-Disposition | attachment; filename*=UTF-8''""quote"double".txt"; filename=""quote"double".txt" |
| Content-Disposition | attachment; filename*=UTF-8''%22quote%22double%22.txt; filename=""quote"double".txt" |
| Content-Security-Policy | child-src 'self'; connect-src 'self'; default-src 'none'; font-src 'self'; frame-ancestors 'self'; frame-src 'self' blob: https://embed.diagrams.net/; img-src 'self' data: blob:; manifest-src 'self'; media-src 'self'; object-src 'self' blob:; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' |
| X-Content-Type-Options | nosniff |
| X-Frame-Options | SAMEORIGIN |

View File

@@ -203,14 +203,14 @@ Feature: create files and folder
Then the HTTP status code should be "<http-status-code>"
Examples:
| dav-path-version | file-name | http-status-code |
| old | /. | 500 |
| old | /. | 400 |
| old | /.. | 404 |
| old | /../lorem | 404 |
| old | | 500 |
| new | /. | 500 |
| old | | 400 |
| new | /. | 400 |
| new | /.. | 405 |
| new | /../lorem | 404 |
| new | | 500 |
| new | /../lorem | 400 |
| new | | 400 |
@skipOnRevaMaster
Examples:
@@ -227,14 +227,14 @@ Feature: create files and folder
Then the HTTP status code should be "<http-status-code>"
Examples:
| dav-path-version | folder-name | http-status-code |
| old | /. | 405 |
| old | /. | 400 |
| old | /.. | 404 |
| old | /../lorem | 404 |
| old | | 405 |
| new | /. | 405 |
| old | | 400 |
| new | /. | 400 |
| new | /.. | 405 |
| new | /../lorem | 409 |
| new | | 405 |
| new | /../lorem | 400 |
| new | | 400 |
@skipOnRevaMaster
Examples:

View File

@@ -58,7 +58,7 @@ func (s *svc) handlePathCopy(w http.ResponseWriter, r *http.Request, ns string)
if r.Body != http.NoBody {
w.WriteHeader(http.StatusUnsupportedMediaType)
b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "")
b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "", "")
errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err)
return
}
@@ -83,21 +83,21 @@ func (s *svc) handlePathCopy(w http.ResponseWriter, r *http.Request, ns string)
dst, err := net.ParseDestination(baseURI, dh)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, "failed to extract destination", "")
b, err := errors.Marshal(http.StatusBadRequest, "failed to extract destination", "", "")
errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err)
return
}
if err := ValidateName(path.Base(src), s.nameValidators); err != nil {
if err := ValidateName(filename(src), s.nameValidators); err != nil {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, "source failed naming rules", "")
b, err := errors.Marshal(http.StatusBadRequest, "source failed naming rules", "", "")
errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err)
return
}
if err := ValidateName(path.Base(dst), s.nameValidators); err != nil {
if err := ValidateDestination(filename(dst), s.nameValidators); err != nil {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, "destination failed naming rules", "")
b, err := errors.Marshal(http.StatusBadRequest, "destination failed naming rules", "", "")
errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err)
return
}
@@ -163,7 +163,7 @@ func (s *svc) executePathCopy(ctx context.Context, selector pool.Selectable[gate
if createRes.Status.Code == rpc.Code_CODE_PERMISSION_DENIED {
w.WriteHeader(http.StatusForbidden)
m := fmt.Sprintf("Permission denied to create %v", createReq.Ref.Path)
b, err := errors.Marshal(http.StatusForbidden, m, "")
b, err := errors.Marshal(http.StatusForbidden, m, "", "")
errors.HandleWebdavError(log, w, b, err)
}
return nil
@@ -264,7 +264,7 @@ func (s *svc) executePathCopy(ctx context.Context, selector pool.Selectable[gate
if uRes.Status.Code == rpc.Code_CODE_PERMISSION_DENIED {
w.WriteHeader(http.StatusForbidden)
m := fmt.Sprintf("Permissions denied to create %v", uReq.Ref.Path)
b, err := errors.Marshal(http.StatusForbidden, m, "")
b, err := errors.Marshal(http.StatusForbidden, m, "", "")
errors.HandleWebdavError(log, w, b, err)
return nil
}
@@ -327,7 +327,7 @@ func (s *svc) handleSpacesCopy(w http.ResponseWriter, r *http.Request, spaceID s
if r.Body != http.NoBody {
w.WriteHeader(http.StatusUnsupportedMediaType)
b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "")
b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "", "")
errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err)
return
}
@@ -394,7 +394,7 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, sele
w.WriteHeader(http.StatusForbidden)
// TODO path could be empty or relative...
m := fmt.Sprintf("Permission denied to create %v", createReq.Ref.Path)
b, err := errors.Marshal(http.StatusForbidden, m, "")
b, err := errors.Marshal(http.StatusForbidden, m, "", "")
errors.HandleWebdavError(log, w, b, err)
}
return nil
@@ -482,7 +482,7 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, sele
w.WriteHeader(http.StatusForbidden)
// TODO path can be empty or relative
m := fmt.Sprintf("Permissions denied to create %v", uReq.Ref.Path)
b, err := errors.Marshal(http.StatusForbidden, m, "")
b, err := errors.Marshal(http.StatusForbidden, m, "", "")
errors.HandleWebdavError(log, w, b, err)
return nil
}
@@ -554,7 +554,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re
}
if isChild {
w.WriteHeader(http.StatusConflict)
b, err := errors.Marshal(http.StatusBadRequest, "can not copy a folder into one of its children", "")
b, err := errors.Marshal(http.StatusBadRequest, "can not copy a folder into one of its children", "", "")
errors.HandleWebdavError(log, w, b, err)
return nil
}
@@ -577,7 +577,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re
if isParent {
w.WriteHeader(http.StatusConflict)
b, err := errors.Marshal(http.StatusBadRequest, "can not copy a folder into its parent", "")
b, err := errors.Marshal(http.StatusBadRequest, "can not copy a folder into its parent", "", "")
errors.HandleWebdavError(log, w, b, err)
return nil
@@ -585,7 +585,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re
if srcRef.Path == dstRef.Path && srcRef.ResourceId == dstRef.ResourceId {
w.WriteHeader(http.StatusConflict)
b, err := errors.Marshal(http.StatusBadRequest, "source and destination are the same", "")
b, err := errors.Marshal(http.StatusBadRequest, "source and destination are the same", "", "")
errors.HandleWebdavError(log, w, b, err)
return nil
}
@@ -595,7 +595,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re
if err != nil {
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Overwrite header is set to incorrect value %v", overwrite)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(log, w, b, err)
return nil
}
@@ -605,7 +605,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re
if err != nil {
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Depth header is set to incorrect value %v", dh)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(log, w, b, err)
return nil
}
@@ -634,7 +634,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re
case srcStatRes.Status.Code == rpc.Code_CODE_NOT_FOUND:
errors.HandleErrorStatus(log, w, srcStatRes.Status)
m := fmt.Sprintf("Resource %v not found", srcStatReq.Ref.Path)
b, err := errors.Marshal(http.StatusNotFound, m, "")
b, err := errors.Marshal(http.StatusNotFound, m, "", "")
errors.HandleWebdavError(log, w, b, err)
return nil
case srcStatRes.Status.Code != rpc.Code_CODE_OK:
@@ -672,7 +672,7 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re
log.Warn().Bool("overwrite", overwrite).Msg("dst already exists")
w.WriteHeader(http.StatusPreconditionFailed)
m := fmt.Sprintf("Could not overwrite Resource %v", dstRef.Path)
b, err := errors.Marshal(http.StatusPreconditionFailed, m, "")
b, err := errors.Marshal(http.StatusPreconditionFailed, m, "", "")
errors.HandleWebdavError(log, w, b, err) // 412, see https://tools.ietf.org/html/rfc4918#section-9.8.5
return nil
}

View File

@@ -52,6 +52,14 @@ const (
WwwAuthenticate = "Www-Authenticate"
)
const (
ErrListingMembers = "ERR_LISTING_MEMBERS_NOT_ALLOWED"
ErrInvalidCredentials = "ERR_INVALID_CREDENTIALS"
ErrMissingBasicAuth = "ERR_MISSING_BASIC_AUTH"
ErrMissingBearerAuth = "ERR_MISSING_BEARER_AUTH"
ErrFileNotFoundInRoot = "ERR_FILE_NOT_FOUND_IN_ROOT"
)
// DavHandler routes to the different sub handlers
type DavHandler struct {
AvatarsHandler *AvatarsHandler
@@ -132,7 +140,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler {
if r.Header.Get(net.HeaderDepth) == "" {
w.WriteHeader(http.StatusMethodNotAllowed)
b, err := errors.Marshal(http.StatusMethodNotAllowed, "Listing members of this collection is disabled", "")
b, err := errors.Marshal(http.StatusMethodNotAllowed, "Listing members of this collection is disabled", "", ErrListingMembers)
if err != nil {
log.Error().Msgf("error marshaling xml response: %s", b)
w.WriteHeader(http.StatusInternalServerError)
@@ -312,11 +320,11 @@ func (h *DavHandler) Handler(s *svc) http.Handler {
case res.Status.Code == rpc.Code_CODE_UNAUTHENTICATED:
w.WriteHeader(http.StatusUnauthorized)
if hasValidBasicAuthHeader {
b, err := errors.Marshal(http.StatusUnauthorized, "Username or password was incorrect", "")
b, err := errors.Marshal(http.StatusUnauthorized, "Username or password was incorrect", "", ErrInvalidCredentials)
errors.HandleWebdavError(log, w, b, err)
return
}
b, err := errors.Marshal(http.StatusUnauthorized, "No 'Authorization: Basic' header found", "")
b, err := errors.Marshal(http.StatusUnauthorized, "No 'Authorization: Basic' header found", "", ErrMissingBasicAuth)
errors.HandleWebdavError(log, w, b, err)
return
case res.Status.Code == rpc.Code_CODE_NOT_FOUND:
@@ -358,7 +366,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler {
if !userExists {
w.Header().Add(WwwAuthenticate, fmt.Sprintf("Bearer realm=\"%s\", charset=\"UTF-8\"", r.Host))
w.WriteHeader(http.StatusUnauthorized)
b, err := errors.Marshal(http.StatusUnauthorized, "No 'Authorization: Bearer' header found", "")
b, err := errors.Marshal(http.StatusUnauthorized, "No 'Authorization: Bearer' header found", "", ErrMissingBearerAuth)
errors.HandleWebdavError(log, w, b, err)
return
}
@@ -388,7 +396,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler {
default:
w.WriteHeader(http.StatusNotFound)
b, err := errors.Marshal(http.StatusNotFound, "File not found in root", "")
b, err := errors.Marshal(http.StatusNotFound, "File not found in root", "", ErrFileNotFoundInRoot)
errors.HandleWebdavError(log, w, b, err)
}
})

View File

@@ -101,13 +101,14 @@ type Exception struct {
}
// Marshal just calls the xml marshaller for a given exception.
func Marshal(code int, message string, header string) ([]byte, error) {
func Marshal(code int, message string, header string, errorCode string) ([]byte, error) {
xmlstring, err := xml.Marshal(&ErrorXML{
Xmlnsd: "DAV",
Xmlnss: "http://sabredav.org/ns",
Exception: sabreException[code],
Message: message,
Header: header,
ErrorCode: errorCode,
})
if err != nil {
return nil, err
@@ -126,6 +127,7 @@ type ErrorXML struct {
Xmlnss string `xml:"xmlns:s,attr"`
Exception string `xml:"s:exception"`
Message string `xml:"s:message"`
ErrorCode string `xml:"s:errorcode"`
InnerXML []byte `xml:",innerxml"`
// Header is used to indicate the conflicting request header
Header string `xml:"s:header,omitempty"`

View File

@@ -68,7 +68,7 @@ func (h *MetaHandler) Handler(s *svc) http.Handler {
logger.Debug().Str("prop", net.PropOcMetaPathForUser).Msg("invalid resource id")
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Invalid resource id %v", id)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(logger, w, b, err)
return
}
@@ -139,7 +139,7 @@ func (h *MetaHandler) handlePathForUser(w http.ResponseWriter, r *http.Request,
sublog.Debug().Str("code", string(pathRes.Status.Code)).Msg("resource not found")
w.WriteHeader(http.StatusNotFound)
m := fmt.Sprintf("Resource %s not found", id)
b, err := errors.Marshal(http.StatusNotFound, m, "")
b, err := errors.Marshal(http.StatusNotFound, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
case rpc.Code_CODE_PERMISSION_DENIED:
@@ -147,7 +147,7 @@ func (h *MetaHandler) handlePathForUser(w http.ResponseWriter, r *http.Request,
sublog.Debug().Str("code", string(pathRes.Status.Code)).Msg("resource access denied")
w.WriteHeader(http.StatusNotFound)
m := fmt.Sprintf("Resource %s not found", id)
b, err := errors.Marshal(http.StatusNotFound, m, "")
b, err := errors.Marshal(http.StatusNotFound, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}

View File

@@ -39,10 +39,10 @@ func (s *svc) handlePathMkcol(w http.ResponseWriter, r *http.Request, ns string)
ctx, span := appctx.GetTracerProvider(r.Context()).Tracer(tracerName).Start(r.Context(), "mkcol")
defer span.End()
fn := path.Join(ns, r.URL.Path)
if err := ValidateName(path.Base(fn), s.nameValidators); err != nil {
if err := ValidateName(filename(r.URL.Path), s.nameValidators); err != nil {
return http.StatusBadRequest, err
}
fn := path.Join(ns, r.URL.Path)
sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger()
client, err := s.gatewaySelector.Next()

View File

@@ -44,7 +44,7 @@ func (s *svc) handlePathMove(w http.ResponseWriter, r *http.Request, ns string)
if r.Body != http.NoBody {
w.WriteHeader(http.StatusUnsupportedMediaType)
b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "")
b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "", "")
errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err)
return
}
@@ -55,21 +55,21 @@ func (s *svc) handlePathMove(w http.ResponseWriter, r *http.Request, ns string)
dstPath, err := net.ParseDestination(baseURI, dh)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, "failed to extract destination", "")
b, err := errors.Marshal(http.StatusBadRequest, "failed to extract destination", "", "")
errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err)
return
}
if err := ValidateName(path.Base(srcPath), s.nameValidators); err != nil {
if err := ValidateName(filename(srcPath), s.nameValidators); err != nil {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, "source failed naming rules", "")
b, err := errors.Marshal(http.StatusBadRequest, "source failed naming rules", "", "")
errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err)
return
}
if err := ValidateName(path.Base(dstPath), s.nameValidators); err != nil {
if err := ValidateDestination(filename(dstPath), s.nameValidators); err != nil {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, "destination naming rules", "")
b, err := errors.Marshal(http.StatusBadRequest, "destination naming rules", "", "")
errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err)
return
}
@@ -108,7 +108,7 @@ func (s *svc) handleSpacesMove(w http.ResponseWriter, r *http.Request, srcSpaceI
if r.Body != http.NoBody {
w.WriteHeader(http.StatusUnsupportedMediaType)
b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "")
b, err := errors.Marshal(http.StatusUnsupportedMediaType, "body must be empty", "", "")
errors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err)
return
}
@@ -157,7 +157,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req
}
if isChild {
w.WriteHeader(http.StatusConflict)
b, err := errors.Marshal(http.StatusBadRequest, "can not move a folder into one of its children", "")
b, err := errors.Marshal(http.StatusBadRequest, "can not move a folder into one of its children", "", "")
errors.HandleWebdavError(&log, w, b, err)
return
}
@@ -179,7 +179,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req
}
if isParent {
w.WriteHeader(http.StatusConflict)
b, err := errors.Marshal(http.StatusBadRequest, "can not move a folder into its parent", "")
b, err := errors.Marshal(http.StatusBadRequest, "can not move a folder into its parent", "", "")
errors.HandleWebdavError(&log, w, b, err)
return
@@ -213,7 +213,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req
if srcStatRes.Status.Code == rpc.Code_CODE_NOT_FOUND {
w.WriteHeader(http.StatusNotFound)
m := fmt.Sprintf("Resource %v not found", srcStatReq.Ref.Path)
b, err := errors.Marshal(http.StatusNotFound, m, "")
b, err := errors.Marshal(http.StatusNotFound, m, "", "")
errors.HandleWebdavError(&log, w, b, err)
}
errors.HandleErrorStatus(&log, w, srcStatRes.Status)
@@ -321,7 +321,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req
w.WriteHeader(status)
b, err := errors.Marshal(status, m, "")
b, err := errors.Marshal(status, m, "", "")
errors.HandleWebdavError(&log, w, b, err)
return
}

View File

@@ -19,6 +19,7 @@
package net
import (
"net/url"
"time"
cs3types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
@@ -27,7 +28,7 @@ import (
// ContentDispositionAttachment builds a ContentDisposition Attachment header with various filename encodings
func ContentDispositionAttachment(filename string) string {
return "attachment; filename*=UTF-8''\"" + filename + "\"; filename=\"" + filename + "\""
return "attachment; filename*=UTF-8''" + url.QueryEscape(filename) + "; filename=\"" + filename + "\""
}
// RFC1123Z formats a CS3 Timestamp to be used in HTTP headers like Last-Modified

View File

@@ -394,3 +394,8 @@ func (s *svc) referenceIsChildOf(ctx context.Context, selector pool.Selectable[g
pp := path.Join(parentPathRes.Path, parent.Path) + "/"
return strings.HasPrefix(cp, pp), nil
}
// filename returns the base filename from a path and replaces any slashes with an empty string
func filename(p string) string {
return strings.Trim(path.Base(p), "/")
}

View File

@@ -243,7 +243,7 @@ func (p *Handler) HandlePathPropfind(w http.ResponseWriter, r *http.Request, ns
sublog.Debug().Str("depth", dh).Msg(err.Error())
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Invalid Depth header value: %v", dh)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -255,7 +255,7 @@ func (p *Handler) HandlePathPropfind(w http.ResponseWriter, r *http.Request, ns
sublog.Debug().Str("depth", dh).Msg(errors.ErrInvalidDepth.Error())
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Invalid Depth header value: %v", dh)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -312,7 +312,7 @@ func (p *Handler) HandleSpacesPropfind(w http.ResponseWriter, r *http.Request, s
sublog.Debug().Str("depth", dh).Msg(err.Error())
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Invalid Depth header value: %v", dh)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -324,7 +324,7 @@ func (p *Handler) HandleSpacesPropfind(w http.ResponseWriter, r *http.Request, s
sublog.Debug().Str("depth", dh).Msg(errors.ErrInvalidDepth.Error())
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Invalid Depth header value: %v", dh)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -341,7 +341,7 @@ func (p *Handler) HandleSpacesPropfind(w http.ResponseWriter, r *http.Request, s
sublog.Debug().Msg("invalid space id")
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Invalid space id: %v", spaceID)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -391,7 +391,7 @@ func (p *Handler) HandleSpacesPropfind(w http.ResponseWriter, r *http.Request, s
m = "Resource not found" // mimic the oc10 error message
}
w.WriteHeader(status)
b, err := errors.Marshal(status, m, "")
b, err := errors.Marshal(status, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -618,7 +618,7 @@ func (p *Handler) getResourceInfos(ctx context.Context, w http.ResponseWriter, r
// TODO if we have children invent node on the fly
w.WriteHeader(http.StatusNotFound)
m := "Resource not found"
b, err := errors.Marshal(http.StatusNotFound, m, "")
b, err := errors.Marshal(http.StatusNotFound, m, "", "")
errors.HandleWebdavError(&log, w, b, err)
return nil, false, false
}

View File

@@ -208,7 +208,7 @@ func (s *svc) handleProppatch(ctx context.Context, w http.ResponseWriter, r *htt
m = "Resource not found" // mimic the oc10 error message
}
w.WriteHeader(status)
b, err := errors.Marshal(status, m, "")
b, err := errors.Marshal(status, m, "", "")
errors.HandleWebdavError(&log, w, b, err)
return nil, nil, false
}
@@ -273,7 +273,7 @@ func (s *svc) handleProppatch(ctx context.Context, w http.ResponseWriter, r *htt
m = "Resource not found" // mimic the oc10 error message
}
w.WriteHeader(status)
b, err := errors.Marshal(status, m, "")
b, err := errors.Marshal(status, m, "", "")
errors.HandleWebdavError(&log, w, b, err)
return nil, nil, false
}

View File

@@ -102,7 +102,7 @@ func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns s
span.SetStatus(codes.Error, ocdaverrors.ErrTokenStatInfoMissing.Error())
span.SetAttributes(semconv.HTTPStatusCodeKey.Int(http.StatusInternalServerError))
w.WriteHeader(http.StatusInternalServerError)
b, err := ocdaverrors.Marshal(http.StatusInternalServerError, ocdaverrors.ErrTokenStatInfoMissing.Error(), "")
b, err := ocdaverrors.Marshal(http.StatusInternalServerError, ocdaverrors.ErrTokenStatInfoMissing.Error(), "", "")
ocdaverrors.HandleWebdavError(appctx.GetLogger(ctx), w, b, err)
return
}
@@ -118,7 +118,7 @@ func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns s
sublog.Debug().Str("depth", dh).Msg(err.Error())
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Invalid Depth header value: %v", dh)
b, err := ocdaverrors.Marshal(http.StatusBadRequest, m, "")
b, err := ocdaverrors.Marshal(http.StatusBadRequest, m, "", "")
ocdaverrors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -130,7 +130,7 @@ func (s *svc) handlePropfindOnToken(w http.ResponseWriter, r *http.Request, ns s
sublog.Debug().Str("depth", dh).Msg(ocdaverrors.ErrInvalidDepth.Error())
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Invalid Depth header value: %v", dh)
b, err := ocdaverrors.Marshal(http.StatusBadRequest, m, "")
b, err := ocdaverrors.Marshal(http.StatusBadRequest, m, "", "")
ocdaverrors.HandleWebdavError(&sublog, w, b, err)
return
}

View File

@@ -113,8 +113,15 @@ func (s *svc) handlePathPut(w http.ResponseWriter, r *http.Request, ns string) {
defer span.End()
fn := path.Join(ns, r.URL.Path)
sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger()
if err := ValidateName(filename(r.URL.Path), s.nameValidators); err != nil {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, err.Error(), "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
space, status, err := spacelookup.LookUpStorageSpaceForPath(ctx, s.gatewaySelector, fn)
if err != nil {
sublog.Error().Err(err).Str("path", fn).Msg("failed to look up storage space")
@@ -135,20 +142,13 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ
return
}
length, err := getContentLength(w, r)
length, err := getContentLength(r)
if err != nil {
log.Error().Err(err).Msg("error getting the content length")
w.WriteHeader(http.StatusBadRequest)
return
}
if err := ValidateName(filepath.Base(ref.Path), s.nameValidators); err != nil {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, err.Error(), "")
errors.HandleWebdavError(&log, w, b, err)
return
}
client, err := s.gatewaySelector.Next()
if err != nil {
log.Error().Err(err).Msg("error selecting next gateway client")
@@ -318,7 +318,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ
m = "Resource not found" // mimic the oc10 error message
}
w.WriteHeader(status)
b, err := errors.Marshal(status, m, "")
b, err := errors.Marshal(status, m, "", "")
errors.HandleWebdavError(&log, w, b, err)
case rpc.Code_CODE_ABORTED:
w.WriteHeader(http.StatusPreconditionFailed)
@@ -364,7 +364,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ
}
if httpRes.StatusCode == errtypes.StatusChecksumMismatch {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, "The computed checksum does not match the one received from the client.", "")
b, err := errors.Marshal(http.StatusBadRequest, "The computed checksum does not match the one received from the client.", "", "")
errors.HandleWebdavError(&log, w, b, err)
return
}
@@ -411,6 +411,15 @@ func (s *svc) handleSpacesPut(w http.ResponseWriter, r *http.Request, spaceID st
return
}
if r.URL.Path != "/" {
if err := ValidateName(filepath.Base(ref.Path), s.nameValidators); err != nil {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, err.Error(), "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
}
s.handlePut(ctx, w, r, &ref, sublog)
}
@@ -432,7 +441,7 @@ func checkPreconditions(w http.ResponseWriter, r *http.Request, log zerolog.Logg
return true
}
func getContentLength(w http.ResponseWriter, r *http.Request) (int64, error) {
func getContentLength(r *http.Request) (int64, error) {
length, err := strconv.ParseInt(r.Header.Get(net.HeaderContentLength), 10, 64)
if err != nil {
// Fallback to Upload-Length

View File

@@ -115,7 +115,7 @@ func (h *SpacesHandler) Handler(s *svc, trashbinHandler *TrashbinHandler) http.H
w.WriteHeader(status)
if status != http.StatusNoContent {
var b []byte
if b, err = errors.Marshal(status, err.Error(), ""); err == nil {
if b, err = errors.Marshal(status, err.Error(), "", ""); err == nil {
_, err = w.Write(b)
}
}

View File

@@ -129,7 +129,7 @@ func (s *svc) handleTPCPull(ctx context.Context, w http.ResponseWriter, r *http.
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Overwrite header is set to incorrect value %v", overwrite)
sublog.Warn().Msgf("HTTP TPC Pull: %s", m)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -293,7 +293,7 @@ func (s *svc) handleTPCPush(ctx context.Context, w http.ResponseWriter, r *http.
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Overwrite header is set to incorrect value %v", overwrite)
sublog.Warn().Msgf("HTTP TPC Push: %s", m)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}

View File

@@ -91,7 +91,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler {
// listing other users trash is forbidden, no auth will change that
// do not leak existence of space and return 404
w.WriteHeader(http.StatusNotFound)
b, err := errors.Marshal(http.StatusNotFound, "not found", "")
b, err := errors.Marshal(http.StatusNotFound, "not found", "", "")
if err != nil {
log.Error().Msgf("error marshaling xml response: %s", b)
w.WriteHeader(http.StatusInternalServerError)
@@ -110,7 +110,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler {
ns, newPath, err := s.ApplyLayout(ctx, h.namespace, useLoggedInUser, r.URL.Path)
if err != nil {
w.WriteHeader(http.StatusNotFound)
b, err := errors.Marshal(http.StatusNotFound, fmt.Sprintf("could not get storage for %s", r.URL.Path), "")
b, err := errors.Marshal(http.StatusNotFound, fmt.Sprintf("could not get storage for %s", r.URL.Path), "", "")
errors.HandleWebdavError(appctx.GetLogger(r.Context()), w, b, err)
}
r.URL.Path = newPath
@@ -125,7 +125,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler {
case rpcstatus.Code != rpc.Code_CODE_OK:
httpStatus := rstatus.HTTPStatusFromCode(rpcstatus.Code)
w.WriteHeader(httpStatus)
b, err := errors.Marshal(httpStatus, rpcstatus.Message, "")
b, err := errors.Marshal(httpStatus, rpcstatus.Message, "", "")
errors.HandleWebdavError(log, w, b, err)
return
}
@@ -165,7 +165,7 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler {
if rpcstatus.Code != rpc.Code_CODE_OK {
httpStatus := rstatus.HTTPStatusFromCode(rpcstatus.Code)
w.WriteHeader(httpStatus)
b, err := errors.Marshal(httpStatus, rpcstatus.Message, "")
b, err := errors.Marshal(httpStatus, rpcstatus.Message, "", "")
errors.HandleWebdavError(log, w, b, err)
return
}
@@ -196,7 +196,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s
sublog.Debug().Str("depth", dh).Msg(err.Error())
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Invalid Depth header value: %v", dh)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -208,7 +208,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s
sublog.Debug().Str("depth", dh).Msg(errors.ErrInvalidDepth.Error())
w.WriteHeader(http.StatusBadRequest)
m := fmt.Sprintf("Invalid Depth header value: %v", dh)
b, err := errors.Marshal(http.StatusBadRequest, m, "")
b, err := errors.Marshal(http.StatusBadRequest, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -256,7 +256,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s
if getRecycleRes.Status.Code != rpc.Code_CODE_OK {
httpStatus := rstatus.HTTPStatusFromCode(getRecycleRes.Status.Code)
w.WriteHeader(httpStatus)
b, err := errors.Marshal(httpStatus, getRecycleRes.Status.Message, "")
b, err := errors.Marshal(httpStatus, getRecycleRes.Status.Message, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -286,7 +286,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s
if getRecycleRes.Status.Code != rpc.Code_CODE_OK {
httpStatus := rstatus.HTTPStatusFromCode(getRecycleRes.Status.Code)
w.WriteHeader(httpStatus)
b, err := errors.Marshal(httpStatus, getRecycleRes.Status.Message, "")
b, err := errors.Marshal(httpStatus, getRecycleRes.Status.Message, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -544,6 +544,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc
http.StatusPreconditionFailed,
"The destination node already exists, and the overwrite header is set to false",
net.HeaderOverwrite,
"",
)
errors.HandleWebdavError(&sublog, w, b, err)
return
@@ -579,7 +580,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc
if res.Status.Code != rpc.Code_CODE_OK {
if res.Status.Code == rpc.Code_CODE_PERMISSION_DENIED {
w.WriteHeader(http.StatusForbidden)
b, err := errors.Marshal(http.StatusForbidden, "Permission denied to restore", "")
b, err := errors.Marshal(http.StatusForbidden, "Permission denied to restore", "", "")
errors.HandleWebdavError(&sublog, w, b, err)
}
errors.HandleErrorStatus(&sublog, w, res.Status)
@@ -638,7 +639,7 @@ func (h *TrashbinHandler) delete(w http.ResponseWriter, r *http.Request, s *svc,
sublog.Debug().Interface("status", res.Status).Msg("resource not found")
w.WriteHeader(http.StatusConflict)
m := fmt.Sprintf("path %s not found", trashPath)
b, err := errors.Marshal(http.StatusConflict, m, "")
b, err := errors.Marshal(http.StatusConflict, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
case rpc.Code_CODE_PERMISSION_DENIED:
w.WriteHeader(http.StatusForbidden)
@@ -648,7 +649,7 @@ func (h *TrashbinHandler) delete(w http.ResponseWriter, r *http.Request, s *svc,
} else {
m = "Permission denied to delete"
}
b, err := errors.Marshal(http.StatusForbidden, m, "")
b, err := errors.Marshal(http.StatusForbidden, m, "", "")
errors.HandleWebdavError(&sublog, w, b, err)
default:
errors.HandleErrorStatus(&sublog, w, res.Status)

View File

@@ -58,21 +58,15 @@ func (s *svc) handlePathTusPost(w http.ResponseWriter, r *http.Request, ns strin
// read filename from metadata
meta := tusd.ParseMetadataHeader(r.Header.Get(net.HeaderUploadMetadata))
if err := ValidateName(path.Base(meta["filename"]), s.nameValidators); err != nil {
w.WriteHeader(http.StatusPreconditionFailed)
return
}
// append filename to current dir
fn := path.Join(ns, r.URL.Path, meta["filename"])
sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger()
// check tus headers?
ref := &provider.Reference{
// FIXME ResourceId?
Path: fn,
// a path based request has no resource id, so we can only provide a path. The gateway has te figure out which provider is responsible
Path: path.Join(ns, r.URL.Path, meta["filename"]),
}
sublog := appctx.GetLogger(ctx).With().Str("path", r.URL.Path).Str("filename", meta["filename"]).Logger()
s.handleTusPost(ctx, w, r, meta, ref, sublog)
}
@@ -82,12 +76,6 @@ func (s *svc) handleSpacesTusPost(w http.ResponseWriter, r *http.Request, spaceI
// read filename from metadata
meta := tusd.ParseMetadataHeader(r.Header.Get(net.HeaderUploadMetadata))
if err := ValidateName(path.Base(meta["filename"]), s.nameValidators); err != nil {
w.WriteHeader(http.StatusPreconditionFailed)
return
}
sublog := appctx.GetLogger(ctx).With().Str("spaceid", spaceID).Str("path", r.URL.Path).Logger()
ref, err := spacelookup.MakeStorageSpaceReference(spaceID, path.Join(r.URL.Path, meta["filename"]))
if err != nil {
@@ -95,6 +83,8 @@ func (s *svc) handleSpacesTusPost(w http.ResponseWriter, r *http.Request, spaceI
return
}
sublog := appctx.GetLogger(ctx).With().Str("spaceid", spaceID).Str("path", r.URL.Path).Str("filename", meta["filename"]).Logger()
s.handleTusPost(ctx, w, r, meta, &ref, sublog)
}
@@ -116,6 +106,10 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http.
w.WriteHeader(http.StatusPreconditionFailed)
return
}
if err := ValidateName(filename(meta["filename"]), s.nameValidators); err != nil {
w.WriteHeader(http.StatusPreconditionFailed)
return
}
// Test if the target is a secret filedrop
var isSecretFileDrop bool

View File

@@ -27,6 +27,11 @@ func ValidatorsFromConfig(c *config.Config) []Validator {
// ValidateName will validate a file or folder name, returning an error when it is not accepted
func ValidateName(name string, validators []Validator) error {
return ValidateDestination(name, append(validators, notReserved()))
}
// ValidateDestination will validate a file or folder destination name (which can be . or ..), returning an error when it is not accepted
func ValidateDestination(name string, validators []Validator) error {
for _, v := range validators {
if err := v(name); err != nil {
return fmt.Errorf("name validation failed: %w", err)
@@ -35,6 +40,15 @@ func ValidateName(name string, validators []Validator) error {
return nil
}
func notReserved() Validator {
return func(s string) error {
if s == ".." || s == "." {
return errors.New(". and .. are reserved names")
}
return nil
}
}
func notEmpty() Validator {
return func(s string) error {
if strings.TrimSpace(s) == "" {

View File

@@ -139,7 +139,7 @@ func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request,
if res.Status.Code != rpc.Code_CODE_OK {
if res.Status.Code == rpc.Code_CODE_PERMISSION_DENIED || res.Status.Code == rpc.Code_CODE_NOT_FOUND {
w.WriteHeader(http.StatusNotFound)
b, err := errors.Marshal(http.StatusNotFound, "Resource not found", "")
b, err := errors.Marshal(http.StatusNotFound, "Resource not found", "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -158,7 +158,7 @@ func (h *VersionsHandler) doListVersions(w http.ResponseWriter, r *http.Request,
if lvRes.Status.Code != rpc.Code_CODE_OK {
if lvRes.Status.Code == rpc.Code_CODE_PERMISSION_DENIED {
w.WriteHeader(http.StatusForbidden)
b, err := errors.Marshal(http.StatusForbidden, "You have no permission to list file versions on this resource", "")
b, err := errors.Marshal(http.StatusForbidden, "You have no permission to list file versions on this resource", "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -247,7 +247,7 @@ func (h *VersionsHandler) doRestore(w http.ResponseWriter, r *http.Request, s *s
if res.Status.Code != rpc.Code_CODE_OK {
if res.Status.Code == rpc.Code_CODE_PERMISSION_DENIED {
w.WriteHeader(http.StatusForbidden)
b, err := errors.Marshal(http.StatusForbidden, "You have no permission to restore versions on this resource", "")
b, err := errors.Marshal(http.StatusForbidden, "You have no permission to restore versions on this resource", "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}

View File

@@ -61,7 +61,7 @@ func (h *WebDavHandler) Handler(s *svc) http.Handler {
ns, newPath, err := s.ApplyLayout(r.Context(), h.namespace, h.useLoggedInUserNS, r.URL.Path)
if err != nil {
w.WriteHeader(http.StatusNotFound)
b, err := errors.Marshal(http.StatusNotFound, fmt.Sprintf("could not get storage for %s", r.URL.Path), "")
b, err := errors.Marshal(http.StatusNotFound, fmt.Sprintf("could not get storage for %s", r.URL.Path), "", "")
errors.HandleWebdavError(appctx.GetLogger(r.Context()), w, b, err)
return
}
@@ -108,7 +108,7 @@ func (h *WebDavHandler) Handler(s *svc) http.Handler {
w.WriteHeader(status)
if status != http.StatusNoContent {
var b []byte
if b, err = errors.Marshal(status, err.Error(), ""); err == nil {
if b, err = errors.Marshal(status, err.Error(), "", ""); err == nil {
_, err = w.Write(b)
}
}

2
vendor/modules.txt vendored
View File

@@ -366,7 +366,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1
github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1
github.com/cs3org/go-cs3apis/cs3/tx/v1beta1
github.com/cs3org/go-cs3apis/cs3/types/v1beta1
# github.com/cs3org/reva/v2 v2.20.1-0.20240626105341-178ea2306cde
# github.com/cs3org/reva/v2 v2.20.1-0.20240705133657-2b682c603c75
## explicit; go 1.21
github.com/cs3org/reva/v2/cmd/revad/internal/grace
github.com/cs3org/reva/v2/cmd/revad/runtime