From bd5f5d794c58bfee80da424d029fc7d9d0c447ea Mon Sep 17 00:00:00 2001 From: Henry Gross-Hellsen <6283258+cowpod@users.noreply.github.com> Date: Wed, 13 Nov 2024 01:37:03 -0800 Subject: [PATCH] support multiple modloader types in one jar --- functions/modInfo.php | 532 +++++++++++++++++++--------------- functions/send_mods.php | 126 ++++++-- resources/js/page_lib-mods.js | 39 ++- 3 files changed, 427 insertions(+), 270 deletions(-) diff --git a/functions/modInfo.php b/functions/modInfo.php index dadf956..b43a1e1 100644 --- a/functions/modInfo.php +++ b/functions/modInfo.php @@ -18,7 +18,7 @@ private function getModTypes(string $filePath): array { // todo: check finfo to ensure it's actually a zip - error_log("getModTypes()"); + // error_log("getModTypes()"); assert (file_exists($filePath)); $has_fabric=FALSE; @@ -83,306 +83,356 @@ private function getModInfos(array $modTypes, string $filePath, string $fileName die ('{"status": "error", "message": "Could not open JAR file as ZIP"}'); } + // error_log('modtypes: '.json_encode($modTypes)); - if ($modTypes['neoforge']===TRUE) { // almost identical to forge - $raw = $zip->getFromName(NEOFORGE_INFO_PATH); - if ($raw === FALSE) { - error_log ('{"status": "error", "message": "Could not access info file from Neoforge mod."}'); - die ('{"status": "error", "message": "Could not access info file from Neoforge mod."}'); - } - - $toml = new Toml; - $parsed = $toml->parse($raw); - $mod_info['neoforge']=$mcmod_orig; + foreach (array_keys($modTypes) as $modtype) { - // there can be multiple mods entries, we are just getting the first. - foreach ($parsed['mods'] as $mod) { - if (empty($mod['modId'])) { - error_log ('{"status": "error", "message": "Missing modId!"}'); - die ('{"status": "error", "message": "Missing modId!"}'); - } else { - $mod_info['neoforge']['modid'] = strtolower($mod['modId']); + if ($modtype=='neoforge' && $modTypes['neoforge']===TRUE) { // almost identical to forge + $raw = $zip->getFromName(NEOFORGE_INFO_PATH); + if ($raw === FALSE) { + error_log ('{"status": "error", "message": "Neoforge: Could not access info file from Neoforge mod."}'); + // die ('{"status": "error", "message": "Could not access info file from Neoforge mod."}'); + $mod_info['neoforge']=null; + array_push($this->warn, 'Neoforge: could not access info file'); + continue; } - if (empty($mod['version']) || $mod['version']=='${file.jarVersion}') { - $matches=[]; - $patchedversion=''; - if (!empty($fileName) && preg_match("/-([0-9a-z\-\.]+)$/", str_replace('.jar','',$fileName), $matches)) { - if (!empty($matches[1])) { - $mod_info['neoforge']['version'] = $matches[1]; + + $toml = new Toml; + $parsed = $toml->parse($raw); + $mod_info['neoforge']=$mcmod_orig; + + // there can be multiple mods entries, we are just getting the first. + if (!empty($parsed['mods'])) { + $maxcount=sizeof($parsed['mods']); + foreach ($parsed['mods'] as $mod) { + $maxcount-=1; + if (empty($mod['modId'])) { + error_log ('{"status": "error", "message": "Neoforge: Missing modId!"}'); + // die ('{"status": "error", "message": "Missing modId!"}'); + if ($maxcount==0) { + array_push($this->warn, 'Neoforge: missing modId'); + $mod_info['neoforge']=null; + } + continue; // maybe next one? } else { - array_push($this->warn, 'Missing version!'); - $mod_info['neoforge']['version'] = ''; + $mod_info['neoforge']['modid'] = strtolower($mod['modId']); } - } else { - array_push($this->warn, 'Missing version!'); - $mod_info['neoforge']['version'] = ''; + if (empty($mod['version']) || $mod['version']=='${file.jarVersion}') { + $matches=[]; + $patchedversion=''; + if (!empty($fileName) && preg_match("/-([0-9a-z\-\.]+)$/", str_replace('.jar','',$fileName), $matches)) { + if (!empty($matches[1])) { + $mod_info['neoforge']['version'] = $matches[1]; + } else { + array_push($this->warn, 'Missing version!'); + $mod_info['neoforge']['version'] = ''; + } + } else { + array_push($this->warn, 'Missing version!'); + $mod_info['neoforge']['version'] = ''; + } + } else { + $mod_info['neoforge']['version'] = $mod['version']; + } + if (!empty($mod['displayName'])) + $mod_info['neoforge']['name'] = $mod['displayName']; + if (!empty($mod['displayURL'])) + $mod_info['neoforge']['url'] = $mod['displayURL']; + if (!empty($mod['credits'])) + $mod_info['neoforge']['credits'] = $mod['credits']; + if (!empty($mod['authors'])) + $mod_info['neoforge']['authors'] = $mod['authors']; + if (!empty($mod['description'])) { + $mod_info['neoforge']['description'] = $mod['description']; + } + break; } - } else { - $mod_info['neoforge']['version'] = $mod['version']; } - if (!empty($mod['displayName'])) - $mod_info['neoforge']['name'] = $mod['displayName']; - if (!empty($mod['displayURL'])) - $mod_info['neoforge']['url'] = $mod['displayURL']; - if (!empty($mod['credits'])) - $mod_info['neoforge']['credits'] = $mod['credits']; - if (!empty($mod['authors'])) - $mod_info['neoforge']['authors'] = $mod['authors']; - if (!empty($mod['description'])) - $mod_info['neoforge']['description'] = $mod['description']; - break; - } - // handle dependencies and get mcversion, sometimes there can be none. - if (!empty($parsed['dependencies']) && !empty($parsed['dependencies'][$mod_info['neoforge']['modid']])) { - // each dependency is an indexed array entry. - foreach ($parsed['dependencies'][$mod_info['neoforge']['modid']] as $dep) { - if (empty($dep['modId'])) - continue; - if (strtolower($dep['modId'])=='minecraft') { - $mod_info['neoforge']['mcversion'] = $dep['versionRange']; + // handle dependencies and get mcversion, sometimes there can be none. + if (!empty($parsed['dependencies']) && !empty($parsed['dependencies'][$mod_info['neoforge']['modid']])) { + // each dependency is an indexed array entry. + foreach ($parsed['dependencies'][$mod_info['neoforge']['modid']] as $dep) { + if (empty($dep['modId'])) + continue; + if (strtolower($dep['modId'])=='minecraft') { + $mod_info['neoforge']['mcversion'] = $dep['versionRange']; + } + array_push($mod_info['neoforge']['dependencies'], strtolower($dep['modId'])); } - array_push($mod_info['neoforge']['dependencies'], strtolower($dep['modId'])); } - } - if (empty($mod_info['neoforge']['mcversion'])) { - array_push($this->warn, 'Missing mcversion!'); - } + if (empty($mod_info['neoforge']['mcversion'])) { + array_push($this->warn, 'Missing mcversion!'); + } - $mod_info['neoforge']['loadertype'] = 'neoforge'; - if (empty($parsed['loaderVersion'])) { - error_log ('{"status": "error", "message": "Missing loaderVersion!"}'); - die ('{"status": "error", "message": "Missing loaderVersion!"}'); - } else { - $mod_info['neoforge']['loaderversion'] = $parsed['loaderVersion']; - } - if (!empty($parsed['license'])) - $mod_info['neoforge']['license'] = $parsed['license']; - } + $mod_info['neoforge']['loadertype'] = 'neoforge'; + if (empty($parsed['loaderVersion'])) { + error_log ('{"status": "error", "message": "Neoforge: Missing loaderVersion!"}'); + // die ('{"status": "error", "message": "Missing loaderVersion!"}'); + $mod_info['neoforge']=null; + array_push($this->warn, 'Neoforge: Missing loaderVersion'); + continue; + } else { + $mod_info['neoforge']['loaderversion'] = $parsed['loaderVersion']; + } + if (!empty($parsed['license'])) + $mod_info['neoforge']['license'] = $parsed['license']; - if ($modTypes['forge']===TRUE) { // almostidentical to neoforge - $raw = $zip->getFromName(FORGE_INFO_PATH); - if ($raw === FALSE) { - error_log ('{"status": "error", "message": "Could not access info file from Forge mod."}'); - die ('{"status": "error", "message": "Could not access info file from Forge mod."}'); + // error_log("modTypes- Neoforge added"); } - $toml = new Toml; - $parsed = $toml->parse($raw); - $mod_info['forge']=$mcmod_orig; - - // there can be multiple mods entries, we are just getting the first. - foreach ($parsed['mods'] as $mod) { - if (empty($mod['modId'])) { - error_log ('{"status": "error", "message": "Missing modId!"}'); - die ('{"status": "error", "message": "Missing modId!"}'); - } else { - $mod_info['forge']['modid'] = strtolower($mod['modId']); + if ($modtype=='forge' && $modTypes['forge']===TRUE) { // almostidentical to neoforge + $raw = $zip->getFromName(FORGE_INFO_PATH); + if ($raw === FALSE) { + error_log ('{"status": "error", "message": "Forge: Could not access info file from Forge mod."}'); + // die ('{"status": "error", "message": "Could not access info file from Forge mod."}'); + $mod_info['forge']=null; + array_push($this->warn, 'Forge: could not access info file'); + continue; } - if (empty($mod['version']) || $mod['version']=='${file.jarVersion}') { - $matches=[]; - $patchedversion=''; - if (!empty($fileName) && preg_match("/-([0-9a-z\-\.]+)$/", str_replace('.jar','',$fileName), $matches)) { - if (!empty($matches[1])) { - $mod_info['forge']['version'] = $matches[1]; + + $toml = new Toml; + $parsed = $toml->parse($raw); + $mod_info['forge']=$mcmod_orig; + + if (!empty($parsed['mods'])) { + // there can be multiple mods entries, we are just getting the first. + $maxcount=sizeof($parsed['mods']); + foreach ($parsed['mods'] as $mod) { + $maxcount-=1; + if (empty($mod['modId'])) { + error_log ('{"status": "error", "message": "Forge: Missing modId!"}'); + // die ('{"status": "error", "message": "Missing modId!"}'); + if ($maxcount==0) { + $mod_info['forge']=null; + array_push($this->warn, 'Forge: missing modId'); + } + continue; // maybe next one? } else { - array_push($this->warn, 'Missing version!'); - $mod_info['forge']['version'] = ''; + $mod_info['forge']['modid'] = strtolower($mod['modId']); } - } else { - array_push($this->warn, 'Missing version!'); - $mod_info['forge']['version'] = ''; + if (empty($mod['version']) || $mod['version']=='${file.jarVersion}') { + $matches=[]; + $patchedversion=''; + if (!empty($fileName) && preg_match("/-([0-9a-z\-\.]+)$/", str_replace('.jar','',$fileName), $matches)) { + if (!empty($matches[1])) { + $mod_info['forge']['version'] = $matches[1]; + } else { + array_push($this->warn, 'Missing version!'); + $mod_info['forge']['version'] = ''; + } + } else { + array_push($this->warn, 'Missing version!'); + $mod_info['forge']['version'] = ''; + } + } else { + $mod_info['forge']['version'] = $mod['version']; + } + if (!empty($mod['displayName'])) + $mod_info['forge']['name'] = $mod['displayName']; + if (!empty($mod['displayURL'])) + $mod_info['forge']['url'] = $mod['displayURL']; + if (!empty($mod['credits'])) + $mod_info['forge']['credits'] = $mod['credits']; + if (!empty($mod['authors'])) + $mod_info['forge']['authors'] = $mod['authors']; + if (!empty($mod['description'])) + $mod_info['forge']['description'] = $mod['description']; + break; } - } else { - $mod_info['forge']['version'] = $mod['version']; } - if (!empty($mod['displayName'])) - $mod_info['forge']['name'] = $mod['displayName']; - if (!empty($mod['displayURL'])) - $mod_info['forge']['url'] = $mod['displayURL']; - if (!empty($mod['credits'])) - $mod_info['forge']['credits'] = $mod['credits']; - if (!empty($mod['authors'])) - $mod_info['forge']['authors'] = $mod['authors']; - if (!empty($mod['description'])) - $mod_info['forge']['description'] = $mod['description']; - break; - } - // handle dependencies and get mcversion, sometimes there can be none. - if (!empty($parsed['dependencies']) && !empty($parsed['dependencies'][$mod_info['forge']['modid']])) { - // each dependency is an indexed array entry. - foreach ($parsed['dependencies'][$mod_info['forge']['modid']] as $dep) { - if (empty($dep['modId'])) - continue; - if (strtolower($dep['modId'])=='minecraft') { - $mod_info['forge']['mcversion'] = $dep['versionRange']; + // handle dependencies and get mcversion, sometimes there can be none. + if (!empty($parsed['dependencies']) && !empty($parsed['dependencies'][$mod_info['forge']['modid']])) { + // each dependency is an indexed array entry. + foreach ($parsed['dependencies'][$mod_info['forge']['modid']] as $dep) { + if (empty($dep['modId'])) + continue; + if (strtolower($dep['modId'])=='minecraft') { + $mod_info['forge']['mcversion'] = $dep['versionRange']; + } + array_push($mod_info['forge']['dependencies'], strtolower($dep['modId'])); } - array_push($mod_info['forge']['dependencies'], strtolower($dep['modId'])); } - } - if (empty($mod_info['forge']['mcversion'])) { - array_push($this->warn, 'Missing mcversion!'); - } + if (empty($mod_info['forge']['mcversion'])) { + array_push($this->warn, 'Missing mcversion!'); + } - $mod_info['forge']['loadertype'] = 'forge'; - if (empty($parsed['loaderVersion'])) { - error_log ('{"status": "error", "message": "Missing loaderVersion!"}'); - die ('{"status": "error", "message": "Missing loaderVersion!"}'); - } else { - $mod_info['forge']['loaderversion'] = $parsed['loaderVersion']; + $mod_info['forge']['loadertype'] = 'forge'; + if (empty($parsed['loaderVersion'])) { + error_log ('{"status": "error", "message": "Forge: Missing loaderVersion!"}'); + // die ('{"status": "error", "message": "Missing loaderVersion!"}'); + $mod_info['forge']=null; + array_push($this->warn, 'Forge: missing loaderVersion'); + continue; + } else { + $mod_info['forge']['loaderversion'] = $parsed['loaderVersion']; + } + if (!empty($parsed['license'])) + $mod_info['forge']['license'] = $parsed['license']; + // error_log("modTypes- Forge added"); } - if (!empty($parsed['license'])) - $mod_info['forge']['license'] = $parsed['license']; - } - if ($modTypes['forge_old']===TRUE) { + if ($modtype=='forge_old' && $modTypes['forge_old']===TRUE) { - $raw = $zip->getFromName(FORGE_OLD_INFO_PATH); - if ($raw === FALSE) { - error_log ('{"status": "error", "message": "Could not access info file from Old Forge mod."}'); - die ('{"status": "error", "message": "Could not access info file from Old Forge mod."}'); - } + $raw = $zip->getFromName(FORGE_OLD_INFO_PATH); + if ($raw === FALSE) { + error_log ('{"status": "error", "message": "Forge_Old: Could not access info file from Old Forge mod."}'); + // die ('{"status": "error", "message": "Could not access info file from Old Forge mod."}'); + $mod_info['forge_old']=null; + array_push($this->warn, 'Forge Old: Could not access info file'); + continue; + } - $mod_info['forge_old']=$mcmod_orig; + $mod_info['forge_old']=$mcmod_orig; - // dictionary is nested in an array - $parsed = json_decode(preg_replace('/\r|\n/', '', trim($raw)), true)[0]; - if (empty($parsed['modid'])) { - error_log ('{"status": "error", "message": "Missing modid!"}'); - die ('{"status": "error", "message": "Missing modid!"}'); - } else { - $mod_info['forge_old']['modid'] = strtolower($parsed['modid']); - } - if (empty($parsed['version']) || $parsed['version']=='${file.jarVersion}') { - // array_push($this->warn, 'Missing version!'); - $matches=[]; - $patchedversion=''; - if (preg_match("/-([0-9a-z\-\.]+)$/", str_replace('.jar','',$fileName), $matches)) { - if (!empty($matches[1])) { - $mod_info['old_forge']['version'] = $matches[1]; + // dictionary is nested in an array + $parsed = json_decode(preg_replace('/\r|\n/', '', trim($raw)), true)[0]; + if (empty($parsed['modid'])) { + error_log ('{"status": "error", "message": "Forge_Old: Missing modid!"}'); + // die ('{"status": "error", "message": "Missing modid!"}'); + array_push($this->warn, 'Forge Old: missing modId'); + $mod_info['forge_old']=null; + continue; + } else { + $mod_info['forge_old']['modid'] = strtolower($parsed['modid']); + } + if (empty($parsed['version']) || $parsed['version']=='${file.jarVersion}') { + // array_push($this->warn, 'Missing version!'); + $matches=[]; + $patchedversion=''; + if (preg_match("/-([0-9a-z\-\.]+)$/", str_replace('.jar','',$fileName), $matches)) { + if (!empty($matches[1])) { + $mod_info['old_forge']['version'] = $matches[1]; + } else { + array_push($this->warn, 'Missing version!'); + $mod_info['old_forge']['version'] = ''; + } } else { array_push($this->warn, 'Missing version!'); $mod_info['old_forge']['version'] = ''; } } else { - array_push($this->warn, 'Missing version!'); - $mod_info['old_forge']['version'] = ''; + $mod_info['forge_old']['version'] = $parsed['version']; } - } else { - $mod_info['forge_old']['version'] = $parsed['version']; - } - if (!empty($parsed['name'])) - $mod_info['forge_old']['name'] = $parsed['name']; - if (!empty($parsed['url'])) - $mod_info['forge_old']['url'] = $parsed['url']; - if (!empty($parsed['credits'])) - $mod_info['forge_old']['credits'] = $parsed['credits']; - if (!empty($parsed['authorList'])) - $mod_info['forge_old']['authors'] = implode(', ', $parsed['authorList']); - if (!empty($parsed['description'])) - $mod_info['forge_old']['description'] = $parsed['description']; - if (!empty($parsed['mcversion'])) - $mod_info['forge_old']['mcversion']=$parsed['mcversion']; - else { - array_push($this->warn, 'Missing mcversion!'); - // error_log('{"status": "warn", "message": "Missing mcversion!"}'); - } - - // each dependency is a string - if (array_key_exists('dependencies', $parsed)) { - foreach ($parsed['dependencies'] as $dep) { - if (empty($dep)) - continue; - array_push($mod_info['forge_old']['dependencies'], strtolower($dep));; + if (!empty($parsed['name'])) + $mod_info['forge_old']['name'] = $parsed['name']; + if (!empty($parsed['url'])) + $mod_info['forge_old']['url'] = $parsed['url']; + if (!empty($parsed['credits'])) + $mod_info['forge_old']['credits'] = $parsed['credits']; + if (!empty($parsed['authorList'])) + $mod_info['forge_old']['authors'] = implode(', ', $parsed['authorList']); + if (!empty($parsed['description'])) + $mod_info['forge_old']['description'] = $parsed['description']; + if (!empty($parsed['mcversion'])) + $mod_info['forge_old']['mcversion']=$parsed['mcversion']; + else { + array_push($this->warn, 'Missing mcversion!'); + error_log('{"status": "warn", "message": "Forge_Old: Missing mcversion!"}'); } - } - $mod_info['forge_old']['loadertype']='forge'; // same - // no loaderversion - // no license - } + // each dependency is a string + if (array_key_exists('dependencies', $parsed)) { + foreach ($parsed['dependencies'] as $dep) { + if (empty($dep)) + continue; + array_push($mod_info['forge_old']['dependencies'], strtolower($dep));; + } + } - if ($modTypes['fabric']===TRUE) { - $raw = $zip->getFromName(FABRIC_INFO_PATH); - if ($raw === FALSE) { - error_log ('{"status": "error", "message": "Could not access info file from Fabric mod."}'); - die ('{"status": "error", "message": "Could not access info file from Fabric mod."}'); + $mod_info['forge_old']['loadertype']='forge'; // same + // no loaderversion + // no license + // error_log("modTypes- Forge Old added"); } - $mod_info['fabric']=$mcmod_orig; - $parsed = json_decode(preg_replace('/\r|\n/', '', trim($raw)), true); + if ($modtype=='fabric' && $modTypes['fabric']===TRUE) { + $raw = $zip->getFromName(FABRIC_INFO_PATH); + if ($raw === FALSE) { + error_log ('{"status": "error", "message": "Fabric: Could not access info file from Fabric mod."}'); + // die ('{"status": "error", "message": "Could not access info file from Fabric mod."}'); + $mod_info['fabric']=null; + array_push($this->warn, 'Fabric: could not access info file'); + continue; + } - if (empty($parsed['id'])) { - error_log ('{"status": "error", "message": "Missing id!"}'); - die ('{"status": "error", "message": "Missing id!"}'); - } else { - $mod_info['fabric']['modid'] = $parsed['id']; - } - if (empty($parsed['version'])) { - array_push($this->warn, 'Missing version!'); - // error_log('{"status": "warn", "message": "Missing version!"}'); - $mod_info['fabric']['version'] = ''; - } else{ - $mod_info['fabric']['version'] = $parsed['version']; - } - if (!empty($parsed['name'])) - $mod_info['fabric']['name'] = $parsed['name']; - if (!empty($parsed['contact']) && !empty($parsed['contact']['homepage'])) - $mod_info['fabric']['url'] = $parsed['contact']['homepage']; - // no credits - if (!empty($parsed['authors'])) - $mod_info['fabric']['authors'] = implode(', ', $parsed['authors']); - if (!empty($parsed['description'])) - $mod_info['fabric']['description'] = $parsed['description']; - - // each dependency is a key=value entry. - if (array_key_exists('depends', $parsed)) { - foreach (array_keys($parsed['depends']) as $depId) { - $dep_version = '*'; // default to any - if (!empty($parsed['depends'][$depId])) { - $dep_version = fabric_to_interval_range($parsed['depends'][$depId]); - } + $mod_info['fabric']=$mcmod_orig; + $parsed = json_decode(preg_replace('/\r|\n/', '', trim($raw)), true); + + if (empty($parsed['id'])) { + error_log ('{"status": "error", "message": "Fabric: Missing id!"}'); + // die ('{"status": "error", "message": "Missing id!"}'); + $mod_info['fabric']=null; + array_push($this->warn, 'Fabric: missing id'); + continue; + } else { + $mod_info['fabric']['modid'] = $parsed['id']; + } + if (empty($parsed['version'])) { + array_push($this->warn, 'Missing version!'); + error_log('{"status": "warn", "message": "Fabric: Missing version!"}'); + $mod_info['fabric']['version'] = ''; + } else{ + $mod_info['fabric']['version'] = $parsed['version']; + } + if (!empty($parsed['name'])) + $mod_info['fabric']['name'] = $parsed['name']; + if (!empty($parsed['contact']) && !empty($parsed['contact']['homepage'])) + $mod_info['fabric']['url'] = $parsed['contact']['homepage']; + // no credits + if (!empty($parsed['authors'])) + $mod_info['fabric']['authors'] = implode(', ', $parsed['authors']); + if (!empty($parsed['description'])) + $mod_info['fabric']['description'] = $parsed['description']; + + // each dependency is a key=value entry. + if (array_key_exists('depends', $parsed)) { + foreach (array_keys($parsed['depends']) as $depId) { + $dep_version = '*'; // default to any + if (!empty($parsed['depends'][$depId])) { + $dep_version = fabric_to_interval_range($parsed['depends'][$depId]); + } - array_push($mod_info['fabric']['dependencies'], $dep_version); + array_push($mod_info['fabric']['dependencies'], $dep_version); - if (strtolower($depId)=='minecraft') { - $mod_info['fabric']['mcversion']=$dep_version; - } - if (strtolower($depId)=='fabricloader') { - $mod_info['fabric']['loaderversion']=$dep_version; + if (strtolower($depId)=='minecraft') { + $mod_info['fabric']['mcversion']=$dep_version; + } + if (strtolower($depId)=='fabricloader') { + $mod_info['fabric']['loaderversion']=$dep_version; + } } } - } - if (empty($mod_info['fabric']['mcversion'])) { - array_push($this->warn, 'Missing mcversion!'); - // error_log('{"status": "warn", "message": "Missing mcversion!"}'); - } + if (empty($mod_info['fabric']['mcversion'])) { + array_push($this->warn, 'Missing mcversion!'); + error_log('{"status": "warn", "message": "Fabric: Missing mcversion!"}'); + } - $mod_info['fabric']['loadertype']='fabric'; + $mod_info['fabric']['loadertype']='fabric'; - if (!empty($parsed['license'])) - $mod_info['fabric']['license'] = $parsed['license']; + if (!empty($parsed['license'])) + $mod_info['fabric']['license'] = $parsed['license']; + // error_log("modTypes- Fabric added"); + } } + // error_log("MOD_INFO: ".json_encode($mod_info,JSON_UNESCAPED_SLASHES)); return $mod_info; } + public function getWarnings() { return $this->warn; } + public function getModInfo(string $filePath, $fileName) { // return first mod detected $mod_types = $this->getModTypes($filePath); $mod_infos = $this->getModInfos($mod_types, $filePath, $fileName); - foreach (array_keys($mod_infos) as $k) { - if (!empty($mod_infos[$k])) { - return $mod_infos[$k]; - } - } - return []; + return $mod_infos; } } ?> \ No newline at end of file diff --git a/functions/send_mods.php b/functions/send_mods.php index 2273830..7346c93 100644 --- a/functions/send_mods.php +++ b/functions/send_mods.php @@ -15,8 +15,55 @@ require_once("db.php"); // fiels = name of input in index.php -$file_name = $_FILES["fiels"]["name"]; -$file_tmp = $_FILES["fiels"]["tmp_name"]; + +// download from given _POST data +// todo: download directly to disk or buffer +if (isset($_FILES['fiels']) && isset($_FILES["fiels"]["name"]) && isset($_FILES["fiels"]["tmp_name"])) { + $file_name = $_FILES["fiels"]["name"]; + $file_tmp = $_FILES["fiels"]["tmp_name"]; +} else { + // only accept url to a JAR file. + if (isset($_POST['url'])) { + if (preg_match('/^(https?:\/\/)([a-zA-Z0-9-.]+)([a-zA-Z0-9\-\_\.\~\/\:\@\&\=\+\$\,\;\?\#\%]+)$/', $_POST['url'])) { + $apiversiondata = json_decode(file_get_contents('../api/version.json'),true); + if (!$apiversiondata) { + die('{"status":"error","message": "could not get solder version"}'); + } + $apiversion=$apiversiondata['version']; + + $options = [ + 'http' => [ + 'method' => 'GET', + 'header' => 'User-Agent: TheGameSpider/TechnicSolder/'.$apiversion.' (Download to package mod into ZIP)\r\nContent-Type: application/json' + ] + ]; + $context = stream_context_create($options); + @$getfile = file_get_contents($_POST['url'], false, $context); + if ($getfile && strlen($getfile)>0) { + if (!empty($_POST['filename']) && preg_match('/^[a-zA-Z0-9_\-\.\(\)\[\]\s\!\?\#\@\&\*\=\+\~\s]+.jar$/', $_POST['filename'])) { + $file_name = $_POST['filename']; + error_log('using given name: '.$file_name); + } else { + $file_name = bin2hex(random_bytes(32)).'.jar'; + error_log("using random name: {$file_name}, invalid name given: {$_POST['filename']}"); + } + $file_tmp = sys_get_temp_dir().'/'.bin2hex(random_bytes(32)).'.jar'; + @$putfile = file_put_contents($file_tmp, $getfile); + if ($putfile) { + error_log('file downloaded to '.$file_tmp); + } else { + die('{"status":"error","message":"Could not save file"}'); + } + } else { + die('{"status":"error","message":"Could not download file"}'); + } + } else { + die('{"status":"error","message":"Invalid URL (not a JAR?)"}'); + } + } else { + die('{"status":"error","message":"No file uploaded."}'); + } +} if (empty($file_tmp)) { error_log ('{"status":"error","message":"File is too big! Check your post_max_size (current value '.ini_get('post_max_size').') and upload_max_filesize (current value '.ini_get('upload_max_filesize').') values in '.php_ini_loaded_file().'"}'); @@ -97,7 +144,7 @@ function processFile(string $filePath, string $fileName, array $modinfo): int { $zip_size= filesize($mod_zip_path); $mcvrange = parse_interval_range($modinfo['mcversion']); - + // error_log('adding mod of loadertype='.$modinfo['loadertype']); $addq = $db->execute("INSERT INTO `mods` (`name`,`pretty_name`,`md5`,`url`,`link`,`author`,`description`,`version`,`mcversion`,`filename`,`type`,`loadertype`,`filesize`) VALUES ( '{$db->sanitize($modinfo['modid'])}', '{$db->sanitize($modinfo['name'])}', @@ -131,61 +178,94 @@ function processFile(string $filePath, string $fileName, array $modinfo): int { } $mi = new modInfo(); -$modinfo = $mi->getModInfo($file_tmp, $file_name); +$modinfos = $mi->getModInfo($file_tmp, $file_name); +error_log(json_encode($modinfos)); -// we only care about the first mod. -// todo: in delete modv, add a check to see if the file is used by another mod entry. -// ie. same file for both forge and fabric loader types! $added_ids=[]; $added_modids=[]; -// foreach ($modInfos as $modinfo) { +$added_authors=[]; +$added_pretty_names=[]; +$added_versions=[]; +$added_mcversions=[]; +$num_mods_to_add=sizeof($modinfos); + +$warn = $mi->getWarnings(); +$num_already_added=0; +$num_process_failed=0; + +foreach ($modinfos as $modinfo) { if (empty($modinfo)) { - error_log('{"status":"error","message":"Unable to add mod to database (empty).", "name": "'.$file_name.'"}'); - die('{"status":"error","message":"Unable to add mod to database (empty).", "name": "'.$file_name.'"}'); - // continue; + $num_mods_to_add = $num_mods_to_add-1; + // error_log('{"status":"error","message":"Unable to add mod to database (empty).", "name": "'.$file_name.'"}'); + // die('{"status":"error","message":"Unable to add mod to database (empty).", "name": "'.$file_name.'"}'); + continue; } - // if we have another mod of same version, name, mcversion, type, loadertype - $query_mod_exists = $db->query("SELECT id,name FROM mods WHERE version = '".$db->sanitize($modinfo['version'])."' AND name = '".$db->sanitize($modinfo['modid'])."' AND mcversion = '".$db->sanitize($modinfo['mcversion'])."' AND `type` = 'mod' AND `loadertype` = '".$db->sanitize($modinfo['loadertype'])."' LIMIT 1"); + // if we have another mod of same name, version, mcversion, type, loadertype + $query_mod_exists = $db->query("SELECT id,name FROM mods + WHERE name = '{$db->sanitize($modinfo['modid'])}' + AND version = '{$db->sanitize($modinfo['version'])}' + AND mcversion = '{$db->sanitize($modinfo['mcversion'])}' + AND type = 'mod' + AND loadertype = '{$db->sanitize($modinfo['loadertype'])}'"); + if ($query_mod_exists && sizeof($query_mod_exists)>0) { error_log('{"status": "info","message":"Mod already in database!","modid":"'.$query_mod_exists[0]['id'].'","name":"'.$query_mod_exists[0]['name'].'"}'); - die('{"status": "info","message":"Mod already in database!","modid":"'.$query_mod_exists[0]['id'].'","name":"'.$query_mod_exists[0]['name'].'"}'); + if ($num_mods_to_add==1) { + die('{"status": "info","message":"Mod already in database!","modid":"'.$query_mod_exists[0]['id'].'","name":"'.$query_mod_exists[0]['name'].'"}'); + } else { + array_push($warn, 'Mod already in database (#'.$num_mods_to_add.')'); + $num_already_added+=1; + continue; + } } // consequence: we allow multiple loadertypes (ie fabric, forge) of the exact same mod $result_mod_id = processFile($file_tmp, $file_name, $modinfo); if ($result_mod_id === -1) { error_log('{"status":"error","message":"Unable to add mod to database (-1).", "name": "'.$file_name.'"}'); - die('{"status":"error","message":"Unable to add mod to database (-1).", "name": "'.$file_name.'"}'); + if ($num_mods_to_add==1) { + die('{"status":"error","message":"Unable to add mod to database (-1).", "name": "'.$file_name.'"}'); + } else { + array_push($warn, 'Unable to add mod to database -1 (#'.$num_mods_to_add.')'); + $num_process_failed+=1; + continue; + } } else { error_log('Successfully added modid='.$modinfo['modid'].' id='.$result_mod_id.' to database!'); + error_log(json_encode($modinfo)); array_push($added_modids, $modinfo['modid']); array_push($added_ids, $result_mod_id); + array_push($added_authors, $modinfo['authors']); + array_push($added_pretty_names, $modinfo['name']); + array_push($added_versions, $modinfo['version']); + array_push($added_mcversions, $modinfo['mcversion']); } -// } +} $db->disconnect(); // error_log(json_encode($added_ids)); -if (sizeof($added_ids)==0) { - error_log('{"status":"error","message":"Unable to add mod to database.", "name": "'.$file_name.'"}'); - die('{"status":"error","message":"Unable to add mod to database.", "name": "'.$file_name.'"}'); +if (sizeof($added_ids)+$num_already_added+$num_process_failed==0) { + error_log('{"status":"error","message":"Unable to add mod to database."}'); + die('{"status":"error","message":"Unable to add mod to database."}'); } +$moredata='"modid":'.json_encode($added_ids,JSON_UNESCAPED_SLASHES).',"name":'.json_encode($added_modids,JSON_UNESCAPED_SLASHES).', "pretty_name": '.json_encode($added_pretty_names,JSON_UNESCAPED_SLASHES).', "author": '.json_encode($added_authors,JSON_UNESCAPED_SLASHES).',"mcversion":'.json_encode($added_mcversions,JSON_UNESCAPED_SLASHES).',"version": '.json_encode($added_versions,JSON_UNESCAPED_SLASHES); + // if we got warnings -$warn = $mi->getWarnings(); if (!empty($warn) && sizeof($warn)>0) { // accumulate them all into one, as we dont support displaying multiple seperate ones in index.php. $acc_message=''; foreach ($warn as $w) { $acc_message.=$w.' '; } - echo '{"status":"warn","message":"'.$acc_message.'Issue(s) must be addressed before using this mod."}'; + echo '{"status":"warn","message":"'.$acc_message.'Issue(s) must be addressed before using this mod.", '.$moredata.'}'; } else { // get the last one added. we don't support displaying multiple.. // todo: support displaying multiple in index.php // modid appears to be the id in the database, name appears to be modid... - error_log('{"status":"succ","message":"Mod added.","modid":'.$added_ids[sizeof($added_ids)-1].',"name":"'.$added_modids[sizeof($added_modids)-1].'"}'); - echo '{"status":"succ","message":"Mod added.","modid":'.$added_ids[sizeof($added_ids)-1].',"name":"'.$added_modids[sizeof($added_modids)-1].'"}'; + error_log('{"status":"succ","message":"Mod added.", '.$moredata.'}'); + die('{"status":"succ","message":"Mod added.", '.$moredata.'}'); } exit(); diff --git a/resources/js/page_lib-mods.js b/resources/js/page_lib-mods.js index dd48466..ade69ed 100644 --- a/resources/js/page_lib-mods.js +++ b/resources/js/page_lib-mods.js @@ -60,12 +60,12 @@ function sendFile(file, i) { $("#" + i).attr("id", i + "-done"); break; } - case "error": + case "info": { $("#cog-" + i).hide(); - $("#times-" + i).show(); + $("#inf-" + i).show(); $("#" + i).removeClass("progress-bar-striped progress-bar-animated"); - $("#" + i).addClass("bg-danger"); + $("#" + i).addClass("bg-success"); $("#info-" + i).text(response.message); $("#" + i).attr("id", i + "-done"); break; @@ -80,17 +80,44 @@ function sendFile(file, i) { $("#" + i).attr("id", i + "-done"); break; } - case "info": + case "error": { $("#cog-" + i).hide(); - $("#inf-" + i).show(); + $("#times-" + i).show(); $("#" + i).removeClass("progress-bar-striped progress-bar-animated"); - $("#" + i).addClass("bg-success"); + $("#" + i).addClass("bg-danger"); $("#info-" + i).text(response.message); $("#" + i).attr("id", i + "-done"); break; } } + let num_versions = response['modid'].length; + let author = response['author']; + let name = response['name']; + let pretty_name = response['pretty_name']; + let mcversion = response['mcversion']; + let version = response['version']; + // console.log(response['status']); + if (response['status']!="error") { + // console.log('add new row'); + let i=0; + // for (let id of response['modid']) { + $('#table-available-mods').append(` +