Skip to content

Commit da6d29e

Browse files
authored
Make PROPFIND response proper for PROPFINDs to files (#5443)
1 parent 3c81581 commit da6d29e

File tree

2 files changed

+33
-41
lines changed

2 files changed

+33
-41
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Bugfix: make PROPFIND on files proper
2+
3+
https://github.com/cs3org/reva/pull/5443

internal/http/services/owncloud/ocdav/propfind.go

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,15 @@ func (s *svc) handlePathPropfind(w http.ResponseWriter, r *http.Request, ns stri
9191
return
9292
}
9393

94-
parentInfo, resourceInfos, ok := s.getResourceInfos(ctx, w, r, pf, ref, false, sublog)
94+
parentInfo, resourceInfos, hrefBase, ok := s.getResourceInfos(ctx, w, r, pf, ref, sublog)
9595
if !ok {
9696
// getResourceInfos handles responses in case of an error so we can just return here.
9797
return
9898
}
99-
s.propfindResponse(ctx, w, r, ns, pf, parentInfo, resourceInfos, sublog)
99+
s.propfindResponse(ctx, w, r, ns, hrefBase, pf, parentInfo, resourceInfos, sublog)
100100
}
101101

102-
func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *http.Request, namespace string, pf propfindXML, parentInfo *provider.ResourceInfo, resourceInfos []*provider.ResourceInfo, log zerolog.Logger) {
102+
func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *http.Request, namespace, hrefBase string, pf propfindXML, parentInfo *provider.ResourceInfo, resourceInfos []*provider.ResourceInfo, log zerolog.Logger) {
103103
user, ok := appctx.ContextGetUser(ctx)
104104
if !ok {
105105
w.WriteHeader(http.StatusUnauthorized)
@@ -167,12 +167,8 @@ func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *ht
167167
} else {
168168
log.Error().Err(err).Msg("propfindResponse: couldn't list user shares")
169169
}
170-
href := r.URL.Path
171-
if ctxPath := ctx.Value(ctxKeyIncomingURL); ctxPath != nil {
172-
href = ctxPath.(string)
173-
}
174170

175-
propRes, err := s.multistatusResponse(ctx, &pf, resourceInfos, parentInfo, namespace, href, usershares, linkshares)
171+
propRes, err := s.multistatusResponse(ctx, &pf, resourceInfos, parentInfo, namespace, hrefBase, usershares, linkshares)
176172
if err != nil {
177173
log.Error().Err(err).Msg("error formatting propfind")
178174
w.WriteHeader(http.StatusInternalServerError)
@@ -200,7 +196,8 @@ func (s *svc) propfindResponse(ctx context.Context, w http.ResponseWriter, r *ht
200196
}
201197
}
202198

203-
func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *http.Request, pf propfindXML, ref *provider.Reference, spacesPropfind bool, log zerolog.Logger) (*provider.ResourceInfo, []*provider.ResourceInfo, bool) {
199+
// returns parent, children, hrefBase, OK
200+
func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *http.Request, pf propfindXML, ref *provider.Reference, log zerolog.Logger) (*provider.ResourceInfo, []*provider.ResourceInfo, string, bool) {
204201
depth := r.Header.Get(HeaderDepth)
205202
if depth == "" {
206203
depth = "1"
@@ -215,14 +212,14 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht
215212
message: m,
216213
}, "")
217214
HandleWebdavError(&log, w, b, err)
218-
return nil, nil, false
215+
return nil, nil, "", false
219216
}
220217

221218
client, err := s.getClient()
222219
if err != nil {
223220
log.Error().Err(err).Msg("error getting grpc client")
224221
w.WriteHeader(http.StatusInternalServerError)
225-
return nil, nil, false
222+
return nil, nil, "", false
226223
}
227224

228225
var metadataKeys []string
@@ -250,7 +247,7 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht
250247
if err != nil {
251248
log.Error().Err(err).Interface("req", req).Msg("error sending a stat request to the gateway")
252249
w.WriteHeader(http.StatusInternalServerError)
253-
return nil, nil, false
250+
return nil, nil, "", false
254251
} else if res.Status.Code != rpc.Code_CODE_OK {
255252
if res.Status.Code == rpc.Code_CODE_NOT_FOUND {
256253
w.WriteHeader(http.StatusNotFound)
@@ -260,25 +257,26 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht
260257
message: m,
261258
}, "")
262259
HandleWebdavError(&log, w, b, err)
263-
return nil, nil, false
260+
return nil, nil, "", false
264261
}
265262
HandleErrorStatus(&log, w, res.Status)
266-
return nil, nil, false
267-
}
268-
269-
if spacesPropfind {
270-
res.Info.Path = ref.Path
263+
return nil, nil, "", false
271264
}
272265

