diff --git a/README.md b/README.md index 04c913b..c009b48 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ leave its login and every other path alone. |---------|-----------|------------| | `workflow` | Yes | `insurance` if no patient files, `insurance+patient` if both | | `insurance_file_type` | No (defaults to `pdf`) | Set to `tif` for an entity whose imaging system exports the daily files as TIFs instead of PDFs (CAMBS, RMI, CONSENSIO, INLAND). Goes at the top level, next to `workflow` — NOT inside `ftps` | -| `ftps.host` | Yes | FTP server address | +| `ftps.host` | Yes | Server address. A plain name (`ftp.example.com`) uses FTP/FTPS per the `tls` setting. You can also paste a full URL — `sftp://server.com` sends these files over **SFTP** instead (some partners use SFTP for everything), and `ftps://server.com` forces FTPS | | `ftps.port` | No (defaults to 21) | FTP port, only if not 21 | | `ftps.tls` | Yes | `true` for FTPS (secure), `false` for plain FTP | | `ftps.username` | Yes | FTP username (shared across all practices) | diff --git a/engine.ps1 b/engine.ps1 index c8f707c..69b0b67 100644 --- a/engine.ps1 +++ b/engine.ps1 @@ -168,16 +168,37 @@ function Get-ArchiveDir($parent, $name) { return $path } +# Host values may be pasted as URLs, e.g. "SFTP://server.com/" - pull out the +# scheme (decides the protocol) and the bare hostname. +function Get-HostInfo($rawHost) { + $h = ([string]$rawHost).Trim() + $scheme = $null + if ($h -imatch '^(\w+)://') { + $scheme = $Matches[1].ToLower() + $h = $h -replace '^\w+://', '' + } + $h = $h.Split('/')[0] + return @{ Scheme = $scheme; HostName = $h } +} + # -- Upload via FTPS ----------------------------------------------------------- function Invoke-FTPSUpload($ftpConfig, $files, $remotePath, $entity, $practice) { + $hostInfo = Get-HostInfo $ftpConfig.host $opts = New-Object WinSCP.SessionOptions - $opts.Protocol = [WinSCP.Protocol]::Ftp - $opts.FtpSecure = if ($ftpConfig.tls) { [WinSCP.FtpSecure]::Explicit } else { [WinSCP.FtpSecure]::None } - $opts.HostName = $ftpConfig.host - $opts.PortNumber = if ($ftpConfig.port) { [int]$ftpConfig.port } else { 21 } + if ($hostInfo.Scheme -eq "sftp") { + $opts.Protocol = [WinSCP.Protocol]::Sftp + $opts.PortNumber = if ($ftpConfig.port) { [int]$ftpConfig.port } else { 22 } + $opts.GiveUpSecurityAndAcceptAnySshHostKey = $true + } else { + $useTls = ($ftpConfig.tls -eq $true) -or ($hostInfo.Scheme -eq "ftps") + $opts.Protocol = [WinSCP.Protocol]::Ftp + $opts.FtpSecure = if ($useTls) { [WinSCP.FtpSecure]::Explicit } else { [WinSCP.FtpSecure]::None } + $opts.PortNumber = if ($ftpConfig.port) { [int]$ftpConfig.port } else { 21 } + if ($useTls) { $opts.GiveUpSecurityAndAcceptAnyTlsHostCertificate = $true } + } + $opts.HostName = $hostInfo.HostName $opts.UserName = $ftpConfig.username $opts.Password = $ftpConfig.password - $opts.GiveUpSecurityAndAcceptAnyTlsHostCertificate = $true $session = New-Object WinSCP.Session if ($logLevel -eq "debug") { @@ -186,7 +207,7 @@ function Invoke-FTPSUpload($ftpConfig, $files, $remotePath, $entity, $practice) $ok = 0; $fail = 0 try { - Write-Debug "FTPS connect: $($ftpConfig.host) user=$($ftpConfig.username) tls=$($ftpConfig.tls)" + Write-Debug "Connect: $($opts.Protocol) $($hostInfo.HostName):$($opts.PortNumber) user=$($ftpConfig.username)" $session.Open($opts) foreach ($file in $files) { $remote = $remotePath.TrimEnd("/") + "/" + $file.Name @@ -216,9 +237,10 @@ function Invoke-FTPSUpload($ftpConfig, $files, $remotePath, $entity, $practice) # -- Upload via SFTP ----------------------------------------------------------- function Invoke-SFTPUpload($sftpConfig, $files, $remotePath, $entity, $practice) { + $hostInfo = Get-HostInfo $sftpConfig.host $opts = New-Object WinSCP.SessionOptions $opts.Protocol = [WinSCP.Protocol]::Sftp - $opts.HostName = $sftpConfig.host + $opts.HostName = $hostInfo.HostName $opts.PortNumber = if ($sftpConfig.port) { [int]$sftpConfig.port } else { 22 } $opts.UserName = $sftpConfig.username $opts.Password = $sftpConfig.password