diff --git a/archive/community.applications-2023.09.23-x86_64-1.txz b/archive/community.applications-2023.09.23-x86_64-1.txz new file mode 100644 index 00000000..d2e9cf94 Binary files /dev/null and b/archive/community.applications-2023.09.23-x86_64-1.txz differ diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/Apps.page b/source/community.applications/usr/local/emhttp/plugins/community.applications/Apps.page index 0495a4e3..9520467a 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/Apps.page +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/Apps.page @@ -43,7 +43,7 @@ $firstRun = is_file($caPaths['warningAccepted']) ? "false" : "true"; $pluginWarning = is_file($caPaths['pluginWarning']) ? "true": "false"; if ( ! is_file($caPaths['docker_cfg']) ) { - exec("logger -t 'Community Applications' 'Fatal Flash Drive Error: /boot/config/docker.cfg does not exist'"); + exec("logger -t 'Community Applications' 'Fatal Flash Drive Error: /boot/config/docker.cfg does not exist'"); } $unRaidSettings = parse_ini_file($caPaths['unRaidVersion']); @@ -57,64 +57,64 @@ exec("cd /usr/local/emhttp/plugins/$plugin/ && md5sum -c ca.md5",$output,$md5Err $previousLocale = $_COOKIE["locale"] ?? ""; switch ($theme) { - case 'black': - $swalBackground = "black"; - $tooltipsterContent = "#f2f2f2"; - $chartGrid = "#222222"; - break; - case 'azure': - $swalBackground = "white"; - $tooltipsterContent = "#101010"; - $chartGrid = "#dddddd"; - break; - case 'gray': - $swalBackground = "black"; - $tooltipsterContent = "#f2f2f2"; - $chartGrid = "#222222"; - break; - case 'white': - $swalBackground = "white"; - $tooltipsterContent = "#101010"; - $chartGrid = "#dddddd"; - break; - default: - $swalBackground = "black"; // default to black. This should only be when someone adds a new theme. It is NOT the default that the OS uses - $tooltipsterContent = "#f2f2f2"; - $chartGrid = "#222222"; - break; + case 'black': + $swalBackground = "black"; + $tooltipsterContent = "#f2f2f2"; + $chartGrid = "#222222"; + break; + case 'azure': + $swalBackground = "white"; + $tooltipsterContent = "#101010"; + $chartGrid = "#dddddd"; + break; + case 'gray': + $swalBackground = "black"; + $tooltipsterContent = "#f2f2f2"; + $chartGrid = "#222222"; + break; + case 'white': + $swalBackground = "white"; + $tooltipsterContent = "#101010"; + $chartGrid = "#dddddd"; + break; + default: + $swalBackground = "black"; // default to black. This should only be when someone adds a new theme. It is NOT the default that the OS uses + $tooltipsterContent = "#f2f2f2"; + $chartGrid = "#222222"; + break; } if ( is_file($caPaths['addConverted']) ) - $dockerConvertFlag = "true"; + $dockerConvertFlag = "true"; else - $dockerConvertFlag = "false"; + $dockerConvertFlag = "false"; $date = (date("n/d")); $startupDisplayed = is_file($caPaths['startupDisplayed']) ? "true" : "false"; if ( $startupDisplayed == "true" && ($_COOKIE['ca_languageSwitch'] ?? false) ) - $killCookie = "true"; + $killCookie = "true"; else - $killCookie = "false"; + $killCookie = "false"; $dockerSearchActive = is_file($caPaths['dockerSearchActive']); // Only check for updates to containers / plugins max once per hour exec("mkdir -p {$caPaths['tempFiles']}"); if ( ($cfg['updateCheck'] == "yes") && ( (time() - @filemtime($caPaths['updateTime']) ) > 3600 ) ) { - touch($caPaths['updateTime']); - exec("echo '/usr/local/emhttp/plugins/community.applications/scripts/checkForUpdates.php >/dev/null 2>&1' | at now -M >/dev/null 2>&1"); + touch($caPaths['updateTime']); + exec("echo '/usr/local/emhttp/plugins/community.applications/scripts/checkForUpdates.php >/dev/null 2>&1' | at now -M >/dev/null 2>&1"); } if ( is_file("/var/run/dockerd.pid") && is_dir("/proc/".@file_get_contents("/var/run/dockerd.pid")) ) { - $caSettings['dockerRunning'] = true; + $caSettings['dockerRunning'] = true; } else { - $caSettings['dockerSearch'] = "no"; - unset($caSettings['dockerRunning']); + $caSettings['dockerSearch'] = "no"; + unset($caSettings['dockerRunning']); } if ( is_file($caPaths['docker_cfg']) ) - getAllInfo(true,false); + getAllInfo(true,false); // Check memory to see if CA's minimums are met (4G same as base OS) - Test is actually for 2.5G though @@ -125,11 +125,11 @@ $CArequirementsNOTmet = $memoryInstalled[0] < 2500000; function tr($string,$ret=false) { - $string = str_replace('"',""",str_replace("'","'",_($string))); - if ( $ret ) - return $string; - else - echo $string; + $string = str_replace('"',""",str_replace("'","'",_($string))); + if ( $ret ) + return $string; + else + echo $string; } ?> @@ -137,14 +137,14 @@ function tr($string,$ret=false) { - + diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/CA_notices.page b/source/community.applications/usr/local/emhttp/plugins/community.applications/CA_notices.page index 72aac3ad..f4b1f880 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/CA_notices.page +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/CA_notices.page @@ -20,52 +20,52 @@ $caCFG = parse_plugin_cfg("community.applications"); \ No newline at end of file diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/ca.md5 b/source/community.applications/usr/local/emhttp/plugins/community.applications/ca.md5 index 6ac0de23..d15f7967 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/ca.md5 +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/ca.md5 @@ -1,25 +1,25 @@ -3580e1add40be466f0d5b1df14508e6c ./Apps.page -106b521c1feebda4d7b3f558cc016cda ./CA_notices.page -4a79f2efa7a8c2f9e41d1050edded513 ./ca_settings.page +dbcd3253215c5714e7fb165f02bc782c ./Apps.page +385834d91dc8758bfcd5d34f1c3e530e ./CA_notices.page +2c2a1b7d148fe51ee38813d1a0e71589 ./ca_settings.page 01ed7990078dee7cecfeda9a4e49377e ./default.cfg -638f22a3dfc75940b2caa27c3e612e28 ./include/exec.php -6315b71595f089a310861ef2e1954d84 ./include/helpers.php -3f6ae4c4fef3077dd2ca45117f780846 ./include/paths.php +2fbccf0c27923cf5089e496993deecfc ./include/exec.php +4bb86b8d71180b347444e9cb88f5d3d3 ./include/helpers.php +343e1d26129551fc142b09b5d6e10503 ./include/paths.php 7234caf6800479df03abb222aaedaca5 ./javascript/libraries.js 71f911a818d88d3d567f8a2898094ee2 ./README.md -ec075d8b9758ba00bda9b02c4692f972 ./scripts/checkForUpdates.php +75b7153ce7582b7234c466c5f73c8528 ./scripts/checkForUpdates.php 99a9d58a49a7f6812f18bd4be2b563b9 ./scripts/checkForUpdates.sh -d4a279514f1adc0e4e2bbfbab5a82a61 ./scripts/dockerConvert.php -6ee3b2cdf12209893af916ab0b42152a ./scripts/installMulti.php -e549862bcbeed9843b6bdcdb83e1bf3f ./scripts/installMultiPlugin.php +529bd09b91b233715167f6c283103ef7 ./scripts/dockerConvert.php +4a0281e185e5d9bc69e8e1ce92443724 ./scripts/installMulti.php +d60714f36cea666eb0fcb752820dabaf ./scripts/installMultiPlugin.php 524afab04ca930f59117a846f819fb2f ./scripts/installPluginUpdate.sh -53879be89ce610c57922c1f25ba2b1d2 ./scripts/installUpdate.php +112064897f06b818e595a63e30a37f11 ./scripts/installUpdate.php 5846421e95b475e1156c3f68164ccc4f ./scripts/languageInstall.sh -cf717f6cb60ff17a7c924c330ed16343 ./scripts/notices.php -ed42a35b3524b55e2024cdd56a795733 ./scripts/pluginInstall.php -f2a86fd875cb73bb095388e69ca035fd ./scripts/showStatistics.php +a1cb6e1930f2ad689ce9e7fc2e39c846 ./scripts/notices.php +4c67ce0b8366c15356d21768ea515d56 ./scripts/pluginInstall.php +47456eef0760a57a792177ea065358c3 ./scripts/showStatistics.php 4425f8fd4ef662a7dc65cee01de3e419 ./scripts/updatePLG.sh -5c088a7cf82229cb64edfd4c415a84a0 ./scripts/updatePluginSupport.php -62498637efe9636e86f805ff75ab327b ./skins/Narrow/css.php -d642a25efb891e51471fc4c7636da885 ./skins/Narrow/skin.html -07c9450dea50baca4b0f9f52526018b1 ./skins/Narrow/skin.php +52355989c2bec01cfd55fe619588a033 ./scripts/updatePluginSupport.php +5a0516d49f7c195b67e4d61913b12bd5 ./skins/Narrow/css.php +53cc49a55e85e0ec20dcd94b965821ed ./skins/Narrow/skin.html +c93b47ea6190783d3d8747721f21439a ./skins/Narrow/skin.php diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/ca_settings.page b/source/community.applications/usr/local/emhttp/plugins/community.applications/ca_settings.page index cf83d971..8aebab00 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/ca_settings.page +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/ca_settings.page @@ -20,29 +20,29 @@ require_once "$docroot/plugins/$plugin/include/helpers.php"; $cfg = parse_plugin_cfg($plugin); function tr($string,$ret=false) { - if ( function_exists("_") ) - $string = str_replace('"',""",str_replace("'","'",_($string))); - if ( $ret ) - return $string; - else - echo $string; + if ( function_exists("_") ) + $string = str_replace('"',""",str_replace("'","'",_($string))); + if ( $ret ) + return $string; + else + echo $string; } ?> @@ -51,58 +51,58 @@ function debug() { _(Hide Deprecated Applications)_: : + + + > _(Hide Incompatible Applications)_: : + + + > _(Allow install of second instance)_: : + + + > _(Automatically open the sidebar)_: : + + + > _(Allow CA to check for updates to applications)_: : - + + + + > _(Disable Mouse Wheel Page Changes)_: : - + + + + > _(Allow CA to send any emergency notifications)_: : + + + >
>
@@ -111,18 +111,18 @@ _(Allow CA to send any emergency notifications)_: _(Save CA debugging information)_: : - + + + + > _(Enable developer mode)_: : - + + + + > diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/include/exec.php b/source/community.applications/usr/local/emhttp/plugins/community.applications/include/exec.php index bb4dd88c..b447daa7 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/include/exec.php +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/include/exec.php @@ -41,23 +41,23 @@ $caSettings['maxPerPage'] = (integer)$caSettings['maxPerPage'] ?: "24"; // Ha if ( $caSettings['maxPerPage'] < 24 ) $caSettings['maxPerPage'] = 24; if ( ! is_file($caPaths['warningAccepted']) ) - $caSettings['NoInstalls'] = true; + $caSettings['NoInstalls'] = true; $DockerClient = new DockerClient(); $DockerTemplates = new DockerTemplates(); if ( is_file("/var/run/dockerd.pid") && is_dir("/proc/".@file_get_contents("/var/run/dockerd.pid")) ) { - $caSettings['dockerRunning'] = true; + $caSettings['dockerRunning'] = true; } else { - $caSettings['dockerSearch'] = "no"; - $caSettings['dockerRunning'] = false; + $caSettings['dockerSearch'] = "no"; + $caSettings['dockerRunning'] = false; } @mkdir($caPaths['tempFiles'],0777,true); if ( !is_dir($caPaths['templates-community']) ) { - @mkdir($caPaths['templates-community'],0777,true); - @unlink($caPaths['community-templates-info']); + @mkdir($caPaths['templates-community'],0777,true); + @unlink($caPaths['community-templates-info']); } debug("POST CALLED ({$_POST['action']})\n".print_r($_POST,true)); @@ -65,9 +65,9 @@ debug("POST CALLED ({$_POST['action']})\n".print_r($_POST,true)); $sortOrder = readJsonFile($caPaths['sortOrder']); if ( ! $sortOrder ) { - $sortOrder['sortBy'] = "Name"; - $sortOrder['sortDir'] = "Up"; - writeJsonFile($caPaths['sortOrder'],$sortOrder); + $sortOrder['sortBy'] = "Name"; + $sortOrder['sortDir'] = "Up"; + writeJsonFile($caPaths['sortOrder'],$sortOrder); } $GLOBALS['templates'] = readJsonFile($caPaths['community-templates-info']); @@ -79,989 +79,989 @@ $GLOBALS['templates'] = readJsonFile($caPaths['community-templates-info']); ############################################ switch ($_POST['action']) { - case 'get_content': - get_content(); - break; - case 'force_update': - force_update(); - break; - case 'display_content': - display_content(); - break; - case 'dismiss_warning': - dismiss_warning(); - break; - case 'dismiss_plugin_warning': - dismiss_plugin_warning(); - break; - case 'previous_apps': - previous_apps(); - break; - case 'remove_application': - remove_application(); - break; - case 'updatePLGstatus': - updatePLGstatus(); - break; - case 'uninstall_docker': - uninstall_docker(); - break; - case "pinApp": - pinApp(); - break; - case "areAppsPinned": - areAppsPinned(); - break; - case "pinnedApps": - pinnedApps(); - break; - case 'displayTags': - displayTags(); - break; - case 'statistics': - statistics(); - break; - case 'populateAutoComplete': - populateAutoComplete(); - break; - case 'caChangeLog': - caChangeLog(); - break; - case 'get_categories': - get_categories(); - break; - case 'getPopupDescription': - getPopupDescription(); - break; - case 'getRepoDescription': - getRepoDescription(); - break; - case 'createXML': - createXML(); - break; - case 'switchLanguage': - switchLanguage(); - break; - case 'remove_multiApplications': - remove_multiApplications(); - break; - case 'getCategoriesPresent': - getCategoriesPresent(); - break; - case 'toggleFavourite': - toggleFavourite(); - break; - case 'getFavourite': - getFavourite(); - break; - case 'changeSortOrder': - changeSortOrder(); - break; - case 'getSortOrder': - getSortOrder(); - break; - case 'defaultSortOrder': - defaultSortOrder(); - break; - case 'javascriptError': - javascriptError(); - break; - case 'onStartupScreen': - onStartupScreen(); - break; - case 'convert_docker': - convert_docker(); - break; - case 'search_dockerhub': - search_dockerhub(); - break; - case 'getPortsInUse': - postReturn(["portsInUse"=>getPortsInUse()]); - break; - case 'getLastUpdate': - postReturn(['lastUpdate'=>getLastUpdate(getPost("ID","Unknown"))]); - break; - case 'changeMaxPerPage': - changeMaxPerPage(); - break; - case 'enableActionCentre': - enableActionCentre(); - break; - case 'var_dump': - break; - case 'checkRequirements': - checkRequirements(); - break; - case 'saveMultiPluginPending': - saveMultiPluginPending(); - break; - case 'downloadStatistics': - downloadStatistics(); - break; - case 'checkPluginInProgress': - checkPluginInProgress(); - break; - ############################################### - # Return an error if the action doesn't exist # - ############################################### - default: - postReturn(["error"=>"Unknown post action {$_POST['action']}"]); - break; + case 'get_content': + get_content(); + break; + case 'force_update': + force_update(); + break; + case 'display_content': + display_content(); + break; + case 'dismiss_warning': + dismiss_warning(); + break; + case 'dismiss_plugin_warning': + dismiss_plugin_warning(); + break; + case 'previous_apps': + previous_apps(); + break; + case 'remove_application': + remove_application(); + break; + case 'updatePLGstatus': + updatePLGstatus(); + break; + case 'uninstall_docker': + uninstall_docker(); + break; + case "pinApp": + pinApp(); + break; + case "areAppsPinned": + areAppsPinned(); + break; + case "pinnedApps": + pinnedApps(); + break; + case 'displayTags': + displayTags(); + break; + case 'statistics': + statistics(); + break; + case 'populateAutoComplete': + populateAutoComplete(); + break; + case 'caChangeLog': + caChangeLog(); + break; + case 'get_categories': + get_categories(); + break; + case 'getPopupDescription': + getPopupDescription(); + break; + case 'getRepoDescription': + getRepoDescription(); + break; + case 'createXML': + createXML(); + break; + case 'switchLanguage': + switchLanguage(); + break; + case 'remove_multiApplications': + remove_multiApplications(); + break; + case 'getCategoriesPresent': + getCategoriesPresent(); + break; + case 'toggleFavourite': + toggleFavourite(); + break; + case 'getFavourite': + getFavourite(); + break; + case 'changeSortOrder': + changeSortOrder(); + break; + case 'getSortOrder': + getSortOrder(); + break; + case 'defaultSortOrder': + defaultSortOrder(); + break; + case 'javascriptError': + javascriptError(); + break; + case 'onStartupScreen': + onStartupScreen(); + break; + case 'convert_docker': + convert_docker(); + break; + case 'search_dockerhub': + search_dockerhub(); + break; + case 'getPortsInUse': + postReturn(["portsInUse"=>getPortsInUse()]); + break; + case 'getLastUpdate': + postReturn(['lastUpdate'=>getLastUpdate(getPost("ID","Unknown"))]); + break; + case 'changeMaxPerPage': + changeMaxPerPage(); + break; + case 'enableActionCentre': + enableActionCentre(); + break; + case 'var_dump': + break; + case 'checkRequirements': + checkRequirements(); + break; + case 'saveMultiPluginPending': + saveMultiPluginPending(); + break; + case 'downloadStatistics': + downloadStatistics(); + break; + case 'checkPluginInProgress': + checkPluginInProgress(); + break; + ############################################### + # Return an error if the action doesn't exist # + ############################################### + default: + postReturn(["error"=>"Unknown post action {$_POST['action']}"]); + break; } # DownloadApplicationFeed MUST BE CALLED prior to DownloadCommunityTemplates in order for private repositories to be merged correctly. function DownloadApplicationFeed() { - global $caPaths, $caSettings, $statistics; + global $caPaths, $caSettings, $statistics; - $info = readJsonFile($caPaths['info']); - exec("rm -rf '{$caPaths['tempFiles']}'"); - @mkdir($caPaths['templates-community'],0777,true); + $info = readJsonFile($caPaths['info']); + exec("rm -rf '{$caPaths['tempFiles']}'"); + @mkdir($caPaths['templates-community'],0777,true); - $currentFeed = "Primary Server"; - $downloadURL = randomFile(); - $ApplicationFeed = download_json($caPaths['application-feed'],$downloadURL,"",20); - if ( (! is_array($ApplicationFeed['applist'])) || empty($ApplicationFeed['applist']) ) { - $currentFeed = "Backup Server"; - $ApplicationFeed = download_json($caPaths['application-feedBackup'],$downloadURL); - } - @unlink($downloadURL); - if ( (! is_array($ApplicationFeed['applist'])) || empty($ApplicationFeed['applist']) ) { - @unlink($caPaths['currentServer']); - ca_file_put_contents($caPaths['appFeedDownloadError'],$downloadURL); - return false; - } - ca_file_put_contents($caPaths['currentServer'],$currentFeed); - $i = 0; - $lastUpdated['last_updated_timestamp'] = $ApplicationFeed['last_updated_timestamp']; - writeJsonFile($caPaths['lastUpdated-old'],$lastUpdated); + $currentFeed = "Primary Server"; + $downloadURL = randomFile(); + $ApplicationFeed = download_json($caPaths['application-feed'],$downloadURL,"",20); + if ( (! is_array($ApplicationFeed['applist'])) || empty($ApplicationFeed['applist']) ) { + $currentFeed = "Backup Server"; + $ApplicationFeed = download_json($caPaths['application-feedBackup'],$downloadURL); + } + @unlink($downloadURL); + if ( (! is_array($ApplicationFeed['applist'])) || empty($ApplicationFeed['applist']) ) { + @unlink($caPaths['currentServer']); + ca_file_put_contents($caPaths['appFeedDownloadError'],$downloadURL); + return false; + } + ca_file_put_contents($caPaths['currentServer'],$currentFeed); + $i = 0; + $lastUpdated['last_updated_timestamp'] = $ApplicationFeed['last_updated_timestamp']; + writeJsonFile($caPaths['lastUpdated-old'],$lastUpdated); - $invalidXML = []; - foreach ($ApplicationFeed['applist'] as $o) { - if ( (! isset($o['Repository']) ) && (! isset($o['Plugin']) ) && (!isset($o['Language']) )){ - $invalidXML[] = $o; - continue; - } - $o = addMissingVars($o); + $invalidXML = []; + foreach ($ApplicationFeed['applist'] as $o) { + if ( (! isset($o['Repository']) ) && (! isset($o['Plugin']) ) && (!isset($o['Language']) )){ + $invalidXML[] = $o; + continue; + } + $o = addMissingVars($o); - if ( $o['CategoryList'] ) { - foreach ($o['CategoryList'] as $cat) { - $cat = str_replace("-",":",$cat); - if ( ! strpos($cat,":") ) - $cat .= ":"; - $o['Category'] .= "$cat "; - } - } - if ( $o['Category'] === null ) - $o['Category'] = ""; - $o['Category'] = trim($o['Category']); - if ( ! $o['Category'] ) - $o['Category'] = "Other:"; + if ( $o['CategoryList'] ) { + foreach ($o['CategoryList'] as $cat) { + $cat = str_replace("-",":",$cat); + if ( ! strpos($cat,":") ) + $cat .= ":"; + $o['Category'] .= "$cat "; + } + } + if ( $o['Category'] === null ) + $o['Category'] = ""; + $o['Category'] = trim($o['Category']); + if ( ! $o['Category'] ) + $o['Category'] = "Other:"; - if ( $o['RecommendedRaw'] ) { - $o['RecommendedDate'] = strtotime($o['RecommendedRaw']); - $o['Category'] .= " spotlight:"; - } + if ( $o['RecommendedRaw'] ) { + $o['RecommendedDate'] = strtotime($o['RecommendedRaw']); + $o['Category'] .= " spotlight:"; + } - if ( $o['Language'] ) { - $o['Category'] = "Language:"; - $o['Compatible'] = true; - $o['Repository'] = "library/"; - } + if ( $o['Language'] ) { + $o['Category'] = "Language:"; + $o['Compatible'] = true; + $o['Repository'] = "library/"; + } - # Move the appropriate stuff over into a CA data file - $o['ID'] = $i; - $o['Displayable'] = true; - $o['Author'] = getAuthor($o); - $o['DockerHubName'] = strtolower($o['Name']); - $o['RepoName'] = $o['Repo']; - $o['SortAuthor'] = $o['Author']; - $o['SortName'] = str_replace("-"," ",$o['Name']); - $o['SortName'] = preg_replace('/\s+/',' ',$o['SortName']); - $o['random'] = rand(); + # Move the appropriate stuff over into a CA data file + $o['ID'] = $i; + $o['Displayable'] = true; + $o['Author'] = getAuthor($o); + $o['DockerHubName'] = strtolower($o['Name']); + $o['RepoName'] = $o['Repo']; + $o['SortAuthor'] = $o['Author']; + $o['SortName'] = str_replace("-"," ",$o['Name']); + $o['SortName'] = preg_replace('/\s+/',' ',$o['SortName']); + $o['random'] = rand(); - if ( $o['CAComment'] ) { - $tmpComment = explode("‍",$o['CAComment']); // non printable delimiter character - $o['CAComment'] = ""; - foreach ($tmpComment as $comment) { - if ( $comment ) - $o['CAComment'] .= tr($comment)." "; - } - } - if ( $o['RequiresFile'] ) $o['RequiresFile'] = trim($o['RequiresFile']); - if ( $o['Requires'] ) $o['Requires'] = trim($o['Requires']); + if ( $o['CAComment'] ) { + $tmpComment = explode("‍",$o['CAComment']); // non printable delimiter character + $o['CAComment'] = ""; + foreach ($tmpComment as $comment) { + if ( $comment ) + $o['CAComment'] .= tr($comment)." "; + } + } + if ( $o['RequiresFile'] ) $o['RequiresFile'] = trim($o['RequiresFile']); + if ( $o['Requires'] ) $o['Requires'] = trim($o['Requires']); - $des = $o['OriginalOverview'] ?? $o['Overview']; - $des = $o['Language'] ? $o['Description'] : $des; - if ( ! $des && $o['Description'] ) $des = $o['Description']; - if ( ! $o['Language'] ) { - $des = str_replace(["[","]"],["<",">"],$des); - $des = str_replace("\n"," ",$des); - $des = html_entity_decode($des); - } + $des = $o['OriginalOverview'] ?? $o['Overview']; + $des = $o['Language'] ? $o['Description'] : $des; + if ( ! $des && $o['Description'] ) $des = $o['Description']; + if ( ! $o['Language'] ) { + $des = str_replace(["[","]"],["<",">"],$des); + $des = str_replace("\n"," ",$des); + $des = html_entity_decode($des); + } - if ( $o['PluginURL'] ) { - $o['Author'] = $o['PluginAuthor']; - $o['Repository'] = $o['PluginURL']; - } + if ( $o['PluginURL'] ) { + $o['Author'] = $o['PluginAuthor']; + $o['Repository'] = $o['PluginURL']; + } - $o['Blacklist'] = $o['CABlacklist'] ? true : $o['Blacklist']; - $o['MinVer'] = max([$o['MinVer'],$o['UpdateMinVer']]); - $tag = explode(":",$o['Repository']); - if (! isset($tag[1])) - $tag[1] = "latest"; - $o['Path'] = $caPaths['templates-community']."/".alphaNumeric($o['RepoName'])."/".alphaNumeric($o['Author'])."-".alphaNumeric($o['Name'])."-{$tag[1]}"; - if ( file_exists($o['Path'].".xml") ) { - $o['Path'] .= "(1)"; - } - $o['Path'] .= ".xml"; + $o['Blacklist'] = $o['CABlacklist'] ? true : $o['Blacklist']; + $o['MinVer'] = max([$o['MinVer'],$o['UpdateMinVer']]); + $tag = explode(":",$o['Repository']); + if (! isset($tag[1])) + $tag[1] = "latest"; + $o['Path'] = $caPaths['templates-community']."/".alphaNumeric($o['RepoName'])."/".alphaNumeric($o['Author'])."-".alphaNumeric($o['Name'])."-{$tag[1]}"; + if ( file_exists($o['Path'].".xml") ) { + $o['Path'] .= "(1)"; + } + $o['Path'] .= ".xml"; - $o = fixTemplates($o); - if ( ! $o ) continue; + $o = fixTemplates($o); + if ( ! $o ) continue; - if ( is_array($o['trends']) && count($o['trends']) > 1 ) { - $o['trendDelta'] = round(end($o['trends']) - $o['trends'][0],4); - $o['trendAverage'] = round(array_sum($o['trends'])/count($o['trends']),4); - } + if ( is_array($o['trends']) && count($o['trends']) > 1 ) { + $o['trendDelta'] = round(end($o['trends']) - $o['trends'][0],4); + $o['trendAverage'] = round(array_sum($o['trends'])/count($o['trends']),4); + } - $o['Category'] = str_replace("Status:Beta","",$o['Category']); # undo changes LT made to my xml schema for no good reason - $o['Category'] = str_replace("Status:Stable","",$o['Category']); - $myTemplates[$i] = $o; + $o['Category'] = str_replace("Status:Beta","",$o['Category']); # undo changes LT made to my xml schema for no good reason + $o['Category'] = str_replace("Status:Stable","",$o['Category']); + $myTemplates[$i] = $o; - if ( ! $o['DonateText'] && ($ApplicationFeed['repositories'][$o['RepoName']]['DonateText'] ?? false) ) - $o['DonateText'] = $ApplicationFeed['repositories'][$o['RepoName']]['DonateText']; - if ( ! $o['DonateLink'] && ($ApplicationFeed['repositories'][$o['RepoName']]['DonateLink'] ?? false) ) - $o['DonateLink'] = $ApplicationFeed['repositories'][$o['RepoName']]['DonateLink']; + if ( ! $o['DonateText'] && ($ApplicationFeed['repositories'][$o['RepoName']]['DonateText'] ?? false) ) + $o['DonateText'] = $ApplicationFeed['repositories'][$o['RepoName']]['DonateText']; + if ( ! $o['DonateLink'] && ($ApplicationFeed['repositories'][$o['RepoName']]['DonateLink'] ?? false) ) + $o['DonateLink'] = $ApplicationFeed['repositories'][$o['RepoName']]['DonateLink']; - $ApplicationFeed['repositories'][$o['RepoName']]['downloads'] = $ApplicationFeed['repositories'][$o['RepoName']]['downloads'] ?? 0; - $ApplicationFeed['repositories'][$o['RepoName']]['trending'] = $ApplicationFeed['repositories'][$o['RepoName']]['trending'] ?? 0; + $ApplicationFeed['repositories'][$o['RepoName']]['downloads'] = $ApplicationFeed['repositories'][$o['RepoName']]['downloads'] ?? 0; + $ApplicationFeed['repositories'][$o['RepoName']]['trending'] = $ApplicationFeed['repositories'][$o['RepoName']]['trending'] ?? 0; - $ApplicationFeed['repositories'][$o['RepoName']]['downloads']++; - $ApplicationFeed['repositories'][$o['RepoName']]['trending'] += $o['trending']; - if ( ! $o['ModeratorComment'] == "Duplicated Template" ) { - if ( $ApplicationFeed['repositories'][$o['RepoName']]['FirstSeen'] ?? false) { - if ( $o['FirstSeen'] < $ApplicationFeed['repositories'][$o['RepoName']]['FirstSeen']) - $ApplicationFeed['repositories'][$o['RepoName']]['FirstSeen'] = $o['FirstSeen']; - } else { - $ApplicationFeed['repositories'][$o['RepoName']]['FirstSeen'] = $o['FirstSeen']; - } - } - if ( is_array($o['Branch']) ) { - if ( ! isset($o['Branch'][0]) ) { - $tmp = $o['Branch']; - unset($o['Branch']); - $o['Branch'][] = $tmp; - } - foreach($o['Branch'] as $branch) { - $i = ++$i; - $subBranch = $o; - $masterRepository = explode(":",$subBranch['Repository']); - $o['BranchDefault'] = $masterRepository[1] ?? null; - $subBranch['Repository'] = $masterRepository[0].":". ($branch['Tag'] ?? ""); #This takes place before any xml elements are overwritten by additional entries in the branch, so you can actually change the repo the app draws from - $subBranch['BranchName'] = $branch['Tag'] ?? ""; - $subBranch['BranchDescription'] = $branch['TagDescription'] ? $branch['TagDescription'] : $branch['Tag']; - $subBranch['Path'] = $caPaths['templates-community']."/".$i.".xml"; - $subBranch['Displayable'] = false; - $subBranch['ID'] = $i; - $subBranch['Overview'] = $o['OriginalOverview'] ?: $o['Overview']; - $subBranch['Description'] = $o['OriginalDescription'] ?: $o['Description']; - $replaceKeys = array_diff(array_keys($branch),["Tag","TagDescription"]); - foreach ($replaceKeys as $key) { - $subBranch[$key] = $branch[$key]; - } - unset($subBranch['Branch']); - $myTemplates[$i] = $subBranch; - $o['BranchID'][] = $i; - } - } - unset($o['Branch']); - $myTemplates[$o['ID']] = $o; - $i = ++$i; - if ( $o['OriginalOverview'] ) { - $o['Overview'] = $o['OriginalOverview']; - unset($o['OriginalOverview']); - unset($o['Description']); - } - if ( $o['OriginalDescription'] ) { - $o['Description'] = $o['OriginalDescription']; - unset($o['OriginalDescription']); - } - } + $ApplicationFeed['repositories'][$o['RepoName']]['downloads']++; + $ApplicationFeed['repositories'][$o['RepoName']]['trending'] += $o['trending']; + if ( ! $o['ModeratorComment'] == "Duplicated Template" ) { + if ( $ApplicationFeed['repositories'][$o['RepoName']]['FirstSeen'] ?? false) { + if ( $o['FirstSeen'] < $ApplicationFeed['repositories'][$o['RepoName']]['FirstSeen']) + $ApplicationFeed['repositories'][$o['RepoName']]['FirstSeen'] = $o['FirstSeen']; + } else { + $ApplicationFeed['repositories'][$o['RepoName']]['FirstSeen'] = $o['FirstSeen']; + } + } + if ( is_array($o['Branch']) ) { + if ( ! isset($o['Branch'][0]) ) { + $tmp = $o['Branch']; + unset($o['Branch']); + $o['Branch'][] = $tmp; + } + foreach($o['Branch'] as $branch) { + $i = ++$i; + $subBranch = $o; + $masterRepository = explode(":",$subBranch['Repository']); + $o['BranchDefault'] = $masterRepository[1] ?? null; + $subBranch['Repository'] = $masterRepository[0].":". ($branch['Tag'] ?? ""); #This takes place before any xml elements are overwritten by additional entries in the branch, so you can actually change the repo the app draws from + $subBranch['BranchName'] = $branch['Tag'] ?? ""; + $subBranch['BranchDescription'] = $branch['TagDescription'] ? $branch['TagDescription'] : $branch['Tag']; + $subBranch['Path'] = $caPaths['templates-community']."/".$i.".xml"; + $subBranch['Displayable'] = false; + $subBranch['ID'] = $i; + $subBranch['Overview'] = $o['OriginalOverview'] ?: $o['Overview']; + $subBranch['Description'] = $o['OriginalDescription'] ?: $o['Description']; + $replaceKeys = array_diff(array_keys($branch),["Tag","TagDescription"]); + foreach ($replaceKeys as $key) { + $subBranch[$key] = $branch[$key]; + } + unset($subBranch['Branch']); + $myTemplates[$i] = $subBranch; + $o['BranchID'][] = $i; + } + } + unset($o['Branch']); + $myTemplates[$o['ID']] = $o; + $i = ++$i; + if ( $o['OriginalOverview'] ) { + $o['Overview'] = $o['OriginalOverview']; + unset($o['OriginalOverview']); + unset($o['Description']); + } + if ( $o['OriginalDescription'] ) { + $o['Description'] = $o['OriginalDescription']; + unset($o['OriginalDescription']); + } + } - if ( $invalidXML ) - writeJsonFile($caPaths['invalidXML_txt'],$invalidXML); - else - @unlink($caPaths['invalidXML_txt']); + if ( $invalidXML ) + writeJsonFile($caPaths['invalidXML_txt'],$invalidXML); + else + @unlink($caPaths['invalidXML_txt']); - writeJsonFile($caPaths['community-templates-info'],$myTemplates); - $GLOBALS['templates'] = $myTemplates; - writeJsonFile($caPaths['categoryList'],$ApplicationFeed['categories']); + writeJsonFile($caPaths['community-templates-info'],$myTemplates); + $GLOBALS['templates'] = $myTemplates; + writeJsonFile($caPaths['categoryList'],$ApplicationFeed['categories']); - foreach ($ApplicationFeed['repositories'] as &$repo) { - if ( $repo['downloads'] ?? false ) { - $repo['trending'] = $repo['trending'] / $repo['downloads']; - } - } + foreach ($ApplicationFeed['repositories'] as &$repo) { + if ( $repo['downloads'] ?? false ) { + $repo['trending'] = $repo['trending'] / $repo['downloads']; + } + } - writeJsonFile($caPaths['repositoryList'],$ApplicationFeed['repositories']); - writeJsonFile($caPaths['extraBlacklist'],$ApplicationFeed['blacklisted']); - writeJsonFile($caPaths['extraDeprecated'],$ApplicationFeed['deprecated']); + writeJsonFile($caPaths['repositoryList'],$ApplicationFeed['repositories']); + writeJsonFile($caPaths['extraBlacklist'],$ApplicationFeed['blacklisted']); + writeJsonFile($caPaths['extraDeprecated'],$ApplicationFeed['deprecated']); - updatePluginSupport($myTemplates); - touch($caPaths['haveTemplates']); + updatePluginSupport($myTemplates); + touch($caPaths['haveTemplates']); - return true; + return true; } function updatePluginSupport($templates) { - $plugins = glob("/boot/config/plugins/*.plg"); + $plugins = glob("/boot/config/plugins/*.plg"); - foreach ($plugins as $plugin) { - $pluginURL = @plugin("pluginURL",$plugin); - $pluginEntry = searchArray($templates,"PluginURL",$pluginURL); - if ( $pluginEntry === false ) { - $pluginEntry = searchArray($templates,"PluginURL",str_replace("https://raw.github.com/","https://raw.githubusercontent.com/",$pluginURL)); - } - if ( $pluginEntry !== false && $templates[$pluginEntry]['PluginURL']) { - $xml = simplexml_load_file($plugin); - if ( ! $templates[$pluginEntry]['Support'] ) { - continue; - } - if ( @plugin("support",$plugin) !== $templates[$pluginEntry]['Support'] ) { - // remove existing support attribute if it exists - if ( @plugin("support",$plugin) ) { - $existing_support = $xml->xpath("//PLUGIN/@support"); - foreach ($existing_support as $node) { - unset($node[0]); - } - } - $xml->addAttribute("support",$templates[$pluginEntry]['Support']); - $dom = new DOMDocument('1.0'); - $dom->preserveWhiteSpace = false; - $dom->formatOutput = true; - $dom->loadXML($xml->asXML()); - ca_file_put_contents($plugin, $dom->saveXML()); - } - } - } + foreach ($plugins as $plugin) { + $pluginURL = @plugin("pluginURL",$plugin); + $pluginEntry = searchArray($templates,"PluginURL",$pluginURL); + if ( $pluginEntry === false ) { + $pluginEntry = searchArray($templates,"PluginURL",str_replace("https://raw.github.com/","https://raw.githubusercontent.com/",$pluginURL)); + } + if ( $pluginEntry !== false && $templates[$pluginEntry]['PluginURL']) { + $xml = simplexml_load_file($plugin); + if ( ! $templates[$pluginEntry]['Support'] ) { + continue; + } + if ( @plugin("support",$plugin) !== $templates[$pluginEntry]['Support'] ) { + // remove existing support attribute if it exists + if ( @plugin("support",$plugin) ) { + $existing_support = $xml->xpath("//PLUGIN/@support"); + foreach ($existing_support as $node) { + unset($node[0]); + } + } + $xml->addAttribute("support",$templates[$pluginEntry]['Support']); + $dom = new DOMDocument('1.0'); + $dom->preserveWhiteSpace = false; + $dom->formatOutput = true; + $dom->loadXML($xml->asXML()); + ca_file_put_contents($plugin, $dom->saveXML()); + } + } + } } function getConvertedTemplates() { - global $caPaths, $caSettings, $statistics; + global $caPaths, $caSettings, $statistics; # Start by removing any pre-existing private (converted templates) - $templates = &$GLOBALS['templates']; + $templates = &$GLOBALS['templates']; - if ( empty($templates) ) return false; + if ( empty($templates) ) return false; - $myTemplates = []; - foreach ($templates as $template) { - if ( ! $template['Private'] ) - $myTemplates[] = $template; - } - $appCount = count($myTemplates); - $i = $appCount; + $myTemplates = []; + foreach ($templates as $template) { + if ( ! $template['Private'] ) + $myTemplates[] = $template; + } + $appCount = count($myTemplates); + $i = $appCount; - if ( ! is_dir($caPaths['convertedTemplates']) ) { - writeJsonFile($caPaths['community-templates-info'],$myTemplates); - $GLOBALS['templates'] = $myTemplates; - return; - } + if ( ! is_dir($caPaths['convertedTemplates']) ) { + writeJsonFile($caPaths['community-templates-info'],$myTemplates); + $GLOBALS['templates'] = $myTemplates; + return; + } - $privateTemplates = glob($caPaths['convertedTemplates']."*/*.xml"); - foreach ($privateTemplates as $templateXML) { - $o = addMissingVars(readXmlFile($templateXML)); - if ( ! $o['Repository'] ) continue; + $privateTemplates = glob($caPaths['convertedTemplates']."*/*.xml"); + foreach ($privateTemplates as $templateXML) { + $o = addMissingVars(readXmlFile($templateXML)); + if ( ! $o['Repository'] ) continue; - $o['Private'] = true; - $o['RepoName'] = basename(pathinfo($templateXML,PATHINFO_DIRNAME))." Repository"; - $o['ID'] = $i; - $o['Displayable'] = true; - $o['Date'] = ( $o['Date'] ) ? strtotime( $o['Date'] ) : 0; - $o['SortAuthor'] = $o['Author']; - $o['Compatible'] = versionCheck($o); - $o['Description'] = $o['Description'] ?: $o['Overview']; - $o['CardDescription'] = strip_tags(trim(markdown($o['Description']))); - $o = fixTemplates($o); - $myTemplates[$i] = $o; - $i = ++$i; - } - writeJsonFile($caPaths['community-templates-info'],$myTemplates); - $GLOBALS['templates'] = $myTemplates; + $o['Private'] = true; + $o['RepoName'] = basename(pathinfo($templateXML,PATHINFO_DIRNAME))." Repository"; + $o['ID'] = $i; + $o['Displayable'] = true; + $o['Date'] = ( $o['Date'] ) ? strtotime( $o['Date'] ) : 0; + $o['SortAuthor'] = $o['Author']; + $o['Compatible'] = versionCheck($o); + $o['Description'] = $o['Description'] ?: $o['Overview']; + $o['CardDescription'] = strip_tags(trim(markdown($o['Description']))); + $o = fixTemplates($o); + $myTemplates[$i] = $o; + $i = ++$i; + } + writeJsonFile($caPaths['community-templates-info'],$myTemplates); + $GLOBALS['templates'] = $myTemplates; } ############################# # Selects an app of the day # ############################# function appOfDay($file) { - global $caPaths,$caSettings,$sortOrder; + global $caPaths,$caSettings,$sortOrder; - $max = is_file("/boot/config/plugins/unlimited-width.plg") ? 12 : 5; - $appOfDay = null; + $max = is_file("/boot/config/plugins/unlimited-width.plg") ? 12 : 5; + $appOfDay = null; - switch ($caSettings['startup']) { - case "random": - $oldAppDay = @filemtime($caPaths['appOfTheDay']); - $oldAppDay = $oldAppDay ?: 1; - $oldAppDay = intval($oldAppDay / 86400); - $currentDay = intval(time() / 86400); - if ( $oldAppDay == $currentDay ) { - $appOfDay = readJsonFile($caPaths['appOfTheDay']); - $flag = false; - foreach ($appOfDay as $testApp) { - if ( ! checkRandomApp($file[$testApp]) ) { - $flag = true; - break; - } - } - if ( $flag ) - $appOfDay = null; - } - if ( ! $appOfDay ) { - shuffle($file); - foreach ($file as $template) { - if ( ! checkRandomApp($template) ) continue; - $appOfDay[] = $template['ID']; - if (count($appOfDay) == $max) break; - } - } - writeJsonFile($caPaths['appOfTheDay'],$appOfDay); + switch ($caSettings['startup']) { + case "random": + $oldAppDay = @filemtime($caPaths['appOfTheDay']); + $oldAppDay = $oldAppDay ?: 1; + $oldAppDay = intval($oldAppDay / 86400); + $currentDay = intval(time() / 86400); + if ( $oldAppDay == $currentDay ) { + $appOfDay = readJsonFile($caPaths['appOfTheDay']); + $flag = false; + foreach ($appOfDay as $testApp) { + if ( ! checkRandomApp($file[$testApp]) ) { + $flag = true; + break; + } + } + if ( $flag ) + $appOfDay = null; + } + if ( ! $appOfDay ) { + shuffle($file); + foreach ($file as $template) { + if ( ! checkRandomApp($template) ) continue; + $appOfDay[] = $template['ID']; + if (count($appOfDay) == $max) break; + } + } + writeJsonFile($caPaths['appOfTheDay'],$appOfDay); - break; - case "onlynew": - $sortOrder['sortBy'] = "FirstSeen"; - $sortOrder['sortDir'] = "Down"; - usort($file,"mySort"); - foreach ($file as $template) { - if ( ! $template['Compatible'] == "true" && $caSettings['hideIncompatible'] == "true" ) continue; - if ( $template['FirstSeen'] > 1538357652 ) { - if ( checkRandomApp($template) ) { - $appOfDay[] = $template['ID']; - if ( count($appOfDay) == $max ) break; - } - } - } - break; - case "topperforming": - $sortOrder['sortBy'] = "trending"; - $sortOrder['sortDir'] = "Down"; - usort($file,"mySort"); - $repos = []; - foreach ($file as $template) { - if ( ! is_array($template['trends']) ) continue; - if ( count($template['trends']) < 6 ) continue; - if ( startsWith($template['Repository'],"ich777/steamcmd") ) continue; // because a ton of apps all use the same repo - if ( $template['trending'] && ($template['downloads'] > 100000) ) { - if ( checkRandomApp($template) ) { - if ( in_array($template['Repository'],$repos) ) - continue; - $repos[] = $template['Repository']; - $appOfDay[] = $template['ID']; - if ( count($appOfDay) == $max ) break; - } - } - } - break; - case "trending": - $sortOrder['sortBy'] = "trendDelta"; - $sortOrder['sortDir'] = "Down"; - usort($file,"mySort"); - $repos = []; - foreach ($file as $template) { - if ( count($template['trends'] ) < 3 ) continue; - if ( startsWith($template['Repository'],"ich777/steamcmd") ) continue; // because a ton of apps all use the same repo` - if ( $template['trending'] && ($template['downloads'] > 10000) ) { - if ( checkRandomApp($template) ) { - if ( in_array($template['Repository'],$repos) ) - continue; - $repos[] = $template['Repository']; - $appOfDay[] = $template['ID']; - if ( count($appOfDay) == $max ) break; - } - } - } - break; - case "spotlight": - $sortOrder['sortBy'] = "RecommendedDate"; - $sortOrder['sortDir'] = "Down"; - usort($file,"mySort"); - foreach($file as $template) { - if ($template['RecommendedDate']) { - if ( ! checkRandomApp($template) ) continue; + break; + case "onlynew": + $sortOrder['sortBy'] = "FirstSeen"; + $sortOrder['sortDir'] = "Down"; + usort($file,"mySort"); + foreach ($file as $template) { + if ( ! $template['Compatible'] == "true" && $caSettings['hideIncompatible'] == "true" ) continue; + if ( $template['FirstSeen'] > 1538357652 ) { + if ( checkRandomApp($template) ) { + $appOfDay[] = $template['ID']; + if ( count($appOfDay) == $max ) break; + } + } + } + break; + case "topperforming": + $sortOrder['sortBy'] = "trending"; + $sortOrder['sortDir'] = "Down"; + usort($file,"mySort"); + $repos = []; + foreach ($file as $template) { + if ( ! is_array($template['trends']) ) continue; + if ( count($template['trends']) < 6 ) continue; + if ( startsWith($template['Repository'],"ich777/steamcmd") ) continue; // because a ton of apps all use the same repo + if ( $template['trending'] && ($template['downloads'] > 100000) ) { + if ( checkRandomApp($template) ) { + if ( in_array($template['Repository'],$repos) ) + continue; + $repos[] = $template['Repository']; + $appOfDay[] = $template['ID']; + if ( count($appOfDay) == $max ) break; + } + } + } + break; + case "trending": + $sortOrder['sortBy'] = "trendDelta"; + $sortOrder['sortDir'] = "Down"; + usort($file,"mySort"); + $repos = []; + foreach ($file as $template) { + if ( count($template['trends'] ) < 3 ) continue; + if ( startsWith($template['Repository'],"ich777/steamcmd") ) continue; // because a ton of apps all use the same repo` + if ( $template['trending'] && ($template['downloads'] > 10000) ) { + if ( checkRandomApp($template) ) { + if ( in_array($template['Repository'],$repos) ) + continue; + $repos[] = $template['Repository']; + $appOfDay[] = $template['ID']; + if ( count($appOfDay) == $max ) break; + } + } + } + break; + case "spotlight": + $sortOrder['sortBy'] = "RecommendedDate"; + $sortOrder['sortDir'] = "Down"; + usort($file,"mySort"); + foreach($file as $template) { + if ($template['RecommendedDate']) { + if ( ! checkRandomApp($template) ) continue; - $appOfDay[] = $template['ID']; - if ( count($appOfDay) == $max ) break; - } else { - break; - } - } - break; - case "featured": - $containers = getAllInfo(); - $sortOrder['sortBy'] = "Featured"; - $sortOrder['sortDir'] = "Down"; - usort($file,"mySort"); - foreach($file as $template) { - if ( ! isset($template['Featured'] ) ) - break; - // Don't show it if the plugin is installed + $appOfDay[] = $template['ID']; + if ( count($appOfDay) == $max ) break; + } else { + break; + } + } + break; + case "featured": + $containers = getAllInfo(); + $sortOrder['sortBy'] = "Featured"; + $sortOrder['sortDir'] = "Down"; + usort($file,"mySort"); + foreach($file as $template) { + if ( ! isset($template['Featured'] ) ) + break; + // Don't show it if the plugin is installed - if ( $template['PluginURL'] && is_file("/var/log/plugins/".basename($template['PluginURL'])) ) { - if ( checkPluginUpdate($template['PluginURL']) ) { - $appOfDay[] = $template['ID']; - if ( count($appOfDay) == $max ) - break; - continue; - } - } - if ( $template['PluginURL'] && is_file("/var/log/plugins/".basename($template['PluginURL'])) && ! $template['UninstallOnly']) - continue; - // Don't show it if the container is installed - if ( ! $template['PluginURL'] ) { - if ( $caSettings['dockerRunning'] ) { - $selected = false; + if ( $template['PluginURL'] && is_file("/var/log/plugins/".basename($template['PluginURL'])) ) { + if ( checkPluginUpdate($template['PluginURL']) ) { + $appOfDay[] = $template['ID']; + if ( count($appOfDay) == $max ) + break; + continue; + } + } + if ( $template['PluginURL'] && is_file("/var/log/plugins/".basename($template['PluginURL'])) && ! $template['UninstallOnly']) + continue; + // Don't show it if the container is installed + if ( ! $template['PluginURL'] ) { + if ( $caSettings['dockerRunning'] ) { + $selected = false; - foreach ($containers as $testDocker) { - if ( ($template['Repository'] == $testDocker['Image'] ) || ($template['Repository'].":latest" == $testDocker['Image']) || (str_replace(":latest","",$template['Repository']) == $testDocker['Image']) ) { - $selected = true; - break; - } - } - } - if ( $selected ) - continue; - } - $appOfDay[] = $template['ID']; - if ( count($appOfDay) == $max ) break; - } - } - return $appOfDay ?: []; + foreach ($containers as $testDocker) { + if ( ($template['Repository'] == $testDocker['Image'] ) || ($template['Repository'].":latest" == $testDocker['Image']) || (str_replace(":latest","",$template['Repository']) == $testDocker['Image']) ) { + $selected = true; + break; + } + } + } + if ( $selected ) + continue; + } + $appOfDay[] = $template['ID']; + if ( count($appOfDay) == $max ) break; + } + } + return $appOfDay ?: []; } ##################################################### # Checks selected app for eligibility as app of day # ##################################################### function checkRandomApp($test) { - global $caSettings; + global $caSettings; - if ( $test['Name'] == "Community Applications" ) return false; - if ( $test['BranchName'] ) return false; - if ( ! $test['Displayable'] ) return false; - if ( ! $test['Compatible'] && $caSettings['hideIncompatible'] == "true" ) return false; - if ( $test['Blacklist'] ) return false; - if ( $test['Deprecated'] && ( $caSettings['hideDeprecated'] == "true" ) ) return false; + if ( $test['Name'] == "Community Applications" ) return false; + if ( $test['BranchName'] ) return false; + if ( ! $test['Displayable'] ) return false; + if ( ! $test['Compatible'] && $caSettings['hideIncompatible'] == "true" ) return false; + if ( $test['Blacklist'] ) return false; + if ( $test['Deprecated'] && ( $caSettings['hideDeprecated'] == "true" ) ) return false; - return true; + return true; } ############################################################## # Gets the repositories that are listed on any given display # ############################################################## function displayRepositories() { - global $caPaths, $caSettings; + global $caPaths, $caSettings; - $repositories = readJsonFile($caPaths['repositoryList']); - if ( is_file($caPaths['community-templates-allSearchResults']) ) { - $temp = readJsonFile($caPaths['community-templates-allSearchResults']); - $templates = &$temp['community']; - } else { - $temp = readJsonFile($caPaths['community-templates-displayed']); - $templates = &$temp['community']; - } - if ( is_file($caPaths['startupDisplayed']) ) { - $templates = &$GLOBALS['templates']; - } - $templates = $templates ?: []; - $allRepos = []; - $bio = []; - foreach ($templates as $template) { - if ( $template['Blacklist'] ) continue; - if ( $template['Deprecated'] && $caSettings['hideDeprecated'] == "true" ) continue; - if ( ! $template['Compatible'] && $caSettings['hideIncompatible'] == "true" ) continue; - $repoName = $template['RepoName']; - if ( ! $repoName ) continue; - if ( $repoName == $caSettings['favourite'] ) { - $fav = $repositories[$repoName]; - $fav['RepositoryTemplate'] = true; - $fav['RepoName'] = $repoName; - $fav['SortName'] = $repoName; - } else { - if ( isset($repositories[$repoName]['bio']) ) { - $bio[$repoName] = $repositories[$repoName]; - $bio[$repoName] = $repositories[$repoName]; - $bio[$repoName]['RepositoryTemplate'] = true; - $bio[$repoName]['RepoName'] = $repoName; - $bio[$repoName]['SortName'] = $repoName; - $bio[$repoName] = addMissingVars($bio[$repoName]); - } else { - $allRepos[$repoName] = $repositories[$repoName]; - $allRepos[$repoName]['RepositoryTemplate'] = true; - $allRepos[$repoName]['RepoName'] = $repoName; - $allRepos[$repoName]['SortName'] = $repoName; - $allRepos[$repoName] = addMissingVars($allRepos[$repoName]); - } - } - } - usort($bio,"mySort"); - usort($allRepos,"mySort"); - $allRepos = array_merge($bio,$allRepos); - if ( isset($fav) ) - array_unshift($allRepos,$fav); - $file['community'] = $allRepos; - writeJsonFile($caPaths['repositoriesDisplayed'],$file); + $repositories = readJsonFile($caPaths['repositoryList']); + if ( is_file($caPaths['community-templates-allSearchResults']) ) { + $temp = readJsonFile($caPaths['community-templates-allSearchResults']); + $templates = &$temp['community']; + } else { + $temp = readJsonFile($caPaths['community-templates-displayed']); + $templates = &$temp['community']; + } + if ( is_file($caPaths['startupDisplayed']) ) { + $templates = &$GLOBALS['templates']; + } + $templates = $templates ?: []; + $allRepos = []; + $bio = []; + foreach ($templates as $template) { + if ( $template['Blacklist'] ) continue; + if ( $template['Deprecated'] && $caSettings['hideDeprecated'] == "true" ) continue; + if ( ! $template['Compatible'] && $caSettings['hideIncompatible'] == "true" ) continue; + $repoName = $template['RepoName']; + if ( ! $repoName ) continue; + if ( $repoName == $caSettings['favourite'] ) { + $fav = $repositories[$repoName]; + $fav['RepositoryTemplate'] = true; + $fav['RepoName'] = $repoName; + $fav['SortName'] = $repoName; + } else { + if ( isset($repositories[$repoName]['bio']) ) { + $bio[$repoName] = $repositories[$repoName]; + $bio[$repoName] = $repositories[$repoName]; + $bio[$repoName]['RepositoryTemplate'] = true; + $bio[$repoName]['RepoName'] = $repoName; + $bio[$repoName]['SortName'] = $repoName; + $bio[$repoName] = addMissingVars($bio[$repoName]); + } else { + $allRepos[$repoName] = $repositories[$repoName]; + $allRepos[$repoName]['RepositoryTemplate'] = true; + $allRepos[$repoName]['RepoName'] = $repoName; + $allRepos[$repoName]['SortName'] = $repoName; + $allRepos[$repoName] = addMissingVars($allRepos[$repoName]); + } + } + } + usort($bio,"mySort"); + usort($allRepos,"mySort"); + $allRepos = array_merge($bio,$allRepos); + if ( isset($fav) ) + array_unshift($allRepos,$fav); + $file['community'] = $allRepos; + writeJsonFile($caPaths['repositoriesDisplayed'],$file); } ###################################################################################### # get_content - get the results from templates according to categories, filters, etc # ###################################################################################### function get_content() { - global $caPaths, $caSettings; + global $caPaths, $caSettings; - $filter = getPost("filter",false); - $category = getPost("category",false); - $newApp = filter_var(getPost("newApp",false),FILTER_VALIDATE_BOOLEAN); + $filter = getPost("filter",false); + $category = getPost("category",false); + $newApp = filter_var(getPost("newApp",false),FILTER_VALIDATE_BOOLEAN); - $caSettings['startup'] = getPost("startupDisplay",false); - @unlink($caPaths['repositoriesDisplayed']); - @unlink($caPaths['dockerSearchActive']); + $caSettings['startup'] = getPost("startupDisplay",false); + @unlink($caPaths['repositoriesDisplayed']); + @unlink($caPaths['dockerSearchActive']); - $noInstallComment = ""; - $displayBlacklisted = false; - $displayDeprecated = false; - $displayIncompatible = false; - $displayPrivates = false; - switch ($category) { - case "PRIVATE": - $category = false; - $displayPrivates = true; - break; - case "DEPRECATED": - $category = false; - $displayDeprecated = true; - $noInstallComment = tr("Deprecated Applications are able to still be installed if you have previously had them installed. New installations of these applications are blocked unless you enable Display Deprecated Applications within CA's General Settings")."

"; - break; - case "BLACKLIST": - $category = false; - $displayBlacklisted = true; - $noInstallComment = tr("The following applications are blacklisted. CA will never allow you to install or reinstall these applications")."

"; - break; - case "INCOMPATIBLE": - $category = false; - $displayIncompatible = true; - $noInstallComment = tr("While highly not recommended to do, incompatible applications can be installed by enabling Display Incompatible Applications within CA's General Settings")."

"; - break; - case "repos": - postReturn(displayRepositories()); - break; - case "": - $category = false; - break; - } - $category = $category ? "/$category/i" : false; + $noInstallComment = ""; + $displayBlacklisted = false; + $displayDeprecated = false; + $displayIncompatible = false; + $displayPrivates = false; + switch ($category) { + case "PRIVATE": + $category = false; + $displayPrivates = true; + break; + case "DEPRECATED": + $category = false; + $displayDeprecated = true; + $noInstallComment = tr("Deprecated Applications are able to still be installed if you have previously had them installed. New installations of these applications are blocked unless you enable Display Deprecated Applications within CA's General Settings")."

"; + break; + case "BLACKLIST": + $category = false; + $displayBlacklisted = true; + $noInstallComment = tr("The following applications are blacklisted. CA will never allow you to install or reinstall these applications")."

"; + break; + case "INCOMPATIBLE": + $category = false; + $displayIncompatible = true; + $noInstallComment = tr("While highly not recommended to do, incompatible applications can be installed by enabling Display Incompatible Applications within CA's General Settings")."

"; + break; + case "repos": + postReturn(displayRepositories()); + break; + case "": + $category = false; + break; + } + $category = $category ? "/$category/i" : false; - if ( strpos($category,":") && $filter ) { - $disp = readJsonFile($caPaths['community-templates-allSearchResults']); - $file = &$disp['community']; - } else - $file = &$GLOBALS['templates']; + if ( strpos($category,":") && $filter ) { + $disp = readJsonFile($caPaths['community-templates-allSearchResults']); + $file = &$disp['community']; + } else + $file = &$GLOBALS['templates']; - if ( empty($file)) return; + if ( empty($file)) return; - if ( !$filter && $category === "/NONE/i" ) { - getConvertedTemplates(); // Only scan for private XMLs when going HOME + if ( !$filter && $category === "/NONE/i" ) { + getConvertedTemplates(); // Only scan for private XMLs when going HOME - ca_file_put_contents($caPaths['startupDisplayed'],"startup"); - $displayApplications = []; - $displayApplications['community'] = []; - if ( count($file) > 200) { - $startupTypes = [ - [ - "type"=>"featured", - "text1"=>tr("Featured Applications"), - "text2"=>"", - "sortby"=>"Name", - "sortdir"=>"Up" - ], - [ - "type"=>"onlynew", - "text1"=>tr("Recently Added"), - "text2"=>tr("Check out these newly added applications from our awesome community"), - "cat"=>"All", - "sortby"=>"FirstSeen", - "sortdir"=>"Down" - ], - [ - "type"=>"spotlight", - "text1"=>tr("Spotlight Apps"), - "text2"=>tr("Each month we highlight some of the amazing work from our community"), - "cat"=>"spotlight:", - "sortby"=> "RecommendedDate", - "sortdir"=> "Down", - ], - [ - "type"=>"trending", - "text1"=>tr("Top Trending Apps"), - "text2"=>tr("Check out these up and coming apps"), - "cat"=>"All", - "sortby"=>"topTrending", - "sortdir"=>"Down" - ], - [ - "type"=>"topperforming", - "text1"=>tr("Top New Installs"), - "text2"=>tr("These apps have the highest percentage of new installs"), - "cat"=>"All", - "sortby"=>"topPerforming", - "sortdir"=>"Down" - ], - [ - "type"=>"random", - "text1"=>tr("Random Apps"), - "text2"=>tr("An assortment of randomly chosen apps"), - "cat"=>"All", - "sortby"=>"random", - "sortdir"=>"Down" - ] - ]; - $o['display'] = ""; - foreach ($startupTypes as $type) { - $display = []; + ca_file_put_contents($caPaths['startupDisplayed'],"startup"); + $displayApplications = []; + $displayApplications['community'] = []; + if ( count($file) > 200) { + $startupTypes = [ + [ + "type"=>"featured", + "text1"=>tr("Featured Applications"), + "text2"=>"", + "sortby"=>"Name", + "sortdir"=>"Up" + ], + [ + "type"=>"onlynew", + "text1"=>tr("Recently Added"), + "text2"=>tr("Check out these newly added applications from our awesome community"), + "cat"=>"All", + "sortby"=>"FirstSeen", + "sortdir"=>"Down" + ], + [ + "type"=>"spotlight", + "text1"=>tr("Spotlight Apps"), + "text2"=>tr("Each month we highlight some of the amazing work from our community"), + "cat"=>"spotlight:", + "sortby"=> "RecommendedDate", + "sortdir"=> "Down", + ], + [ + "type"=>"trending", + "text1"=>tr("Top Trending Apps"), + "text2"=>tr("Check out these up and coming apps"), + "cat"=>"All", + "sortby"=>"topTrending", + "sortdir"=>"Down" + ], + [ + "type"=>"topperforming", + "text1"=>tr("Top New Installs"), + "text2"=>tr("These apps have the highest percentage of new installs"), + "cat"=>"All", + "sortby"=>"topPerforming", + "sortdir"=>"Down" + ], + [ + "type"=>"random", + "text1"=>tr("Random Apps"), + "text2"=>tr("An assortment of randomly chosen apps"), + "cat"=>"All", + "sortby"=>"random", + "sortdir"=>"Down" + ] + ]; + $o['display'] = ""; + foreach ($startupTypes as $type) { + $display = []; - $caSettings['startup'] = $type['type']; - $appsOfDay = appOfDay($file); + $caSettings['startup'] = $type['type']; + $appsOfDay = appOfDay($file); - if ( ! $appsOfDay || empty($appsOfDay) ) - continue; + if ( ! $appsOfDay || empty($appsOfDay) ) + continue; - for ($i=0;$i<$caSettings['maxPerPage'];$i++) { - if ( ! isset($appsOfDay[$i])) continue; - $file[$appsOfDay[$i]]['NewApp'] = ($caSettings['startup'] != "random"); - $spot = $file[$appsOfDay[$i]]; - $spot['homeScreen'] = true; - $displayApplications['community'][] = $spot; - $display[] = $spot; - } - if ( $displayApplications['community'] ) { - $o['display'] .= "
{$type['text1']}
"; - $o['display'] .= "
{$type['text2']} "; - if ( $type['cat'] ?? false ) - $o['display'] .= "".tr("SHOW MORE"); - $o['display'] .= "
"; - $homeClass = "caHomeSpotlight"; + for ($i=0;$i<$caSettings['maxPerPage'];$i++) { + if ( ! isset($appsOfDay[$i])) continue; + $file[$appsOfDay[$i]]['NewApp'] = ($caSettings['startup'] != "random"); + $spot = $file[$appsOfDay[$i]]; + $spot['homeScreen'] = true; + $displayApplications['community'][] = $spot; + $display[] = $spot; + } + if ( $displayApplications['community'] ) { + $o['display'] .= "
{$type['text1']}
"; + $o['display'] .= "
{$type['text2']} "; + if ( $type['cat'] ?? false ) + $o['display'] .= "".tr("SHOW MORE"); + $o['display'] .= "
"; + $homeClass = "caHomeSpotlight"; - $o['display'] .= "
".my_display_apps($display,"1")."
"; - $o['script'] = "$('#templateSortButtons,#sortButtons,.maxPerPage').hide();$('.ca_holder').addClass('mobileHolderFix');"; + $o['display'] .= "
".my_display_apps($display,"1")."
"; + $o['script'] = "$('#templateSortButtons,#sortButtons,.maxPerPage').hide();$('.ca_holder').addClass('mobileHolderFix');"; - } else { - switch ($caSettings['startup']) { - case "onlynew": - $startupType = "New"; break; - case "new": - $startupType = "Updated"; break; - case "trending": - $startupType = "Top Performing"; break; - case "random": - $startupType = "Random"; break; - case "upandcoming": - $startupType = "Trending"; break; - case "featured": - $startupType = "Featured"; break; - } + } else { + switch ($caSettings['startup']) { + case "onlynew": + $startupType = "New"; break; + case "new": + $startupType = "Updated"; break; + case "trending": + $startupType = "Top Performing"; break; + case "random": + $startupType = "Random"; break; + case "upandcoming": + $startupType = "Trending"; break; + case "featured": + $startupType = "Featured"; break; + } - $o['display'] .= "
".sprintf(tr("An error occurred. Could not find any %s Apps"),$startupType)."

"; - $o['script'] = "$('#templateSortButtons,#sortButtons,.maxPerPage').hide();"; + $o['display'] .= "
".sprintf(tr("An error occurred. Could not find any %s Apps"),$startupType)."

"; + $o['script'] = "$('#templateSortButtons,#sortButtons,.maxPerPage').hide();"; - writeJsonFile($caPaths['community-templates-displayed'],$displayApplications); - postReturn($o); - return; - } - } - @unlink($caPaths['community-templates-allSearchResults']); - @unlink($caPaths['community-templates-catSearchResults']); - writeJsonFile($caPaths['community-templates-displayed'],$displayApplications); - postReturn($o); - return; - } - } else { - @unlink($caPaths['startupDisplayed']); - } - $display = []; - $official = []; + writeJsonFile($caPaths['community-templates-displayed'],$displayApplications); + postReturn($o); + return; + } + } + @unlink($caPaths['community-templates-allSearchResults']); + @unlink($caPaths['community-templates-catSearchResults']); + writeJsonFile($caPaths['community-templates-displayed'],$displayApplications); + postReturn($o); + return; + } + } else { + @unlink($caPaths['startupDisplayed']); + } + $display = []; + $official = []; - foreach ($file as $template) { - $template['NoInstall'] = $noInstallComment; + foreach ($file as $template) { + $template['NoInstall'] = $noInstallComment; - if ( $displayBlacklisted ) { - if ( $template['Blacklist'] ) { - $display[] = $template; - continue; - } else continue; - } + if ( $displayBlacklisted ) { + if ( $template['Blacklist'] ) { + $display[] = $template; + continue; + } else continue; + } - if ( $displayIncompatible) { - if ( ! $template['Compatible'] && $displayIncompatible) { - $display[] = $template; - continue; - } else continue; - } - if ( $template['Deprecated'] && $displayDeprecated && ! $template['Blacklist']) { - if ( ! ($template['BranchID']??false) ) - $display[] = $template; - continue; - } - if ( ($caSettings['hideDeprecated'] == "true") && ($template['Deprecated'] && ! $displayDeprecated) ) continue; - if ( $displayDeprecated && ! $template['Deprecated'] ) continue; - if ( ! $template['Displayable'] ) continue; - if ( $caSettings['hideIncompatible'] == "true" && ! $template['Compatible'] && ! $displayIncompatible && ! $template['Featured']) continue; - if ( $template['Blacklist'] ) continue; + if ( $displayIncompatible) { + if ( ! $template['Compatible'] && $displayIncompatible) { + $display[] = $template; + continue; + } else continue; + } + if ( $template['Deprecated'] && $displayDeprecated && ! $template['Blacklist']) { + if ( ! ($template['BranchID']??false) ) + $display[] = $template; + continue; + } + if ( ($caSettings['hideDeprecated'] == "true") && ($template['Deprecated'] && ! $displayDeprecated) ) continue; + if ( $displayDeprecated && ! $template['Deprecated'] ) continue; + if ( ! $template['Displayable'] ) continue; + if ( $caSettings['hideIncompatible'] == "true" && ! $template['Compatible'] && ! $displayIncompatible && ! $template['Featured']) continue; + if ( $template['Blacklist'] ) continue; - $name = $template['Name']; + $name = $template['Name']; - if ( $template['Plugin'] && file_exists("/var/log/plugins/".basename($template['PluginURL'])) ) - $template['InstallPath'] = $template['PluginURL']; + if ( $template['Plugin'] && file_exists("/var/log/plugins/".basename($template['PluginURL'])) ) + $template['InstallPath'] = $template['PluginURL']; - $template['NewApp'] = $newApp; + $template['NewApp'] = $newApp; - if ( $category && ! preg_match($category,$template['Category'])) { - continue; - } - if ( $category == "/spotlight:/i" ) - $template['class'] = "spotlightHome"; + if ( $category && ! preg_match($category,$template['Category'])) { + continue; + } + if ( $category == "/spotlight:/i" ) + $template['class'] = "spotlightHome"; - if ( $displayPrivates && ! $template['Private'] ) continue; + if ( $displayPrivates && ! $template['Private'] ) continue; - if ($filter) { - # Can't be done at appfeed download time because the translation may or may not exist if the user switches languages - foreach (explode(" ",$template['Category']) as $trCat) { - $template['translatedCategories'] .= tr($trCat)." "; - } - if ( endsWith($filter," Repository") && $template['RepoName'] !== $filter) { - continue; - } - if ( filterMatch($filter,[$template['SortName']]) && $caSettings['favourite'] == $template['RepoName']) { - $searchResults['favNameHit'][] = $template; - continue; - } - if ( strpos($filter,"/") && filterMatch($filter,[$template['Repository']]) ) - $searchResults['nameHit'][] = $template; - else { - if ( filterMatch($filter,[$template['SortName'],$template['RepoShort'],$template['Language'],$template['LanguageLocal'],$template['ExtraSearchTerms']]) ) { - if ( filterMatch($filter,[$template['ExtraSearchTerms']]) && $template['ExtraPriority'] ) - $searchResults['extraHit'][] = $template; - else - $searchResults['nameHit'][] = $template; - } elseif ( filterMatch($filter,[$template['Author'],$template['RepoName'],$template['Overview'],$template['translatedCategories']]) ) { - if ( $template['RepoName'] == $caSettings['favourite'] ) { - $searchResults['nameHit'][] = $template; - } else { - $searchResults['anyHit'][] = $template; - } - } else continue; - } - } - $display[] = $template; - } - if ( $filter ) { - if ( isset($searchResults['nameHit']) ) { - usort($searchResults['nameHit'],"mySort"); - if ( ! strpos($filter," Repository") ) { - if ( $caSettings['favourite'] && $caSettings['favourite'] !== "none" ) { - usort($searchResults['nameHit'],"favouriteSort"); - } - } - } - else - $searchResults['nameHit'] = []; + if ($filter) { + # Can't be done at appfeed download time because the translation may or may not exist if the user switches languages + foreach (explode(" ",$template['Category']) as $trCat) { + $template['translatedCategories'] .= tr($trCat)." "; + } + if ( endsWith($filter," Repository") && $template['RepoName'] !== $filter) { + continue; + } + if ( filterMatch($filter,[$template['SortName']]) && $caSettings['favourite'] == $template['RepoName']) { + $searchResults['favNameHit'][] = $template; + continue; + } + if ( strpos($filter,"/") && filterMatch($filter,[$template['Repository']]) ) + $searchResults['nameHit'][] = $template; + else { + if ( filterMatch($filter,[$template['SortName'],$template['RepoShort'],$template['Language'],$template['LanguageLocal'],$template['ExtraSearchTerms']]) ) { + if ( filterMatch($filter,[$template['ExtraSearchTerms']]) && $template['ExtraPriority'] ) + $searchResults['extraHit'][] = $template; + else + $searchResults['nameHit'][] = $template; + } elseif ( filterMatch($filter,[$template['Author'],$template['RepoName'],$template['Overview'],$template['translatedCategories']]) ) { + if ( $template['RepoName'] == $caSettings['favourite'] ) { + $searchResults['nameHit'][] = $template; + } else { + $searchResults['anyHit'][] = $template; + } + } else continue; + } + } + $display[] = $template; + } + if ( $filter ) { + if ( isset($searchResults['nameHit']) ) { + usort($searchResults['nameHit'],"mySort"); + if ( ! strpos($filter," Repository") ) { + if ( $caSettings['favourite'] && $caSettings['favourite'] !== "none" ) { + usort($searchResults['nameHit'],"favouriteSort"); + } + } + } + else + $searchResults['nameHit'] = []; - if ( isset($searchResults['anyHit']) ) { - usort($searchResults['anyHit'],"mySort"); - } - else - $searchResults['anyHit'] = []; - if ( isset($searchResults['favNameHit']) ) - usort($searchResults['favNameHit'],"mySort"); - else - $searchResults['favNameHit'] = []; + if ( isset($searchResults['anyHit']) ) { + usort($searchResults['anyHit'],"mySort"); + } + else + $searchResults['anyHit'] = []; + if ( isset($searchResults['favNameHit']) ) + usort($searchResults['favNameHit'],"mySort"); + else + $searchResults['favNameHit'] = []; - if ( isset($searchResults['extraHit']) ) - usort($searchResults['extraHit'],"mySort"); - else - $searchResults['extraHit'] = []; + if ( isset($searchResults['extraHit']) ) + usort($searchResults['extraHit'],"mySort"); + else + $searchResults['extraHit'] = []; - $displayApplications['community'] = array_merge($searchResults['extraHit'],$searchResults['favNameHit'],$searchResults['nameHit'],$searchResults['anyHit']); - } else { - usort($display,"mySort"); - $displayApplications['community'] = $display; - } - if ( ! $category && $filter ) { - writeJsonFile($caPaths['community-templates-allSearchResults'],$displayApplications); - writeJsonFile($caPaths['community-templates-catSearchResults'],$displayApplications); - } - if ( $category && $filter) { - writeJsonFile($caPaths['community-templates-catSearchResults'],$displayApplications); - } - if ( ! $filter ) { - writeJsonFile($caPaths['community-templates-displayed'],$displayApplications); - @unlink($caPaths['community-templates-allsearchResults']); - @unlink($caPaths['community-templates-catSearchResults']); - } - $o['display'] = "
".display_apps()."
"; + $displayApplications['community'] = array_merge($searchResults['extraHit'],$searchResults['favNameHit'],$searchResults['nameHit'],$searchResults['anyHit']); + } else { + usort($display,"mySort"); + $displayApplications['community'] = $display; + } + if ( ! $category && $filter ) { + writeJsonFile($caPaths['community-templates-allSearchResults'],$displayApplications); + writeJsonFile($caPaths['community-templates-catSearchResults'],$displayApplications); + } + if ( $category && $filter) { + writeJsonFile($caPaths['community-templates-catSearchResults'],$displayApplications); + } + if ( ! $filter ) { + writeJsonFile($caPaths['community-templates-displayed'],$displayApplications); + @unlink($caPaths['community-templates-allsearchResults']); + @unlink($caPaths['community-templates-catSearchResults']); + } + $o['display'] = "
".display_apps()."
"; - postReturn($o); + postReturn($o); } ######################################################## # force_update -> forces an update of the applications # ######################################################## function force_update() { - global $caPaths; + global $caPaths; - $lastUpdatedOld = readJsonFile($caPaths['lastUpdated-old']); - debug("old feed timestamp: ".($lastUpdatedOld['last_updated_timestamp'] ?? "")); - @unlink($caPaths['lastUpdated']); - $latestUpdate = download_json($caPaths['application-feed-last-updated'],$caPaths['lastUpdated'],"",5); - if ( ! $latestUpdate['last_updated_timestamp'] ?? false ) - $latestUpdate = download_json($caPaths['application-feed-last-updatedBackup'],$caPaths['lastUpdated'],"",5); - debug("new appfeed timestamp: {$latestUpdate['last_updated_timestamp']}"); - if ( ! isset($latestUpdate['last_updated_timestamp']) ) { - $latestUpdate['last_updated_timestamp'] = INF; - $badDownload = true; - @unlink($caPaths['lastUpdated']); - } + $lastUpdatedOld = readJsonFile($caPaths['lastUpdated-old']); + debug("old feed timestamp: ".($lastUpdatedOld['last_updated_timestamp'] ?? "")); + @unlink($caPaths['lastUpdated']); + $latestUpdate = download_json($caPaths['application-feed-last-updated'],$caPaths['lastUpdated'],"",5); + if ( ! $latestUpdate['last_updated_timestamp'] ?? false ) + $latestUpdate = download_json($caPaths['application-feed-last-updatedBackup'],$caPaths['lastUpdated'],"",5); + debug("new appfeed timestamp: {$latestUpdate['last_updated_timestamp']}"); + if ( ! isset($latestUpdate['last_updated_timestamp']) ) { + $latestUpdate['last_updated_timestamp'] = INF; + $badDownload = true; + @unlink($caPaths['lastUpdated']); + } - if ( ($latestUpdate['last_updated_timestamp'] ?? 0) != ($lastUpdatedOld['last_updated_timestamp'] ?? 0) ) { - exec("rm -rf '{$caPaths['tempFiles']}'"); - $GLOBALS['templates'] = []; - } + if ( ($latestUpdate['last_updated_timestamp'] ?? 0) != ($lastUpdatedOld['last_updated_timestamp'] ?? 0) ) { + exec("rm -rf '{$caPaths['tempFiles']}'"); + $GLOBALS['templates'] = []; + } - if (!file_exists($caPaths['community-templates-info']) || ! $GLOBALS['templates']) { - $updatedSyncFlag = true; - if (! DownloadApplicationFeed() ) { - $o['script'] = "$('.onlyShowWithFeed').hide();"; - $o['data'] = "
".tr("Download of appfeed failed.")."

Community Applications requires your server to have internet access. The most common cause of this failure is a failure to resolve DNS addresses. You can try and reset your modem and router to fix this issue, or set static DNS addresses (Settings - Network Settings) of 208.67.222.222 and 208.67.220.220 and try again.

Alternatively, there is also a chance that the server handling the application feed is temporarily down. See also this post for more information"; - $tempFile = @file_get_contents($caPaths['appFeedDownloadError']); - $downloaded = @file_get_contents($tempFile); - if (strlen($downloaded) > 100) - $o['data'] .= "

It *appears* that a partial download of the application feed happened (or is malformed), therefore it is probable that the application feed is temporarily down. Please try again later)
"; + if (!file_exists($caPaths['community-templates-info']) || ! $GLOBALS['templates']) { + $updatedSyncFlag = true; + if (! DownloadApplicationFeed() ) { + $o['script'] = "$('.onlyShowWithFeed').hide();"; + $o['data'] = "
".tr("Download of appfeed failed.")."

Community Applications requires your server to have internet access. The most common cause of this failure is a failure to resolve DNS addresses. You can try and reset your modem and router to fix this issue, or set static DNS addresses (Settings - Network Settings) of 208.67.222.222 and 208.67.220.220 and try again.

Alternatively, there is also a chance that the server handling the application feed is temporarily down. See also this post for more information"; + $tempFile = @file_get_contents($caPaths['appFeedDownloadError']); + $downloaded = @file_get_contents($tempFile); + if (strlen($downloaded) > 100) + $o['data'] .= "

It *appears* that a partial download of the application feed happened (or is malformed), therefore it is probable that the application feed is temporarily down. Please try again later)
"; - $o['data'] .= "
Last JSON error Recorded: "; - $jsonDecode = json_decode($downloaded,true); - $o['data'] .= json_last_error_msg(); + $o['data'] .= "
Last JSON error Recorded: "; + $jsonDecode = json_decode($downloaded,true); + $o['data'] .= json_last_error_msg(); - $o['data'] .= "
"; - @unlink($caPaths['appFeedDownloadError']); - @unlink($caPaths['community-templates-info']); - $GLOBALS['templates'] = []; - postReturn($o); - return; - } - } - getConvertedTemplates(); - moderateTemplates(); - $currentServer = @file_get_contents($caPaths['currentServer']); + $o['data'] .= "
"; + @unlink($caPaths['appFeedDownloadError']); + @unlink($caPaths['community-templates-info']); + $GLOBALS['templates'] = []; + postReturn($o); + return; + } + } + getConvertedTemplates(); + moderateTemplates(); + $currentServer = @file_get_contents($caPaths['currentServer']); - $appFeedTime = readJsonFile($caPaths['lastUpdated-old']); - $updateTime = tr(date("F",$appFeedTime['last_updated_timestamp']),0).date(" d, Y @ g:i a",$appFeedTime['last_updated_timestamp']); - $updateTime = str_replace("'","'",$updateTime); - postReturn(['status'=>"ok",'script'=>"feedWarning('$currentServer');$('.statistics').attr('title','{$updateTime}');"]); + $appFeedTime = readJsonFile($caPaths['lastUpdated-old']); + $updateTime = tr(date("F",$appFeedTime['last_updated_timestamp']),0).date(" d, Y @ g:i a",$appFeedTime['last_updated_timestamp']); + $updateTime = str_replace("'","'",$updateTime); + postReturn(['status'=>"ok",'script'=>"feedWarning('$currentServer');$('.statistics').attr('title','{$updateTime}');"]); } @@ -1069,1479 +1069,1479 @@ function force_update() { # display_content - displays the templates according to view mode, sort order, etc # #################################################################################### function display_content() { - global $caPaths; + global $caPaths; - $pageNumber = getPost("pageNumber","1"); - $startup = getPost("startup",false); - $selectedApps = json_decode(getPost("selected",false),true); - $o['display'] = ""; - if ( file_exists($caPaths['community-templates-displayed']) || file_exists($caPaths['repositoriesDisplayed']) ) { - $o['display'] = "
".display_apps($pageNumber,$selectedApps,$startup)."
"; - } + $pageNumber = getPost("pageNumber","1"); + $startup = getPost("startup",false); + $selectedApps = json_decode(getPost("selected",false),true); + $o['display'] = ""; + if ( file_exists($caPaths['community-templates-displayed']) || file_exists($caPaths['repositoriesDisplayed']) ) { + $o['display'] = "
".display_apps($pageNumber,$selectedApps,$startup)."
"; + } - $displayedApps = readJsonFile($caPaths['community-templates-displayed']); - $currentServer = @file_get_contents($caPaths['currentServer']); - $o['script'] = "feedWarning('$currentServer');"; - postReturn($o); + $displayedApps = readJsonFile($caPaths['community-templates-displayed']); + $currentServer = @file_get_contents($caPaths['currentServer']); + $o['script'] = "feedWarning('$currentServer');"; + postReturn($o); } ##################################################################### # dismiss_warning - dismisses the warning from appearing at startup # ##################################################################### function dismiss_warning() { - global $caPaths; + global $caPaths; - ca_file_put_contents($caPaths['warningAccepted'],"warning dismissed"); - postReturn(['status'=>"warning dismissed"]); + ca_file_put_contents($caPaths['warningAccepted'],"warning dismissed"); + postReturn(['status'=>"warning dismissed"]); } function dismiss_plugin_warning() { - global $caPaths; + global $caPaths; - ca_file_put_contents($caPaths['pluginWarning'],"disclaimer ok"); - postReturn(['status'=>"disclaimed"]); + ca_file_put_contents($caPaths['pluginWarning'],"disclaimer ok"); + postReturn(['status'=>"disclaimed"]); } ############################################################### # Displays the list of installed or previously installed apps # ############################################################### function previous_apps() { - global $caPaths, $caSettings, $DockerClient; + global $caPaths, $caSettings, $DockerClient; - $installed = getPost("installed",""); - $filter = getPost("filter",""); - $info = getAllInfo(); + $installed = getPost("installed",""); + $filter = getPost("filter",""); + $info = getAllInfo(); - @unlink($caPaths['community-templates-allSearchResults']); - @unlink($caPaths['community-templates-catSearchResults']); - @unlink($caPaths['repositoriesDisplayed']); - @unlink($caPaths['startupDisplayed']); - @unlink($caPaths['dockerSearchActive']); + @unlink($caPaths['community-templates-allSearchResults']); + @unlink($caPaths['community-templates-catSearchResults']); + @unlink($caPaths['repositoriesDisplayed']); + @unlink($caPaths['startupDisplayed']); + @unlink($caPaths['dockerSearchActive']); - $file = &$GLOBALS['templates']; - $extraBlacklist = readJsonFile($caPaths['extraBlacklist']); - $extraDeprecated = readJsonFile($caPaths['extraDeprecated']); - $displayed = []; - $updateCount = 0; + $file = &$GLOBALS['templates']; + $extraBlacklist = readJsonFile($caPaths['extraBlacklist']); + $extraDeprecated = readJsonFile($caPaths['extraDeprecated']); + $displayed = []; + $updateCount = 0; - if ( is_file("/var/run/dockerd.pid") && is_dir("/proc/".@file_get_contents("/var/run/dockerd.pid")) ) { - $dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']); - } else { - $dockerUpdateStatus = []; - } + if ( is_file("/var/run/dockerd.pid") && is_dir("/proc/".@file_get_contents("/var/run/dockerd.pid")) ) { + $dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']); + } else { + $dockerUpdateStatus = []; + } # $info contains all installed containers # now correlate that to a template; # this section handles containers that have not been renamed from the appfeed - if ( $caSettings['dockerRunning'] ) { - $all_files = glob("{$caPaths['dockerManTemplates']}/*.xml"); - $all_files = $all_files ?: []; - if ( $installed == "true" || $installed == "action") { - if ( !$filter || $filter == "docker" ) { - foreach ($all_files as $xmlfile) { - $o = readXmlFile($xmlfile); - $o['Overview'] = fixDescription($o['Overview']); - $o['Description'] = $o['Overview']; - $o['CardDescription'] = $o['Overview']; - $o['InstallPath'] = $xmlfile; - $o['UnknownCompatible'] = true; - $containerID = false; + if ( $caSettings['dockerRunning'] ) { + $all_files = glob("{$caPaths['dockerManTemplates']}/*.xml"); + $all_files = $all_files ?: []; + if ( $installed == "true" || $installed == "action") { + if ( !$filter || $filter == "docker" ) { + foreach ($all_files as $xmlfile) { + $o = readXmlFile($xmlfile); + $o['Overview'] = fixDescription($o['Overview']); + $o['Description'] = $o['Overview']; + $o['CardDescription'] = $o['Overview']; + $o['InstallPath'] = $xmlfile; + $o['UnknownCompatible'] = true; + $containerID = false; - $runningflag = false; - foreach ($info as $installedDocker) { - $installedImage = str_replace("library/","",$installedDocker['Image']); - $installedName = $installedDocker['Name']; - if ( $installedName == $o['Name'] ) { - if ( startsWith($installedImage, $o['Repository']) ) { - $runningflag = true; - $searchResult = searchArray($file,'Repository',$o['Repository']); - if ( $searchResult === false) { - $searchResult = searchArray($file,'Repository',explode(":",$o['Repository'])[0]); - } - if ( $searchResult !== false ) { - $tempPath = $o['InstallPath']; - $containerID = $file[$searchResult]['ID']; - $tmpOvr = $o['Overview']; - $o = $file[$searchResult]; - $o['Name'] = $installedName; - $o['Overview'] = $tmpOvr; - $o['CardDescription'] = $tmpOvr; - $o['InstallPath'] = $tempPath; - $o['SortName'] = str_replace("-"," ",$installedName); - if ( $installedName !== $file[$searchResult]['Name'] ) - $o['NoPin'] = true; # This is renamed and effectively outside of CA's control - } else { - $runningFlag = true; - } - break; - } - } - } - if ( $runningflag ) { - $o['Uninstall'] = true; - $o['ID'] = $containerID; + $runningflag = false; + foreach ($info as $installedDocker) { + $installedImage = str_replace("library/","",$installedDocker['Image']); + $installedName = $installedDocker['Name']; + if ( $installedName == $o['Name'] ) { + if ( startsWith($installedImage, $o['Repository']) ) { + $runningflag = true; + $searchResult = searchArray($file,'Repository',$o['Repository']); + if ( $searchResult === false) { + $searchResult = searchArray($file,'Repository',explode(":",$o['Repository'])[0]); + } + if ( $searchResult !== false ) { + $tempPath = $o['InstallPath']; + $containerID = $file[$searchResult]['ID']; + $tmpOvr = $o['Overview']; + $o = $file[$searchResult]; + $o['Name'] = $installedName; + $o['Overview'] = $tmpOvr; + $o['CardDescription'] = $tmpOvr; + $o['InstallPath'] = $tempPath; + $o['SortName'] = str_replace("-"," ",$installedName); + if ( $installedName !== $file[$searchResult]['Name'] ) + $o['NoPin'] = true; # This is renamed and effectively outside of CA's control + } else { + $runningFlag = true; + } + break; + } + } + } + if ( $runningflag ) { + $o['Uninstall'] = true; + $o['ID'] = $containerID; - if ( $installed == "action" ) { - $tmpRepo = strpos($o['Repository'],":") ? $o['Repository'] : $o['Repository'].":latest"; + if ( $installed == "action" ) { + $tmpRepo = strpos($o['Repository'],":") ? $o['Repository'] : $o['Repository'].":latest"; - if ( $tmpRepo && ($dockerUpdateStatus[$tmpRepo]['status'] ?? null) == "false" ) { - $o['actionCentre'] = true; - $o['updateAvailable'] = true; - $updateCount++; - } + if ( $tmpRepo && ($dockerUpdateStatus[$tmpRepo]['status'] ?? null) == "false" ) { + $o['actionCentre'] = true; + $o['updateAvailable'] = true; + $updateCount++; + } - if ( ! $o['Blacklist'] && ! $o['Deprecated'] ) { - if ( $extraBlacklist[$o['Repository']] ?? false) { - $o['Blacklist'] = true; - $o['ModeratorComment'] = $extraBlacklist[$o['Repository']]; - } - if ( $extraDeprecated[$o['Repository']] ?? false ) { - $o['Deprecated'] = true; - $o['ModeratorComment'] = $extraDeprecated[$o['Deprecated']]; - } - } + if ( ! $o['Blacklist'] && ! $o['Deprecated'] ) { + if ( $extraBlacklist[$o['Repository']] ?? false) { + $o['Blacklist'] = true; + $o['ModeratorComment'] = $extraBlacklist[$o['Repository']]; + } + if ( $extraDeprecated[$o['Repository']] ?? false ) { + $o['Deprecated'] = true; + $o['ModeratorComment'] = $extraDeprecated[$o['Deprecated']]; + } + } - if ( !$o['Blacklist'] && !$o['Deprecated'] && !$o['actionCentre'] ) - continue; - } - if ( $installed == "action" ) - $o['actionCentre'] = true; + if ( !$o['Blacklist'] && !$o['Deprecated'] && !$o['actionCentre'] ) + continue; + } + if ( $installed == "action" ) + $o['actionCentre'] = true; - $displayed[] = $o; - } - } - } - } else { - if ( ! $filter || $filter == "docker" ) { - # now get the old not installed docker apps - foreach ($all_files as $xmlfile) { - $o = readXmlFile($xmlfile); - if ( ! $o ) continue; - $o['Overview'] = fixDescription($o['Overview']); - $o['Description'] = $o['Overview']; - $o['CardDescription'] = $o['Overview']; - $o['InstallPath'] = $xmlfile; - $o['UnknownCompatible'] = true; - $o['Removable'] = true; - # is the container running? + $displayed[] = $o; + } + } + } + } else { + if ( ! $filter || $filter == "docker" ) { + # now get the old not installed docker apps + foreach ($all_files as $xmlfile) { + $o = readXmlFile($xmlfile); + if ( ! $o ) continue; + $o['Overview'] = fixDescription($o['Overview']); + $o['Description'] = $o['Overview']; + $o['CardDescription'] = $o['Overview']; + $o['InstallPath'] = $xmlfile; + $o['UnknownCompatible'] = true; + $o['Removable'] = true; + # is the container running? - $flag = false; - foreach ($info as $installedDocker) { - $installedImage = $installedDocker['Image']; - $installedImage = str_replace("library/","",$installedImage); - $installedName = $installedDocker['Name']; - if ( startsWith($installedImage, $o['Repository']) ) { - if ( $installedName == $o['Name'] ) { - $flag = true; - continue; - } - } - } - if ( ! $flag ) { - $testRepo = explode(":",$o['Repository'])[0]; - # now associate the template back to a template in the appfeed + $flag = false; + foreach ($info as $installedDocker) { + $installedImage = $installedDocker['Image']; + $installedImage = str_replace("library/","",$installedImage); + $installedName = $installedDocker['Name']; + if ( startsWith($installedImage, $o['Repository']) ) { + if ( $installedName == $o['Name'] ) { + $flag = true; + continue; + } + } + } + if ( ! $flag ) { + $testRepo = explode(":",$o['Repository'])[0]; + # now associate the template back to a template in the appfeed - foreach ($file as $appTemplate) { - if (startsWith($appTemplate['Repository'],$testRepo)) { - $tempPath = $o['InstallPath']; - $tempName = $o['Name']; - $tempOvr = $o['Overview']; - $o = $appTemplate; - $o['Overview'] = $tempOvr; - $o['Description'] = $tempOvr; - $o['CardDescription'] = $tempOvr; - $o['Removable'] = true; - $o['InstallPath'] = $tempPath; - $o['Name'] = $tempName; - $o['SortName'] = str_replace("-"," ",$o['Name']); - $o['NoPin'] = true; - break; - } - } + foreach ($file as $appTemplate) { + if (startsWith($appTemplate['Repository'],$testRepo)) { + $tempPath = $o['InstallPath']; + $tempName = $o['Name']; + $tempOvr = $o['Overview']; + $o = $appTemplate; + $o['Overview'] = $tempOvr; + $o['Description'] = $tempOvr; + $o['CardDescription'] = $tempOvr; + $o['Removable'] = true; + $o['InstallPath'] = $tempPath; + $o['Name'] = $tempName; + $o['SortName'] = str_replace("-"," ",$o['Name']); + $o['NoPin'] = true; + break; + } + } - if ( ! $o['Blacklist'] ) - $displayed[] = $o; - } - } - } - } - } + if ( ! $o['Blacklist'] ) + $displayed[] = $o; + } + } + } + } + } # Now work on plugins - if ( $installed == "true" || $installed == "action" ) { - if ( ! $filter || $filter == "plugins" ) { - foreach ($file as $template) { - if ( ! $template['Plugin'] ) continue; + if ( $installed == "true" || $installed == "action" ) { + if ( ! $filter || $filter == "plugins" ) { + foreach ($file as $template) { + if ( ! $template['Plugin'] ) continue; - $filename = pathinfo($template['Repository'],PATHINFO_BASENAME); + $filename = pathinfo($template['Repository'],PATHINFO_BASENAME); - if ( checkInstalledPlugin($template) ) { - $template['InstallPath'] = "/var/log/plugins/$filename"; - $template['Uninstall'] = true; + if ( checkInstalledPlugin($template) ) { + $template['InstallPath'] = "/var/log/plugins/$filename"; + $template['Uninstall'] = true; - if ( $installed == "action" && $template['PluginURL'] && $template['Name'] !== "Community Applications") { - $installedVersion = plugin("version","/var/log/plugins/$filename"); - if ( ( strcmp($installedVersion,$template['pluginVersion']) < 0 || $template['UpdateAvailable']) ) { - $template['actionCentre'] = true; - $template['UpdateAvailable'] = true; - $updateCount++; - } - if ( is_file("/tmp/plugins/$filename") && strcmp($installedVersion,plugin("version","/tmp/plugins/$filename")) < 0 ) { - $template['actionCentre'] = true; - $template['UpdateAvailable'] = true; - $updateCount++; - } - } + if ( $installed == "action" && $template['PluginURL'] && $template['Name'] !== "Community Applications") { + $installedVersion = plugin("version","/var/log/plugins/$filename"); + if ( ( strcmp($installedVersion,$template['pluginVersion']) < 0 || $template['UpdateAvailable']) ) { + $template['actionCentre'] = true; + $template['UpdateAvailable'] = true; + $updateCount++; + } + if ( is_file("/tmp/plugins/$filename") && strcmp($installedVersion,plugin("version","/tmp/plugins/$filename")) < 0 ) { + $template['actionCentre'] = true; + $template['UpdateAvailable'] = true; + $updateCount++; + } + } - if ( $installed == "action" && !$template['Blacklist'] && !$template['Deprecated'] && $template['Compatible'] && !$template['actionCentre'] ) - continue; - if ( $installed == "action" ) - $template['actionCentre'] = true; - $displayed[] = $template; - } - } - $installedLanguages = array_diff(scandir($caPaths['languageInstalled']),[".","..","en_US"]); - foreach ($installedLanguages as $language) { - $index = searchArray($file,"LanguagePack",$language); - if ( $index !== false ) { - $tmpL = $file[$index]; - $tmpL['Uninstall'] = true; + if ( $installed == "action" && !$template['Blacklist'] && !$template['Deprecated'] && $template['Compatible'] && !$template['actionCentre'] ) + continue; + if ( $installed == "action" ) + $template['actionCentre'] = true; + $displayed[] = $template; + } + } + $installedLanguages = array_diff(scandir($caPaths['languageInstalled']),[".","..","en_US"]); + foreach ($installedLanguages as $language) { + $index = searchArray($file,"LanguagePack",$language); + if ( $index !== false ) { + $tmpL = $file[$index]; + $tmpL['Uninstall'] = true; - if ( $installed == "action" ) { - $tmpL['actionCentre'] = true; - if ( !languageCheck($tmpL) ) - continue; - $tmpL['Updated'] = true; - $updateCount++; - } + if ( $installed == "action" ) { + $tmpL['actionCentre'] = true; + if ( !languageCheck($tmpL) ) + continue; + $tmpL['Updated'] = true; + $updateCount++; + } - $displayed[] = $tmpL; - } - } - } - } else { - if ( ! $filter || $filter == "plugins" ) { - $all_plugs = array_merge(glob("/boot/config/plugins-error/*.plg"),glob("/boot/config/plugins-removed/*.plg")); - foreach ($all_plugs as $oldplug) { - foreach ($file as $template) { - if ( basename($oldplug) == basename($template['Repository']) ) { - if ( ! file_exists("/boot/config/plugins/".basename($oldplug)) ) { - if ( $template['Blacklist'] || ( ($caSettings['hideIncompatible'] == "true") && (! $template['Compatible']) ) ) continue; - $oldPlugURL = trim(plugin("pluginURL",$oldplug)); - if ( ! $oldPlugURL ) - continue; - if ( strtolower(trim($template['PluginURL'])) != strtolower(trim($oldPlugURL)) ) { - continue; - } - $template['Removable'] = true; - $template['InstallPath'] = $oldplug; - if ( isset($alreadySeen[$oldPlugURL]) ) - continue; - $alreadySeen[$oldPlugURL] = true; - $displayed[] = $template; - break; - } - } - } - } - } - } - if ( isset($displayed) && is_array($displayed) ) { - usort($displayed,"mySort"); - } - $displayedApplications['community'] = $displayed; - writeJsonFile($caPaths['community-templates-displayed'],$displayedApplications); - if ( $installed == "action" && empty($displayed) ) { - postReturn(['status'=>"ok",'script'=>'$(".actionCentre").hide();$(".startupButton").trigger("click");']); - } else { - postReturn(['status'=>"ok",'updateCount'=>$updateCount]); - } + $displayed[] = $tmpL; + } + } + } + } else { + if ( ! $filter || $filter == "plugins" ) { + $all_plugs = array_merge(glob("/boot/config/plugins-error/*.plg"),glob("/boot/config/plugins-removed/*.plg")); + foreach ($all_plugs as $oldplug) { + foreach ($file as $template) { + if ( basename($oldplug) == basename($template['Repository']) ) { + if ( ! file_exists("/boot/config/plugins/".basename($oldplug)) ) { + if ( $template['Blacklist'] || ( ($caSettings['hideIncompatible'] == "true") && (! $template['Compatible']) ) ) continue; + $oldPlugURL = trim(plugin("pluginURL",$oldplug)); + if ( ! $oldPlugURL ) + continue; + if ( strtolower(trim($template['PluginURL'])) != strtolower(trim($oldPlugURL)) ) { + continue; + } + $template['Removable'] = true; + $template['InstallPath'] = $oldplug; + if ( isset($alreadySeen[$oldPlugURL]) ) + continue; + $alreadySeen[$oldPlugURL] = true; + $displayed[] = $template; + break; + } + } + } + } + } + } + if ( isset($displayed) && is_array($displayed) ) { + usort($displayed,"mySort"); + } + $displayedApplications['community'] = $displayed; + writeJsonFile($caPaths['community-templates-displayed'],$displayedApplications); + if ( $installed == "action" && empty($displayed) ) { + postReturn(['status'=>"ok",'script'=>'$(".actionCentre").hide();$(".startupButton").trigger("click");']); + } else { + postReturn(['status'=>"ok",'updateCount'=>$updateCount]); + } } #################################################################################### # Removes an app from the previously installed list (ie: deletes the user template # #################################################################################### function remove_application() { - $application = realpath(getPost("application","")); - if ( ! (strpos($application,"/boot/config") === false) ) { - if ( pathinfo($application,PATHINFO_EXTENSION) == "xml" || pathinfo($application,PATHINFO_EXTENSION) == "plg" ) - @unlink($application); - } - postReturn(['status'=>"ok"]); + $application = realpath(getPost("application","")); + if ( ! (strpos($application,"/boot/config") === false) ) { + if ( pathinfo($application,PATHINFO_EXTENSION) == "xml" || pathinfo($application,PATHINFO_EXTENSION) == "plg" ) + @unlink($application); + } + postReturn(['status'=>"ok"]); } ################################################################################### # Checks for an update still available (to update display) after update installed # ################################################################################### function updatePLGstatus() { - global $caPaths; + global $caPaths; - $filename = getPost("filename",""); - $displayed = readJsonFile($caPaths['community-templates-displayed']); - $superCategories = array_keys($displayed); - foreach ($superCategories as $category) { - foreach ($displayed[$category] as $template) { - if ( strpos($template['PluginURL'],$filename) ) - $template['UpdateAvailable'] = checkPluginUpdate($filename); + $filename = getPost("filename",""); + $displayed = readJsonFile($caPaths['community-templates-displayed']); + $superCategories = array_keys($displayed); + foreach ($superCategories as $category) { + foreach ($displayed[$category] as $template) { + if ( strpos($template['PluginURL'],$filename) ) + $template['UpdateAvailable'] = checkPluginUpdate($filename); - $newDisplayed[$category][] = $template; - } - } - writeJsonFile($caPaths['community-templates-displayed'],$newDisplayed); - postReturn(['status'=>"ok"]); + $newDisplayed[$category][] = $template; + } + } + writeJsonFile($caPaths['community-templates-displayed'],$newDisplayed); + postReturn(['status'=>"ok"]); } ####################### # Uninstalls a docker # ####################### function uninstall_docker() { - global $DockerClient, $caPaths, $caSettings; - $application = getPost("application",""); + global $DockerClient, $caPaths, $caSettings; + $application = getPost("application",""); # get the name of the container / image - $doc = new DOMDocument(); - $doc->load($application); - $containerName = stripslashes($doc->getElementsByTagName( "Name" )->item(0)->nodeValue); + $doc = new DOMDocument(); + $doc->load($application); + $containerName = stripslashes($doc->getElementsByTagName( "Name" )->item(0)->nodeValue); - $dockerRunning = $DockerClient->getDockerContainers(); - $container = searchArray($dockerRunning,"Name",$containerName); + $dockerRunning = $DockerClient->getDockerContainers(); + $container = searchArray($dockerRunning,"Name",$containerName); - if ( $dockerRunning[$container]['Running'] ) - myStopContainer($dockerRunning[$container]['Id']); + if ( $dockerRunning[$container]['Running'] ) + myStopContainer($dockerRunning[$container]['Id']); - $DockerClient->removeContainer($containerName,$dockerRunning[$container]['Id']); - $DockerClient->removeImage($dockerRunning[$container]['ImageId']); - exec("/usr/bin/docker volume prune"); + $DockerClient->removeContainer($containerName,$dockerRunning[$container]['Id']); + $DockerClient->removeImage($dockerRunning[$container]['ImageId']); + exec("/usr/bin/docker volume prune"); - $info = getAllInfo(true); + $info = getAllInfo(true); - postReturn(['status'=>"Uninstalled"]); + postReturn(['status'=>"Uninstalled"]); } ################################################## # Pins / Unpins an application for later viewing # ################################################## function pinApp() { - global $caPaths; + global $caPaths; - $repository = getPost("repository","oops"); - $name = getPost("name","oops"); - $pinnedApps = readJsonFile($caPaths['pinnedV2']); - if (isset($pinnedApps["$repository&$name"]) ) - $pinnedApps["$repository&$name"] = false; - else - $pinnedApps["$repository&$name"] = "$repository&$name"; - $pinnedApps = array_filter($pinnedApps); - writeJsonFile($caPaths['pinnedV2'],$pinnedApps); - postReturn(['status' => in_array(true,$pinnedApps)]); + $repository = getPost("repository","oops"); + $name = getPost("name","oops"); + $pinnedApps = readJsonFile($caPaths['pinnedV2']); + if (isset($pinnedApps["$repository&$name"]) ) + $pinnedApps["$repository&$name"] = false; + else + $pinnedApps["$repository&$name"] = "$repository&$name"; + $pinnedApps = array_filter($pinnedApps); + writeJsonFile($caPaths['pinnedV2'],$pinnedApps); + postReturn(['status' => in_array(true,$pinnedApps)]); } ###################################### # Gets if any apps are pinned or not # ###################################### function areAppsPinned() { - global $caPaths; + global $caPaths; - postReturn(['status' => in_array(true,readJsonFile($caPaths['pinnedV2']))]); + postReturn(['status' => in_array(true,readJsonFile($caPaths['pinnedV2']))]); } #################################### # Displays the pinned applications # #################################### function pinnedApps() { - global $caPaths, $caSettings; + global $caPaths, $caSettings; - $pinnedApps = readJsonFile($caPaths['pinnedV2']); - $file = &$GLOBALS['templates']; - @unlink($caPaths['community-templates-allSearchResults']); - @unlink($caPaths['community-templates-catSearchResults']); - @unlink($caPaths['repositoriesDisplayed']); - @unlink($caPaths['startupDisplayed']); - @unlink($caPaths['dockerSearchActive']); + $pinnedApps = readJsonFile($caPaths['pinnedV2']); + $file = &$GLOBALS['templates']; + @unlink($caPaths['community-templates-allSearchResults']); + @unlink($caPaths['community-templates-catSearchResults']); + @unlink($caPaths['repositoriesDisplayed']); + @unlink($caPaths['startupDisplayed']); + @unlink($caPaths['dockerSearchActive']); - $displayed = []; - foreach ($pinnedApps as $pinned) { - $startIndex = 0; - $search = explode("&",$pinned); - for ($i=0;$i<10;$i++) { - $index = searchArray($file,"Repository",$search[0],$startIndex); - if ( $index === false && (strpos($search[0],"library/") !== false)) { - $index = searchArray($file,"Repository",str_replace("library/","",$search[0]),$startIndex); - } + $displayed = []; + foreach ($pinnedApps as $pinned) { + $startIndex = 0; + $search = explode("&",$pinned); + for ($i=0;$i<10;$i++) { + $index = searchArray($file,"Repository",$search[0],$startIndex); + if ( $index === false && (strpos($search[0],"library/") !== false)) { + $index = searchArray($file,"Repository",str_replace("library/","",$search[0]),$startIndex); + } - if ( $index !== false ) { - if ( $file[$index]['Blacklist'] ) { #This handles things like duplicated templates - $startIndex = $index + 1; - continue; - } - if ($file[$index]['SortName'] !== $search[1]) { - $startIndex = $index +1; - continue; - } - if (!$file[$index]['Compatible'] && $caSettings['hideIncompatible'] == "true") { - $startIndex = $index +1; - continue; - } - $displayed[] = $file[$index]; - break; - } - } - } - usort($displayed,"mySort"); - if ( empty($displayed) ) - $script = "$('.caPinnedMenu').addClass('caMenuDisabled').removeClass('caMenuEnabled');"; - $displayedApplications['community'] = $displayed; - $displayedApplications['pinnedFlag'] = true; - writeJsonFile($caPaths['community-templates-displayed'],$displayedApplications); - postReturn(["status"=>"ok","script"=>$script ?? ""]); + if ( $index !== false ) { + if ( $file[$index]['Blacklist'] ) { #This handles things like duplicated templates + $startIndex = $index + 1; + continue; + } + if ($file[$index]['SortName'] !== $search[1]) { + $startIndex = $index +1; + continue; + } + if (!$file[$index]['Compatible'] && $caSettings['hideIncompatible'] == "true") { + $startIndex = $index +1; + continue; + } + $displayed[] = $file[$index]; + break; + } + } + } + usort($displayed,"mySort"); + if ( empty($displayed) ) + $script = "$('.caPinnedMenu').addClass('caMenuDisabled').removeClass('caMenuEnabled');"; + $displayedApplications['community'] = $displayed; + $displayedApplications['pinnedFlag'] = true; + writeJsonFile($caPaths['community-templates-displayed'],$displayedApplications); + postReturn(["status"=>"ok","script"=>$script ?? ""]); } ################################################ # Displays the possible branch tags for an app # ################################################ function displayTags() { - $leadTemplate = getPost("leadTemplate","oops"); - $rename = getPost("rename","false"); - postReturn(['tags'=>formatTags($leadTemplate,$rename)]); + $leadTemplate = getPost("leadTemplate","oops"); + $rename = getPost("rename","false"); + postReturn(['tags'=>formatTags($leadTemplate,$rename)]); } ########################################### # Displays The Statistics For The Appfeed # ########################################### function statistics() { - global $caPaths, $caSettings; + global $caPaths, $caSettings; - @unlink($caPaths['community-templates-displayed']); - @unlink($caPaths['community-templates-allSearchResults']); - @unlink($caPaths['community-templates-catSearchResults']); - if ( ! is_file($caPaths['statistics']) ) - $statistics = download_json($caPaths['statisticsURL'],$caPaths['statistics']); - else - $statistics = readJsonFile($caPaths['statistics']); + @unlink($caPaths['community-templates-displayed']); + @unlink($caPaths['community-templates-allSearchResults']); + @unlink($caPaths['community-templates-catSearchResults']); + if ( ! is_file($caPaths['statistics']) ) + $statistics = download_json($caPaths['statisticsURL'],$caPaths['statistics']); + else + $statistics = readJsonFile($caPaths['statistics']); - download_json($caPaths['moderationURL'],$caPaths['moderation']); - $statistics['totalModeration'] = count(readJsonFile($caPaths['moderation'])); - $repositories = readJsonFile($caPaths['repositoryList']); - $templates = &$GLOBALS['templates']; - pluginDupe(); - $invalidXML = readJsonFile($caPaths['invalidXML_txt']); - $statistics['blacklist'] = $statistics['plugin'] = $statistics['docker'] = $statistics['private'] = $statistics['totalDeprecated'] = $statistics['totalIncompatible'] = $statistics['official'] = $statistics['invalidXML'] = 0; + download_json($caPaths['moderationURL'],$caPaths['moderation']); + $statistics['totalModeration'] = count(readJsonFile($caPaths['moderation'])); + $repositories = readJsonFile($caPaths['repositoryList']); + $templates = &$GLOBALS['templates']; + pluginDupe(); + $invalidXML = readJsonFile($caPaths['invalidXML_txt']); + $statistics['blacklist'] = $statistics['plugin'] = $statistics['docker'] = $statistics['private'] = $statistics['totalDeprecated'] = $statistics['totalIncompatible'] = $statistics['official'] = $statistics['invalidXML'] = 0; - foreach ($templates as $template) { - if ( ($template['Deprecated']??false) && ! ($template['Blacklist']??false) && ! ($template['BranchID']??false)) $statistics['totalDeprecated']++; + foreach ($templates as $template) { + if ( ($template['Deprecated']??false) && ! ($template['Blacklist']??false) && ! ($template['BranchID']??false)) $statistics['totalDeprecated']++; - if ( ! ($template['Compatible']??false) ) $statistics['totalIncompatible']++; + if ( ! ($template['Compatible']??false) ) $statistics['totalIncompatible']++; - if ( $template['Blacklist']??false ) $statistics['blacklist']++; + if ( $template['Blacklist']??false ) $statistics['blacklist']++; - if ( ($template['Private']??false) && ! ($template['Blacklist']??false)) { - if ( ! ($caSettings['hideDeprecated'] == 'true' && ($template['Deprecated']??false)) ) - $statistics['private']++; - } + if ( ($template['Private']??false) && ! ($template['Blacklist']??false)) { + if ( ! ($caSettings['hideDeprecated'] == 'true' && ($template['Deprecated']??false)) ) + $statistics['private']++; + } - if ( ($template['Official']??false) && ! ($template['Blacklist']??false) ) - $statistics['official']++; + if ( ($template['Official']??false) && ! ($template['Blacklist']??false) ) + $statistics['official']++; - if ( ! ($template['PluginURL']??false) && ! ($template['Repository']??false) ) - $statistics['invalidXML']++; - else { - if ( $template['PluginURL'] ?? false) - $statistics['plugin']++; - else { - if ( $template['BranchID'] ?? false) { - continue; - } else { - $statistics['docker']++; - } - } - } - } - $statistics['totalApplications'] = $statistics['plugin']+$statistics['docker']; - if ( $statistics['fixedTemplates'] ) - writeJsonFile($caPaths['fixedTemplates_txt'],$statistics['fixedTemplates']); - else - @unlink($caPaths['fixedTemplates_txt']); + if ( ! ($template['PluginURL']??false) && ! ($template['Repository']??false) ) + $statistics['invalidXML']++; + else { + if ( $template['PluginURL'] ?? false) + $statistics['plugin']++; + else { + if ( $template['BranchID'] ?? false) { + continue; + } else { + $statistics['docker']++; + } + } + } + } + $statistics['totalApplications'] = $statistics['plugin']+$statistics['docker']; + if ( $statistics['fixedTemplates'] ) + writeJsonFile($caPaths['fixedTemplates_txt'],$statistics['fixedTemplates']); + else + @unlink($caPaths['fixedTemplates_txt']); - if ( is_file($caPaths['lastUpdated-old']) ) - $appFeedTime = readJsonFile($caPaths['lastUpdated-old']); + if ( is_file($caPaths['lastUpdated-old']) ) + $appFeedTime = readJsonFile($caPaths['lastUpdated-old']); - $updateTime = tr(date("F",$appFeedTime['last_updated_timestamp']),0).date(" d, Y @ g:i a",$appFeedTime['last_updated_timestamp']); - $defaultArray = ['caFixed' => 0,'totalApplications' => 0, 'repository' => 0, 'docker' => 0, 'plugin' => 0, 'invalidXML' => 0, 'blacklist' => 0, 'totalIncompatible' =>0, 'totalDeprecated' => 0, 'totalModeration' => 0, 'private' => 0, 'NoSupport' => 0]; - $statistics = array_merge($defaultArray,$statistics); + $updateTime = tr(date("F",$appFeedTime['last_updated_timestamp']),0).date(" d, Y @ g:i a",$appFeedTime['last_updated_timestamp']); + $defaultArray = ['caFixed' => 0,'totalApplications' => 0, 'repository' => 0, 'docker' => 0, 'plugin' => 0, 'invalidXML' => 0, 'blacklist' => 0, 'totalIncompatible' =>0, 'totalDeprecated' => 0, 'totalModeration' => 0, 'private' => 0, 'NoSupport' => 0]; + $statistics = array_merge($defaultArray,$statistics); - foreach ($statistics as &$stat) { - if ( ! $stat ) $stat = "0"; - } + foreach ($statistics as &$stat) { + if ( ! $stat ) $stat = "0"; + } - $currentServer = @file_get_contents($caPaths['currentServer']); - if ( $currentServer != "Primary Server" ) - $currentServer = " $currentServer"; + $currentServer = @file_get_contents($caPaths['currentServer']); + if ( $currentServer != "Primary Server" ) + $currentServer = " $currentServer"; - $statistics['invalidXML'] = @count($invalidXML) ?: tr("unknown"); - $statistics['repositories'] = @count($repositories) ?: tr("unknown"); + $statistics['invalidXML'] = @count($invalidXML) ?: tr("unknown"); + $statistics['repositories'] = @count($repositories) ?: tr("unknown"); - $o = " -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "; - if ($statistics['private']) { - $o .= ""; - } - $o .= " - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
- Community Applications -
-
- ".tr("Last Change To Application Feed")." - - $updateTime
".tr($currentServer)." -
- ".tr("Docker Applications")." - - {$statistics['docker']} -
- ".tr("Plugin Applications")." - - {$statistics['plugin']} -
- ".tr("Templates")." - - {$statistics['totalApplications']} -
- ".tr("Official Containers")." - - {$statistics['official']} -
- ".tr("Repositories")." - - {$statistics['repositories']} -
".tr("Private Docker Applications")."{$statistics['private']}
- ".tr("Invalid Templates")." - - {$statistics['invalidXML']} -
- ".tr("Template Errors")." - - {$statistics['caFixed']}+ -
- ".tr("Blacklisted Apps")." - - {$statistics['blacklist']} -
- ".tr("Incompatible Applications")." - - {$statistics['totalIncompatible']} -
- ".tr("Deprecated Applications")." - - {$statistics['totalDeprecated']} -
- ".tr("Moderation Entries")." - - {$statistics['totalModeration']}+ -
- ".tr("Primary Server")." / ".tr("Backup Server")." -
- "; + $o = " +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "; + if ($statistics['private']) { + $o .= ""; + } + $o .= " + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+ Community Applications +
+
+ ".tr("Last Change To Application Feed")." + + $updateTime
".tr($currentServer)." +
+ ".tr("Docker Applications")." + + {$statistics['docker']} +
+ ".tr("Plugin Applications")." + + {$statistics['plugin']} +
+ ".tr("Templates")." + + {$statistics['totalApplications']} +
+ ".tr("Official Containers")." + + {$statistics['official']} +
+ ".tr("Repositories")." + + {$statistics['repositories']} +
".tr("Private Docker Applications")."{$statistics['private']}
+ ".tr("Invalid Templates")." + + {$statistics['invalidXML']} +
+ ".tr("Template Errors")." + + {$statistics['caFixed']}+ +
+ ".tr("Blacklisted Apps")." + + {$statistics['blacklist']} +
+ ".tr("Incompatible Applications")." + + {$statistics['totalIncompatible']} +
+ ".tr("Deprecated Applications")." + + {$statistics['totalDeprecated']} +
+ ".tr("Moderation Entries")." + + {$statistics['totalModeration']}+ +
+ ".tr("Primary Server")." / ".tr("Backup Server")." +
+ "; - postReturn(['statistics'=>$o]); + postReturn(['statistics'=>$o]); } #################################################### # Creates the entries for autocomplete on searches # #################################################### function populateAutoComplete() { - global $caPaths, $caSettings; + global $caPaths, $caSettings; - $templates = null; - while ( ! $templates ) { - $templates = &$GLOBALS['templates']; - if ( ! $templates ) - sleep(1); - } - $autoComplete = array_map(function($x){return str_replace(":","",tr($x['Cat']));},readJsonFile($caPaths['categoryList'])); - foreach ($templates as $template) { - if ( $template['RepoTemplate'] ) - continue; - if ( ! $template['Blacklist'] && ! ($template['Deprecated'] && $caSettings['hideDeprecated'] == "true") && ($template['Compatible'] || $caSettings['hideIncompatible'] != "true") || ($template['Featured']??false) ) { - if ( $template['Language'] && $template['LanguageLocal'] ) { - $autoComplete[strtolower($template['Language'])] = $template['Language']; - $autoComplete[strtolower($template['LanguageLocal'])] = $template['LanguageLocal']; - } else { - if ( isset($template['Repo']) ) - $autoComplete[$template['Repo']] = $template['Repo']; - } - $name = trim(strtolower($template['SortName'])); + $templates = null; + while ( ! $templates ) { + $templates = &$GLOBALS['templates']; + if ( ! $templates ) + sleep(1); + } + $autoComplete = array_map(function($x){return str_replace(":","",tr($x['Cat']));},readJsonFile($caPaths['categoryList'])); + foreach ($templates as $template) { + if ( $template['RepoTemplate'] ) + continue; + if ( ! $template['Blacklist'] && ! ($template['Deprecated'] && $caSettings['hideDeprecated'] == "true") && ($template['Compatible'] || $caSettings['hideIncompatible'] != "true") || ($template['Featured']??false) ) { + if ( $template['Language'] && $template['LanguageLocal'] ) { + $autoComplete[strtolower($template['Language'])] = $template['Language']; + $autoComplete[strtolower($template['LanguageLocal'])] = $template['LanguageLocal']; + } else { + if ( isset($template['Repo']) ) + $autoComplete[$template['Repo']] = $template['Repo']; + } + $name = trim(strtolower($template['SortName'])); - $autoComplete[$name] = $name; - if ( startsWith($autoComplete[$name],"dynamix ") ) - $autoComplete[$name] = str_replace("dynamix ","",$autoComplete[$name]); - if ( startsWith($autoComplete[$name],"ca ") ) - $autoComplete[$name] = str_replace("ca ","",$autoComplete[$name]); - if ( startsWith($autoComplete[$name],"binhex ") ) - $autoComplete[$name] = str_replace("binhex ","",$autoComplete[$name]); - if ( startsWith($autoComplete[$name],"activ ") ) - $autoComplete[$name] = str_replace("activ ","",$autoComplete[$name]); + $autoComplete[$name] = $name; + if ( startsWith($autoComplete[$name],"dynamix ") ) + $autoComplete[$name] = str_replace("dynamix ","",$autoComplete[$name]); + if ( startsWith($autoComplete[$name],"ca ") ) + $autoComplete[$name] = str_replace("ca ","",$autoComplete[$name]); + if ( startsWith($autoComplete[$name],"binhex ") ) + $autoComplete[$name] = str_replace("binhex ","",$autoComplete[$name]); + if ( startsWith($autoComplete[$name],"activ ") ) + $autoComplete[$name] = str_replace("activ ","",$autoComplete[$name]); - if ( ! isset($autoComplete[strtolower($template['Author'])."'s Repository"]) && ! isset($autoComplete[strtolower($template['Author']."' Repository")])) { - $autoComplete[strtolower($template['Author'])] = $template['Author']; - } + if ( ! isset($autoComplete[strtolower($template['Author'])."'s Repository"]) && ! isset($autoComplete[strtolower($template['Author']."' Repository")])) { + $autoComplete[strtolower($template['Author'])] = $template['Author']; + } - if ( $template['ExtraSearchTerms'] ) { - foreach (explode(" ",$template['ExtraSearchTerms']) as $searchTerm) { - $searchTerm = str_replace("%20"," ",$searchTerm); - $autoComplete[strtolower($searchTerm)] = strtolower($searchTerm); - } - } - } - } - $autoComplete[tr("language")] = tr("Language"); + if ( $template['ExtraSearchTerms'] ) { + foreach (explode(" ",$template['ExtraSearchTerms']) as $searchTerm) { + $searchTerm = str_replace("%20"," ",$searchTerm); + $autoComplete[strtolower($searchTerm)] = strtolower($searchTerm); + } + } + } + } + $autoComplete[tr("language")] = tr("Language"); - postReturn(['autocomplete'=>array_values(array_filter(array_unique($autoComplete)))]); + postReturn(['autocomplete'=>array_values(array_filter(array_unique($autoComplete)))]); } ########################## # Displays the changelog # ########################## function caChangeLog() { - $o = "
"; - $o .= "
".tr("Community Applications Changelog")."


"; - postReturn(["changelog"=>$o.Markdown(plugin("changes","/var/log/plugins/community.applications.plg"))."

"]); + $o = "
"; + $o .= "
".tr("Community Applications Changelog")."


"; + postReturn(["changelog"=>$o.Markdown(plugin("changes","/var/log/plugins/community.applications.plg"))."

"]); } ############################### # Populates the category list # ############################### function get_categories() { - global $caPaths, $sortOrder, $caSettings, $DockerClient, $DockerTemplates; - $categories = readJsonFile($caPaths['categoryList']); - if ( ! is_array($categories) || empty($categories) ) { - $cat = "Category list N/A

"; - postReturn(['categories'=>$cat]); - return; - } else { - $categories[] = ["Des"=>"Language","Cat"=>"Language:"]; + global $caPaths, $sortOrder, $caSettings, $DockerClient, $DockerTemplates; + $categories = readJsonFile($caPaths['categoryList']); + if ( ! is_array($categories) || empty($categories) ) { + $cat = "Category list N/A

"; + postReturn(['categories'=>$cat]); + return; + } else { + $categories[] = ["Des"=>"Language","Cat"=>"Language:"]; - foreach ($categories as $category) { - $category['Des'] = tr($category['Des']); - if ( isset($category['Sub']) && is_array($category['Sub']) ) { - unset($subCat); - foreach ($category['Sub'] as $subcategory) { - $subcategory['Des'] = tr($subcategory['Des']); - $subCat[] = $subcategory; - } - $category['Sub'] = $subCat; - } - $newCat[] = $category; - } - $sortOrder['sortBy'] = "Des"; - $sortOrder['sortDir'] = "Up"; - usort($newCat,"mySort"); // Sort it alphabetically according to the language. May not work right in non-roman charsets + foreach ($categories as $category) { + $category['Des'] = tr($category['Des']); + if ( isset($category['Sub']) && is_array($category['Sub']) ) { + unset($subCat); + foreach ($category['Sub'] as $subcategory) { + $subcategory['Des'] = tr($subcategory['Des']); + $subCat[] = $subcategory; + } + $category['Sub'] = $subCat; + } + $newCat[] = $category; + } + $sortOrder['sortBy'] = "Des"; + $sortOrder['sortDir'] = "Up"; + usort($newCat,"mySort"); // Sort it alphabetically according to the language. May not work right in non-roman charsets - $cat = ""; - foreach ($newCat as $category) { - $cat .= "
  • ".$category['Des']."
  • "; - if (isset($category['Sub']) && is_array($category['Sub'])) { - $cat .= "
      "; - foreach($category['Sub'] as $subcategory) { - $cat .= "
    • ".$subcategory['Des']."
    • "; - } - $cat .= "
    "; - } - } - $templates = &$GLOBALS['templates']; - foreach ($templates as $template) { - if ($template['Private'] == true && ! $template['Blacklist']) { - $cat .= "
  • ".tr("Private Apps")."
  • "; - break; - } - } - } - postReturn(["categories"=>$cat]); + $cat = ""; + foreach ($newCat as $category) { + $cat .= "
  • ".$category['Des']."
  • "; + if (isset($category['Sub']) && is_array($category['Sub'])) { + $cat .= "
      "; + foreach($category['Sub'] as $subcategory) { + $cat .= "
    • ".$subcategory['Des']."
    • "; + } + $cat .= "
    "; + } + } + $templates = &$GLOBALS['templates']; + foreach ($templates as $template) { + if ($template['Private'] == true && ! $template['Blacklist']) { + $cat .= "
  • ".tr("Private Apps")."
  • "; + break; + } + } + } + postReturn(["categories"=>$cat]); } ############################## # Get the html for the popup # ############################## function getPopupDescription() { - $appNumber = getPost("appPath",""); - postReturn(getPopupDescriptionSkin($appNumber)); + $appNumber = getPost("appPath",""); + postReturn(getPopupDescriptionSkin($appNumber)); } ################################# # Get the html for a repo popup # ################################# function getRepoDescription() { - $repository = html_entity_decode(getPost("repository",""),ENT_QUOTES); - postReturn(getRepoDescriptionSkin($repository)); + $repository = html_entity_decode(getPost("repository",""),ENT_QUOTES); + postReturn(getRepoDescriptionSkin($repository)); } ########################################### # Creates the XML for a container install # ########################################### function createXML() { - global $caPaths, $caSettings; + global $caPaths, $caSettings; - $xmlFile = getPost("xml",""); - $type = getPost("type",""); - if ( ! $xmlFile ) { - postReturn(["error"=>"CreateXML: XML file was missing"]); - return; - } - $templates = &$GLOBALS['templates']; - if ( ! $templates ) { - postReturn(["error"=>"Create XML: templates file missing or empty"]); - return; - } - if ( !startsWith($xmlFile,"/boot/") ) { - $index = searchArray($templates,"Path",$xmlFile); - if ( $index === false ) { - postReturn(["error"=>"Create XML: couldn't find template with path of $xmlFile"]); - return; - } - $template = $templates[$index]; - if ( $template['OriginalOverview'] ) - $template['Overview'] = $template['OriginalOverview']; - if ( $template['OriginalDescription'] ) - $template['Description'] = $template['OriginalDescription']; - $template['Icon'] = $template["Icon-{$caSettings['dynamixTheme']}"] ?? $template['Icon']; - + $xmlFile = getPost("xml",""); + $type = getPost("type",""); + if ( ! $xmlFile ) { + postReturn(["error"=>"CreateXML: XML file was missing"]); + return; + } + $templates = &$GLOBALS['templates']; + if ( ! $templates ) { + postReturn(["error"=>"Create XML: templates file missing or empty"]); + return; + } + if ( !startsWith($xmlFile,"/boot/") ) { + $index = searchArray($templates,"Path",$xmlFile); + if ( $index === false ) { + postReturn(["error"=>"Create XML: couldn't find template with path of $xmlFile"]); + return; + } + $template = $templates[$index]; + if ( $template['OriginalOverview'] ) + $template['Overview'] = $template['OriginalOverview']; + if ( $template['OriginalDescription'] ) + $template['Description'] = $template['OriginalDescription']; + $template['Icon'] = $template["Icon-{$caSettings['dynamixTheme']}"] ?? $template['Icon']; + // Handle paths directly referencing disks / poola that aren't present in the user's system, and replace the path with the first disk present - $unRaidDisks = parse_ini_file($caPaths['disksINI'],true); + $unRaidDisks = parse_ini_file($caPaths['disksINI'],true); - $disksPresent = array_keys(array_filter($unRaidDisks, function($k) { - return ($k['status'] !== "DISK_NP" && ! preg_match("/(parity|parity2|disks|diskP|diskQ)/",$k['name'])); - })); + $disksPresent = array_keys(array_filter($unRaidDisks, function($k) { + return ($k['status'] !== "DISK_NP" && ! preg_match("/(parity|parity2|disks|diskP|diskQ)/",$k['name'])); + })); - $unRaidVersion = parse_ini_file($caPaths['unRaidVersion']); - $cachePools = array_filter($unRaidDisks, function($k) { - return ! preg_match("/disk\d(\d|$)|(parity|parity2|disks|flash|diskP|diskQ)/",$k['name']); - }); - $cachePools = array_keys(array_filter($cachePools, function($k) { - return $k['status'] !== "DISK_NP"; - })); + $unRaidVersion = parse_ini_file($caPaths['unRaidVersion']); + $cachePools = array_filter($unRaidDisks, function($k) { + return ! preg_match("/disk\d(\d|$)|(parity|parity2|disks|flash|diskP|diskQ)/",$k['name']); + }); + $cachePools = array_keys(array_filter($cachePools, function($k) { + return $k['status'] !== "DISK_NP"; + })); - // always prefer the default cache pool - if ( in_array("cache",$cachePools) ) - array_unshift($cachePools,"cache"); // This will be a duplicate, but it doesn't matter as we only reference item0 + // always prefer the default cache pool + if ( in_array("cache",$cachePools) ) + array_unshift($cachePools,"cache"); // This will be a duplicate, but it doesn't matter as we only reference item0 - // Prefer cache pools over disks - $disksPresent = array_merge($cachePools,$disksPresent,["disks"]); + // Prefer cache pools over disks + $disksPresent = array_merge($cachePools,$disksPresent,["disks"]); - // check to see if user shares enabled - $unRaidVars = parse_ini_file($caPaths['unRaidVars']); - if ( $unRaidVars['shareUser'] == "e" ) - $disksPresent[] = "user"; - if ( @is_array($template['Data']['Volume']) ) { - $testarray = $template['Data']['Volume']; - if ( ( ! isset($testarray[0]) ) || ( ! is_array($testarray[0]) ) ) $testarray = [$testarray]; - foreach ($testarray as &$volume) { - $diskReferenced = array_values(array_filter(explode("/",$volume['HostDir']))); - if ( $diskReferenced[0] == "mnt" && $diskReferenced[1] && ! in_array($diskReferenced[1],$disksPresent) ) { - $volume['HostDir'] = str_replace("/mnt/{$diskReferenced[1]}/","/mnt/{$disksPresent[0]}/",$volume['HostDir']); - } - } - $template['Data']['Volume'] = $testarray; - } + // check to see if user shares enabled + $unRaidVars = parse_ini_file($caPaths['unRaidVars']); + if ( $unRaidVars['shareUser'] == "e" ) + $disksPresent[] = "user"; + if ( @is_array($template['Data']['Volume']) ) { + $testarray = $template['Data']['Volume']; + if ( ( ! isset($testarray[0]) ) || ( ! is_array($testarray[0]) ) ) $testarray = [$testarray]; + foreach ($testarray as &$volume) { + $diskReferenced = array_values(array_filter(explode("/",$volume['HostDir']))); + if ( $diskReferenced[0] == "mnt" && $diskReferenced[1] && ! in_array($diskReferenced[1],$disksPresent) ) { + $volume['HostDir'] = str_replace("/mnt/{$diskReferenced[1]}/","/mnt/{$disksPresent[0]}/",$volume['HostDir']); + } + } + $template['Data']['Volume'] = $testarray; + } - if ( $template['Config'] ) { - $testarray = $template['Config'] ?: []; - if (!($testarray[0]??false)) $testarray = [$testarray]; + if ( $template['Config'] ) { + $testarray = $template['Config'] ?: []; + if (!($testarray[0]??false)) $testarray = [$testarray]; - foreach ($testarray as &$config) { - if ( is_array($config['@attributes']) ) { - if ( $config['@attributes']['Type'] == "Path" ) { - $defaultReferenced = array_values(array_filter(explode("/",$config['@attributes']['Default']))); + foreach ($testarray as &$config) { + if ( is_array($config['@attributes']) ) { + if ( $config['@attributes']['Type'] == "Path" ) { + $defaultReferenced = array_values(array_filter(explode("/",$config['@attributes']['Default']))); - if ( isset($defaultReferenced[0]) && isset($defaultReferenced[1]) ) { - if ( $defaultReferenced[0] == "mnt" && $defaultReferenced[1] && ! in_array($defaultReferenced[1],$disksPresent) ) - $config['@attributes']['Default'] = str_replace("/mnt/{$defaultReferenced[1]}/","/mnt/{$disksPresent[0]}/",$config['@attributes']['Default']); - } + if ( isset($defaultReferenced[0]) && isset($defaultReferenced[1]) ) { + if ( $defaultReferenced[0] == "mnt" && $defaultReferenced[1] && ! in_array($defaultReferenced[1],$disksPresent) ) + $config['@attributes']['Default'] = str_replace("/mnt/{$defaultReferenced[1]}/","/mnt/{$disksPresent[0]}/",$config['@attributes']['Default']); + } - $valueReferenced = array_values(array_filter(explode("/",$config['value']))); - if ( isset($valueReferenced[0]) && isset($valueReferenced[1]) ) { - if ( $valueReferenced[0] == "mnt" && $valueReferenced[1] && ! in_array($valueReferenced[1],$disksPresent) ) - $config['value'] = str_replace("/mnt/{$valueReferenced[1]}/","/mnt/{$disksPresent[0]}/",$config['value']); - } + $valueReferenced = array_values(array_filter(explode("/",$config['value']))); + if ( isset($valueReferenced[0]) && isset($valueReferenced[1]) ) { + if ( $valueReferenced[0] == "mnt" && $valueReferenced[1] && ! in_array($valueReferenced[1],$disksPresent) ) + $config['value'] = str_replace("/mnt/{$valueReferenced[1]}/","/mnt/{$disksPresent[0]}/",$config['value']); + } - // Check for pre-existing folders only differing by "case" and adjust accordingly + // Check for pre-existing folders only differing by "case" and adjust accordingly - // Default path - if ( ! $config['value'] ) { // Don't override default if value exists - $configPath = explode("/",$config['@attributes']['Default']); - $testPath = "/"; - foreach ($configPath as &$entry) { - $directories = @scandir($testPath); - if ( ! $directories ) { - break; - } - foreach ($directories as $testDir) { - if ( strtolower($testDir) == strtolower($entry) ) { - if ( $testDir == $entry ) - break; + // Default path + if ( ! $config['value'] ) { // Don't override default if value exists + $configPath = explode("/",$config['@attributes']['Default']); + $testPath = "/"; + foreach ($configPath as &$entry) { + $directories = @scandir($testPath); + if ( ! $directories ) { + break; + } + foreach ($directories as $testDir) { + if ( strtolower($testDir) == strtolower($entry) ) { + if ( $testDir == $entry ) + break; - $entry = $testDir; - } - } - $testPath .= $entry."/"; - } - $config['@attributes']['Default'] = implode("/",$configPath); - } + $entry = $testDir; + } + } + $testPath .= $entry."/"; + } + $config['@attributes']['Default'] = implode("/",$configPath); + } - // entered path - if ( $config['value'] ) { - $configPath = explode("/",$config['value']); - $testPath = "/"; - foreach ($configPath as &$entry) { - $directories = @scandir($testPath); - if ( ! $directories ) { - break; - } - foreach ($directories as $testDir) { - if ( strtolower($testDir) == strtolower($entry) ) { - if ( $testDir == $entry ) - break; + // entered path + if ( $config['value'] ) { + $configPath = explode("/",$config['value']); + $testPath = "/"; + foreach ($configPath as &$entry) { + $directories = @scandir($testPath); + if ( ! $directories ) { + break; + } + foreach ($directories as $testDir) { + if ( strtolower($testDir) == strtolower($entry) ) { + if ( $testDir == $entry ) + break; - $entry = $testDir; - } - } - $testPath .= $entry."/"; - } - $config['value'] = implode("/",$configPath); - } - } - } - } - $template['Config'] = $testarray; - } - $template['Name'] = str_replace(" ","-",$template['Name']); - $alreadyInstalled = getAllInfo(); - foreach ( $alreadyInstalled as $installed ) { - if ( strtolower($template['Name']) == $installed['Name'] ) { - for ( ;; ) { - if (is_file("{$caPaths['dockerManTemplates']}/my-{$template['Name']}.xml") ) { - $template['Name'] .= "-1"; - } else break; - } - } - } - for ( ;; ) { - if ($type == "second" && is_file("{$caPaths['dockerManTemplates']}/my-{$template['Name']}.xml") ) { - $template['Name'] .= "-1"; - } else break; - } - if (! isset($template['Environment']) ) - $template['Environment']['Variable'] = ["Name"=>"test","Value"=>"yes"]; - if ( empty($template['Config']) ) // handles extra garbage entry being created on templates that are v1 only - unset($template['Config']); - $xml = makeXML($template); - @mkdir(dirname($xmlFile)); - ca_file_put_contents($xmlFile,$xml); - } - postReturn(["status"=>"ok","cache"=>$cacheVolume ?? ""]); + $entry = $testDir; + } + } + $testPath .= $entry."/"; + } + $config['value'] = implode("/",$configPath); + } + } + } + } + $template['Config'] = $testarray; + } + $template['Name'] = str_replace(" ","-",$template['Name']); + $alreadyInstalled = getAllInfo(); + foreach ( $alreadyInstalled as $installed ) { + if ( strtolower($template['Name']) == $installed['Name'] ) { + for ( ;; ) { + if (is_file("{$caPaths['dockerManTemplates']}/my-{$template['Name']}.xml") ) { + $template['Name'] .= "-1"; + } else break; + } + } + } + for ( ;; ) { + if ($type == "second" && is_file("{$caPaths['dockerManTemplates']}/my-{$template['Name']}.xml") ) { + $template['Name'] .= "-1"; + } else break; + } + if (! isset($template['Environment']) ) + $template['Environment']['Variable'] = ["Name"=>"test","Value"=>"yes"]; + if ( empty($template['Config']) ) // handles extra garbage entry being created on templates that are v1 only + unset($template['Config']); + $xml = makeXML($template); + @mkdir(dirname($xmlFile)); + ca_file_put_contents($xmlFile,$xml); + } + postReturn(["status"=>"ok","cache"=>$cacheVolume ?? ""]); } ######################## # Switch to a language # ######################## function switchLanguage() { - global $caPaths; + global $caPaths; - $language = getPost("language",""); - if ( $language == "en_US" ) - $language = ""; + $language = getPost("language",""); + if ( $language == "en_US" ) + $language = ""; - if ( ! is_dir("/usr/local/emhttp/languages/$language") ) { - postReturn(["error"=>"language $language is not installed"]); - return; - } - $dynamixSettings = @parse_ini_file($caPaths['dynamixSettings'],true); - $dynamixSettings['display']['locale'] = $language; - write_ini_file($caPaths['dynamixSettings'],$dynamixSettings); - postReturn(["status"=> "ok"]); + if ( ! is_dir("/usr/local/emhttp/languages/$language") ) { + postReturn(["error"=>"language $language is not installed"]); + return; + } + $dynamixSettings = @parse_ini_file($caPaths['dynamixSettings'],true); + $dynamixSettings['display']['locale'] = $language; + write_ini_file($caPaths['dynamixSettings'],$dynamixSettings); + postReturn(["status"=> "ok"]); } ####################################################### # Delete multiple checked off apps from previous apps # ####################################################### function remove_multiApplications() { - $apps = getPostArray("apps"); - if ( ! count($apps) ) { - postReturn(["error"=>"No apps were in post when trying to remove multiple applications"]); - return; - } - foreach ($apps as $app) { - if ( strpos(realpath($app),"/boot/config/") === false ) { - $error = "Remove multiple apps: $app was not in /boot/config"; - break; - } - @unlink($app); - } - if ( $error ) - postReturn(["error"=>$error]); - else - postReturn(["status"=>"ok"]); + $apps = getPostArray("apps"); + if ( ! count($apps) ) { + postReturn(["error"=>"No apps were in post when trying to remove multiple applications"]); + return; + } + foreach ($apps as $app) { + if ( strpos(realpath($app),"/boot/config/") === false ) { + $error = "Remove multiple apps: $app was not in /boot/config"; + break; + } + @unlink($app); + } + if ( $error ) + postReturn(["error"=>$error]); + else + postReturn(["status"=>"ok"]); } ############################################ # Get's the categories present on a search # ############################################ function getCategoriesPresent() { - global $caPaths; + global $caPaths; - if ( is_file($caPaths['community-templates-allSearchResults']) ) - $displayed = readJsonFile($caPaths['community-templates-allSearchResults']); - else - $displayed = readJsonFile($caPaths['community-templates-displayed']); + if ( is_file($caPaths['community-templates-allSearchResults']) ) + $displayed = readJsonFile($caPaths['community-templates-allSearchResults']); + else + $displayed = readJsonFile($caPaths['community-templates-displayed']); - $categories = []; - foreach ($displayed['community'] as $template) { - $cats = explode(" ",$template['Category']); - foreach ($cats as $category) { - if (strpos($category,":")) { - $categories[] = explode(":",$category)[0].":"; - } - $categories[] = $category; - } - } - if (! empty($categories) ) { - $categories[] = "repos"; - $categories[] = "All"; - } + $categories = []; + foreach ($displayed['community'] as $template) { + $cats = explode(" ",$template['Category']); + foreach ($cats as $category) { + if (strpos($category,":")) { + $categories[] = explode(":",$category)[0].":"; + } + $categories[] = $category; + } + } + if (! empty($categories) ) { + $categories[] = "repos"; + $categories[] = "All"; + } - postReturn(array_values(array_unique($categories))); + postReturn(array_values(array_unique($categories))); } ################################## # Set's the favourite repository # ################################## function toggleFavourite() { - global $caPaths, $caSettings; + global $caPaths, $caSettings; - $repository = html_entity_decode(getPost("repository",""),ENT_QUOTES); - if ( $caSettings['favourite'] == $repository ) - $repository = ""; + $repository = html_entity_decode(getPost("repository",""),ENT_QUOTES); + if ( $caSettings['favourite'] == $repository ) + $repository = ""; - $caSettings['favourite'] = $repository; - write_ini_file($caPaths['pluginSettings'],$caSettings); - postReturn(['status'=>"ok",'fav'=>$repository]); + $caSettings['favourite'] = $repository; + write_ini_file($caPaths['pluginSettings'],$caSettings); + postReturn(['status'=>"ok",'fav'=>$repository]); } #################################### # Returns the favourite repository # #################################### function getFavourite() { - global $caSettings; + global $caSettings; - postReturn(["favourite"=>$caSettings['favourite']]); + postReturn(["favourite"=>$caSettings['favourite']]); } ########################## # Changes the sort order # ########################## function changeSortOrder() { - global $caPaths, $sortOrder; + global $caPaths, $sortOrder; - $sortOrder = getPostArray("sortOrder"); - writeJsonFile($caPaths['sortOrder'],$sortOrder); + $sortOrder = getPostArray("sortOrder"); + writeJsonFile($caPaths['sortOrder'],$sortOrder); - if ( is_file($caPaths['community-templates-displayed']) ) { - $displayed = readJsonFile($caPaths['community-templates-displayed']); - if ($displayed['community']) - usort($displayed['community'],"mySort"); - writeJsonFile($caPaths['community-templates-displayed'],$displayed); - } - if ( is_file($caPaths['community-templates-allSearchResults']) ) { - $allSearchResults = readJsonFile($caPaths['community-templates-allSearchResults']); - if ( $allSearchResults['community'] ) - usort($allSearchResults['community'],"mySort"); - writeJsonFile($caPaths['community-templates-allSearchResults'],$allSearchResults); - } - if ( is_file($caPaths['community-templates-catSearchResults']) ) { - $catSearchResults = readJsonFile($caPaths['community-templates-catSearchResults']); - if ( $catSearchResults['community'] ) - usort($catSearchResults['community'],"mySort"); - writeJsonFile($caPaths['community-templates-catSearchResults'],$catSearchResults); - } - if ( is_file($caPaths['repositoriesDisplayed']) ) { - $reposDisplayed = readJsonFile($caPaths['repositoriesDisplayed']); - $bio = []; - $nonbio = []; - foreach ($reposDisplayed['community'] as $repo) { - if ($repo['bio']) - $bio[] = $repo; - else - $nonbio[] = $repo; - } - usort($bio,"mysort"); - usort($nonbio,"mysort"); - $reposDisplayed['community'] = array_merge($bio,$nonbio); - writeJsonFile($caPaths['repositoriesDisplayed'],$reposDisplayed); - } - postReturn(['status'=>"ok"]); + if ( is_file($caPaths['community-templates-displayed']) ) { + $displayed = readJsonFile($caPaths['community-templates-displayed']); + if ($displayed['community']) + usort($displayed['community'],"mySort"); + writeJsonFile($caPaths['community-templates-displayed'],$displayed); + } + if ( is_file($caPaths['community-templates-allSearchResults']) ) { + $allSearchResults = readJsonFile($caPaths['community-templates-allSearchResults']); + if ( $allSearchResults['community'] ) + usort($allSearchResults['community'],"mySort"); + writeJsonFile($caPaths['community-templates-allSearchResults'],$allSearchResults); + } + if ( is_file($caPaths['community-templates-catSearchResults']) ) { + $catSearchResults = readJsonFile($caPaths['community-templates-catSearchResults']); + if ( $catSearchResults['community'] ) + usort($catSearchResults['community'],"mySort"); + writeJsonFile($caPaths['community-templates-catSearchResults'],$catSearchResults); + } + if ( is_file($caPaths['repositoriesDisplayed']) ) { + $reposDisplayed = readJsonFile($caPaths['repositoriesDisplayed']); + $bio = []; + $nonbio = []; + foreach ($reposDisplayed['community'] as $repo) { + if ($repo['bio']) + $bio[] = $repo; + else + $nonbio[] = $repo; + } + usort($bio,"mysort"); + usort($nonbio,"mysort"); + $reposDisplayed['community'] = array_merge($bio,$nonbio); + writeJsonFile($caPaths['repositoriesDisplayed'],$reposDisplayed); + } + postReturn(['status'=>"ok"]); } ############################################ # Gets the sort order when restoring state # ############################################ function getSortOrder() { - global $sortOrder; + global $sortOrder; - postReturn(["sortBy"=>$sortOrder['sortBy'],"sortDir"=>$sortOrder['sortDir']]); + postReturn(["sortBy"=>$sortOrder['sortBy'],"sortDir"=>$sortOrder['sortDir']]); } ############################################################ # Reset the sort order to default when reloading Apps page # ############################################################ function defaultSortOrder() { - global $caPaths, $sortOrder; + global $caPaths, $sortOrder; - $sortOrder['sortBy'] = "Name"; - $sortOrder['sortDir'] = "Up"; - writeJsonFile($caPaths['sortOrder'],$sortOrder); - postReturn(['status'=>"ok"]); + $sortOrder['sortBy'] = "Name"; + $sortOrder['sortDir'] = "Up"; + writeJsonFile($caPaths['sortOrder'],$sortOrder); + postReturn(['status'=>"ok"]); } ################################################################### # Checks whether we're on the startup screen when restoring state # ################################################################### function onStartupScreen() { - global $caPaths; + global $caPaths; - postReturn(['status'=>is_file($caPaths['startupDisplayed'])]); + postReturn(['status'=>is_file($caPaths['startupDisplayed'])]); } ####################################################################### # convert_docker - called when system adds a container from dockerHub # ####################################################################### function convert_docker() { - global $caPaths, $dockerManPaths; + global $caPaths, $dockerManPaths; - $dockerID = getPost("ID",""); + $dockerID = getPost("ID",""); - $file = readJsonFile($caPaths['dockerSearchResults']); - $dockerIndex = searchArray($file['results'],"ID",$dockerID); - $docker = $file['results'][$dockerIndex]; - $docker['Description'] = str_replace("&", "&", $docker['Description']); + $file = readJsonFile($caPaths['dockerSearchResults']); + $dockerIndex = searchArray($file['results'],"ID",$dockerID); + $docker = $file['results'][$dockerIndex]; + $docker['Description'] = str_replace("&", "&", $docker['Description']); - $dockerfile['Name'] = $docker['Name']; - $dockerfile['Support'] = $docker['DockerHub']; - $dockerfile['Description'] = $docker['Description']."\n\nConverted By Community Applications Always verify this template (and values) against the support page for the container\n\n{$docker['DockerHub']}"; - $dockerfile['Overview'] = $dockerfile['Description']; - $dockerfile['Registry'] = $docker['DockerHub']; - $dockerfile['Repository'] = $docker['Repository']; - $dockerfile['BindTime'] = "true"; - $dockerfile['Privileged'] = "false"; - $dockerfile['Networking']['Mode'] = "bridge"; + $dockerfile['Name'] = $docker['Name']; + $dockerfile['Support'] = $docker['DockerHub']; + $dockerfile['Description'] = $docker['Description']."\n\nConverted By Community Applications Always verify this template (and values) against the support page for the container\n\n{$docker['DockerHub']}"; + $dockerfile['Overview'] = $dockerfile['Description']; + $dockerfile['Registry'] = $docker['DockerHub']; + $dockerfile['Repository'] = $docker['Repository']; + $dockerfile['BindTime'] = "true"; + $dockerfile['Privileged'] = "false"; + $dockerfile['Networking']['Mode'] = "bridge"; - $existing_templates = array_diff(scandir($dockerManPaths['templates-user']),[".",".."]); - foreach ( $existing_templates as $template ) { - if ( strtolower($dockerfile['Name']) == strtolower(str_replace(["my-",".xml"],["",""],$template)) ) - $dockerfile['Name'] .= "-1"; - } + $existing_templates = array_diff(scandir($dockerManPaths['templates-user']),[".",".."]); + foreach ( $existing_templates as $template ) { + if ( strtolower($dockerfile['Name']) == strtolower(str_replace(["my-",".xml"],["",""],$template)) ) + $dockerfile['Name'] .= "-1"; + } - $dockerXML = makeXML($dockerfile); + $dockerXML = makeXML($dockerfile); - ca_file_put_contents($caPaths['dockerSearchInstall'],$dockerXML); - postReturn(['xml'=>$caPaths['dockerSearchInstall']]); + ca_file_put_contents($caPaths['dockerSearchInstall'],$dockerXML); + postReturn(['xml'=>$caPaths['dockerSearchInstall']]); } ######################################################### # search_dockerhub - returns the results from dockerHub # ######################################################### function search_dockerhub() { - global $caPaths; + global $caPaths; - $filter = getPost("filter",""); - $pageNumber = getPost("page","1"); + $filter = getPost("filter",""); + $pageNumber = getPost("page","1"); - $communityTemplates = &$GLOBALS['templates']; - $filter = str_replace(" ","%20",$filter); - $filter = str_replace("/","%20",$filter); - $jsonPage = shell_exec("curl -s -X GET 'https://registry.hub.docker.com/v1/search?q=$filter&page=$pageNumber'"); - $pageresults = json_decode($jsonPage,true); - $num_pages = $pageresults['num_pages']; + $communityTemplates = &$GLOBALS['templates']; + $filter = str_replace(" ","%20",$filter); + $filter = str_replace("/","%20",$filter); + $jsonPage = shell_exec("curl -s -X GET 'https://registry.hub.docker.com/v1/search?q=$filter&page=$pageNumber'"); + $pageresults = json_decode($jsonPage,true); + $num_pages = $pageresults['num_pages']; - if ($pageresults['num_results'] == 0) { - $o['display'] = "
    ".tr("No Matching Applications Found On Docker Hub")."
    "; - $o['script'] = "$('#dockerSearch').hide();"; - postReturn($o); - @unlink($caPaths['dockerSearchResults']); - @unlink($caPaths['dockerSearchActive']); - return; - } + if ($pageresults['num_results'] == 0) { + $o['display'] = "
    ".tr("No Matching Applications Found On Docker Hub")."
    "; + $o['script'] = "$('#dockerSearch').hide();"; + postReturn($o); + @unlink($caPaths['dockerSearchResults']); + @unlink($caPaths['dockerSearchActive']); + return; + } - touch($caPaths['dockerSearchActive']); - $i = 0; - foreach ($pageresults['results'] as $result) { - unset($o); - $o['IconFA'] = "docker"; - $o['Repository'] = $result['name']; - $details = explode("/",$result['name']); - $o['Author'] = $details[0]; - $o['Name'] = $details[1]; - $o['Description'] = $result['description']; - $o['Automated'] = $result['is_automated']; - $o['Stars'] = $result['star_count']; - $o['Official'] = $result['is_official']; - $o['Trusted'] = $result['is_trusted']; - if ( $o['Official'] ) { - $o['DockerHub'] = "https://hub.docker.com/_/".$result['name']."/"; - $o['Name'] = $o['Author']; - } else - $o['DockerHub'] = "https://hub.docker.com/r/".$result['name']."/"; + touch($caPaths['dockerSearchActive']); + $i = 0; + foreach ($pageresults['results'] as $result) { + unset($o); + $o['IconFA'] = "docker"; + $o['Repository'] = $result['name']; + $details = explode("/",$result['name']); + $o['Author'] = $details[0]; + $o['Name'] = $details[1]; + $o['Description'] = $result['description']; + $o['Automated'] = $result['is_automated']; + $o['Stars'] = $result['star_count']; + $o['Official'] = $result['is_official']; + $o['Trusted'] = $result['is_trusted']; + if ( $o['Official'] ) { + $o['DockerHub'] = "https://hub.docker.com/_/".$result['name']."/"; + $o['Name'] = $o['Author']; + } else + $o['DockerHub'] = "https://hub.docker.com/r/".$result['name']."/"; - $o['ID'] = $i; - $searchName = str_replace("docker-","",$o['Name']); - $searchName = str_replace("-docker","",$searchName); + $o['ID'] = $i; + $searchName = str_replace("docker-","",$o['Name']); + $searchName = str_replace("-docker","",$searchName); - $dockerResults[$i] = addMissingVars($o); - $i=++$i; - } - $dockerFile['num_pages'] = $num_pages; - $dockerFile['page_number'] = $pageNumber; - $dockerFile['results'] = $dockerResults; + $dockerResults[$i] = addMissingVars($o); + $i=++$i; + } + $dockerFile['num_pages'] = $num_pages; + $dockerFile['page_number'] = $pageNumber; + $dockerFile['results'] = $dockerResults; - writeJsonFile($caPaths['dockerSearchResults'],$dockerFile); - postReturn(['display'=>displaySearchResults($pageNumber)]); + writeJsonFile($caPaths['dockerSearchResults'],$dockerFile); + postReturn(['display'=>displaySearchResults($pageNumber)]); } ############################################## # Gets the last update issued to a container # ############################################## function getLastUpdate($ID) { - global $caPaths; + global $caPaths; - $count = 0; - $registry_json = null; - while ( $count < 5 ) { - $templates = &$GLOBALS['templates']; - if ( $templates ) break; - sleep(1); # keep trying in case of a collision between reading and writing - $count++; - } - $index = searchArray($templates,"ID",$ID); - if ( $index === false ) - return "Unknown"; + $count = 0; + $registry_json = null; + while ( $count < 5 ) { + $templates = &$GLOBALS['templates']; + if ( $templates ) break; + sleep(1); # keep trying in case of a collision between reading and writing + $count++; + } + $index = searchArray($templates,"ID",$ID); + if ( $index === false ) + return "Unknown"; - $app = $templates[$index]; - if ( $app['PluginURL'] || $app['LanguageURL'] ) - return; + $app = $templates[$index]; + if ( $app['PluginURL'] || $app['LanguageURL'] ) + return; - if ( strpos($app['Repository'],"ghcr.io") !== false || strpos($app['Repository'],"cr.hotio.dev") !== false || strpos($app['Repository'],"lscr.io") !== false) { // try dockerhub for info on ghcr stuff - $info = pathinfo($app['Repository']); - $regs = basename($info['dirname'])."/".$info['filename']; - } else { - $regs = $app['Repository']; - } - $reg = explode(":",$regs); - if ( ($reg[1] ?? "latest") !== "latest" ) - return tr("Unknown"); + if ( strpos($app['Repository'],"ghcr.io") !== false || strpos($app['Repository'],"cr.hotio.dev") !== false || strpos($app['Repository'],"lscr.io") !== false) { // try dockerhub for info on ghcr stuff + $info = pathinfo($app['Repository']); + $regs = basename($info['dirname'])."/".$info['filename']; + } else { + $regs = $app['Repository']; + } + $reg = explode(":",$regs); + if ( ($reg[1] ?? "latest") !== "latest" ) + return tr("Unknown"); - if ( !strpos($reg[0],"/") ) - $reg[0] = "library/{$reg[0]}"; + if ( !strpos($reg[0],"/") ) + $reg[0] = "library/{$reg[0]}"; - $count = 0; - $registry = false; - while ( ! $registry && $count < 5 ) { - $registry = download_url("https://registry.hub.docker.com/v2/repositories/{$reg[0]}"); - if ( ! $registry ) { - $count++; - sleep(1); - continue; - } - $registry_json = json_decode($registry,true); - if ( ! $registry_json['last_updated'] ) - return; + $count = 0; + $registry = false; + while ( ! $registry && $count < 5 ) { + $registry = download_url("https://registry.hub.docker.com/v2/repositories/{$reg[0]}"); + if ( ! $registry ) { + $count++; + sleep(1); + continue; + } + $registry_json = json_decode($registry,true); + if ( ! $registry_json['last_updated'] ) + return; - } - $registry_json['last_updated'] = $registry_json['last_updated'] ?? false; - $lastUpdated = $registry_json['last_updated'] ? tr(date("M j, Y",strtotime($registry_json['last_updated'])),0) : "Unknown"; + } + $registry_json['last_updated'] = $registry_json['last_updated'] ?? false; + $lastUpdated = $registry_json['last_updated'] ? tr(date("M j, Y",strtotime($registry_json['last_updated'])),0) : "Unknown"; - return $lastUpdated; + return $lastUpdated; } ###################################### # Changes the max per page displayed # ###################################### function changeMaxPerPage() { - global $caPaths, $caSettings; + global $caPaths, $caSettings; - $max = getPost("max",24); - if ($caSettings['maxPerPage'] == $max) - postReturn(["status"=>"same"]); - else { - $caSettings['maxPerPage'] = $max; - write_ini_file($caPaths['pluginSettings'],$caSettings); - postReturn(["status"=>"updated"]); - } + $max = getPost("max",24); + if ($caSettings['maxPerPage'] == $max) + postReturn(["status"=>"same"]); + else { + $caSettings['maxPerPage'] = $max; + write_ini_file($caPaths['pluginSettings'],$caSettings); + postReturn(["status"=>"updated"]); + } } ################################################################ # Enables if necessary the action centre # # Basically a duplicate of action centre code in previous apps # ################################################################ function enableActionCentre() { - global $caPaths, $caSettings, $DockerClient; + global $caPaths, $caSettings, $DockerClient; # wait til check for updates is finished - for ( $i=0;$i<100;$i++ ) { - if ( is_file($caPaths['updateRunning']) && file_exists("/proc/".@file_get_contents($caPaths['updateRunning'])) ) { - debug("Action Centre sleeping -> update running"); - sleep(5); - clearstatcache(); - } - else break; - } - if ( $i >= 100 ) { - debug("Something went wrong. EnableActionCentre ran longer than 500 seconds"); - postReturn(['status'=>"noaction"]); - return; - } + for ( $i=0;$i<100;$i++ ) { + if ( is_file($caPaths['updateRunning']) && file_exists("/proc/".@file_get_contents($caPaths['updateRunning'])) ) { + debug("Action Centre sleeping -> update running"); + sleep(5); + clearstatcache(); + } + else break; + } + if ( $i >= 100 ) { + debug("Something went wrong. EnableActionCentre ran longer than 500 seconds"); + postReturn(['status'=>"noaction"]); + return; + } # wait til templates are downloaded - for ( $i=0;$i<100;$i++ ) { - if ( ! is_file($caPaths['haveTemplates']) ) { - debug("Action Centre sleeping - no templates yet"); - sleep(5); - } else { - debug("action centre: have templates"); - break; - } - } - if ( $i >= 100 ) { - debug("Something went wrong. EnableActionCentre ran longer than 500 seconds"); - postReturn(['status'=>"noaction"]); - return; - } - $file = readJsonFile($caPaths['community-templates-info']); - $extraBlacklist = readJsonFile($caPaths['extraBlacklist']); - $extraDeprecated = readJsonFile($caPaths['extraDeprecated']); + for ( $i=0;$i<100;$i++ ) { + if ( ! is_file($caPaths['haveTemplates']) ) { + debug("Action Centre sleeping - no templates yet"); + sleep(5); + } else { + debug("action centre: have templates"); + break; + } + } + if ( $i >= 100 ) { + debug("Something went wrong. EnableActionCentre ran longer than 500 seconds"); + postReturn(['status'=>"noaction"]); + return; + } + $file = readJsonFile($caPaths['community-templates-info']); + $extraBlacklist = readJsonFile($caPaths['extraBlacklist']); + $extraDeprecated = readJsonFile($caPaths['extraDeprecated']); - if ( is_file("/var/run/dockerd.pid") && is_dir("/proc/".@file_get_contents("/var/run/dockerd.pid")) ) { - $dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']); - } else { - $dockerUpdateStatus = []; - } + if ( is_file("/var/run/dockerd.pid") && is_dir("/proc/".@file_get_contents("/var/run/dockerd.pid")) ) { + $dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']); + } else { + $dockerUpdateStatus = []; + } - $info = getAllInfo(); + $info = getAllInfo(); # $info contains all installed containers # now correlate that to a template; # this section handles containers that have not been renamed from the appfeed - if ( $caSettings['dockerRunning'] ) { - $all_files = glob("{$caPaths['dockerManTemplates']}/*.xml"); - $all_files = $all_files ?: []; - foreach ($all_files as $xmlfile) { - $o = readXmlFile($xmlfile); + if ( $caSettings['dockerRunning'] ) { + $all_files = glob("{$caPaths['dockerManTemplates']}/*.xml"); + $all_files = $all_files ?: []; + foreach ($all_files as $xmlfile) { + $o = readXmlFile($xmlfile); - $runningflag = false; - foreach ($info as $installedDocker) { - $installedImage = str_replace("library/","",$installedDocker['Image']); - $installedName = $installedDocker['Name']; - if ( $installedName == $o['Name'] ) { - if ( startsWith($installedImage, $o['Repository']) ) { - $runningflag = true; - $searchResult = searchArray($file,'Repository',$o['Repository']); - if ( $searchResult === false) { - $searchResult = searchArray($file,'Repository',explode(":",$o['Repository'])[0]); - } - if ( $searchResult === false ) { - $runningFlag = true; - if ( $extraBlacklist[$o['Repository']] ?? false ) { - $o['Blacklist'] = true; - } - if ( $extraDeprecated[$o['Repository']] ?? false ) { - $o['Deprecated'] = true; - } - } - break; - } - } - } - if ( $runningflag ) { - $tmpRepo = strpos($o['Repository'],":") ? $o['Repository'] : $o['Repository'].":latest"; - $tmpRepo = strpos($tmpRepo,"/") ? $tmpRepo : "library/$tmpRepo"; - if ( $tmpRepo ) { - if ( isset($dockerUpdateStatus[$tmpRepo]['status']) && $dockerUpdateStatus[$tmpRepo]['status'] == "false" ) - $o['actionCentre'] = true; - } - if ( ! $o['Blacklist'] && ! $o['Deprecated'] ) { - if ( isset($extraBlacklist[$o['Repository']]) ) { - $o['Blacklist'] = true; - } - if ( isset($extraDeprecated[$o['Repository']]) ) { - $o['Deprecated'] = true; - } - } + $runningflag = false; + foreach ($info as $installedDocker) { + $installedImage = str_replace("library/","",$installedDocker['Image']); + $installedName = $installedDocker['Name']; + if ( $installedName == $o['Name'] ) { + if ( startsWith($installedImage, $o['Repository']) ) { + $runningflag = true; + $searchResult = searchArray($file,'Repository',$o['Repository']); + if ( $searchResult === false) { + $searchResult = searchArray($file,'Repository',explode(":",$o['Repository'])[0]); + } + if ( $searchResult === false ) { + $runningFlag = true; + if ( $extraBlacklist[$o['Repository']] ?? false ) { + $o['Blacklist'] = true; + } + if ( $extraDeprecated[$o['Repository']] ?? false ) { + $o['Deprecated'] = true; + } + } + break; + } + } + } + if ( $runningflag ) { + $tmpRepo = strpos($o['Repository'],":") ? $o['Repository'] : $o['Repository'].":latest"; + $tmpRepo = strpos($tmpRepo,"/") ? $tmpRepo : "library/$tmpRepo"; + if ( $tmpRepo ) { + if ( isset($dockerUpdateStatus[$tmpRepo]['status']) && $dockerUpdateStatus[$tmpRepo]['status'] == "false" ) + $o['actionCentre'] = true; + } + if ( ! $o['Blacklist'] && ! $o['Deprecated'] ) { + if ( isset($extraBlacklist[$o['Repository']]) ) { + $o['Blacklist'] = true; + } + if ( isset($extraDeprecated[$o['Repository']]) ) { + $o['Deprecated'] = true; + } + } - if ( !$o['Blacklist'] && !$o['Deprecated'] && !$o['actionCentre'] ) - continue; + if ( !$o['Blacklist'] && !$o['Deprecated'] && !$o['actionCentre'] ) + continue; - $displayed[] = $o; - break; - } - } - } + $displayed[] = $o; + break; + } + } + } # Now work on plugins - foreach ($file as $template) { - if ( ! $template['Plugin'] ) continue; + foreach ($file as $template) { + if ( ! $template['Plugin'] ) continue; - if ( $template['Name'] == "Community Applications" ) - continue; + if ( $template['Name'] == "Community Applications" ) + continue; - $filename = pathinfo($template['Repository'],PATHINFO_BASENAME); + $filename = pathinfo($template['Repository'],PATHINFO_BASENAME); - if ( checkInstalledPlugin($template) ) { - $template['InstallPath'] = "/var/log/plugins/$filename"; - $template['Uninstall'] = true; - if ( plugin("pluginURL","/var/log/plugins/$filename") !== $template['PluginURL'] ) - continue; + if ( checkInstalledPlugin($template) ) { + $template['InstallPath'] = "/var/log/plugins/$filename"; + $template['Uninstall'] = true; + if ( plugin("pluginURL","/var/log/plugins/$filename") !== $template['PluginURL'] ) + continue; - $installedVersion = plugin("version","/var/log/plugins/$filename"); - if ( ( strcmp($installedVersion,$template['pluginVersion']) < 0 || $template['UpdateAvailable']) ) { - $template['actionCentre'] = true; - } - if ( ! $template['actionCentre'] && is_file("/tmp/plugins/$filename") ) { - if ( strcmp($installedVersion,plugin("version","/tmp/plugins/$filename")) < 0 ) - $template['actionCentre'] = true; - } + $installedVersion = plugin("version","/var/log/plugins/$filename"); + if ( ( strcmp($installedVersion,$template['pluginVersion']) < 0 || $template['UpdateAvailable']) ) { + $template['actionCentre'] = true; + } + if ( ! $template['actionCentre'] && is_file("/tmp/plugins/$filename") ) { + if ( strcmp($installedVersion,plugin("version","/tmp/plugins/$filename")) < 0 ) + $template['actionCentre'] = true; + } - if ( !$template['Blacklist'] && !$template['Deprecated'] && $template['Compatible'] && !$template['actionCentre'] ) - continue; - $displayed[] = $template; - break; - } - } - $installedLanguages = array_diff(scandir($caPaths['languageInstalled']),[".","..","en_US"]); - foreach ($installedLanguages as $language) { - $index = searchArray($file,"LanguagePack",$language); - if ( $index !== false ) { - $tmpL = $file[$index]; - $tmpL['Uninstall'] = true; + if ( !$template['Blacklist'] && !$template['Deprecated'] && $template['Compatible'] && !$template['actionCentre'] ) + continue; + $displayed[] = $template; + break; + } + } + $installedLanguages = array_diff(scandir($caPaths['languageInstalled']),[".","..","en_US"]); + foreach ($installedLanguages as $language) { + $index = searchArray($file,"LanguagePack",$language); + if ( $index !== false ) { + $tmpL = $file[$index]; + $tmpL['Uninstall'] = true; - if ( !languageCheck($tmpL) ) - continue; + if ( !languageCheck($tmpL) ) + continue; - $displayed[] = $tmpL; - break; - } - } - if ( isset($displayed) ) { - debug("action center enabled"); - postReturn(['status'=>"action"]); - } else { - debug("action centre disabled"); - postReturn(['status'=>"noaction"]); - } + $displayed[] = $tmpL; + break; + } + } + if ( isset($displayed) ) { + debug("action center enabled"); + postReturn(['status'=>"action"]); + } else { + debug("action centre disabled"); + postReturn(['status'=>"noaction"]); + } } ################################################### # Checks the requirements being met on an upgrade # ################################################### function checkRequirements() { - $requiresFile = getPost("requires",""); - if (! $requiresFile || ($requiresFile && is_file($requiresFile) ) ) { - postReturn(['met'=>true]); - } else { - postReturn(['met'=>""]); - } + $requiresFile = getPost("requires",""); + if (! $requiresFile || ($requiresFile && is_file($requiresFile) ) ) { + postReturn(['met'=>true]); + } else { + postReturn(['met'=>""]); + } } ######################################################## # Saves the list of plugins which are pending installs # ######################################################## function saveMultiPluginPending() { - global $caPaths; + global $caPaths; - $plugin = getPost("plugin",""); - $plugins = array_filter(explode("*",$plugin)); - if ( count($plugins) > 1 ) { - exec("mkdir -p {$caPaths['pluginPending']}"); - foreach ($plugins as $plg) { - if (! $plg ) continue; - $pluginName = basename($plg); - touch($caPaths['pluginPending'].$pluginName); - } - } - postReturn(['status'=>'ok']); + $plugin = getPost("plugin",""); + $plugins = array_filter(explode("*",$plugin)); + if ( count($plugins) > 1 ) { + exec("mkdir -p {$caPaths['pluginPending']}"); + foreach ($plugins as $plg) { + if (! $plg ) continue; + $pluginName = basename($plg); + touch($caPaths['pluginPending'].$pluginName); + } + } + postReturn(['status'=>'ok']); } ############################################## # Downloads the stats file in the background # ############################################## function downloadStatistics() { - global $caPaths; + global $caPaths; - if ( ! is_file($caPaths['statistics']) ) - download_json($caPaths['statisticsURL'],$caPaths['statistics']); + if ( ! is_file($caPaths['statistics']) ) + download_json($caPaths['statisticsURL'],$caPaths['statistics']); } ########################################################################### # Checks to see if a plugin installation or update is already in progress # ########################################################################### function checkPluginInProgress() { - global $caPaths; + global $caPaths; - $pluginsPending = glob("{$caPaths['pluginPending']}/*"); + $pluginsPending = glob("{$caPaths['pluginPending']}/*"); - postReturn(['inProgress'=>empty($pluginsPending)? "" : "true"]); + postReturn(['inProgress'=>empty($pluginsPending)? "" : "true"]); } @@ -2549,9 +2549,9 @@ function checkPluginInProgress() { # Logs Javascript errors being caught # ####################################### function javascriptError() { - return; - global $caPaths, $caSettings; + return; + global $caPaths, $caSettings; - debug("******* ERROR **********\n".print_r($_POST,true)); + debug("******* ERROR **********\n".print_r($_POST,true)); } ?> \ No newline at end of file diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/include/helpers.php b/source/community.applications/usr/local/emhttp/plugins/community.applications/include/helpers.php index 686f57a8..645e8be1 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/include/helpers.php +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/include/helpers.php @@ -10,191 +10,191 @@ # Convert Array("one","two","three") to be Array("one"=>$defaultFlag, "two"=>$defaultFlag, "three"=>$defaultFlag # ################################################################################################################## function arrayEntriesToObject($sourceArray,$defaultFlag=true) { - return is_array($sourceArray) ? array_fill_keys($sourceArray,$defaultFlag) : []; + return is_array($sourceArray) ? array_fill_keys($sourceArray,$defaultFlag) : []; } ########################################################################### # Helper function to determine if a plugin has an update available or not # ########################################################################### function checkPluginUpdate($filename) { - global $caSettings; + global $caSettings; - $filename = basename($filename); - if ( ! is_file("/var/log/plugins/$filename") ) return false; - $upgradeVersion = (is_file("/tmp/plugins/$filename")) ? plugin("version","/tmp/plugins/$filename") : "0"; - $installedVersion = $upgradeVersion ? plugin("version","/var/log/plugins/$filename") : 0; + $filename = basename($filename); + if ( ! is_file("/var/log/plugins/$filename") ) return false; + $upgradeVersion = (is_file("/tmp/plugins/$filename")) ? plugin("version","/tmp/plugins/$filename") : "0"; + $installedVersion = $upgradeVersion ? plugin("version","/var/log/plugins/$filename") : 0; - if ( $installedVersion < $upgradeVersion ) { - $unRaid = plugin("unRAID","/tmp/plugins/$filename"); - return ( $unRaid === false || version_compare($caSettings['unRaidVersion'],$unRaid,">=") ) ? true : false; - } - return false; + if ( $installedVersion < $upgradeVersion ) { + $unRaid = plugin("unRAID","/tmp/plugins/$filename"); + return ( $unRaid === false || version_compare($caSettings['unRaidVersion'],$unRaid,">=") ) ? true : false; + } + return false; } ################################################################################### # returns a random file name (/tmp/community.applications/tempFiles/34234234.tmp) # ################################################################################### function randomFile() { - global $caPaths; + global $caPaths; - return tempnam($caPaths['tempFiles'],"CA-Temp-"); + return tempnam($caPaths['tempFiles'],"CA-Temp-"); } ################################################################## # 7 Functions to avoid typing the same lines over and over again # ################################################################## function readJsonFile($filename) { - global $caSettings, $caPaths; + global $caSettings, $caPaths; - debug("CA Read JSON file $filename"); + debug("CA Read JSON file $filename"); - $json = json_decode(@file_get_contents($filename),true); - if ( $json === false ) { - if ( ! is_file($filename) ) - debug("$filename not found"); + $json = json_decode(@file_get_contents($filename),true); + if ( $json === false ) { + if ( ! is_file($filename) ) + debug("$filename not found"); - debug("JSON Read Error ($filename)"); - } - debug("Memory Usage:".round(memory_get_usage()/1048576,2)." MB"); - return is_array($json) ? $json : array(); + debug("JSON Read Error ($filename)"); + } + debug("Memory Usage:".round(memory_get_usage()/1048576,2)." MB"); + return is_array($json) ? $json : array(); } function writeJsonFile($filename,$jsonArray) { - global $caSettings, $caPaths; + global $caSettings, $caPaths; - debug("Write JSON File $filename"); - $jsonFlags = $caSettings['dev'] == "yes" ? JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT : JSON_UNESCAPED_SLASHES; - $result = ca_file_put_contents($filename,json_encode($jsonArray, $jsonFlags)); - debug("Memory Usage:".round(memory_get_usage()/1048576,2)." MB"); + debug("Write JSON File $filename"); + $jsonFlags = $caSettings['dev'] == "yes" ? JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT : JSON_UNESCAPED_SLASHES; + $result = ca_file_put_contents($filename,json_encode($jsonArray, $jsonFlags)); + debug("Memory Usage:".round(memory_get_usage()/1048576,2)." MB"); } function ca_file_put_contents($filename,$data,$flags=0) { - $result = @file_put_contents($filename,$data,$flags); + $result = @file_put_contents($filename,$data,$flags); - if ( $result === false ) { - debug("Failed to write to $filename"); - $GLOBALS['script'] = "alert('Failed to write to ".htmlentities($filename,ENT_QUOTES)."');"; - } - return $result; + if ( $result === false ) { + debug("Failed to write to $filename"); + $GLOBALS['script'] = "alert('Failed to write to ".htmlentities($filename,ENT_QUOTES)."');"; + } + return $result; } function download_url($url, $path = "", $bg = false, $timeout = 45) { - global $caSettings, $caPaths; + global $caSettings, $caPaths; - debug("DOWNLOAD starting $url\n"); - $startTime = time(); + debug("DOWNLOAD starting $url\n"); + $startTime = time(); - $ch = curl_init(); - curl_setopt($ch,CURLOPT_URL,$url); - curl_setopt($ch,CURLOPT_FRESH_CONNECT,true); - curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); - curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout); - curl_setopt($ch,CURLOPT_TIMEOUT,$timeout); - curl_setopt($ch,CURLOPT_ENCODING,""); - curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); - curl_setopt($ch,CURLOPT_FOLLOWLOCATION, true); - curl_setopt($ch,CURLOPT_FAILONERROR,true); + $ch = curl_init(); + curl_setopt($ch,CURLOPT_URL,$url); + curl_setopt($ch,CURLOPT_FRESH_CONNECT,true); + curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); + curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout); + curl_setopt($ch,CURLOPT_TIMEOUT,$timeout); + curl_setopt($ch,CURLOPT_ENCODING,""); + curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); + curl_setopt($ch,CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch,CURLOPT_FAILONERROR,true); - if ( is_file("/boot/config/plugins/community.applications/proxy.cfg") ) { - $proxyCFG = parse_ini_file("/boot/config/plugins/community.applications/proxy.cfg"); - curl_setopt($ch, CURLOPT_PROXYPORT,intval($proxyCFG['port'])); - curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL,intval($proxyCFG['tunnel'])); - curl_setopt($ch, CURLOPT_PROXY,$proxyCFG['proxy']); - } - $out = curl_exec($ch); - curl_close($ch); - if ( $path ) - ca_file_put_contents($path,$out); + if ( is_file("/boot/config/plugins/community.applications/proxy.cfg") ) { + $proxyCFG = parse_ini_file("/boot/config/plugins/community.applications/proxy.cfg"); + curl_setopt($ch, CURLOPT_PROXYPORT,intval($proxyCFG['port'])); + curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL,intval($proxyCFG['tunnel'])); + curl_setopt($ch, CURLOPT_PROXY,$proxyCFG['proxy']); + } + $out = curl_exec($ch); + curl_close($ch); + if ( $path ) + ca_file_put_contents($path,$out); - $totalTime = time() - $startTime; - debug("DOWNLOAD $url Time: $totalTime RESULT:\n".var_dump_ret($out)); - return $out ?: false; + $totalTime = time() - $startTime; + debug("DOWNLOAD $url Time: $totalTime RESULT:\n".var_dump_ret($out)); + return $out ?: false; } function download_json($url,$path="",$bg=false,$timeout=45) { - return json_decode(download_url($url,$path,$bg,$timeout),true); + return json_decode(download_url($url,$path,$bg,$timeout),true); } function getPost($setting,$default) { - return isset($_POST[$setting]) ? urldecode(($_POST[$setting])) : $default; + return isset($_POST[$setting]) ? urldecode(($_POST[$setting])) : $default; } function getPostArray($setting) { - return $_POST[$setting]; + return $_POST[$setting]; } function var_dump_ret($mixed = null) { - ob_start(); - var_dump($mixed); - $content = ob_get_contents(); - ob_end_clean(); - return $content; + ob_start(); + var_dump($mixed); + $content = ob_get_contents(); + ob_end_clean(); + return $content; } ############################################## # Determine if $haystack begins with $needle # ############################################## function startsWith($haystack, $needle) { - if ( !is_string($haystack) || ! is_string($needle) ) return false; - return $needle === "" || strripos($haystack, $needle, -strlen($haystack)) !== FALSE; + if ( !is_string($haystack) || ! is_string($needle) ) return false; + return $needle === "" || strripos($haystack, $needle, -strlen($haystack)) !== FALSE; } ############################################# # Determine if $string ends with $endstring # ############################################# function endsWith($string, $endString) { - $len = strlen($endString); - if ($len == 0) { - return true; - } - return (substr($string, -$len) === $endString); + $len = strlen($endString); + if ($len == 0) { + return true; + } + return (substr($string, -$len) === $endString); } ########################################### # Replace the first occurance in a string # ########################################### function first_str_replace($haystack, $needle, $replace) { - $pos = strpos($haystack, $needle); - return ($pos !== false) ? substr_replace($haystack, $replace, $pos, strlen($needle)) : $haystack; + $pos = strpos($haystack, $needle); + return ($pos !== false) ? substr_replace($haystack, $replace, $pos, strlen($needle)) : $haystack; } ########################################## # Replace the last occurance in a string # ########################################## function last_str_replace($haystack, $needle, $replace) { - $pos = strrpos($haystack, $needle); - return ($pos !== false) ? substr_replace($haystack, $replace, $pos, strlen($needle)) : $haystack; + $pos = strrpos($haystack, $needle); + return ($pos !== false) ? substr_replace($haystack, $replace, $pos, strlen($needle)) : $haystack; } ####################### # Custom sort routine # ####################### function mySort($a, $b) { - global $sortOrder; + global $sortOrder; - if ( $sortOrder['sortBy'] == "Name" ) - $sortOrder['sortBy'] = "SortName"; - if ( $sortOrder['sortBy'] != "downloads" && $sortOrder['sortBy'] != "trendDelta") { - $c = strtolower($a[$sortOrder['sortBy']] ?? ""); - $d = strtolower($b[$sortOrder['sortBy']] ?? ""); - } else { - $c = $a[$sortOrder['sortBy']]; - $d = $b[$sortOrder['sortBy']]; - } + if ( $sortOrder['sortBy'] == "Name" ) + $sortOrder['sortBy'] = "SortName"; + if ( $sortOrder['sortBy'] != "downloads" && $sortOrder['sortBy'] != "trendDelta") { + $c = strtolower($a[$sortOrder['sortBy']] ?? ""); + $d = strtolower($b[$sortOrder['sortBy']] ?? ""); + } else { + $c = $a[$sortOrder['sortBy']]; + $d = $b[$sortOrder['sortBy']]; + } - $return1 = ($sortOrder['sortDir'] == "Down") ? -1 : 1; - $return2 = ($sortOrder['sortDir'] == "Down") ? 1 : -1; + $return1 = ($sortOrder['sortDir'] == "Down") ? -1 : 1; + $return2 = ($sortOrder['sortDir'] == "Down") ? 1 : -1; - if ( ! is_numeric($c) ) { - $c = strtolower($c ?? ""); - $d = strtolower($d ?? ""); - } - if ($c > $d) return $return1; - else if ($c < $d) return $return2; - else return 0; + if ( ! is_numeric($c) ) { + $c = strtolower($c ?? ""); + $d = strtolower($d ?? ""); + } + if ($c > $d) return $return1; + else if ($c < $d) return $return2; + else return 0; } function repositorySort($a,$b) { - global $caSettings; + global $caSettings; - if ( $a['RepoName'] == $caSettings['favourite'] ) return -1; - if ( $b['RepoName'] == $caSettings['favourite'] ) return 1; - return 0; + if ( $a['RepoName'] == $caSettings['favourite'] ) return -1; + if ( $b['RepoName'] == $caSettings['favourite'] ) return 1; + return 0; } function favouriteSort($a,$b) { - global $caSettings; + global $caSettings; - if ( $a['Repo'] == $caSettings['favourite'] ) return -1; - if ( $b['Repo'] == $caSettings['favourite'] ) return 1; - return 0; + if ( $a['Repo'] == $caSettings['favourite'] ) return -1; + if ( $b['Repo'] == $caSettings['favourite'] ) return 1; + return 0; } ############################################### # Search array for a particular key and value # @@ -202,169 +202,169 @@ function favouriteSort($a,$b) { # return value === false if not found # ############################################### function searchArray($array,$key,$value,$startingIndex=0) { - $result = false; - if (is_array($array) && count($array) ) { - for ($i = $startingIndex; $i <= max(array_keys($array)); $i++) { - if ( $array[$i][$key] == $value ) { - $result = $i; - break; - } - } - } - return $result; + $result = false; + if (is_array($array) && count($array) ) { + for ($i = $startingIndex; $i <= max(array_keys($array)); $i++) { + if ( $array[$i][$key] == $value ) { + $result = $i; + break; + } + } + } + return $result; } ######################################################## # Fix common problems (maintainer errors) in templates # ######################################################## function fixTemplates($template) { - global $statistics, $caSettings; + global $statistics, $caSettings; - if ( ! $template['MinVer'] ) $template['MinVer'] = $template['Plugin'] ? "6.1" : "6.0"; - if ( ! $template['Date'] ) $template['Date'] = (is_numeric($template['DateInstalled'])) ? $template['DateInstalled'] : 0; - $template['Date'] = max($template['Date'],$template['FirstSeen']); - if ($template['Date'] == 1) $template['Date'] = null; - if ( ($template['Date'] == $template['FirstSeen']) && ( $template['FirstSeen'] >= 1538357652 )) {# 1538357652 is when the new appfeed first started - $template['BrandNewApp'] = true; - $template['Date'] = null; - } + if ( ! $template['MinVer'] ) $template['MinVer'] = $template['Plugin'] ? "6.1" : "6.0"; + if ( ! $template['Date'] ) $template['Date'] = (is_numeric($template['DateInstalled'])) ? $template['DateInstalled'] : 0; + $template['Date'] = max($template['Date'],$template['FirstSeen']); + if ($template['Date'] == 1) $template['Date'] = null; + if ( ($template['Date'] == $template['FirstSeen']) && ( $template['FirstSeen'] >= 1538357652 )) {# 1538357652 is when the new appfeed first started + $template['BrandNewApp'] = true; + $template['Date'] = null; + } - # fix where template author includes or entries in template (CA used booleans, but appfeed winds up saying "FALSE" which equates to be true - $template['Deprecated'] = filter_var($template['Deprecated'],FILTER_VALIDATE_BOOLEAN); - $template['Blacklist'] = filter_var($template['Blacklist'],FILTER_VALIDATE_BOOLEAN); + # fix where template author includes or entries in template (CA used booleans, but appfeed winds up saying "FALSE" which equates to be true + $template['Deprecated'] = filter_var($template['Deprecated'],FILTER_VALIDATE_BOOLEAN); + $template['Blacklist'] = filter_var($template['Blacklist'],FILTER_VALIDATE_BOOLEAN); - if ( $template['DeprecatedMaxVer'] && version_compare($caSettings['unRaidVersion'],$template['DeprecatedMaxVer'],">") ) - $template['Deprecated'] = true; + if ( $template['DeprecatedMaxVer'] && version_compare($caSettings['unRaidVersion'],$template['DeprecatedMaxVer'],">") ) + $template['Deprecated'] = true; - if ( version_compare($caSettings['unRaidVersion'],"6.10.0-beta4",">") ) { - if ( $template['Config'] ) { - if ( $template['Config']['@attributes'] ?? false ) { - if (preg_match("/^(Container Path:|Container Port:|Container Label:|Container Variable:|Container Device:)/",$template['Config']['@attributes']['Description']) ) { - $template['Config']['@attributes']['Description'] = ""; - } - } else { - if (is_array($template['Config'])) { - foreach ($template['Config'] as &$config) { - if (preg_match("/^(Container Path:|Container Port:|Container Label:|Container Variable:|Container Device:)/",$config['@attributes']['Description']??"") ) { - $config['@attributes']['Description'] = ""; - } - } - } - } - } - } - return $template; + if ( version_compare($caSettings['unRaidVersion'],"6.10.0-beta4",">") ) { + if ( $template['Config'] ) { + if ( $template['Config']['@attributes'] ?? false ) { + if (preg_match("/^(Container Path:|Container Port:|Container Label:|Container Variable:|Container Device:)/",$template['Config']['@attributes']['Description']) ) { + $template['Config']['@attributes']['Description'] = ""; + } + } else { + if (is_array($template['Config'])) { + foreach ($template['Config'] as &$config) { + if (preg_match("/^(Container Path:|Container Port:|Container Label:|Container Variable:|Container Device:)/",$config['@attributes']['Description']??"") ) { + $config['@attributes']['Description'] = ""; + } + } + } + } + } + } + return $template; } ############################################### # Function used to create XML's from appFeeds # ############################################### function makeXML($template) { - # ensure its a v2 template if the Config entries exist - if ( isset($template['Config']) && ! isset($template['@attributes']) ) - $template['@attributes'] = ["version"=>2]; + # ensure its a v2 template if the Config entries exist + if ( isset($template['Config']) && ! isset($template['@attributes']) ) + $template['@attributes'] = ["version"=>2]; - if ($template['Overview']) $template['Description'] = $template['Overview']; + if ($template['Overview']) $template['Description'] = $template['Overview']; - fixAttributes($template,"Network"); - fixAttributes($template,"Config"); + fixAttributes($template,"Network"); + fixAttributes($template,"Config"); # Sanitize the Requires entry if there is any CA links within it - if ($template['Requires'] ?? false) { - preg_match_all("/\/\/(.*?)\/m",$template['Requires'],$searchMatches); + if ($template['Requires'] ?? false) { + preg_match_all("/\/\/(.*?)\/m",$template['Requires'],$searchMatches); - if ( isset($searchMatches[1]) && count($searchMatches[1]) ) { - foreach ($searchMatches[1] as $searchResult) { - $template['Requires'] = str_replace("//$searchResult\\\\",$searchResult,$template['Requires']); - } - } - } - $Array2XML = new Array2XML(); - $xml = $Array2XML->createXML("Container",$template); - return $xml->saveXML(); + if ( isset($searchMatches[1]) && count($searchMatches[1]) ) { + foreach ($searchMatches[1] as $searchResult) { + $template['Requires'] = str_replace("//$searchResult\\\\",$searchResult,$template['Requires']); + } + } + } + $Array2XML = new Array2XML(); + $xml = $Array2XML->createXML("Container",$template); + return $xml->saveXML(); } ################################################################################# # Function to fix differing schema in the appfeed vs what Array2XML class wants # ################################################################################# function fixAttributes(&$template,$attribute) { - if ( ! isset($template[$attribute]) ) return; - if ( ! is_array($template[$attribute]) ) return; - if ( isset($template[$attribute]['@attributes']) ) { - $template[$attribute][0]['@attributes'] = $template[$attribute]['@attributes']; - if ( $template[$attribute]['value']) - $template[$attribute][0]['value'] = $template[$attribute]['value']; + if ( ! isset($template[$attribute]) ) return; + if ( ! is_array($template[$attribute]) ) return; + if ( isset($template[$attribute]['@attributes']) ) { + $template[$attribute][0]['@attributes'] = $template[$attribute]['@attributes']; + if ( $template[$attribute]['value']) + $template[$attribute][0]['value'] = $template[$attribute]['value']; - unset($template[$attribute]['@attributes']); - unset($template[$attribute]['value']); - } + unset($template[$attribute]['@attributes']); + unset($template[$attribute]['value']); + } - if ( $template[$attribute] ) { - foreach ($template[$attribute] as $tempArray) - $tempArray2[] = isset($tempArray['value']) ? ['@attributes'=>$tempArray['@attributes'],'@value'=>$tempArray['value']] : ['@attributes'=>$tempArray['@attributes']]; - $template[$attribute] = $tempArray2; - } + if ( $template[$attribute] ) { + foreach ($template[$attribute] as $tempArray) + $tempArray2[] = isset($tempArray['value']) ? ['@attributes'=>$tempArray['@attributes'],'@value'=>$tempArray['value']] : ['@attributes'=>$tempArray['@attributes']]; + $template[$attribute] = $tempArray2; + } } ################################################################# # checks the Min/Max version of an app against unRaid's version # # Returns: TRUE if it's valid to run, FALSE if not # ################################################################# function versionCheck($template) { - global $caSettings; + global $caSettings; - if ( $template['IncompatibleVersion'] ) { - if ( ! is_array($template['IncompatibleVersion']) ) { - $incompatible[] = $template['IncompatibleVersion']; - } else { - $incompatible = $template['IncompatibleVersion']; - } - foreach ($incompatible as $ver) { - if ( $ver == $template['pluginVersion'] ) return false; - } - } + if ( $template['IncompatibleVersion'] ) { + if ( ! is_array($template['IncompatibleVersion']) ) { + $incompatible[] = $template['IncompatibleVersion']; + } else { + $incompatible = $template['IncompatibleVersion']; + } + foreach ($incompatible as $ver) { + if ( $ver == $template['pluginVersion'] ) return false; + } + } - if ( $template['MinVer'] && ( version_compare($template['MinVer'],$caSettings['unRaidVersion']) > 0 ) ) return false; - if ( $template['MaxVer'] && ( version_compare($template['MaxVer'],$caSettings['unRaidVersion']) < 0 ) ) return false; - return true; + if ( $template['MinVer'] && ( version_compare($template['MinVer'],$caSettings['unRaidVersion']) > 0 ) ) return false; + if ( $template['MaxVer'] && ( version_compare($template['MaxVer'],$caSettings['unRaidVersion']) < 0 ) ) return false; + return true; } ############################################### # Function to read a template XML to an array # ############################################### function readXmlFile($xmlfile,$generic=false,$stats=true) { - global $statistics; + global $statistics; - if ( ! $xmlfile || ! is_file($xmlfile) ) return false; - $xml = file_get_contents($xmlfile); - $o = TypeConverter::xmlToArray($xml,TypeConverter::XML_GROUP); - $o = addMissingVars($o); - if ( ! $o ) return false; - if ( $generic ) return $o; + if ( ! $xmlfile || ! is_file($xmlfile) ) return false; + $xml = file_get_contents($xmlfile); + $o = TypeConverter::xmlToArray($xml,TypeConverter::XML_GROUP); + $o = addMissingVars($o); + if ( ! $o ) return false; + if ( $generic ) return $o; - # Fix some errors in templates prior to continuing + # Fix some errors in templates prior to continuing - $o['Path'] = $xmlfile; - $o['Author'] = getAuthor($o); - $o['DockerHubName'] = strtolower($o['Name']); - $o['Base'] = $o['BaseImage'] ?? ""; - $o['SortAuthor'] = $o['Author']; - $o['SortName'] = $o['Name']; - $o['Forum'] = $Repo['forum'] ?? ""; + $o['Path'] = $xmlfile; + $o['Author'] = getAuthor($o); + $o['DockerHubName'] = strtolower($o['Name']); + $o['Base'] = $o['BaseImage'] ?? ""; + $o['SortAuthor'] = $o['Author']; + $o['SortName'] = $o['Name']; + $o['Forum'] = $Repo['forum'] ?? ""; # configure the config attributes to same format as appfeed # handle the case where there is only a single entry - if ( isset($o['Config']['@attributes']) ) - $o['Config'] = ['@attributes'=>$o['Config']['@attributes'],'value'=>$o['Config']['value']]; + if ( isset($o['Config']['@attributes']) ) + $o['Config'] = ['@attributes'=>$o['Config']['@attributes'],'value'=>$o['Config']['value']]; - if ( $stats) { - $statistics['plugin'] = $statistics['plugin'] ?? 0; - $statistics['docker'] = $statistics['docker'] ?? 0; - if ( $o['Plugin'] ) { - $o['Author'] = $o['PluginAuthor']; - $o['Repository'] = $o['PluginURL']; - $o['SortAuthor'] = $o['Author']; - $o['SortName'] = $o['Name']; - $statistics['plugin']++; - } else - $statistics['docker']++; - } - return $o; + if ( $stats) { + $statistics['plugin'] = $statistics['plugin'] ?? 0; + $statistics['docker'] = $statistics['docker'] ?? 0; + if ( $o['Plugin'] ) { + $o['Author'] = $o['PluginAuthor']; + $o['Repository'] = $o['PluginURL']; + $o['SortAuthor'] = $o['Author']; + $o['SortName'] = $o['Name']; + $statistics['plugin']++; + } else + $statistics['docker']++; + } + return $o; } ################################################################### # Function To Merge Moderation into templates array # @@ -372,493 +372,493 @@ function readXmlFile($xmlfile,$generic=false,$stats=true) { # If appfeed is updated, this is done when creating the templates # ################################################################### function moderateTemplates() { - global $caPaths,$caSettings; + global $caPaths,$caSettings; // $templates = readJsonFile($caPaths['community-templates-info']); - $templates = &$GLOBALS['templates']; + $templates = &$GLOBALS['templates']; - if ( ! $templates ) return; - foreach ($templates as $template) { - $template['Compatible'] = versionCheck($template); - if ( $template['MaxVer'] && version_compare($template['MaxVer'],$caSettings['unRaidVersion']) < 0 ) - $template['Featured'] = false; - if ( $template['CAMinVer'] ?? false ) { - $template['UninstallOnly'] = version_compare($template['CAMinVer'],$caSettings['unRaidVersion'],">="); - } + if ( ! $templates ) return; + foreach ($templates as $template) { + $template['Compatible'] = versionCheck($template); + if ( $template['MaxVer'] && version_compare($template['MaxVer'],$caSettings['unRaidVersion']) < 0 ) + $template['Featured'] = false; + if ( $template['CAMinVer'] ?? false ) { + $template['UninstallOnly'] = version_compare($template['CAMinVer'],$caSettings['unRaidVersion'],">="); + } - if ( $template["DeprecatedMaxVer"] && version_compare($caSettings['unRaidVersion'],$template["DeprecatedMaxVer"],">") ) - $template['Deprecated'] = true; + if ( $template["DeprecatedMaxVer"] && version_compare($caSettings['unRaidVersion'],$template["DeprecatedMaxVer"],">") ) + $template['Deprecated'] = true; - $template['ModeratorComment'] = $template['CaComment'] ?: $template['ModeratorComment']; - $o[] = $template; - } - writeJsonFile($caPaths['community-templates-info'],$o); - $GLOBALS['templates'] = $o; - pluginDupe(); + $template['ModeratorComment'] = $template['CaComment'] ?: $template['ModeratorComment']; + $o[] = $template; + } + writeJsonFile($caPaths['community-templates-info'],$o); + $GLOBALS['templates'] = $o; + pluginDupe(); } ####################################################### # Function to check for a valid URL # ####################################################### function validURL($URL) { - return filter_var($URL, FILTER_VALIDATE_URL); + return filter_var($URL, FILTER_VALIDATE_URL); } ####################################################### # Function used to determine if a search term matches # ####################################################### function filterMatch($filter,$searchArray,$exact=true) { - $filterwords = explode(" ",$filter); - $foundword = null; - foreach ( $filterwords as $testfilter) { - if ( ! trim($testfilter) ) continue; - foreach ($searchArray as $search) { - if ( ! $search ) continue; - if ( stripos($search,$testfilter) !== false ) { - $foundword++; - break; - } - } - } - return $exact ? ($foundword == count($filterwords)) : ($foundword > 0); + $filterwords = explode(" ",$filter); + $foundword = null; + foreach ( $filterwords as $testfilter) { + if ( ! trim($testfilter) ) continue; + foreach ($searchArray as $search) { + if ( ! $search ) continue; + if ( stripos($search,$testfilter) !== false ) { + $foundword++; + break; + } + } + } + return $exact ? ($foundword == count($filterwords)) : ($foundword > 0); } ########################################################## # Used to figure out which plugins have duplicated names # ########################################################## function pluginDupe() { - global $caPaths; + global $caPaths; - $pluginList = []; - $dupeList = []; - foreach ($GLOBALS['templates'] as $template) { - if ( $template['Plugin'] ) { - if ( ! isset($pluginList[basename($template['Repository'])]) ) - $pluginList[basename($template['Repository'])] = 0; - $pluginList[basename($template['Repository'])]++; - } - } - foreach (array_keys($pluginList) as $plugin) { - if ( $pluginList[$plugin] > 1 ) - $dupeList[$plugin] = 1; - } - writeJsonFile($caPaths['pluginDupes'],$dupeList); + $pluginList = []; + $dupeList = []; + foreach ($GLOBALS['templates'] as $template) { + if ( $template['Plugin'] ) { + if ( ! isset($pluginList[basename($template['Repository'])]) ) + $pluginList[basename($template['Repository'])] = 0; + $pluginList[basename($template['Repository'])]++; + } + } + foreach (array_keys($pluginList) as $plugin) { + if ( $pluginList[$plugin] > 1 ) + $dupeList[$plugin] = 1; + } + writeJsonFile($caPaths['pluginDupes'],$dupeList); } ################################### # Checks if a plugin is installed # ################################### function checkInstalledPlugin($template) { - global $caPaths; + global $caPaths; - $pluginName = basename($template['PluginURL']); - if ( ! file_exists("/var/log/plugins/$pluginName") ) return false; - $dupeList = readJsonFile($caPaths['pluginDupes']); - if ( ! isset($dupeList[$pluginName]) ) return true; - return strtolower(trim(plugin("pluginURL","/var/log/plugins/$pluginName"))) == strtolower(trim($template['PluginURL'])); + $pluginName = basename($template['PluginURL']); + if ( ! file_exists("/var/log/plugins/$pluginName") ) return false; + $dupeList = readJsonFile($caPaths['pluginDupes']); + if ( ! isset($dupeList[$pluginName]) ) return true; + return strtolower(trim(plugin("pluginURL","/var/log/plugins/$pluginName"))) == strtolower(trim($template['PluginURL'])); } ########################################################### # Returns a string with only alphanumeric characters only # ########################################################### function alphaNumeric($string) { - return preg_replace("/[^a-zA-Z0-9]+/", "", $string); + return preg_replace("/[^a-zA-Z0-9]+/", "", $string); } ################################################################## # mobile browser detection from http://detectmobilebrowsers.com/ # ################################################################## function isMobile() { - global $caSettings; + global $caSettings; - $useragent=$_SERVER['HTTP_USER_AGENT']; - return (preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($useragent,0,4))); + $useragent=$_SERVER['HTTP_USER_AGENT']; + return (preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($useragent,0,4))); } ################################################ # Returns the author from the Repository entry # ################################################ function getAuthor($template) { - if ( isset($template['PluginURL']) ) return $template['PluginAuthor']; + if ( isset($template['PluginURL']) ) return $template['PluginAuthor']; - if ( isset($template['Author']) ) return strip_tags($template['Author']); - $template['Repository'] = str_replace(["lscr.io/","ghcr.io/","registry.hub.docker.com/","library/"],"",$template['Repository']); - $repoEntry = explode("/",$template['Repository']); - if (count($repoEntry) < 2) - $repoEntry[] = ""; + if ( isset($template['Author']) ) return strip_tags($template['Author']); + $template['Repository'] = str_replace(["lscr.io/","ghcr.io/","registry.hub.docker.com/","library/"],"",$template['Repository']); + $repoEntry = explode("/",$template['Repository']); + if (count($repoEntry) < 2) + $repoEntry[] = ""; - return strip_tags(explode(":",$repoEntry[count($repoEntry)-2])[0]); + return strip_tags(explode(":",$repoEntry[count($repoEntry)-2])[0]); } ############################ # Trims the category lists # ############################ function categoryList($cat,$popUp = false) { - $cat = str_replace([":,",": "," "],",",$cat); - $cat = rtrim($cat,": "); - $all_cat = explode(",",$cat); - foreach ($all_cat as $trcat) - $all_categories[] = tr($trcat); + $cat = str_replace([":,",": "," "],",",$cat); + $cat = rtrim($cat,": "); + $all_cat = explode(",",$cat); + foreach ($all_cat as $trcat) + $all_categories[] = tr($trcat); - $categoryList = $popUp ? $all_categories : array_slice($all_categories,0,2); + $categoryList = $popUp ? $all_categories : array_slice($all_categories,0,2); - if ( count($all_categories) > count($categoryList) ) { - $excess = count($all_categories) - count($categoryList); - $categoryList[] = " ".sprintf(tr("and %s more"),$excess); - } - return rtrim(implode(", ",$categoryList),", "); + if ( count($all_categories) > count($categoryList) ) { + $excess = count($all_categories) - count($categoryList); + $categoryList[] = " ".sprintf(tr("and %s more"),$excess); + } + return rtrim(implode(", ",$categoryList),", "); } ################################## # Trims the language author list # ################################## function languageAuthorList($authors) { - $allAuthors = explode(",",$authors); - if ( count($allAuthors) > 3 ) { - $newAuthors = array_slice($allAuthors,0,2); - foreach ($newAuthors as $author) { - $newAuthor .= trim($author).", "; - } - $excess = count($allAuthors) -2; - $authors = rtrim($newAuthor,", ")." ".sprintf(tr("and %s more"),$excess); - } - return $authors; + $allAuthors = explode(",",$authors); + if ( count($allAuthors) > 3 ) { + $newAuthors = array_slice($allAuthors,0,2); + foreach ($newAuthors as $author) { + $newAuthor .= trim($author).", "; + } + $excess = count($allAuthors) -2; + $authors = rtrim($newAuthor,", ")." ".sprintf(tr("and %s more"),$excess); + } + return $authors; } ##################################### # Gets a rounded off download count # ##################################### function getDownloads($downloads,$lowFlag=false) { - $downloadCount = ["10000000000","5000000000","1000000000","500000000","100000000","50000000","25000000","10000000","5000000","2500000","1000000","500000","250000","100000","50000","25000","10000","5000","1000","500","100"]; - foreach ($downloadCount as $downloadtmp) { - if ($downloads > $downloadtmp) { - return sprintf(tr("More than %s"),number_format($downloadtmp)); - } - } - return ($lowFlag) ? $downloads : ""; + $downloadCount = ["10000000000","5000000000","1000000000","500000000","100000000","50000000","25000000","10000000","5000000","2500000","1000000","500000","250000","100000","50000","25000","10000","5000","1000","500","100"]; + foreach ($downloadCount as $downloadtmp) { + if ($downloads > $downloadtmp) { + return sprintf(tr("More than %s"),number_format($downloadtmp)); + } + } + return ($lowFlag) ? $downloads : ""; } ##################### # Stops a container # ##################### function myStopContainer($id) { - global $DockerClient; + global $DockerClient; - $DockerClient->stopContainer($id); + $DockerClient->stopContainer($id); } ##################################### # Fix Descriptions on previous apps # ##################################### function fixDescription($Description) { - if ( is_string($Description) ) { - $Description = preg_replace("#\[br\s*\]#i", "{}", $Description); - $Description = preg_replace("#\[b[\\\]*\s*\]#i", "||", $Description); - $Description = preg_replace('#\[([^\]]*)\]#', '<$1>', $Description); - $Description = preg_replace("#]*>#i", '', $Description); - $Description = preg_replace("#"."{}"."#i", '
    ', $Description); - $Description = preg_replace("#"."\|\|"."#i", '', $Description); - $Description = str_replace("<","<",$Description); - $Description = str_replace(">",">",$Description); - $Description = strip_tags($Description); - $Description = trim($Description); - } - return is_string($Description) ? $Description : ""; + if ( is_string($Description) ) { + $Description = preg_replace("#\[br\s*\]#i", "{}", $Description); + $Description = preg_replace("#\[b[\\\]*\s*\]#i", "||", $Description); + $Description = preg_replace('#\[([^\]]*)\]#', '<$1>', $Description); + $Description = preg_replace("#]*>#i", '', $Description); + $Description = preg_replace("#"."{}"."#i", '
    ', $Description); + $Description = preg_replace("#"."\|\|"."#i", '', $Description); + $Description = str_replace("<","<",$Description); + $Description = str_replace(">",">",$Description); + $Description = strip_tags($Description); + $Description = trim($Description); + } + return is_string($Description) ? $Description : ""; } ############################ # displays the branch tags # ############################ function formatTags($leadTemplate,$rename="false") { - global $caPaths; + global $caPaths; - $type = $rename == "true" ? "second" : "default"; + $type = $rename == "true" ? "second" : "default"; - $file = &$GLOBALS['templates']; + $file = &$GLOBALS['templates']; - $template = $file[$leadTemplate]; - $childTemplates = $file[$leadTemplate]['BranchID']; - if ( ! is_array($childTemplates) ) - $o = tr("Something really went wrong here"); - else { - $defaultTag = $template['BranchDefault'] ? $template['BranchDefault'] : "latest"; + $template = $file[$leadTemplate]; + $childTemplates = $file[$leadTemplate]['BranchID']; + if ( ! is_array($childTemplates) ) + $o = tr("Something really went wrong here"); + else { + $defaultTag = $template['BranchDefault'] ? $template['BranchDefault'] : "latest"; - $o = ""; - $o .= ""; - foreach ($childTemplates as $child) { - $o .= ""; - } - $o .= "
          Default".tr("Install Using The Template's Default Tag")." (:$defaultTag)
          {$file[$child]['BranchName']}{$file[$child]['BranchDescription']}
    "; - } - return $o; + $o = ""; + $o .= ""; + foreach ($childTemplates as $child) { + $o .= ""; + } + $o .= "
          Default".tr("Install Using The Template's Default Tag")." (:$defaultTag)
          {$file[$child]['BranchName']}{$file[$child]['BranchDescription']}
    "; + } + return $o; } ########################### # handles the POST return # ########################### function postReturn($retArray) { - global $caSettings, $caPaths; + global $caSettings, $caPaths; - if (is_array($retArray)) { - if ( isset($GLOBALS['script']) ) - $retArray['globalScript'] = $GLOBALS['script']; + if (is_array($retArray)) { + if ( isset($GLOBALS['script']) ) + $retArray['globalScript'] = $GLOBALS['script']; - echo json_encode($retArray); - } else - echo $retArray; - flush(); - debug("POST RETURN ({$_POST['action']})\n".var_dump_ret($retArray)); - debug("POST RETURN Memory Usage:".round(memory_get_usage()/1048576,2)." MB"); + echo json_encode($retArray); + } else + echo $retArray; + flush(); + debug("POST RETURN ({$_POST['action']})\n".var_dump_ret($retArray)); + debug("POST RETURN Memory Usage:".round(memory_get_usage()/1048576,2)." MB"); } #################################### # Translation backwards compatible # #################################### if ( ! function_exists("tr") ) { - function tr($string,$options=-1) { - $translated = _($string,$options); - if ( ! trim($translated) ) - $translated = $string; + function tr($string,$options=-1) { + $translated = _($string,$options); + if ( ! trim($translated) ) + $translated = $string; - if ( startsWith($translated,""") && endsWith($translated,""") ) - $translated = first_str_replace(last_str_replace($translated,""",""),""",""); + if ( startsWith($translated,""") && endsWith($translated,""") ) + $translated = first_str_replace(last_str_replace($translated,""",""),""",""); - $translated = str_replace(['"',"'"],[""","'"],$translated); + $translated = str_replace(['"',"'"],[""","'"],$translated); - return $translated; - } + return $translated; + } } ############################# # Check for language update # ############################# function languageCheck($template) { - global $caPaths; + global $caPaths; - if ( ! $template['LanguageURL'] ) return false; + if ( ! $template['LanguageURL'] ) return false; - $countryCode = $template['LanguagePack']; - $installedLanguage = "{$caPaths['installedLanguages']}/lang-$countryCode.xml"; - $dynamixUpdate = "{$caPaths['dynamixUpdates']}/lang-$countryCode.xml"; - if ( ! is_file($installedLanguage) ) - return false; + $countryCode = $template['LanguagePack']; + $installedLanguage = "{$caPaths['installedLanguages']}/lang-$countryCode.xml"; + $dynamixUpdate = "{$caPaths['dynamixUpdates']}/lang-$countryCode.xml"; + if ( ! is_file($installedLanguage) ) + return false; - $OSupdates = readXmlFile($dynamixUpdate,true); // Because the OS might check for an update before the feed - if ( ! $OSupdates ) - $OSupdates['Version'] = "1900.01.01"; + $OSupdates = readXmlFile($dynamixUpdate,true); // Because the OS might check for an update before the feed + if ( ! $OSupdates ) + $OSupdates['Version'] = "1900.01.01"; - $xmlFile = readXmlFile($installedLanguage,true); + $xmlFile = readXmlFile($installedLanguage,true); - if ( !$xmlFile['Version'] ) return false; - return (strcmp($template['Version'],$xmlFile['Version']) > 0) || (strcmp($OSupdates['Version'],$xmlFile['Version']) > 0); + if ( !$xmlFile['Version'] ) return false; + return (strcmp($template['Version'],$xmlFile['Version']) > 0) || (strcmp($OSupdates['Version'],$xmlFile['Version']) > 0); } ###################### # Writes an ini file # ###################### function write_ini_file($file,$array) { - $res = []; - foreach($array as $key => $val) { - if(is_array($val)) { - $res[] = "[$key]"; - foreach($val as $skey => $sval) - $res[] = $skey.'="'.$sval.'"'; - } - else - $res[] = $key.'="'.$val.'"'; - } - ca_file_put_contents($file,implode("\r\n", $res),LOCK_EX); + $res = []; + foreach($array as $key => $val) { + if(is_array($val)) { + $res[] = "[$key]"; + foreach($val as $skey => $sval) + $res[] = $skey.'="'.$sval.'"'; + } + else + $res[] = $key.'="'.$val.'"'; + } + ca_file_put_contents($file,implode("\r\n", $res),LOCK_EX); } ################################################### # Gets all the information about what's installed # ################################################### function getAllInfo($force=false) { - global $caSettings, $DockerTemplates, $DockerClient, $caPaths; + global $caSettings, $DockerTemplates, $DockerClient, $caPaths; - $containers = readJsonFile($caPaths['info']); + $containers = readJsonFile($caPaths['info']); - if ( $force || ! $containers || empty($containers) ) { - if ( $caSettings['dockerRunning'] ?? false ) { - $info = $DockerTemplates->getAllInfo(false,true,true); - $containers = $DockerClient->getDockerContainers(); - foreach ($containers as &$container) { - $container['running'] = $info[$container['Name']]['running'] ?? null; - $container['url'] = $info[$container['Name']]['url'] ?? null; - $container['template'] = $info[$container['Name']]['template'] ?? null; - } - } - debug("Forced info update"); - writeJsonFile($caPaths['info'],$containers); - } else { - debug("Cached info update"); - } - return $containers; + if ( $force || ! $containers || empty($containers) ) { + if ( $caSettings['dockerRunning'] ?? false ) { + $info = $DockerTemplates->getAllInfo(false,true,true); + $containers = $DockerClient->getDockerContainers(); + foreach ($containers as &$container) { + $container['running'] = $info[$container['Name']]['running'] ?? null; + $container['url'] = $info[$container['Name']]['url'] ?? null; + $container['template'] = $info[$container['Name']]['template'] ?? null; + } + } + debug("Forced info update"); + writeJsonFile($caPaths['info'],$containers); + } else { + debug("Cached info update"); + } + return $containers; } ####################### # Logs the debug info # ####################### function debug($str) { - global $caSettings, $caPaths; + global $caSettings, $caPaths; - if ( $caSettings['debugging'] == "yes" ) { - if ( ! is_file($caPaths['logging']) ) { - touch($caPaths['logging']); - $caVersion = plugin("version","/var/log/plugins/community.applications.plg"); + if ( $caSettings['debugging'] == "yes" ) { + if ( ! is_file($caPaths['logging']) ) { + touch($caPaths['logging']); + $caVersion = plugin("version","/var/log/plugins/community.applications.plg"); - debug("Community Applications Version: $caVersion"); - debug("Unraid version: {$caSettings['unRaidVersion']}"); - debug("MD5's: \n".shell_exec("cd /usr/local/emhttp/plugins/community.applications && md5sum -c ca.md5")); - $lingo = $_SESSION['locale'] ?? "en_US"; - debug("Language: $lingo"); - debug("Settings:\n".print_r($caSettings,true)); - } - @file_put_contents($caPaths['logging'],date('Y-m-d H:i:s')." $str\n",FILE_APPEND); //don't run through CA wrapper as this is non-critical - } + debug("Community Applications Version: $caVersion"); + debug("Unraid version: {$caSettings['unRaidVersion']}"); + debug("MD5's: \n".shell_exec("cd /usr/local/emhttp/plugins/community.applications && md5sum -c ca.md5")); + $lingo = $_SESSION['locale'] ?? "en_US"; + debug("Language: $lingo"); + debug("Settings:\n".print_r($caSettings,true)); + } + @file_put_contents($caPaths['logging'],date('Y-m-d H:i:s')." $str\n",FILE_APPEND); //don't run through CA wrapper as this is non-critical + } } ######################################## # Gets the default ports in a template # ######################################## function portsUsed($template) { - if ( ($template['Network'] ?? "whatever") !== "bridge") - return; - $portsUsed = []; - if ( isset($template['Config']['@attributes']) ) - $template['Config'] = ['@attributes'=>$template['Config']]; - if ( is_array($template['Config']) ) { - foreach ($template['Config'] as $config) { - if ( $config['@attributes']['Type'] !== "Port" ) - continue; - $portsUsed[] = $config['value'] ?: $config['@attributes']['Default']; - } - } - return json_encode($portsUsed); + if ( ($template['Network'] ?? "whatever") !== "bridge") + return; + $portsUsed = []; + if ( isset($template['Config']['@attributes']) ) + $template['Config'] = ['@attributes'=>$template['Config']]; + if ( is_array($template['Config']) ) { + foreach ($template['Config'] as $config) { + if ( $config['@attributes']['Type'] !== "Port" ) + continue; + $portsUsed[] = $config['value'] ?: $config['@attributes']['Default']; + } + } + return json_encode($portsUsed); } ######################## # Get the ports in use # ######################## function getPortsInUse() { - global $var, $caPaths; + global $var, $caPaths; - $addr = null; - if ( !$var ) - $var = parse_ini_file($caPaths['unRaidVars']); + $addr = null; + if ( !$var ) + $var = parse_ini_file($caPaths['unRaidVars']); - $portsInUse = []; - exec("lsof -Pni|awk '/LISTEN/ && \$9!~/127.0.0.1/ && \$9!~/\\[::1\\]/{print \$9}'|sort -u", $output); + $portsInUse = []; + exec("lsof -Pni|awk '/LISTEN/ && \$9!~/127.0.0.1/ && \$9!~/\\[::1\\]/{print \$9}'|sort -u", $output); - $bind = $var['BIND_MGT']=='yes'; - $list = is_array($addr) ? array_merge(['*'],$addr) : ['*',$addr]; + $bind = $var['BIND_MGT']=='yes'; + $list = is_array($addr) ? array_merge(['*'],$addr) : ['*',$addr]; - foreach ($output as $line) { - [$ip, $port] = ca_explode(':', $line); - if (!in_array($port,$portsInUse) && (!$bind || in_array(plain($ip),$list))) - if ( is_numeric($port) ) - $portsInUse[] = $port; - } + foreach ($output as $line) { + [$ip, $port] = ca_explode(':', $line); + if (!in_array($port,$portsInUse) && (!$bind || in_array(plain($ip),$list))) + if ( is_numeric($port) ) + $portsInUse[] = $port; + } - return $portsInUse; + return $portsInUse; } function ca_explode($split,$text,$count=2) { - return array_pad(explode($split,$text,$count),$count,''); + return array_pad(explode($split,$text,$count),$count,''); } function plain($ip) { - return str_replace(['[',']'],'',$ip); + return str_replace(['[',']'],'',$ip); } ################################################################################## # Adds in all the various missing entries from the templates for PHP8 compliance # ################################################################################## function addMissingVars($o) { - if ( ! is_array($o) ) - return $o; - $vars = [ - 'Category', - 'CategoryList', - 'CABlacklist', - 'Blacklist', - 'MinVer', - 'MaxVer', - 'UpdateMinVer', - 'Plugin', - 'PluginURL', - 'Date', - 'DonateText', - 'DonateLink', - 'Branch', - 'OriginalOverview', - 'DateInstalled', - 'Config', - 'trending', - 'CAComment', - 'ModeratorComment', - 'DeprecatedMaxVer', - 'downloads', - 'FirstSeen', - 'OriginalDescription', - 'Deprecated', - 'RecommendedRaw', - 'Language', - 'RequiresFile', - 'Requires', - 'trends', - 'Description', - 'OriginalDescription', - 'Overview', - 'Repository', - 'Tag', - 'Plugin', - 'CaComment', - 'IncompatibleVersion', - 'Private', - 'BranchName', - 'display', - 'RepositoryTemplate', - 'bio', - 'NoInstall', - 'Twitter', - 'Discord', - 'Reddit', - 'Facebook', - 'ReadMe', - 'display_dockerName', - 'actionCentre', - 'SupportLanguage', - 'DockerHub', - 'Official', - 'Removable', - 'IconFA', - 'imageNoClick', - 'RecommendedDate', - 'UpdateAvailable', - 'Installed', - 'Uninstall', - 'caTemplateExists', - 'Support', - 'Beta', - 'Project', - 'Trusted', - 'InstallPath', - 'LanguagePack', - 'trendDelta', - 'RepoTemplate', - 'ExtraSearchTerms', - 'Icon', - 'LanguageDefault', - 'translatedCategories', - 'RepoShort', - 'LanguageLocal', - 'ExtraPriority', - 'Registry', - 'caTemplateURL', - 'Changes', - 'ChangeLogPresent', - 'Photo', - 'Screenshot', - 'Video', - 'RecommendedReason', - 'stars', - 'LanguageURL', - 'LastUpdate', - 'RecommendedWho', - 'RepoName', - 'SortName', - 'ca_fav', - 'Pinned' + if ( ! is_array($o) ) + return $o; + $vars = [ + 'Category', + 'CategoryList', + 'CABlacklist', + 'Blacklist', + 'MinVer', + 'MaxVer', + 'UpdateMinVer', + 'Plugin', + 'PluginURL', + 'Date', + 'DonateText', + 'DonateLink', + 'Branch', + 'OriginalOverview', + 'DateInstalled', + 'Config', + 'trending', + 'CAComment', + 'ModeratorComment', + 'DeprecatedMaxVer', + 'downloads', + 'FirstSeen', + 'OriginalDescription', + 'Deprecated', + 'RecommendedRaw', + 'Language', + 'RequiresFile', + 'Requires', + 'trends', + 'Description', + 'OriginalDescription', + 'Overview', + 'Repository', + 'Tag', + 'Plugin', + 'CaComment', + 'IncompatibleVersion', + 'Private', + 'BranchName', + 'display', + 'RepositoryTemplate', + 'bio', + 'NoInstall', + 'Twitter', + 'Discord', + 'Reddit', + 'Facebook', + 'ReadMe', + 'display_dockerName', + 'actionCentre', + 'SupportLanguage', + 'DockerHub', + 'Official', + 'Removable', + 'IconFA', + 'imageNoClick', + 'RecommendedDate', + 'UpdateAvailable', + 'Installed', + 'Uninstall', + 'caTemplateExists', + 'Support', + 'Beta', + 'Project', + 'Trusted', + 'InstallPath', + 'LanguagePack', + 'trendDelta', + 'RepoTemplate', + 'ExtraSearchTerms', + 'Icon', + 'LanguageDefault', + 'translatedCategories', + 'RepoShort', + 'LanguageLocal', + 'ExtraPriority', + 'Registry', + 'caTemplateURL', + 'Changes', + 'ChangeLogPresent', + 'Photo', + 'Screenshot', + 'Video', + 'RecommendedReason', + 'stars', + 'LanguageURL', + 'LastUpdate', + 'RecommendedWho', + 'RepoName', + 'SortName', + 'ca_fav', + 'Pinned' - ]; + ]; - foreach ($vars as $var) { - $o[$var] = $o[$var] ?? null; - } - return $o; + foreach ($vars as $var) { + $o[$var] = $o[$var] ?? null; + } + return $o; } @@ -877,483 +877,483 @@ function addMissingVars($o) { */ class TypeConverter { - /** - * Disregard XML attributes and only return the value. - */ - const XML_NONE = 0; + /** + * Disregard XML attributes and only return the value. + */ + const XML_NONE = 0; - /** - * Merge attributes and the value into a single dimension; the values key will be "value". - */ - const XML_MERGE = 1; + /** + * Merge attributes and the value into a single dimension; the values key will be "value". + */ + const XML_MERGE = 1; - /** - * Group the attributes into a key "attributes" and the value into a key of "value". - */ - const XML_GROUP = 2; + /** + * Group the attributes into a key "attributes" and the value into a key of "value". + */ + const XML_GROUP = 2; - /** - * Attributes will only be returned. - */ - const XML_OVERWRITE = 3; + /** + * Attributes will only be returned. + */ + const XML_OVERWRITE = 3; - /** - * Returns a string for the detected type. - * - * @access public - * @param mixed $data - * @return string - * @static - */ - public static function is($data) { - if (self::isArray($data)) { - return 'array'; + /** + * Returns a string for the detected type. + * + * @access public + * @param mixed $data + * @return string + * @static + */ + public static function is($data) { + if (self::isArray($data)) { + return 'array'; - } else if (self::isObject($data)) { - return 'object'; + } else if (self::isObject($data)) { + return 'object'; - } else if (self::isJson($data)) { - return 'json'; + } else if (self::isJson($data)) { + return 'json'; - } else if (self::isSerialized($data)) { - return 'serialized'; + } else if (self::isSerialized($data)) { + return 'serialized'; - } else if (self::isXml($data)) { - return 'xml'; - } + } else if (self::isXml($data)) { + return 'xml'; + } - return 'other'; - } + return 'other'; + } - /** - * Check to see if data passed is an array. - * - * @access public - * @param mixed $data - * @return boolean - * @static - */ - public static function isArray($data) { - return is_array($data); - } + /** + * Check to see if data passed is an array. + * + * @access public + * @param mixed $data + * @return boolean + * @static + */ + public static function isArray($data) { + return is_array($data); + } - /** - * Check to see if data passed is a JSON object. - * - * @access public - * @param mixed $data - * @return boolean - * @static - */ - public static function isJson($data) { - return (@json_decode($data) !== null); - } + /** + * Check to see if data passed is a JSON object. + * + * @access public + * @param mixed $data + * @return boolean + * @static + */ + public static function isJson($data) { + return (@json_decode($data) !== null); + } - /** - * Check to see if data passed is an object. - * - * @access public - * @param mixed $data - * @return boolean - * @static - */ - public static function isObject($data) { - return is_object($data); - } + /** + * Check to see if data passed is an object. + * + * @access public + * @param mixed $data + * @return boolean + * @static + */ + public static function isObject($data) { + return is_object($data); + } - /** - * Check to see if data passed has been serialized. - * - * @access public - * @param mixed $data - * @return boolean - * @static - */ - public static function isSerialized($data) { - $ser = @unserialize($data); + /** + * Check to see if data passed has been serialized. + * + * @access public + * @param mixed $data + * @return boolean + * @static + */ + public static function isSerialized($data) { + $ser = @unserialize($data); - return ($ser !== false) ? $ser : false; - } + return ($ser !== false) ? $ser : false; + } - /** - * Check to see if data passed is an XML document. - * - * @access public - * @param mixed $data - * @return boolean - * @static - */ - public static function isXml($data) { - $xml = @simplexml_load_string($data); + /** + * Check to see if data passed is an XML document. + * + * @access public + * @param mixed $data + * @return boolean + * @static + */ + public static function isXml($data) { + $xml = @simplexml_load_string($data); - return ($xml instanceof SimpleXmlElement) ? $xml : false; - } + return ($xml instanceof SimpleXmlElement) ? $xml : false; + } - /** - * Transforms a resource into an array. - * - * @access public - * @param mixed $resource - * @return array - * @static - */ - public static function toArray($resource) { - if (self::isArray($resource)) { - return $resource; + /** + * Transforms a resource into an array. + * + * @access public + * @param mixed $resource + * @return array + * @static + */ + public static function toArray($resource) { + if (self::isArray($resource)) { + return $resource; - } else if (self::isObject($resource)) { - return self::buildArray($resource); + } else if (self::isObject($resource)) { + return self::buildArray($resource); - } else if (self::isJson($resource)) { - return json_decode($resource, true); + } else if (self::isJson($resource)) { + return json_decode($resource, true); - } else if ($ser = self::isSerialized($resource)) { - return self::toArray($ser); + } else if ($ser = self::isSerialized($resource)) { + return self::toArray($ser); - } else if ($xml = self::isXml($resource)) { - return self::xmlToArray($xml); - } + } else if ($xml = self::isXml($resource)) { + return self::xmlToArray($xml); + } - return $resource; - } + return $resource; + } - /** - * Transforms a resource into a JSON object. - * - * @access public - * @param mixed $resource - * @return string (json) - * @static - */ - public static function toJson($resource) { - if (self::isJson($resource)) { - return $resource; - } + /** + * Transforms a resource into a JSON object. + * + * @access public + * @param mixed $resource + * @return string (json) + * @static + */ + public static function toJson($resource) { + if (self::isJson($resource)) { + return $resource; + } - if ($xml = self::isXml($resource)) { - $resource = self::xmlToArray($xml); + if ($xml = self::isXml($resource)) { + $resource = self::xmlToArray($xml); - } else if ($ser = self::isSerialized($resource)) { - $resource = $ser; - } + } else if ($ser = self::isSerialized($resource)) { + $resource = $ser; + } - return json_encode($resource); - } + return json_encode($resource); + } - /** - * Transforms a resource into an object. - * - * @access public - * @param mixed $resource - * @return object - * @static - */ - public static function toObject($resource) { - if (self::isObject($resource)) { - return $resource; + /** + * Transforms a resource into an object. + * + * @access public + * @param mixed $resource + * @return object + * @static + */ + public static function toObject($resource) { + if (self::isObject($resource)) { + return $resource; - } else if (self::isArray($resource)) { - return self::buildObject($resource); + } else if (self::isArray($resource)) { + return self::buildObject($resource); - } else if (self::isJson($resource)) { - return json_decode($resource); + } else if (self::isJson($resource)) { + return json_decode($resource); - } else if ($ser = self::isSerialized($resource)) { - return self::toObject($ser); + } else if ($ser = self::isSerialized($resource)) { + return self::toObject($ser); - } else if ($xml = self::isXml($resource)) { - return $xml; - } + } else if ($xml = self::isXml($resource)) { + return $xml; + } - return $resource; - } + return $resource; + } - /** - * Transforms a resource into a serialized form. - * - * @access public - * @param mixed $resource - * @return string - * @static - */ - public static function toSerialize($resource) { - if (!self::isArray($resource)) { - $resource = self::toArray($resource); - } + /** + * Transforms a resource into a serialized form. + * + * @access public + * @param mixed $resource + * @return string + * @static + */ + public static function toSerialize($resource) { + if (!self::isArray($resource)) { + $resource = self::toArray($resource); + } - return serialize($resource); - } + return serialize($resource); + } - /** - * Transforms a resource into an XML document. - * - * @access public - * @param mixed $resource - * @param string $root - * @return string (xml) - * @static - */ - public static function toXml($resource, $root = 'root') { - if (self::isXml($resource)) { - return $resource; - } + /** + * Transforms a resource into an XML document. + * + * @access public + * @param mixed $resource + * @param string $root + * @return string (xml) + * @static + */ + public static function toXml($resource, $root = 'root') { + if (self::isXml($resource)) { + return $resource; + } - $array = self::toArray($resource); + $array = self::toArray($resource); - if (!empty($array)) { - $xml = simplexml_load_string('<'. $root .'>'); - $response = self::buildXml($xml, $array); + if (!empty($array)) { + $xml = simplexml_load_string('<'. $root .'>'); + $response = self::buildXml($xml, $array); - return $response->asXML(); - } + return $response->asXML(); + } - return $resource; - } + return $resource; + } - /** - * Turn an object into an array. Alternative to array_map magic. - * - * @access public - * @param object $object - * @return array - */ - public static function buildArray($object) { - $array = array(); + /** + * Turn an object into an array. Alternative to array_map magic. + * + * @access public + * @param object $object + * @return array + */ + public static function buildArray($object) { + $array = array(); - foreach ($object as $key => $value) { - if (is_object($value)) { - $array[$key] = self::buildArray($value); - } else { - $array[$key] = $value; - } - } + foreach ($object as $key => $value) { + if (is_object($value)) { + $array[$key] = self::buildArray($value); + } else { + $array[$key] = $value; + } + } - return $array; - } + return $array; + } - /** - * Turn an array into an object. Alternative to array_map magic. - * - * @access public - * @param array $array - * @return object - */ - public static function buildObject($array) { - $obj = new \stdClass(); + /** + * Turn an array into an object. Alternative to array_map magic. + * + * @access public + * @param array $array + * @return object + */ + public static function buildObject($array) { + $obj = new \stdClass(); - foreach ($array as $key => $value) { - if (is_array($value)) { - $obj->{$key} = self::buildObject($value); - } else { - $obj->{$key} = $value; - } - } + foreach ($array as $key => $value) { + if (is_array($value)) { + $obj->{$key} = self::buildObject($value); + } else { + $obj->{$key} = $value; + } + } - return $obj; - } + return $obj; + } - /** - * Turn an array into an XML document. Alternative to array_map magic. - * - * @access public - * @param object $xml - * @param array $array - * @return object - */ - public static function buildXml(&$xml, $array) { - if (is_array($array)) { - foreach ($array as $key => $value) { - // XML_NONE - if (!is_array($value)) { - $xml->addChild($key, $value); - continue; - } + /** + * Turn an array into an XML document. Alternative to array_map magic. + * + * @access public + * @param object $xml + * @param array $array + * @return object + */ + public static function buildXml(&$xml, $array) { + if (is_array($array)) { + foreach ($array as $key => $value) { + // XML_NONE + if (!is_array($value)) { + $xml->addChild($key, $value); + continue; + } - // Multiple nodes of the same name - if (isset($value[0])) { - foreach ($value as $kValue) { - if (is_array($kValue)) { - self::buildXml($xml, array($key => $kValue)); - } else { - $xml->addChild($key, $kValue); - } - } + // Multiple nodes of the same name + if (isset($value[0])) { + foreach ($value as $kValue) { + if (is_array($kValue)) { + self::buildXml($xml, array($key => $kValue)); + } else { + $xml->addChild($key, $kValue); + } + } - // XML_GROUP - } else if (isset($value['@attributes'])) { - if (is_array($value['value'])) { - $node = $xml->addChild($key); - self::buildXml($node, $value['value']); - } else { - $node = $xml->addChild($key, $value['value']); - } + // XML_GROUP + } else if (isset($value['@attributes'])) { + if (is_array($value['value'])) { + $node = $xml->addChild($key); + self::buildXml($node, $value['value']); + } else { + $node = $xml->addChild($key, $value['value']); + } - if (!empty($value['@attributes'])) { - foreach ($value['@attributes'] as $aKey => $aValue) { - $node->addAttribute($aKey, $aValue); - } - } + if (!empty($value['@attributes'])) { + foreach ($value['@attributes'] as $aKey => $aValue) { + $node->addAttribute($aKey, $aValue); + } + } - // XML_MERGE - } else if (isset($value['value'])) { - $node = $xml->addChild($key, $value['value']); - unset($value['value']); + // XML_MERGE + } else if (isset($value['value'])) { + $node = $xml->addChild($key, $value['value']); + unset($value['value']); - if (!empty($value)) { - foreach ($value as $aKey => $aValue) { - if (is_array($aValue)) { - self::buildXml($node, array($aKey => $aValue)); - } else { - $node->addAttribute($aKey, $aValue); - } - } - } + if (!empty($value)) { + foreach ($value as $aKey => $aValue) { + if (is_array($aValue)) { + self::buildXml($node, array($aKey => $aValue)); + } else { + $node->addAttribute($aKey, $aValue); + } + } + } - // XML_OVERWRITE - } else { - $node = $xml->addChild($key); + // XML_OVERWRITE + } else { + $node = $xml->addChild($key); - if (!empty($value)) { - foreach ($value as $aKey => $aValue) { - if (is_array($aValue)) { - self::buildXml($node, array($aKey => $aValue)); - } else { - $node->addChild($aKey, $aValue); - } - } - } - } - } - } + if (!empty($value)) { + foreach ($value as $aKey => $aValue) { + if (is_array($aValue)) { + self::buildXml($node, array($aKey => $aValue)); + } else { + $node->addChild($aKey, $aValue); + } + } + } + } + } + } - return $xml; - } + return $xml; + } - /** - * Convert a SimpleXML object into an array. - * - * @access public - * @param object $xml - * @param int $format - * @return array - */ - public static function xmlToArray($xml, $format = self::XML_GROUP) { - if (is_string($xml)) { - $xml = @simplexml_load_string($xml); - } - if ( ! $xml ) { return false; } - if (count($xml->children()) <= 0) { - return (string)$xml; - } + /** + * Convert a SimpleXML object into an array. + * + * @access public + * @param object $xml + * @param int $format + * @return array + */ + public static function xmlToArray($xml, $format = self::XML_GROUP) { + if (is_string($xml)) { + $xml = @simplexml_load_string($xml); + } + if ( ! $xml ) { return false; } + if (count($xml->children()) <= 0) { + return (string)$xml; + } - $array = array(); + $array = array(); - foreach ($xml->children() as $element => $node) { - $data = array(); + foreach ($xml->children() as $element => $node) { + $data = array(); - if (!isset($array[$element])) { + if (!isset($array[$element])) { # $array[$element] = ""; - $array[$element] = []; - } + $array[$element] = []; + } - if (!$node->attributes() || $format === self::XML_NONE) { - $data = self::xmlToArray($node, $format); + if (!$node->attributes() || $format === self::XML_NONE) { + $data = self::xmlToArray($node, $format); - } else { - switch ($format) { - case self::XML_GROUP: - $data = array( - '@attributes' => array(), - 'value' => (string)$node - ); + } else { + switch ($format) { + case self::XML_GROUP: + $data = array( + '@attributes' => array(), + 'value' => (string)$node + ); - if (count($node->children()) > 0) { - $data['value'] = self::xmlToArray($node, $format); - } + if (count($node->children()) > 0) { + $data['value'] = self::xmlToArray($node, $format); + } - foreach ($node->attributes() as $attr => $value) { - $data['@attributes'][$attr] = (string)$value; - } - break; + foreach ($node->attributes() as $attr => $value) { + $data['@attributes'][$attr] = (string)$value; + } + break; - case self::XML_MERGE: - case self::XML_OVERWRITE: - if ($format === self::XML_MERGE) { - if (count($node->children()) > 0) { - $data = $data + self::xmlToArray($node, $format); - } else { - $data['value'] = (string)$node; - } - } + case self::XML_MERGE: + case self::XML_OVERWRITE: + if ($format === self::XML_MERGE) { + if (count($node->children()) > 0) { + $data = $data + self::xmlToArray($node, $format); + } else { + $data['value'] = (string)$node; + } + } - foreach ($node->attributes() as $attr => $value) { - $data[$attr] = (string)$value; - } - break; - } - } + foreach ($node->attributes() as $attr => $value) { + $data[$attr] = (string)$value; + } + break; + } + } - if (count($xml->{$element}) > 1) { - $array[$element][] = $data; - } else { - $array[$element] = $data; - } - } + if (count($xml->{$element}) > 1) { + $array[$element][] = $data; + } else { + $array[$element] = $data; + } + } - return $array; - } + return $array; + } - /** - * Encode a resource object for UTF-8. - * - * @access public - * @param mixed $data - * @return array|string - * @static - */ - public static function utf8Encode($data) { - if (is_string($data)) { - return utf8_encode($data); + /** + * Encode a resource object for UTF-8. + * + * @access public + * @param mixed $data + * @return array|string + * @static + */ + public static function utf8Encode($data) { + if (is_string($data)) { + return utf8_encode($data); - } else if (is_array($data)) { - foreach ($data as $key => $value) { - $data[utf8_encode($key)] = self::utf8Encode($value); - } + } else if (is_array($data)) { + foreach ($data as $key => $value) { + $data[utf8_encode($key)] = self::utf8Encode($value); + } - } else if (is_object($data)) { - foreach ($data as $key => $value) { - $data->{$key} = self::utf8Encode($value); - } - } + } else if (is_object($data)) { + foreach ($data as $key => $value) { + $data->{$key} = self::utf8Encode($value); + } + } - return $data; - } + return $data; + } - /** - * Decode a resource object for UTF-8. - * - * @access public - * @param mixed $data - * @return array|string - * @static - */ - public static function utf8Decode($data) { - if (is_string($data)) { - return utf8_decode($data); + /** + * Decode a resource object for UTF-8. + * + * @access public + * @param mixed $data + * @return array|string + * @static + */ + public static function utf8Decode($data) { + if (is_string($data)) { + return utf8_decode($data); - } else if (is_array($data)) { - foreach ($data as $key => $value) { - $data[utf8_decode($key)] = self::utf8Decode($value); - } + } else if (is_array($data)) { + foreach ($data as $key => $value) { + $data[utf8_decode($key)] = self::utf8Decode($value); + } - } else if (is_object($data)) { - foreach ($data as $key => $value) { - $data->{$key} = self::utf8Decode($value); - } - } + } else if (is_object($data)) { + foreach ($data as $key => $value) { + $data->{$key} = self::utf8Decode($value); + } + } - return $data; - } + return $data; + } } @@ -1389,120 +1389,120 @@ class TypeConverter { * echo $xml->saveXML(); */ class Array2XML { - private static $xml = null; - private static $encoding = 'UTF-8'; - /** - * Initialize the root XML node [optional] - * @param $version - * @param $encoding - * @param $format_output - */ - public static function init($version = '1.0', $encoding = 'UTF-8', $format_output = true) { - self::$xml = new DomDocument($version, $encoding); - self::$xml->formatOutput = $format_output; - self::$encoding = $encoding; - } - /** - * Convert an Array to XML - * @param string $node_name - name of the root node to be converted - * @param array $arr - aray to be converterd - * @return DomDocument - */ - public static function &createXML($node_name, $arr=array()) { - $xml = self::getXMLRoot(); - $xml->appendChild(self::convert($node_name, $arr)); - self::$xml = null; // clear the xml node in the class for 2nd time use. - return $xml; - } - /** - * Convert an Array to XML - * @param string $node_name - name of the root node to be converted - * @param array $arr - aray to be converterd - * @return DOMNode - */ - private static function &convert($node_name, $arr=array()) { - //print_arr($node_name); - $xml = self::getXMLRoot(); - $node = $xml->createElement($node_name); - if(is_array($arr)){ - // get the attributes first.; - if(isset($arr['@attributes'])) { - foreach($arr['@attributes'] as $key => $value) { - if(!self::isValidTagName($key)) { - throw new Exception('[Array2XML] Illegal character in attribute name. attribute: '.$key.' in node: '.$node_name); - } - $node->setAttribute($key, self::bool2str($value)); - } - unset($arr['@attributes']); //remove the key from the array once done. - } - // check if it has a value stored in @value, if yes store the value and return - // else check if its directly stored as string - if(isset($arr['@value'])) { - $node->appendChild($xml->createTextNode(self::bool2str($arr['@value']))); - unset($arr['@value']); //remove the key from the array once done. - //return from recursion, as a note with value cannot have child nodes. - return $node; - } else if(isset($arr['@cdata'])) { - $node->appendChild($xml->createCDATASection(self::bool2str($arr['@cdata']))); - unset($arr['@cdata']); //remove the key from the array once done. - //return from recursion, as a note with cdata cannot have child nodes. - return $node; - } - } - //create subnodes using recursion - if(is_array($arr)){ - // recurse to get the node for that key - foreach($arr as $key=>$value){ - if(!self::isValidTagName($key)) { - throw new Exception('[Array2XML] Illegal character in tag name. tag: '.$key.' in node: '.$node_name); - } - if(is_array($value) && is_numeric(key($value))) { - // MORE THAN ONE NODE OF ITS KIND; - // if the new array is numeric index, means it is array of nodes of the same kind - // it should follow the parent key name - foreach($value as $k=>$v){ - $node->appendChild(self::convert($key, $v)); - } - } else { - // ONLY ONE NODE OF ITS KIND - $node->appendChild(self::convert($key, $value)); - } - unset($arr[$key]); //remove the key from the array once done. - } - } - // after we are done with all the keys in the array (if it is one) - // we check if it has any text value, if yes, append it. - if(!is_array($arr)) { - $node->appendChild($xml->createTextNode(self::bool2str($arr ?? ""))); - } - return $node; - } - /* - * Get the root XML node, if there isn't one, create it. - */ - private static function getXMLRoot(){ - if(empty(self::$xml)) { - self::init(); - } - return self::$xml; - } - /* - * Get string representation of boolean value - */ - private static function bool2str($v){ - //convert boolean to text value. - $v = $v === true ? 'true' : $v; - $v = $v === false ? 'false' : $v; - return $v; - } - /* - * Check if the tag name or attribute name contains illegal characters - * Ref: http://www.w3.org/TR/xml/#sec-common-syn - */ - private static function isValidTagName($tag){ - $pattern = '/^[a-z_]+[a-z0-9\:\-\.\_]*[^:]*$/i'; - return preg_match($pattern, $tag, $matches) && $matches[0] == $tag; - } + private static $xml = null; + private static $encoding = 'UTF-8'; + /** + * Initialize the root XML node [optional] + * @param $version + * @param $encoding + * @param $format_output + */ + public static function init($version = '1.0', $encoding = 'UTF-8', $format_output = true) { + self::$xml = new DomDocument($version, $encoding); + self::$xml->formatOutput = $format_output; + self::$encoding = $encoding; + } + /** + * Convert an Array to XML + * @param string $node_name - name of the root node to be converted + * @param array $arr - aray to be converterd + * @return DomDocument + */ + public static function &createXML($node_name, $arr=array()) { + $xml = self::getXMLRoot(); + $xml->appendChild(self::convert($node_name, $arr)); + self::$xml = null; // clear the xml node in the class for 2nd time use. + return $xml; + } + /** + * Convert an Array to XML + * @param string $node_name - name of the root node to be converted + * @param array $arr - aray to be converterd + * @return DOMNode + */ + private static function &convert($node_name, $arr=array()) { + //print_arr($node_name); + $xml = self::getXMLRoot(); + $node = $xml->createElement($node_name); + if(is_array($arr)){ + // get the attributes first.; + if(isset($arr['@attributes'])) { + foreach($arr['@attributes'] as $key => $value) { + if(!self::isValidTagName($key)) { + throw new Exception('[Array2XML] Illegal character in attribute name. attribute: '.$key.' in node: '.$node_name); + } + $node->setAttribute($key, self::bool2str($value)); + } + unset($arr['@attributes']); //remove the key from the array once done. + } + // check if it has a value stored in @value, if yes store the value and return + // else check if its directly stored as string + if(isset($arr['@value'])) { + $node->appendChild($xml->createTextNode(self::bool2str($arr['@value']))); + unset($arr['@value']); //remove the key from the array once done. + //return from recursion, as a note with value cannot have child nodes. + return $node; + } else if(isset($arr['@cdata'])) { + $node->appendChild($xml->createCDATASection(self::bool2str($arr['@cdata']))); + unset($arr['@cdata']); //remove the key from the array once done. + //return from recursion, as a note with cdata cannot have child nodes. + return $node; + } + } + //create subnodes using recursion + if(is_array($arr)){ + // recurse to get the node for that key + foreach($arr as $key=>$value){ + if(!self::isValidTagName($key)) { + throw new Exception('[Array2XML] Illegal character in tag name. tag: '.$key.' in node: '.$node_name); + } + if(is_array($value) && is_numeric(key($value))) { + // MORE THAN ONE NODE OF ITS KIND; + // if the new array is numeric index, means it is array of nodes of the same kind + // it should follow the parent key name + foreach($value as $k=>$v){ + $node->appendChild(self::convert($key, $v)); + } + } else { + // ONLY ONE NODE OF ITS KIND + $node->appendChild(self::convert($key, $value)); + } + unset($arr[$key]); //remove the key from the array once done. + } + } + // after we are done with all the keys in the array (if it is one) + // we check if it has any text value, if yes, append it. + if(!is_array($arr)) { + $node->appendChild($xml->createTextNode(self::bool2str($arr ?? ""))); + } + return $node; + } + /* + * Get the root XML node, if there isn't one, create it. + */ + private static function getXMLRoot(){ + if(empty(self::$xml)) { + self::init(); + } + return self::$xml; + } + /* + * Get string representation of boolean value + */ + private static function bool2str($v){ + //convert boolean to text value. + $v = $v === true ? 'true' : $v; + $v = $v === false ? 'false' : $v; + return $v; + } + /* + * Check if the tag name or attribute name contains illegal characters + * Ref: http://www.w3.org/TR/xml/#sec-common-syn + */ + private static function isValidTagName($tag){ + $pattern = '/^[a-z_]+[a-z0-9\:\-\.\_]*[^:]*$/i'; + return preg_match($pattern, $tag, $matches) && $matches[0] == $tag; + } } /** @@ -1526,122 +1526,122 @@ class Array2XML { class XML2Array { - private static $xml = null; - private static $encoding = 'UTF-8'; + private static $xml = null; + private static $encoding = 'UTF-8'; - /** - * Initialize the root XML node [optional] - * @param $version - * @param $encoding - * @param $format_output - */ - public static function init($version = '1.0', $encoding = 'UTF-8', $format_output = true) { - self::$xml = new DOMDocument($version, $encoding); - self::$xml->formatOutput = $format_output; - self::$encoding = $encoding; - } + /** + * Initialize the root XML node [optional] + * @param $version + * @param $encoding + * @param $format_output + */ + public static function init($version = '1.0', $encoding = 'UTF-8', $format_output = true) { + self::$xml = new DOMDocument($version, $encoding); + self::$xml->formatOutput = $format_output; + self::$encoding = $encoding; + } - /** - * Convert an XML to Array - * @param string $node_name - name of the root node to be converted - * @param array $arr - aray to be converterd - * @return DOMDocument - */ - public static function &createArray($input_xml) { - $xml = self::getXMLRoot(); - if(is_string($input_xml)) { - $parsed = $xml->loadXML($input_xml); - if(!$parsed) { - throw new Exception('[XML2Array] Error parsing the XML string.'); - } - } else { - if(get_class($input_xml) != 'DOMDocument') { - throw new Exception('[XML2Array] The input XML object should be of type: DOMDocument.'); - } - $xml = self::$xml = $input_xml; - } - $array[$xml->documentElement->tagName] = self::convert($xml->documentElement); - self::$xml = null; // clear the xml node in the class for 2nd time use. - return $array; - } + /** + * Convert an XML to Array + * @param string $node_name - name of the root node to be converted + * @param array $arr - aray to be converterd + * @return DOMDocument + */ + public static function &createArray($input_xml) { + $xml = self::getXMLRoot(); + if(is_string($input_xml)) { + $parsed = $xml->loadXML($input_xml); + if(!$parsed) { + throw new Exception('[XML2Array] Error parsing the XML string.'); + } + } else { + if(get_class($input_xml) != 'DOMDocument') { + throw new Exception('[XML2Array] The input XML object should be of type: DOMDocument.'); + } + $xml = self::$xml = $input_xml; + } + $array[$xml->documentElement->tagName] = self::convert($xml->documentElement); + self::$xml = null; // clear the xml node in the class for 2nd time use. + return $array; + } - /** - * Convert an Array to XML - * @param mixed $node - XML as a string or as an object of DOMDocument - * @return mixed - */ - private static function &convert($node) { - $output = array(); + /** + * Convert an Array to XML + * @param mixed $node - XML as a string or as an object of DOMDocument + * @return mixed + */ + private static function &convert($node) { + $output = array(); - switch ($node->nodeType) { - case XML_CDATA_SECTION_NODE: - $output['@cdata'] = trim($node->textContent); - break; + switch ($node->nodeType) { + case XML_CDATA_SECTION_NODE: + $output['@cdata'] = trim($node->textContent); + break; - case XML_TEXT_NODE: - $output = trim($node->textContent); - break; + case XML_TEXT_NODE: + $output = trim($node->textContent); + break; - case XML_ELEMENT_NODE: + case XML_ELEMENT_NODE: - // for each child node, call the covert function recursively - for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) { - $child = $node->childNodes->item($i); - $v = self::convert($child); - if(isset($child->tagName)) { - $t = $child->tagName; + // for each child node, call the covert function recursively + for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) { + $child = $node->childNodes->item($i); + $v = self::convert($child); + if(isset($child->tagName)) { + $t = $child->tagName; - // assume more nodes of same kind are coming - if(!isset($output[$t])) { - $output[$t] = array(); - } - $output[$t][] = $v; - } else { - //check if it is not an empty text node - if($v !== '') { - $output = $v; - } - } - } + // assume more nodes of same kind are coming + if(!isset($output[$t])) { + $output[$t] = array(); + } + $output[$t][] = $v; + } else { + //check if it is not an empty text node + if($v !== '') { + $output = $v; + } + } + } - if(is_array($output)) { - // if only one node of its kind, assign it directly instead if array($value); - foreach ($output as $t => $v) { - if(is_array($v) && count($v)==1) { - $output[$t] = $v[0]; - } - } - if(empty($output)) { - //for empty nodes - $output = ''; - } - } + if(is_array($output)) { + // if only one node of its kind, assign it directly instead if array($value); + foreach ($output as $t => $v) { + if(is_array($v) && count($v)==1) { + $output[$t] = $v[0]; + } + } + if(empty($output)) { + //for empty nodes + $output = ''; + } + } - // loop through the attributes and collect them - if($node->attributes->length) { - $a = array(); - foreach($node->attributes as $attrName => $attrNode) { - $a[$attrName] = (string) $attrNode->value; - } - // if its an leaf node, store the value in @value instead of directly storing it. - if(!is_array($output)) { - $output = array('@value' => $output); - } - $output['@attributes'] = $a; - } - break; - } - return $output; - } + // loop through the attributes and collect them + if($node->attributes->length) { + $a = array(); + foreach($node->attributes as $attrName => $attrNode) { + $a[$attrName] = (string) $attrNode->value; + } + // if its an leaf node, store the value in @value instead of directly storing it. + if(!is_array($output)) { + $output = array('@value' => $output); + } + $output['@attributes'] = $a; + } + break; + } + return $output; + } - /* - * Get the root XML node, if there isn't one, create it. - */ - private static function getXMLRoot(){ - if(empty(self::$xml)) { - self::init(); - } - return self::$xml; - } + /* + * Get the root XML node, if there isn't one, create it. + */ + private static function getXMLRoot(){ + if(empty(self::$xml)) { + self::init(); + } + return self::$xml; + } } ?> \ No newline at end of file diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/include/paths.php b/source/community.applications/usr/local/emhttp/plugins/community.applications/include/paths.php index d661dee9..fa7039e7 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/include/paths.php +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/include/paths.php @@ -12,18 +12,18 @@ require_once "$docroot/plugins/dynamix/include/Wrappers.php"; $CA = "community.applications"; if ( ! isset($dockerManPaths) ) { - $dockerManPaths = [ - 'autostart-file' => "/var/lib/docker/unraid-autostart", - 'update-status' => "/var/lib/docker/unraid-update-status.json", - 'template-repos' => "/boot/config/plugins/dockerMan/template-repos", - 'templates-user' => "/boot/config/plugins/dockerMan/templates-user", - 'templates-usb' => "/boot/config/plugins/dockerMan/templates", - 'images' => "/var/lib/docker/unraid/images", - 'user-prefs' => "/boot/config/plugins/dockerMan/userprefs.cfg", - 'plugin' => "$docroot/plugins/dynamix.docker.manager", - 'images-ram' => "$docroot/state/plugins/dynamix.docker.manager/images", - 'webui-info' => "$docroot/state/plugins/dynamix.docker.manager/docker.json" - ]; + $dockerManPaths = [ + 'autostart-file' => "/var/lib/docker/unraid-autostart", + 'update-status' => "/var/lib/docker/unraid-update-status.json", + 'template-repos' => "/boot/config/plugins/dockerMan/template-repos", + 'templates-user' => "/boot/config/plugins/dockerMan/templates-user", + 'templates-usb' => "/boot/config/plugins/dockerMan/templates", + 'images' => "/var/lib/docker/unraid/images", + 'user-prefs' => "/boot/config/plugins/dockerMan/userprefs.cfg", + 'plugin' => "$docroot/plugins/dynamix.docker.manager", + 'images-ram' => "$docroot/state/plugins/dynamix.docker.manager/images", + 'webui-info' => "$docroot/state/plugins/dynamix.docker.manager/docker.json" + ]; } $caPaths['tempFiles'] = "/tmp/$CA/tempFiles"; /* path to temporary files */ diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/checkForUpdates.php b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/checkForUpdates.php index 03ab66d4..93df1403 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/checkForUpdates.php +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/checkForUpdates.php @@ -14,8 +14,8 @@ require_once "$docroot/plugins/community.applications/include/paths.php"; require_once "$docroot/plugins/community.applications/include/helpers.php"; if ( is_file($caPaths['updateRunning']) && file_exists("/proc/".@file_get_contents($caPaths['updateRunning'])) ) { - echo tr("Check for updates already running")."\n"; - exit(); + echo tr("Check for updates already running")."\n"; + exit(); } file_put_contents($caPaths['updateRunning'],getmypid()); @@ -25,16 +25,16 @@ echo tr("Checking for docker container updates")."\n"; exec("$docroot/plugins/dynamix.docker.manager/scripts/dockerupdate check nonotify > /dev/null 2>&1"); echo tr("Checking for plugin updates")."\n"; foreach (glob("/var/log/plugins/*.plg") as $plg) { - if ( $plg == "/var/log/plugins/community.applications.plg" || $plg == "/var/log/plugins/unRAIDServer.plg" || $plg == "/var/log/plugins/gui.search.plg" || $plg == "/var/log/plugins/page.notes.plg") - continue; // avoid possible race condition since CA / gui.search automatically check for updates for themselves when on Apps tab - echo sprintf(tr("Checking %s"),$plg)."\n"; - exec("$docroot/plugins/dynamix.plugin.manager/scripts/plugin check ".escapeshellarg(basename($plg))." > /dev/null 2>&1"); + if ( $plg == "/var/log/plugins/community.applications.plg" || $plg == "/var/log/plugins/unRAIDServer.plg" || $plg == "/var/log/plugins/gui.search.plg" || $plg == "/var/log/plugins/page.notes.plg") + continue; // avoid possible race condition since CA / gui.search automatically check for updates for themselves when on Apps tab + echo sprintf(tr("Checking %s"),$plg)."\n"; + exec("$docroot/plugins/dynamix.plugin.manager/scripts/plugin check ".escapeshellarg(basename($plg))." > /dev/null 2>&1"); } echo tr("Checking for language updates")."\n"; foreach (glob("/var/log/plugins/lang-*.xml") as $lang) { - $lingo = str_replace(["lang-",".xml"],["",""],$lang); - echo sprintf(tr("Checking %s"),basename($lingo))."\n"; - exec("$docroot/plugins/dynamix.plugin.manager/scripts/language check ".basename($lingo)); + $lingo = str_replace(["lang-",".xml"],["",""],$lang); + echo sprintf(tr("Checking %s"),basename($lingo))."\n"; + exec("$docroot/plugins/dynamix.plugin.manager/scripts/language check ".basename($lingo)); } @unlink($caPaths['updateRunning']); ?> \ No newline at end of file diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/dockerConvert.php b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/dockerConvert.php index baba28b7..5e31b27a 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/dockerConvert.php +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/dockerConvert.php @@ -28,141 +28,141 @@ $javascript = file_get_contents("/usr/local/emhttp/plugins/dynamix/javascript/dy echo ""; if ( $_GET['ID'] !== false) { - $dockerID = $_GET['ID']; - $file = readJsonFile($caPaths['dockerSearchResults']); - $dockerIndex = searchArray($file['results'],"ID",$dockerID); - $docker = $file['results'][$dockerIndex]; - $docker['Description'] = str_replace("&", "&", $docker['Description']); + $dockerID = $_GET['ID']; + $file = readJsonFile($caPaths['dockerSearchResults']); + $dockerIndex = searchArray($file['results'],"ID",$dockerID); + $docker = $file['results'][$dockerIndex]; + $docker['Description'] = str_replace("&", "&", $docker['Description']); - $dockerfile['Name'] = "CA_TEST_CONTAINER_DOCKERHUB"; - $dockerfile['Support'] = $docker['DockerHub']; - $dockerfile['Description'] = $docker['Description']."\n\nConverted By Community Applications Always verify this template (and values) against the support page for the container\n\n{$docker['DockerHub']}"; - $dockerfile['Overview'] = $dockerfile['Description']; - $dockerfile['Registry'] = $docker['DockerHub']; - $dockerfile['Repository'] = $docker['Repository']; - $dockerfile['BindTime'] = "true"; - $dockerfile['Privileged'] = "false"; - $dockerfile['Networking']['Mode'] = "bridge"; - $dockerXML = makeXML($dockerfile); - file_put_contents("/boot/config/plugins/dockerMan/templates-user/my-CA_TEST_CONTAINER_DOCKERHUB.xml",$dockerXML); - - - echo "
    "; - $dockers = ["CA_TEST_CONTAINER_DOCKERHUB"]; - echo sprintf(tr("Installing test container"),str_replace(",",", ",$_GET['docker'] ?? ""))."
    "; - $_GET['updateContainer'] = true; - $_GET['ct'] = $dockers; - $_GET['communityApplications'] = true; - $_GET['mute'] = false; - @include($exeFile); # under new GUI, this line returns a duplicated session_start() error. - echo "
    "; + $dockerfile['Name'] = "CA_TEST_CONTAINER_DOCKERHUB"; + $dockerfile['Support'] = $docker['DockerHub']; + $dockerfile['Description'] = $docker['Description']."\n\nConverted By Community Applications Always verify this template (and values) against the support page for the container\n\n{$docker['DockerHub']}"; + $dockerfile['Overview'] = $dockerfile['Description']; + $dockerfile['Registry'] = $docker['DockerHub']; + $dockerfile['Repository'] = $docker['Repository']; + $dockerfile['BindTime'] = "true"; + $dockerfile['Privileged'] = "false"; + $dockerfile['Networking']['Mode'] = "bridge"; + $dockerXML = makeXML($dockerfile); + file_put_contents("/boot/config/plugins/dockerMan/templates-user/my-CA_TEST_CONTAINER_DOCKERHUB.xml",$dockerXML); + + + echo "
    "; + $dockers = ["CA_TEST_CONTAINER_DOCKERHUB"]; + echo sprintf(tr("Installing test container"),str_replace(",",", ",$_GET['docker'] ?? ""))."
    "; + $_GET['updateContainer'] = true; + $_GET['ct'] = $dockers; + $_GET['communityApplications'] = true; + $_GET['mute'] = false; + @include($exeFile); # under new GUI, this line returns a duplicated session_start() error. + echo "
    "; ?> ".tr("Removing test installation")."
    "; - exec("docker rm CA_TEST_CONTAINER_DOCKERHUB"); - - exec("docker rmi {$docker['Repository']}"); - @unlink("/boot/config/plugins/dockerMan/templates-user/my-CA_TEST_CONTAINER_DOCKERHUB.xml"); - - $json = json_decode($output,true); - if ( $json ) { - $paths = isset($json[0]['Mounts']) ? $json[0]['Mounts'] : []; - $ports = isset($json[0]['Config']['ExposedPorts']) ? $json[0]['Config']['ExposedPorts'] : []; - $vars = isset($json[0]['Config']['Env']) ? $json[0]['Config']['Env'] : []; - - $count = 1; - $Config = []; - foreach ($paths as $path) { - $p = ["Name"=>"Container Path $count",'Type'=>"Path","Target"=>$path['Destination'],"Default"=>"","Mode"=>"rw","Display"=>"always","Required"=>"false","Mask"=>"false"]; - if ( $unRaid69 ) $p['Description'] = "Container Path: {$path['Destination']}"; - $Config[]['@attributes'] = $p; - $count++; - } - $count = 1; - foreach ($ports as $port => $name) { - $pp = explode("/",$port); - $p = ["Name"=>"Container Port $count",'Type'=>"Port","Target"=>$pp[0],"Default"=>$pp[0],"Mode"=>$pp[1],"Display"=>"always","Required"=>"false","Mask"=>"false","Description"=>""]; - if ( $unRaid69 ) $p['Description'] = "Container Port: {$pp[0]}"; - $Config[]['@attributes'] = $p; - $count++; - } - $textvars = ""; - foreach ($vars as $var) { - $textvars .= "$var\n"; - } - $testvars = @parse_ini_string($textvars) ?: []; - $defaultvars = ["HOST_HOSTNAME","HOST_OS","HOST_CONTAINERNAME","TZ","PATH"]; - $count = 1; - foreach ($testvars as $var => $varcont) { - if ( in_array($var,$defaultvars) ) - continue; + $output = shell_exec("docker inspect CA_TEST_CONTAINER_DOCKERHUB"); + echo "
    ".tr("Removing test installation")."
    "; + exec("docker rm CA_TEST_CONTAINER_DOCKERHUB"); + + exec("docker rmi {$docker['Repository']}"); + @unlink("/boot/config/plugins/dockerMan/templates-user/my-CA_TEST_CONTAINER_DOCKERHUB.xml"); + + $json = json_decode($output,true); + if ( $json ) { + $paths = isset($json[0]['Mounts']) ? $json[0]['Mounts'] : []; + $ports = isset($json[0]['Config']['ExposedPorts']) ? $json[0]['Config']['ExposedPorts'] : []; + $vars = isset($json[0]['Config']['Env']) ? $json[0]['Config']['Env'] : []; + + $count = 1; + $Config = []; + foreach ($paths as $path) { + $p = ["Name"=>"Container Path $count",'Type'=>"Path","Target"=>$path['Destination'],"Default"=>"","Mode"=>"rw","Display"=>"always","Required"=>"false","Mask"=>"false"]; + if ( $unRaid69 ) $p['Description'] = "Container Path: {$path['Destination']}"; + $Config[]['@attributes'] = $p; + $count++; + } + $count = 1; + foreach ($ports as $port => $name) { + $pp = explode("/",$port); + $p = ["Name"=>"Container Port $count",'Type'=>"Port","Target"=>$pp[0],"Default"=>$pp[0],"Mode"=>$pp[1],"Display"=>"always","Required"=>"false","Mask"=>"false","Description"=>""]; + if ( $unRaid69 ) $p['Description'] = "Container Port: {$pp[0]}"; + $Config[]['@attributes'] = $p; + $count++; + } + $textvars = ""; + foreach ($vars as $var) { + $textvars .= "$var\n"; + } + $testvars = @parse_ini_string($textvars) ?: []; + $defaultvars = ["HOST_HOSTNAME","HOST_OS","HOST_CONTAINERNAME","TZ","PATH"]; + $count = 1; + foreach ($testvars as $var => $varcont) { + if ( in_array($var,$defaultvars) ) + continue; - $p = ["Name"=>"Container Variable $count",'Target'=>$var,"Type"=>"Variable","Default"=>$varcont,"Description"=>"","Required"=>"false","Mask"=>"false","Display"=>"always"]; - if ( $unRaid69 ) $p['Description'] = "Container Variable: $var"; - $Config[]['@attributes'] = $p; - $count++; - } - $Config[]['@attributes'] = ["Name"=>"Community Applications Conversion",'Target'=>"Community_Applications_Conversion","Type"=>"Variable","Default"=>"true","Description"=>"","Required"=>"false","Mask"=>"false","Display"=>"always"]; + $p = ["Name"=>"Container Variable $count",'Target'=>$var,"Type"=>"Variable","Default"=>$varcont,"Description"=>"","Required"=>"false","Mask"=>"false","Display"=>"always"]; + if ( $unRaid69 ) $p['Description'] = "Container Variable: $var"; + $Config[]['@attributes'] = $p; + $count++; + } + $Config[]['@attributes'] = ["Name"=>"Community Applications Conversion",'Target'=>"Community_Applications_Conversion","Type"=>"Variable","Default"=>"true","Description"=>"","Required"=>"false","Mask"=>"false","Display"=>"always"]; - if ( !empty($Config) ) - $dockerfile['Config'] = $Config; - } else { - $error = tr("An error occurred - Could not determine configuration"); - } - $dockerfile['Name'] = $docker['Name']; + if ( !empty($Config) ) + $dockerfile['Config'] = $Config; + } else { + $error = tr("An error occurred - Could not determine configuration"); + } + $dockerfile['Name'] = $docker['Name']; - $existing_templates = array_diff(scandir($dockerManPaths['templates-user']),[".",".."]); - foreach ( $existing_templates as $template ) { - if ( strtolower($dockerfile['Name']) == strtolower(str_replace(["my-",".xml"],["",""],$template)) ) - $dockerfile['Name'] .= "-1"; - } - - file_put_contents($caPaths['dockerSearchInstall'],makeXML($dockerfile)); + $existing_templates = array_diff(scandir($dockerManPaths['templates-user']),[".",".."]); + foreach ( $existing_templates as $template ) { + if ( strtolower($dockerfile['Name']) == strtolower(str_replace(["my-",".xml"],["",""],$template)) ) + $dockerfile['Name'] .= "-1"; + } + + file_put_contents($caPaths['dockerSearchInstall'],makeXML($dockerfile)); } ?> \ No newline at end of file diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installMulti.php b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installMulti.php index ec7a0f2c..977d025d 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installMulti.php +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installMulti.php @@ -23,16 +23,16 @@ require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php"; $unRaidVersion = parse_ini_file($caPaths['unRaidVersion']); function tr($string,$ret=true) { - if ( function_exists("_") ) - $string = str_replace('"',""",str_replace("'","'",_($string))); - if ( $ret ) - return $string; - else - echo $string; + if ( function_exists("_") ) + $string = str_replace('"',""",str_replace("'","'",_($string))); + if ( $ret ) + return $string; + else + echo $string; } function startsWith($haystack, $needle) { - return $needle === "" || strripos($haystack, $needle, -strlen($haystack)) !== FALSE; + return $needle === "" || strripos($haystack, $needle, -strlen($haystack)) !== FALSE; } $exeFile = "/usr/local/emhttp/plugins/dynamix.docker.manager/include/CreateDocker.php"; @@ -41,15 +41,15 @@ $javascript = file_get_contents("/usr/local/emhttp/plugins/dynamix/javascript/dy echo ""; if ( $_GET['docker'] ) { - echo "
    "; - $dockers = explode(",",$_GET['docker']); - echo sprintf(tr("Installing docker applications %s"),str_replace(",",", ",$_GET['docker']))."
    "; - $_GET['updateContainer'] = true; - $_GET['ct'] = $dockers; - $_GET['communityApplications'] = true; - $_GET['mute'] = false; - @include($exeFile); # under new GUI, this line returns a duplicated session_start() error. - echo "
    "; + echo "
    "; + $dockers = explode(",",$_GET['docker']); + echo sprintf(tr("Installing docker applications %s"),str_replace(",",", ",$_GET['docker']))."
    "; + $_GET['updateContainer'] = true; + $_GET['ct'] = $dockers; + $_GET['communityApplications'] = true; + $_GET['mute'] = false; + @include($exeFile); # under new GUI, this line returns a duplicated session_start() error. + echo "
    "; ?> $docker")."
    "; - unset($output); - exec("docker start $docker 2>&1",$output,$retval); - if ($retval) { - $failFlag = true; - echo sprintf(tr("%s failed to start. You should install it by itself to fix the errors"),"$docker")."
    "; - foreach ($output as $line) { - echo "$line
    "; - } - echo "
    "; - } - } - if ( ! is_file("/var/lib/docker/unraid-autostart") ) { - echo "
    ".tr("Setting installed applications to autostart")."
    "; - $autostartFile = array(); + $failFlag = false; + foreach ($dockers as $docker) { + echo sprintf(tr("Starting %s"),"$docker")."
    "; + unset($output); + exec("docker start $docker 2>&1",$output,$retval); + if ($retval) { + $failFlag = true; + echo sprintf(tr("%s failed to start. You should install it by itself to fix the errors"),"$docker")."
    "; + foreach ($output as $line) { + echo "$line
    "; + } + echo "
    "; + } + } + if ( ! is_file("/var/lib/docker/unraid-autostart") ) { + echo "
    ".tr("Setting installed applications to autostart")."
    "; + $autostartFile = array(); - foreach ($dockers as $docker) { - $autostart[$docker] = true; - } - $autostartFile = implode("\n",array_keys($autostart)); - file_put_contents("/var/lib/docker/unraid-autostart",$autostartFile); - } - - echo "
    ".tr("Downloading docker icons")."
    "; - $DockerTemplates->getAllInfo(); - exec("$docroot/plugins/dynamix.docker.manager/scripts/dockerupdate check nonotify > /dev/null 2>&1"); + foreach ($dockers as $docker) { + $autostart[$docker] = true; + } + $autostartFile = implode("\n",array_keys($autostart)); + file_put_contents("/var/lib/docker/unraid-autostart",$autostartFile); + } + + echo "
    ".tr("Downloading docker icons")."
    "; + $DockerTemplates->getAllInfo(); + exec("$docroot/plugins/dynamix.docker.manager/scripts/dockerupdate check nonotify > /dev/null 2>&1"); - if ( $failFlag || !$_GET['plugin']) { - echo "
    ".tr("Docker Application Installation finished")."
    "; - } else { - echo ""; - } - @unlink("/tmp/community.applications/tempFiles/newCreateDocker.php"); + if ( $failFlag || !$_GET['plugin']) { + echo "
    ".tr("Docker Application Installation finished")."
    "; + } else { + echo ""; + } + @unlink("/tmp/community.applications/tempFiles/newCreateDocker.php"); } ?> \ No newline at end of file diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installMultiPlugin.php b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installMultiPlugin.php index 5eb29bf9..4fc42651 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installMultiPlugin.php +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installMultiPlugin.php @@ -12,25 +12,25 @@ require_once "/usr/local/emhttp/plugins/community.applications/include/helpers.p $apps = readJsonFile($caPaths['community-templates-info']); $plugins = explode("*",$argv[1]); foreach ($plugins as $plugin) { - echo $plugin; - if (! $plugin ) continue; - $pluginName = basename($plugin); - $pathInfo = pathinfo($plugin); - if ( $pathInfo['extension'] !== "plg" ) { - if ( is_file("/var/log/plugins/lang-$pluginName.xml") ) { - passthru("/usr/local/emhttp/plugins/community.applications/scripts/languageInstall.sh update $pluginName"); - continue; - } - } - if ( searchArray($apps,"PluginURL",$plugin) !== false ) { - if ( is_file("/var/log/plugins/$pluginName") ) { - passthru("/usr/local/emhttp/plugins/dynamix.plugin.manager/scripts/plugin update $pluginName"); - } else { - passthru("/usr/local/emhttp/plugins/dynamix.plugin.manager/scripts/plugin install ".escapeshellarg($plugin)); - } - } else - echo "$plugin not found in application feed\n"; - @unlink("{$caPaths['pluginPending']}/$pluginName"); + echo $plugin; + if (! $plugin ) continue; + $pluginName = basename($plugin); + $pathInfo = pathinfo($plugin); + if ( $pathInfo['extension'] !== "plg" ) { + if ( is_file("/var/log/plugins/lang-$pluginName.xml") ) { + passthru("/usr/local/emhttp/plugins/community.applications/scripts/languageInstall.sh update $pluginName"); + continue; + } + } + if ( searchArray($apps,"PluginURL",$plugin) !== false ) { + if ( is_file("/var/log/plugins/$pluginName") ) { + passthru("/usr/local/emhttp/plugins/dynamix.plugin.manager/scripts/plugin update $pluginName"); + } else { + passthru("/usr/local/emhttp/plugins/dynamix.plugin.manager/scripts/plugin install ".escapeshellarg($plugin)); + } + } else + echo "$plugin not found in application feed\n"; + @unlink("{$caPaths['pluginPending']}/$pluginName"); } passthru("/usr/local/emhttp/plugins/community.applications/scripts/updatePluginSupport.php"); ?> \ No newline at end of file diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installUpdate.php b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installUpdate.php index 464d4fe0..3583291f 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installUpdate.php +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/installUpdate.php @@ -20,7 +20,7 @@ require_once "/usr/local/emhttp/plugins/dynamix/include/Helpers.php"; $_GET['updateContainer'] = "true"; $_GET['mute'] = false; // $_GET['communityApplications'] = true; - include("/usr/local/emhttp/plugins/dynamix.docker.manager/include/CreateDocker.php"); +include("/usr/local/emhttp/plugins/dynamix.docker.manager/include/CreateDocker.php"); ?> \ No newline at end of file diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/updatePluginSupport.php b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/updatePluginSupport.php index fbae4c1c..298d669f 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/updatePluginSupport.php +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/scripts/updatePluginSupport.php @@ -24,39 +24,39 @@ require_once("$docroot/plugins/dynamix/include/Translations.php"); $plugins = glob("/boot/config/plugins/*.plg"); $templates = readJsonFile($caPaths['community-templates-info']); if ( ! $templates ) { - echo "You must enter the apps tab before using this script\n"; - return; + echo "You must enter the apps tab before using this script\n"; + return; } echo "\n".tr("Updating Support Links")."\n\n"; foreach ($plugins as $plugin) { - $pluginURL = plugin("pluginURL",$plugin); - $pluginEntry = searchArray($templates,"PluginURL",$pluginURL); - if ( $pluginEntry === false ) { - $pluginEntry = searchArray($templates,"PluginURL",str_replace("https://raw.github.com/","https://raw.githubusercontent.com/",$pluginURL)); - } - if ( $pluginEntry !== false && $templates[$pluginEntry]['PluginURL']) { - $xml = simplexml_load_file($plugin); - if ( ! $templates[$pluginEntry]['Support'] ) { - continue; - } - if ( @plugin("support",$plugin) !== $templates[$pluginEntry]['Support'] ) { - // remove existing support attribute if it exists - if ( @plugin("support",$plugin) ) { - $existing_support = $xml->xpath("//PLUGIN/@support"); - foreach ($existing_support as $node) { - unset($node[0]); - } - } - $xml->addAttribute("support",$templates[$pluginEntry]['Support']); - $dom = new DOMDocument('1.0'); - $dom->preserveWhiteSpace = false; - $dom->formatOutput = true; - $dom->loadXML($xml->asXML()); - file_put_contents($plugin, $dom->saveXML()); - echo "".plugin("name",$plugin)." --> {$templates[$pluginEntry]['Support']}\n"; - } - } + $pluginURL = plugin("pluginURL",$plugin); + $pluginEntry = searchArray($templates,"PluginURL",$pluginURL); + if ( $pluginEntry === false ) { + $pluginEntry = searchArray($templates,"PluginURL",str_replace("https://raw.github.com/","https://raw.githubusercontent.com/",$pluginURL)); + } + if ( $pluginEntry !== false && $templates[$pluginEntry]['PluginURL']) { + $xml = simplexml_load_file($plugin); + if ( ! $templates[$pluginEntry]['Support'] ) { + continue; + } + if ( @plugin("support",$plugin) !== $templates[$pluginEntry]['Support'] ) { + // remove existing support attribute if it exists + if ( @plugin("support",$plugin) ) { + $existing_support = $xml->xpath("//PLUGIN/@support"); + foreach ($existing_support as $node) { + unset($node[0]); + } + } + $xml->addAttribute("support",$templates[$pluginEntry]['Support']); + $dom = new DOMDocument('1.0'); + $dom->preserveWhiteSpace = false; + $dom->formatOutput = true; + $dom->loadXML($xml->asXML()); + file_put_contents($plugin, $dom->saveXML()); + echo "".plugin("name",$plugin)." --> {$templates[$pluginEntry]['Support']}\n"; + } + } } echo "\n\n"; echo tr("Finished Installing. If the DONE button did not appear, then you will need to click the red X in the top right corner")."\n"; diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/css.php b/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/css.php index a1078de1..60c6958a 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/css.php +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/css.php @@ -23,96 +23,96 @@ $unRaid66color = "#FF8C2F"; $linkColor = "#486dba"; $startupColor = "#FF8C2F"; switch ($theme) { - case 'black': - $donateBackground = "#ffffff"; - $donateText = "#000000"; - $templateBackground = "#191818"; - $templateHoverBackground = "#121212"; - $templateFavourite = "#333333"; - $hrColor = "#2b2b2b"; - $borderColor = "#2b2b2b"; - $watermarkColor = "rgba(43, 43, 43, 0.4)"; - $aColor = "#00b8d6"; - $sidebarBackground = "#000000"; - $sidebarText = "#f2f2f2"; - $betaPopupOffset = "0"; - $supportPopupText = "#000000"; - $supportPopupBackground = "#ffffff"; - $modCommentBorder = "#cf3131"; - $sidebarCloseBackground = "rgba(0,0,0,0.7)"; - break; - case 'white': - $donateBackground = "#1c1b1b"; - $donateText = "#f2f2f2"; - $templateBackground = "#f5f5f5"; - $templateHoverBackground = "#ffffff"; - $templateFavourite = "#d0d0d0"; - $hrColor = "lightgrey"; - $borderColor = "#e3e3e3"; - $watermarkColor = "rgba(211, 211, 211, 0.8)"; - $aColor = "#486dba"; - $sidebarBackground = "#ffffff"; - $sidebarText = "#000000"; - $betaPopupOffset = "0"; - $supportPopupText = "#f2f2f2"; - $supportPopupBackground = "#1c1b1b"; - $modCommentBorder = "#cf3131"; - $sidebarCloseBackground = "rgba(0,0,0,0.7)"; - break; - case 'azure': - $donateBackground = "#606e7f"; - $donateText = "#e4e2e4"; - $templateBackground = "transparent"; - $templateHoverBackground = "#edeaef"; - $templateFavourite = "#e0e0e0"; - $hrColor = "#606e7f"; - $border = "#9794a7"; - $watermarkColor = "rgba(96, 110, 127, 0.1)"; - $aColor = "#486dba"; - $sidebarBackground = "#edeaef"; - $sidebarText = "#606e7f"; - $betaPopupOffset = "1.5rem;"; - $supportPopupText = "#1b1d1b"; - $supportPopupBackground = "#ffffff"; - $modCommentBorder = "#cf3131"; - $sidebarCloseBackground = "rgba(0,0,0,0.7)"; - break; - case 'gray': - $donateBackground = "#606e7f"; - $donateText = "#1b1d1b"; - $templateBackground = "transparent"; - $templateHoverBackground = "#0c0f0b"; - $templateFavourite = "#2b2b2b"; - $hrColor = "#606e7f"; - $border = "#606e7f"; - $watermarkColor = "rgba(96, 110, 127, 0.1)"; - $aColor = "#00b8d6"; - $sidebarBackground = "#121510"; - $sidebarText = "#f2f2f2"; - $betaPopupOffset = "1.5rem;"; - $supportPopupText = "#1b1d1b"; - $supportPopupBackground = "#ffffff"; - $modCommentBorder = "#cf3131"; - $sidebarCloseBackground = "rgba(0,0,0,0.7)"; - break; + case 'black': + $donateBackground = "#ffffff"; + $donateText = "#000000"; + $templateBackground = "#191818"; + $templateHoverBackground = "#121212"; + $templateFavourite = "#333333"; + $hrColor = "#2b2b2b"; + $borderColor = "#2b2b2b"; + $watermarkColor = "rgba(43, 43, 43, 0.4)"; + $aColor = "#00b8d6"; + $sidebarBackground = "#000000"; + $sidebarText = "#f2f2f2"; + $betaPopupOffset = "0"; + $supportPopupText = "#000000"; + $supportPopupBackground = "#ffffff"; + $modCommentBorder = "#cf3131"; + $sidebarCloseBackground = "rgba(0,0,0,0.7)"; + break; + case 'white': + $donateBackground = "#1c1b1b"; + $donateText = "#f2f2f2"; + $templateBackground = "#f5f5f5"; + $templateHoverBackground = "#ffffff"; + $templateFavourite = "#d0d0d0"; + $hrColor = "lightgrey"; + $borderColor = "#e3e3e3"; + $watermarkColor = "rgba(211, 211, 211, 0.8)"; + $aColor = "#486dba"; + $sidebarBackground = "#ffffff"; + $sidebarText = "#000000"; + $betaPopupOffset = "0"; + $supportPopupText = "#f2f2f2"; + $supportPopupBackground = "#1c1b1b"; + $modCommentBorder = "#cf3131"; + $sidebarCloseBackground = "rgba(0,0,0,0.7)"; + break; + case 'azure': + $donateBackground = "#606e7f"; + $donateText = "#e4e2e4"; + $templateBackground = "transparent"; + $templateHoverBackground = "#edeaef"; + $templateFavourite = "#e0e0e0"; + $hrColor = "#606e7f"; + $border = "#9794a7"; + $watermarkColor = "rgba(96, 110, 127, 0.1)"; + $aColor = "#486dba"; + $sidebarBackground = "#edeaef"; + $sidebarText = "#606e7f"; + $betaPopupOffset = "1.5rem;"; + $supportPopupText = "#1b1d1b"; + $supportPopupBackground = "#ffffff"; + $modCommentBorder = "#cf3131"; + $sidebarCloseBackground = "rgba(0,0,0,0.7)"; + break; + case 'gray': + $donateBackground = "#606e7f"; + $donateText = "#1b1d1b"; + $templateBackground = "transparent"; + $templateHoverBackground = "#0c0f0b"; + $templateFavourite = "#2b2b2b"; + $hrColor = "#606e7f"; + $border = "#606e7f"; + $watermarkColor = "rgba(96, 110, 127, 0.1)"; + $aColor = "#00b8d6"; + $sidebarBackground = "#121510"; + $sidebarText = "#f2f2f2"; + $betaPopupOffset = "1.5rem;"; + $supportPopupText = "#1b1d1b"; + $supportPopupBackground = "#ffffff"; + $modCommentBorder = "#cf3131"; + $sidebarCloseBackground = "rgba(0,0,0,0.7)"; + break; // Use settings for black as a fallback - default: - $donateBackground = "#f2f2f2"; - $donateText = "#1c1b1b"; - $templateBackground = "#0f0f0f"; - $templateFavourite = "#333333"; - $hrColor = "#2b2b2b"; - $borderColor = "#2b2b2b"; - $watermarkColor = "rgba(43, 43, 43, 0.4)"; - $aColor = "#00b8d6"; - $sidebarBackground = "#000000"; - $sidebarText = "#f2f2f2"; - $betaPopupOffset = "0"; - $supportPopupText = "#000000"; - $supportPopupBackground = "#ffffff"; - $modCommentBorder = "#cf3131"; - $sidebarCloseBackground = "rgba(0,0,0,.7)"; - break; + default: + $donateBackground = "#f2f2f2"; + $donateText = "#1c1b1b"; + $templateBackground = "#0f0f0f"; + $templateFavourite = "#333333"; + $hrColor = "#2b2b2b"; + $borderColor = "#2b2b2b"; + $watermarkColor = "rgba(43, 43, 43, 0.4)"; + $aColor = "#00b8d6"; + $sidebarBackground = "#000000"; + $sidebarText = "#f2f2f2"; + $betaPopupOffset = "0"; + $supportPopupText = "#000000"; + $supportPopupBackground = "#ffffff"; + $modCommentBorder = "#cf3131"; + $sidebarCloseBackground = "rgba(0,0,0,.7)"; + break; } ?> a {color:;} @@ -462,8 +462,8 @@ table {background-color:transparent;} @keyframes cycleRed { - 0% {color: inherit;} - 50% {color: #882626;} + 0% {color: inherit;} + 50% {color: #882626;} } .awesomplete [hidden] {display: none;} .awesomplete .visually-hidden {position: absolute;clip: rect(0, 0, 0, 0);} @@ -473,7 +473,7 @@ table {background-color:transparent;} .awesomplete > ul:empty {display: none;} .awesomplete > ul {border-radius: .3em;margin: .2em 0 0;background: hsla(0,0%,100%);background: linear-gradient(to bottom right, white, hsla(0,0%,100%));border: 1px solid rgba(0,0,0,.3);box-shadow: .05em .2em .6em rgba(0,0,0,.2);text-shadow: none;} @supports (transform: scale(0)) {.awesomplete > ul {transition: .3s cubic-bezier(.4,.2,.5,1.4);transform-origin: 1.43em -.43em;} - .awesomplete > ul[hidden],.awesomplete > ul:empty {opacity: 0;transform: scale(0);display: block;transition-timing-function: ease;} + .awesomplete > ul[hidden],.awesomplete > ul:empty {opacity: 0;transform: scale(0);display: block;transition-timing-function: ease;} } /* Pointer */ .awesomplete > ul:before {content: "";position: absolute;top: -.43em;left: 1em;width: 0; height: 0;padding: .4em;background: white;border: inherit;border-right: 0;border-bottom: 0;-webkit-transform: rotate(45deg);transform: rotate(45deg);} @@ -543,22 +543,22 @@ img.mfp-img {width: auto;max-width: 100%;height: auto;display: block;line-height .mfp-gallery .mfp-image-holder .mfp-figure {cursor: pointer; } @media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) { /** - * Remove all paddings around the image on small screen + * Remove all paddings around the image on small screen */ - .mfp-img-mobile .mfp-image-holder {padding-left: 0;padding-right: 0; } - .mfp-img-mobile img.mfp-img {padding: 0; } - .mfp-img-mobile .mfp-figure:after {top: 0;bottom: 0; } - .mfp-img-mobile .mfp-figure small {display: inline;margin-left: 5px; } - .mfp-img-mobile .mfp-bottom-bar {background: rgba(0, 0, 0, 0.6);bottom: 0;margin: 0;top: auto;padding: 3px 5px;position: fixed;box-sizing: border-box; } - .mfp-img-mobile .mfp-bottom-bar:empty {padding: 0; } - .mfp-img-mobile .mfp-counter {right: 5px;top: 3px; } - .mfp-img-mobile .mfp-close {top: 0;right: 0;width: 35px;height: 35px;line-height: 35px;background: rgba(0, 0, 0, 0.6);position: fixed;text-align: center;padding: 0; } + .mfp-img-mobile .mfp-image-holder {padding-left: 0;padding-right: 0; } + .mfp-img-mobile img.mfp-img {padding: 0; } + .mfp-img-mobile .mfp-figure:after {top: 0;bottom: 0; } + .mfp-img-mobile .mfp-figure small {display: inline;margin-left: 5px; } + .mfp-img-mobile .mfp-bottom-bar {background: rgba(0, 0, 0, 0.6);bottom: 0;margin: 0;top: auto;padding: 3px 5px;position: fixed;box-sizing: border-box; } + .mfp-img-mobile .mfp-bottom-bar:empty {padding: 0; } + .mfp-img-mobile .mfp-counter {right: 5px;top: 3px; } + .mfp-img-mobile .mfp-close {top: 0;right: 0;width: 35px;height: 35px;line-height: 35px;background: rgba(0, 0, 0, 0.6);position: fixed;text-align: center;padding: 0; } } @media all and (max-width: 900px) { - .mfp-arrow {-webkit-transform: scale(0.75);transform: scale(0.75); } - .mfp-arrow-left {-webkit-transform-origin: 0;transform-origin: 0; } - .mfp-arrow-right {-webkit-transform-origin: 100%;transform-origin: 100%; } - .mfp-container {padding-left: 6px;padding-right: 6px; } + .mfp-arrow {-webkit-transform: scale(0.75);transform: scale(0.75); } + .mfp-arrow-left {-webkit-transform-origin: 0;transform-origin: 0; } + .mfp-arrow-right {-webkit-transform-origin: 100%;transform-origin: 100%; } + .mfp-container {padding-left: 6px;padding-right: 6px; } } /* overlay at start */ .mfp-fade.mfp-bg {opacity: 0;-webkit-transition: all 0.5s ease-out;-moz-transition: all 0.5s ease-out;transition: all 0.5s ease-out;} diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/skin.html b/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/skin.html index c9ece6eb..0796cb76 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/skin.html +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/skin.html @@ -1,45 +1,45 @@
    @@ -61,22 +61,22 @@
    \ No newline at end of file diff --git a/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/skin.php b/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/skin.php index f2800b0d..9103ba98 100644 --- a/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/skin.php +++ b/source/community.applications/usr/local/emhttp/plugins/community.applications/skins/Narrow/skin.php @@ -7,447 +7,447 @@ ############################################################### function display_apps($pageNumber=1,$selectedApps=false,$startup=false) { - global $caPaths, $caSettings, $sortOrder; + global $caPaths, $caSettings, $sortOrder; - if ( is_file($caPaths['repositoriesDisplayed']) ) { - $file = readJsonFile($caPaths['repositoriesDisplayed']); - //$startup = true; - } else { - if ( is_file($caPaths['community-templates-catSearchResults']) ) - $file = readJsonFile($caPaths['community-templates-catSearchResults']); - else - $file = readJsonFile($caPaths['community-templates-displayed']); - } - $communityApplications = is_array($file['community']) ? $file['community'] : []; - $totalApplications = count($communityApplications); + if ( is_file($caPaths['repositoriesDisplayed']) ) { + $file = readJsonFile($caPaths['repositoriesDisplayed']); + //$startup = true; + } else { + if ( is_file($caPaths['community-templates-catSearchResults']) ) + $file = readJsonFile($caPaths['community-templates-catSearchResults']); + else + $file = readJsonFile($caPaths['community-templates-displayed']); + } + $communityApplications = is_array($file['community']) ? $file['community'] : []; + $totalApplications = count($communityApplications); - $display = ( $totalApplications ) ? my_display_apps($communityApplications,$pageNumber,$selectedApps,$startup) : "
    ".tr("No Matching Applications Found")."
    "; + $display = ( $totalApplications ) ? my_display_apps($communityApplications,$pageNumber,$selectedApps,$startup) : "
    ".tr("No Matching Applications Found")."
    "; - return $display; + return $display; } function my_display_apps($file,$pageNumber=1,$selectedApps=false,$startup=false) { - global $caPaths, $caSettings, $plugin, $displayDeprecated, $sortOrder, $DockerTemplates, $DockerClient; + global $caPaths, $caSettings, $plugin, $displayDeprecated, $sortOrder, $DockerTemplates, $DockerClient; - $dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']); - $repositories = readJsonFile($caPaths['repositoryList']); - $extraBlacklist = readJsonFile($caPaths['extraBlacklist']); - $extraDeprecated = readJsonFile($caPaths['extraDeprecated']); - $ct = ""; - $count = 0; + $dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']); + $repositories = readJsonFile($caPaths['repositoryList']); + $extraBlacklist = readJsonFile($caPaths['extraBlacklist']); + $extraDeprecated = readJsonFile($caPaths['extraDeprecated']); + $ct = ""; + $count = 0; - if ( is_file("/var/run/dockerd.pid") && is_dir("/proc/".@file_get_contents("/var/run/dockerd.pid")) ) { - $caSettings['dockerRunning'] = "true"; - $info = getAllInfo(); - $dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']); - } else { - $caSettings['dockerRunning'] = false; - $info = []; - $dockerUpdateStatus = []; - } + if ( is_file("/var/run/dockerd.pid") && is_dir("/proc/".@file_get_contents("/var/run/dockerd.pid")) ) { + $caSettings['dockerRunning'] = "true"; + $info = getAllInfo(); + $dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']); + } else { + $caSettings['dockerRunning'] = false; + $info = []; + $dockerUpdateStatus = []; + } - if ( ! $selectedApps ) - $selectedApps = []; + if ( ! $selectedApps ) + $selectedApps = []; - $dockerWarningFlag = $dockerNotEnabled = (! $caSettings['dockerRunning'] && ! ($caSettings['NoInstalls'] ?? false) ) ? "true" : "false"; + $dockerWarningFlag = $dockerNotEnabled = (! $caSettings['dockerRunning'] && ! ($caSettings['NoInstalls'] ?? false) ) ? "true" : "false"; - if ( $dockerNotEnabled == "true" ) { - $unRaidVars = parse_ini_file($caPaths['unRaidVars']); - $dockerVars = parse_ini_file($caPaths['docker_cfg']); + if ( $dockerNotEnabled == "true" ) { + $unRaidVars = parse_ini_file($caPaths['unRaidVars']); + $dockerVars = parse_ini_file($caPaths['docker_cfg']); - if ( $unRaidVars['mdState'] == "STARTED" && $dockerVars['DOCKER_ENABLED'] !== "yes" ) - $dockerNotEnabled = 1; // Array started, docker not enabled - if ( $unRaidVars['mdState'] == "STARTED" && $dockerVars['DOCKER_ENABLED'] == "yes" ) - $dockerNotEnabled = 2; // Docker failed to start - if ( $unRaidVars['mdState'] !== "STARTED" ) - $dockerNotEnabled = 3; // Array not started - } - $displayHeader = ""; + if ( $unRaidVars['mdState'] == "STARTED" && $dockerVars['DOCKER_ENABLED'] !== "yes" ) + $dockerNotEnabled = 1; // Array started, docker not enabled + if ( $unRaidVars['mdState'] == "STARTED" && $dockerVars['DOCKER_ENABLED'] == "yes" ) + $dockerNotEnabled = 2; // Docker failed to start + if ( $unRaidVars['mdState'] !== "STARTED" ) + $dockerNotEnabled = 3; // Array not started + } + $displayHeader = ""; - $pinnedApps = readJsonFile($caPaths['pinnedV2']); + $pinnedApps = readJsonFile($caPaths['pinnedV2']); - $selectedApps['docker'] = $selectedApps['docker'] ?? []; - $selectedApps['plugin'] = $selectedApps['plugin'] ?? []; - $checkedOffApps = arrayEntriesToObject(@array_merge(@array_values($selectedApps['docker']),@array_values($selectedApps['plugin']))); + $selectedApps['docker'] = $selectedApps['docker'] ?? []; + $selectedApps['plugin'] = $selectedApps['plugin'] ?? []; + $checkedOffApps = arrayEntriesToObject(@array_merge(@array_values($selectedApps['docker']),@array_values($selectedApps['plugin']))); - $columnNumber = 0; - $appCount = 0; - $startingApp = ($pageNumber -1) * $caSettings['maxPerPage'] + 1; - $startingAppCounter = 0; + $columnNumber = 0; + $appCount = 0; + $startingApp = ($pageNumber -1) * $caSettings['maxPerPage'] + 1; + $startingAppCounter = 0; - $displayedTemplates = []; - foreach ($file as $template) { - $startingAppCounter++; - if ( $startingAppCounter < $startingApp ) continue; - $displayedTemplates[] = $template; - } + $displayedTemplates = []; + foreach ($file as $template) { + $startingAppCounter++; + if ( $startingAppCounter < $startingApp ) continue; + $displayedTemplates[] = $template; + } - # Create entries for skins. - foreach ($displayedTemplates as $template) { - if ( ! $template['RepositoryTemplate'] ) { - if ( ! $template['Blacklist'] ) { - if ( isset($extraBlacklist[$template['Repository']]) ) { - $template['Blacklist'] = true; - $template['ModeratorComment'] = $extraBlacklist[$template['Repository']]; - } - } - if ( ! $template['Deprecated'] && isset($extraDeprecated[$template['Repository']]) ) { - $template['Deprecated'] = true; - $template['ModeratorComment'] = $extraDeprecated[$template['Repository']]; - } - } - $template['Icon'] = $template["Icon-{$caSettings['dynamixTheme']}"] ?? $template['Icon']; + # Create entries for skins. + foreach ($displayedTemplates as $template) { + if ( ! $template['RepositoryTemplate'] ) { + if ( ! $template['Blacklist'] ) { + if ( isset($extraBlacklist[$template['Repository']]) ) { + $template['Blacklist'] = true; + $template['ModeratorComment'] = $extraBlacklist[$template['Repository']]; + } + } + if ( ! $template['Deprecated'] && isset($extraDeprecated[$template['Repository']]) ) { + $template['Deprecated'] = true; + $template['ModeratorComment'] = $extraDeprecated[$template['Repository']]; + } + } + $template['Icon'] = $template["Icon-{$caSettings['dynamixTheme']}"] ?? $template['Icon']; - if ( $template['RepositoryTemplate'] ) { - $template['Icon'] = $template['icon'] ?? "/plugins/dynamix.docker.manager/images/question.png"; + if ( $template['RepositoryTemplate'] ) { + $template['Icon'] = $template['icon'] ?? "/plugins/dynamix.docker.manager/images/question.png"; - if ( ! isset($template['bio']) ) - $template['CardDescription'] = tr("No description present"); - else { - $template['bio'] = strip_tags(markdown($template['bio'])); - $template['Description'] = $template['bio']; - } - $template['display_dockerName'] = $template['RepoName']; + if ( ! isset($template['bio']) ) + $template['CardDescription'] = tr("No description present"); + else { + $template['bio'] = strip_tags(markdown($template['bio'])); + $template['Description'] = $template['bio']; + } + $template['display_dockerName'] = $template['RepoName']; - $favClass = ( $caSettings['favourite'] && ($caSettings['favourite'] == $template['RepoName']) ) ? "ca_favouriteRepo" : "ca_non_favouriteRepo"; - $template['ca_fav'] = $caSettings['favourite'] && ($caSettings['favourite'] == $template['RepoName']); - $niceRepoName = str_replace("'s Repository","",$template['RepoName']); - $niceRepoName = str_replace("' Repository","",$niceRepoName); - $niceRepoName = str_replace(" Repository","",$niceRepoName); + $favClass = ( $caSettings['favourite'] && ($caSettings['favourite'] == $template['RepoName']) ) ? "ca_favouriteRepo" : "ca_non_favouriteRepo"; + $template['ca_fav'] = $caSettings['favourite'] && ($caSettings['favourite'] == $template['RepoName']); + $niceRepoName = str_replace("'s Repository","",$template['RepoName']); + $niceRepoName = str_replace("' Repository","",$niceRepoName); + $niceRepoName = str_replace(" Repository","",$niceRepoName); - $ct .= displayCard($template); - $count++; - if ( $count == $caSettings['maxPerPage'] ) break; - } else { - $actionsContext = []; - $selected = false; - $installComment = $template['CAComment']; + $ct .= displayCard($template); + $count++; + if ( $count == $caSettings['maxPerPage'] ) break; + } else { + $actionsContext = []; + $selected = false; + $installComment = $template['CAComment']; - if ( $template['Requires'] ) { - $template['Requires'] = markdown(strip_tags(str_replace(["\r","\n"," ","'"],["","
    ","","'"],trim($template['Requires'])),"
    ")); - preg_match_all("/\/\/(.*?)\/m",$template['Requires'],$searchMatches); - if ( count($searchMatches[1]) ) { - foreach ($searchMatches[1] as $searchResult) { - $template['Requires'] = str_replace("//$searchResult\","$searchResult",$template['Requires']); - } - } - $installComment = tr("This application has additional requirements")."
    {$template['Requires']}
    $installComment"; - } + if ( $template['Requires'] ) { + $template['Requires'] = markdown(strip_tags(str_replace(["\r","\n"," ","'"],["","
    ","","'"],trim($template['Requires'])),"
    ")); + preg_match_all("/\/\/(.*?)\/m",$template['Requires'],$searchMatches); + if ( count($searchMatches[1]) ) { + foreach ($searchMatches[1] as $searchResult) { + $template['Requires'] = str_replace("//$searchResult\","$searchResult",$template['Requires']); + } + } + $installComment = tr("This application has additional requirements")."
    {$template['Requires']}
    $installComment"; + } - $installComment = str_replace("\n","",$installComment ?: ""); - if ( ! $template['Language'] ) { - if ( ! $template['NoInstall'] && ! ($caSettings['NoInstalls'] ?? false) ) { - if ( ! $template['Plugin'] ) { - if ( $caSettings['dockerRunning'] ) { - foreach ($info as $testDocker) { - $tmpRepo = strpos($template['Repository'],":") ? $template['Repository'] : $template['Repository'].":latest"; - $tmpRepo = strpos($tmpRepo,"/") ? $tmpRepo : "library/$tmpRepo"; - if ( ( ($tmpRepo == $testDocker['Image'] && $template['Name'] == $testDocker['Name']) || "{$tmpRepo}:latest" == $testDocker['Image']) && ($template['Name'] == $testDocker['Name']) ) { - $selected = true; - $name = $testDocker['Name']; - break; - } - } + $installComment = str_replace("\n","",$installComment ?: ""); + if ( ! $template['Language'] ) { + if ( ! $template['NoInstall'] && ! ($caSettings['NoInstalls'] ?? false) ) { + if ( ! $template['Plugin'] ) { + if ( $caSettings['dockerRunning'] ) { + foreach ($info as $testDocker) { + $tmpRepo = strpos($template['Repository'],":") ? $template['Repository'] : $template['Repository'].":latest"; + $tmpRepo = strpos($tmpRepo,"/") ? $tmpRepo : "library/$tmpRepo"; + if ( ( ($tmpRepo == $testDocker['Image'] && $template['Name'] == $testDocker['Name']) || "{$tmpRepo}:latest" == $testDocker['Image']) && ($template['Name'] == $testDocker['Name']) ) { + $selected = true; + $name = $testDocker['Name']; + break; + } + } - $template['Installed'] = $selected; - if ( $selected ) { + $template['Installed'] = $selected; + if ( $selected ) { - $ind = searchArray($info,"Name",$name); - if ( $info[$ind]['url'] && $info[$ind]['running'] ) { - $actionsContext[] = ["icon"=>"ca_fa-globe","text"=>"WebUI","action"=>"openNewWindow('{$info[$ind]['url']}','_blank');"]; - } + $ind = searchArray($info,"Name",$name); + if ( $info[$ind]['url'] && $info[$ind]['running'] ) { + $actionsContext[] = ["icon"=>"ca_fa-globe","text"=>"WebUI","action"=>"openNewWindow('{$info[$ind]['url']}','_blank');"]; + } - if ( $dockerUpdateStatus[$tmpRepo]['status'] == "false" ) { - $template['UpdateAvailable'] = true; - $actionsContext[] = ["icon"=>"ca_fa-update","text"=>tr("Update"),"action"=>"updateDocker('$name');"]; - } else { - $template['UpdateAvailable'] = false; - } - if ( $caSettings['defaultReinstall'] == "true" && ! $template['Blacklist']) { - if ( $template['ID'] !== false ) { # don't allow 2nd if there's not a "default" within CA - if ( $template['BranchID'] ?? false ) - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install second instance"),"action"=>"displayTags('{$template['ID']}',true,'".str_replace(" "," ",htmlspecialchars($installComment))."','".portsUsed($template)."');"]; - else - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install second instance"),"action"=>"popupInstallXML('".addslashes($template['Path'])."','second','".str_replace(" "," ",htmlspecialchars($installComment))."','".portsUsed($template)."');"]; - } - } - if ( is_file($info[$ind]['template']) ) - $actionsContext[] = ["icon"=>"ca_fa-edit","text"=>tr("Edit"),"action"=>"popupInstallXML('".addslashes($info[$ind]['template'])."','edit');"]; + if ( $dockerUpdateStatus[$tmpRepo]['status'] == "false" ) { + $template['UpdateAvailable'] = true; + $actionsContext[] = ["icon"=>"ca_fa-update","text"=>tr("Update"),"action"=>"updateDocker('$name');"]; + } else { + $template['UpdateAvailable'] = false; + } + if ( $caSettings['defaultReinstall'] == "true" && ! $template['Blacklist']) { + if ( $template['ID'] !== false ) { # don't allow 2nd if there's not a "default" within CA + if ( $template['BranchID'] ?? false ) + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install second instance"),"action"=>"displayTags('{$template['ID']}',true,'".str_replace(" "," ",htmlspecialchars($installComment))."','".portsUsed($template)."');"]; + else + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install second instance"),"action"=>"popupInstallXML('".addslashes($template['Path'])."','second','".str_replace(" "," ",htmlspecialchars($installComment))."','".portsUsed($template)."');"]; + } + } + if ( is_file($info[$ind]['template']) ) + $actionsContext[] = ["icon"=>"ca_fa-edit","text"=>tr("Edit"),"action"=>"popupInstallXML('".addslashes($info[$ind]['template'])."','edit');"]; - $actionsContext[] = ["divider"=>true]; - if ($info[$ind]['template']) - $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>tr("Uninstall"),"action"=>"uninstallDocker('".addslashes($info[$ind]['template'])."','{$template['Name']}');"]; - if ( $template['DonateLink'] ) { - $actionsContext[] = ["divider"=>true]; - $actionsContext[] = ["icon"=>"ca_fa-money","text"=>tr("Donate"),"action"=>"openNewWindow('".addslashes($template['DonateLink'])."','_blank');"]; - } - } elseif ( ! $template['Blacklist'] || ! $template['Compatible']) { - if ( $template['InstallPath'] ) { - $userTemplate = readXmlFile($template['InstallPath'],false,false); - if ( ! $template['Blacklist'] ) { - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Reinstall"),"action"=>"popupInstallXML('".addslashes($template['InstallPath'])."','user','','".portsUsed($userTemplate)."');"]; - $actionsContext[] = ["divider"=>true]; - } - $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>tr("Remove from Previous Apps"),"alternate"=>tr("Remove"),"action"=>"removeApp('{$template['InstallPath']}','{$template['Name']}');"]; - } else { - if ( ! ($template['BranchID'] ?? null) ) { - if ( is_file("{$caPaths['dockerManTemplates']}/my-{$template['Name']}.xml") ) { - $test = readXmlFile("{$caPaths['dockerManTemplates']}/my-{$template['Name']}.xml",true); - if ( $template['Repository'] == $test['Repository'] ) { - $userTemplate = readXmlFile($template['InstallPath'],false,false); - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>"".tr("Reinstall From Previous Apps")."","action"=>"popupInstallXML('".addslashes("{$caPaths['dockerManTemplates']}/my-{$template['Name']}").".xml','user','','".portsUsed($userTemplate)."');"]; - $actionsContext[] = ["divider"=>true]; - } - } - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"popupInstallXML('".addslashes($template['Path'])."','default','".str_replace(" "," ",htmlspecialchars($installComment))."','".portsUsed($template)."');"]; - } else { - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"displayTags('{$template['ID']}',false,'".str_replace(" "," ",htmlspecialchars($installComment))."','".portsUsed($template)."');"]; - } - } - } - } - } else { - $pluginName = basename($template['PluginURL']); - $template['Installed'] = file_exists("/var/log/plugins/$pluginName"); - if ( $template['Installed'] ) { - $pluginInstalledVersion = plugin("version","/var/log/plugins/$pluginName"); - if ( file_exists("/tmp/plugins/$pluginName") ) { - $tmpPluginVersion = plugin("version","/tmp/plugins/$pluginName"); - if (strcmp($template['pluginVersion'],$tmpPluginVersion) < 0) - $template['pluginVersion'] = $tmpPluginVersion; - } - $template['pluginVersion'] = plugin("version","/tmp/plugins/$pluginName"); + $actionsContext[] = ["divider"=>true]; + if ($info[$ind]['template']) + $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>tr("Uninstall"),"action"=>"uninstallDocker('".addslashes($info[$ind]['template'])."','{$template['Name']}');"]; + if ( $template['DonateLink'] ) { + $actionsContext[] = ["divider"=>true]; + $actionsContext[] = ["icon"=>"ca_fa-money","text"=>tr("Donate"),"action"=>"openNewWindow('".addslashes($template['DonateLink'])."','_blank');"]; + } + } elseif ( ! $template['Blacklist'] || ! $template['Compatible']) { + if ( $template['InstallPath'] ) { + $userTemplate = readXmlFile($template['InstallPath'],false,false); + if ( ! $template['Blacklist'] ) { + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Reinstall"),"action"=>"popupInstallXML('".addslashes($template['InstallPath'])."','user','','".portsUsed($userTemplate)."');"]; + $actionsContext[] = ["divider"=>true]; + } + $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>tr("Remove from Previous Apps"),"alternate"=>tr("Remove"),"action"=>"removeApp('{$template['InstallPath']}','{$template['Name']}');"]; + } else { + if ( ! ($template['BranchID'] ?? null) ) { + if ( is_file("{$caPaths['dockerManTemplates']}/my-{$template['Name']}.xml") ) { + $test = readXmlFile("{$caPaths['dockerManTemplates']}/my-{$template['Name']}.xml",true); + if ( $template['Repository'] == $test['Repository'] ) { + $userTemplate = readXmlFile($template['InstallPath'],false,false); + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>"".tr("Reinstall From Previous Apps")."","action"=>"popupInstallXML('".addslashes("{$caPaths['dockerManTemplates']}/my-{$template['Name']}").".xml','user','','".portsUsed($userTemplate)."');"]; + $actionsContext[] = ["divider"=>true]; + } + } + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"popupInstallXML('".addslashes($template['Path'])."','default','".str_replace(" "," ",htmlspecialchars($installComment))."','".portsUsed($template)."');"]; + } else { + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"displayTags('{$template['ID']}',false,'".str_replace(" "," ",htmlspecialchars($installComment))."','".portsUsed($template)."');"]; + } + } + } + } + } else { + $pluginName = basename($template['PluginURL']); + $template['Installed'] = file_exists("/var/log/plugins/$pluginName"); + if ( $template['Installed'] ) { + $pluginInstalledVersion = plugin("version","/var/log/plugins/$pluginName"); + if ( file_exists("/tmp/plugins/$pluginName") ) { + $tmpPluginVersion = plugin("version","/tmp/plugins/$pluginName"); + if (strcmp($template['pluginVersion'],$tmpPluginVersion) < 0) + $template['pluginVersion'] = $tmpPluginVersion; + } + $template['pluginVersion'] = plugin("version","/tmp/plugins/$pluginName"); - if ( ( strcmp($pluginInstalledVersion,$template['pluginVersion']) < 0 || $template['UpdateAvailable']) && $template['Name'] !== "Community Applications" && ( ! ($template['UninstallOnly'] ?? false) ) ) { - @copy($caPaths['pluginTempDownload'],"/tmp/plugins/$pluginName"); - $template['UpdateAvailable'] = true; - $actionsContext[] = ["icon"=>"ca_fa-update","text"=>tr("Update"),"action"=>"installPlugin('$pluginName',true,'','{$template['RequiresFile']}');"]; - } else { - if ( ! $template['UpdateAvailable'] ) # this handles if the feed hasn't caught up to the update yet - $template['UpdateAvailable'] = false; - } - $pluginSettings = ($pluginName == "community.applications.plg") ? "ca_settings" : plugin("launch","/var/log/plugins/$pluginName"); - if ( $pluginSettings ) { - $actionsContext[] = ["icon"=>"ca_fa-pluginSettings","text"=>tr("Settings"),"action"=>"openNewWindow('/Apps/$pluginSettings');"]; - } + if ( ( strcmp($pluginInstalledVersion,$template['pluginVersion']) < 0 || $template['UpdateAvailable']) && $template['Name'] !== "Community Applications" && ( ! ($template['UninstallOnly'] ?? false) ) ) { + @copy($caPaths['pluginTempDownload'],"/tmp/plugins/$pluginName"); + $template['UpdateAvailable'] = true; + $actionsContext[] = ["icon"=>"ca_fa-update","text"=>tr("Update"),"action"=>"installPlugin('$pluginName',true,'','{$template['RequiresFile']}');"]; + } else { + if ( ! $template['UpdateAvailable'] ) # this handles if the feed hasn't caught up to the update yet + $template['UpdateAvailable'] = false; + } + $pluginSettings = ($pluginName == "community.applications.plg") ? "ca_settings" : plugin("launch","/var/log/plugins/$pluginName"); + if ( $pluginSettings ) { + $actionsContext[] = ["icon"=>"ca_fa-pluginSettings","text"=>tr("Settings"),"action"=>"openNewWindow('/Apps/$pluginSettings');"]; + } - if ( $pluginName != "community.applications.plg" ) { - if ( ! empty($actionsContext) ) - $actionsContext[] = ["divider"=>true]; + if ( $pluginName != "community.applications.plg" ) { + if ( ! empty($actionsContext) ) + $actionsContext[] = ["divider"=>true]; - $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>tr("Uninstall"),"action"=>"uninstallApp('/var/log/plugins/$pluginName','".str_replace(" "," ",$template['Name'])."');"]; - } - if ( $template['DonateLink'] ) { - $actionsContext[] = ["divider"=>true]; - $actionsContext[] = ["icon"=>"ca_fa-money","text"=>tr("Donate"),"action"=>"openNewWindow('".addslashes($template['DonateLink'])."','_blank');"]; - } - } elseif ( ! $template['Blacklist'] || ! $template['Compatible'] ) { - $buttonTitle = $template['InstallPath'] ? tr("Reinstall") : tr("Install"); - if ( ! $template['InstallPath'] ) { - $installComment = $template['CAComment']; - if ( ! $installComment && $template['Requires'] ){ - // Remove the flags to indicate a search taking place - preg_match_all("/\/\/(.*?)\\\\/m",$template['Requires'],$searchMatches); - if ( count($searchMatches[1]) ) { - foreach ($searchMatches[1] as $searchResult) { - $template['Requires'] = str_replace("//$searchResult\\\\",$searchResult,$template['Requires']); - } - } - $installComment = tr("This application has additional requirements")."
    ".markdown($template['Requires']); - } - } - $isDeprecated = $template['Deprecated'] ? "&deprecated" : ""; - $isDeprecated = $template['Compatible'] ? "&incompatible" : ""; + $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>tr("Uninstall"),"action"=>"uninstallApp('/var/log/plugins/$pluginName','".str_replace(" "," ",$template['Name'])."');"]; + } + if ( $template['DonateLink'] ) { + $actionsContext[] = ["divider"=>true]; + $actionsContext[] = ["icon"=>"ca_fa-money","text"=>tr("Donate"),"action"=>"openNewWindow('".addslashes($template['DonateLink'])."','_blank');"]; + } + } elseif ( ! $template['Blacklist'] || ! $template['Compatible'] ) { + $buttonTitle = $template['InstallPath'] ? tr("Reinstall") : tr("Install"); + if ( ! $template['InstallPath'] ) { + $installComment = $template['CAComment']; + if ( ! $installComment && $template['Requires'] ){ + // Remove the flags to indicate a search taking place + preg_match_all("/\/\/(.*?)\\\\/m",$template['Requires'],$searchMatches); + if ( count($searchMatches[1]) ) { + foreach ($searchMatches[1] as $searchResult) { + $template['Requires'] = str_replace("//$searchResult\\\\",$searchResult,$template['Requires']); + } + } + $installComment = tr("This application has additional requirements")."
    ".markdown($template['Requires']); + } + } + $isDeprecated = $template['Deprecated'] ? "&deprecated" : ""; + $isDeprecated = $template['Compatible'] ? "&incompatible" : ""; - $updateFlag = false; - $requiresText = ""; - if ( $template['RequiresFile'] && ! is_file($template['RequiresFile']) ) { - $requiresText = "AnythingHere"; - $updateFlag = true; // This forces the system to double check the requirements and abort the install - } else { - $installComment = $template['RequiresFile'] ? "" : $installComment; - } - if ( ! ($template['UninstallOnly'] ?? false) ) { - if ( $template['Compatible'] ) - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>$buttonTitle,"action"=>"installPlugin('{$template['PluginURL']}$isDeprecated','$updateFlag','".str_replace([" ","\n"],[" ",""],htmlspecialchars($installComment ?? ""))."','$requiresText');"]; - } - if ( $template['InstallPath'] ) { - if ( ! empty($actionsContext) ) - $actionsContext[] = ["divider"=>true]; - $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>tr("Remove from Previous Apps"),"action"=>"removeApp('{$template['InstallPath']}','$pluginName');"]; - } - } - if ( file_exists($caPaths['pluginPending'].$pluginName) ) { - unset($actionsContext); - $actionsContext[] = ["text"=>tr("Pending")]; - } - } - } - } - if ( $template['Language'] ) { - $countryCode = $template['LanguageDefault'] ? "en_US" : $template['LanguagePack']; - $dynamixSettings = @parse_ini_file($caPaths['dynamixSettings'],true); - $currentLanguage = $dynamixSettings['display']['locale'] ?? "en_US"; - $installedLanguages = array_diff(scandir("/usr/local/emhttp/languages"),[".",".."]); - $installedLanguages = array_filter($installedLanguages,function($v) { - return is_dir("/usr/local/emhttp/languages/$v"); - }); - $installedLanguages[] = "en_US"; - $currentLanguage = (is_dir("/usr/local/emhttp/languages/$currentLanguage") ) ? $currentLanguage : "en_US"; - if ( in_array($countryCode,$installedLanguages) ) { - if ( $currentLanguage != $countryCode ) { - $actionsContext[] = ["icon"=>"ca_fa-switchto","text"=>$template['SwitchLanguage'],"action"=>"CAswitchLanguage('$countryCode');"]; - } - } else { - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"installLanguage('{$template['TemplateURL']}','$countryCode');"]; - } - if ( file_exists("/var/log/plugins/lang-$countryCode.xml") ) { - $template['Installed'] = true; - if ( languageCheck($template) ) { - $template['UpdateAvailable'] = true; - $actionsContext[] = ["icon"=>"ca_fa-update","text"=>$template['UpdateLanguage'],"action"=>"updateLanguage('$countryCode');"]; - } - if ( $currentLanguage != $countryCode ) { - if ( ! empty($actionsContext) ) - $actionsContext[] = ["divider"=>true]; - $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>tr("Remove Language Pack"),"action"=>"removeLanguage('$countryCode');"]; - } - } - if ( file_exists($caPaths['pluginPending'].$template['LanguagePack']) || file_exists("{$caPaths['pluginPending']}lang-{$template['LanguagePack']}.xml") ) { - unset($actionsContext); - $actionsContext[] = ["text"=>tr("Pending")]; - } - } + $updateFlag = false; + $requiresText = ""; + if ( $template['RequiresFile'] && ! is_file($template['RequiresFile']) ) { + $requiresText = "AnythingHere"; + $updateFlag = true; // This forces the system to double check the requirements and abort the install + } else { + $installComment = $template['RequiresFile'] ? "" : $installComment; + } + if ( ! ($template['UninstallOnly'] ?? false) ) { + if ( $template['Compatible'] ) + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>$buttonTitle,"action"=>"installPlugin('{$template['PluginURL']}$isDeprecated','$updateFlag','".str_replace([" ","\n"],[" ",""],htmlspecialchars($installComment ?? ""))."','$requiresText');"]; + } + if ( $template['InstallPath'] ) { + if ( ! empty($actionsContext) ) + $actionsContext[] = ["divider"=>true]; + $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>tr("Remove from Previous Apps"),"action"=>"removeApp('{$template['InstallPath']}','$pluginName');"]; + } + } + if ( file_exists($caPaths['pluginPending'].$pluginName) ) { + unset($actionsContext); + $actionsContext[] = ["text"=>tr("Pending")]; + } + } + } + } + if ( $template['Language'] ) { + $countryCode = $template['LanguageDefault'] ? "en_US" : $template['LanguagePack']; + $dynamixSettings = @parse_ini_file($caPaths['dynamixSettings'],true); + $currentLanguage = $dynamixSettings['display']['locale'] ?? "en_US"; + $installedLanguages = array_diff(scandir("/usr/local/emhttp/languages"),[".",".."]); + $installedLanguages = array_filter($installedLanguages,function($v) { + return is_dir("/usr/local/emhttp/languages/$v"); + }); + $installedLanguages[] = "en_US"; + $currentLanguage = (is_dir("/usr/local/emhttp/languages/$currentLanguage") ) ? $currentLanguage : "en_US"; + if ( in_array($countryCode,$installedLanguages) ) { + if ( $currentLanguage != $countryCode ) { + $actionsContext[] = ["icon"=>"ca_fa-switchto","text"=>$template['SwitchLanguage'],"action"=>"CAswitchLanguage('$countryCode');"]; + } + } else { + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"installLanguage('{$template['TemplateURL']}','$countryCode');"]; + } + if ( file_exists("/var/log/plugins/lang-$countryCode.xml") ) { + $template['Installed'] = true; + if ( languageCheck($template) ) { + $template['UpdateAvailable'] = true; + $actionsContext[] = ["icon"=>"ca_fa-update","text"=>$template['UpdateLanguage'],"action"=>"updateLanguage('$countryCode');"]; + } + if ( $currentLanguage != $countryCode ) { + if ( ! empty($actionsContext) ) + $actionsContext[] = ["divider"=>true]; + $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>tr("Remove Language Pack"),"action"=>"removeLanguage('$countryCode');"]; + } + } + if ( file_exists($caPaths['pluginPending'].$template['LanguagePack']) || file_exists("{$caPaths['pluginPending']}lang-{$template['LanguagePack']}.xml") ) { + unset($actionsContext); + $actionsContext[] = ["text"=>tr("Pending")]; + } + } - $template['actionsContext'] = $actionsContext; + $template['actionsContext'] = $actionsContext; - $template['ca_fav'] = $caSettings['favourite'] && ($caSettings['favourite'] == $template['RepoName']); - if ( strpos($template['Repository'],"/") === false ) - $template['Pinned'] = $pinnedApps["library/{$template['Repository']}&{$template['SortName']}"] ?? false; - else - $template['Pinned'] = $pinnedApps["{$template['Repository']}&{$template['SortName']}"] ?? false; - if ( isset($template['Repo']) ) { - $template['Twitter'] = $template['Twitter'] ?? ($repositories[$template['Repo']]['Twitter'] ?? null); - $template['Reddit'] = $template['Reddit'] ?? ($repositories[$template['Repo']]['Reddit'] ?? null); - $template['Facebook'] = $template['Facebook'] ?? ($repositories[$template['Repo']]['Facebook'] ?? null); - $template['Discord'] = $template['Discord'] ?? ($repositories[$template['RepoName']]['Discord'] ?? null); - } else { - $template['Twitter'] = $template['Twitter'] ?? null; - $template['Reddit'] = $template['Reddit'] ?? null; - $template['Facebook'] = $template['Facebook'] ?? null; - $template['Discord'] = $template['Discord'] ?? null; - } + $template['ca_fav'] = $caSettings['favourite'] && ($caSettings['favourite'] == $template['RepoName']); + if ( strpos($template['Repository'],"/") === false ) + $template['Pinned'] = $pinnedApps["library/{$template['Repository']}&{$template['SortName']}"] ?? false; + else + $template['Pinned'] = $pinnedApps["{$template['Repository']}&{$template['SortName']}"] ?? false; + if ( isset($template['Repo']) ) { + $template['Twitter'] = $template['Twitter'] ?? ($repositories[$template['Repo']]['Twitter'] ?? null); + $template['Reddit'] = $template['Reddit'] ?? ($repositories[$template['Repo']]['Reddit'] ?? null); + $template['Facebook'] = $template['Facebook'] ?? ($repositories[$template['Repo']]['Facebook'] ?? null); + $template['Discord'] = $template['Discord'] ?? ($repositories[$template['RepoName']]['Discord'] ?? null); + } else { + $template['Twitter'] = $template['Twitter'] ?? null; + $template['Reddit'] = $template['Reddit'] ?? null; + $template['Facebook'] = $template['Facebook'] ?? null; + $template['Discord'] = $template['Discord'] ?? null; + } - $previousAppName = $template['Plugin'] ? $template['PluginURL'] : $template['Name']; - if ( isset($checkedOffApps[$previousAppName]) ) - $template['checked'] = $checkedOffApps[$previousAppName] ? "checked" : ""; + $previousAppName = $template['Plugin'] ? $template['PluginURL'] : $template['Name']; + if ( isset($checkedOffApps[$previousAppName]) ) + $template['checked'] = $checkedOffApps[$previousAppName] ? "checked" : ""; - if ( ! $template['Plugin'] ) { - $tmpRepo = $template['Repository']; - if ( ! strpos($tmpRepo,"/") ) { - $tmpRepo = "library/$tmpRepo"; - } - foreach ($info as $testDocker) { - if ( ($tmpRepo == $testDocker['Image'] || "$tmpRepo:latest" == $testDocker['Image']) && ($template['Name'] == $testDocker['Name']) ) { - $template['Installed'] = true; + if ( ! $template['Plugin'] ) { + $tmpRepo = $template['Repository']; + if ( ! strpos($tmpRepo,"/") ) { + $tmpRepo = "library/$tmpRepo"; + } + foreach ($info as $testDocker) { + if ( ($tmpRepo == $testDocker['Image'] || "$tmpRepo:latest" == $testDocker['Image']) && ($template['Name'] == $testDocker['Name']) ) { + $template['Installed'] = true; - break; - } - } - } else { - $pluginName = basename($template['PluginURL']); - $template['Installed'] = checkInstalledPlugin($template) ; + break; + } + } + } else { + $pluginName = basename($template['PluginURL']); + $template['Installed'] = checkInstalledPlugin($template) ; - } + } - if ( $template['Language'] ) { - $template['Installed'] = is_dir("{$caPaths['languageInstalled']}{$template['LanguagePack']}") && ! $template['Uninstall']; - } + if ( $template['Language'] ) { + $template['Installed'] = is_dir("{$caPaths['languageInstalled']}{$template['LanguagePack']}") && ! $template['Uninstall']; + } - if ( startsWith($template['Repository'],"library/") || startsWith($template['Repository'],"registry.hub.docker.com/library/") || strpos($template['Repository'],"/") === false) - $template['Official'] = true; + if ( startsWith($template['Repository'],"library/") || startsWith($template['Repository'],"registry.hub.docker.com/library/") || strpos($template['Repository'],"/") === false) + $template['Official'] = true; - # Entries created. Now display it - $ct .= displayCard($template); - $count++; - if ( $count == $caSettings['maxPerPage'] ) break; - } - } + # Entries created. Now display it + $ct .= displayCard($template); + $count++; + if ( $count == $caSettings['maxPerPage'] ) break; + } + } - $ct .= getPageNavigation($pageNumber,count($file),false,true); + $ct .= getPageNavigation($pageNumber,count($file),false,true); - if ( ! $count ) - $displayHeader .= "
    ".tr("No Matching Applications Found")."
    "; + if ( ! $count ) + $displayHeader .= "
    ".tr("No Matching Applications Found")."
    "; - if ( $count == 1 && ! isset($template['homeScreen']) ) { - if ( $template['RepositoryTemplate'] ) { - $displayHeader .= ""; - } else { - if ($template['InstallPath']) - $template['Path'] = $template['InstallPath']; + if ( $count == 1 && ! isset($template['homeScreen']) ) { + if ( $template['RepositoryTemplate'] ) { + $displayHeader .= ""; + } else { + if ($template['InstallPath']) + $template['Path'] = $template['InstallPath']; - $displayHeader .= ""; - } - } - // Handle MaxPerPage changing on a different tab - $displayHeader .= ""; + $displayHeader .= ""; + } + } + // Handle MaxPerPage changing on a different tab + $displayHeader .= ""; - return "$displayHeader$ct"; + return "$displayHeader$ct"; } function getPageNavigation($pageNumber,$totalApps,$dockerSearch,$displayCount = true) { - global $caSettings; + global $caSettings; - $pageFunction = $dockerSearch ? "dockerSearch": "changePage"; - if ( $dockerSearch ) - $caSettings['maxPerPage'] = 25; + $pageFunction = $dockerSearch ? "dockerSearch": "changePage"; + if ( $dockerSearch ) + $caSettings['maxPerPage'] = 25; - if ( $caSettings['maxPerPage'] < 0 ) return; - $swipeScript = ""; + if ($totalPages <= 1) return ""; - $startApp = ($pageNumber - 1) * $caSettings['maxPerPage'] + 1; - $endApp = $pageNumber * $caSettings['maxPerPage']; - if ( $endApp > $totalApps ) - $endApp = $totalApps; + $startApp = ($pageNumber - 1) * $caSettings['maxPerPage'] + 1; + $endApp = $pageNumber * $caSettings['maxPerPage']; + if ( $endApp > $totalApps ) + $endApp = $totalApps; - $o = "
    "; - if ($displayCount) - $o .= "".sprintf(tr("Displaying %s - %s (of %s)"),$startApp,$endApp,$totalApps)."
    "; + $o = "
    "; + if ($displayCount) + $o .= "".sprintf(tr("Displaying %s - %s (of %s)"),$startApp,$endApp,$totalApps)."
    "; - $o .= ""; - return $o.$swipeScript; + if ( ($totalPages - $pageNumber ) >5 ) + $o .= "$totalPages"; + } + $nextPage = $pageNumber + 1; + $o .= ( $pageNumber < $totalPages ) ? "" : ""; + $swipeScript .= ( $pageNumber < $totalPages ) ? "data.nextpage = $nextPage;" : "data.nextpage = 0;"; + $swipeScript .= ""; + $o .= "
    "; + return $o.$swipeScript; } @@ -455,1219 +455,1219 @@ function getPageNavigation($pageNumber,$totalApps,$dockerSearch,$displayCount = # Generate the display for the popup # ###################################### function getPopupDescriptionSkin($appNumber) { - global $caSettings, $caPaths, $language, $DockerTemplates, $DockerClient; + global $caSettings, $caPaths, $language, $DockerTemplates, $DockerClient; - $unRaidVars = parse_ini_file($caPaths['unRaidVars']); - $dockerVars = parse_ini_file($caPaths['docker_cfg']); - $csrf_token = $unRaidVars['csrf_token']; - $tabMode = '_parent'; + $unRaidVars = parse_ini_file($caPaths['unRaidVars']); + $dockerVars = parse_ini_file($caPaths['docker_cfg']); + $csrf_token = $unRaidVars['csrf_token']; + $tabMode = '_parent'; - $allRepositories = readJsonFile($caPaths['repositoryList']); - $extraBlacklist = readJsonFile($caPaths['extraBlacklist']); - $extraDeprecated = readJsonFile($caPaths['extraDeprecated']); - $templateDescription = ""; - $selected = null; + $allRepositories = readJsonFile($caPaths['repositoryList']); + $extraBlacklist = readJsonFile($caPaths['extraBlacklist']); + $extraDeprecated = readJsonFile($caPaths['extraDeprecated']); + $templateDescription = ""; + $selected = null; - $pinnedApps = readJsonFile($caPaths['pinnedV2']); - $info = []; + $pinnedApps = readJsonFile($caPaths['pinnedV2']); + $info = []; - if ( is_file("/var/run/dockerd.pid") && is_dir("/proc/".@file_get_contents("/var/run/dockerd.pid")) ) { - $caSettings['dockerRunning'] = "true"; - $infoTmp = getAllInfo(); - foreach ($infoTmp as $container) { - $info[$container['Name']] = $container; - } - $dockerRunning = $DockerClient->getDockerContainers(); - $dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']); - } else { - $caSettings['dockerRunning'] = false; - $dockerRunning = []; - $dockerUpdateStatus = []; - } - if ( ! is_file($caPaths['warningAccepted']) ) - $caSettings['NoInstalls'] = true; + if ( is_file("/var/run/dockerd.pid") && is_dir("/proc/".@file_get_contents("/var/run/dockerd.pid")) ) { + $caSettings['dockerRunning'] = "true"; + $infoTmp = getAllInfo(); + foreach ($infoTmp as $container) { + $info[$container['Name']] = $container; + } + $dockerRunning = $DockerClient->getDockerContainers(); + $dockerUpdateStatus = readJsonFile($caPaths['dockerUpdateStatus']); + } else { + $caSettings['dockerRunning'] = false; + $dockerRunning = []; + $dockerUpdateStatus = []; + } + if ( ! is_file($caPaths['warningAccepted']) ) + $caSettings['NoInstalls'] = true; - # $appNumber is actually the path to the template. It's pretty much always going to be the same even if the database is out of sync. - if ( is_file($caPaths['community-templates-allSearchResults']) ) - $displayed = readJsonFile($caPaths['community-templates-allSearchResults']); - else - $displayed = readJsonFile($caPaths['community-templates-displayed']); + # $appNumber is actually the path to the template. It's pretty much always going to be the same even if the database is out of sync. + if ( is_file($caPaths['community-templates-allSearchResults']) ) + $displayed = readJsonFile($caPaths['community-templates-allSearchResults']); + else + $displayed = readJsonFile($caPaths['community-templates-displayed']); - $index = searchArray($displayed['community'],"InstallPath",$appNumber); - if ( $index === false ) { - $ind = $index; - while ( true ) { - if ( $ind !== false ) { - if ( isset($displayed[$ind]) ) { - $template = $displayed[$ind]; - if ( $template['Name'] == ($displayed['community'][$ind]['Name'] ?? "") ) { - $index = $ind; - break; - } - } - } - $ind = searchArray($displayed['community'],"Path",$appNumber,$ind+1); - if ( $ind === false ) { - unset($template); - break; - } - } - } + $index = searchArray($displayed['community'],"InstallPath",$appNumber); + if ( $index === false ) { + $ind = $index; + while ( true ) { + if ( $ind !== false ) { + if ( isset($displayed[$ind]) ) { + $template = $displayed[$ind]; + if ( $template['Name'] == ($displayed['community'][$ind]['Name'] ?? "") ) { + $index = $ind; + break; + } + } + } + $ind = searchArray($displayed['community'],"Path",$appNumber,$ind+1); + if ( $ind === false ) { + unset($template); + break; + } + } + } - if ( $index !== false ) { - $template = $displayed['community'][$index]; - } + if ( $index !== false ) { + $template = $displayed['community'][$index]; + } - # handle case where the app being asked to display isn't on the most recent displayed list (ie: multiple browser tabs open) - if ( ! isset($template) ) { - $file = &$GLOBALS['templates']; - $index = searchArray($file,"Path",$appNumber); - if ( $index === false ) { - echo json_encode(["description"=>tr("Something really wrong happened. Reloading the Apps tab will probably fix the problem")]); - return; - } - $template = $file[$index]; - } + # handle case where the app being asked to display isn't on the most recent displayed list (ie: multiple browser tabs open) + if ( ! isset($template) ) { + $file = &$GLOBALS['templates']; + $index = searchArray($file,"Path",$appNumber); + if ( $index === false ) { + echo json_encode(["description"=>tr("Something really wrong happened. Reloading the Apps tab will probably fix the problem")]); + return; + } + $template = $file[$index]; + } - if ( ! $template['Blacklist'] ) { - if ( isset($extraBlacklist[$template['Repository']]) ) { - $template['Blacklist'] = true; - $template['ModeratorComment'] = $extraBlacklist[$template['Repository']]; - } - } - if ( ! $template['Deprecated'] && isset($extraDeprecated[$template['Repository']]) ) { - $template['Deprecated'] = true; - $template['ModeratorComment'] = isset($extraDeprecated[$template['Repository']]); - } + if ( ! $template['Blacklist'] ) { + if ( isset($extraBlacklist[$template['Repository']]) ) { + $template['Blacklist'] = true; + $template['ModeratorComment'] = $extraBlacklist[$template['Repository']]; + } + } + if ( ! $template['Deprecated'] && isset($extraDeprecated[$template['Repository']]) ) { + $template['Deprecated'] = true; + $template['ModeratorComment'] = isset($extraDeprecated[$template['Repository']]); + } - $ID = $template['ID']; + $ID = $template['ID']; - $template['Profile'] = $allRepositories[$template['RepoName']]['profile'] ?? ""; - $template['ProfileIcon'] = $allRepositories[$template['RepoName']]['icon'] ?? ""; + $template['Profile'] = $allRepositories[$template['RepoName']]['profile'] ?? ""; + $template['ProfileIcon'] = $allRepositories[$template['RepoName']]['icon'] ?? ""; - // Hack the system so that language's popups always appear in the appropriate language - if ( $template['Language'] ) { - $countryCode = $template['LanguageDefault'] ? "en_US" : $template['LanguagePack']; - if ( $countryCode !== "en_US" ) { - if ( ! is_file("{$caPaths['tempFiles']}/CA_language-$countryCode") ) { - download_url("{$caPaths['CA_languageBase']}$countryCode","{$caPaths['tempFiles']}/CA_language-$countryCode"); - } - $language = is_file("{$caPaths['tempFiles']}/CA_language-$countryCode") ? @parse_lang_file("{$caPaths['tempFiles']}/CA_language-$countryCode") : []; - } else { - $language = []; - } - } + // Hack the system so that language's popups always appear in the appropriate language + if ( $template['Language'] ) { + $countryCode = $template['LanguageDefault'] ? "en_US" : $template['LanguagePack']; + if ( $countryCode !== "en_US" ) { + if ( ! is_file("{$caPaths['tempFiles']}/CA_language-$countryCode") ) { + download_url("{$caPaths['CA_languageBase']}$countryCode","{$caPaths['tempFiles']}/CA_language-$countryCode"); + } + $language = is_file("{$caPaths['tempFiles']}/CA_language-$countryCode") ? @parse_lang_file("{$caPaths['tempFiles']}/CA_language-$countryCode") : []; + } else { + $language = []; + } + } - $donatelink = $template['DonateLink']; - if ( $donatelink ) { - $donatetext = $template['DonateText']; - } + $donatelink = $template['DonateLink']; + if ( $donatelink ) { + $donatetext = $template['DonateText']; + } - if ( ! $template['Plugin'] ) { - if ( ! strpos($template['Repository'],"/") ) { - $template['Repository'] = "library/{$template['Repository']}"; - } - foreach ($dockerRunning as $testDocker) { - if ( ($template['Repository'] == $testDocker['Image'] || "{$template['Repository']}:latest" == $testDocker['Image']) && ($template['Name'] == $testDocker['Name']) ) { - $selected = true; - $name = $testDocker['Name']; - break; - } - } - } else - $pluginName = basename($template['PluginURL']); + if ( ! $template['Plugin'] ) { + if ( ! strpos($template['Repository'],"/") ) { + $template['Repository'] = "library/{$template['Repository']}"; + } + foreach ($dockerRunning as $testDocker) { + if ( ($template['Repository'] == $testDocker['Image'] || "{$template['Repository']}:latest" == $testDocker['Image']) && ($template['Name'] == $testDocker['Name']) ) { + $selected = true; + $name = $testDocker['Name']; + break; + } + } + } else + $pluginName = basename($template['PluginURL']); - if ( $template['trending'] ) { - $allApps = &$GLOBALS['templates']; + if ( $template['trending'] ) { + $allApps = &$GLOBALS['templates']; - $allTrends = array_unique(array_column($allApps,"trending")); - rsort($allTrends); - $trendRank = array_search($template['trending'],$allTrends) + 1; - } - $template['Category'] = categoryList($template['Category'],true); - $template['Icon'] = $template['Icon'] ? $template['Icon'] : "/plugins/dynamix.docker.manager/images/question.png"; - if ( $template['Overview'] ) - $ovr = $template['OriginalOverview'] ?: $template['Overview']; - if ( ! isset($ovr) ) - $ovr = $template['OriginalDescription'] ?: $template['Description']; - $ovr = html_entity_decode($ovr); - $ovr = str_replace(["[","]"],["<",">"],$ovr); - $ovr = str_replace("\n","
    ",$ovr); - $ovr = str_replace(" ","    ",$ovr); - $ovr = markdown(strip_tags($ovr,"
    ")); - $template['display_ovr'] = $ovr; + $allTrends = array_unique(array_column($allApps,"trending")); + rsort($allTrends); + $trendRank = array_search($template['trending'],$allTrends) + 1; + } + $template['Category'] = categoryList($template['Category'],true); + $template['Icon'] = $template['Icon'] ? $template['Icon'] : "/plugins/dynamix.docker.manager/images/question.png"; + if ( $template['Overview'] ) + $ovr = $template['OriginalOverview'] ?: $template['Overview']; + if ( ! isset($ovr) ) + $ovr = $template['OriginalDescription'] ?: $template['Description']; + $ovr = html_entity_decode($ovr); + $ovr = str_replace(["[","]"],["<",">"],$ovr); + $ovr = str_replace("\n","
    ",$ovr); + $ovr = str_replace(" ","    ",$ovr); + $ovr = markdown(strip_tags($ovr,"
    ")); + $template['display_ovr'] = $ovr; - if ( $template['Plugin'] ) { - $templateURL = $template['PluginURL']; - download_url($templateURL,$caPaths['pluginTempDownload'],"",5); - $template['Changes'] = @plugin("changes",$caPaths['pluginTempDownload']) ?: $template['Changes']; + if ( $template['Plugin'] ) { + $templateURL = $template['PluginURL']; + download_url($templateURL,$caPaths['pluginTempDownload'],"",5); + $template['Changes'] = @plugin("changes",$caPaths['pluginTempDownload']) ?: $template['Changes']; - $template['pluginVersion'] = @plugin("version",$caPaths['pluginTempDownload']) ?: $template['pluginVersion']; + $template['pluginVersion'] = @plugin("version",$caPaths['pluginTempDownload']) ?: $template['pluginVersion']; - } else { - if ( ! $template['Changes'] && $template['ChangeLogPresent']) { - $templateURL = $template['caTemplateURL'] ?: $template['TemplateURL']; - download_url($templateURL,$caPaths['pluginTempDownload'],"",5); - $xml = readXmlFile($caPaths['pluginTempDownload']); - $template['Changes'] = $xml['Changes']; - } - } - $template['Changes'] = str_replace(" ","    ",$template['Changes'] ?: ""); // Prevent inadvertent code blocks - $template['Changes'] = Markdown(strip_tags(str_replace(["[","]"],["<",">"],$template['Changes'] ?: ""),"
    ")); - if ( trim($template['Changes']) ) - $template['display_changes'] = trim($template['Changes']); + } else { + if ( ! $template['Changes'] && $template['ChangeLogPresent']) { + $templateURL = $template['caTemplateURL'] ?: $template['TemplateURL']; + download_url($templateURL,$caPaths['pluginTempDownload'],"",5); + $xml = readXmlFile($caPaths['pluginTempDownload']); + $template['Changes'] = $xml['Changes']; + } + } + $template['Changes'] = str_replace(" ","    ",$template['Changes'] ?: ""); // Prevent inadvertent code blocks + $template['Changes'] = Markdown(strip_tags(str_replace(["[","]"],["<",">"],$template['Changes'] ?: ""),"
    ")); + if ( trim($template['Changes']) ) + $template['display_changes'] = trim($template['Changes']); - if ( $template['IconFA'] ) { - $template['IconFA'] = $template['IconFA'] ?: $template['Icon']; - $templateIcon = startsWith($template['IconFA'],"icon-") ? "{$template['IconFA']} unraidIcon" : "fa fa-{$template['IconFA']}"; - $template['display_icon'] = ""; - } else { - $template['Icon'] = $template["Icon-{$caSettings['dynamixTheme']}"] ?? $template['Icon']; - $template['display_icon'] = "Application Icon"; - } - - if ( $template['Requires'] ) { - $template['Requires'] = Markdown(strip_tags(str_replace(["\r","\n"," "],["","
    ",""],trim($template['Requires'])),"
    ")); - preg_match_all("/\/\/(.*?)\/m",$template['Requires'],$searchMatches); - if ( count($searchMatches[1]) ) { - foreach ($searchMatches[1] as $searchResult) { - $template['Requires'] = str_replace("//$searchResult\","$searchResult",$template['Requires']); - } - } - } - $actionsContext = []; - if ( ! $template['Language'] ) { - if ( ! $template['NoInstall'] && ! ($caSettings['NoInstalls'] ?? false) ) { - if ( ! $template['Plugin'] ) { - if ( $caSettings['dockerRunning'] ) { - if ( $selected ) { - if ( $info[$name]['url'] && $info[$name]['running'] ) { - $actionsContext[] = ["icon"=>"ca_fa-globe","text"=>"WebUI","action"=>"openNewWindow('{$info[$name]['url']}','_blank');"]; - } - $tmpRepo = strpos($template['Repository'],":") ? $template['Repository'] : $template['Repository'].":latest"; - $tmpRepo = strpos($tmpRepo,"/") ? $tmpRepo : "library/$tmpRepo"; - if ( $dockerUpdateStatus[$tmpRepo]['status'] == "false" ) { - $template['UpdateAvailable'] = true; - $actionsContext[] = ["icon"=>"ca_fa-update","text"=>tr("Update"),"action"=>"updateDocker('$name');"]; - } else { - $template['UpdateAvailable'] = false; - } - if ( $caSettings['defaultReinstall'] == "true" && ! $template['Blacklist'] && $template['ID'] !== false) { - if ( $template['BranchID'] ?? false ) - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install second instance"),"action"=>"displayTags('{$template['ID']}',true,'','".portsUsed($template)."');"]; - else - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install second instance"),"action"=>"popupInstallXML('".addslashes($template['Path'])."','second','','".portsUsed($template)."');"]; - } - if ( is_file($info[$name]['template']) ) - $actionsContext[] = ["icon"=>"ca_fa-edit","text"=>tr("Edit"),"action"=>"popupInstallXML('".addslashes($info[$name]['template'])."','edit');"]; + if ( $template['IconFA'] ) { + $template['IconFA'] = $template['IconFA'] ?: $template['Icon']; + $templateIcon = startsWith($template['IconFA'],"icon-") ? "{$template['IconFA']} unraidIcon" : "fa fa-{$template['IconFA']}"; + $template['display_icon'] = ""; + } else { + $template['Icon'] = $template["Icon-{$caSettings['dynamixTheme']}"] ?? $template['Icon']; + $template['display_icon'] = "Application Icon"; + } + + if ( $template['Requires'] ) { + $template['Requires'] = Markdown(strip_tags(str_replace(["\r","\n"," "],["","
    ",""],trim($template['Requires'])),"
    ")); + preg_match_all("/\/\/(.*?)\/m",$template['Requires'],$searchMatches); + if ( count($searchMatches[1]) ) { + foreach ($searchMatches[1] as $searchResult) { + $template['Requires'] = str_replace("//$searchResult\","$searchResult",$template['Requires']); + } + } + } + $actionsContext = []; + if ( ! $template['Language'] ) { + if ( ! $template['NoInstall'] && ! ($caSettings['NoInstalls'] ?? false) ) { + if ( ! $template['Plugin'] ) { + if ( $caSettings['dockerRunning'] ) { + if ( $selected ) { + if ( $info[$name]['url'] && $info[$name]['running'] ) { + $actionsContext[] = ["icon"=>"ca_fa-globe","text"=>"WebUI","action"=>"openNewWindow('{$info[$name]['url']}','_blank');"]; + } + $tmpRepo = strpos($template['Repository'],":") ? $template['Repository'] : $template['Repository'].":latest"; + $tmpRepo = strpos($tmpRepo,"/") ? $tmpRepo : "library/$tmpRepo"; + if ( $dockerUpdateStatus[$tmpRepo]['status'] == "false" ) { + $template['UpdateAvailable'] = true; + $actionsContext[] = ["icon"=>"ca_fa-update","text"=>tr("Update"),"action"=>"updateDocker('$name');"]; + } else { + $template['UpdateAvailable'] = false; + } + if ( $caSettings['defaultReinstall'] == "true" && ! $template['Blacklist'] && $template['ID'] !== false) { + if ( $template['BranchID'] ?? false ) + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install second instance"),"action"=>"displayTags('{$template['ID']}',true,'','".portsUsed($template)."');"]; + else + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install second instance"),"action"=>"popupInstallXML('".addslashes($template['Path'])."','second','','".portsUsed($template)."');"]; + } + if ( is_file($info[$name]['template']) ) + $actionsContext[] = ["icon"=>"ca_fa-edit","text"=>tr("Edit"),"action"=>"popupInstallXML('".addslashes($info[$name]['template'])."','edit');"]; - $actionsContext[] = ["divider"=>true]; - if ( $info[$name]['template'] ) { - $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>"".tr("Uninstall")."","action"=>"uninstallDocker('".addslashes($info[$name]['template'])."','{$template['Name']}');"]; - $template['Installed'] = true; - } - } elseif ( ! $template['Blacklist'] ) { - if ( $template['InstallPath'] ) { - $userTemplate = readXmlFile($template['InstallPath'],false,false); - if ( ! $template['Blacklist'] ) { - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Reinstall"),"action"=>"popupInstallXML('".addslashes($template['InstallPath'])."','user','','".portsUsed($userTemplate)."');"]; - $actionsContext[] = ["divider"=>true]; - } - $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>"".tr("Remove from Previous Apps")."","action"=>"removeApp('{$template['InstallPath']}','{$template['Name']}');"]; - } else { - if ( ! $template['Blacklist'] ) { - if ( ( $template['Compatible'] || $caSettings['hideIncompatible'] !== "true" ) ) { - if ( !$template['Deprecated'] || $caSettings['hideDeprecated'] !== "true" ) { - if ( ! isset($template['BranchID']) ) { - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"popupInstallXML('".addslashes($template['Path'])."','default','','".portsUsed($template)."');"]; - } else { - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"displayTags('{$template['ID']}',false,'','".portsUsed($template)."');"]; - } - } - } - } - } - } - } - } else { - if ( file_exists("/var/log/plugins/$pluginName") ) { - $template['Installed'] = true; - $template['installedVersion'] = plugin("version","/var/log/plugins/$pluginName"); - if ( ($template['installedVersion'] != $template['pluginVersion'] || $template['installedVersion'] != plugin("version","/tmp/plugins/$pluginName") ) && $template['Name'] !== "Community Applications") { - if (is_file($caPaths['pluginTempDownload'])) { - @copy($caPaths['pluginTempDownload'],"/tmp/plugins/$pluginName"); - $template['UpdateAvailable'] = true; - $actionsContext[] = ["icon"=>"ca_fa-update","text"=>tr("Update"),"action"=>"installPlugin('$pluginName',true);"]; - } - } else { - $template['UpdateAvailable'] = false; - } - $pluginSettings = ($pluginName == "community.applications.plg") ? "ca_settings" : plugin("launch","/var/log/plugins/$pluginName"); - if ( $pluginSettings ) { - $actionsContext[] = ["icon"=>"ca_fa-pluginSettings","text"=>tr("Settings"),"action"=>"openNewWindow('/Apps/$pluginSettings');"]; - } - if ( $pluginName != "community.applications.plg" ) { - if ( ! empty($actionsContext) ) - $actionsContext[] = ["divider"=>true]; + $actionsContext[] = ["divider"=>true]; + if ( $info[$name]['template'] ) { + $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>"".tr("Uninstall")."","action"=>"uninstallDocker('".addslashes($info[$name]['template'])."','{$template['Name']}');"]; + $template['Installed'] = true; + } + } elseif ( ! $template['Blacklist'] ) { + if ( $template['InstallPath'] ) { + $userTemplate = readXmlFile($template['InstallPath'],false,false); + if ( ! $template['Blacklist'] ) { + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Reinstall"),"action"=>"popupInstallXML('".addslashes($template['InstallPath'])."','user','','".portsUsed($userTemplate)."');"]; + $actionsContext[] = ["divider"=>true]; + } + $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>"".tr("Remove from Previous Apps")."","action"=>"removeApp('{$template['InstallPath']}','{$template['Name']}');"]; + } else { + if ( ! $template['Blacklist'] ) { + if ( ( $template['Compatible'] || $caSettings['hideIncompatible'] !== "true" ) ) { + if ( !$template['Deprecated'] || $caSettings['hideDeprecated'] !== "true" ) { + if ( ! isset($template['BranchID']) ) { + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"popupInstallXML('".addslashes($template['Path'])."','default','','".portsUsed($template)."');"]; + } else { + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"displayTags('{$template['ID']}',false,'','".portsUsed($template)."');"]; + } + } + } + } + } + } + } + } else { + if ( file_exists("/var/log/plugins/$pluginName") ) { + $template['Installed'] = true; + $template['installedVersion'] = plugin("version","/var/log/plugins/$pluginName"); + if ( ($template['installedVersion'] != $template['pluginVersion'] || $template['installedVersion'] != plugin("version","/tmp/plugins/$pluginName") ) && $template['Name'] !== "Community Applications") { + if (is_file($caPaths['pluginTempDownload'])) { + @copy($caPaths['pluginTempDownload'],"/tmp/plugins/$pluginName"); + $template['UpdateAvailable'] = true; + $actionsContext[] = ["icon"=>"ca_fa-update","text"=>tr("Update"),"action"=>"installPlugin('$pluginName',true);"]; + } + } else { + $template['UpdateAvailable'] = false; + } + $pluginSettings = ($pluginName == "community.applications.plg") ? "ca_settings" : plugin("launch","/var/log/plugins/$pluginName"); + if ( $pluginSettings ) { + $actionsContext[] = ["icon"=>"ca_fa-pluginSettings","text"=>tr("Settings"),"action"=>"openNewWindow('/Apps/$pluginSettings');"]; + } + if ( $pluginName != "community.applications.plg" ) { + if ( ! empty($actionsContext) ) + $actionsContext[] = ["divider"=>true]; - $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>"".tr("Uninstall")."","action"=>"uninstallApp('/var/log/plugins/$pluginName','".str_replace(" "," ",$template['Name'])."');"]; - } - } elseif ( ! $template['Blacklist'] ) { - if ( ($template['Compatible'] || $caSettings['hideIncompatible'] !== "true") && !($template['UninstallOnly'] ?? false) ) { - if ( !$template['Deprecated'] || $caSettings['hideDeprecated'] !== "true" || ($template['Deprecated'] && $template['InstallPath']) ) { - if ( ($template['RequiresFile'] && is_file($template['RequiresFile']) ) || ! $template['RequiresFile'] ) { - $buttonTitle = $template['InstallPath'] ? tr("Reinstall") : tr("Install"); - $isDeprecated = $template['Deprecated'] ? "&deprecated" : ""; - $isDeprecated = $template['Compatible'] ? "&incompatible" : ""; - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>$buttonTitle,"action"=>"installPlugin('{$template['PluginURL']}$isDeprecated');"]; - } - } - } - if ( $template['InstallPath'] ) { - if ( ! empty($actionsContext) ) - $actionsContext[] = ["divider"=>true]; - $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>"".tr("Remove from Previous Apps")."","action"=>"removeApp('{$template['InstallPath']}','$pluginName');"]; - } - } - if ( is_file($caPaths['pluginPending'].$pluginName) ) { - unset($actionsContext); - $actionsContext[] = ["text"=>tr("Pending")]; - } - } - } - } - if ( $template['Language'] ) { - $dynamixSettings = @parse_ini_file($caPaths['dynamixSettings'],true); - $currentLanguage = $dynamixSettings['display']['locale'] ?? "en_US"; - $installedLanguages = array_diff(scandir("/usr/local/emhttp/languages"),array(".","..")); - $installedLanguages = array_filter($installedLanguages,function($v) { - return is_dir("/usr/local/emhttp/languages/$v"); - }); - $installedLanguages[] = "en_US"; - $currentLanguage = (is_dir("/usr/local/emhttp/languages/$currentLanguage") ) ? $currentLanguage : "en_US"; - if ( in_array($countryCode,$installedLanguages) ) { - if ( $currentLanguage != $countryCode ) { - $actionsContext[] = ["icon"=>"ca_fa-switchto","text"=>$template['SwitchLanguage'],"action"=>"CAswitchLanguage('$countryCode');"]; - } - } else { - $actionsContext[] = ["icon"=>"ca_fa-install","text"=>$template['InstallLanguage'],"action"=>"installLanguage('{$template['TemplateURL']}','$countryCode');"]; - } - if ( file_exists("/var/log/plugins/lang-$countryCode.xml") ) { - if ( languageCheck($template) ) { - $template['UpdateAvailable'] = true; - $actionsContext[] = ["icon"=>"ca_fa-update","text"=>$template['UpdateLanguage'],"action"=>"updateLanguage('$countryCode');"]; - } - if ( $currentLanguage != $countryCode ) { - if ( ! empty($actionsContext) ) - $actionsContext[] = ["divider"=>true]; - $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>"".tr("Remove Language Pack")."","action"=>"removeLanguage('$countryCode');"]; - } - } - if ( $countryCode !== "en_US" ) { - $template['Changes'] = "
    ".tr("Click here to view the language changelog")."
    "; - } else { - unset($template['Changes']); - } - if ( file_exists($caPaths['pluginPending'].$template['LanguagePack']) || file_exists("{$caPaths['pluginPending']}lang-{$template['LanguagePack']}.xml") ) { - unset($actionsContext); - $actionsContext[] = ["text"=>tr("Pending")]; - } - } + $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>"".tr("Uninstall")."","action"=>"uninstallApp('/var/log/plugins/$pluginName','".str_replace(" "," ",$template['Name'])."');"]; + } + } elseif ( ! $template['Blacklist'] ) { + if ( ($template['Compatible'] || $caSettings['hideIncompatible'] !== "true") && !($template['UninstallOnly'] ?? false) ) { + if ( !$template['Deprecated'] || $caSettings['hideDeprecated'] !== "true" || ($template['Deprecated'] && $template['InstallPath']) ) { + if ( ($template['RequiresFile'] && is_file($template['RequiresFile']) ) || ! $template['RequiresFile'] ) { + $buttonTitle = $template['InstallPath'] ? tr("Reinstall") : tr("Install"); + $isDeprecated = $template['Deprecated'] ? "&deprecated" : ""; + $isDeprecated = $template['Compatible'] ? "&incompatible" : ""; + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>$buttonTitle,"action"=>"installPlugin('{$template['PluginURL']}$isDeprecated');"]; + } + } + } + if ( $template['InstallPath'] ) { + if ( ! empty($actionsContext) ) + $actionsContext[] = ["divider"=>true]; + $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>"".tr("Remove from Previous Apps")."","action"=>"removeApp('{$template['InstallPath']}','$pluginName');"]; + } + } + if ( is_file($caPaths['pluginPending'].$pluginName) ) { + unset($actionsContext); + $actionsContext[] = ["text"=>tr("Pending")]; + } + } + } + } + if ( $template['Language'] ) { + $dynamixSettings = @parse_ini_file($caPaths['dynamixSettings'],true); + $currentLanguage = $dynamixSettings['display']['locale'] ?? "en_US"; + $installedLanguages = array_diff(scandir("/usr/local/emhttp/languages"),array(".","..")); + $installedLanguages = array_filter($installedLanguages,function($v) { + return is_dir("/usr/local/emhttp/languages/$v"); + }); + $installedLanguages[] = "en_US"; + $currentLanguage = (is_dir("/usr/local/emhttp/languages/$currentLanguage") ) ? $currentLanguage : "en_US"; + if ( in_array($countryCode,$installedLanguages) ) { + if ( $currentLanguage != $countryCode ) { + $actionsContext[] = ["icon"=>"ca_fa-switchto","text"=>$template['SwitchLanguage'],"action"=>"CAswitchLanguage('$countryCode');"]; + } + } else { + $actionsContext[] = ["icon"=>"ca_fa-install","text"=>$template['InstallLanguage'],"action"=>"installLanguage('{$template['TemplateURL']}','$countryCode');"]; + } + if ( file_exists("/var/log/plugins/lang-$countryCode.xml") ) { + if ( languageCheck($template) ) { + $template['UpdateAvailable'] = true; + $actionsContext[] = ["icon"=>"ca_fa-update","text"=>$template['UpdateLanguage'],"action"=>"updateLanguage('$countryCode');"]; + } + if ( $currentLanguage != $countryCode ) { + if ( ! empty($actionsContext) ) + $actionsContext[] = ["divider"=>true]; + $actionsContext[] = ["icon"=>"ca_fa-delete","text"=>"".tr("Remove Language Pack")."","action"=>"removeLanguage('$countryCode');"]; + } + } + if ( $countryCode !== "en_US" ) { + $template['Changes'] = "
    ".tr("Click here to view the language changelog")."
    "; + } else { + unset($template['Changes']); + } + if ( file_exists($caPaths['pluginPending'].$template['LanguagePack']) || file_exists("{$caPaths['pluginPending']}lang-{$template['LanguagePack']}.xml") ) { + unset($actionsContext); + $actionsContext[] = ["text"=>tr("Pending")]; + } + } - $supportContext = []; - if ( $template['ReadMe'] ) - $supportContext[] = ["icon"=>"ca_fa-readme","link"=>$template['ReadMe'],"text"=>tr("Read Me First")]; - if ( $template['Project'] ) - $supportContext[] = ["icon"=>"ca_fa-project","link"=>$template['Project'],"text"=> tr("Project")]; + $supportContext = []; + if ( $template['ReadMe'] ) + $supportContext[] = ["icon"=>"ca_fa-readme","link"=>$template['ReadMe'],"text"=>tr("Read Me First")]; + if ( $template['Project'] ) + $supportContext[] = ["icon"=>"ca_fa-project","link"=>$template['Project'],"text"=> tr("Project")]; - if ( $template['Discord'] ) - $supportContext[] = ["icon"=>"ca_discord","link"=>$template['Discord'],"text"=>tr("Discord")]; - elseif ( isset($allRepositories[$template['Repo']]['Discord']) ) - $supportContext[] = ["icon"=>"ca_discord","link"=>$allRepositories[$template['Repo']]['Discord'],"text"=>tr("Discord")]; + if ( $template['Discord'] ) + $supportContext[] = ["icon"=>"ca_discord","link"=>$template['Discord'],"text"=>tr("Discord")]; + elseif ( isset($allRepositories[$template['Repo']]['Discord']) ) + $supportContext[] = ["icon"=>"ca_discord","link"=>$allRepositories[$template['Repo']]['Discord'],"text"=>tr("Discord")]; - if ( $template['Facebook'] ) - $supportContext[] = ["icon"=>"ca_facebook","link"=>$template['Facebook'],"text"=>tr("Facebook")]; - if ( $template['Reddit'] ) - $supportContext[] = ["icon"=>"ca_reddit","link"=>$template['Reddit'],"text"=>tr("Reddit")]; + if ( $template['Facebook'] ) + $supportContext[] = ["icon"=>"ca_facebook","link"=>$template['Facebook'],"text"=>tr("Facebook")]; + if ( $template['Reddit'] ) + $supportContext[] = ["icon"=>"ca_reddit","link"=>$template['Reddit'],"text"=>tr("Reddit")]; - if ( $template['Support'] ) - $supportContext[] = ["icon"=>"ca_fa-support","link"=>$template['Support'],"text"=> $template['SupportLanguage'] ?: tr("Support Forum")]; + if ( $template['Support'] ) + $supportContext[] = ["icon"=>"ca_fa-support","link"=>$template['Support'],"text"=> $template['SupportLanguage'] ?: tr("Support Forum")]; - if ( $template['Registry'] ) - $supportContext[] = ["icon"=>"ca_fa-docker","link"=>$template['Registry'],"text"=> tr("Registry")]; - if ( $caSettings['dev'] == "yes" ) - $supportContext[] = ["icon"=>"ca_fa-template","link"=> $template['caTemplateURL'] ?: ($template['TemplateURL']??""),"text"=>tr("Application Template")]; + if ( $template['Registry'] ) + $supportContext[] = ["icon"=>"ca_fa-docker","link"=>$template['Registry'],"text"=> tr("Registry")]; + if ( $caSettings['dev'] == "yes" ) + $supportContext[] = ["icon"=>"ca_fa-template","link"=> $template['caTemplateURL'] ?: ($template['TemplateURL']??""),"text"=>tr("Application Template")]; - $author = $template['PluginURL'] ? $template['PluginAuthor'] : $template['SortAuthor']; + $author = $template['PluginURL'] ? $template['PluginAuthor'] : $template['SortAuthor']; - if (is_array($template['trends']) && (count($template['trends']) > 1) ){ - if ( $template['downloadtrend'] ) { - $templateDescription .= "
    "; - $templateDescription .= "
    "; - $templateDescription .= "
    "; - } - } - if ( ! isset($countryCode) ) { - $changeLogMessage = "Note: not all "; - $changeLogMessage .= $template['PluginURL'] || $template['Language'] ? "authors" : "maintainers"; - $changeLogMessage .= " keep up to date on change logs
    "; - $template['display_changelogMessage'] = tr($changeLogMessage); - } + if (is_array($template['trends']) && (count($template['trends']) > 1) ){ + if ( $template['downloadtrend'] ) { + $templateDescription .= "
    "; + $templateDescription .= "
    "; + $templateDescription .= "
    "; + } + } + if ( ! isset($countryCode) ) { + $changeLogMessage = "Note: not all "; + $changeLogMessage .= $template['PluginURL'] || $template['Language'] ? "authors" : "maintainers"; + $changeLogMessage .= " keep up to date on change logs
    "; + $template['display_changelogMessage'] = tr($changeLogMessage); + } - if ( isset($template['trendsDate']) ) { - array_walk($template['trendsDate'],function(&$entry) { - $entry = tr(date("M",$entry),0).date(" j",$entry); - }); - } + if ( isset($template['trendsDate']) ) { + array_walk($template['trendsDate'],function(&$entry) { + $entry = tr(date("M",$entry),0).date(" j",$entry); + }); + } - if ( is_array($template['trends']) ) { - if ( count($template['trends']) < count($template['downloadtrend']) ) - array_shift($template['downloadtrend']); + if ( is_array($template['trends']) ) { + if ( count($template['trends']) < count($template['downloadtrend']) ) + array_shift($template['downloadtrend']); - $chartLabel = $template['trendsDate']; - if ( is_array($template['downloadtrend']) ) { - #get what the previous download value would have been based upon the trend - $minDownload = intval( ((100 - $template['trends'][0]) / 100) * ($template['downloadtrend'][0]) ); - foreach ($template['downloadtrend'] as $download) { - $totalDown[] = $download; - $down[] = intval($download - $minDownload); - $minDownload = $download; - } - $downloadLabel = $template['trendsDate']; - } - $down = is_array($down) ? $down : []; - } + $chartLabel = $template['trendsDate']; + if ( is_array($template['downloadtrend']) ) { + #get what the previous download value would have been based upon the trend + $minDownload = intval( ((100 - $template['trends'][0]) / 100) * ($template['downloadtrend'][0]) ); + foreach ($template['downloadtrend'] as $download) { + $totalDown[] = $download; + $down[] = intval($download - $minDownload); + $minDownload = $download; + } + $downloadLabel = $template['trendsDate']; + } + $down = is_array($down) ? $down : []; + } - if ( $pinnedApps["{$template['Repository']}&{$template['SortName']}"] ?? false ) { - $template['pinned'] = tr("Unpin App"); - $template['pinnedTitle'] = tr("Click to unpin this application"); - $template['pinnedClass'] = "pinned"; - } else { - $template['pinned'] = tr("Pin App"); - $template['pinnedTitle'] = tr("Click to pin this application"); - $template['pinnedClass'] = "unpinned"; - } - $template['actionsContext'] = $actionsContext; - $template['supportContext'] = $supportContext; - @unlink($caPaths['pluginTempDownload']); + if ( $pinnedApps["{$template['Repository']}&{$template['SortName']}"] ?? false ) { + $template['pinned'] = tr("Unpin App"); + $template['pinnedTitle'] = tr("Click to unpin this application"); + $template['pinnedClass'] = "pinned"; + } else { + $template['pinned'] = tr("Pin App"); + $template['pinnedTitle'] = tr("Click to pin this application"); + $template['pinnedClass'] = "unpinned"; + } + $template['actionsContext'] = $actionsContext; + $template['supportContext'] = $supportContext; + @unlink($caPaths['pluginTempDownload']); - return ["description"=>displayPopup($template),"trendData"=>$template['trends'],"trendLabel"=>$chartLabel ?? "","downloadtrend"=>$down ?? "","downloadLabel"=>$downloadLabel ?? "","totaldown"=>$totalDown ?? "","totaldownLabel"=>$downloadLabel ?? "","supportContext"=>$supportContext,"actionsContext"=>$actionsContext,"ID"=>$template['ID']]; + return ["description"=>displayPopup($template),"trendData"=>$template['trends'],"trendLabel"=>$chartLabel ?? "","downloadtrend"=>$down ?? "","downloadLabel"=>$downloadLabel ?? "","totaldown"=>$totalDown ?? "","totaldownLabel"=>$downloadLabel ?? "","supportContext"=>$supportContext,"actionsContext"=>$actionsContext,"ID"=>$template['ID']]; } ##################################### # Generate the display for the repo # ##################################### function getRepoDescriptionSkin($repository) { - global $caSettings, $caPaths, $language; + global $caSettings, $caPaths, $language; - $dockerVars = parse_ini_file($caPaths['docker_cfg']); - $repositories = readJsonFile($caPaths['repositoryList']); - $templates = &$GLOBALS['templates']; + $dockerVars = parse_ini_file($caPaths['docker_cfg']); + $repositories = readJsonFile($caPaths['repositoryList']); + $templates = &$GLOBALS['templates']; - $repo = $repositories[$repository]; - $iconPrefix = $repo['icon'] ? "" : ""; - $iconPostfix = $repo['icon'] ? "" : ""; + $repo = $repositories[$repository]; + $iconPrefix = $repo['icon'] ? "" : ""; + $iconPostfix = $repo['icon'] ? "" : ""; - $repo['icon'] = $repo['icon'] ?? "/plugins/dynamix.docker.manager/images/question.png"; - $repo['bio'] = isset($repo['bio']) ? markdown($repo['bio']) : "
    ".tr("No description present"); - $favRepoClass = ($caSettings['favourite'] == $repository) ? "fav" : "nonfav"; + $repo['icon'] = $repo['icon'] ?? "/plugins/dynamix.docker.manager/images/question.png"; + $repo['bio'] = isset($repo['bio']) ? markdown($repo['bio']) : "
    ".tr("No description present"); + $favRepoClass = ($caSettings['favourite'] == $repository) ? "fav" : "nonfav"; - $totalApps = $totalLanguage = $totalPlugins = $totalDocker = $totalDownloads = $downloadDockerCount = 0; - foreach ($templates as $template) { - if ( $template['RepoName'] !== $repository ) continue; - if ( isset($template['BranchID']) ) continue; + $totalApps = $totalLanguage = $totalPlugins = $totalDocker = $totalDownloads = $downloadDockerCount = 0; + foreach ($templates as $template) { + if ( $template['RepoName'] !== $repository ) continue; + if ( isset($template['BranchID']) ) continue; - if ( $template['Blacklist'] ) continue; - if ( $template['Deprecated'] && $caSettings['hideDeprecated'] !== "false" ) continue; - if ( ! $template['Compatible'] && $caSettings['hideIncompatible'] !== "false" ) continue; + if ( $template['Blacklist'] ) continue; + if ( $template['Deprecated'] && $caSettings['hideDeprecated'] !== "false" ) continue; + if ( ! $template['Compatible'] && $caSettings['hideIncompatible'] !== "false" ) continue; - if ( $template['Registry'] ) { - $totalDocker++; - if ( $template['downloads'] ) { - $totalDownloads = $totalDownloads + $template['downloads']; - $downloadDockerCount++; - } - } - if ( $template['PluginURL'] ) { - $totalPlugins++; - } - if ( $template['Language'] ) { - $totalLanguage++; - } + if ( $template['Registry'] ) { + $totalDocker++; + if ( $template['downloads'] ) { + $totalDownloads = $totalDownloads + $template['downloads']; + $downloadDockerCount++; + } + } + if ( $template['PluginURL'] ) { + $totalPlugins++; + } + if ( $template['Language'] ) { + $totalLanguage++; + } - $totalApps++; - } + $totalApps++; + } - $t = " -
    ".tr("CLOSE")."
    -
    ".tr("BACK")."
    -
    -
    - $iconPrefix$iconPostfix -
    -
    -
    $repository
    -
    ".tr("See All Apps")."
    -
    ".tr("Favourite")."
    -
    -
    -

    ".strip_tags($repo['bio'])."
    - "; - if ( isset($repo['DonateLink']) ) { - $t .= " -
    -
    {$repo['DonateText']}
    - -
    - "; - } - if ( isset($repo['Photo']) || isset($repo['Video']) ) { - $t .= "
    "; - if ( isset($repo['Photo']) ) { - $photos = is_array($repo['Photo']) ? $repo['Photo'] : [$repo['Photo']]; - $t .= "
    "; - foreach ($photos as $shot) { - $t .= ""; - } - $t .= "
    "; - } - if ( isset($repo['Video']) ) { - if ( isset($repo['Photo']) ) - $t .= "

    "; + $t = " +
    ".tr("CLOSE")."
    +
    ".tr("BACK")."
    +
    +
    + $iconPrefix$iconPostfix +
    +
    +
    $repository
    +
    ".tr("See All Apps")."
    +
    ".tr("Favourite")."
    +
    +
    +

    ".strip_tags($repo['bio'])."
    + "; + if ( isset($repo['DonateLink']) ) { + $t .= " +
    +
    {$repo['DonateText']}
    + +
    + "; + } + if ( isset($repo['Photo']) || isset($repo['Video']) ) { + $t .= "
    "; + if ( isset($repo['Photo']) ) { + $photos = is_array($repo['Photo']) ? $repo['Photo'] : [$repo['Photo']]; + $t .= "
    "; + foreach ($photos as $shot) { + $t .= ""; + } + $t .= "
    "; + } + if ( isset($repo['Video']) ) { + if ( isset($repo['Photo']) ) + $t .= "

    "; - $videos = is_array($repo['Video']) ? $repo['Video'] : [$repo['Video']]; - $vidText = (count($videos) == 1) ? "Play Video" : "Play Video %s"; - $t .= "
    "; - $count = 1; - foreach ($videos as $vid) { - $t .= "
    ".sprintf(tr($vidText),$count)."
    "; - $count++; - } - $t .= "
    "; - } + $videos = is_array($repo['Video']) ? $repo['Video'] : [$repo['Video']]; + $vidText = (count($videos) == 1) ? "Play Video" : "Play Video %s"; + $t .= "
    "; + $count = 1; + foreach ($videos as $vid) { + $t .= "
    ".sprintf(tr($vidText),$count)."
    "; + $count++; + } + $t .= "
    "; + } - $t .= "
    "; - } - $t .= " -
    - "; + } + $t .= " +
    + "; - $t = ""; - return ["description"=>$t]; + $t = ""; + return ["description"=>$t]; } ######################################################################################## # function used to display the navigation (page up/down buttons) for dockerHub results # ######################################################################################## function dockerNavigate($num_pages, $pageNumber) { - return getPageNavigation($pageNumber,$num_pages * 25, true); + return getPageNavigation($pageNumber,$num_pages * 25, true); } ############################################################## # function that actually displays the results from dockerHub # ############################################################## function displaySearchResults($pageNumber) { - global $caPaths, $caSettings, $plugin; + global $caPaths, $caSettings, $plugin; - $tempFile = readJsonFile($caPaths['dockerSearchResults']); - $num_pages = $tempFile['num_pages']; - $file = $tempFile['results']; - $templates = &$GLOBALS['templates']; - $count = 0; - $caSettings['NoInstalls'] = is_file($caPaths['warningAccepted']) ? false : true; + $tempFile = readJsonFile($caPaths['dockerSearchResults']); + $num_pages = $tempFile['num_pages']; + $file = $tempFile['results']; + $templates = &$GLOBALS['templates']; + $count = 0; + $caSettings['NoInstalls'] = is_file($caPaths['warningAccepted']) ? false : true; - $ct = "
    ".tr("NOTE You must visit the dockerHub page to gather the information required to install correctly")."Show CA templates


    "; - $ct .= "
    "; + $ct = "
    ".tr("NOTE You must visit the dockerHub page to gather the information required to install correctly")."Show CA templates


    "; + $ct .= "
    "; - $columnNumber = 0; - foreach ($file as $result) { - $result['Icon'] = "/plugins/dynamix.docker.manager/images/question.png"; - $result['display_dockerName'] = "{$result['Name']}"; - $result['Category'] = "Docker Hub Search"; - $result['Description'] = $result['Description'] ?: tr("No description present"); - $result['Compatible'] = true; - if ( ! $caSettings['NoInstalls'] ) - $result['actionsContext'] = [["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"dockerConvert({$result['ID']});"]]; + $columnNumber = 0; + foreach ($file as $result) { + $result['Icon'] = "/plugins/dynamix.docker.manager/images/question.png"; + $result['display_dockerName'] = "{$result['Name']}"; + $result['Category'] = "Docker Hub Search"; + $result['Description'] = $result['Description'] ?: tr("No description present"); + $result['Compatible'] = true; + if ( ! $caSettings['NoInstalls'] ) + $result['actionsContext'] = [["icon"=>"ca_fa-install","text"=>tr("Install"),"action"=>"dockerConvert({$result['ID']});"]]; - $templateSearch = searchArray($templates,"Repository",$result['Repository']); - if ( $templateSearch === false ) - $templateSearch = searchArray($templates,"Repository","{$result['Repository']}.latest"); + $templateSearch = searchArray($templates,"Repository",$result['Repository']); + if ( $templateSearch === false ) + $templateSearch = searchArray($templates,"Repository","{$result['Repository']}.latest"); - if ( $templateSearch !== false && ! $templates[$templateSearch]['Deprecated'] && ! $templates[$templateSearch]['Blacklist']) { - $result['caTemplateExists'] = true; - $result['Icon'] = $templates[$templateSearch]['Icon']; - $result['Description'] = $templates[$templateSearch]['Overview'] ?: $templates[$templateSearch]['Description']; - unset($result['IconFA']); - $result['ID'] = $templates[$templateSearch]['ID']; - $result['actionsContext'] = [["icon"=>"ca_fa-template","text"=>tr("Show Template"),"action"=>"doSearch(false,'{$templates[$templateSearch]['Repository']}');"]]; - } - $ct .= displayCard($result); - $count++; - } - $ct .= "
    "; + if ( $templateSearch !== false && ! $templates[$templateSearch]['Deprecated'] && ! $templates[$templateSearch]['Blacklist']) { + $result['caTemplateExists'] = true; + $result['Icon'] = $templates[$templateSearch]['Icon']; + $result['Description'] = $templates[$templateSearch]['Overview'] ?: $templates[$templateSearch]['Description']; + unset($result['IconFA']); + $result['ID'] = $templates[$templateSearch]['ID']; + $result['actionsContext'] = [["icon"=>"ca_fa-template","text"=>tr("Show Template"),"action"=>"doSearch(false,'{$templates[$templateSearch]['Repository']}');"]]; + } + $ct .= displayCard($result); + $count++; + } + $ct .= "
    "; - return $ct.dockerNavigate($num_pages,$pageNumber); + return $ct.dockerNavigate($num_pages,$pageNumber); } ########################### # Generate the app's card # ########################### function displayCard($template) { - global $caSettings, $caPaths; - $appName = str_replace("-"," ",$template['display_dockerName'] ?? ""); - $holderClass = ""; - $card = ""; + global $caSettings, $caPaths; + $appName = str_replace("-"," ",$template['display_dockerName'] ?? ""); + $holderClass = ""; + $card = ""; - if ( $template['RepositoryTemplate'] ) - $template['DockerHub'] = false; + if ( $template['RepositoryTemplate'] ) + $template['DockerHub'] = false; - if ( $template['DockerHub'] ) - $popupType = null; - else { - $popupType = $template['RepositoryTemplate'] ? "ca_repoPopup" : "ca_appPopup"; + if ( $template['DockerHub'] ) + $popupType = null; + else { + $popupType = $template['RepositoryTemplate'] ? "ca_repoPopup" : "ca_appPopup"; - if (! $template['RepositoryTemplate'] && $template['Language']) { - $language = "{$template['Language']}"; - $language .= $template['LanguageLocal'] ? " - {$template['LanguageLocal']}" : ""; - $template['Category'] = ""; - } - } + if (! $template['RepositoryTemplate'] && $template['Language']) { + $language = "{$template['Language']}"; + $language .= $template['LanguageLocal'] ? " - {$template['LanguageLocal']}" : ""; + $template['Category'] = ""; + } + } - extract($template); + extract($template); - $class = "spotlightHome"; - $RepoName = $RepoName ?? ""; + $class = "spotlightHome"; + $RepoName = $RepoName ?? ""; - if ( $RepositoryTemplate ) - $appType = "appRepository"; - else { - $appType = $Plugin ? "appPlugin" : "appDocker"; - $appType = $Language ? "appLanguage": $appType; - $appType = (strpos($Category,"Drivers") !== false) && $Plugin ? "appDriver" : $appType; - } - switch ($appType) { - case "appPlugin": - $typeTitle = tr("This application is a plugin"); - break; - case "appDocker": - $typeTitle = tr("This application is a docker container"); - break; - case "appLanguage": - $typeTitle = tr("This is a language pack"); - break; - case "appDriver": - $typeTitle = tr("This application is a driver (plugin)"); - break; - default: - $typeTitle = ""; - break; - } - if ($InstallPath ?? false) - $Path = $InstallPath; + if ( $RepositoryTemplate ) + $appType = "appRepository"; + else { + $appType = $Plugin ? "appPlugin" : "appDocker"; + $appType = $Language ? "appLanguage": $appType; + $appType = (strpos($Category,"Drivers") !== false) && $Plugin ? "appDriver" : $appType; + } + switch ($appType) { + case "appPlugin": + $typeTitle = tr("This application is a plugin"); + break; + case "appDocker": + $typeTitle = tr("This application is a docker container"); + break; + case "appLanguage": + $typeTitle = tr("This is a language pack"); + break; + case "appDriver": + $typeTitle = tr("This application is a driver (plugin)"); + break; + default: + $typeTitle = ""; + break; + } + if ($InstallPath ?? false) + $Path = $InstallPath; - $Category = $Category ?? ""; - $Category = explode(" ",$Category)[0]; - $Category = explode(":",$Category)[0]; + $Category = $Category ?? ""; + $Category = explode(" ",$Category)[0]; + $Category = explode(":",$Category)[0]; - if ( ! $DockerHub ) - $author = $RepoShort ?? $RepoName; - else - $author = $Author; + if ( ! $DockerHub ) + $author = $RepoShort ?? $RepoName; + else + $author = $Author; - $ID = $ID ?? ""; + $ID = $ID ?? ""; - $author = $author ?? ""; - if ( $author == $RepoName ) { - if (strpos($author,"' Repository") ) - $author = sprintf(tr("%s's Repository"),str_replace("' Repository","",$author)); - elseif (strpos($author,"'s Repository")) - $author = sprintf(tr("%s's Repository"),str_replace("'s Repository","",$author)); - elseif (strpos($author," Repository") ) - $author = sprintf(tr("%s Repository"),str_replace(" Repository","",$author)); - } + $author = $author ?? ""; + if ( $author == $RepoName ) { + if (strpos($author,"' Repository") ) + $author = sprintf(tr("%s's Repository"),str_replace("' Repository","",$author)); + elseif (strpos($author,"'s Repository")) + $author = sprintf(tr("%s's Repository"),str_replace("'s Repository","",$author)); + elseif (strpos($author," Repository") ) + $author = sprintf(tr("%s Repository"),str_replace(" Repository","",$author)); + } - if ( !$RepositoryTemplate ) { - $cardClass = "ca_appPopup"; - $supportContext = []; - if ( $ReadMe ) - $supportContext[] = ["icon"=>"ca_fa-readme","link"=>$ReadMe,"text"=>tr("Read Me First")]; - if ( $Project ) - $supportContext[] = ["icon"=>"ca_fa-project","link"=>$Project,"text"=> tr("Project")]; - if ( $Discord ) - $supportContext[] = ["icon"=>"ca_discord","link"=>$Discord,"text"=>tr("Discord")]; - if ( $Support ) - $supportContext[] = ["icon"=>"ca_fa-support","link"=>$Support,"text"=> $SupportLanguage ?: tr("Support Forum")]; - if ( $Registry ?? false) - $supportContext[] = ["icon"=>"docker","link"=>$Registry,"text"=>tr("Registry")]; - } else { - $holderClass='repositoryCard'; - $cardClass = "ca_repoinfo"; - $ID = str_replace(" ","",$RepoName); - $supportContext = []; - if ( $profile ?? false ) - $supportContext[] = ["icon"=>"ca_profile","link"=>$profile,"text"=>tr("Profile")]; - if ( $Forum ?? false) - $supportContext[] = ["icon"=>"ca_forum","link"=>$Forum,"text"=>tr("Forum")]; - if ( $Twitter ?? false) - $supportContext[] = ["icon"=>"ca_twitter","link"=>$Twitter,"text"=>tr("Twitter")]; - if ( $Reddit ?? false) - $supportContext[] = ["icon"=>"ca_reddit","link"=>$Reddit,"text"=>tr("Reddit")]; - if ( $Facebook ?? false) - $supportContext[] = ["icon"=>"ca_facebook","link"=>$Facebook,"text"=>tr("Facebook")]; - if ( $WebPage ?? false) - $supportContext[] = ["icon"=>"ca_webpage","link"=>$WebPage,"text"=>tr("Web Page")]; + if ( !$RepositoryTemplate ) { + $cardClass = "ca_appPopup"; + $supportContext = []; + if ( $ReadMe ) + $supportContext[] = ["icon"=>"ca_fa-readme","link"=>$ReadMe,"text"=>tr("Read Me First")]; + if ( $Project ) + $supportContext[] = ["icon"=>"ca_fa-project","link"=>$Project,"text"=> tr("Project")]; + if ( $Discord ) + $supportContext[] = ["icon"=>"ca_discord","link"=>$Discord,"text"=>tr("Discord")]; + if ( $Support ) + $supportContext[] = ["icon"=>"ca_fa-support","link"=>$Support,"text"=> $SupportLanguage ?: tr("Support Forum")]; + if ( $Registry ?? false) + $supportContext[] = ["icon"=>"docker","link"=>$Registry,"text"=>tr("Registry")]; + } else { + $holderClass='repositoryCard'; + $cardClass = "ca_repoinfo"; + $ID = str_replace(" ","",$RepoName); + $supportContext = []; + if ( $profile ?? false ) + $supportContext[] = ["icon"=>"ca_profile","link"=>$profile,"text"=>tr("Profile")]; + if ( $Forum ?? false) + $supportContext[] = ["icon"=>"ca_forum","link"=>$Forum,"text"=>tr("Forum")]; + if ( $Twitter ?? false) + $supportContext[] = ["icon"=>"ca_twitter","link"=>$Twitter,"text"=>tr("Twitter")]; + if ( $Reddit ?? false) + $supportContext[] = ["icon"=>"ca_reddit","link"=>$Reddit,"text"=>tr("Reddit")]; + if ( $Facebook ?? false) + $supportContext[] = ["icon"=>"ca_facebook","link"=>$Facebook,"text"=>tr("Facebook")]; + if ( $WebPage ?? false) + $supportContext[] = ["icon"=>"ca_webpage","link"=>$WebPage,"text"=>tr("Web Page")]; - $Name = str_replace(["' Repository","'s Repository"," Repository"],"",html_entity_decode($author,ENT_QUOTES)); + $Name = str_replace(["' Repository","'s Repository"," Repository"],"",html_entity_decode($author,ENT_QUOTES)); - $Name = str_replace(["'s","'s"],"",$Name); - $author = ""; - $Path = $Repository = $Plugin = $IconFA = $ModeratorComment = $RecommendedDate = $UpdateAvailable = $Blacklist = $Official = $Trusted = $Pinned = $actionsContext = $Deprecated = $Removable = $CAComment = $Installed = $Uninstalled = $Uninstall = $fav = $Beta = $Requires = $caTemplateExists = $actionCentre = $Overview = $imageNoClick = ""; - } + $Name = str_replace(["'s","'s"],"",$Name); + $author = ""; + $Path = $Repository = $Plugin = $IconFA = $ModeratorComment = $RecommendedDate = $UpdateAvailable = $Blacklist = $Official = $Trusted = $Pinned = $actionsContext = $Deprecated = $Removable = $CAComment = $Installed = $Uninstalled = $Uninstall = $fav = $Beta = $Requires = $caTemplateExists = $actionCentre = $Overview = $imageNoClick = ""; + } - $bottomClass = "ca_bottomLineSpotLight"; - if ( $DockerHub ) { - $backgroundClickable = "dockerCardBackground"; - $card .= " -
    -
    -
    ".tr("Docker Hub")."
    "; - } else { - if ( $PluginURL ?? false) { - $dataPluginURL = "data-pluginurl='$PluginURL'"; - } else { - $dataPluginURL = ""; - } - $backgroundClickable = "ca_backgroundClickable"; - $card .= " -
    -
    -
    ".tr("Info")."
    - "; - } - if ( count($supportContext) == 1) - $card .= "
    {$supportContext[0]['text']}
    "; - elseif (!empty($supportContext)) - $card .= " -
    ".tr("Support")."
    - "; + $bottomClass = "ca_bottomLineSpotLight"; + if ( $DockerHub ) { + $backgroundClickable = "dockerCardBackground"; + $card .= " +
    +
    +
    ".tr("Docker Hub")."
    "; + } else { + if ( $PluginURL ?? false) { + $dataPluginURL = "data-pluginurl='$PluginURL'"; + } else { + $dataPluginURL = ""; + } + $backgroundClickable = "ca_backgroundClickable"; + $card .= " +
    +
    +
    ".tr("Info")."
    + "; + } + if ( count($supportContext) == 1) + $card .= "
    {$supportContext[0]['text']}
    "; + elseif (!empty($supportContext)) + $card .= " +
    ".tr("Support")."
    + "; - if ( $actionsContext ) { - if ( count($actionsContext) == 1) { - $dispText = $actionsContext[0]['alternate'] ?? $actionsContext[0]['text']; - $card .= "
    $dispText
    "; - } - else - $card .= "
    ".tr("Actions")."
    "; - } + if ( $actionsContext ) { + if ( count($actionsContext) == 1) { + $dispText = $actionsContext[0]['alternate'] ?? $actionsContext[0]['text']; + $card .= "
    $dispText
    "; + } + else + $card .= "
    ".tr("Actions")."
    "; + } - $card .= ""; - if ( $ca_fav ) { - $favText = $RepositoryTemplate ? tr("This is your favourite repository") : tr("This application is from your favourite repository"); - $card .= ""; - } else - $card .= ""; + $card .= ""; + if ( $ca_fav ) { + $favText = $RepositoryTemplate ? tr("This is your favourite repository") : tr("This application is from your favourite repository"); + $card .= ""; + } else + $card .= ""; - $pinStyle = $Pinned ? "" : "display:none;"; + $pinStyle = $Pinned ? "" : "display:none;"; - $pindata = (strpos($Repository,"/") !== false) ? $Repository : "library/$Repository"; - $card .= ""; + $pindata = (strpos($Repository,"/") !== false) ? $Repository : "library/$Repository"; + $card .= ""; - $previousAppName = $Plugin ? $PluginURL : $Name; - switch ($appType) { - case 'appDocker': - $type = "docker"; - break; - case 'appPlugin': - $type = "plugin"; - break; - case 'appLanguage': - $type = "language"; - break; - case 'appDriver': - $type = 'plugin'; - break; - } - $checked = $checked ?? ""; - if ($Removable && !($DockerInfo ?? false) && ! $Installed && ! $Blacklist) { - $card .= ""; - } elseif ( $actionCentre && $UpdateAvailable ) { - $card .= ""; - } + $previousAppName = $Plugin ? $PluginURL : $Name; + switch ($appType) { + case 'appDocker': + $type = "docker"; + break; + case 'appPlugin': + $type = "plugin"; + break; + case 'appLanguage': + $type = "language"; + break; + case 'appDriver': + $type = 'plugin'; + break; + } + $checked = $checked ?? ""; + if ($Removable && !($DockerInfo ?? false) && ! $Installed && ! $Blacklist) { + $card .= ""; + } elseif ( $actionCentre && $UpdateAvailable ) { + $card .= ""; + } - $card .= "
    "; - $card .= "
    "; - $card .= "
    "; - if ( $DockerHub ) - $imageNoClick = "noClick"; + $card .= "
    "; + $card .= "
    "; + $card .= "
    "; + if ( $DockerHub ) + $imageNoClick = "noClick"; - if ( ! $IconFA ) - $card .= " - Application Icon - "; - else { - $displayIcon = $template['IconFA'] ?: $template['Icon']; - $displayIconClass = startsWith($displayIcon,"icon-") ? $displayIcon : "fa fa-$displayIcon"; - $card .= ""; - } - $card .= "
    "; + if ( ! $IconFA ) + $card .= " + Application Icon + "; + else { + $displayIcon = $template['IconFA'] ?: $template['Icon']; + $displayIconClass = startsWith($displayIcon,"icon-") ? $displayIcon : "fa fa-$displayIcon"; + $card .= ""; + } + $card .= "
    "; - $card .= " -
    $Name - "; - if ( $CAComment || $ModeratorComment || $Requires) { - $commentIcon = ""; - $warning = ""; - if ( $CAComment || $ModeratorComment) { - $commentIcon = "ca_fa-comment"; - $warning = tr("Click info to see the notes regarding this application"); - } - if ( $Requires ) { - if ( $RequiresFile && ! is_file($RequiresFile) ) { - $commentIcon = "ca_fa-additional"; - $warning = tr("This application has additional requirements"); - } - } + $card .= " +
    $Name + "; + if ( $CAComment || $ModeratorComment || $Requires) { + $commentIcon = ""; + $warning = ""; + if ( $CAComment || $ModeratorComment) { + $commentIcon = "ca_fa-comment"; + $warning = tr("Click info to see the notes regarding this application"); + } + if ( $Requires ) { + if ( $RequiresFile && ! is_file($RequiresFile) ) { + $commentIcon = "ca_fa-additional"; + $warning = tr("This application has additional requirements"); + } + } - $card .= " "; - } - $card .= " -
    -
    $author
    -
    $Category
    - "; + $card .= " "; + } + $card .= " +
    +
    $author
    +
    $Category
    + "; - $card .= " -
    - "; + $card .= " +
    + "; - $Overview = $Overview ?: ($Description ?? ""); + $Overview = $Overview ?: ($Description ?? ""); - if ( ! $Overview ) - $Overview = tr("No description present"); + if ( ! $Overview ) + $Overview = tr("No description present"); - $ovr = html_entity_decode($Overview); - $ovr = trim($ovr); - $ovr = str_replace(["[","]"],["<",">"],$ovr); - $ovr = str_replace("\n","
    ",$ovr); + $ovr = html_entity_decode($Overview); + $ovr = trim($ovr); + $ovr = str_replace(["[","]"],["<",">"],$ovr); + $ovr = str_replace("\n","
    ",$ovr); // $ovr = str_replace(" ","    ",$ovr); - $ovr = markdown(strip_tags($ovr,"
    ")); + $ovr = markdown(strip_tags($ovr,"
    ")); - $ovr = str_replace("\n","
    ",$ovr); - $Overview = strip_tags(str_replace("
    "," ",$ovr)); + $ovr = str_replace("\n","
    ",$ovr); + $Overview = strip_tags(str_replace("
    "," ",$ovr)); - if ( ($UninstallOnly ?? false) && $Featured && is_file("/var/log/plugins/".basename($PluginURL)) ) - $Overview = "".sprintf(tr("%s is incompatible with your OS version. Either uninstall %s or update the OS"),$Name,$Name)."  $Overview"; - else - if ( (! $Compatible || ($UninstallOnly ?? false) ) && $Featured ) - $Overview = "".sprintf(tr("%s is incompatible with your OS version. Please update the OS to proceed"),$Name)."  $Overview"; + if ( ($UninstallOnly ?? false) && $Featured && is_file("/var/log/plugins/".basename($PluginURL)) ) + $Overview = "".sprintf(tr("%s is incompatible with your OS version. Either uninstall %s or update the OS"),$Name,$Name)."  $Overview"; + else + if ( (! $Compatible || ($UninstallOnly ?? false) ) && $Featured ) + $Overview = "".sprintf(tr("%s is incompatible with your OS version. Please update the OS to proceed"),$Name)."  $Overview"; - $descClass= $RepositoryTemplate ? "cardDescriptionRepo" : "cardDescription"; - $card .= "
    $Overview
    "; - if ( $RecommendedDate ) { - $card .= " -
    -
    Spotlight
    -
    ".tr(date("M Y",$RecommendedDate),0)."
    -
    - "; - } - $card .= "
    "; - if ( $Installed || $Uninstall ) { - $flagTextStart = tr("Installed")."
    "; - $flagTextEnd = ""; - } else { - $flagTextStart = " "; - $flagTextEnd = " "; - } - if ( $UpdateAvailable ) { - $card .= " -
    -
    ".tr("UPDATED")."
    -
    "; - } elseif ( ($Installed || $Uninstall) && !$actionCentre) { - $card .= " -
    -
      ".tr("INSTALLED")."  
    -
    "; - } elseif ( $Blacklist ) { - $card .= " -
    -
    ".tr("Blacklisted")."$flagTextEnd
    -
    - "; - } elseif ( $caTemplateExists ) { - $card .= " -
    -
    ".tr("Template Exists")."
    -
    - "; - } elseif ( isset($Compatible) && ! $Compatible ) { - $verMsg = $VerMessage ?? tr("This application is not compatible with your version of Unraid"); - $card .= " -
    -
    $flagTextStart".tr("Incompatible")."$flagTextEnd
    -
    - "; - } elseif ( $Deprecated ) { - $card .= " -
    -
    ".tr("Deprecated")."$flagTextEnd
    -
    - "; - } elseif ( $Official ) { - $card .= " -
    -
    ".tr("OFFICIAL")."
    -
    - "; - } elseif ( $LTOfficial ?? false ) { - $card .= " -
    -
    ".tr("OFFICIAL")."
    -
    - "; - } elseif ( $Beta ) { - $card .= " -
    -
    ".tr("BETA")."
    -
    - "; - }/* elseif ( $RecommendedDate ) { - $card .= " -
    -
    -
    - "; - } */ elseif ( $Trusted ) { - $card .= " -
    -
    ".tr("Digitally Signed")."
    -
    - "; - } - return str_replace(["\t","\n"],"",$card); + $descClass= $RepositoryTemplate ? "cardDescriptionRepo" : "cardDescription"; + $card .= "
    $Overview
    "; + if ( $RecommendedDate ) { + $card .= " +
    +
    Spotlight
    +
    ".tr(date("M Y",$RecommendedDate),0)."
    +
    + "; + } + $card .= "
    "; + if ( $Installed || $Uninstall ) { + $flagTextStart = tr("Installed")."
    "; + $flagTextEnd = ""; + } else { + $flagTextStart = " "; + $flagTextEnd = " "; + } + if ( $UpdateAvailable ) { + $card .= " +
    +
    ".tr("UPDATED")."
    +
    "; + } elseif ( ($Installed || $Uninstall) && !$actionCentre) { + $card .= " +
    +
      ".tr("INSTALLED")."  
    +
    "; + } elseif ( $Blacklist ) { + $card .= " +
    +
    ".tr("Blacklisted")."$flagTextEnd
    +
    + "; + } elseif ( $caTemplateExists ) { + $card .= " +
    +
    ".tr("Template Exists")."
    +
    + "; + } elseif ( isset($Compatible) && ! $Compatible ) { + $verMsg = $VerMessage ?? tr("This application is not compatible with your version of Unraid"); + $card .= " +
    +
    $flagTextStart".tr("Incompatible")."$flagTextEnd
    +
    + "; + } elseif ( $Deprecated ) { + $card .= " +
    +
    ".tr("Deprecated")."$flagTextEnd
    +
    + "; + } elseif ( $Official ) { + $card .= " +
    +
    ".tr("OFFICIAL")."
    +
    + "; + } elseif ( $LTOfficial ?? false ) { + $card .= " +
    +
    ".tr("OFFICIAL")."
    +
    + "; + } elseif ( $Beta ) { + $card .= " +
    +
    ".tr("BETA")."
    +
    + "; + }/* elseif ( $RecommendedDate ) { + $card .= " +
    +
    +
    + "; + } */ elseif ( $Trusted ) { + $card .= " +
    +
    ".tr("Digitally Signed")."
    +
    + "; + } + return str_replace(["\t","\n"],"",$card); } function displayPopup($template) { - global $caSettings, $caPaths; + global $caSettings, $caPaths; - extract($template); + extract($template); - if ( !$Private) { - $RepoName = str_replace("' Repository","",str_replace("'s Repository","",$Repo)); - $RepoName = str_replace("Repository","",$RepoName); - } else { - $RepoName = str_replace("' Repository","",str_replace("'s Repository","",$RepoName)); - $Repo = $RepoName; - } - if ( $RepoShort ) $RepoName = $RepoShort; + if ( !$Private) { + $RepoName = str_replace("' Repository","",str_replace("'s Repository","",$Repo)); + $RepoName = str_replace("Repository","",$RepoName); + } else { + $RepoName = str_replace("' Repository","",str_replace("'s Repository","",$RepoName)); + $Repo = $RepoName; + } + if ( $RepoShort ) $RepoName = $RepoShort; - $FirstSeen = ($FirstSeen < 1433649600 ) ? 1433000000 : $FirstSeen; - $DateAdded = tr(date("M j, Y",$FirstSeen),0); - $favRepoClass = ($caSettings['favourite'] == $Repo) ? "fav" : "nonfav"; - $card = " - +
    + "; - if (is_array($trends) && (count($trends) > 1) ){ - if ( $downloadtrend ) { - $card .= " -
    ".tr("Trends")."
    -
    Show: ".tr("Trend Per Month")."".tr("Downloads Per Month")."".tr("Total Downloads")."
    -
    -
    -
    -
    -
    - "; - } - } + if (is_array($trends) && (count($trends) > 1) ){ + if ( $downloadtrend ) { + $card .= " +
    ".tr("Trends")."
    +
    Show: ".tr("Trend Per Month")."".tr("Downloads Per Month")."".tr("Total Downloads")."
    +
    +
    +
    +
    +
    + "; + } + } - if ( isset($display_changes) ) { - $card .= " -
    ".tr("Change Log")."
    -
    $display_changelogMessage
    - - "; - } - $moderation = readJsonFile($caPaths['statistics']); - if ( isset($moderation['fixedTemplates'][$Repo][str_replace("library/","",$Repository)]) ) { - $card .= "
    ".tr("Template Errors")."
    "; - foreach ($moderation['fixedTemplates'][$Repo][str_replace("library/","",$Repository)] as $error) { - $card .= "
  • $error
  • "; - } - } - if ( ! $Plugin && ! $Language ){ - $card .= "

    ".tr("Note: All statistics are only gathered every 30 days")."
    "; - } - if ( $UpdateAvailable ) { - $card .= " -
    -
    ".tr("UPDATED")."
    - "; - } elseif ( $Beta ) { - $card .= " -
    -
    ".tr("BETA")."
    - "; - } elseif ( $Installed ) { - $card .= " -
    -
    ".tr("INSTALLED")."
    - "; - } + if ( isset($display_changes) ) { + $card .= " +
    ".tr("Change Log")."
    +
    $display_changelogMessage
    + + "; + } + $moderation = readJsonFile($caPaths['statistics']); + if ( isset($moderation['fixedTemplates'][$Repo][str_replace("library/","",$Repository)]) ) { + $card .= "
    ".tr("Template Errors")."
    "; + foreach ($moderation['fixedTemplates'][$Repo][str_replace("library/","",$Repository)] as $error) { + $card .= "
  • $error
  • "; + } + } + if ( ! $Plugin && ! $Language ){ + $card .= "

    ".tr("Note: All statistics are only gathered every 30 days")."
    "; + } + if ( $UpdateAvailable ) { + $card .= " +
    +
    ".tr("UPDATED")."
    + "; + } elseif ( $Beta ) { + $card .= " +
    +
    ".tr("BETA")."
    + "; + } elseif ( $Installed ) { + $card .= " +
    +
    ".tr("INSTALLED")."
    + "; + } - return $card; + return $card; } ?>