273266
parentInfo := res.Info
274267
resourceInfos := []*provider.ResourceInfo{parentInfo}
275268

269+
hrefBase := r.URL.Path
270+
if ctxPath := ctx.Value(ctxKeyIncomingURL); ctxPath != nil {
271+
hrefBase = ctxPath.(string)
272+
}
273+
276274
switch {
277275
case depth == "0":
278276
// https://www.ietf.org/rfc/rfc2518.txt:
279277
// the method is to be applied only to the resource
280-
return parentInfo, resourceInfos, true
281-
case !spacesPropfind && parentInfo.Type != provider.ResourceType_RESOURCE_TYPE_CONTAINER:
278+
return parentInfo, resourceInfos, hrefBase, true
279+
case parentInfo.Type != provider.ResourceType_RESOURCE_TYPE_CONTAINER:
282280
// The propfind is requested for a file that exists
283281
// In this case, we can stat the parent directory and return both
284282
parentPath := path.Dir(parentInfo.Path)
@@ -290,7 +288,7 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht
290288
if err != nil {
291289
log.Error().Err(err).Interface("req", req).Msg("error sending a grpc stat request")
292290
w.WriteHeader(http.StatusInternalServerError)
293-
return nil, nil, false
291+
return nil, nil, "", false
294292
} else if parentRes.Status.Code != rpc.Code_CODE_OK {
295293
if parentRes.Status.Code == rpc.Code_CODE_NOT_FOUND {
296294
w.WriteHeader(http.StatusNotFound)
@@ -300,12 +298,15 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht
300298
message: m,
301299
}, "")
302300
HandleWebdavError(&log, w, b, err)
303-
return nil, nil, false
301+
return nil, nil, "", false
304302
}
305303
HandleErrorStatus(&log, w, parentRes.Status)
306-
return nil, nil, false
304+
return nil, nil, "", false
307305
}
308306
parentInfo = parentRes.Info
307+
// The incoming URL was not to a folder, but to the file itself.
308+
// So the href we constructed up to now is wrong: it needs to be refering to the parent
309+
hrefBase = path.Dir(hrefBase)
309310

310311
case parentInfo.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER && depth == "1":
311312
req := &provider.ListContainerRequest{
@@ -316,12 +317,12 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht
316317
if err != nil {
317318
log.Error().Err(err).Msg("error sending list container grpc request")
318319
w.WriteHeader(http.StatusInternalServerError)
319-
return nil, nil, false
320+
return nil, nil, "", false
320321
}
321322

322323
if res.Status.Code != rpc.Code_CODE_OK {
323324
HandleErrorStatus(&log, w, res.Status)
324-
return nil, nil, false
325+
return nil, nil, "", false
325326
}
326327
resourceInfos = append(resourceInfos, res.Infos...)
327328

@@ -333,38 +334,26 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht
333334
// retrieve path on top of stack
334335
path := stack[len(stack)-1]
335336

336-
var nRef *provider.Reference
337-
if spacesPropfind {
338-
nRef = &provider.Reference{
339-
ResourceId: ref.ResourceId,
340-
Path: path,
341-
}
342-
} else {
343-
nRef = &provider.Reference{Path: path}
344-
}
345337
req := &provider.ListContainerRequest{
346-
Ref: nRef,
338+
Ref: &provider.Reference{Path: path},
347339
ArbitraryMetadataKeys: metadataKeys,
348340
}
349341
res, err := client.ListContainer(ctx, req)
350342
if err != nil {
351343
log.Error().Err(err).Str("path", path).Msg("error sending list container grpc request")
352344
w.WriteHeader(http.StatusInternalServerError)
353-
return nil, nil, false
345+
return nil, nil, "", false
354346
}
355347
if res.Status.Code != rpc.Code_CODE_OK {
356348
HandleErrorStatus(&log, w, res.Status)
357-
return nil, nil, false
349+
return nil, nil, "", false
358350
}
359351

360352
stack = stack[:len(stack)-1]
361353

362354
// check sub-containers in reverse order and add them to the stack
363355
// the reversed order here will produce a more logical sorting of results
364356
for i := len(res.Infos) - 1; i >= 0; i-- {
365-
if spacesPropfind {
366-
res.Infos[i].Path = utils.MakeRelativePath(filepath.Join(nRef.Path, res.Infos[i].Path))
367-
}
368357
if res.Infos[i].Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
369358
stack = append(stack, res.Infos[i].Path)
370359
}
@@ -380,7 +369,7 @@ func (s *svc) getResourceInfos(ctx context.Context, w http.ResponseWriter, r *ht
380369
}
381370
}
382371

383-
return parentInfo, resourceInfos, true
372+
return parentInfo, resourceInfos, hrefBase, true
384373
}
385374

386375
func requiresExplicitFetching(n *xml.Name) bool {

0 commit comments

Comments
 (0)