[to #1] support Nextcloud IOS
This commit is contained in:
258
webdav/prop.go
258
webdav/prop.go
@@ -107,18 +107,23 @@ var liveProps = map[xml.Name]struct {
|
||||
findFn func(context.Context, FileSystem, string, os.FileInfo) (string, error)
|
||||
// dir is true if the property applies to directories.
|
||||
dir bool
|
||||
// file is true if the property applies to files.
|
||||
file bool
|
||||
}{
|
||||
{Space: "DAV:", Local: "resourcetype"}: {
|
||||
findFn: findResourceType,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "DAV:", Local: "displayname"}: {
|
||||
findFn: findDisplayName,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "DAV:", Local: "getcontentlength"}: {
|
||||
findFn: findContentLength,
|
||||
dir: false,
|
||||
file: true,
|
||||
},
|
||||
{Space: "DAV:", Local: "getlastmodified"}: {
|
||||
findFn: findLastModified,
|
||||
@@ -130,26 +135,143 @@ var liveProps = map[xml.Name]struct {
|
||||
// sortable by getlastmodified date, so this value is true, not false.
|
||||
// See golang.org/issue/15334.
|
||||
dir: true,
|
||||
file:true,
|
||||
},
|
||||
{Space: "DAV:", Local: "creationdate"}: {
|
||||
findFn: nil,
|
||||
dir: false,
|
||||
file: true,
|
||||
},
|
||||
{Space: "DAV:", Local: "getcontentlanguage"}: {
|
||||
findFn: nil,
|
||||
dir: false,
|
||||
file: true,
|
||||
},
|
||||
{Space: "DAV:", Local: "getcontenttype"}: {
|
||||
findFn: findContentType,
|
||||
dir: false,
|
||||
file: true,
|
||||
},
|
||||
{Space: "DAV:", Local: "getetag"}: {
|
||||
findFn: findETag,
|
||||
// findETag implements ETag as the concatenated hex values of a file's
|
||||
// modification time and size. This is not a reliable synchronization
|
||||
// mechanism for directories, so we do not advertise getetag for DAV
|
||||
// collections.
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "DAV:", Local: "quota-available-bytes"}: {
|
||||
findFn: fnGetQuotaAvailableBytes,
|
||||
dir: true,
|
||||
file: false,
|
||||
},
|
||||
{Space: "DAV:", Local: "quota-used-bytes"}: {
|
||||
findFn: fnGetQuotaUsedBytes,
|
||||
dir: true,
|
||||
file: false,
|
||||
},
|
||||
|
||||
{Space: "http://owncloud.org/ns", Local: "permissions"}: {
|
||||
findFn: fnGetPermissions,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://owncloud.org/ns", Local: "id"}: {
|
||||
findFn: fnGetID,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://owncloud.org/ns", Local: "fileid"}: {
|
||||
findFn: fnGetFileID,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://owncloud.org/ns", Local: "size"}: {
|
||||
findFn: fnGetSize,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://owncloud.org/ns", Local: "favorite"}: {
|
||||
findFn: fnGetFavorite,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://owncloud.org/ns", Local: "share-types"}: {
|
||||
findFn: fnGetShareTypes,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://owncloud.org/ns", Local: "owner-id"}: {
|
||||
findFn: fnGetOwnerID,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://owncloud.org/ns", Local: "owner-display-name"}: {
|
||||
findFn: fnGetOwnerDisplayName,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://owncloud.org/ns", Local: "comments-unread"}: {
|
||||
findFn: fnGetCommentsUnread,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://owncloud.org/ns", Local: "checksums"}: {
|
||||
findFn: fnGetChecksums,
|
||||
dir: false,
|
||||
file: false,
|
||||
},
|
||||
{Space: "http://owncloud.org/ns", Local: "downloadURL"}: {
|
||||
findFn: fnGetDownloadURL,
|
||||
dir: false,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://owncloud.org/ns", Local: "data-fingerprint"}: {
|
||||
findFn: fnGetDataFingerprint,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://nextcloud.org/ns", Local: "creation_time"}: {
|
||||
findFn: fnGetCreationTime,
|
||||
dir: false,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://nextcloud.org/ns", Local: "upload_time"}: {
|
||||
findFn: fnGetUploadTime,
|
||||
dir: false,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://nextcloud.org/ns", Local: "is-encrypted"}: {
|
||||
findFn: fnGetIsEncrypted,
|
||||
dir: true,
|
||||
file: false,
|
||||
},
|
||||
{Space: "http://nextcloud.org/ns", Local: "has-preview"}: {
|
||||
findFn: fnGetHasPreview,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://nextcloud.org/ns", Local: "mount-type"}: {
|
||||
findFn: fnGetMountType,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://nextcloud.org/ns", Local: "rich-workspace"}: {
|
||||
findFn: fnGetRichWorkspace,
|
||||
dir: false,
|
||||
file: false,
|
||||
},
|
||||
{Space: "http://nextcloud.org/ns", Local: "note"}: {
|
||||
findFn: fnGetNote,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://open-collaboration-services.org/ns", Local: "share-permissions"}: {
|
||||
findFn: fnGetSharePermissionsOCS,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
{Space: "http://open-cloud-mesh.org/ns", Local: "share-permissions"}: {
|
||||
findFn: fnGetSharePermissionsOCM,
|
||||
dir: true,
|
||||
file: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -188,7 +310,8 @@ func props(ctx context.Context, fs FileSystem, name string, pnames []xml.Name) (
|
||||
continue
|
||||
}
|
||||
// Otherwise, it must either be a live property or we don't know it.
|
||||
if prop := liveProps[pn]; prop.findFn != nil && (prop.dir || !isDir) {
|
||||
//fmt.Println(liveProps[pn], liveProps[pn].findFn, name, pn)
|
||||
if prop := liveProps[pn]; prop.findFn != nil && ((prop.dir && isDir) || (prop.file && !isDir)){
|
||||
innerXML, err := prop.findFn(ctx, fs, name, fi)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -287,7 +410,7 @@ func escapeXML(s string) string {
|
||||
|
||||
func findResourceType(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
if fi.IsDir() {
|
||||
return `<D:collection xmlns:D="DAV:"/>`, nil
|
||||
return `<d:collection/>`, nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
@@ -358,33 +481,104 @@ func findContentType(ctx context.Context, fs FileSystem, name string, fi os.File
|
||||
return ctype, err
|
||||
}
|
||||
|
||||
// ETager is an optional interface for the os.FileInfo objects
|
||||
// returned by the FileSystem.
|
||||
//
|
||||
// If this interface is defined then it will be used to read the ETag
|
||||
// for the object.
|
||||
//
|
||||
// If this interface is not defined an ETag will be computed using the
|
||||
// ModTime() and the Size() methods of the os.FileInfo object.
|
||||
type ETager interface {
|
||||
// ETag returns an ETag for the file. This should be of the
|
||||
// form "value" or W/"value"
|
||||
//
|
||||
// If this returns error ErrNotImplemented then the error will
|
||||
// be ignored and the base implementation will be used
|
||||
// instead.
|
||||
ETag(ctx context.Context) (string, error)
|
||||
func findETag(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return fmt.Sprintf(`"%x%x"`, fi.ModTime().UnixNano(), fi.Size()), nil
|
||||
}
|
||||
|
||||
func findETag(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
if do, ok := fi.(ETager); ok {
|
||||
etag, err := do.ETag(ctx)
|
||||
if err != ErrNotImplemented {
|
||||
return etag, err
|
||||
}
|
||||
func fnGetQuotaAvailableBytes(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "1057129933", nil
|
||||
}
|
||||
|
||||
func fnGetQuotaUsedBytes(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "16611891", nil
|
||||
}
|
||||
|
||||
func fnGetPermissions(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
if fi.IsDir() {
|
||||
return "RGDNVCK", nil
|
||||
}
|
||||
// The Apache http 2.4 web server by default concatenates the
|
||||
// modification time and size of a file. We replicate the heuristic
|
||||
// with nanosecond granularity.
|
||||
return fmt.Sprintf(`"%x%x"`, fi.ModTime().UnixNano(), fi.Size()), nil
|
||||
return "RGDNVW", nil
|
||||
}
|
||||
|
||||
func fnGetID(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return name, nil
|
||||
}
|
||||
|
||||
func fnGetFileID(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "0", nil
|
||||
}
|
||||
|
||||
func fnGetSize(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "16611891", nil
|
||||
}
|
||||
|
||||
func fnGetFavorite(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "0", nil
|
||||
}
|
||||
|
||||
func fnGetShareTypes(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func fnGetOwnerID(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "vscode", nil
|
||||
}
|
||||
|
||||
func fnGetOwnerDisplayName(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "vscode", nil
|
||||
}
|
||||
|
||||
func fnGetCommentsUnread(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "0", nil
|
||||
}
|
||||
|
||||
func fnGetChecksums(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func fnGetDownloadURL(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func fnGetDataFingerprint(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func fnGetCreationTime(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "0", nil
|
||||
}
|
||||
|
||||
func fnGetUploadTime(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "0", nil
|
||||
}
|
||||
|
||||
func fnGetIsEncrypted(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "0", nil
|
||||
}
|
||||
|
||||
func fnGetHasPreview(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "false", nil
|
||||
}
|
||||
|
||||
func fnGetMountType(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func fnGetRichWorkspace(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func fnGetNote(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func fnGetSharePermissionsOCS(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
if fi.IsDir() {
|
||||
return "31", nil
|
||||
}
|
||||
return "19", nil
|
||||
}
|
||||
|
||||
func fnGetSharePermissionsOCM(ctx context.Context, fs FileSystem, name string, fi os.FileInfo) (string, error) {
|
||||
return "[\"share\",\"read\",\"write\"]", nil
|
||||
}
|
||||
Reference in New Issue
Block a user