Powershell FTP won't list files on server - powershell

I want to make a backup script for ZyWall USG 20.
I used this Powershell code to get a list of the content in the directory:
[System.Net.FtpWebRequest]$ftp = [System.Net.WebRequest]::Create("ftp://*server*/*path*")
$ftp.Credentials = New-Object System.Net.NetworkCredential("*user*","*password*")
$ftp.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory
$response = $ftp.getresponse()
echo $response
I expected to get a list of all the files..instead I get this:
PS Z:\> ...\list-files-test.ps1
ContentLength : -1
Headers : {}
SupportsHeaders : True
ResponseUri : ftp://*server*/*path*/
StatusCode : OpeningData
StatusDescription : 150 Opening BINARY mode data connection for file list
LastModified : 01.01.0001 00:00:00
BannerMessage : 220 FTP Server (ZyWALL USG 20) [::ffff:*server*]
WelcomeMessage : 230 User *user* logged in
ExitMessage :
IsFromCache : False
IsMutuallyAuthenticated : False
ContentType :
PS Z:\>
Why don' I get a list of files?
I checked it with filezilla - the folder is not empty.
And I can download specific files using [System.Net.WebRequestMethods+Ftp]::DownloadFile.

WebRequest.GetResponse() makes the remote call and gets the response details, but there's no content within the response itself.
Instead, you need to continue on and read the response stream out of the response with WebResponse.GetResponseStream().

Related

Extract first part of URL

I have an URL like so:
https://www.example.com/oauth/connect/token
I want to get only https://www.example.com and I have tried a bunch of ways to get this but all the ways I have tried require me to hardcode multiple /s.
Example:
$Url.Split('/')[0] + "//" + $url.split('/')[2]
Is there a way to do this without using the harcoding?
You may use [System.Uri], to 'cast' the string into an System.Uri class.
$url = [System.Uri]"https://www.example.com/oauth/connect/token"
You can then use the host and scheme to get the part of the URL you want.
$result = $url.Scheme, $url.Host -join "://"
You could also remove the AbsolutePath from the entire URL.
$url = [System.Uri]"https://www.example.com/oauth/connect/token"
$result = $url.AbsoluteUri.Replace($url.AbsolutePath, "")
This is the complete list of attributes that the System.Uri instance will have:
AbsolutePath : /oauth/connect/token
AbsoluteUri : https://www.example.com/oauth/connect/token
LocalPath : /oauth/connect/token
Authority : www.example.com
HostNameType : Dns
IsDefaultPort : True
IsFile : False
IsLoopback : False
PathAndQuery : /oauth/connect/token
Segments : {/, oauth/, connect/, token}
IsUnc : False
Host : www.example.com
Port : 443
Query :
Fragment :
Scheme : https
OriginalString : https://www.example.com/oauth/connect/token
DnsSafeHost : www.example.com
IdnHost : www.example.com
IsAbsoluteUri : True
UserEscaped : False
UserInfo :

Changes in System.Net.HttpWebRequest between Powershell versions?

