$MediaServer_hostname_or_IPv4 = 'mediaserver.domain.local' $MediaServer_Tomcat_HTTP_port = '8080' # If you don't enter a password between the '' characters, PowerShell's Get-Credential command will prompt thee user to enter the credentials. # This is useful if you don't want to, or aren't allowed to store the password, for example, in a PowerShell variable, or as cleartext in this script, or in a file that contains this script. $MediaServer_Tomcat_username = 'admin' $MediaServer_Tomcat_password = 'password' # You can set up this script to automatically re-download new or changed files, every 15 seconds, until you press CTRL+C. # To do that, specify $true in the next line. To turn the re-download feature off, specify $false $Repeat_until_user_presses_CTRL_C = $false $Seconds_to_wait_between_repeats = 15 # Limit resource usage to avoid excessive load on the Tomcat service on the media aerver. Typically there's no need to change the following value. $Milliseconds_to_wait_between_requests = 100 # This script is unsupported, but known to work on the following media server versions: # * 6.45 (Release 5.5u3.1) # * 6.56 (Release 6.0u1) # * 7.28 (Release 6.5u2) # ...and probably anything in between. function RecursiveWebRequest ($HttpPathName) # HttpPathName must begin with a / character, and must end with a / character { write-host "HTTP directory: $HttpPathName" $WebResult=$null if ($script:ErrorFlag -eq $false) { try { Start-Sleep -m $Milliseconds_to_wait_between_requests $WebResult=Invoke-WebRequest -Credential $TomcatAdminCredentials -uri "http://$MediaServer_hostname_or_IPv4`:$MediaServer_Tomcat_HTTP_port$HttpPathName" } catch { write-host $_.Exception -ForegroundColor yellow write-host 'ERROR: The script has stopped.' -ForegroundColor Red $script:ErrorFlag=$true } } if ($WebResult) { foreach ($HtmlElement in $WebResult.AllElements) { # Select only those HTML tags that are hyperlinks () and contain an actual value within the HREF="..." property of the hyperlink # Also, stop if an error has been detected if (($HtmlElement.tagName -eq 'A') -and ($HtmlElement.href -ne '') -and ($script:ErrorFlag -eq $false)) { $HrefValue=$HtmlElement.href.tostring() # Examples of $HrefValues. # The first and second one ends with / and therefore represent directories. The rest does not, and therefore represent files. # /switch-logs/ # /switch-logs/tomcat-logs/ # /switch-logs/tomcat-logs/host-manager.2019-01-08.log # /switch-logs/asterisk-logs/Misc/collectInfo_run_20190109_103424.tgz # /switch-logs/asterisk-logs/full if ($HrefValue.EndsWith('/')) { # --- FOLDER --- # We assume that this $HrefValue takes us to a subfolder, because the value within the HREF tag ends with / $A_Tag_InnerText=$HtmlElement.innertext # The text between and # Examples: # tomcat-logs/ # Up To / <-- Older media servers # Up To /asterisk-logs <-- Older media servers # Up To [/] <-- Recent media servers # Up To [/asterisk-logs] <-- Recent media servers # asterisk-logs/ # The first hyperlink at the top of each page takes us to the parent folder. # To prevent infinite recursion, ignore tags where inner text contains one of those strings. if ($A_Tag_InnerText.contains('Up To /') -or ($A_Tag_InnerText.contains('Up To [/'))) { # Do nothing! Ignore the link at the top of the page that takes us back to the parent folder } else { $SubFolderNameExclPath=$HrefValue.Replace($HttpPathName,'') # $HrefValue always contains the full path, including all parent folders all the way up the root, and not just the name of the subfolder. # For example, for the "Misc/" folder, $HrefValuevalue "/switch-logs/asterisk-logs/Misc/" # To get the $HttpPathName correct for the recursion of the subfolder, remove $HttpPathName from $HttpPathName # Note that the parameter HttpPathName must begin with a / character, and must end with a / character, when you call the function RecursiveWebRequest # To process the subfolder, make the recursive function call RecursiveWebRequest -HttpPathName "$HttpPathName$SubFolderNameExclPath" } } else { # --- FILE --- # We assume that this $HrefValue takes us to a file, because the value within the HREF tag does not end with / foreach ($TableRow_file in $WebResult.AllElements) { # Select only the HTML tags that are table rows () # Each of those tags represent the FILES that you can see on the web page. # Also, stop if any error has been detected if (($TableRow_file.tagName -eq 'tr') -and ($script:ErrorFlag -eq $false)) { $TableRow_file_Innerhtml=$TableRow_file.innerhtml # For example, a $TableRow_file_Innerhtml can look like: # #    collectInfo_run_20190109_103424.tgz # 4832.2 kb # Wed, 09 Jan 2019 09:34:25 GMT # # Select exactly the single element that represents the file we are looking for, as stored in $HrefValue # We include href="..." to make sure we don't get a false match, if a filename is a part of another filename. if ($TableRow_file_Innerhtml.contains("href=""$HrefValue""")) { # --- GET FILE DATE LAST MODIFIED --- # Select the contents of $TableRow_file_Innerhtml after the third tag. This part contains the "Date last modified" string. # After the -split operation, $arrAfterSplit_TT_tag[3] will then represent that string and some redundant information ( GMT) after the date we need. # Also, stop all recursion, with an error if we can't find exactly 3 tags. $arrAfterSplit_TT_tag=$TableRow_file_Innerhtml.tostring() -split '',0,'simplematch' if ($arrAfterSplit_TT_tag.count -eq 4) # Convert/parse the string $arrAfterSplit_TT_tag[3].substring(5,20) into a date { # Example of $arrAfterSplit_TT_tag[3] data: # # $arrAfterSplit_TT_tag[3] Example: "Wed, 09 Jan 2019 09:34:21 GMT" # $arrAfterSplit_TT_tag[3].substring(5,20) Example "09 Jan 2019 09:34:21" # $FileDateLastModified=$null $FileDateLastModified=[datetime]::parse($arrAfterSplit_TT_tag[3].substring(5,20)) if ($FileDateLastModified -eq $null) { # Unexpected data on web page. Stop! write-host "ERROR: Unable to convert the text between the third set of tags to a date, for the file: $HrefValue" -ForegroundColor yellow write-host "`r`nThe text between the tags for that file contains:" -ForegroundColor Yellow write-host "$TableRow_file_Innerhtml" -ForegroundColor Gray write-host "`r`nThe string contains:" -ForegroundColor yellow write-host $arrAfterSplit_TT_tag[3] -ForegroundColor gray write-host "`r`nSubstring(5,20) contains:" -ForegroundColor yellow write-host $arrAfterSplit_TT_tag[3].substring(5,20) -ForegroundColor gray $script:ErrorFlag=$true } else { # File is valid and date last modified is valid # Create the folder structure in the $DownloadFolder if (-not (test-path -path "$DownloadFolder")) {mkdir "$DownloadFolder"|Out-Null} if (-not (test-path -path "$DownloadFolder$HttpPathName")) {mkdir "$DownloadFolder$HttpPathName"|Out-Null} # Get LastWriteTime from local file, or return $null if no local file exists if (test-path "$DownloadFolder\$HrefValue") { $LocalFileDate=(dir "$DownloadFolder\$HrefValue").LastWriteTime -eq $FileDateLastModified } else { $LocalFileDate=$null } # --- DOWNLOAD FILE --- # If the file has a different LastWriteTime, download it if ($LocalFileDate -eq $FileDateLastModified) { # Do nothing, local file LastWriteTime matches server file LastWriteTime } else { # Download file write-host " - Downloading changed file: $HrefValue $FileDateLastModified" -ForegroundColor green $ProgressPreference = 'SilentlyContinue' Start-Sleep -m $Milliseconds_to_wait_between_requests Invoke-WebRequest -uri "http://$MediaServer_hostname_or_IPv4`:$MediaServer_Tomcat_HTTP_port$HrefValue" -OutFile "$DownloadFolder\$HrefValue" -Credential $TomcatAdminCredentials # Update local file date last modified from the server (dir "$DownloadFolder\$HrefValue").LastWriteTime=$FileDateLastModified # Open download folder in windows explorer, but only do it once if ($script:OpenDownloadFolderInExplorer -eq $false) { &explorer $DownloadFolder $script:OpenDownloadFolderInExplorer=$true } } } } else { write-host "ERROR: Unable to locate the text between the third set of tags, for the file: $HrefValue" -ForegroundColor Red write-host "`r`nThe text between the tags for that file contains:" -ForegroundColor Yellow write-host $TableRow_file_Innerhtml -ForegroundColor Gray $script:ErrorFlag=$true } } } } } } } } } # main () $DownloadFolder=[Environment]::GetFolderPath("Desktop")+"\Files downloaded from media server" $script:ErrorFlag=$false $script:OpenDownloadFolderInExplorer=$false # Prevent the user from running this tool on PowerShell versions older than 3.0 if ($PSVersionTable.PSVersion.Major -lt 3) { write-host 'ERROR: The script has stopped.' -ForegroundColor Red write-host "Unfortunately, you can't use this PowerShell script!`n`rTo use this script, your computer needs some updates.`n`rTo continue, you must use Windows Update to install PowerShell version 3.0 or newer." -ForegroundColor Yellow $script:ErrorFlag=$true } else { # If username or password wasn't specified in the beginning of this script, we're going to prompt the user to enter the credentials. # This makes it possible to use this script without storing credentials inside the script. That's useful if IT-policies within your organization doesn't allow this. if (($MediaServer_Tomcat_username -eq '') -or ($MediaServer_Tomcat_password -eq '')) { # Prompt the user for credentials $TomcatAdminCredentials = Get-Credential -Message "Enter credentials for the Tomcat Admin user on $MediaServer_hostname_or_IPv4`:$MediaServer_Tomcat_HTTP_port" -UserName $MediaServer_Tomcat_username } else { # https://stackoverflow.com/questions/6239647/using-powershell-credentials-without-being-prompted-for-a-password $secstr=New-Object -TypeName System.Security.SecureString $MediaServer_Tomcat_password.ToCharArray()|ForEach-Object {$secstr.AppendChar($_)} $TomcatAdminCredentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $MediaServer_Tomcat_username,$secstr } do { # Note that the parameter HttpPathName must begin with a / character, and must end with a / character, when you call the function RecursiveWebRequest if ($script:ErrorFlag -eq $false) { RecursiveWebRequest -HttpPathName '/switch-logs/' } if ($script:ErrorFlag -eq $false -and $Repeat_until_user_presses_CTRL_C) { write-host "-----------------------------------------------------------------------------------------------------------------" write-host "Changed files will be re-downloaded every"$Seconds_to_wait_between_repeats" seconds. Press CTRL+C to stop." write-host "-----------------------------------------------------------------------------------------------------------------" Start-Sleep -s $Seconds_to_wait_between_repeats } } until ((-not $Repeat_until_user_presses_CTRL_C) -or ($script:ErrorFlag -eq $true)) # Press CTRL+C to stop } # #