From 6d3a5bb42013be1b34974e65b0d00ecfb960b09c Mon Sep 17 00:00:00 2001 From: abbodi1406 <33669284+abbodi1406@users.noreply.github.com> Date: Sat, 6 Feb 2021 16:26:21 +0300 Subject: [PATCH] Add support for WCOS Windows 10X --- fetchupd.php | 26 +++++++-- get.php | 138 +++++++++++++++++++++++++++----------------- readme.md | 5 +- shared/main.php | 2 +- shared/packs.php | 14 ++++- shared/requests.php | 74 +++++++++++++++++++----- 6 files changed, 185 insertions(+), 74 deletions(-) diff --git a/fetchupd.php b/fetchupd.php index 6fcbadc..f6abed6 100644 --- a/fetchupd.php +++ b/fetchupd.php @@ -26,6 +26,7 @@ function uupFetchUpd( $build = 'latest', $minor = '0', $sku = '48', + $type = 'Production', $cacheRequests = 0 ) { uupApiPrintBrand(); @@ -84,7 +85,12 @@ function uupFetchUpd( $build = '10.0.'.$build.'.'.$minor; - $cacheHash = hash('sha256', strtolower("api-fetch-$arch-$ring-$flight-$build-$minor-$sku")); + $type = ucwords(strtolower($type)); + if(!($type == 'Production' || $type == 'Test')) { + $type = 'Production'; + } + + $cacheHash = hash('sha256', strtolower("api-fetch-$arch-$ring-$flight-$build-$minor-$sku-$type")); $cached = 0; if(file_exists('cache/'.$cacheHash.'.json.gz') && $cacheRequests == 1) { @@ -104,7 +110,7 @@ function uupFetchUpd( if(!$cached) { consoleLogger('Fetching information from the server...'); - $postData = composeFetchUpdRequest(uupDevice(), uupEncryptedData(), $arch, $flight, $ring, $build, $sku); + $postData = composeFetchUpdRequest(uupDevice(), uupEncryptedData(), $arch, $flight, $ring, $build, $sku, $type); $out = sendWuPostRequest('https://fe3cr.delivery.mp.microsoft.com/ClientWebService/client.asmx', $postData); $out = html_entity_decode($out); @@ -141,7 +147,7 @@ function uupFetchUpd( $num++; consoleLogger("Checking build information for update {$num} of {$updatesNum}..."); - $info = parseFetchUpdate($val, $out, $arch, $ring, $flight, $build, $sku); + $info = parseFetchUpdate($val, $out, $arch, $ring, $flight, $build, $sku, $type); if(isset($info['error'])) { $errorCount++; continue; @@ -165,7 +171,7 @@ function uupFetchUpd( ); } -function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku) { +function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku, $type) { $updateNumId = preg_replace('/|<\/ID>.*/i', '', $updateInfo); $updates = preg_replace('//', "\n", $out); @@ -193,7 +199,7 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku $foundArch = @strtolower($info[2]); $foundBuild = @$info[3]; - if((!$foundArch)) { + if(!isset($foundArch) || empty($foundArch)) { preg_match('/ProductReleaseInstalled Name\="(.*?)\.(.*?)" Version\="10\.0\.(.*?)"/', $updateInfo, $info); $foundType = @strtolower($info[1]); $foundArch = @strtolower($info[2]); @@ -213,6 +219,9 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku $updateTitle = 'Windows 10 build '.$foundBuild; } + if($foundType == 'hololens' || $foundType == 'wcosdevice0') + $updateTitle = preg_replace('/ for .{3,5}-based/i', ' for', $updateTitle); + $isCumulativeUpdate = 0; if(preg_match('/\d{4}-\d{2}.+Update|Cumulative Update|Microsoft Edge|Windows Feature Experience Pack/i', $updateTitle)) { $isCumulativeUpdate = 1; @@ -227,6 +236,9 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku if($foundType == 'sedimentpack') $updateTitle = $updateTitle.' - KB4023057'; + if($foundType == 'hololens' || $foundType == 'wcosdevice0') + $updateTitle = $updateTitle.' - '.$type; + if(!preg_match("/$foundBuild/i", $updateTitle)) $updateTitle = $updateTitle.' ('.$foundBuild.')'; @@ -330,6 +342,10 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku $temp['containsCU'] = 1; } + if($foundType == 'hololens' || $foundType == 'wcosdevice0') { + $temp['releasetype'] = $type; + } + $temp['created'] = time(); $temp['files'] = $shaArray; diff --git a/get.php b/get.php index 41fd197..5b21736 100644 --- a/get.php +++ b/get.php @@ -88,15 +88,15 @@ function uupGetFiles( if($usePack) { $fileListSource = 'GENERATEDPACKS'; - $filesList = array(); + $filesPacksList = array(); foreach($genPack[$usePack] as $val) { foreach($val as $package) { - $filesList[] = $package; + $filesPacksList[] = $package; } } - array_unique($filesList); - sort($filesList); + array_unique($filesPacksList); + sort($filesPacksList); } break; @@ -109,13 +109,13 @@ function uupGetFiles( return array('error' => 'UNSUPPORTED_COMBINATION'); } - $filesList = $genPack[$usePack][$desiredEdition]; + $filesPacksList = $genPack[$usePack][$desiredEdition]; $fileListSource = 'GENERATEDPACKS'; break; } } else { $fileListSource = 'GENERATEDPACKS'; - $filesList = array(); + $filesPacksList = array(); foreach($desiredEdition as $edition) { $edition = strtoupper($edition); @@ -123,7 +123,7 @@ function uupGetFiles( return array('error' => 'UNSUPPORTED_COMBINATION'); } - $filesList = array_merge($filesList, $genPack[$usePack][$edition]); + $filesPacksList = array_merge($filesPacksList, $genPack[$usePack][$edition]); } } @@ -133,102 +133,117 @@ function uupGetFiles( $updateId = preg_replace('/_rev\..*/', '', $updateId); } + $updateSku = $info['sku']; $updateArch = (isset($info['arch'])) ? $info['arch'] : 'UNKNOWN'; $updateBuild = (isset($info['build'])) ? $info['build'] : 'UNKNOWN'; $updateName = (isset($info['title'])) ? $info['title'] : 'Unknown update: '.$updateId; + if(isset($info['releasetype'])) { + $type = $info['releasetype']; + } + if(!isset($type)) { + $type = 'Production'; + if($updateSku == 189 || $updateSku == 135) foreach($info['files'] as $val) { + if(preg_match('/NonProductionFM/i', $val['name'])) $type = 'Test'; + } + } + if($requestType < 2) { - $files = uupGetOnlineFiles($updateId, $rev, $info, $requestType); + $filesInfoList = uupGetOnlineFiles($updateId, $rev, $info, $requestType, $type); } else { - $files = uupGetOfflineFiles($info); + $filesInfoList = uupGetOfflineFiles($info); } - if(isset($files['error'])) { - return $files; + if(isset($filesInfoList['error'])) { + return $filesInfoList; } - $baseless = preg_grep('/^baseless_|-baseless\....$/i', array_keys($files)); + $baseless = preg_grep('/^baseless_|-baseless\....$/i', array_keys($filesInfoList)); foreach($baseless as $val) { - if(isset($files[$val])) unset($files[$val]); + if(isset($filesInfoList[$val])) unset($filesInfoList[$val]); } - $diffs = preg_grep('/.*_Diffs_.*|.*_Forward_CompDB_.*|\.cbsu\.cab$/i', array_keys($files)); + $diffs = preg_grep('/.*_Diffs_.*|.*_Forward_CompDB_.*|\.cbsu\.cab$/i', array_keys($filesInfoList)); foreach($diffs as $val) { - if(isset($files[$val])) unset($files[$val]); + if(isset($filesInfoList[$val])) unset($filesInfoList[$val]); } - $psf = array_keys($files); + $psf = array_keys($filesInfoList); $psf = preg_grep('/\.psf$/i', $psf); $removeFiles = array(); foreach($psf as $val) { $name = preg_replace('/\.psf$/i', '', $val); $removeFiles[] = $name; - unset($files[$val]); + unset($filesInfoList[$val]); } unset($index, $name, $psf); $temp = preg_grep('/'.$updateArch.'_.*|arm64\.arm_.*|arm64\.x86_.*/i', $removeFiles); foreach($temp as $key => $val) { - if(isset($files[$val.'.cab'])) unset($files[$val.'.cab']); + if(isset($filesInfoList[$val.'.cab'])) unset($filesInfoList[$val.'.cab']); unset($removeFiles[$key]); } unset($temp); foreach($removeFiles as $val) { - if(isset($files[$val.'.esd'])) { - if(isset($files[$val.'.cab'])) unset($files[$val.'.cab']); + if(isset($filesInfoList[$val.'.esd'])) { + if(isset($filesInfoList[$val.'.cab'])) unset($filesInfoList[$val.'.cab']); } } unset($removeFiles); - $filesKeys = array_keys($files); + $filesInfoKeys = array_keys($filesInfoList); switch($fileListSource) { case 'UPDATEONLY': $skipPackBuild = 1; - $removeFiles = preg_grep('/Windows10\.0-KB.*-EXPRESS/i', $filesKeys); + $removeFiles = preg_grep('/Windows10\.0-KB.*-EXPRESS/i', $filesInfoKeys); foreach($removeFiles as $val) { - if(isset($files[$val])) unset($files[$val]); + if(isset($filesInfoList[$val])) unset($filesInfoList[$val]); } + unset($removeFiles); - unset($removeFiles, $temp); - $filesKeys = array_keys($files); + $filesInfoKeys = array_keys($filesInfoList); - $filesKeys = preg_grep('/Windows10\.0-KB/i', $filesKeys); - if(count($filesKeys) == 0) { + $filesInfoKeys = preg_grep('/Windows10\.0-KB/i', $filesInfoKeys); + if(count($filesInfoKeys) == 0) { return array('error' => 'NOT_CUMULATIVE_UPDATE'); } break; case 'WUBFILE': $skipPackBuild = 1; - $filesKeys = preg_grep('/WindowsUpdateBox.exe/i', $filesKeys); + $filesInfoKeys = preg_grep('/WindowsUpdateBox.exe/i', $filesInfoKeys); break; } + $uupCleanFunc = 'uupCleanName'; + if($updateSku == 189) $uupCleanFunc = 'uupCleanWCOS'; + if($updateSku == 135) $uupCleanFunc = 'uupCleanHolo'; + if($fileListSource == 'GENERATEDPACKS') { - $temp = preg_grep('/Windows10\.0-KB.*-EXPRESS/i', $filesKeys, PREG_GREP_INVERT); + $temp = preg_grep('/Windows10\.0-KB.*-EXPRESS/i', $filesInfoKeys, PREG_GREP_INVERT); $temp = preg_grep('/Windows10\.0-KB/i', $temp); - $filesList = array_merge($filesList, $temp); + $filesPacksList = array_merge($filesPacksList, $temp); $newFiles = array(); - foreach($filesList as $val) { - $name = uupCleanName($val); - $filesListKeys[] = $name; + foreach($filesPacksList as $val) { + $name = $uupCleanFunc($val); + $filesPacksKeys[] = $name; - if(isset($files[$name])) { - $newFiles[$name] = $files[$name]; + if(isset($filesInfoList[$name])) { + $newFiles[$name] = $filesInfoList[$name]; } } - $files = $newFiles; - $filesKeys = array_keys($files); + $filesInfoList = $newFiles; + $filesInfoKeys = array_keys($filesInfoList); - $filesListKeys = array_unique($filesListKeys); - sort($filesListKeys); - $compare = array_diff($filesListKeys, $filesKeys); + $filesPacksKeys = array_unique($filesPacksKeys); + sort($filesPacksKeys); + $compare = array_diff($filesPacksKeys, $filesInfoKeys); if(count($compare)) { foreach($compare as $val) { @@ -238,12 +253,13 @@ function uupGetFiles( } } - if(empty($filesKeys)) { + if(empty($filesInfoKeys)) { return array('error' => 'NO_FILES'); } - foreach($filesKeys as $val) { - $filesNew[$val] = $files[$val]; + $filesNew = array(); + foreach($filesInfoKeys as $val) { + $filesNew[$val] = $filesInfoList[$val]; } $files = $filesNew; @@ -256,11 +272,12 @@ function uupGetFiles( 'updateName' => $updateName, 'arch' => $updateArch, 'build' => $updateBuild, + 'sku' => $updateSku, 'files' => $files, ); } -function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests) { +function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests, $type) { $cacheHash = hash('sha256', strtolower("api-get-${updateId}_rev.$rev")); $cached = 0; @@ -283,7 +300,7 @@ function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests) { if(!$cached) { $fetchTime = time(); consoleLogger('Fetching information from the server...'); - $postData = composeFileGetRequest($updateId, uupDevice(), $info, $rev); + $postData = composeFileGetRequest($updateId, uupDevice(), $info, $rev, $type); $out = sendWuPostRequest('https://fe3cr.delivery.mp.microsoft.com/ClientWebService/client.asmx/secured', $postData); consoleLogger('Information has been successfully fetched.'); } @@ -310,6 +327,10 @@ function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests) { return array('error' => 'EMPTY_FILELIST'); } + $uupCleanFunc = 'uupCleanName'; + if($info['sku'] == 189) $uupCleanFunc = 'uupCleanWCOS'; + if($info['sku'] == 135) $uupCleanFunc = 'uupCleanHolo'; + $fileLocations = $getResult->FileLocations; $info = $info['files']; @@ -323,13 +344,9 @@ function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests) { if(empty($info[$sha1]['name'])) { $name = $guid; - } else { - $name = $info[$sha1]['name']; - } - - if(empty($info[$sha1]['name'])) { $size = -1; } else { + $name = $info[$sha1]['name']; $size = $info[$sha1]['size']; } @@ -360,7 +377,7 @@ function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests) { $temp['expire'] = $expire; $temp['debug'] = $val->asXML(); - $newName = uupCleanName($name); + $newName = $uupCleanFunc($name); $files[$newName] = $temp; } } @@ -382,6 +399,10 @@ function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests) { function uupGetOfflineFiles($info) { if(empty($info['files'])) return array(); + $uupCleanFunc = 'uupCleanName'; + if($info['sku'] == 189) $uupCleanFunc = 'uupCleanWCOS'; + if($info['sku'] == 135) $uupCleanFunc = 'uupCleanHolo'; + consoleLogger('Parsing information...'); foreach($info['files'] as $sha1 => $val) { $name = $val['name']; @@ -399,7 +420,7 @@ function uupGetOfflineFiles($info) { $temp['expire'] = 0; $temp['debug'] = null; - $newName = uupCleanName($name); + $newName = $uupCleanFunc($name); $files[$newName] = $temp; } } @@ -421,3 +442,16 @@ function uupCleanName($name) { $name = strtr($name, 'QWERTYUIOPASDFGHJKLZXCVBNM', 'qwertyuiopasdfghjklzxcvbnm'); return strtr($name, $replace); } + +function uupCleanWCOS($name) { + $name = preg_replace('/^(appx)_(messaging_desktop|.*?)_/i', '$1/$2/', $name); + $name = preg_replace('/^(retail)_(.{3,5})_fre_/i', '$1/$2/fre/', $name); + return strtr($name, 'QWERTYUIOPASDFGHJKLZXCVBNM', 'qwertyuiopasdfghjklzxcvbnm'); +} + +function uupCleanHolo($name) { + $name = preg_replace('/^(appx)_(Cortana_WCOS|FeedbackHub_WCOS|HEVCExtension_HoloLens|MixedRealityViewer_arm64|MoviesTV_Hololens|Outlook_WindowsTeam|WinStore_HoloLens)_/i', '$1/$2/', $name); + $name = preg_replace('/^(appx)_(.*?)_/i', '$1/$2/', $name); + $name = preg_replace('/^(retail)_(.{3,5})_fre_/i', '$1/$2/fre/', $name); + return strtr($name, 'QWERTYUIOPASDFGHJKLZXCVBNM', 'qwertyuiopasdfghjklzxcvbnm'); +} diff --git a/readme.md b/readme.md index 96401d5..cd18c19 100644 --- a/readme.md +++ b/readme.md @@ -2,7 +2,7 @@ UUP dump API ------------ ### Functions -#### fetchupd.php: `uupFetchUpd($arch, $ring, $flight, $build, $minor, $sku, $cacheRequests);` +#### fetchupd.php: `uupFetchUpd($arch, $ring, $flight, $build, $minor, $sku, $type, $cacheRequests);` Fetches latest update information from Windows Update servers. Parameters: @@ -27,6 +27,9 @@ Parameters: - `sku` - SKU number to use when fetching information - **Supported values:** Any integer + - `type` - Release type to use when fetching information for Windows Core OS (WCOS), e.g. Windows 10X + - **Supported values:** `Production`, `Test` + - `cacheRequests` - Should request responses be cached? (optional) - **Supported values:** 0 = Disable (default), 1 = Enable diff --git a/shared/main.php b/shared/main.php index 93178bd..be68df0 100644 --- a/shared/main.php +++ b/shared/main.php @@ -16,7 +16,7 @@ limitations under the License. */ function uupApiVersion() { - return '1.30.4'; + return '1.31.0'; } require_once dirname(__FILE__).'/auths.php'; diff --git a/shared/packs.php b/shared/packs.php index 80dcd06..404aaad 100644 --- a/shared/packs.php +++ b/shared/packs.php @@ -1,6 +1,6 @@ 'Windows 10 Education N', 'ENTERPRISE' => 'Windows 10 Enterprise', 'ENTERPRISEN' => 'Windows 10 Enterprise N', + 'HOLOGRAPHIC' => 'Windows Holographic', + 'LITE' => 'Windows 10X', 'PPIPRO' => 'Windows 10 Team', 'PROFESSIONAL' => 'Windows 10 Pro', 'PROFESSIONALN' => 'Windows 10 Pro N', @@ -82,6 +84,7 @@ function uupGetInfoTexts() { 'ANDROMEDA', 'CLOUD', 'CLOUDE', + 'CLOUDEN', 'CLOUDN', 'CORE', 'CORECOUNTRYSPECIFIC', @@ -104,7 +107,13 @@ function uupGetInfoTexts() { 'ENTERPRISESEVAL', 'ENTERPRISESN', 'ENTERPRISESNEVAL', + 'HOLOGRAPHIC', + 'HUBOS', + 'IOTENTERPRISE', + 'IOTENTERPRISES', + 'IOTOS', 'IOTUAP', + 'LITE', 'MOBILECORE', 'ONECOREUPDATEOS', 'PPIPRO', @@ -161,6 +170,9 @@ function uupGetInfoTexts() { 'SERVERSTORAGEWORKGROUPCORE', 'SERVERSTORAGEWORKGROUPEVAL', 'SERVERSTORAGEWORKGROUPEVALCORE', + 'SERVERAZURESTACKHCICOR', + 'SERVERTURBINE', + 'SERVERTURBINECOR', 'SERVERWEB', 'SERVERWEBCORE', 'STARTER', diff --git a/shared/requests.php b/shared/requests.php index 21be6a9..945f2c8 100644 --- a/shared/requests.php +++ b/shared/requests.php @@ -16,7 +16,7 @@ limitations under the License. */ // Composes DeviceAttributes parameter needed to fetch data -function composeDeviceAttributes($flight, $ring, $build, $arch, $sku) { +function composeDeviceAttributes($flight, $ring, $build, $arch, $sku, $type) { $branch = branchFromBuild($build); $blockUpgrades = 0; $flightEnabled = 1; @@ -29,13 +29,33 @@ function composeDeviceAttributes($flight, $ring, $build, $arch, $sku) { if($sku == 125 || $sku == 126 || $sku == 7 || $sku == 8 || $sku == 120 || $sku == 145 || $sku == 146 || $sku == 168) $blockUpgrades = 1; + $dvcFamily = 'Windows.Desktop'; + $insType = 'Client'; + if($sku == 119) { + $dvcFamily = 'Windows.Team'; + } + if($sku == 7 || $sku == 8 || $sku == 120 || $sku == 145 || $sku == 146 || $sku == 168) { + $dvcFamily = 'Windows.Server'; + $insType = 'Server'; + } + /*/ Hololens + if($sku == 135) { + $dvcFamily = 'Windows.Holographic'; + $insType = 'FactoryOS'; + }*/ + // HubOS Andromeda Lite + if($sku == 180 || $sku == 184 || $sku == 189) { + $dvcFamily = 'Windows.Core'; + $insType = 'FactoryOS'; + } + $fltContent = 'Mainline'; $fltRing = 'External'; $flight = 'Active'; if($ring == 'RETAIL') { $fltBranch = ''; - $fltContent = ''; + $fltContent = $flight; $fltRing = 'Retail'; $flightEnabled = 0; $isRetail = 1; @@ -86,7 +106,7 @@ function composeDeviceAttributes($flight, $ring, $build, $arch, $sku) { $attrib = array( 'App=WU_OS', 'AppVer='.$build, - 'AttrDataVer=118', + 'AttrDataVer=120', 'BlockFeatureUpdates='.$blockUpgrades, 'BranchReadinessLevel=CB', 'CurrentBranch='.$branch, @@ -94,9 +114,13 @@ function composeDeviceAttributes($flight, $ring, $build, $arch, $sku) { 'DataExpDateEpoch_19H1='.(time()+82800), 'DataVer_RS5=2000000000', 'DefaultUserRegion=191', - 'DeviceFamily=Windows.Desktop', + 'DeviceFamily='.$dvcFamily, 'EKB19H2InstallCount=1', 'EKB19H2InstallTimeEpoch=1255000000', + 'EKB20H2InstallCount=1', + 'EKB20H2InstallTimeEpoch=1255000000', + 'EKB21H1InstallCount=1', + 'EKB21H1InstallTimeEpoch=1255000000', 'FlightingBranchName='.$fltBranch, 'FlightContent='.$fltContent, 'FlightRing='.$fltRing, @@ -109,12 +133,13 @@ function composeDeviceAttributes($flight, $ring, $build, $arch, $sku) { 'GenTelRunTimestamp_19H1='.(time()-3600), 'InstallDate=1438196400', 'InstallLanguage=en-US', - 'InstallationType=Client', + 'InstallationType='.$insType, 'IsDeviceRetailDemo=0', 'IsFlightingEnabled='.$flightEnabled, 'IsRetailOS='.$isRetail, + 'MediaBranch=', 'MediaVersion='.$build, - 'MediaBranch='.$branch, + 'CloudPBR=1', 'DUScan=1', 'OEMModel=Largehard Device Model 42069', 'OEMModelBaseBoard=Largehard Base Board', @@ -125,7 +150,7 @@ function composeDeviceAttributes($flight, $ring, $build, $arch, $sku) { 'OSVersion='.$build, 'ProcessorIdentifier=Intel64 Family 6 Model 85 Stepping 4', 'ProcessorManufacturer=GenuineIntel', - 'ReleaseType=Production', + 'ReleaseType='.$type, 'SdbVer_20H1=2000000000', 'SdbVer_19H1=2000000000', 'TelemetryLevel=3', @@ -184,6 +209,10 @@ function branchFromBuild($build) { $branch = 'vb_release'; break; + case 20279: + $branch = 'fe_release_10x'; + break; + default: $branch = 'rs_prerelease'; break; @@ -193,7 +222,7 @@ function branchFromBuild($build) { } // Composes POST data for gathering list of urls for download -function composeFileGetRequest($updateId, $device, $info, $rev = 1) { +function composeFileGetRequest($updateId, $device, $info, $rev = 1, $type = 'Production') { $uuid = genUUID(); $createdTime = time(); @@ -202,14 +231,15 @@ function composeFileGetRequest($updateId, $device, $info, $rev = 1) { $created = gmdate(DATE_W3C, $createdTime); $expires = gmdate(DATE_W3C, $expiresTime); - $branch = branchFromBuild($info['checkBuild']); + //$branch = branchFromBuild($info['checkBuild']); $deviceAttributes = composeDeviceAttributes( $info['flight'], $info['ring'], $info['checkBuild'], $info['arch'], - $info['sku'] + $info['sku'], + $type ); return <<