I am having some trouble converting a Powershell script from PS5 to PS7.
My goal is to get information on a remote server cert.
This IP can be anything with a cert:
$url = "https://192.168.1.1"
[Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
$req = [Net.HttpWebRequest]::Create($url)
$req.GetResponse()
[datetime]$expiration =
[System.DateTime]::Parse($req.ServicePoint.Certificate.GetExpirationDateString())
Write-Output $expiration
When run in Powershell 5, this script completes successfully with the output below:
IsMutuallyAuthenticated : False
Cookies : {}
Headers : {Accept-Ranges, Content-Length, Content-Type, Date...}
SupportsHeaders : True
ContentLength : 98540
ContentEncoding :
ContentType : text/html
CharacterSet : ISO-8859-1
Server : Microsoft-IIS/10.0
...
Date : 7/7/2020 12:00:00 AM
...
This script errors on $req.GetResponse when run in Powershell 7.
MethodInvocationException: Exception calling "GetResponse" with "0" argument(s): "The SSL connection could not be established, see inner exception. There is no Runspace available to run scripts in this thread. You can provide one in the DefaultRunspace property of the System.Management.Automation.Runspaces.Runspace type. The script block you attempted to invoke was: $true "
Any ideas?

How to get email address from the emails inside an Oulook folder via PowerShell?

I have an Outlook folder, let's call it LoremIpsum, where I have more than 1000+ email drafts that I want to enumarate and do some filtering via PowerShell. I can access the folder and see the emails already, using this script:
Function HandleRemaining {
[CmdletBinding()]
Param()
BEGIN {
Clear-Host
}
PROCESS {
$outlook = New-Object -ComObject outlook.application
$mapi = $outlook.getnamespace("MAPI");
$email = $mapi.Folders.Item(1).Folders.Item('LoremIpsum').Items(1)
foreach ($recip in $email.Recipients) {
$recip
}
$email.To
$email.CC
}
END {
}
}
HandleRemaining
The problem is that neither $recip nor $email.To return the email address of the To or CC of that email, instead I get the person's resolved name, example:
Application : Microsoft.Office.Interop.Outlook.ApplicationClass
Class : 4
Session : Microsoft.Office.Interop.Outlook.NameSpaceClass
Parent : System.__ComObject
Address : /o=ExchangeLabs/ou=Exchange Administrative Group (ALPHA-NUMERIC)/cn=Recipients/cn=LONG-ALPHANUMERIC-HERE
AddressEntry : System.__ComObject
AutoResponse :
DisplayType : 0
EntryID : <snip>
Index : 1
MeetingResponseStatus : 0
Name : John Walker
Resolved : True
TrackingStatus : 0
TrackingStatusTime : 01-Jan-01 00:00:00
Type : 1
PropertyAccessor : System.__ComObject
Sendable : True
John Walker
I changed the numbers and codes to preserve privacy, but that's the return I get. So, how can I get the proper emaill address of the recipients of a given email draft?
I think you need to use the PropertyAccessor.
$PR_SMTP_ADDRESS = "http://schemas.microsoft.com/mapi/proptag/0x39FE001E"
$smtpAddress = $recip.PropertyAccessor.GetProperty($PR_SMTP_ADDRESS)
See here (Warning! VBA): https://msdn.microsoft.com/en-us/VBA/Outlook-VBA/articles/obtain-the-e-mail-address-of-a-recipient

Get Domain from URL in PowerShell

I'm looking to strip out the domain in this scenario using PowerShell. What is the most effective method to get example.com out of the following variable?
$URL = "http://www.example.com/folder/"
(some sort of regex command here to convert/strip $URL into $DOMAIN using PowerShell)
$DOMAIN = "example.com" #<-- taken from $URL
I've searched and I've found results for finding the IP address from a domain but I need to establish what the domain is first using regex (or another method).
Try the URI class:
PS> [System.Uri]"http://www.example.com/folder/"
AbsolutePath : /folder/
AbsoluteUri : http://www.example.com/folder/
LocalPath : /folder/
Authority : www.example.com
HostNameType : Dns
IsDefaultPort : True
IsFile : False
IsLoopback : False
PathAndQuery : /folder/
Segments : {/, folder/}
IsUnc : False
Host : www.example.com
Port : 80
Query :
Fragment :
Scheme : http
OriginalString : http://www.example.com/folder/
DnsSafeHost : www.example.com
IsAbsoluteUri : True
UserEscaped : False
UserInfo :
And remove the www prefix:
PS> ([System.Uri]"http://www.example.com/folder/").Host -replace '^www\.'
example.com
Like this:
PS C:\ps> [uri]$URL = "http://www.example.com/folder/"
PS C:\ps> $domain = $url.Authority -replace '^www\.'
PS C:\ps> $domain
example.com
For properly calculating the sub-domain, the trick is you need to know the second to last period. Then you take a substring of that second to last period (or none if it is only one .) to the final position by subtracting the location of second period (or 0) from total length of domain. This will return the proper domain-only and will work regardless of how many sub-domains are nested under the TLD:
$domain.substring((($domain.substring(0,$domain.lastindexof("."))).lastindexof(".")+1),$domain.length-(($domain.substring(0,$domain.lastindexof("."))).lastindexof(".")+1))
Also note that System URI itself is valid 99% of the time but I'm parsing my IIS logs and finding that with VERY long (often invalid/malicious requests) URIs it does not properly parse and fails those.
I have this in function form as:
Function Get-DomainFromURL {
<#
.SYNOPSIS
Takes string URL and returns domain only
.DESCRIPTION
Takes string URL and returns domain only
.PARAMETER URL
URL to parse for domain
.NOTES
Author: Dane Kantner 9/16/2016
#>
[CmdletBinding()]
param(
[Alias("URI")][parameter(Mandatory=$True,ValueFromPipeline=$True)][string] $URL
)
try { $URL=([System.URI]$URL).host }
catch { write-error "Error parsing URL"}
return $URL.substring((($URL.substring(0,$URL.lastindexof("."))).lastindexof(".")+1),$URL.length-(($URL.substring(0,$URL.lastindexof("."))).lastindexof(".")+1))
}

Powershell web request - 400 Bad Request

Im building a powershell script to execute commands on a REST-like server, I am using powershell to POST XML data to the webservice. Everything is working perfectly except when the "application" produces an error. The application replies back with details in xml and also gives me a Web Request Error (in this case 400) which is when i have problems. Whenever i get a Web Request Error that is not 200 the commands throw an error which screws up how i handle the error.
This is an example of the response im receiving (using fiddler):
HTTP/1.1 400 Bad Request
Date: Thu, 29 Nov 2012 04:29:48 GMT
Content-Type: text/xml;charset=ISO-8859-1
Connection: close
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Status>
<operation>Add Network</operation>
<result>ERROR</result>
<resultCode>REASON_210</resultCode>
</Status>
This is the error i receive in powershell:
Exception calling "UploadData" with "3" argument(s): "The remote server returned an error: (400) Bad Request."
At C:\Scripting\test.ps1:47 char:34
+ $response = $query.UploadData <<<< ($url,"POST",$byteArray)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Exception calling "GetString" with "1" argument(s): "Array cannot be null.
Parameter name: bytes"
At C:\Scripting\test.ps1:48 char:62
+ $stringresponse = [System.Text.Encoding]::ASCII.GetString <<<< ($response)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
I dug further into the error and this is as close as i could get to retrieving the content of the response (the XML).
I thought I might be able to pull it out from this..
$error[1].exception.InnerException.Data
But it is empty :(
PS C:\Scripting> $error[1].exception.InnerException | fl -force
Status : ProtocolError
Response : System.Net.HttpWebResponse
Message : The remote server returned an error: (400) Bad Request.
Data : {}
InnerException :
TargetSite : Byte[] UploadDataInternal(System.Uri, System.String, Byte[], System.Net.WebRequest ByRef)
StackTrace : at System.Net.WebClient.UploadDataInternal(Uri address, String method, Byte[] data, WebRequest& request)
at System.Net.WebClient.UploadData(Uri address, String method, Byte[] data)
at System.Net.WebClient.UploadData(String address, String method, Byte[] data)
at UploadData(Object , Object[] )
at System.Management.Automation.MethodInformation.Invoke(Object target, Object[] arguments)
at System.Management.Automation.DotNetAdapter.AuxiliaryMethodInvoke(Object target, Object[] arguments, MethodInformation methodInformation, Object[]
originalArguments)
HelpLink :
Source : System
PS C:\Scripting> $error[1].exception.InnerException.response | fl
IsMutuallyAuthenticated : False
Cookies : {}
Headers : {Connection, Transfer-Encoding, Content-Type, Date}
ContentLength : -1
ContentEncoding :
ContentType : text/xml;charset=ISO-8859-1
CharacterSet : ISO-8859-1
Server :
LastModified : 29/11/12 4:04:19 PM
StatusCode : BadRequest
StatusDescription : Bad Request
ProtocolVersion : 1.1
ResponseUri : https://api-au.dimensiondata.com/oec/0.9/cdefb891-1552-4008-8638-7393eda8d7e1/network
Method : POST
IsFromCache : False
Here is my powershell code that I am using:
function send_web ($url,$data) {
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$query = new-object system.net.WebClient
$auth = 'Basic ' + [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($username+":"+$password ))
$query.Headers.Add('Authorization', $auth )
[byte[]]$byteArray = [System.Text.Encoding]::ASCII.GetBytes($data)
$query.Headers.Add("ContentType","application/xml")
$response = $query.UploadData($url,"POST",$byteArray)
$stringresponse = [System.Text.Encoding]::ASCII.GetString($response)
return $stringresponse
}
This seems like it shouldn't be a hard thing to do any help would be much appreciated :)
Richard