Commands/Set-OpenPackage.ps1
|
function Set-OpenPackage { <# .SYNOPSIS Sets Open Package content .DESCRIPTION Sets content in an Open Packaging Conventions archive. .EXAMPLE $miniServer = Get-OpenPackage | Set-OpenPackage -Uri '/index.html' -Content ([xml]"<h1>Hello World</h1>") -ContentType text/html | Start-OpenPackage Start-Process -FilePath $miniServer.Name .LINK Get-OpenPackage #> [Alias('Set-OP','sop','sOpenPackage')] param( # The uri to set [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [Alias('Url','Href','PartUri','PartUrl','LocalPath')] [uri] $Uri, # The content to set. [Parameter(ValueFromPipelineByPropertyName)] [Alias('Buffer','Text')] [PSObject] $Content, # The content type. By default, `text/plain` [Parameter(ValueFromPipelineByPropertyName)] [string] $ContentType, # The serialization depth. [Parameter(ValueFromPipelineByPropertyName)] [ValidateRange(1,100)] [int] $Depth = $( if ($FormatEnumerationLimit * 2 -gt 1) { $FormatEnumerationLimit * 2 } else { 4 } ), # The options used to write the content. [Parameter(ValueFromPipelineByPropertyName)] [Alias('Options')] [Collections.IDictionary] $Option = [Ordered]@{}, # The input object. # This must be a package, and it must be writeable. [Parameter(ValueFromPipeline)] [Alias('Package')] [PSObject] $InputObject, # A content type map. # This maps extensions and URIs to a content type. [Collections.IDictionary] $TypeMap = $( ([PSCustomObject]@{PSTypeName='OpenPackage.ContentTypeMap'}).TypeMap ), # Sets a part, even if it already exists. [switch] $Force ) process { # If there is no input, there is nothing to do if (-not $InputObject) { return } # If the input is not a package, pass it thru. if ($InputObject -isnot [IO.Packaging.Package]) { return $InputObject } # If the uri is not prefixed, if ($uri -notmatch '^/') { $uri = "/$uri" # add it to avoid easy errors. } # Create or recreate the part (otherwise writes might be partial) $part = if ($InputObject.PartExists($uri)) { if (-not $Force) { Write-Error "'$uri' already exists, use -Force to overwrite" return } $InputObject.GetPart($uri) } else { if (-not $PSBoundParameters['ContentType']) { $extension = @($uri -split '\.' -ne '')[-1] if ($typeMap.TypeMap.Contains($extension)) { $contentType = $typeMap.TypeMap[$extension] } else { $contentType = 'text/plain' } } $InputObject.CreatePart($uri, $ContentType) } # If we don't have a part, return if (-not $part) { return } # If we have a writer for the part: if ($part.Writer -and $part.Write) { # * Prepare the options if (-not $option) { $Option = [Ordered]@{} } # * Copy in depth if (-not $option.Depth) { $Option.Depth = $Depth } # * Call the writer $part.Write($Content, $option) # * and return. return $InputObject } # Get the stream $partStream = $part.GetStream() $partStream.SetLength(0) # First see if the content is a byte[] if ($content -is [byte[]]) { # if so, just write it $partStream.Write($content, 0, $content.Length) } # If the content is a stream, elseif ($content -is [IO.Stream]) { # copy it in. $content.CopyTo($partStream) } # If the content was xml or could be, elseif ($content -is [xml] -or ($contentXml = $content -as [xml])) { if ($contentXml) { $content = $contentXml } $content.Save($partStream) } elseif ($content -is [string]) { # Put strings in as a byte array. $buffer = $OutputEncoding.GetBytes($content) $partStream.Write($buffer, 0, $buffer.Length) } elseif ($contentBytes = $content -as [byte[]]) { # Bytes are obviously a byte array $partStream.Write($contentBytes, 0, $contentBytes.Length) } else { # and everything else is stringified $buffer = $OutputEncoding.GetBytes("$content") $partStream.Write($buffer, 0, $buffer.Length) } # Close the part stream $partStream.Close() # then pass it thru so we can keep piping. $inputObject } } |