adapt test

This commit is contained in:
Roman Perekhod
2024-07-04 19:59:49 +02:00
committed by Michael Barz
parent 7babaf634b
commit 572b32075e
21 changed files with 113 additions and 96 deletions

2
go.mod
View File

@@ -368,3 +368,5 @@ replace github.com/unrolled/secure => github.com/DeepDiver1975/secure v0.0.0-202
// exclude the v2 line of go-sqlite3 which was released accidentally and prevents pulling in newer versions of go-sqlite3
// see https://github.com/mattn/go-sqlite3/issues/965 for more details
exclude github.com/mattn/go-sqlite3 v2.0.3+incompatible
replace github.com/cs3org/reva/v2 => github.com/2403905/reva/v2 v2.0.0-20240705082107-f9c7bb40d488

4
go.sum
View File

@@ -766,6 +766,8 @@ dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
github.com/2403905/reva/v2 v2.0.0-20240705082107-f9c7bb40d488 h1:7EAtJ37ia/WJaw0oYi3OnpSCNbwgStorEPzjbQMjCaI=
github.com/2403905/reva/v2 v2.0.0-20240705082107-f9c7bb40d488/go.mod h1:Rb2XnhpGKnH7k6WBFZlMygbyBxW6ma09Z4Uk+ro0v+A=
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck=
@@ -1024,8 +1026,6 @@ 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.20240703055901-d599d8898158 h1:FaA/DIEtTvHLzShprZWmNkeLS2t85YlUxrJahMxweFo=
github.com/cs3org/reva/v2 v2.20.1-0.20240703055901-d599d8898158/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''<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 |
| old | textfile.txt |
| old | comma%2C.txt |
| old | %27quote%27single%27.txt |
| new | textfile.txt |
| new | comma%2C.txt |
| new | %27quote%27single%27.txt |
| spaces | textfile.txt |
| spaces | comma%2C.txt |
| spaces | %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

@@ -215,10 +215,10 @@ Feature: create files and folder
@skipOnRevaMaster
Examples:
| dav-path-version | file-name | http-status-code |
| spaces | /. | 400 |
| spaces | /. | 500 |
| spaces | /.. | 405 |
| spaces | /../lorem | 400 |
| spaces | | 400 |
| spaces | /../lorem | 404 |
| spaces | | 500 |
Scenario Outline: try to create folder with '.', '..' and 'empty'

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(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 := 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

@@ -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(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 := 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

@@ -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

@@ -117,7 +117,7 @@ func (s *svc) handlePathPut(w http.ResponseWriter, r *http.Request, ns string) {
if err := ValidateName(filename(r.URL.Path), s.nameValidators); err != nil {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, err.Error(), "")
b, err := errors.Marshal(http.StatusBadRequest, err.Error(), "", "")
errors.HandleWebdavError(&sublog, w, b, err)
return
}
@@ -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,11 +411,13 @@ func (s *svc) handleSpacesPut(w http.ResponseWriter, r *http.Request, spaceID st
return
}
if err := ValidateName(filename(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
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)

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

@@ -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)
}
}

3
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.20240703055901-d599d8898158
# github.com/cs3org/reva/v2 v2.20.1-0.20240703055901-d599d8898158 => github.com/2403905/reva/v2 v2.0.0-20240705082107-f9c7bb40d488
## explicit; go 1.21
github.com/cs3org/reva/v2/cmd/revad/internal/grace
github.com/cs3org/reva/v2/cmd/revad/runtime
@@ -2434,3 +2434,4 @@ stash.kopano.io/kgol/rndm
# github.com/studio-b12/gowebdav => github.com/aduffeck/gowebdav v0.0.0-20231215102054-212d4a4374f6
# github.com/egirna/icap-client => github.com/fschade/icap-client v0.0.0-20240123094924-5af178158eaf
# github.com/unrolled/secure => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c
# github.com/cs3org/reva/v2 => github.com/2403905/reva/v2 v2.0.0-20240705082107-f9c7bb40d488