By Mell Rosandich
-------------------------------------------------------
Setting up System values
-------------------------------------------------------
<system>
<basefolderpath>C:\Users\ServerAdmin\Desktop\AppVault</basefolderpath>
<datfolderpath>C:\Users\ServerAdmin\Desktop\dats</datfolderpath>
</system>
basefolderpath - where all doaloaded app are stored
datfolderpath - date file location, keeps versions and errors in files
-------------------------------------------------------
Setting up applications
-------------------------------------------------------
Each app you want to keep updated you need a appitem node in the applist.xml (or what ever file you pass as the config).
<appitem>
<appname>7zip</appname>
<checkversionurl>http://www.7-zip.org/</checkversionurl>
<checkversionregex matchnumber="1"><![CDATA[Download 7-Zip.(.*).\(.*\) for Windows]]></checkversionregex>
<checkdownloadurl>http://www.7-zip.org/download.html</checkdownloadurl>
<checkdownloadregex matchnumber="1"><![CDATA[<A.*?href="(.*x64\.msi)".*?>]]></checkdownloadregex>
<downloadurl use="checkdownloadurl" usereg="no"></downloadurl>
<downloadurlregex matchnumber="1"></downloadurlregex>
<saveasname useurlpart="yes"></saveasname>
<overridesavepath uncompress="no">C:\Users\ServerAdmin\Desktop\AppVault\test</overridesavepath>
<saverelativepath uncompress="no">7Zip</saverelativepath>
</appitem>
The way the script works is as follows:
checkversionurl - this node contains the http link to the site with the version number of the application
checkversionregex matchnumber="1" - When the URL is pulled we regex with this expression and take the matchednumer="which match by regex" and this is how we get version
checkdownloadurl - A url where the donload might be
checkdownloadregex matchnumber="1"- a regex to fetch nother link to the down load matchnumber="which match by regex" to use for the dowload, can go 1 level deeper
downloadurl use="checkdownloadurl" - when set to use "checkdownloadurl" nodes
[or]
downloadurl usereg="no" - the URL defined here is a direct link to the files.
[or]
downloadurl use="checkdownloadurl" usereg="yes" - we now have another page with a direct download URL and must regex to get it.
downloadurlregex matchnumber="1" - final regex to get the URL for download.
saveasname useurlpart="yes" - no data need will use the name of the file feched from the URL
saveasname useurlpart="no" - what ever you want to name the file
overridesavepath - if set will override the path where the file will be saved
saverelativepath - save to the location set in the system.basefolderpath \ appName\
Sample 1 Smartermail, direct download, version is regex
<appitem>
<appname>SmarterMail9</appname>
<checkversionurl>http://smartertools.com/smartermail/releasenotes/v9.aspx</checkversionurl>
<checkversionregex matchnumber="1"><![CDATA[Version (.*)\((.*)\)</h3>]]></checkversionregex>
<checkdownloadurl></checkdownloadurl>
<checkdownloadregex matchnumber="1"></checkdownloadregex>
<downloadurl usereg="no">http://smartertools.com/Download.aspx?Product=SmarterMail&File=MSIInstaller&Version=9&Location=Primary</downloadurl>
<downloadurlregex matchnumber="1"></downloadurlregex>
<saveasname useurlpart="no">Smartermail9.msi</saveasname>
<overridesavepath uncompress="no"></overridesavepath>
<saverelativepath uncompress="no">SmarterMail9</saverelativepath>
</appitem>
sample 2, notepad++, download URL changes per version. Version is regex
<appitem>
<appname>notepad</appname>
<checkversionurl>http://notepad-plus-plus.org/</checkversionurl>
<checkversionregex matchnumber="2"><![CDATA[<a.*>(.*)Current Version.*<span>(.*)</span>]]></checkversionregex>
<checkdownloadurl>http://notepad-plus-plus.org/</checkdownloadurl>
<checkdownloadregex matchnumber="1" ><![CDATA[<a.*?href="(.*)".*?>.*Current Version.*<span>(.*)</span>]]></checkdownloadregex>
<downloadurl use="checkdownloadurl" usereg="yes"></downloadurl>
<downloadurlregex matchnumber="1"><![CDATA[<a.*?href="(.*)".*?>.* zip package</a>]]></downloadurlregex>
<saveasname useurlpart="yes"></saveasname>
<overridesavepath uncompress="no"></overridesavepath>
<saverelativepath uncompress="yes">NotePad</saverelativepath>
</appitem>
----------------------------------------------
applist.xml
-----------------------
<applicationvault>
<system>
<basefolderpath>C:\Users\ServerAdmin\Desktop\AppVault</basefolderpath>
<datfolderpath>C:\Users\ServerAdmin\Desktop\dats</datfolderpath>
</system>
<appitem>
<appname>notepad</appname>
<checkversionurl>http://notepad-plus-plus.org/</checkversionurl>
<checkversionregex matchnumber="2"><![CDATA[<a.*>(.*)Current Version.*<span>(.*)</span>]]></checkversionregex>
<checkdownloadurl>http://notepad-plus-plus.org/</checkdownloadurl>
<checkdownloadregex matchnumber="1" ><![CDATA[<a.*?href="(.*)".*?>.*Current Version.*<span>(.*)</span>]]></checkdownloadregex>
<downloadurl use="checkdownloadurl" usereg="yes"></downloadurl>
<downloadurlregex matchnumber="1"><![CDATA[<a.*?href="(.*)".*?>.* zip package</a>]]></downloadurlregex>
<saveasname useurlpart="yes"></saveasname>
<overridesavepath uncompress="no"></overridesavepath>
<saverelativepath uncompress="yes">NotePad</saverelativepath>
</appitem>
<appitem>
<appname>7zip</appname>
<checkversionurl>http://www.7-zip.org/</checkversionurl>
<checkversionregex matchnumber="1"><![CDATA[Download 7-Zip.(.*).\(.*\) for Windows]]></checkversionregex>
<checkdownloadurl>http://www.7-zip.org/download.html</checkdownloadurl>
<checkdownloadregex matchnumber="1"><![CDATA[<A.*?href="(.*x64\.msi)".*?>]]></checkdownloadregex>
<downloadurl use="checkdownloadurl" usereg="no"></downloadurl>
<downloadurlregex matchnumber="1"></downloadurlregex>
<saveasname useurlpart="yes"></saveasname>
<overridesavepath uncompress="no">C:\Users\ServerAdmin\Desktop\AppVault\test</overridesavepath>
<saverelativepath uncompress="no">7Zip</saverelativepath>
</appitem>
<appitem>
<appname>SmarterMail10</appname>
<checkversionurl>http://smartertools.com/smartermail/mail-server-download.aspx</checkversionurl>
<checkversionregex matchnumber="1"><![CDATA[ SmarterMail 10.x \((.*)\)]]></checkversionregex>
<checkdownloadurl></checkdownloadurl>
<checkdownloadregex matchnumber="1"></checkdownloadregex>
<downloadurl usereg="no">http://smartertools.com/Download.aspx?Product=SmarterMail&File=MSIInstaller&Version=10&Location=Primary</downloadurl>
<downloadurlregex matchnumber="1"></downloadurlregex>
<saveasname useurlpart="no">Smartermail10.msi</saveasname>
<overridesavepath uncompress="no"></overridesavepath>
<saverelativepath uncompress="no">SmarterMail10</saverelativepath>
</appitem>
<appitem>
<appname>SmarterMail9</appname>
<checkversionurl>http://smartertools.com/smartermail/releasenotes/v9.aspx</checkversionurl>
<checkversionregex matchnumber="1"><![CDATA[Version (.*)\((.*)\)</h3>]]></checkversionregex>
<checkdownloadurl></checkdownloadurl>
<checkdownloadregex matchnumber="1"></checkdownloadregex>
<downloadurl usereg="no">http://smartertools.com/Download.aspx?Product=SmarterMail&File=MSIInstaller&Version=9&Location=Primary</downloadurl>
<downloadurlregex matchnumber="1"></downloadurlregex>
<saveasname useurlpart="no">Smartermail9.msi</saveasname>
<overridesavepath uncompress="no"></overridesavepath>
<saverelativepath uncompress="no">SmarterMail9</saverelativepath>
</appitem>
<appitem>
<appname>SmarterMail8</appname>
<checkversionurl>http://smartertools.com/smartermail/releasenotes/v8.aspx</checkversionurl>
<checkversionregex matchnumber="1"><![CDATA[Version (.*)\((.*)\)</h3>]]></checkversionregex>
<checkdownloadurl></checkdownloadurl>
<checkdownloadregex matchnumber="1"></checkdownloadregex>
<downloadurl usereg="no">http://smartertools.com/Download.aspx?Product=SmarterMail&File=MSIInstaller&Version=8&Location=Primary</downloadurl>
<downloadurlregex matchnumber="1"></downloadurlregex>
<saveasname useurlpart="no">Smartermail8.msi</saveasname>
<overridesavepath uncompress="no"></overridesavepath>
<saverelativepath uncompress="no">SmarterMail8</saverelativepath>
</appitem>
</applicationvault>
########################################################################
# Hostgator Application Repository Updater
# Version .1
# Created by: Mell Rosandich
########################################################################
Param([string]$config,[string]$debug)
#define the options and check for valid options.
if( $config.length -lt 1 ){Write-Host "-config not set switching to dev location. C:\Users\ServerAdmin\Desktop\applist.xml";$config="C:\Users\ServerAdmin\Desktop\applist.xml";}
if( $debug.length -lt 1 ){Write-Host "-debug not set. for more information use -debug 1, -debug -2";$debug = "0";}
if($debug -ne "0" -and $debug -ne "1" -and $debug -ne "2"){$debug = "0";}
if( Test-Path $config ){
try{
[xml]$DummyTest = Get-Content $config
}
catch{
#if we hit this then there is an error in the file
#could be bad formated XML
Write-Host "The config path you specified was not a well formed XML file."
exit;
}
}
else
{
Write-Host "The config path you specified doesn't exsist"
exit;
}
#Global Scoped vars
$global:basefolderpath
$global:datfolderpath
$global:debugoutput = $debug
function get-filehashmd5($fileIn) {
if($global:debugoutput -gt 1){write-host "function: get-filehashmd5 File:" $file}
$file = get-item -literalpath $fileIn
$hashstring = new-object System.Text.StringBuilder
$stream = $file.OpenRead()
if ($stream) {
foreach ($byte in $Provider.ComputeHash($stream)) {
[Void] $hashstring.Append($byte.ToString("X2"))
}
$stream.Close()
}
if($global:debugoutput -gt 0){write-host "File Hash: " $hashstring.ToString()}
return " " + $hashstring.ToString()
}#get-filehashmd5
#This will extract the verision number from the website you just need to pass the URL and a regexp to match the text and a match number
function pullURLRegMatch( [string]$inURL , [regex]$inReg, [int]$inMatchNumber){
if($global:debugoutput -gt 1){write-host "function: pullURLRegMatch URL:" $inURL ", RegExp: " $inReg ", Match: " $inMatchNumber}
[String]$result = $null
$wc = new-object System.Net.WebClient
$result = $wc.Downloadstring( $inURL)
[regex]$pattern = $inReg
if ($result -match $pattern)
{
return $matches[$inMatchNumber].trim()
}
return "not found"
}
#returns Hash if downloaded 0 if fail
function getFileFromURL([string]$inURL,[string]$inSavePath, [string]$doUncompress){
if($global:debugoutput -gt 1){write-host "function: getFileFromURL URL:" $inURL ", SavePath: " $inSavePath }
$RetVal = 1
$isValidPath = Test-Path $inSavePath
if($isValidPath){
Remove-Item $inSavePath
}
else
{
New-Item $inSavePath -type file -value "temp" -Force
Remove-Item $inSavePath
}
write-host "Started Downaloding"
try{
$webclient = New-Object System.Net.WebClient
$webclient.DownloadFile($inURL,$inSavePath)
}catch{return 0}
if($global:debugoutput -gt 0){write-host "Saved to: " $inSavePath}
write-host "End download"
if($global:debugoutput -gt 0){write-host "Uncompress: " $doUncompress}
$RetVal = get-filehashmd5( $inSavePath)
if($global:debugoutput -gt 0){write-host "getFileFromURL: Return Val: " $RetVal}
return $RetVal
}
function checkDatFilLocalVersion( [string]$AppName )
{
if($global:debugoutput -gt 1){write-host "function: checkDatFilLocalVersion AppName:" $AppName}
$DT = [DateTime]::Now
$FilePath = $global:datfolderpath + "\" + $AppName + ".xml"
write-host "File Path: " + $FilePath
$isValidPath = Test-Path $FilePath
if( $isValidPath ){
[xml]$LocalAppInfo = Get-Content $FilePath
$LocalAppInfo.application.lastchecked = [string]$DT
$LocalAppInfo.Save($FilePath)
return $LocalAppInfo.application.version
}
else
{
#lets make a blank xml cos this app is new.
$BlankAppInfoXML = "<application>`n`t<name>"+$AppName+"</name>`n`t<filename>"+$AppName+"</filename>`n`t<filemd5>0</filemd5>`n`t<version>0</version>`n`t<lastchecked></lastchecked>`n`t<lastupdated></lastupdated>`n`t<errors>`n`t`t" + '<error time="'+$DT+'">no application.xml (created this file)</error>' + "`n`t</errors>`n</application>"
New-Item $FilePath -type file -value $BlankAppInfoXML
return 0
}
}
function updateApplicationXML( [string]$AppName, [string]$FileNameSavedAs, [string]$versionFromURL, [string]$FileHashMD){
if($global:debugoutput -gt 1){write-host "function: updateApplicationXML AppName:" $AppName ", FileName:" $FileNameSavedAs ", versionFromURL:" $versionFromURL ", fileHash:" $FileHashMD }
$DT = [DateTime]::Now
$FilePath = $global:datfolderpath + "\" + $AppName + ".xml"
[xml]$LocalAppInfo = Get-Content $FilePath
$LocalAppInfo.application.version = $versionFromURL
$LocalAppInfo.application.filename = $FileNameSavedAs
$LocalAppInfo.application.lastupdated = [string]$DT
$LocalAppInfo.application.lastchecked = [string]$DTc
$PIECES=$FileHashMD.split(" ")
$NUMBEROFPIECES=$PIECES.Count
$NewHash=$PIECES[$NumberOfPieces-1]
$LocalAppInfo.application.filemd5 = $NewHash
$LocalAppInfo.Save($FilePath)
}
[xml]$ApplicatList = Get-Content $config
$global:basefolderpath = $ApplicatList.applicationvault.system.basefolderpath
$global:datfolderpath = $ApplicatList.applicationvault.system.datfolderpath
$Provider = new-object System.Security.Cryptography.MD5CryptoServiceProvider
foreach( $appitem in $ApplicatList.applicationvault.appitem)
{
Write-Host "Checking Application:" $appitem.appname
#Write-Host $appitem.checkversionurl
#Write-Host $appitem.checkversionregex."#cdata-section"
#Write-Host $appitem.saverelativepath."#text"
$RelativePathAdd = ""
if($appitem.saverelativepath."#text" -ne $null){
$RelativePathAdd = $appitem.saverelativepath."#text" + "\"
if($global:debugoutput -gt 0){write-host "Set Relative Path part to:" $RelativePathAdd}
}
$doUncompress = "no"
$versionFromURL = pullURLRegMatch $appitem.checkversionurl $appitem.checkversionregex."#cdata-section" $appitem.checkversionregex."matchnumber"
$versionFromDAT = checkDatFilLocalVersion $appitem.appname
if($global:debugoutput -gt 0){write-host "Version From URL:" $versionFromURL "Version From Local XML:" $versionFromDAT }
write-host "Site Version: " $versionFromURL
if( $versionFromURL -ne $versionFromDAT ){
if($global:debugoutput -gt 0){write-host "Stepping into Version Different logic"}
if($appitem.checkdownloadurl -ne ""){
$downloadlink = pullURLRegMatch $appitem.checkdownloadurl $appitem.checkdownloadregex."#cdata-section" $appitem.checkdownloadregex."matchnumber"
write-host "Versions are differnt"
if($global:debugoutput -gt 0){write-host "Stepping into CheckDownLoad URL logic"}
if($appitem.downloadurl."use" -eq "checkdownloadurl"){
if($global:debugoutput -gt 0){write-host "Stepping into CheckDownLoad URL 'Use' checkdownloadurl logic"}
if($appitem.downloadurl."usereg" -eq "yes"){
if($global:debugoutput -gt 0){write-host "Stepping into downloadURL 'Use' regex=yes logic"}
$FullURL = $appitem.checkdownloadurl+$downloadlink
$Directdownloadlink = pullURLRegMatch $FullURL $appitem.downloadurlregex."#cdata-section" $appitem.downloadurlregex."matchnumber"
if( $appitem.saveasname."useurlpart" -eq "yes" ){
$DlFilename = $Directdownloadlink.split("/")
$FileNameSavedAs = $DlFilename[$DlFilename.length-1]
if($global:debugoutput -gt 0){write-host "Save As Name: using URL parts"}
}
else
{
$FileNameSavedAs = $appitem.saveasname."#text"
if($global:debugoutput -gt 0){write-host "Save As Name: using saveasname from config"}
}
if($appitem.overridesavepath."#text" -ne $null){
$FullSavePath = $appitem.overridesavepath."#text" + '\' + $FileNameSavedAs
if($global:debugoutput -gt 0){write-host "Save Path: using override path: " $FullSavePath}
$doUncompress = $appitem.overridesavepath."uncompress"
}
else
{
$FullSavePath = $global:basefolderpath + '\' + $RelativePathAdd + $FileNameSavedAs
if($global:debugoutput -gt 0){write-host "Save Path: using Relative path: " $FullSavePath}
$doUncompress = $appitem.saverelativepath."uncompress"
}
$filedlMdHash = getFileFromURL $Directdownloadlink $FullSavePath $doUncompress
write-host "File Path:" $FullSavePath
if( $filedlMdHash -ne 0 ){
#Update App XML
updateApplicationXML $appitem.appname $FileNameSavedAs $versionFromURL $filedlMdHash
}
else
{
Write-host "Error Saving Download"
}
}
else
{
#We didn't use regex to get the link, it was grabed in the first regex attempt
if($global:debugoutput -gt 0){write-host "Stepping into downloadURL 'Use' regex=no logic"}
write-host "Direct Link " $downloadlink
if( $appitem.saveasname."useurlpart" -eq "yes" ){
$DlFilename = $downloadlink.split("/")
$FileNameSavedAs = $DlFilename[$DlFilename.length-1]
if($global:debugoutput -gt 0){write-host "Save As Name: using URL parts"}
}
else
{
$FileNameSavedAs = $appitem.saveasname."#text"
if($global:debugoutput -gt 0){write-host "Save As Name: using saveasname from config"}
}
if($appitem.overridesavepath."#text" -ne $null ){
$FullSavePath = $appitem.overridesavepath."#text" + '\' + $FileNameSavedAs
if($global:debugoutput -gt 0){write-host "Save Path: using override path: " $FullSavePath}
$doUncompress = $appitem.overridesavepath."uncompress"
}
else
{
$FullSavePath = $global:basefolderpath + '\' + $RelativePathAdd + $FileNameSavedAs
if($global:debugoutput -gt 0){write-host "Save Path: using Relative path: " $FullSavePath}
$doUncompress = $appitem.saverelativepath."uncompress"
}
$filedlMdHash = getFileFromURL $downloadlink $FullSavePath $doUncompress
write-host "File Path:" $FullSavePath
if( $filedlMdHash -ne 0 ){
#Update App XML
updateApplicationXML $appitem.appname $FileNameSavedAs $versionFromURL $filedlMdHash
}
else
{
Write-host "Error Saving Download"
}
}
}
}#end if $appitem.checkdownloadurl -ne ""
else
{
#This is a direct download from a staic URL
if($global:debugoutput -gt 0){write-host "Stepping into downloadURL direct link download"}
if( $appitem.saveasname."useurlpart" -eq "yes" )
{
$DlFilename = $downloadlink.split("/")
$FileNameSavedAs = $DlFilename[$DlFilename.length-1]
if($global:debugoutput -gt 0){write-host "Save As Name: using URL parts"}
}
else
{
$FileNameSavedAs = $appitem.saveasname."#text"
if($global:debugoutput -gt 0){write-host "Save As Name: using saveasname from config"}
}
if($appitem.overridesavepath."#text" -ne $null){
$FullSavePath = $appitem.overridesavepath + '\' + $FileNameSavedAs
if($global:debugoutput -gt 0){write-host "Save Path: using override path: " $FullSavePath}
$doUncompress = $appitem.overridesavepath."uncompress"
}
else
{
$FullSavePath = $global:basefolderpath + '\' + $RelativePathAdd + $FileNameSavedAs
if($global:debugoutput -gt 0){write-host "Save Path: using Relative path: " $FullSavePath}
$doUncompress = $appitem.saverelativepath."uncompress"
}
$filedlMdHash = getFileFromURL $appitem.downloadurl."#text" $FullSavePath $doUncompress
write-host "File Path:" $FullSavePath
if( $filedlMdHash -ne 0 ){
#Update App XML
updateApplicationXML $appitem.appname $FileNameSavedAs $versionFromURL $filedlMdHash
}
else
{
Write-host "Error Saving Download"
}
}
}
else
{
write-host $appitem.appname is up to date: Nothing done.
}
write-host "-------------------------------------------------------------------------------------"
}