Public/Get-VBNextcloudFolders.ps1
|
# ============================================================ # FUNCTION : Get-VBNextcloudFolders # MODULE : VB.NextCloud # VERSION : 1.0.0 # CHANGED : 15-04-2026 -- Initial release # AUTHOR : Vibhu Bhatnagar # PURPOSE : Lists subfolders in a Nextcloud directory via WebDAV PROPFIND # ENCODING : UTF-8 with BOM # ============================================================ function Get-VBNextcloudFolders { <# .SYNOPSIS Lists subfolders in a Nextcloud directory via WebDAV PROPFIND. .DESCRIPTION Get-VBNextcloudFolders queries a Nextcloud server using the WebDAV PROPFIND method to retrieve metadata for all subfolders in a specified folder. Only folders are returned -- files are excluded. The folder itself is excluded from results so only direct children are returned. TLS 1.2 is enforced. .PARAMETER BaseUrl Base URL of the Nextcloud instance, e.g. 'https://cloud.example.com'. .PARAMETER Credential PSCredential object containing the Nextcloud username and password. .PARAMETER FolderPath Remote folder path to list, e.g. 'Vibhu/Reports'. Defaults to the WebDAV root. .PARAMETER WebDAVPath WebDAV endpoint path appended to BaseUrl. Defaults to 'remote.php/webdav'. .EXAMPLE Get-VBNextcloudFolders -BaseUrl 'https://cloud.example.com' -Credential (Get-Credential) Lists all subfolders in the WebDAV root. .EXAMPLE Get-VBNextcloudFolders -BaseUrl 'https://cloud.example.com' ` -Credential $cred -FolderPath 'Vibhu' Lists all subfolders inside the Vibhu folder. .EXAMPLE Get-VBNextcloudFolders -BaseUrl 'https://cloud.example.com' -Credential $cred | Select-Object Name, Path, LastModified Lists root subfolders showing name, path and last modified date. .OUTPUTS PSCustomObject Returns an object per folder with: - Name : Display name of the folder - Path : Full WebDAV href path - LastModified : Last modified date string from the server - Status : 'Success' or 'Failed' - Error : Error message (only present on failure) .NOTES Version : 1.0.0 Module : VB.NextCloud Author : Vibhu Bhatnagar Requirements: - PowerShell 5.1 or higher - Network access to the Nextcloud instance - Valid Nextcloud credentials with read access to the target folder #> [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$BaseUrl, [Parameter(Mandatory)] [PSCredential]$Credential, [string]$FolderPath = '', [ValidateNotNullOrEmpty()] [string]$WebDAVPath = 'remote.php/webdav' ) process { try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $webDavUrl = '{0}/{1}' -f $BaseUrl.TrimEnd('/'), $WebDAVPath.Trim('/') $targetPath = $FolderPath.Trim('/').Replace('\', '/') $listUrl = if ($targetPath) { '{0}/{1}' -f $webDavUrl, $targetPath } else { $webDavUrl } Write-Verbose "Listing Nextcloud folders: $listUrl" $propfindBody = @' <?xml version="1.0"?> <d:propfind xmlns:d="DAV:"> <d:prop> <d:displayname/> <d:getlastmodified/> <d:resourcetype/> </d:prop> </d:propfind> '@ # Invoke-WebRequest does not support PROPFIND on PS 5.1 -- use HttpWebRequest directly $httpRequest = [System.Net.HttpWebRequest]::Create($listUrl) $httpRequest.Method = 'PROPFIND' $httpRequest.ContentType = 'application/xml' $httpRequest.Headers.Add('Depth', '1') $httpRequest.Credentials = $Credential.GetNetworkCredential() $bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($propfindBody) $httpRequest.ContentLength = $bodyBytes.Length $requestStream = $httpRequest.GetRequestStream() $requestStream.Write($bodyBytes, 0, $bodyBytes.Length) $requestStream.Close() $webResponse = $httpRequest.GetResponse() $responseStream = $webResponse.GetResponseStream() $reader = [System.IO.StreamReader]::new($responseStream) $responseBody = $reader.ReadToEnd() $reader.Close() $webResponse.Close() $xml = [xml]$responseBody $collectionTime = (Get-Date).ToString('dd-MM-yyyy HH:mm:ss') foreach ($item in $xml.multistatus.response) { # Skip the requested folder itself $itemHref = $item.href.TrimEnd('/') $selfHref = if ($targetPath) { ('/{0}/{1}' -f $WebDAVPath.Trim('/'), $targetPath).TrimEnd('/') } else { ('/{0}' -f $WebDAVPath.Trim('/')).TrimEnd('/') } if ($itemHref -eq $selfHref) { continue } # Only return folders $isFolder = $null -ne $item.propstat.prop.resourcetype.collection if (-not $isFolder) { continue } Write-Debug "Found folder: $($item.propstat.prop.displayname)" [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME Name = $item.propstat.prop.displayname Path = $item.href LastModified = $item.propstat.prop.getlastmodified CollectionTime = $collectionTime Status = 'Success' } } } catch { Write-Error -Message $_.Exception.Message -ErrorAction Continue [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME Name = $null Path = $FolderPath LastModified = $null Error = $_.Exception.Message Status = 'Failed' CollectionTime = (Get-Date).ToString('dd-MM-yyyy HH:mm:ss') } } } } |