1010from httpx import Response
1111
1212from .._exceptions import NextcloudException , check_error
13- from .._misc import clear_from_params_empty
13+ from .._misc import check_capabilities , clear_from_params_empty
1414from . import FsNode , SystemTag
1515
1616PROPFIND_PROPERTIES = [
2929 "oc:share-types" ,
3030 "oc:favorite" ,
3131 "nc:is-encrypted" ,
32+ ]
33+
34+ PROPFIND_LOCKING_PROPERTIES = [
3235 "nc:lock" ,
3336 "nc:lock-owner-displayname" ,
3437 "nc:lock-owner" ,
3538 "nc:lock-owner-type" ,
36- "nc:lock-owner-editor" ,
37- "nc:lock-time" ,
38- "nc:lock-timeout" ,
39+ "nc:lock-owner-editor" , # App id of an app owned lock
40+ "nc:lock-time" , # Timestamp of the log creation time
41+ "nc:lock-timeout" , # TTL of the lock in seconds staring from the creation time
3942]
4043
4144SEARCH_PROPERTIES_MAP = {
@@ -57,15 +60,22 @@ class PropFindType(enum.IntEnum):
5760 VERSIONS_FILE_ID = 3
5861
5962
60- def build_find_request (req : list , path : str | FsNode , user : str ) -> ElementTree .Element :
63+ def get_propfind_properties (capabilities : dict ) -> list :
64+ r = PROPFIND_PROPERTIES
65+ if not check_capabilities ("files.locking" , capabilities ):
66+ r += PROPFIND_LOCKING_PROPERTIES
67+ return r
68+
69+
70+ def build_find_request (req : list , path : str | FsNode , user : str , capabilities : dict ) -> ElementTree .Element :
6171 path = path .user_path if isinstance (path , FsNode ) else path
6272 root = ElementTree .Element (
6373 "d:searchrequest" ,
6474 attrib = {"xmlns:d" : "DAV:" , "xmlns:oc" : "http://owncloud.org/ns" , "xmlns:nc" : "http://nextcloud.org/ns" },
6575 )
6676 xml_search = ElementTree .SubElement (root , "d:basicsearch" )
6777 xml_select_prop = ElementTree .SubElement (ElementTree .SubElement (xml_search , "d:select" ), "d:prop" )
68- for i in PROPFIND_PROPERTIES :
78+ for i in get_propfind_properties ( capabilities ) :
6979 ElementTree .SubElement (xml_select_prop , i )
7080 xml_from_scope = ElementTree .SubElement (ElementTree .SubElement (xml_search , "d:from" ), "d:scope" )
7181 href = f"/files/{ user } /{ path .removeprefix ('/' )} "
@@ -76,15 +86,17 @@ def build_find_request(req: list, path: str | FsNode, user: str) -> ElementTree.
7686 return root
7787
7888
79- def build_list_by_criteria_req (properties : list [str ] | None , tags : list [int | SystemTag ] | None ) -> ElementTree .Element :
89+ def build_list_by_criteria_req (
90+ properties : list [str ] | None , tags : list [int | SystemTag ] | None , capabilities : dict
91+ ) -> ElementTree .Element :
8092 if not properties and not tags :
8193 raise ValueError ("Either specify 'properties' or 'tags' to filter results." )
8294 root = ElementTree .Element (
8395 "oc:filter-files" ,
8496 attrib = {"xmlns:d" : "DAV:" , "xmlns:oc" : "http://owncloud.org/ns" , "xmlns:nc" : "http://nextcloud.org/ns" },
8597 )
8698 prop = ElementTree .SubElement (root , "d:prop" )
87- for i in PROPFIND_PROPERTIES :
99+ for i in get_propfind_properties ( capabilities ) :
88100 ElementTree .SubElement (prop , i )
89101 xml_filter_rules = ElementTree .SubElement (root , "oc:filter-rules" )
90102 if properties and "favorite" in properties :
@@ -243,7 +255,7 @@ def etag_fileid_from_response(response: Response) -> dict:
243255 return {"etag" : response .headers .get ("OC-Etag" , "" ), "file_id" : response .headers ["OC-FileId" ]}
244256
245257
246- def _parse_record (full_path : str , prop_stats : list [dict ]) -> FsNode :
258+ def _parse_record (full_path : str , prop_stats : list [dict ]) -> FsNode : # noqa pylint: disable = too-many-branches
247259 fs_node_args = {}
248260 for prop_stat in prop_stats :
249261 if str (prop_stat .get ("d:status" , "" )).find ("200 OK" ) == - 1 :
@@ -274,7 +286,17 @@ def _parse_record(full_path: str, prop_stats: list[dict]) -> FsNode:
274286 fs_node_args ["trashbin_original_location" ] = prop ["nc:trashbin-original-location" ]
275287 if "nc:trashbin-deletion-time" in prop_keys :
276288 fs_node_args ["trashbin_deletion_time" ] = prop ["nc:trashbin-deletion-time" ]
277- # xz = prop.get("oc:dDC", "")
289+ for k , v in {
290+ "nc:lock" : "is_locked" ,
291+ "nc:lock-owner-type" : "lock_owner_type" ,
292+ "nc:lock-owner" : "lock_owner" ,
293+ "nc:lock-owner-displayname" : "lock_owner_displayname" ,
294+ "nc:lock-owner-editor" : "lock_owner_editor" ,
295+ "nc:lock-time" : "lock_time" ,
296+ "nc:lock-timeout" : "lock_ttl" ,
297+ }.items ():
298+ if k in prop_keys and prop [k ] is not None :
299+ fs_node_args [v ] = prop [k ]
278300 return FsNode (full_path , ** fs_node_args )
279301
280302
0 commit comments