Public/Connect-DokuServer.ps1

function Connect-DokuServer {
    <#
    .SYNOPSIS
        Connect to a DokuWiki API endpoint
 
    .DESCRIPTION
        Connect to a DokuWiki API endpoint to enable subsequent DokuWiki commands from the same PowerShell session
 
    .PARAMETER ComputerName
        The computer name (single label or FQDN) / IP to connect to
 
    .PARAMETER Credential
        The credentials used to authenticate to the API endpoint
 
    .PARAMETER SessionMethod
        The session method to use for the connection. Options are Cookie or HttpBasic
 
    .PARAMETER Unencrypted
        Specify that the APi endpoint is at a http rather than https address. Recommended for development only!!
 
    .PARAMETER ApiPath
        The web path that the api executable is at. DokuWiki default is /lib/exe/xmlrpc.php
 
    .PARAMETER Force
        Force a connection even if one is already established to the same endpoint
 
    .EXAMPLE
        PS C:\> Connect-DokuServer -ComputerName wiki.example.com -Credential (Get-Credential)
 
    .OUTPUTS
        Nothing
 
    .NOTES
        AndyDLP - 2019
 
    .LINK
        https://github.com/AndyDLP/PSDokuWiki
#>


    [CmdletBinding(PositionalBinding = $true)]
    param
    (
        [Parameter(Mandatory = $true,
            Position = 1,
            HelpMessage = 'The server to connect to')]
        [ValidateNotNullOrEmpty()]
        [Alias('Server')]
        [string]$ComputerName,

        [Parameter(Mandatory = $true,
            Position = 2,
            HelpMessage = 'The credentials to use to connect')]
        [ValidateNotNullOrEmpty()]
        [pscredential]$Credential,
        
        [Parameter(Mandatory = $false,
            Position = 3,
            HelpMessage = 'The session method to use')]
        [ValidateNotNullOrEmpty()]
        [ValidateSet('Cookie','HttpBasic',IgnoreCase = $true)]
        [string]$SessionMethod = 'Cookie',
        
        [Parameter(Mandatory = $false,
            Position = 4,
            HelpMessage = 'Connect to an unencrypted endpoint')]
        [ValidateNotNullOrEmpty()]
        [switch]$Unencrypted,
        
        [Parameter(Mandatory = $false,
            Position = 5,
            HelpMessage = 'The path to the api endpoint')]
        [ValidateNotNullOrEmpty()]
        [string]$APIPath = '/lib/exe/xmlrpc.php',
        
        [Parameter(Mandatory = $false,
            Position = 6,
            HelpMessage = 'Force a re-connection')]
        [ValidateNotNullOrEmpty()]
        [switch]$Force
    )

    begin {
        # intentionally empty
    }

    process {
        $headers = @{ "Content-Type" = "text/xml"; }
        $Protocol = if ($Unencrypted) { "http" } else { "https" }

        $TargetUri = ($Protocol + "://" + $ComputerName + $APIPath)

        # Check if already connected
        if (($null -ne $Script:DokuServer) -and (-not $Force)) {
            throw "Open connection already exists to: $($Script:DokuServer.TargetUri) - Use the -Force parameter to connect anyway"
        }

        $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credential.Password)
        $password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

        if ($SessionMethod -eq "HttpBasic") {
            $pair = "$($Credential.username):$($password)"
            $encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
            $headers.Add("Authorization", "Basic $encodedCreds")
        } else {
            $XMLPayload = ConvertTo-XmlRpcMethodCall -Name "dokuwiki.login" -Params @($Credential.username, $password)
            # $Websession var defined here
            try {
                $httpResponse = Invoke-WebRequest -Uri $TargetUri -Method Post -Headers $headers -Body $XMLPayload -SessionVariable WebSession -ErrorAction Stop
                $XMLContent = [xml]($httpResponse.Content)
            }
            catch [System.Management.Automation.PSInvalidCastException] {
                Write-Verbose "Connected to API endpoint: $($Script:DokuServer.TargetUri) but did not receive valid response"
                $PSCmdlet.ThrowTerminatingError(
                    [System.Management.Automation.ErrorRecord]::new(
                        ("XML payload sent to: $TargetUri but received an invalid response"),
                        'DokuWiki.Session.InvalidResponse',
                        [System.Management.Automation.ErrorCategory]::InvalidResult,
                        $TargetUri
                    )
                )
            }
            catch [System.Net.WebException] {
                $PSCmdlet.ThrowTerminatingError(
                    [System.Management.Automation.ErrorRecord]::new(
                        ("Failed to send POST request to $TargetUri"),
                        'DokuWiki.Session.InvalidRequest',
                        [System.Management.Automation.ErrorCategory]::InvalidOperation,
                        $TargetUri
                    )
                )
            }
            catch {
                Write-Verbose "Unspecified error caught"
                throw $_
                exit
            }
        }

        if ($null -ne ($XMLContent | Select-Xml -XPath "//fault").node) {
            # connected but API failed
            Write-Error "Connected to API endpoint: $ComputerName, but failed login. FaultCode: $(($XMLContent | Select-Xml -XPath '//struct').node.member[0].value.int) - FaultString: $(($XMLContent | Select-Xml -XPath '//struct').node.member[1].value.string)"
            $PSCmdlet.ThrowTerminatingError(
                [System.Management.Automation.ErrorRecord]::new(
                    ("FaultCode: $(($XMLContent | Select-Xml -XPath '//struct').node.member[0].value.int) - FaultString: $(($XMLContent | Select-Xml -XPath '//struct').node.member[1].value.string)"),
                    'DokuWiki.Session.FailedLogin',
                    [System.Management.Automation.ErrorCategory]::AuthenticationError,
                    $TargetUri
                )
            )
        } elseif ($null -eq ($XMLContent | Select-Xml -XPath "//methodResponse").node) {
            # not connected / invalid response
            Write-Verbose "Connected to API endpoint: $($Script:DokuServer.TargetUri) but did not receive valid response"
            $PSCmdlet.ThrowTerminatingError(
                [System.Management.Automation.ErrorRecord]::new(
                    ("XML payload sent to: $TargetUri but received an invalid response"),
                    'DokuWiki.Session.InvalidResponse',
                    [System.Management.Automation.ErrorCategory]::InvalidResult,
                    $TargetUri
                )
            )
        } else {
            # success
            Write-Verbose "Successfully connected to API server: $ComputerName"
            $DokuSession = New-Object PSObject -Property @{
                Server = $ComputerName
                TargetUri = $TargetUri
                SessionMethod = $SessionMethod
                Headers = $headers
                WebSession = $WebSession
                TimeStamp = (Get-Date)
                UnencryptedEndpoint = [boolean]$Unencrypted
            }
            $DokuSession.PSTypeNames.Insert(0,'DokuWiki.Session.Detail')
            
            # Module scoped variables are defined like the below apparently
            $Script:DokuServer = $DokuSession
        }
    } # process

    end {
        # intentionally empty
    }
}