package nextcloud import ( "context" "io" "net/http" "strings" ) func (c *Client) ListFilesAtDAV(ctx context.Context, userID, davPath, logicalPath string) ([]FileInfo, error) { body := propfindBody resp, err := c.DoAsUser(ctx, "PROPFIND", davPath, strings.NewReader(body), userID, map[string]string{ "Depth": "1", "Content-Type": "application/xml", }) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode != 207 { return nil, &HTTPStatusError{Operation: "propfind", StatusCode: resp.StatusCode} } return parsePropfindResponse(resp.Body, logicalPath) } func (c *Client) StatFileAtDAV(ctx context.Context, userID, davPath, logicalPath string) (FileInfo, error) { body := propfindBody resp, err := c.DoAsUser(ctx, "PROPFIND", davPath, strings.NewReader(body), userID, map[string]string{ "Depth": "0", "Content-Type": "application/xml", }) if err != nil { return FileInfo{}, err } defer resp.Body.Close() if resp.StatusCode != 207 { return FileInfo{}, &HTTPStatusError{Operation: "propfind", StatusCode: resp.StatusCode} } files, err := parsePropfindResponse(resp.Body, logicalPath) if err != nil { return FileInfo{}, err } if len(files) == 0 { return FileInfo{}, &HTTPStatusError{Operation: "stat", StatusCode: http.StatusNotFound} } return files[0], nil } func (c *Client) UploadAtDAV(ctx context.Context, userID, davPath, contentType string, content io.Reader) error { if contentType == "" { contentType = "application/octet-stream" } resp, err := c.DoAsUser(ctx, "PUT", davPath, content, userID, map[string]string{ "Content-Type": contentType, }) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusNoContent { return &HTTPStatusError{Operation: "upload", StatusCode: resp.StatusCode} } return nil } func (c *Client) CreateFolderAtDAV(ctx context.Context, userID, davPath string) error { resp, err := c.DoAsUser(ctx, "MKCOL", davPath, nil, userID, nil) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusCreated { return &HTTPStatusError{Operation: "mkcol", StatusCode: resp.StatusCode} } return nil } func (c *Client) DeleteAtDAV(ctx context.Context, userID, davPath string) error { resp, err := c.DoAsUser(ctx, "DELETE", davPath, nil, userID, nil) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusOK { return &HTTPStatusError{Operation: "delete", StatusCode: resp.StatusCode} } return nil } func (c *Client) MoveAtDAV(ctx context.Context, userID, srcDAV, destDAV string) error { resp, err := c.DoAsUser(ctx, "MOVE", srcDAV, nil, userID, map[string]string{ "Destination": c.webDAVDestination(destDAV), "Overwrite": "T", }) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusNoContent { return &HTTPStatusError{Operation: "move", StatusCode: resp.StatusCode} } return nil } func (c *Client) CopyAtDAV(ctx context.Context, userID, srcDAV, destDAV string) error { resp, err := c.DoAsUser(ctx, "COPY", srcDAV, nil, userID, map[string]string{ "Destination": c.webDAVDestination(destDAV), "Overwrite": "T", }) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusNoContent { return &HTTPStatusError{Operation: "copy", StatusCode: resp.StatusCode} } return nil } func (c *Client) DownloadAtDAV(ctx context.Context, userID, davPath string) (io.ReadCloser, string, error) { resp, err := c.DoAsUser(ctx, "GET", davPath, nil, userID, nil) if err != nil { return nil, "", err } if resp.StatusCode != http.StatusOK { resp.Body.Close() return nil, "", &HTTPStatusError{Operation: "download", StatusCode: resp.StatusCode} } contentType := resp.Header.Get("Content-Type") if contentType == "" { contentType = "application/octet-stream" } return resp.Body, contentType, nil } const propfindBody = ` `