PoshCode Logo PowerShell Code Repository

HttpRest 1.4 by Joel Bennett 18 months ago (modification of post by Joel Bennett view diff)
View followups from Joel Bennett | diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/2028"></script>download | new post

A few miscellaneous enhancements to HttpRest for pipelining urls, and the beginning of documentation …

VERY OLD documentation on this post on HuddledMasses and I’m finally starting to update this to be an example of best practices … I guess ;)

  1. #requires -version 2.0
  2. ## HttpRest module version 1.4
  3. ####################################################################################################
  4. ## Still only the initial stages of converting to a full v2 module
  5. ## Based on the REST api from MindTouch's Dream SDK
  6. ##
  7. ## INSTALL:
  8. ## You need mindtouch.dream.dll (mindtouch.core.dll, SgmlReaderDll.dll, log4net.dll) from the SDK
  9. ## Get MindTouch_Dream_1.6.0.zip or greater from http`://sourceforge.net/projects/dekiwiki/files/
  10. ##
  11. ## Unpack it, and you can find these dlls in the "dist" folder.
  12. ## Make sure to put them in the folder with this script module.
  13. ##
  14. ## For documentation of Dream:  http`://wiki.developer.mindtouch.com/Dream
  15. ####################################################################################################
  16. ## Version History
  17. ## 1.0   2008-11-30  First Release
  18. ## 1.0.1 2009-01-05  Added Get-WebPageContent
  19. ## 1.0.2 2009-05-14  Bug fix for Invoke-Http credential issues
  20. ## 1.1.0 2009-05-14  First release of a PowerShell 2.0 (CTP3/Windows7) version....
  21. ## 1.1.1 2009-05-15  Added Get-WebPageText and Get-Webfile ... cleaned up options
  22. ## 1.2   2009-08-09  Added Hashtable parsing on Get-DreamMessage
  23. ##                   Fixed parsing on Get-DreamPlug so we don't get errors on PowerShell 2
  24. ##                   Added ParameterSet on Invoke-Http to pass in a plug directly (easier to debug)
  25. ## 1.3   2010-07-27  Added a few more aliases to make life easier
  26. ## 1.4   2010-07-28  Changed Get-WebPageContent and Get-WebPageText to support pipline input
  27. ##                   Started adding help ...
  28. ####################################################################################################
  29. ## Usage:
  30. ##   function Get-Google {
  31. ##     Invoke-Http GET http`://www.google.com/search @{q=$args} |
  32. ##       Receive-Http Xml "//h3[@class='r']/a" | Select href, InnerText
  33. ##   }
  34. ##   #########################################################################
  35. ##   function Get-WebFile($url,$cred) {
  36. ##     Invoke-Http GET $url -auth $cred | Receive-Http File
  37. ##   }
  38. ##   #########################################################################
  39. ##   function Send-Paste {
  40. ##   PARAM($PastebinURI="http`://posh.jaykul.com/p/",[IO.FileInfo]$file)
  41. ##   PROCESS {
  42. ##     if($_){[IO.FileInfo]$file=$_}
  43. ##
  44. ##     if($file.Exists) {
  45. ##       $ofs="`n"
  46. ##       $result = Invoke-Http POST $PastebinURI @{
  47. ##         format="posh"           # PowerShell
  48. ##         expiry="d"              # (d)ay or (m)onth or (f)orever
  49. ##         poster=$([Security.Principal.WindowsIdentity]::GetCurrent().Name.Split("\")[-1])
  50. ##         code2="$((gc $file) -replace "http`://","http``://")" # To get past the spam filter.
  51. ##         paste="Send"
  52. ##       } -Type FORM_URLENCODED -Wait
  53. ##       $xml = $result.AsDocument().ToXml()
  54. ##       write-output $xml.SelectSingleNode("//*[@class='highlight']/*").href
  55. ##     } else { throw "File Not Found" }
  56. ##   }}
  57. ##
  58. ####################################################################################################
  59. if(!$PSScriptRoot){
  60.    throw "HttpRest is a module, and must be invoked by Import-Module"
  61. }
  62. Write-Debug "PSScriptRoot: '$PSScriptRoot'"
  63. # This Module depends on MindTouch.Dream
  64. $null = Add-Type -Path "$PSScriptRoot\mindtouch.dream.dll" -ErrorAction Stop
  65. # MindTouch.Dream requires: mindtouch.dream.dll, mindtouch.core.dll, SgmlReaderDll.dll, and log4net.dll)
  66. # This Module also depends on utility functions from System.Web
  67. $null = Add-Type -Assembly System.Web -ErrorAction Stop
  68.  
  69. ## Some utility functions are defined at the bottom
  70. [uri]$global:url = ""
  71. [System.Management.Automation.PSCredential]$global:HttpRestCredential = $null
  72.  
  73. Function Get-DreamMessage {
  74. PARAM($Content,$Type)
  75.    #Write-Verbose "Content: $(if($Content){$Content.GetType()}else{"null"}) $($Content.Length) and Type: $(if($Type){$Type.GetType()}else{"null"})"
  76.    if(!$Content) {
  77.       Write-Verbose "No Content"
  78.       return [MindTouch.Dream.DreamMessage]::Ok()
  79.    }
  80.    if( $Content -is [System.Xml.XmlDocument]) {
  81.       Write-Verbose "Xml Content"
  82.       return [MindTouch.Dream.DreamMessage]::Ok( $Content )
  83.    }
  84.    if($Content -is [Hashtable]) {
  85.       $kvp = $Content.GetEnumerator() | %{ new-object "System.Collections.Generic.KeyValuePair[[String],[String]]" $_.Key, $_.Value }
  86.       Write-Verbose "Hashtable content: $($kvp | ft -auto | out-string -stream | %{ "   $_ ".TrimEnd()} )"
  87.       return [MindTouch.Dream.DreamMessage]::Ok( $kvp )
  88.    }
  89.    
  90.    if(Test-Path $Content -EA "SilentlyContinue") {
  91.       Write-Verbose "File Content"
  92.       return [MindTouch.Dream.DreamMessage]::FromFile((Convert-Path (Resolve-Path $Content)));
  93.    }
  94.    if($Type -is [String]) {
  95.       Write-Verbose "Specific Content: $([MindTouch.Dream.MimeType]::$Type)"
  96.       $Type = [MindTouch.Dream.MimeType]::$Type
  97.    }
  98.    if($Type -is [MindTouch.Dream.DreamMessage]) {
  99.       Write-Verbose "Specific Content: $([MindTouch.Dream.MimeType]::$Type)"
  100.       return [MindTouch.Dream.DreamMessage]::Ok( $Type, $Content )
  101.    } else {  
  102.       Write-Verbose "Unspecified string content"
  103.       return [MindTouch.Dream.DreamMessage]::Ok( $([MindTouch.Dream.MimeType]::TEXT), $Content )
  104.    }
  105. }
  106.  
  107. Function Get-DreamPlug {
  108.    [CmdletBinding()]
  109.    PARAM ( $Url, [hashtable]$With, [hashtable]$Headers )
  110.    if($Url -is [array]) {
  111.       Write-Verbose "URL is an array of parts"
  112.       if($Url[0] -is [hashtable]) {
  113.          Write-Verbose "URL is an array of hashtable parts"
  114.          $plug = [MindTouch.Dream.Plug]::New($global:url)
  115.          foreach($param in $url.GetEnumerator()) {
  116.             if($param.Value) {
  117.                $plug = $plug.At($param.Key,"=$(Encode-Twice $param.Value)")
  118.             } else {
  119.                $plug = $plug.At($param.Key)
  120.             }
  121.          }
  122.       }
  123.       else
  124.       {
  125.          [URI]$uri = Join-Url $global:url $url
  126.          $plug = [MindTouch.Dream.Plug]::New($uri)
  127.       }
  128.    }
  129.    elseif($url -is [string])
  130.    {
  131.       Write-Verbose "String URL"
  132.       trap { continue }
  133.       [URI]$uri = $url
  134.       if(!$uri.IsAbsoluteUri) {
  135.          $uri = Join-Url $global:url $url
  136.          Write-Verbose "Relative URL, appending to $($global:url) to get: $uri"
  137.       }
  138.       $plug = [MindTouch.Dream.Plug]::New($uri)
  139.    }
  140.    else {
  141.       Write-Verbose "No URL, using default $($global:url)"
  142.       $plug = [MindTouch.Dream.Plug]::New($global:url)
  143.    }
  144.    if($with) {
  145.       foreach($w in $with.GetEnumerator()) {
  146.          if($w.Value) {
  147.             $plug = $plug.With($w.Key,$w.Value)
  148.          }
  149.       }
  150.       Write-Verbose "Added 'with' params: $plug"
  151.    }
  152.    if($headers) {
  153.       foreach($header in $Headers.GetEnumerator()) {
  154.          if($header.Value) {
  155.             $plug = $plug.WithHeader($header.Key,$header.Value)
  156.          }
  157.       }
  158.       Write-Verbose "Added 'with' params: $plug"
  159.    }
  160.    return $plug
  161. }
  162.  
  163. Function Receive-Http {
  164. PARAM(
  165.    # [Parameter(Position=1, Mandatory=$false)]
  166.    # [ValidateSet("Xml", "File", "Text","Bytes")]
  167.    # [Alias("As")]
  168.    $Output = "Xml"
  169. ,
  170.    #  [Parameter(Position=2, Mandatory=$false)]
  171.    [string]$Path
  172. ,
  173.    #  [Parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="Result")]
  174.    #  [Alias("IO")]
  175.    #  [MindTouch.Dream.Result``1[[MindTouch.Dream.DreamMessage]]]
  176.    $InputObject
  177. #,
  178.    #  [Parameter(Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="Response")]
  179.    #  [MindTouch.Dream.DreamMessage]
  180.    #  $response
  181. )
  182. BEGIN {
  183.    if($InputObject) {
  184.       Write-Output $inputObject | Receive-Http $Output $Path
  185.    } # else they'd better pass it in on the pipeline ...
  186. }
  187. PROCESS {
  188.    $response = $null
  189.    if($_ -is [MindTouch.Dream.Result``1[[MindTouch.Dream.DreamMessage]]]) {
  190.       $response = $_.Wait()
  191.    } elseif($_ -is [MindTouch.Dream.DreamMessage]) {
  192.       $response = $_
  193.    } elseif($_) {
  194.       throw "We can only pipeline [MindTouch.Dream.DreamMessage] objects, or [MindTouch.Dream.Result`1[DreamMessage]] objects"
  195.    }
  196.    
  197.    if($response) {
  198.       Write-Debug $($response | Out-String)
  199.       if(!$response.IsSuccessful) {
  200.          Write-Error $($response | Out-String)
  201.          Write-Verbose $response.AsText()
  202.          throw "ERROR: '$($response.Status)' Response Status."
  203.       } else {  
  204.          switch($Output) {
  205.             "File" {
  206.                ## Joel's magic filename guesser ...
  207.                if(!$Path) {
  208.                   [string]$fileName = ([regex]'(?i)filename=(.*)$').Match( $response.Headers["Content-Disposition"] ).Groups[1].Value
  209.                   $Path = $fileName.trim("\/""'")
  210.                   if(!$Path){
  211.                      if($response.ResponseUri)  {
  212.                         $fileName = $response.ResponseUri.Segments[-1]
  213.                         $Path = $fileName.trim("\/")
  214.                         if(!([IO.FileInfo]$Path).Extension) {
  215.                            $Path = $Path + "." + $response.ContentType.Split(";")[0].Split("/")[1]
  216.                         }
  217.                      }
  218.                   }
  219.                }
  220.                if($Path) {
  221.                   $File = Get-FileName $Path
  222.                } else {
  223.                   $File = Get-FileName
  224.                }
  225.                $null = [StreamUtil]::CopyToFile( $response.AsStream(), $response.ContentLength, $File )
  226.                Get-ChildItem $File
  227.             }
  228.             "XDoc" {
  229.                if($Path) {
  230.                   $response.AsDocument()[$Path]
  231.                } else {
  232.                   $response.AsDocument()#.ToXml()
  233.                }
  234.             }
  235.             "Xml" {
  236.                if($Path) {
  237.                   $response.AsDocument().ToXml().SelectNodes($Path)
  238.                } else {
  239.                   $response.AsDocument().ToXml()
  240.                }
  241.             }
  242.             "Text" {
  243.                if($Path) {
  244.                   $response.AsDocument()[$Path] | % { $_.AsInnerText }
  245.                } else {
  246.                   $response.AsText()
  247.                }
  248.             }
  249.             "Bytes" {
  250.                $response.AsBytes()
  251.             }
  252.          }
  253.       }
  254.    }
  255. }
  256. }
  257.  
  258. Function Invoke-Http {
  259. #.Synopsis
  260. #  Invoke an HTTP verb on a URI
  261. #.Description
  262. #  This is the core http rest cmdlet, which does most of the work and allows fetching web pages, files, etc.
  263. [CmdletBinding(DefaultParameterSetName="ByPath")]
  264. PARAM(
  265.    ## http`://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
  266.    ## Nobody actually uses HEAD or OPTIONS, right?
  267.    ## And nobody's even heard of TRACE or CONNECT ;)
  268.    [Parameter(Position=0, Mandatory=$false)]
  269.    [ValidateSet("POST", "GET", "PUT", "DELETE", "HEAD", "OPTIONS")] ## There are other verbs, but we need a list to make sure you don't screw up
  270.    [string]$Verb = "GET"
  271. ,
  272.    [Parameter(Position=1, Mandatory=$true, ValueFromPipeline=$false, ParameterSetName="WithPlug")]
  273.    [MindTouch.Dream.Plug]
  274.    $Plug
  275. ,
  276.    [Parameter(Position=1, Mandatory=$true, ValueFromPipeline=$true, ParameterSetName="ByPath")]
  277.    [string]
  278.    $Path
  279. ,
  280.    [Parameter(Position=2, Mandatory=$false, ParameterSetName="ByPath")]
  281.    [hashtable]$With
  282. ,
  283.    [Parameter(Position=3, Mandatory=$false, ParameterSetName="ByPath")]
  284.    [hashtable]$Headers
  285. ,
  286.    [Parameter(Mandatory=$false)]
  287.    $Content
  288. ,
  289.    [Parameter(Mandatory=$false)]
  290.    [System.Collections.Generic.IEnumerable[MindTouch.Dream.DreamCookie]]$Cookies
  291. ,
  292.    [Parameter(Mandatory=$false)]
  293.    $Type # Of Content
  294. ,
  295.    [Parameter(Mandatory=$false)]
  296.    [switch]$authenticate
  297. ,
  298.    [Parameter(Mandatory=$false)]
  299.    $credentials
  300. ,
  301.    [Parameter(Mandatory=$false)]
  302.    [switch]$Persistent  ## Note this ALSO causes WaitForResponse
  303. ,
  304.    [switch]$waitForResponse
  305. )
  306. PROCESS {
  307.       if(!$Plug){ #$PSCmdlet.ParameterSetName -eq $ByPath) {
  308.          $Plug = Get-DreamPlug $Path $With $Headers
  309.       }
  310.  
  311.       ## Special Handling for FORM_URLENCODED
  312.       if($Type -like "Form*" -and !$Content) {
  313.          $dream = [MindTouch.Dream.DreamMessage]::Ok( $Plug.Uri )
  314.          $Plug = [MindTouch.Dream.Plug]::New( $Plug.Uri.SchemeHostPortPath )
  315.          Write-Verbose "RECREATED Plug: $($Plug.Uri.SchemeHostPortPath)"
  316.       } else {
  317.          $dream = Get-DreamMessage $Content $Type
  318.          Write-Verbose "Created Dream with Content: $($dream.AsText() |out-String)"
  319.       }
  320.      
  321.       if(!$plug -or !$dream) {
  322.          throw "Can't come up with a request!"
  323.       }
  324.      
  325.       if($Persistent -and $global:HttpRestCookies) {
  326.          $dream.Cookies.AddRange( $global:HttpRestCookies )
  327.       }
  328.       if($Cookies) {
  329.          $dream.Cookies.AddRange( $Cookies )
  330.       }
  331.      
  332.       if($authenticate -or $credentials){
  333.          if($credentials -is [System.Management.Automation.PSCredential]) {
  334.             Write-Verbose "AUTHENTICATING AS $($credentials.GetNetworkCredential().UserName)"
  335.             $plug = $plug.WithCredentials($credentials.GetNetworkCredential())
  336.          } elseif($credentials -is [System.Net.ICredentials]) {
  337.             Write-Verbose "AUTHENTICATING AS $($credentials.GetNetworkCredential().UserName)"
  338.             $plug = $plug.WithCredentials($credentials.GetNetworkCredential())
  339.          } else {
  340.             if($credentials) {
  341.                Write-Error "Credential must be a PSCredential or a System.Net.ICredentials"
  342.             }
  343.             $null = Get-HttpCredential  # Make sure they have global credentials
  344.             Write-Verbose "AUTHENTICATING AS $($global:HttpRestCredential.UserName)"
  345.             $plug = $plug.WithCredentials($global:HttpRestCredential.GetNetworkCredential())
  346.          }
  347.       }
  348.      
  349.       Write-Verbose $plug.Uri
  350.      
  351.       ## DEBUG:
  352.       Write-Debug "URI: $($Plug.Uri)"
  353.       Write-Debug "Verb: $($Verb.ToUpper())"
  354.       Write-Debug $($dream | gm | Out-String)
  355.      
  356.       $result = $plug.InvokeAsync( $Verb.ToUpper(),  $dream )
  357.      
  358.       Write-Debug $($result | Out-String)
  359.       #  if($DebugPreference -eq "Continue") {
  360.       #     Write-Debug $($result.Wait() | Out-String)
  361.       #  }
  362.      
  363.       if($waitForResponse -or $Persistent) {
  364.          $result = $result.Wait()
  365.          $global:HttpRestCookies = $result.Cookies
  366.       }
  367.      
  368.       write-output $result
  369.    
  370.       trap [MindTouch.Dream.DreamResponseException] {
  371.          Write-Error @"
  372. TRAPPED DreamResponseException
  373.      
  374. $($_.Exception.Response | Out-String)
  375.  
  376. $($_.Exception.Response.Headers | Out-String)
  377. "@
  378.          break;
  379.       }
  380. }
  381. }
  382.  
  383. Function Get-WebPageContent {
  384. #.Synopsis
  385. #  A wrapper for http get | rcv xml
  386. [CmdletBinding()]
  387. param(
  388.    [Parameter(Position=0,Mandatory=$true, ValueFromPipeline=$true)]
  389.    [string]$url
  390. ,
  391.    [Parameter(Mandatory=$false)]
  392.    [string]$xpath=""
  393. ,
  394.    [Parameter(Position=2,Mandatory=$false)]
  395.    [hashtable]$with=@{}
  396. ,
  397.    [Parameter(Mandatory=$false)]
  398.    [switch]$Persist
  399. ,
  400.    [Parameter(Mandatory=$false)]
  401.    [switch]$Authenticate
  402. )
  403. PROCESS {
  404.    invoke-http get $url $with -Authenticate:$Authenticate -Persist:$Persist | receive-http xml $xpath | select -expand outerxml
  405. }
  406. }
  407.  
  408. Function Get-WebPageText {
  409. #.Synopsis
  410. #  A wrapper for http get | rcv text
  411. [CmdletBinding()]
  412. param(
  413.    [Parameter(Position=0,Mandatory=$true, ValueFromPipeline=$true)]
  414.    [string]$url
  415. ,
  416.    [Parameter(Mandatory=$false)]
  417.    [string]$xpath=""
  418. ,
  419.    [Parameter(Position=2,Mandatory=$false)]
  420.    [hashtable]$with=@{}
  421. ,
  422.    [Parameter(Mandatory=$false)]
  423.    [switch]$Persist
  424. ,
  425.    [Parameter(Mandatory=$false)]
  426.    [switch]$Authenticate
  427. )
  428. PROCESS {
  429.    invoke-http get $url $with -Authenticate:$Authenticate -Persist:$Persist | receive-http text $xpath
  430. }
  431. }
  432.  
  433. Function Get-WebFile {
  434. #.Synopsis
  435. #  Download a file from a URI to the local computer
  436. [CmdletBinding()]
  437. param(
  438.    [Parameter(Position=0,Mandatory=$true, ValueFromPipeline=$true)]
  439.    [string]$url
  440. ,
  441.    [Parameter(Mandatory=$false)]
  442.    [Alias("output")]
  443.    [string]$path=""
  444. ,
  445.    [Parameter(Position=2,Mandatory=$false)]
  446.    [hashtable]$with=@{}
  447. ,
  448.    [Parameter(Mandatory=$false)]
  449.    [switch]$Persist
  450. ,
  451.    [Parameter(Mandatory=$false)]
  452.    [switch]$Authenticate
  453. )
  454. PROCESS {
  455.    Invoke-Http GET $url $with -Authenticate:$Authenticate -Persist:$Persist | Receive-Http File $path
  456. }
  457. }
  458.  
  459. Function Set-HttpDefaultUrl {
  460. #.Synopsis
  461. #  Set the base URI for making lots of calls to a single webservice without re-entering the full URL each time
  462. PARAM ([uri]$baseUri=$(Read-Host "Please enter the base Uri for your RESTful web-service"))
  463.    $global:url = $baseUri
  464. }
  465.  
  466. Function Set-HttpCredential {
  467. #.Synopsis
  468. #  Set the default credentials for making lots of calls to a single webservice without re-entering credentials
  469. param($Credential=$(Get-CredentialBetter -Title   "Http Authentication Request - $($global:url.Host)" `
  470.                                          -Message "Your login for $($global:url.Host)" `
  471.                                          -Domain  $($global:url.Host)) )
  472.    if($Credential -is [System.Management.Automation.PSCredential]) {
  473.       $global:HttpRestCredential = $Credential
  474.    } elseif($Credential -is [System.Net.NetworkCredential]) {
  475.       $global:HttpRestCredential = new-object System.Management.Automation.PSCredential $Credential.UserName, $(ConvertTo-SecureString $credential.Password)
  476.    }
  477. }
  478.  
  479. Function Get-HttpCredential {
  480. #.Synopsis
  481. #  Retrieves the default credentials for making lots of calls to a single webservice without re-entering credentials
  482.    if(!$global:url) { Set-HttpDefaultUrl }
  483.    if(!$global:HttpRestCredential) { Set-HttpCredential }
  484.    if(!$Secure) {
  485.       return $global:HttpRestCredential.GetNetworkCredential();
  486.    } else {
  487.       return $global:HttpRestCredential
  488.    }
  489. }
  490.  
  491. Function ConvertTo-UrlDoubleEncode {
  492. #.Synopsis
  493. #  Encode URLs twice for use with mindtouch APIs
  494.    param([string]$text)
  495.    return [System.Web.HttpUtility]::UrlEncode( [System.Web.HttpUtility]::UrlEncode( $text ) )
  496. }
  497.  
  498. Function Join-Url {
  499. #.Synopsis
  500. #  Like Join-Path, but for URIs
  501. [CmdletBinding()]
  502. param(
  503. [Parameter()]
  504. [uri]$baseUri=$global:url
  505. ,
  506. [Parameter(ValueFromRemainingArguments=$true)]
  507. [string[]]$path
  508. )
  509.    $ofs="/";$BaseUrl = ""
  510.    if($BaseUri -and $baseUri.AbsoluteUri) {
  511.       $BaseUrl = "$($baseUri.AbsoluteUri.Trim('/'))/"
  512.    }
  513.    return [URI]"$BaseUrl$([string]::join("/",@($path)).TrimStart('/'))"
  514. }
  515.  
  516. Function ConvertTo-SecureString {
  517. #.Synopsis
  518. #   Helper function which converts a string to a SecureString
  519. Param([string]$input)
  520.    $result = new-object System.Security.SecureString
  521.  
  522.    foreach($c in $input.ToCharArray()) {
  523.       $result.AppendChar($c)
  524.    }
  525.    $result.MakeReadOnly()
  526.    return $result
  527. }
  528.  
  529. Function Get-FileName {
  530. #.Synopsis
  531. #  Helper function to get a VALID filesystem path
  532.    param($fileName=$([IO.Path]::GetRandomFileName()), $path)
  533.    $fileName = $fileName.trim("\/""'")
  534.    ## if the $Path has a file name, and it's folder exists:
  535.    if($Path -and !(Test-Path $Path -Type Container) -and (Test-Path (Split-Path $path) -Type Container)) {
  536.       $path
  537.    ## if the $Path is just a folder (and it exists)
  538.    } elseif($Path -and (Test-Path $path -Type Container)) {
  539.       $fileName = Split-Path $fileName -leaf
  540.       Join-Path $path $fileName
  541.    ## If there's no valid $Path, and the $FileName has a folder...
  542.    } elseif((Split-Path $fileName) -and (Test-Path (Split-Path $fileName))) {
  543.       $fileName
  544.    } else {
  545.       Join-Path (Get-Location -PSProvider "FileSystem") (Split-Path $fileName -Leaf)
  546.    }
  547. }
  548.  
  549. Function Get-UtcTime {
  550.    Param($Format="yyyyMMddhhmmss")
  551.    [DateTime]::Now.ToUniversalTime().ToString($Format)
  552. }
  553.  
  554. Function Get-CredentialBetter {
  555. ## .Synopsis
  556. ##    Gets a credential object based on a user name and password.
  557. ## .Description
  558. ##    The Get-Credential function creates a credential object for a specified username and password, with an optional domain. You can use the credential object in security operations.
  559. ##
  560. ##    The function accepts more parameters to customize the security prompt than the default Get-Credential cmdlet (including forcing the call through the console if you're in the native PowerShell.exe CMD console), but otherwise functions identically.
  561. ##
  562. ## .Parameter UserName
  563. ##    A default user name for the credential prompt, or a pre-existing credential (would skip all prompting)
  564. ## .Parameter Title
  565. ##    Allows you to override the default window title of the credential dialog/prompt
  566. ##
  567. ##    You should use this to allow users to differentiate one credential prompt from another.  In particular, if you're prompting for, say, Twitter credentials, you should put "Twitter" in the title somewhere. If you're prompting for domain credentials. Being specific not only helps users differentiate and know what credentials to provide, but also allows tools like KeePass to automatically determine it.
  568. ## .Parameter Message
  569. ##    Allows you to override the text displayed inside the credential dialog/prompt.
  570. ##    
  571. ##    You can use this for things like presenting an explanation of what you need the credentials for.
  572. ## .Parameter Domain
  573. ##    Specifies the default domain to use if the user doesn't provide one (by default, this is null)
  574. ## .Parameter GenericCredentials
  575. ##    The Get-Credential cmdlet forces you to always return DOMAIN credentials (so even if the user provides just a plain user name, it prepends "\" to the user name). This switch allows you to override that behavior and allow generic credentials without any domain name or the leading "\".
  576. ## .Parameter Inline
  577. ##    Forces the credential prompt to occur inline in the console/host using Read-Host -AsSecureString (not implemented properly in PowerShell ISE)
  578. ##
  579. [CmdletBinding(DefaultParameterSetName="Better")]
  580. PARAM(
  581.    [Parameter(Position=1,Mandatory=$false)]
  582.    [Alias("Credential")]
  583.    [PSObject]$UserName=$null,
  584.    [Parameter(Position=2,Mandatory=$false)]
  585.    [string]$Title=$null,
  586.    [Parameter(Position=3,Mandatory=$false)]
  587.    [string]$Message=$null,
  588.    [Parameter(Position=4,Mandatory=$false)]
  589.    [string]$Domain=$null,
  590.    [Parameter(Mandatory=$false)]
  591.    [switch]$GenericCredentials,
  592.    [Parameter(Mandatory=$false)]
  593.    [switch]$Inline
  594. )
  595. PROCESS {
  596.    if( $UserName -is [System.Management.Automation.PSCredential]) {
  597.       return $UserName
  598.    } elseif($UserName -ne $null) {
  599.       $UserName = $UserName.ToString()
  600.    }
  601.    
  602.    if($Inline) {
  603.       if($Title)    { Write-Host $Title }
  604.       if($Message)  { Write-Host $Message }
  605.       if($Domain) {
  606.          if($UserName -and $UserName -notmatch "[@\\]") {
  607.             $UserName = "${Domain}\${UserName}"
  608.          }
  609.       }
  610.       if(!$UserName) {
  611.          $UserName = Read-Host "User"
  612.          if(($Domain -OR !$GenericCredentials) -and $UserName -notmatch "[@\\]") {
  613.             $UserName = "${Domain}\${UserName}"
  614.          }
  615.       }
  616.       return New-Object System.Management.Automation.PSCredential $UserName,$(Read-Host "Password for user $UserName" -AsSecureString)
  617.    }
  618.    if($GenericCredentials) { $Credential = "Generic" } else { $Credential = "Domain" }
  619.    
  620.    ## Now call the Host.UI method ... if they don't have one, we'll die, yay.
  621.    ## BugBug? PowerShell.exe disregards the last parameter
  622.    $Host.UI.PromptForCredential($Title, $Message, $UserName, $Domain, $Credential,"Default")
  623. }
  624. }
  625.  
  626. New-Alias Encode-Twice ConvertTo-UrlDoubleEncode
  627.  
  628. new-alias gwpc Get-WebPageContent -EA "SilentlyContinue"
  629. new-alias gwpt Get-WebPageText    -EA "SilentlyContinue"
  630. new-alias http Invoke-Http        -EA "SilentlyContinue"
  631. new-alias rcv  Receive-Http       -EA "SilentlyContinue"
  632.  
  633. Export-ModuleMember -Function Invoke-Http, Receive-Http, ConvertTo-UrlDoubleEncode, Get-WebPageContent, Get-WebPageText, Get-WebFile, Get-HttpCredential, Set-HttpCredential, Set-HttpDefaultUrl -Alias *
  634. # SIG # Begin signature block
  635. # MIIIDQYJKoZIhvcNAQcCoIIH/jCCB/oCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
  636. # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
  637. # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUr09whcNnLQwup5+1zj3w+DcA
  638. # +/agggUrMIIFJzCCBA+gAwIBAgIQKQm90jYWUDdv7EgFkuELajANBgkqhkiG9w0B
  639. # AQUFADCBlTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0
  640. # IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD
  641. # VQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAbBgNVBAMTFFVUTi1VU0VS
  642. # Rmlyc3QtT2JqZWN0MB4XDTEwMDUxNDAwMDAwMFoXDTExMDUxNDIzNTk1OVowgZUx
  643. # CzAJBgNVBAYTAlVTMQ4wDAYDVQQRDAUwNjg1MDEUMBIGA1UECAwLQ29ubmVjdGlj
  644. # dXQxEDAOBgNVBAcMB05vcndhbGsxFjAUBgNVBAkMDTQ1IEdsb3ZlciBBdmUxGjAY
  645. # BgNVBAoMEVhlcm94IENvcnBvcmF0aW9uMRowGAYDVQQDDBFYZXJveCBDb3Jwb3Jh
  646. # dGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMfUdxwiuWDb8zId
  647. # KuMg/jw0HndEcIsP5Mebw56t3+Rb5g4QGMBoa8a/N8EKbj3BnBQDJiY5Z2DGjf1P
  648. # n27g2shrDaNT1MygjYfLDntYzNKMJk4EjbBOlR5QBXPM0ODJDROg53yHcvVaXSMl
  649. # 498SBhXVSzPmgprBJ8FDL00o1IIAAhYUN3vNCKPBXsPETsKtnezfzBg7lOjzmljC
  650. # mEOoBGT1g2NrYTq3XqNo8UbbDR8KYq5G101Vl0jZEnLGdQFyh8EWpeEeksv7V+YD
  651. # /i/iXMSG8HiHY7vl+x8mtBCf0MYxd8u1IWif0kGgkaJeTCVwh1isMrjiUnpWX2NX
  652. # +3PeTmsCAwEAAaOCAW8wggFrMB8GA1UdIwQYMBaAFNrtZHQUnBQ8q92Zqb1bKE2L
  653. # PMnYMB0GA1UdDgQWBBTK0OAaUIi5wvnE8JonXlTXKWENvTAOBgNVHQ8BAf8EBAMC
  654. # B4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzARBglghkgBhvhC
  655. # AQEEBAMCBBAwRgYDVR0gBD8wPTA7BgwrBgEEAbIxAQIBAwIwKzApBggrBgEFBQcC
  656. # ARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLm5ldC9DUFMwQgYDVR0fBDswOTA3oDWg
  657. # M4YxaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0
  658. # LmNybDA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNv
  659. # bW9kb2NhLmNvbTAhBgNVHREEGjAYgRZKb2VsLkJlbm5ldHRAWGVyb3guY29tMA0G
  660. # CSqGSIb3DQEBBQUAA4IBAQAEss8yuj+rZvx2UFAgkz/DueB8gwqUTzFbw2prxqee
  661. # zdCEbnrsGQMNdPMJ6v9g36MRdvAOXqAYnf1RdjNp5L4NlUvEZkcvQUTF90Gh7OA4
  662. # rC4+BjH8BA++qTfg8fgNx0T+MnQuWrMcoLR5ttJaWOGpcppcptdWwMNJ0X6R2WY7
  663. # bBPwa/CdV0CIGRRjtASbGQEadlWoc1wOfR+d3rENDg5FPTAIdeRVIeA6a1ZYDCYb
  664. # 32UxoNGArb70TCpV/mTWeJhZmrPFoJvT+Lx8ttp1bH2/nq6BDAIvu0VGgKGxN4bA
  665. # T3WE6MuMS2fTc1F8PCGO3DAeA9Onks3Ufuy16RhHqeNcMYICTDCCAkgCAQEwgaow
  666. # gZUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtl
  667. # IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
  668. # aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0
  669. # LU9iamVjdAIQKQm90jYWUDdv7EgFkuELajAJBgUrDgMCGgUAoHgwGAYKKwYBBAGC
  670. # NwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
  671. # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUBKVb3pGB
  672. # 1I/RXvlaTjJsduu94KYwDQYJKoZIhvcNAQEBBQAEggEAOUrgnwmYthZZQ7oleYBr
  673. # hy1y4h7DRJ8eNTpjV8wfbJYmriuqWZsbnmZUiMQqXDgQJ7rWx/2KZOtlp5Q4EYdi
  674. # +j8Q3YChnUwVr0Z1zjCj91PtnU5M7IB1eyTqmUgWIX3ldd9AnmCB8Eted487/VuK
  675. # YrAO0gHQVmIX6t/Yv2bG0D3ggvqDmUbuqw7UV526ykVAmbX0tYOXeFBC5sCo9c3L
  676. # lmBO/cgZDXq5C7DC5mnLBYxsvXvSitAE7m/S+v7U2irc2pnGqiIabz/spC+O+YOw
  677. # zWbfdzyHxWNMMQ2ZTfkQ8AVEv+Um1zT81x8Mf2CSznaBawU/7byZdSIObsHTZ2EK
  678. # gg==
  679. # SIG # End signature block

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me