forked from uup-dump/api
433 lines
13 KiB
PHP
433 lines
13 KiB
PHP
<?php
|
|
/*
|
|
Copyright 2018 UUP dump API authors
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
require_once dirname(__FILE__).'/shared/main.php';
|
|
require_once dirname(__FILE__).'/shared/requests.php';
|
|
require_once dirname(__FILE__).'/shared/packs.php';
|
|
|
|
function uupGetFiles($updateId = 'c2a1d787-647b-486d-b264-f90f3782cdc6', $usePack = 0, $desiredEdition = 0) {
|
|
uupApiPrintBrand();
|
|
|
|
$info = @file_get_contents('fileinfo/'.$updateId.'.json');
|
|
if(empty($info)) {
|
|
$info = array(
|
|
'ring' => 'WIF',
|
|
'flight' => 'Active',
|
|
'arch' => 'amd64',
|
|
'checkBuild' => '10.0.16251.0',
|
|
'sku' => '48',
|
|
'files' => array(),
|
|
);
|
|
} else {
|
|
$info = json_decode($info, true);
|
|
}
|
|
|
|
if(isset($info['build'])) {
|
|
$build = explode('.', $info['build']);
|
|
$build = $build[0];
|
|
} else {
|
|
$build = 9841;
|
|
}
|
|
|
|
if(!isset($info['sku'])) {
|
|
$info['sku'] = 48;
|
|
}
|
|
|
|
$packs = uupGetPacks($build);
|
|
$packsForLangs = $packs['packsForLangs'];
|
|
$editionPacks = $packs['editionPacks'];
|
|
$checkEditions = $packs['allEditions'];
|
|
$skipNeutral = $packs['skipNeutral'];
|
|
$skipLangPack = $packs['skipLangPack'];
|
|
$packs = $packs['packs'];
|
|
|
|
$noLangPack = 0;
|
|
$noNeutral = 0;
|
|
|
|
$useGeneratedPacks = 0;
|
|
|
|
if(file_exists('packs/'.$updateId.'.json.gz') && $usePack) {
|
|
$genPack = @gzdecode(@file_get_contents('packs/'.$updateId.'.json.gz'));
|
|
|
|
if(!empty($genPack)) {
|
|
$genPack = json_decode($genPack, 1);
|
|
|
|
if(!isset($genPack[$usePack])) {
|
|
return array('error' => 'UNSUPPORTED_LANG');
|
|
}
|
|
|
|
$packsForLangs = array();
|
|
$packsForLangs[$usePack] = array(0);
|
|
|
|
$useGeneratedPacks = 1;
|
|
}
|
|
}
|
|
|
|
if($usePack) {
|
|
$usePack = strtolower($usePack);
|
|
if(!isset($packsForLangs[$usePack])) {
|
|
return array('error' => 'UNSUPPORTED_LANG');
|
|
}
|
|
}
|
|
|
|
$desiredEdition = strtoupper($desiredEdition);
|
|
|
|
switch($desiredEdition) {
|
|
case '0':
|
|
if($useGeneratedPacks) {
|
|
$desiredEdition = 'GENERATEDPACKS';
|
|
|
|
$filesList = array();
|
|
foreach($genPack[$usePack] as $val) {
|
|
foreach($val as $package) {
|
|
$filesList[] = $package;
|
|
}
|
|
}
|
|
|
|
array_unique($filesList);
|
|
sort($filesList);
|
|
}
|
|
break;
|
|
|
|
case 'WUBFILE': break;
|
|
|
|
case 'UPDATEONLY':
|
|
if(!isset($info['containsCU']) || !$info['containsCU']) {
|
|
return array('error' => 'NOT_CUMULATIVE_UPDATE');
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if($useGeneratedPacks) {
|
|
if(!isset($genPack[$usePack][$desiredEdition])) {
|
|
return array('error' => 'UNSUPPORTED_COMBINATION');
|
|
}
|
|
|
|
$filesList = $genPack[$usePack][$desiredEdition];
|
|
$desiredEdition = 'GENERATEDPACKS';
|
|
break;
|
|
}
|
|
|
|
if(!$usePack) {
|
|
return array('error' => 'UNSPECIFIED_LANG');
|
|
}
|
|
|
|
if(!isset($editionPacks[$desiredEdition])) {
|
|
return array('error' => 'UNSUPPORTED_EDITION');
|
|
}
|
|
|
|
$supported = 0;
|
|
foreach($packsForLangs[$usePack] as $val) {
|
|
if($editionPacks[$desiredEdition] == $val) $supported = 1;
|
|
}
|
|
|
|
if(!$supported) {
|
|
return array('error' => 'UNSUPPORTED_COMBINATION');
|
|
}
|
|
unset($supported);
|
|
|
|
if(isset($skipLangPack[$desiredEdition])) {
|
|
if($skipLangPack[$desiredEdition]) {
|
|
$noLangPack = 1;
|
|
}
|
|
}
|
|
|
|
if(isset($skipNeutral[$desiredEdition])) {
|
|
if($skipNeutral[$desiredEdition]) {
|
|
$noNeutral = 1;
|
|
}
|
|
}
|
|
|
|
$checkEditions = array($desiredEdition);
|
|
break;
|
|
}
|
|
|
|
if($noNeutral) {
|
|
foreach($packsForLangs[$usePack] as $num) {
|
|
if(isset($packs[$num]['editionNeutral'])) {
|
|
unset($packs[$num]['editionNeutral']);
|
|
}
|
|
}
|
|
}
|
|
|
|
$rev = 1;
|
|
if(preg_match('/_rev\./', $updateId)) {
|
|
$rev = preg_replace('/.*_rev\./', '', $updateId);
|
|
$updateId = preg_replace('/_rev\..*/', '', $updateId);
|
|
}
|
|
|
|
$updateArch = (isset($info['arch'])) ? $info['arch'] : 'UNKNOWN';
|
|
$updateBuild = (isset($info['build'])) ? $info['build'] : 'UNKNOWN';
|
|
$updateName = (isset($info['title'])) ? $info['title'] : 'Unknown update: '.$updateId;
|
|
|
|
$fetchTime = time();
|
|
consoleLogger('Fetching information from the server...');
|
|
$postData = composeFileGetRequest($updateId, uupDevice(), $info, $rev);
|
|
$out = sendWuPostRequest('https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx/secured', $postData);
|
|
consoleLogger('Information has been successfully fetched.');
|
|
|
|
consoleLogger('Parsing information...');
|
|
$xmlOut = simplexml_load_string($out);
|
|
$xmlBody = $xmlOut->children('s', true)->Body->children();
|
|
|
|
if(!isset($xmlBody->GetExtendedUpdateInfo2Response)) {
|
|
consoleLogger('An error has occurred');
|
|
return array('error' => 'EMPTY_FILELIST');
|
|
}
|
|
|
|
$getResponse = $xmlBody->GetExtendedUpdateInfo2Response;
|
|
$getResult = $getResponse->GetExtendedUpdateInfo2Result;
|
|
|
|
if(!isset($getResult->FileLocations)) {
|
|
consoleLogger('An error has occurred');
|
|
return array('error' => 'EMPTY_FILELIST');
|
|
}
|
|
|
|
$fileLocations = $getResult->FileLocations;
|
|
$info = $info['files'];
|
|
|
|
$files = array();
|
|
foreach($fileLocations->FileLocation as $val) {
|
|
$sha1 = bin2hex(base64_decode((string)$val->FileDigest));
|
|
$url = (string)$val->Url;
|
|
|
|
preg_match('/files\/(.{8}-.{4}-.{4}-.{4}-.{12})/', $url, $guid);
|
|
$guid = $guid[1];
|
|
|
|
if(empty($info[$sha1]['name'])) {
|
|
$name = $guid;
|
|
} else {
|
|
$name = $info[$sha1]['name'];
|
|
}
|
|
|
|
if(empty($info[$sha1]['name'])) {
|
|
$size = -1;
|
|
} else {
|
|
$size = $info[$sha1]['size'];
|
|
}
|
|
|
|
if(!isset($fileSizes[$name])) $fileSizes[$name] = -2;
|
|
|
|
if($size > $fileSizes[$name]) {
|
|
preg_match('/P1=(.*?)&/', $url, $expire);
|
|
if(isset($expire[0])) {
|
|
$expire = $expire[1];
|
|
}
|
|
|
|
$expire = intval($expire);
|
|
|
|
if($size < 0) {
|
|
$temp = ($expire - $fetchTime) / 600;
|
|
$size = ($temp - 1) * 31457280;
|
|
if($size < 0) $size = 0;
|
|
unset($temp);
|
|
}
|
|
|
|
$fileSizes[$name] = $size;
|
|
|
|
$temp = array();
|
|
$temp['sha1'] = $sha1;
|
|
$temp['size'] = $size;
|
|
$temp['url'] = $url;
|
|
$temp['uuid'] = $guid;
|
|
$temp['expire'] = $expire;
|
|
|
|
$newName = preg_replace('/^cabs_|^metadataesd_|~31bf3856ad364e35/i', '', $name);
|
|
$newName = preg_replace('/~~\.|~\./', '.', $newName);
|
|
$newName = preg_replace('/~/', '-', $newName);
|
|
$newName = strtolower($newName);
|
|
|
|
$files[$newName] = $temp;
|
|
}
|
|
}
|
|
unset($temp, $newName);
|
|
|
|
$baseless = preg_grep('/^baseless_|-baseless\....$/i', array_keys($files));
|
|
foreach($baseless as $val) {
|
|
if(isset($files[$val])) unset($files[$val]);
|
|
}
|
|
|
|
$psf = array_keys($files);
|
|
$psf = preg_grep('/\.psf$/i', $psf);
|
|
|
|
$removeFiles = array();
|
|
foreach($psf as $val) {
|
|
$name = preg_replace('/\.psf$/i', '', $val);
|
|
$removeFiles[] = $name;
|
|
unset($files[$val]);
|
|
}
|
|
unset($index, $name, $psf);
|
|
|
|
$temp = preg_grep('/'.$updateArch.'_.*|arm64.arm_.*/i', $removeFiles);
|
|
foreach($temp as $key => $val) {
|
|
if(isset($files[$val.'.cab'])) unset($files[$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']);
|
|
}
|
|
}
|
|
unset($removeFiles);
|
|
|
|
$filesKeys = array_keys($files);
|
|
|
|
switch($desiredEdition) {
|
|
case 'UPDATEONLY':
|
|
$skipPackBuild = 1;
|
|
$removeFiles = preg_grep('/Windows10\.0-KB.*-EXPRESS/i', $filesKeys);
|
|
|
|
foreach($removeFiles as $val) {
|
|
if(isset($files[$val])) unset($files[$val]);
|
|
}
|
|
|
|
unset($removeFiles, $temp);
|
|
$filesKeys = array_keys($files);
|
|
|
|
$filesKeys = preg_grep('/Windows10\.0-KB/i', $filesKeys);
|
|
break;
|
|
|
|
case 'WUBFILE':
|
|
$skipPackBuild = 1;
|
|
$filesKeys = preg_grep('/WindowsUpdateBox.exe/i', $filesKeys);
|
|
break;
|
|
|
|
case 'GENERATEDPACKS':
|
|
$skipPackBuild = 1;
|
|
break;
|
|
|
|
default:
|
|
$skipPackBuild = 0;
|
|
break;
|
|
}
|
|
|
|
if($usePack && !$skipPackBuild) {
|
|
$esd = array_keys($files);
|
|
$esd = preg_grep('/\.esd$/i', $esd);
|
|
|
|
foreach($esd as $key => $val) {
|
|
$esd[$key] = strtoupper($val);
|
|
}
|
|
|
|
foreach($checkEditions as $val) {
|
|
$testEsd[] = $val.'_'.strtoupper($usePack).'.ESD';
|
|
}
|
|
|
|
$foundMetadata = array_intersect($testEsd, $esd);
|
|
consoleLogger('Found '.count($foundMetadata).' metadata ESD file(s).');
|
|
|
|
if(empty($foundMetadata)) {
|
|
return array('error' => 'NO_METADATA_ESD');
|
|
}
|
|
|
|
$removeFiles = array();
|
|
$removeFiles[0] = preg_grep('/RetailDemo-OfflineContent/i', $filesKeys);
|
|
$removeFiles[1] = preg_grep('/Windows10\.0-KB.*-EXPRESS/i', $filesKeys);
|
|
|
|
foreach($removeFiles as $val) {
|
|
foreach($val as $temp) {
|
|
if(isset($files[$temp])) unset($files[$temp]);
|
|
}
|
|
}
|
|
unset($removeFiles, $temp, $val);
|
|
|
|
$filesKeys = array_keys($files);
|
|
$filesTemp = array();
|
|
|
|
if(!$noLangPack) {
|
|
$temp = preg_grep('/.*'.$usePack.'-Package.*/i', $filesKeys);
|
|
$filesTemp = array_merge($filesTemp, $temp);
|
|
|
|
$temp = preg_grep('/.*'.$usePack.'_lp..../i', $filesKeys);
|
|
$filesTemp = array_merge($filesTemp, $temp);
|
|
}
|
|
|
|
foreach($packsForLangs[$usePack] as $num) {
|
|
foreach($packs[$num] as $key => $val) {
|
|
if($key == 'editionNeutral'
|
|
|| $key == $desiredEdition
|
|
|| !$desiredEdition) {
|
|
$temp = packsByEdition($key, $val, $usePack, $filesKeys);
|
|
$filesTemp = array_merge($filesTemp, $temp);
|
|
}
|
|
}
|
|
}
|
|
|
|
$filesKeys = array_unique($filesTemp);
|
|
unset($filesTemp, $temp, $val, $num);
|
|
}
|
|
|
|
if($desiredEdition == 'GENERATEDPACKS') {
|
|
$temp = preg_grep('/Windows10\.0-KB.*-EXPRESS/i', $filesKeys, PREG_GREP_INVERT);
|
|
$temp = preg_grep('/Windows10\.0-KB/i', $temp);
|
|
$filesList = array_merge($filesList, $temp);
|
|
|
|
$newFiles = array();
|
|
foreach($filesList as $val) {
|
|
$name = preg_replace('/~31bf3856ad364e35/', '', $val);
|
|
$name = preg_replace('/~~\.|~\./', '.', $name);
|
|
$name = preg_replace('/~/', '-', $name);
|
|
$name = strtolower($name);
|
|
|
|
$newFiles[$name] = $files[$name];
|
|
}
|
|
|
|
$files = $newFiles;
|
|
$filesKeys = array_keys($files);
|
|
}
|
|
|
|
if(empty($filesKeys)) {
|
|
return array('error' => 'NO_FILES');
|
|
}
|
|
|
|
foreach($filesKeys as $val) {
|
|
$filesNew[$val] = $files[$val];
|
|
}
|
|
|
|
$files = $filesNew;
|
|
ksort($files);
|
|
|
|
consoleLogger('Successfully parsed the information.');
|
|
|
|
return array(
|
|
'apiVersion' => uupApiVersion(),
|
|
'updateName' => $updateName,
|
|
'arch' => $updateArch,
|
|
'build' => $updateBuild,
|
|
'files' => $files,
|
|
);
|
|
}
|
|
|
|
function packsByEdition($edition, $pack, $lang, $filesKeys) {
|
|
$filesTemp = array();
|
|
|
|
if($edition != 'editionNeutral') {
|
|
$temp = preg_grep('/'.$edition.'_'.$lang.'\.esd/i', $filesKeys);
|
|
$filesTemp = array_merge($filesTemp, $temp);
|
|
}
|
|
|
|
foreach($pack as $val) {
|
|
$temp = preg_grep('/'.$val.'.*/i', $filesKeys);
|
|
$filesTemp = array_merge($filesTemp, $temp);
|
|
}
|
|
|
|
return $filesTemp;
|
|
}
|
|
?>
|