#!/usr/bin/php $v) { if (!isset($addon[$k])) { $addon[$k] = $v; } } $addons[] = $addon; } //==========================================================================// // Addons to keep up to date, edit these. //==========================================================================// if (file_exists($config['addonlist'])) { include($config['addonlist']); } else { addAddon("Atlas", CURSE, "Atlas"); addAddon("AtlasLoot Enhanced", CURSE, "AtlasLoot-Enhanced", "AtlasLoot"); addAddon("Baud Bag", CURSE, "Baud-Bag", "BaudBag"); addAddon("Examiner", CURSE, "Examiner"); addAddon("FreeRefills", CURSE, "Free-Refills"); addAddon("FloAspectBar", CURSE, "Flo-Aspect-Bar"); addAddon("MobInfo-2 (includes MobHealth)", CURSE, "mob-info-2-includes-mob-health", "MobInfo2"); addAddon("MozzFullWorldMap(Fan's Update)", CURSE, "mozz-full-world-map-fans-update", "MozzFullWorldMap"); addAddon("Omen Threat Meter", CURSE, "Omen-Threat-Meter", "Omen"); //addAddon("PetInfo", CURSE, "pet-info"); addAddon("WarlockAlert", CURSE, "warlock-alert"); addAddon("QuestHelper", CURSE, "quest-helper"); addAddon("EasySerum", CURSE, "easyserum"); addAddon("DoTimer", CURSE, "do-timer"); addAddon("Recount", CURSE, "recount"); addAddon("Ripped", CURSE, "ripped"); addAddon("RippedAdvancedWarlockStrategy", CURSE, "arws"); addAddon("GroupCalendar", CURSE, "group-calendar"); addAddon("DoubleWide", WOWINTERFACE, 6887, '', array("FileVersionRegex" => "/## Title: DoubleWide \(v(.*)\)/", "AddToc" => true)); addAddon("EquipCompare", WOWINTERFACE, 4392); addAddon("AuditorFu", WOWINTERFACE, 5429, "FuBar_AuditorFu"); addAddon("LightHeaded", WOWINTERFACE, 7017); addAddon("TomTom", WOWINTERFACE, 7032); addAddon("Titan Panel", WOWINTERFACE, 8092, "Titan"); addAddon("CTMod", CUSTOM, 0, "CT_Core", array("downloadurl" => "http://www.ctmod.net/media/packages/Advanced.zip", "custom_url" => "http://www.ctmod.net/downloads/", "custom_versionregex" => "/This package contains:<\/b> CT_Core v(.*?),/", "FileVersionRegex" => '/^## Version: (.*) \(.*$/i')); addAddon("FeedOMatic", CUSTOM, 0, "GFW_FeedOMatic", array("custom_url" => "http://fizzwidget.com/notes/feedomatic/feed", "custom_versionregex" => "/Feed-O-Matic (.*?)<\/title>/", "custom_downloadregex" => "/<enclosure url=\"(http:\/\/fizzwidget.com\/downloads\/.*?)\" length/")); addAddon("Quest Log Level Patch", COSMOS, "QuestLogLevelPatch", "QuestLogLevelPatch"); addAddon("Enhanced Flight Map", CUSTOM, 0, "EnhancedFlightMap", array("custom_preurl" => "http://lysaddons.game-host.org/download/", "custom_url" => "http://lysaddons.game-host.org/efm/index.html", "custom_versionregex" => "/latest version of the addon <A HREF=\"..\/download\/EnhancedFlightMap-(.*?)\.zip\">Here<\/A>/", "custom_downloadregex" => "/latest version of the addon <A HREF=\"..\/download\/(EnhancedFlightMap-.*?\.zip)\">Here<\/A>/")); // addAddon("Auctioneer", MANUAL, "http://auctioneeraddon.com/dl/"); // addAddon("Auctioneer", CURSE, "auctioneer", "Auc-Advanced", array("FileVersionRegex" => "/## Version: (.*?) \(/")); addAddon("Auctioneer-Beta", CUSTOM, 0, "Auc-Advanced", array("FileVersionRegex" => "/## Version: (.*?) \(/", "custom_preurl" => "http://mirror01.auctioneeraddon.com/dl/", "custom_url" => "http://auctioneeraddon.com/dl/", "custom_versionregex" => "/<td class=\"beta\"><a href=\"\?dl=Packages(?:.*?)\/AuctioneerSuite-(.*?)\.zip\">AuctioneerSuite-(?:.*?)\.zip<\/a>/", "custom_downloadregex" => "/<td class=\"beta\"><a href=\"\?dl=(Packages.*\/AuctioneerSuite-.*?\.zip)\">AuctioneerSuite-(?:.*?)\.zip<\/a>/")); addAddon("Deadly Boss Mods", CUSTOM, 0, "DBM-Core", array("custom_preurl" => "http://www.deadlybossmods.com/", "custom_url" => "http://www.deadlybossmods.com/downloads.php", "custom_versionregex" => "/<tr><td><a href=\".*?\">DBM-Core\+WotLK Mods<\/a><\/td><td>(.*?)<\/td><td>/", "custom_downloadregex" => "/<tr><td><a href=\"(.*?)\">DBM-Core\+WotLK Mods<\/a><\/td><td>.*?<\/td><td>/")); addAddon('Improved Casting Bar', WOWUI, 3657, "improvedCastingBar"); // addAddon("AutoBindOnPickup", CURSE, 227); // addAddon("Notes", CURSE, 3628); // addAddon("SuperMacro", WOWUI, 1325); // addAddon("WeaponQuickSwap", WOWUI, 121); } //==========================================================================// // Functions for actual work, no need to edit below here. //==========================================================================// // Used for echoing define(CRLF, "\n"); define(T, "\t"); /** * Check each addon, and do work etc! */ function checkAddons() { global $addons, $config; foreach ($addons as &$addon) { if ($addon['type'] == MANUAL) { continue; } echo 'Found addon: ', $addon['name'], CRLF; getLocalVersion($addon); $tries = 0; do { echo '.'; getRemoteData($addon); $tries++; } while ((!isset($addon['newversion']) || $addon['newversion'] == '') && $tries < 2); echo T, ' Local Version: "', trim($addon['myversion']), '"', CRLF; echo T, 'Remote Version: "', trim($addon['newversion']), '"', CRLF; echo T, ' Download URL: "', trim($addon['downloadurl']), '"', ' [', $addon['type'], ']', CRLF; $my = trim($addon['myversion']); $new = trim($addon['newversion']); if ($my != $new) { echo T, '[Needs Update]', CRLF; } else if ($config['downloadall']) { echo T, '[Forced Update]', CRLF; } } echo '=====================================', CRLF; echo 'Needing Update:', CRLF; $downloads = array(); foreach ($addons as $a) { if ($addon['type'] == MANUAL) { continue; } $my = trim($a['myversion']); $new = trim($a['newversion']); if ($new == "" && !$config['downloadblank']) { echo T, $a['name'], ' -> Unable to find current version.', CRLF; } else if ($a['downloadurl'] == "") { echo T, $a['name'], ' -> Unable to find download URL.', CRLF; } else if ($my != $new || $config['downloadall']) { echo T, $a['name'], ' ("', $my, '" != "', $new, '") [', $a['downloadurl'], ']', CRLF; $downloads[] = array("name" => $a['name'].'.zip', "url" => $a['downloadurl'], "version" => $new, "addon" => $a); } } echo '=====================================', CRLF; echo 'Updating:', CRLF; // Now download them! getAddons($downloads); // Cleanup execAndPrint('rm -Rfv AddOns/*.txt AddOns/*.zip*'); execAndPrint('chmod -Rf 755 '.$config['addondir']); // Remind about manual addons. $first = true; foreach ($addons as &$addon) { if ($addon['type'] == MANUAL) { if ($first) { echo CRLF, 'The following addons need checked manually:', CRLF; $first = false; } echo T, $addon['name'], ' -> '. $addon['id'], CRLF; } } } /** * Download/Install addons on linux. * * @param $downloads Array from checkAddons() with addons to get */ function getAddons($downloads) { if (PHP_OS == 'Linux' || PHP_OS == 'Darwin' || substr(PHP_OS, -3) == 'BSD') { getAddonsUnix($downloads); } else { echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@', CRLF; echo 'Error: This script only updates on unix-based OSs', CRLF; echo 'Your OS: ', PHP_OS, CRLF; echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@', CRLF; die(); } } /** * Prepare for download/unzip by finding the applications. * This uses "which" */ function prepareGet() { global $config; if (file_exists('/usr/bin/which') || file_exists('/bin/which')) { $which = file_exists('/usr/bin/which') ? '/usr/bin/which' : '/bin/which'; } else { echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@', CRLF; echo 'Error: This script was unable to figure out how to download on your OS.', CRLF; echo 'Your OS: ', PHP_OS, CRLF; echo 'Unable to find `which` (in either /usr/bin or /bin)', CRLF; echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@', CRLF; die(); } $wget = trim(`$which wget`); $curl = trim(`$which curl`); $fetch = trim(`$which fetch`); if ($wget != '') { $config['download_method'] = 'wget'; $config['download_app'] = $wget; } else if ($curl != '') { $config['download_method'] = 'curl'; $config['download_app'] = $curl; } else if ($fetch != '') { $config['download_method'] = 'fetch'; $config['download_app'] = $fetch; } else { echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@', CRLF; echo 'Error: This script was unable to figure out how to download on your OS.', CRLF; echo 'Your OS: ', PHP_OS, CRLF; echo 'Supported Methods:', CRLF; echo T, 'wget, curl, fetch', CRLF; echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@', CRLF; die(); } $unzip = trim(`$which unzip`); if ($unzip != '') { $config['unzip_method'] = 'unzip'; $config['unzip_app'] = $unzip; } else { echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@', CRLF; echo 'Error: This script was unable to figure out how to unzip on your OS.', CRLF; echo 'Your OS: ', PHP_OS, CRLF; echo 'Supported Methods:', CRLF; echo T, 'unzip', CRLF; echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@', CRLF; die(); } } /** * Download/Install addons on linux. * * @param $downloads Array from checkAddons() with addons to get */ function getAddonsUnix($downloads) { global $config; // Make sure we have the ability to download/unzip prepareGet(); chdir($config['addondir']); if (!file_exists($config['addondir'].'zipfiles')) { mkdir($config['addondir'].'zipfiles'); } foreach ($downloads as $dl) { if ($config['download_method'] == 'wget') { execAndPrint($config['download_app'].' "'.$dl['url'].'" -O "'.$dl['name'].'" 2>&1'); } else if ($config['download_method'] == 'curl') { execAndPrint($config['download_app'].' "'.$dl['url'].'" -# -o "'.$dl['name'].'" 2>&1'); } else if ($config['download_method'] == 'fetch') { execAndPrint($config['download_app'].' -o "'.$dl['name'].'" "'.$dl['url'].'" 2>&1'); } if ($config['unzip_method'] == 'unzip') { execAndPrint($config['unzip_app'].' -o "'.$dl['name'].'" -d "'.$config['addondir'].'" 2>&1'); } execAndPrint('/bin/mv -fv "'.$dl['name'].'" zipfiles 2>&1'); addNewVersion($dl['addon']); } } /** * Adds the verison number we think this addon is to the toc file. * This is used because some addons are crap and don't provide this data! * * We add the X-DF-Version and X-DF-Date params. * * @param $addon to add to! */ function addNewVersion($addon) { echo "Updating Toc for ".$addon." (".$addon['tocfile'].")".CRLF; $data = explode("\n", file_get_contents($addon['tocfile'])); foreach ($data as $line) { if (stristr($line, 'X-DF-Version') === False) { $newdata[] = trim($line); } if (stristr($line, '## Interface:') !== False) { $newdata[] = '## X-DF-Version: '.trim($addon['newversion']); $newdata[] = '## X-DF-Date: '.time().' ['.date('r').']'; } } file_put_contents($addon['tocfile'], implode("\n", $newdata)); } /** * Execute the given command and print the output from stdout as it happens * * @param $cmd Command to execute */ function execAndPrint($cmd) { echo "execAndPrint: ", $cmd, "\n"; appexec($cmd, $proc); fclose($proc['pipes'][0]); // Now close the process handle while (!feof($proc['pipes'][1])) { echo fread($proc['pipes'][1], 512); flush(); } fclose($proc['pipes'][1]); proc_close($proc['process']); } /** * Runs an application and puts the process and the pipes in the given array * $process['pipes'][0] is stdin * $process['pipes'][1] is stdout * * @param $path Patch to exec * @param $process Array where process pipes will be put * @return true/false on successful execution */ function appexec($path, &$process) { $descriptorspec = array(0 => array("pipe", "r"),1 => array("pipe", "w"),2 => array("file", "/dev/null", "a")); $process = array(); $process['process'] = proc_open($path, $descriptorspec, $process['pipes']); return is_resource($process['process']); } /** * Get the local version of the given addon. * This sets $addon['myversion']. * -3 = Local copy of Addon not found * -2 = TOC not found * -1 = Version not found. * * @param $addon Array with addon information */ function getLocalVersion(&$addon) { unset($addon['myversion']); unset($addon['toc']); unset($addon['dfversion']); if (!file_exists($addon['dir'])) { $addon['myversion'] = -3; return; } $toc = $addon['dir'].$addon['tocname'].'.toc'; if (!file_exists($toc)) { // Look for toc, it could have a different case -_- $found = false; if ($handle = opendir($addon['dir'])) { while (false !== ($file = readdir($handle))) { if (strtolower($file) == strtolower($addon['tocname'].'.toc')) { $toc = $addon['dir'].$file; $found = true; break; } } if (!$found) { $addon['myversion'] = -2; return; } } } $addon['tocfile'] = $toc; $lines = file($toc); foreach ($lines as $line) { $regex = (isset($addon['FileVersionRegex'])) ? $addon['FileVersionRegex'] : '/^## Version: (.*)$/i'; $dfversion = '/^## X-DF-Version: (.*)$/i'; $tocregex = '/^## Interface: (.*)$/i'; if (!isset($addon['myversion']) && preg_match($regex, $line, $matches)) { $addon['myversion'] = $matches[1]; } else if (!isset($addon['dfversion']) && preg_match($dfversion, $line, $matches)) { $addon['dfversion'] = $matches[1]; } else if (!isset($addon['toc']) && preg_match($tocregex, $line, $matches)) { $addon['toc'] = $matches[1]; } } if (isset($addon['myversion']) || isset($addon['dfversion'])) { if (isset($addon['AddToc'])) { $addon['myversion'] .= '-'.$addon['toc']; } if (isset($addon['dfversion'])) { $addon['myversion'] = $addon['dfversion']; } return $addon['myversion']; } $addon['myversion'] -1; } /** * Get the remote version/download url of the given addon * This populates $addon['newversion'] and $addon['downloadurl'] * * @param $addon Array with addon information */ function getRemoteData(&$addon) { Switch ($addon['type']) { case CURSE: $url = 'http://wow.curse.com/downloads/wow-addons/details/'.$addon['id'].'.aspx'; $preurl = 'http://wow.curse.com'; $mid = (isset($addon['VersionSubRegex'])) ? $addon['VersionSubRegex'] : '(?:'.preg_quote($addon['name']).' )?r?v?(?:ersion)?(.*?)' ; $versionregex = '/<a href="\/downloads\/wow-addons\/details\/.*?\/download\/[0-9]+.aspx">'.$mid.'<\/a>/i'; $downloadregex = '/<a title=".*?" class="button button-download" href="(\/downloads\/wow-addons\/details\/.*?\/download\/[0-9]+.aspx)"/i'; break; case WOWINTERFACE: $url = 'http://www.wowinterface.com/downloads/info'.$addon['id'].'.html'; $preurl = 'http://www.wowinterface.com'; $versionregex = '/<td class="alt2"><div class="infoboxfont1">Version:<\/div><\/td>.+?<td class="alt2"><div class="smallfont">r?v?(?:ersion)?(.*?)<\/div><\/td>/ims'; $addon['downloadurl'] = 'http://www.wowinterface.com/downloads/download'.$addon['id']; break; case WOWUI: $url = 'http://wowui.worldofwar.net/?p=mod&m='.$addon['id']; $addon['downloadurl'] = 'http://wowui.worldofwar.net/?p=download&m='.$addon['id']; $versionregex = '/<b>Download size:<\/b> (.*?)<br \/>Updated <b>(.*?)<\/b>/i'; break; case COSMOS: $url = 'http://www.cosmosui.org/addons.php?info='.$addon['id']; $preurl = 'http://www.cosmosui.org/'; $versionregex = '/<li>Revision: (.*)<\/li>/i'; $downloadregex = '/href="(download\.php\?t=addons&f=.*?)"/i'; break; case CUSTOM: $url = $addon['custom_url']; if (isset($addon['custom_preurl'])) { $preurl = $addon['custom_preurl']; } if (isset($addon['custom_versionregex'])) { $versionregex = $addon['custom_versionregex']; } if (isset($addon['custom_downloadregex'])) { $downloadregex = $addon['custom_downloadregex']; } break; default: return -1; break; } $context = stream_context_create(array('http' => array('timeout' => 5))); $page = @file_get_contents($url, false, $context); if ($page === false) { $addon['newversion'] = "Unknown"; $addon['downloadurl'] = ""; return; } if (isset($downloadregex)) { preg_match($downloadregex, $page, $matches); $addon['downloadurl'] = $matches[1]; if (isset($preurl)) { $addon['downloadurl'] = $preurl.$addon['downloadurl']; } Switch ($addon['type']) { case CURSE: $page2 = file_get_contents($addon['downloadurl']); $regex = '/<a class="button button-pop" href="(.*?)"><span>Manual Install<\/span>/'; preg_match($regex, $page2, $matches); $addon['downloadurl'] = html_entity_decode($matches[1]); if (!empty($addon['downloadurl'])) { $addon['downloadurl'] = $preurl.$addon['downloadurl']; } break; } } preg_match($versionregex, $page, $matches); Switch ($addon['type']) { case WOWUI: $addon['newversion'] = preg_replace('/\s/', '', $matches[1].$matches[2]); break; default: $addon['newversion'] = $matches[1]; } } // And begin! checkAddons(); ?>