forked from uup-dump/api
Compare commits
69 Commits
sha256-san
...
master
Author | SHA1 | Date | |
---|---|---|---|
3855dc9ac4 | |||
8959eb14a4 | |||
|
ada8ae6011 | ||
492fd22e46 | |||
|
03258c7bfe | ||
c7512dd40d | |||
|
b1d8121507 | ||
|
1fc14b6fd4 | ||
|
c5d4090bac | ||
|
b0f78dedbc | ||
|
2cfa0422c1 | ||
|
d089aa698c | ||
|
aeb86d4333 | ||
|
cf34eea8e1 | ||
|
c025da99dc | ||
|
f5f4795cd9 | ||
|
1cc48ae9d8 | ||
|
79730cdd24 | ||
|
cf57876aca | ||
|
541f8d9515 | ||
|
6831bb17e9 | ||
|
0d06ee36f5 | ||
|
76092ff092 | ||
|
9e3c1c574b | ||
|
16b3bc786d | ||
|
8894bd9cc0 | ||
|
54b605c1d4 | ||
|
6d5f3a80f9 | ||
|
980863c20e | ||
|
e310ab4246 | ||
|
6a524aa0c0 | ||
|
749fd65769 | ||
|
a3c0065706 | ||
|
0ea0de8c2c | ||
|
6e55605fb2 | ||
|
4a29784380 | ||
|
6cd9c0c414 | ||
|
64959ebf3d | ||
|
6c00b7c16f | ||
|
be2a2f2877 | ||
|
067f7f2937 | ||
|
7011b1ead2 | ||
|
547aa1512a | ||
|
2d5fcf1f15 | ||
|
4971a19b8a | ||
|
2dbb52dc7f | ||
|
82070f9c15 | ||
|
4dbe52a32b | ||
|
c85957b8a9 | ||
|
9a80701470 | ||
|
d5769f635c | ||
|
99f6e8d940 | ||
|
c14287dcbd | ||
|
aa86232bd3 | ||
|
6e4e53ade8 | ||
|
12db118aae | ||
|
16d048df08 | ||
|
a0f0574a81 | ||
|
89209ff40c | ||
d007804b5e | |||
e4b33f0465 | |||
a3c35f89fa | |||
47b7ee6703 | |||
a46a5628c0 | |||
|
972cff36a5 | ||
|
bcabed0d33 | ||
|
e889ec6629 | ||
0665adf5f6 | |||
3b884e2086 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
shared/cookie.json
|
|
78
fetchupd.php
78
fetchupd.php
@ -17,6 +17,8 @@ limitations under the License.
|
|||||||
|
|
||||||
require_once dirname(__FILE__).'/shared/main.php';
|
require_once dirname(__FILE__).'/shared/main.php';
|
||||||
require_once dirname(__FILE__).'/shared/requests.php';
|
require_once dirname(__FILE__).'/shared/requests.php';
|
||||||
|
require_once dirname(__FILE__).'/shared/cache.php';
|
||||||
|
require_once dirname(__FILE__).'/shared/fileinfo.php';
|
||||||
require_once dirname(__FILE__).'/listid.php';
|
require_once dirname(__FILE__).'/listid.php';
|
||||||
|
|
||||||
function uupFetchUpd(
|
function uupFetchUpd(
|
||||||
@ -37,14 +39,18 @@ function uupFetchUpd(
|
|||||||
$flight = 'Active';
|
$flight = 'Active';
|
||||||
|
|
||||||
if($build == 'latest' || (!$build)) {
|
if($build == 'latest' || (!$build)) {
|
||||||
$builds = array('17134.1');
|
$builds = array('22000.1');
|
||||||
|
|
||||||
$ids = uupListIds();
|
$ids = uupListIds();
|
||||||
if(isset($ids['error'])) {
|
if(isset($ids['error'])) {
|
||||||
$ids['builds'] = array();
|
$ids['builds'] = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(empty($ids['builds'])) {
|
||||||
|
$build = $builds[0];
|
||||||
|
} else {
|
||||||
$build = $ids['builds'][0]['build'];
|
$build = $ids['builds'][0]['build'];
|
||||||
|
}
|
||||||
unset($builds, $ids);
|
unset($builds, $ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +63,7 @@ function uupFetchUpd(
|
|||||||
return array('error' => 'UNKNOWN_ARCH');
|
return array('error' => 'UNKNOWN_ARCH');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!($ring == 'DEV' || $ring == 'BETA' || $ring == 'RELEASEPREVIEW' || $ring == 'WIF' || $ring == 'WIS' || $ring == 'RP' || $ring == 'RETAIL' || $ring == 'MSIT')) {
|
if(!($ring == 'CANARY' || $ring == 'DEV' || $ring == 'BETA' || $ring == 'RELEASEPREVIEW' || $ring == 'WIF' || $ring == 'WIS' || $ring == 'RP' || $ring == 'RETAIL' || $ring == 'MSIT')) {
|
||||||
return array('error' => 'UNKNOWN_RING');
|
return array('error' => 'UNKNOWN_RING');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,45 +96,22 @@ function uupFetchUpd(
|
|||||||
$type = 'Production';
|
$type = 'Production';
|
||||||
}
|
}
|
||||||
|
|
||||||
$cacheHash = hash('sha256', strtolower("api-fetch-$arch-$ring-$flight-$build-$minor-$sku-$type"));
|
$res = "api-fetch-$arch-$ring-$flight-$build-$minor-$sku-$type";
|
||||||
$cached = 0;
|
$cache = new UupDumpCache($res);
|
||||||
|
$fromCache = $cache->get();
|
||||||
|
if($fromCache !== false) return $fromCache;
|
||||||
|
|
||||||
if(file_exists('cache/'.$cacheHash.'.json.gz') && $cacheRequests == 1) {
|
|
||||||
$cache = @gzdecode(@file_get_contents('cache/'.$cacheHash.'.json.gz'));
|
|
||||||
$cache = json_decode($cache, 1);
|
|
||||||
|
|
||||||
if(!empty($cache['content']) && ($cache['expires'] > time())) {
|
|
||||||
consoleLogger('Using cached response...');
|
|
||||||
$out = $cache['content'];
|
|
||||||
$cached = 1;
|
|
||||||
} else {
|
|
||||||
$cached = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unset($cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$cached) {
|
|
||||||
consoleLogger('Fetching information from the server...');
|
consoleLogger('Fetching information from the server...');
|
||||||
$postData = composeFetchUpdRequest(uupDevice(), uupEncryptedData(), $arch, $flight, $ring, $build, $sku, $type);
|
$composerArgs = [$arch, $flight, $ring, $build, $sku, $type];
|
||||||
$out = sendWuPostRequest('https://fe3cr.delivery.mp.microsoft.com/ClientWebService/client.asmx', $postData);
|
$out = sendWuPostRequestHelper('client', 'composeFetchUpdRequest', $composerArgs);
|
||||||
|
if($out['error'] != 200) {
|
||||||
|
consoleLogger('The request has failed');
|
||||||
|
return array('error' => 'WU_REQUEST_FAILED');
|
||||||
|
}
|
||||||
|
|
||||||
$out = html_entity_decode($out);
|
$out = html_entity_decode($out['out']);
|
||||||
consoleLogger('Information has been successfully fetched.');
|
consoleLogger('Information has been successfully fetched.');
|
||||||
|
|
||||||
if($cacheRequests == 1) {
|
|
||||||
$cache = array(
|
|
||||||
'expires' => time()+120,
|
|
||||||
'content' => $out,
|
|
||||||
);
|
|
||||||
|
|
||||||
if(!file_exists('cache')) mkdir('cache');
|
|
||||||
@file_put_contents('cache/'.$cacheHash.'.json.gz', gzencode(json_encode($cache)."\n"));
|
|
||||||
|
|
||||||
unset($cache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
preg_match_all('/<UpdateInfo>.*?<\/UpdateInfo>/', $out, $updateInfos);
|
preg_match_all('/<UpdateInfo>.*?<\/UpdateInfo>/', $out, $updateInfos);
|
||||||
$updateInfo = preg_grep('/<IsLeaf>true<\/IsLeaf>/', $updateInfos[0]);
|
$updateInfo = preg_grep('/<IsLeaf>true<\/IsLeaf>/', $updateInfos[0]);
|
||||||
sort($updateInfo);
|
sort($updateInfo);
|
||||||
@ -160,7 +143,7 @@ function uupFetchUpd(
|
|||||||
return array('error' => 'EMPTY_FILELIST');
|
return array('error' => 'EMPTY_FILELIST');
|
||||||
}
|
}
|
||||||
|
|
||||||
return array(
|
$data = [
|
||||||
'apiVersion' => uupApiVersion(),
|
'apiVersion' => uupApiVersion(),
|
||||||
'updateId' => $updateArray[0]['updateId'],
|
'updateId' => $updateArray[0]['updateId'],
|
||||||
'updateTitle' => $updateArray[0]['updateTitle'],
|
'updateTitle' => $updateArray[0]['updateTitle'],
|
||||||
@ -168,7 +151,13 @@ function uupFetchUpd(
|
|||||||
'arch' => $updateArray[0]['arch'],
|
'arch' => $updateArray[0]['arch'],
|
||||||
'fileWrite' => $updateArray[0]['fileWrite'],
|
'fileWrite' => $updateArray[0]['fileWrite'],
|
||||||
'updateArray' => $updateArray,
|
'updateArray' => $updateArray,
|
||||||
);
|
];
|
||||||
|
|
||||||
|
if($cacheRequests == 1) {
|
||||||
|
$cache->put($data, 120);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku, $type) {
|
function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku, $type) {
|
||||||
@ -237,8 +226,10 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku
|
|||||||
|
|
||||||
$updateTitle = preg_replace("/ ?\d{4}-\d{2}\D ?| ?$foundArch ?| ?x64 ?/i", '', $updateTitle);
|
$updateTitle = preg_replace("/ ?\d{4}-\d{2}\D ?| ?$foundArch ?| ?x64 ?/i", '', $updateTitle);
|
||||||
|
|
||||||
if($foundType == 'server')
|
if($foundType == 'server') {
|
||||||
$updateTitle = str_replace('Windows 10', 'Windows Server', $updateTitle);
|
$updateTitle = str_replace('Windows 10', 'Windows Server', $updateTitle);
|
||||||
|
$updateTitle = str_replace('Windows 11', 'Windows Server', $updateTitle);
|
||||||
|
}
|
||||||
|
|
||||||
if($sku == 406)
|
if($sku == 406)
|
||||||
$updateTitle = str_replace('Microsoft server operating system', 'Azure Stack HCI', $updateTitle);
|
$updateTitle = str_replace('Microsoft server operating system', 'Azure Stack HCI', $updateTitle);
|
||||||
@ -300,16 +291,16 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku
|
|||||||
return array('error' => 'BROKEN_UPDATE');
|
return array('error' => 'BROKEN_UPDATE');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(preg_match('/Corpnet Required/i', $updateTitle)) {
|
$isCorpnet = preg_match('/Corpnet Required/i', $updateTitle);
|
||||||
|
if($isCorpnet && !uupApiConfigIsTrue('allow_corpnet')) {
|
||||||
consoleLogger('Skipping corpnet only update...');
|
consoleLogger('Skipping corpnet only update...');
|
||||||
return array('error' => 'CORPNET_ONLY_UPDATE');
|
return array('error' => 'CORPNET_ONLY_UPDATE');
|
||||||
}
|
}
|
||||||
|
|
||||||
$fileWrite = 'NO_SAVE';
|
$fileWrite = 'NO_SAVE';
|
||||||
if(!file_exists('fileinfo/'.$updateString.'.json')) {
|
if(!uupApiFileInfoExists($updateId)) {
|
||||||
consoleLogger('WARNING: This build is NOT in the database. It will be saved now.');
|
consoleLogger('WARNING: This build is NOT in the database. It will be saved now.');
|
||||||
consoleLogger('Parsing information to write...');
|
consoleLogger('Parsing information to write...');
|
||||||
if(!file_exists('fileinfo')) mkdir('fileinfo');
|
|
||||||
|
|
||||||
$fileList = preg_replace('/<Files>|<\/Files>/', '', $fileList[0]);
|
$fileList = preg_replace('/<Files>|<\/Files>/', '', $fileList[0]);
|
||||||
preg_match_all('/<File.*?<\/File>/', $fileList, $fileList);
|
preg_match_all('/<File.*?<\/File>/', $fileList, $fileList);
|
||||||
@ -367,10 +358,11 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku
|
|||||||
consoleLogger('Successfully parsed the information.');
|
consoleLogger('Successfully parsed the information.');
|
||||||
consoleLogger('Writing new build information to the disk...');
|
consoleLogger('Writing new build information to the disk...');
|
||||||
|
|
||||||
$success = file_put_contents('fileinfo/'.$updateString.'.json', json_encode($temp)."\n");
|
$success = uupApiWriteFileinfo($updateString, $temp);
|
||||||
if($success) {
|
if($success) {
|
||||||
consoleLogger('Successfully written build information to the disk.');
|
consoleLogger('Successfully written build information to the disk.');
|
||||||
$fileWrite = 'INFO_WRITTEN';
|
$fileWrite = 'INFO_WRITTEN';
|
||||||
|
uupApiPrivateInvalidateFileinfoCache();
|
||||||
} else {
|
} else {
|
||||||
consoleLogger('An error has occured while writing the information to the disk.');
|
consoleLogger('An error has occured while writing the information to the disk.');
|
||||||
}
|
}
|
||||||
|
181
get.php
181
get.php
@ -18,6 +18,8 @@ limitations under the License.
|
|||||||
require_once dirname(__FILE__).'/shared/main.php';
|
require_once dirname(__FILE__).'/shared/main.php';
|
||||||
require_once dirname(__FILE__).'/shared/requests.php';
|
require_once dirname(__FILE__).'/shared/requests.php';
|
||||||
require_once dirname(__FILE__).'/shared/packs.php';
|
require_once dirname(__FILE__).'/shared/packs.php';
|
||||||
|
require_once dirname(__FILE__).'/shared/cache.php';
|
||||||
|
require_once dirname(__FILE__).'/shared/fileinfo.php';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
$updateId = Update Identifier
|
$updateId = Update Identifier
|
||||||
@ -45,7 +47,13 @@ function uupGetFiles(
|
|||||||
return array('error' => 'INCORRECT_ID');
|
return array('error' => 'INCORRECT_ID');
|
||||||
}
|
}
|
||||||
|
|
||||||
$info = @file_get_contents('fileinfo/'.$updateId.'.json');
|
$edition = is_array($desiredEdition) ? implode('_', $desiredEdition) : $desiredEdition;
|
||||||
|
$res = "api-get-{$updateId}_{$usePack}_{$edition}_{$requestType}";
|
||||||
|
$cache = new UupDumpCache($res);
|
||||||
|
$fromCache = $cache->get();
|
||||||
|
if($fromCache !== false) return $fromCache;
|
||||||
|
|
||||||
|
$info = uupApiReadFileinfo($updateId);
|
||||||
if(empty($info)) {
|
if(empty($info)) {
|
||||||
$info = array(
|
$info = array(
|
||||||
'ring' => 'WIF',
|
'ring' => 'WIF',
|
||||||
@ -55,8 +63,6 @@ function uupGetFiles(
|
|||||||
'sku' => '48',
|
'sku' => '48',
|
||||||
'files' => array(),
|
'files' => array(),
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
$info = json_decode($info, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isset($info['build'])) {
|
if(isset($info['build'])) {
|
||||||
@ -79,6 +85,8 @@ function uupGetFiles(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$appEdition = 0;
|
||||||
|
|
||||||
if(!is_array($desiredEdition)) {
|
if(!is_array($desiredEdition)) {
|
||||||
$desiredEdition = strtoupper($desiredEdition);
|
$desiredEdition = strtoupper($desiredEdition);
|
||||||
$fileListSource = $desiredEdition;
|
$fileListSource = $desiredEdition;
|
||||||
@ -104,13 +112,19 @@ function uupGetFiles(
|
|||||||
|
|
||||||
case 'UPDATEONLY': break;
|
case 'UPDATEONLY': break;
|
||||||
|
|
||||||
|
case 'APP': $appEdition = 1;
|
||||||
|
case 'APP_MOMENT': $appEdition = 1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if(!isset($genPack[$usePack][$desiredEdition])) {
|
if(!isset($genPack[$usePack][$desiredEdition])) {
|
||||||
return array('error' => 'UNSUPPORTED_COMBINATION');
|
return array('error' => 'UNSUPPORTED_COMBINATION');
|
||||||
}
|
}
|
||||||
|
|
||||||
$filesPacksList = $genPack[$usePack][$desiredEdition];
|
|
||||||
$fileListSource = 'GENERATEDPACKS';
|
$fileListSource = 'GENERATEDPACKS';
|
||||||
|
$filesPacksList = $genPack[$usePack][$desiredEdition];
|
||||||
|
if($desiredEdition == 'APP' && isset($genPack[$usePack]['APP_MOMENT'])) {
|
||||||
|
$filesPacksList = array_merge($filesPacksList, $genPack[$usePack]['APP_MOMENT']);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -123,6 +137,7 @@ function uupGetFiles(
|
|||||||
return array('error' => 'UNSUPPORTED_COMBINATION');
|
return array('error' => 'UNSUPPORTED_COMBINATION');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($edition == 'APP' || $edition == 'APP_MOMENT') $appEdition = 1;
|
||||||
$filesPacksList = array_merge($filesPacksList, $genPack[$usePack][$edition]);
|
$filesPacksList = array_merge($filesPacksList, $genPack[$usePack][$edition]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,6 +153,7 @@ function uupGetFiles(
|
|||||||
$updateBuild = (isset($info['build'])) ? $info['build'] : 'UNKNOWN';
|
$updateBuild = (isset($info['build'])) ? $info['build'] : 'UNKNOWN';
|
||||||
$updateName = (isset($info['title'])) ? $info['title'] : 'Unknown update: '.$updateId;
|
$updateName = (isset($info['title'])) ? $info['title'] : 'Unknown update: '.$updateId;
|
||||||
$sha256capable = isset($info['sha256ready']);
|
$sha256capable = isset($info['sha256ready']);
|
||||||
|
$hasUpdates = false;
|
||||||
|
|
||||||
if(isset($info['releasetype'])) {
|
if(isset($info['releasetype'])) {
|
||||||
$type = $info['releasetype'];
|
$type = $info['releasetype'];
|
||||||
@ -164,16 +180,34 @@ function uupGetFiles(
|
|||||||
if(isset($filesInfoList[$val])) unset($filesInfoList[$val]);
|
if(isset($filesInfoList[$val])) unset($filesInfoList[$val]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$baseless = preg_grep('/^baseless_|Windows10\.0-KB.*-EXPRESS|SSU-.*-EXPRESS/i', array_keys($filesInfoList));
|
$baseless = preg_grep('/^baseless_/i', array_keys($filesInfoList));
|
||||||
foreach($baseless as $val) {
|
foreach($baseless as $val) {
|
||||||
if(isset($filesInfoList[$val])) unset($filesInfoList[$val]);
|
if(isset($filesInfoList[$val])) unset($filesInfoList[$val]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$expresscab = preg_grep('/Windows(10|11)\.0-KB.*-EXPRESS|SSU-.*-EXPRESS/i', array_keys($filesInfoList));
|
||||||
|
|
||||||
|
$expresspsf = array();
|
||||||
|
foreach($expresscab as $val) {
|
||||||
|
$name = preg_replace('/-EXPRESS.cab$/i', '', $val);
|
||||||
|
$expresspsf[] = $name;
|
||||||
|
if(isset($filesInfoList[$val])) unset($filesInfoList[$val]);
|
||||||
|
}
|
||||||
|
unset($index, $name, $expresscab);
|
||||||
|
|
||||||
|
foreach($expresspsf as $val) {
|
||||||
|
if(isset($filesInfoList[$val.'.cab'])) {
|
||||||
|
if(isset($filesInfoList[$val.'.psf'])) unset($filesInfoList[$val.'.psf']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($expresspsf);
|
||||||
|
|
||||||
$psf = array_keys($filesInfoList);
|
$psf = array_keys($filesInfoList);
|
||||||
$psf = preg_grep('/\.psf$/i', $psf);
|
$psf = preg_grep('/\.psf$/i', $psf);
|
||||||
|
|
||||||
$psfk = preg_grep('/Windows10\.0-KB.*/i', $psf);
|
$psfk = preg_grep('/Windows(10|11)\.0-KB.*/i', $psf);
|
||||||
$psfk = preg_grep('/.*-EXPRESS/i', $psfk, PREG_GREP_INVERT);
|
$psfk = preg_grep('/.*-EXPRESS/i', $psfk, PREG_GREP_INVERT);
|
||||||
|
if($build < 17763) $psfk = preg_grep('/Windows(10|11)\.0-KB.*_\d\.psf$/i', $psfk, PREG_GREP_INVERT);
|
||||||
foreach($psfk as $key => $val) {
|
foreach($psfk as $key => $val) {
|
||||||
if(isset($psf[$key])) unset($psf[$key]);
|
if(isset($psf[$key])) unset($psf[$key]);
|
||||||
}
|
}
|
||||||
@ -201,24 +235,46 @@ function uupGetFiles(
|
|||||||
}
|
}
|
||||||
unset($removeFiles);
|
unset($removeFiles);
|
||||||
|
|
||||||
|
$msu = array_keys($filesInfoList);
|
||||||
|
$msu = preg_grep('/\.msu$/i', $msu);
|
||||||
|
$removeMSUs = array();
|
||||||
|
foreach($msu as $val) {
|
||||||
|
$name = preg_replace('/\.msu$/i', '', $val);
|
||||||
|
$removeMSUs[] = $name;
|
||||||
|
}
|
||||||
|
unset($index, $name, $msu);
|
||||||
|
|
||||||
$filesInfoKeys = array_keys($filesInfoList);
|
$filesInfoKeys = array_keys($filesInfoList);
|
||||||
|
$updatesRegex = '/Windows(10|11)\.0-KB|SSU-.*?\....$/i';
|
||||||
|
|
||||||
switch($fileListSource) {
|
switch($fileListSource) {
|
||||||
case 'UPDATEONLY':
|
case 'UPDATEONLY':
|
||||||
$skipPackBuild = 1;
|
$skipPackBuild = 1;
|
||||||
$removeFiles = preg_grep('/Windows10\.0-KB.*-EXPRESS|Windows10\.0-KB.*-baseless|SSU-\d*?\.\d*?-.{3,5}-EXPRESS/i', $filesInfoKeys);
|
$removeFiles = preg_grep('/Windows(10|11)\.0-KB.*-baseless/i', $filesInfoKeys);
|
||||||
|
|
||||||
foreach($removeFiles as $val) {
|
foreach($removeFiles as $val) {
|
||||||
if(isset($filesInfoList[$val])) unset($filesInfoList[$val]);
|
if(isset($filesInfoList[$val])) unset($filesInfoList[$val]);
|
||||||
}
|
}
|
||||||
unset($removeFiles);
|
unset($removeFiles);
|
||||||
|
|
||||||
$filesInfoKeys = array_keys($filesInfoList);
|
foreach($removeMSUs as $val) {
|
||||||
|
if(isset($filesInfoList[$val.'.cab']) && isset($filesInfoList[$val.'.msu'])) {
|
||||||
|
unset($filesInfoList[$val.'.msu']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($removeMSUs);
|
||||||
|
|
||||||
$filesInfoKeys = preg_grep('/Windows10\.0-KB|SSU-\d*?\.\d*?-.*?\.cab/i', $filesInfoKeys);
|
$filesInfoKeys = array_keys($filesInfoList);
|
||||||
|
$temp = preg_grep('/.*?AggregatedMetadata.*?\.cab|.*?DesktopDeployment.*?\.cab/i', $filesInfoKeys);
|
||||||
|
|
||||||
|
$filesInfoKeys = preg_grep($updatesRegex, $filesInfoKeys);
|
||||||
if(count($filesInfoKeys) == 0) {
|
if(count($filesInfoKeys) == 0) {
|
||||||
return array('error' => 'NOT_CUMULATIVE_UPDATE');
|
return array('error' => 'NOT_CUMULATIVE_UPDATE');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($build > 21380) $filesInfoKeys = array_merge($filesInfoKeys, $temp);
|
||||||
|
unset($temp);
|
||||||
|
$hasUpdates = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'WUBFILE':
|
case 'WUBFILE':
|
||||||
@ -232,8 +288,24 @@ function uupGetFiles(
|
|||||||
if($updateSku == 135) $uupCleanFunc = 'uupCleanHolo';
|
if($updateSku == 135) $uupCleanFunc = 'uupCleanHolo';
|
||||||
|
|
||||||
if($fileListSource == 'GENERATEDPACKS') {
|
if($fileListSource == 'GENERATEDPACKS') {
|
||||||
$temp = preg_grep('/Windows10\.0-KB.*-EXPRESS|Windows10\.0-KB.*-baseless|SSU-\d*?\.\d*?-.{3,5}-EXPRESS/i', $filesInfoKeys, PREG_GREP_INVERT);
|
foreach($removeMSUs as $val) {
|
||||||
$temp = preg_grep('/Windows10\.0-KB|SSU-\d*?\.\d*?-.*?\.cab/i', $temp);
|
if(isset($filesInfoList[$val.'.cab']) && isset($filesInfoList[$val.'.msu'])) {
|
||||||
|
unset($filesInfoList[$val.'.msu']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($removeMSUs);
|
||||||
|
$filesInfoKeys = array_keys($filesInfoList);
|
||||||
|
|
||||||
|
$temp = preg_grep('/Windows(10|11)\.0-KB.*-baseless/i', $filesInfoKeys, PREG_GREP_INVERT);
|
||||||
|
if($appEdition) {
|
||||||
|
$temp = preg_grep('/.*?AggregatedMetadata.*?\.cab|.*?DesktopDeployment.*?\.cab/i', $temp);
|
||||||
|
} else if($build > 21380) {
|
||||||
|
$temp = preg_grep('/Windows(10|11)\.0-KB|SSU-.*?\....$|.*?AggregatedMetadata.*?\.cab|.*?DesktopDeployment.*?\.cab/i', $temp);
|
||||||
|
} else {
|
||||||
|
$temp = preg_grep($updatesRegex, $temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
$hasUpdates = !empty(preg_grep($updatesRegex, $temp));
|
||||||
$filesPacksList = array_merge($filesPacksList, $temp);
|
$filesPacksList = array_merge($filesPacksList, $temp);
|
||||||
|
|
||||||
$newFiles = array();
|
$newFiles = array();
|
||||||
@ -285,6 +357,7 @@ function uupGetFiles(
|
|||||||
$filesNew = array();
|
$filesNew = array();
|
||||||
foreach($filesInfoKeys as $val) {
|
foreach($filesInfoKeys as $val) {
|
||||||
$filesNew[$val] = $filesInfoList[$val];
|
$filesNew[$val] = $filesInfoList[$val];
|
||||||
|
$filesNew[$val]['url'] = uupApiFixDownloadLink($filesInfoList[$val]['url']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$files = $filesNew;
|
$files = $filesNew;
|
||||||
@ -292,48 +365,53 @@ function uupGetFiles(
|
|||||||
|
|
||||||
consoleLogger('Successfully parsed the information.');
|
consoleLogger('Successfully parsed the information.');
|
||||||
|
|
||||||
return array(
|
$data = [
|
||||||
'apiVersion' => uupApiVersion(),
|
'apiVersion' => uupApiVersion(),
|
||||||
'updateName' => $updateName,
|
'updateName' => $updateName,
|
||||||
'arch' => $updateArch,
|
'arch' => $updateArch,
|
||||||
'build' => $updateBuild,
|
'build' => $updateBuild,
|
||||||
'sku' => $updateSku,
|
'sku' => $updateSku,
|
||||||
|
'hasUpdates' => $hasUpdates,
|
||||||
'files' => $files,
|
'files' => $files,
|
||||||
);
|
];
|
||||||
|
|
||||||
|
if($requestType > 0) {
|
||||||
|
$cacheData = $data;
|
||||||
|
$cache->put($cacheData, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests, $type) {
|
function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests, $type) {
|
||||||
$cacheHash = hash('sha256', strtolower("api-get-${updateId}_rev.$rev"));
|
$res = "api-get-online-{$updateId}_rev.$rev";
|
||||||
$cached = 0;
|
$cache = new UupDumpCache($res);
|
||||||
|
$fromCache = $cache->get();
|
||||||
|
$cached = ($fromCache !== false);
|
||||||
|
|
||||||
if(file_exists('cache/'.$cacheHash.'.json.gz') && $cacheRequests == 1) {
|
if($cached) {
|
||||||
$cache = @gzdecode(@file_get_contents('cache/'.$cacheHash.'.json.gz'));
|
$out = $fromCache['out'];
|
||||||
$cache = json_decode($cache, 1);
|
$fetchTime = $fromCache['fetchTime'];
|
||||||
|
|
||||||
if(!empty($cache['content']) && ($cache['expires'] > time())) {
|
|
||||||
consoleLogger('Using cached response...');
|
|
||||||
$out = $cache['content'];
|
|
||||||
$fetchTime = $cache['fetchTime'];
|
|
||||||
$cached = 1;
|
|
||||||
} else {
|
} else {
|
||||||
$cached = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unset($cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$cached) {
|
|
||||||
$fetchTime = time();
|
$fetchTime = time();
|
||||||
consoleLogger('Fetching information from the server...');
|
consoleLogger('Fetching information from the server...');
|
||||||
$postData = composeFileGetRequest($updateId, uupDevice(), $info, $rev, $type);
|
|
||||||
$out = sendWuPostRequest('https://fe3cr.delivery.mp.microsoft.com/ClientWebService/client.asmx/secured', $postData);
|
$composerArgs = [$updateId, $info, $rev, $type];
|
||||||
|
$out = sendWuPostRequestHelper('clientSecured', 'composeFileGetRequest', $composerArgs);
|
||||||
|
|
||||||
|
if($out['error'] != 200) {
|
||||||
|
consoleLogger('The request has failed');
|
||||||
|
return array('error' => 'WU_REQUEST_FAILED');
|
||||||
|
}
|
||||||
|
|
||||||
|
$out = $out['out'];
|
||||||
consoleLogger('Information has been successfully fetched.');
|
consoleLogger('Information has been successfully fetched.');
|
||||||
}
|
}
|
||||||
|
|
||||||
consoleLogger('Parsing information...');
|
consoleLogger('Parsing information...');
|
||||||
$xmlOut = @simplexml_load_string($out);
|
$xmlOut = @simplexml_load_string($out);
|
||||||
if($xmlOut === false) {
|
if($xmlOut === false) {
|
||||||
@unlink('cache/'.$cacheHash.'.json.gz');
|
$cache->delete();
|
||||||
return array('error' => 'XML_PARSE_ERROR');
|
return array('error' => 'XML_PARSE_ERROR');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,15 +459,11 @@ function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests, $type) {
|
|||||||
if($sha256capable) {
|
if($sha256capable) {
|
||||||
$tempname = uupCleanSha256($name);
|
$tempname = uupCleanSha256($name);
|
||||||
if(isset($files[$tempname])) {
|
if(isset($files[$tempname])) {
|
||||||
if(preg_match('/\.cab$/i', $tempname)) {
|
|
||||||
if($size > $files[$tempname]['size']) {
|
if($size > $files[$tempname]['size']) {
|
||||||
$express = 'baseless_'.$tempname;
|
$smaller = uupAppendSha1($tempname, $files[$tempname]['sha1']);
|
||||||
$files[$express] = $files[$tempname];
|
$files[$smaller] = $files[$tempname];
|
||||||
unset($files[$tempname]);
|
unset($files[$tempname]);
|
||||||
$newName = $tempname;
|
$newName = $tempname;
|
||||||
} else {
|
|
||||||
$newName = 'baseless_'.$tempname;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$newName = uupAppendSha1($tempname, $sha1);
|
$newName = uupAppendSha1($tempname, $sha1);
|
||||||
}
|
}
|
||||||
@ -433,14 +507,12 @@ function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests, $type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($cacheRequests == 1 && $cached == 0) {
|
if($cacheRequests == 1 && $cached == 0) {
|
||||||
$cache = array(
|
$cacheData = [
|
||||||
'expires' => time()+90,
|
'out' => $out,
|
||||||
'content' => $out,
|
|
||||||
'fetchTime' => $fetchTime,
|
'fetchTime' => $fetchTime,
|
||||||
);
|
];
|
||||||
|
|
||||||
if(!file_exists('cache')) mkdir('cache');
|
$cache->put($cacheData, 90);
|
||||||
@file_put_contents('cache/'.$cacheHash.'.json.gz', gzencode(json_encode($cache)."\n"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $files;
|
return $files;
|
||||||
@ -462,24 +534,14 @@ function uupGetOfflineFiles($info) {
|
|||||||
$sha256 = isset($val['sha256']) ? $val['sha256'] : null;
|
$sha256 = isset($val['sha256']) ? $val['sha256'] : null;
|
||||||
|
|
||||||
if($sha256capable) {
|
if($sha256capable) {
|
||||||
// clean file name
|
|
||||||
$tempname = uupCleanSha256($name);
|
$tempname = uupCleanSha256($name);
|
||||||
if(isset($files[$tempname])) {
|
if(isset($files[$tempname])) {
|
||||||
// check existing file with the same name
|
|
||||||
if(preg_match('/\.cab$/i', $tempname)) {
|
|
||||||
// compare cab files only
|
|
||||||
if($size > $files[$tempname]['size']) {
|
if($size > $files[$tempname]['size']) {
|
||||||
// if the existing file is smaller, rename it
|
$smaller = uupAppendSha1($tempname, $files[$tempname]['sha1']);
|
||||||
$express = 'baseless_'.$tempname;
|
$files[$smaller] = $files[$tempname];
|
||||||
$files[$express] = $files[$tempname];
|
|
||||||
unset($files[$tempname]);
|
unset($files[$tempname]);
|
||||||
$newName = $tempname;
|
$newName = $tempname;
|
||||||
} else {
|
} else {
|
||||||
// if the new file is smaller, rename it
|
|
||||||
$newName = 'baseless_'.$tempname;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// not a cab file, append hash to differentiate
|
|
||||||
$newName = uupAppendSha1($tempname, $sha1);
|
$newName = uupAppendSha1($tempname, $sha1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -518,8 +580,7 @@ function uupAppendSha1($name, $sha1) {
|
|||||||
|
|
||||||
function uupCleanSha256($name) {
|
function uupCleanSha256($name) {
|
||||||
$replace = array(
|
$replace = array(
|
||||||
'MetadataESD_' => null,
|
'prss_signed_appx_' => null,
|
||||||
'metadataesd_' => null,
|
|
||||||
'~31bf3856ad364e35' => null,
|
'~31bf3856ad364e35' => null,
|
||||||
'~~.' => '.',
|
'~~.' => '.',
|
||||||
'~.' => '.',
|
'~.' => '.',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
Copyright 2019 UUP dump API authors
|
Copyright 2022 UUP dump API authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -21,7 +21,7 @@ require_once dirname(__FILE__).'/updateinfo.php';
|
|||||||
|
|
||||||
function uupListEditions($lang = 'en-us', $updateId = 0) {
|
function uupListEditions($lang = 'en-us', $updateId = 0) {
|
||||||
if($updateId) {
|
if($updateId) {
|
||||||
$info = uupUpdateInfo($updateId);
|
$info = uupUpdateInfo($updateId, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$lang) {
|
if(!$lang) {
|
||||||
@ -56,6 +56,7 @@ function uupListEditions($lang = 'en-us', $updateId = 0) {
|
|||||||
$editionListFancy = array();
|
$editionListFancy = array();
|
||||||
foreach(array_keys($genPack[$lang]) as $edition) {
|
foreach(array_keys($genPack[$lang]) as $edition) {
|
||||||
if($edition == 'LXP') continue;
|
if($edition == 'LXP') continue;
|
||||||
|
if($edition == 'FOD') continue;
|
||||||
|
|
||||||
if(isset($fancyEditionNames[$edition])) {
|
if(isset($fancyEditionNames[$edition])) {
|
||||||
$fancyName = $fancyEditionNames[$edition];
|
$fancyName = $fancyEditionNames[$edition];
|
||||||
|
59
listid.php
59
listid.php
@ -16,22 +16,31 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
require_once dirname(__FILE__).'/shared/main.php';
|
require_once dirname(__FILE__).'/shared/main.php';
|
||||||
|
require_once dirname(__FILE__).'/shared/cache.php';
|
||||||
|
require_once dirname(__FILE__).'/shared/fileinfo.php';
|
||||||
|
|
||||||
function uupListIds($search = null, $sortByDate = 0) {
|
function uupApiPrivateInvalidateFileinfoCache() {
|
||||||
uupApiPrintBrand();
|
$cache1 = new UupDumpCache('listid-0', false);
|
||||||
|
$cache2 = new UupDumpCache('listid-1', false);
|
||||||
|
|
||||||
if(!file_exists('fileinfo')) return array('error' => 'NO_FILEINFO_DIR');
|
$cache1->delete();
|
||||||
|
$cache2->delete();
|
||||||
|
}
|
||||||
|
|
||||||
$files = scandir('fileinfo');
|
function uupApiPrivateGetFromFileinfo($sortByDate = 0) {
|
||||||
|
$dirs = uupApiGetFileinfoDirs();
|
||||||
|
$fileinfo = $dirs['fileinfoData'];
|
||||||
|
$fileinfoRoot = $dirs['fileinfo'];
|
||||||
|
|
||||||
|
$files = scandir($fileinfo);
|
||||||
$files = preg_grep('/\.json$/', $files);
|
$files = preg_grep('/\.json$/', $files);
|
||||||
|
|
||||||
consoleLogger('Parsing database info...');
|
consoleLogger('Parsing database info...');
|
||||||
|
|
||||||
$cacheFile = 'cache/fileinfo_v2.json';
|
$cacheFile = $fileinfoRoot.'/cache.json';
|
||||||
$cacheV2Version = 1;
|
$cacheV2Version = 1;
|
||||||
|
|
||||||
$database = @file_get_contents($cacheFile);
|
$database = uupApiReadJson($cacheFile);
|
||||||
$database = json_decode($database, true);
|
|
||||||
|
|
||||||
if(isset($database['version'])) {
|
if(isset($database['version'])) {
|
||||||
$version = $database['version'];
|
$version = $database['version'];
|
||||||
@ -50,12 +59,13 @@ function uupListIds($search = null, $sortByDate = 0) {
|
|||||||
$newDb = array();
|
$newDb = array();
|
||||||
$builds = array();
|
$builds = array();
|
||||||
foreach($files as $file) {
|
foreach($files as $file) {
|
||||||
if($file == '.' || $file == '..') continue;
|
if($file == '.' || $file == '..')
|
||||||
|
continue;
|
||||||
|
|
||||||
$uuid = preg_replace('/\.json$/', '', $file);
|
$uuid = preg_replace('/\.json$/', '', $file);
|
||||||
|
|
||||||
if(!isset($database[$uuid])) {
|
if(!isset($database[$uuid])) {
|
||||||
$info = @file_get_contents('fileinfo/'.$file);
|
$info = uupApiReadFileinfoMeta($uuid);
|
||||||
$info = json_decode($info, true);
|
|
||||||
|
|
||||||
$title = isset($info['title']) ? $info['title'] : 'UNKNOWN';
|
$title = isset($info['title']) ? $info['title'] : 'UNKNOWN';
|
||||||
$build = isset($info['build']) ? $info['build'] : 'UNKNOWN';
|
$build = isset($info['build']) ? $info['build'] : 'UNKNOWN';
|
||||||
@ -105,12 +115,7 @@ function uupListIds($search = null, $sortByDate = 0) {
|
|||||||
$builds[$tmp.$arch.$title.$uuid] = $temp;
|
$builds[$tmp.$arch.$title.$uuid] = $temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(empty($buildAssoc)) {
|
if(empty($buildAssoc)) return [];
|
||||||
return array(
|
|
||||||
'apiVersion' => uupApiVersion(),
|
|
||||||
'builds' => array(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
krsort($buildAssoc);
|
krsort($buildAssoc);
|
||||||
$buildsNew = array();
|
$buildsNew = array();
|
||||||
@ -141,7 +146,27 @@ function uupListIds($search = null, $sortByDate = 0) {
|
|||||||
if(!$success) consoleLogger('Failed to update database cache.');
|
if(!$success) consoleLogger('Failed to update database cache.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if($search) {
|
return $builds;
|
||||||
|
}
|
||||||
|
|
||||||
|
function uupListIds($search = null, $sortByDate = 0) {
|
||||||
|
uupApiPrintBrand();
|
||||||
|
|
||||||
|
$sortByDate = $sortByDate ? 1 : 0;
|
||||||
|
|
||||||
|
$res = "listid-$sortByDate";
|
||||||
|
$cache = new UupDumpCache($res, false);
|
||||||
|
$builds = $cache->get();
|
||||||
|
$cached = ($builds !== false);
|
||||||
|
|
||||||
|
if(!$cached) {
|
||||||
|
$builds = uupApiPrivateGetFromFileinfo($sortByDate);
|
||||||
|
if($builds === false) return ['error' => 'NO_FILEINFO_DIR'];
|
||||||
|
|
||||||
|
$cache->put($builds, 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count($builds) && $search != null) {
|
||||||
if(!preg_match('/^regex:/', $search)) {
|
if(!preg_match('/^regex:/', $search)) {
|
||||||
$searchSafe = preg_quote($search, '/');
|
$searchSafe = preg_quote($search, '/');
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
Copyright 2019 UUP dump API authors
|
Copyright 2022 UUP dump API authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -21,7 +21,7 @@ require_once dirname(__FILE__).'/updateinfo.php';
|
|||||||
|
|
||||||
function uupListLangs($updateId = 0) {
|
function uupListLangs($updateId = 0) {
|
||||||
if($updateId) {
|
if($updateId) {
|
||||||
$info = uupUpdateInfo($updateId);
|
$info = uupUpdateInfo($updateId, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isset($info['info'])) {
|
if(isset($info['info'])) {
|
||||||
@ -50,6 +50,9 @@ function uupListLangs($updateId = 0) {
|
|||||||
if(!count(array_diff(array_keys($val), array('LXP')))) {
|
if(!count(array_diff(array_keys($val), array('LXP')))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if(!count(array_diff(array_keys($val), array('FOD')))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(isset($fancyLangNames[$key])) {
|
if(isset($fancyLangNames[$key])) {
|
||||||
$fancyName = $fancyLangNames[$key];
|
$fancyName = $fancyLangNames[$key];
|
||||||
|
30
readme.md
30
readme.md
@ -10,7 +10,7 @@ Parameters:
|
|||||||
- **Supported values:** `amd64`, `x86`, `arm64`, `all`
|
- **Supported values:** `amd64`, `x86`, `arm64`, `all`
|
||||||
|
|
||||||
- `ring` - Channel to use when fetching information (Previously called Ring)
|
- `ring` - Channel to use when fetching information (Previously called Ring)
|
||||||
- **Supported values:** `Dev`, `Beta`, `ReleasePreview`, `Retail`
|
- **Supported values:** `Canary`, `Dev`, `Beta`, `ReleasePreview`, `Retail`
|
||||||
- **Supported Ring values :** `WIF`, `WIS`, `RP`
|
- **Supported Ring values :** `WIF`, `WIS`, `RP`
|
||||||
|
|
||||||
- `flight` - Content type to use when fetching information (Previously called Flight)
|
- `flight` - Content type to use when fetching information (Previously called Flight)
|
||||||
@ -82,7 +82,7 @@ Parameters:
|
|||||||
- **Supported values:** any update UUID
|
- **Supported values:** any update UUID
|
||||||
|
|
||||||
|
|
||||||
#### updateinfo.php: `uupUpdateInfo($updateId, $onlyInfo);`
|
#### updateinfo.php: `uupUpdateInfo($updateId, $onlyInfo, $ignoreFiles);`
|
||||||
Outputs specified information of specified `updateId`.
|
Outputs specified information of specified `updateId`.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
@ -92,12 +92,36 @@ Parameters:
|
|||||||
- `onlyInfo` - Key to output
|
- `onlyInfo` - Key to output
|
||||||
- **Supported values:** any string
|
- **Supported values:** any string
|
||||||
|
|
||||||
|
- `ignoreFiles` - Skips the `files` key in the output
|
||||||
|
- **Supported values:** `true` or `false`
|
||||||
|
|
||||||
#### shared/main.php: `uupApiVersion();`
|
#### shared/main.php: `uupApiVersion();`
|
||||||
Returns version of the API.
|
Returns version of the API.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- None
|
- None
|
||||||
|
|
||||||
|
#### shared/utils.php: `uupApiCheckUpdateId($updateId);`
|
||||||
|
Checks if the provided update ID is correctly formatted.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- `updateId` - update ID to check
|
||||||
|
- **Supported values:** Any string
|
||||||
|
|
||||||
|
#### shared/utils.php: `uupApiIsServer($skuId);`
|
||||||
|
Checks if the provided SKU ID is a Windows Sever SKU.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- `skuId` - SKU ID to check
|
||||||
|
- **Supported values:** Any integer
|
||||||
|
|
||||||
|
#### shared/utils.php: `uupApiBuildMajor($build);`
|
||||||
|
Returns a build major of the build number.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- `build` - Build number (for example 22621.1) to split
|
||||||
|
- **Supported values:** Any correctly formatted build number
|
||||||
|
|
||||||
### Error codes thrown by API
|
### Error codes thrown by API
|
||||||
**fetchupd.php**
|
**fetchupd.php**
|
||||||
- UNKNOWN_ARCH
|
- UNKNOWN_ARCH
|
||||||
@ -108,6 +132,7 @@ Parameters:
|
|||||||
- ILLEGAL_MINOR
|
- ILLEGAL_MINOR
|
||||||
- NO_UPDATE_FOUND
|
- NO_UPDATE_FOUND
|
||||||
- EMPTY_FILELIST
|
- EMPTY_FILELIST
|
||||||
|
- WU_REQUEST_FAILED
|
||||||
|
|
||||||
**get.php**
|
**get.php**
|
||||||
- UNSUPPORTED_LANG
|
- UNSUPPORTED_LANG
|
||||||
@ -118,6 +143,7 @@ Parameters:
|
|||||||
- MISSING_FILES
|
- MISSING_FILES
|
||||||
- NO_FILES
|
- NO_FILES
|
||||||
- XML_PARSE_ERROR
|
- XML_PARSE_ERROR
|
||||||
|
- WU_REQUEST_FAILED
|
||||||
|
|
||||||
**listeditions.php**
|
**listeditions.php**
|
||||||
- UNSUPPORTED_LANG
|
- UNSUPPORTED_LANG
|
||||||
|
@ -25,19 +25,43 @@ function uupDevice() {
|
|||||||
return base64_encode(chunk_split($data, 1, "\0"));
|
return base64_encode(chunk_split($data, 1, "\0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function uupSaveCookieFromResponse($out) {
|
||||||
|
$outDecoded = html_entity_decode($out);
|
||||||
|
preg_match('/<NewCookie>.*?<\/NewCookie>|<GetCookieResult>.*?<\/GetCookieResult>/', $outDecoded, $cookieData);
|
||||||
|
|
||||||
|
if(empty($cookieData))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
preg_match('/<Expiration>.*<\/Expiration>/', $cookieData[0], $expirationDate);
|
||||||
|
preg_match('/<EncryptedData>.*<\/EncryptedData>/', $cookieData[0], $encryptedData);
|
||||||
|
|
||||||
|
$expirationDate = preg_replace('/<Expiration>|<\/Expiration>/', '', $expirationDate[0]);
|
||||||
|
$encryptedData = preg_replace('/<EncryptedData>|<\/EncryptedData>/', '', $encryptedData[0]);
|
||||||
|
|
||||||
|
$cookieData = array(
|
||||||
|
'expirationDate' => $expirationDate,
|
||||||
|
'encryptedData' => $encryptedData,
|
||||||
|
);
|
||||||
|
|
||||||
|
$cookieStorage = new UupDumpCache('WuRequestCookie', false);
|
||||||
|
$cookieStorage->put($cookieData, false);
|
||||||
|
|
||||||
|
return $cookieData;
|
||||||
|
}
|
||||||
|
|
||||||
|
function uupInvalidateCookie() {
|
||||||
|
$cookieStorage = new UupDumpCache('WuRequestCookie', false);
|
||||||
|
$cookieInfo = $cookieStorage->delete();
|
||||||
|
}
|
||||||
|
|
||||||
function uupEncryptedData() {
|
function uupEncryptedData() {
|
||||||
$cookieInfo = @file_get_contents(dirname(__FILE__).'/cookie.json');
|
$cookieStorage = new UupDumpCache('WuRequestCookie', false);
|
||||||
$cookieInfo = json_decode($cookieInfo, 1);
|
$cookieInfo = $cookieStorage->get();
|
||||||
|
|
||||||
if(empty($cookieInfo)) {
|
if(empty($cookieInfo)) {
|
||||||
$postData = composeGetCookieRequest(uupDevice());
|
$data = sendWuPostRequestHelper('client', 'composeGetCookieRequest', [], false);
|
||||||
sendWuPostRequest('https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx', $postData);
|
$cookieInfo = uupSaveCookieFromResponse($data['out']);
|
||||||
|
|
||||||
$encData = uupEncryptedData();
|
|
||||||
} else {
|
|
||||||
$encData = $cookieInfo['encryptedData'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $encData;
|
return $cookieInfo['encryptedData'];
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
76
shared/cache.php
Normal file
76
shared/cache.php
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
Copyright 2022 eraseyourknees
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class UupDumpCache {
|
||||||
|
private $cacheFile;
|
||||||
|
private $newCacheVersion = 1;
|
||||||
|
|
||||||
|
public function __construct($resource, private $isCompressed = true) {
|
||||||
|
$res = $resource."+cache_v".$this->newCacheVersion;
|
||||||
|
$cacheHash = hash('sha256', strtolower($res));
|
||||||
|
$ext = $isCompressed ? '.json.gz' : '.json';
|
||||||
|
$this->cacheFile = 'cache/'.$cacheHash.$ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFileName() {
|
||||||
|
return $this->cacheFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete() {
|
||||||
|
@unlink($this->cacheFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get() {
|
||||||
|
$cacheFile = $this->cacheFile;
|
||||||
|
|
||||||
|
if(!file_exists($cacheFile)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache = @file_get_contents($cacheFile);
|
||||||
|
if($this->isCompressed) $cache = @gzdecode($cache);
|
||||||
|
|
||||||
|
$cache = json_decode($cache, 1);
|
||||||
|
|
||||||
|
$expires = $cache['expires'];
|
||||||
|
$isExpired = ($expires !== false) && (time() > $expires);
|
||||||
|
|
||||||
|
if(empty($cache['content']) || $isExpired) {
|
||||||
|
$this->delete();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cache['content'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function put($content, $validity) {
|
||||||
|
$cacheFile = $this->cacheFile;
|
||||||
|
$expires = $validity ? time() + $validity : false;
|
||||||
|
|
||||||
|
$cache = array(
|
||||||
|
'expires' => $expires,
|
||||||
|
'content' => $content,
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!file_exists('cache')) mkdir('cache');
|
||||||
|
|
||||||
|
$cacheContent = json_encode($cache)."\n";
|
||||||
|
if($this->isCompressed) $cacheContent = @gzencode($cacheContent);
|
||||||
|
|
||||||
|
@file_put_contents($cacheFile, $cacheContent);
|
||||||
|
}
|
||||||
|
}
|
94
shared/fileinfo.php
Normal file
94
shared/fileinfo.php
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
Copyright 2022 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__).'/utils.php';
|
||||||
|
|
||||||
|
function uupApiGetFileinfoDirs() {
|
||||||
|
$dirs = [];
|
||||||
|
$dirs['fileinfo'] = 'fileinfo';
|
||||||
|
$dirs['fileinfoMeta'] = $dirs['fileinfo'].'/metadata';
|
||||||
|
$dirs['fileinfoData'] = $dirs['fileinfo'].'/full';
|
||||||
|
|
||||||
|
foreach($dirs as $dir) {
|
||||||
|
if(!file_exists($dir)) mkdir($dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function uupApiGetFileinfoName($updateId, $meta = false) {
|
||||||
|
$fileName = $updateId.'.json';
|
||||||
|
$dirs = uupApiGetFileinfoDirs();
|
||||||
|
|
||||||
|
$fileinfoMeta = $dirs['fileinfoMeta'].'/'.$fileName;
|
||||||
|
$fileinfoData = $dirs['fileinfoData'].'/'.$fileName;
|
||||||
|
|
||||||
|
return $meta ? $fileinfoMeta : $fileinfoData;
|
||||||
|
}
|
||||||
|
|
||||||
|
function uupApiFileInfoExists($updateId) {
|
||||||
|
return file_exists(uupApiGetFileinfoName($updateId));
|
||||||
|
}
|
||||||
|
|
||||||
|
function uupApiWriteFileinfoMeta($updateId, $info) {
|
||||||
|
if(isset($info['files']))
|
||||||
|
unset($info['files']);
|
||||||
|
|
||||||
|
$file = uupApiGetFileinfoName($updateId, true);
|
||||||
|
return uupApiWriteJson($file, $info);
|
||||||
|
}
|
||||||
|
|
||||||
|
function uupApiWriteFileinfo($updateId, $info) {
|
||||||
|
$file = uupApiGetFileinfoName($updateId);
|
||||||
|
|
||||||
|
if(uupApiWriteJson($file, $info) === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return uupApiWriteFileinfoMeta($updateId, $info);
|
||||||
|
}
|
||||||
|
|
||||||
|
function uupApiReadFileinfoMeta($updateId) {
|
||||||
|
$file = uupApiGetFileinfoName($updateId, true);
|
||||||
|
|
||||||
|
if(file_exists($file))
|
||||||
|
return uupApiReadJson($file);
|
||||||
|
|
||||||
|
$info = uupApiReadFileinfo($updateId, false);
|
||||||
|
if($info === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(isset($info['files']))
|
||||||
|
unset($info['files']);
|
||||||
|
|
||||||
|
if(uupApiWriteFileinfoMeta($updateId, $info) === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return $info;
|
||||||
|
}
|
||||||
|
|
||||||
|
function uupApiReadFileinfo($updateId, $meta = false) {
|
||||||
|
if(!uupApiFileInfoExists($updateId))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if($meta === true)
|
||||||
|
return uupApiReadFileinfoMeta($updateId);
|
||||||
|
|
||||||
|
$file = uupApiGetFileinfoName($updateId);
|
||||||
|
$info = uupApiReadJson($file);
|
||||||
|
|
||||||
|
return $info;
|
||||||
|
}
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function uupApiVersion() {
|
function uupApiVersion() {
|
||||||
return '1.32.0';
|
return '1.41.0';
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once dirname(__FILE__).'/auths.php';
|
require_once dirname(__FILE__).'/auths.php';
|
||||||
|
165
shared/packs.php
165
shared/packs.php
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
Copyright 2021 UUP dump API authors
|
Copyright 2022 UUP dump API authors
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -19,6 +19,7 @@ require_once dirname(__FILE__).'/../listid.php';
|
|||||||
|
|
||||||
function uupGetInfoTexts() {
|
function uupGetInfoTexts() {
|
||||||
$fancyLangNames = array(
|
$fancyLangNames = array(
|
||||||
|
'neutral' => 'Any Language',
|
||||||
'ar-sa' => 'Arabic (Saudi Arabia)',
|
'ar-sa' => 'Arabic (Saudi Arabia)',
|
||||||
'bg-bg' => 'Bulgarian',
|
'bg-bg' => 'Bulgarian',
|
||||||
'cs-cz' => 'Czech',
|
'cs-cz' => 'Czech',
|
||||||
@ -61,6 +62,9 @@ function uupGetInfoTexts() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
$fancyEditionNames = array(
|
$fancyEditionNames = array(
|
||||||
|
'APP' => 'Microsoft Store Inbox Apps',
|
||||||
|
'APP_MOMENT' => 'Microsoft Store Moment Apps',
|
||||||
|
'FOD' => 'Features on Demand (Capabilities)',
|
||||||
'CLOUD' => 'Windows S',
|
'CLOUD' => 'Windows S',
|
||||||
'CLOUDN' => 'Windows S N',
|
'CLOUDN' => 'Windows S N',
|
||||||
'CLOUDE' => 'Windows Lean',
|
'CLOUDE' => 'Windows Lean',
|
||||||
@ -199,165 +203,12 @@ function uupGetInfoTexts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function uupGetGenPacks($build = 15063, $arch = null, $updateId = null) {
|
function uupGetGenPacks($build = 15063, $arch = null, $updateId = null) {
|
||||||
$internalPacks = dirname(__FILE__).'/packs';
|
if(empty($updateId)) return [];
|
||||||
|
if(!file_exists('packs/'.$updateId.'.json.gz')) return [];
|
||||||
|
|
||||||
if(!file_exists($internalPacks.'/metadata.json')) {
|
|
||||||
if(!uupCreateInternalPacksMetadata($internalPacks)) {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!empty($updateId)) {
|
|
||||||
if(file_exists('packs/'.$updateId.'.json.gz')) {
|
|
||||||
$genPack = @gzdecode(@file_get_contents('packs/'.$updateId.'.json.gz'));
|
$genPack = @gzdecode(@file_get_contents('packs/'.$updateId.'.json.gz'));
|
||||||
if(empty($genPack)) return array();
|
if(empty($genPack)) return [];
|
||||||
|
|
||||||
$genPack = json_decode($genPack, 1);
|
$genPack = json_decode($genPack, 1);
|
||||||
return $genPack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$metadata = @file_get_contents($internalPacks.'/metadata.json');
|
|
||||||
if(empty($metadata)) {
|
|
||||||
return array();
|
|
||||||
} else {
|
|
||||||
$metadata = json_decode($metadata, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$hashDetermined = 0;
|
|
||||||
$useAllHashesForBuild = 0;
|
|
||||||
|
|
||||||
if($updateId) {
|
|
||||||
if(isset($metadata['knownIds'][$updateId])) {
|
|
||||||
$hash = $metadata['knownIds'][$updateId];
|
|
||||||
$hashDetermined = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$hashDetermined) {
|
|
||||||
foreach($metadata['knownBuilds'] as $buildNum => $val) {
|
|
||||||
if($build < $buildNum) continue;
|
|
||||||
$useBuild = $buildNum;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!isset($useBuild)) {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$arch && !isset($metadata['knownBuilds'][$useBuild][$arch])) {
|
|
||||||
$genPack = array();
|
|
||||||
foreach($metadata['knownBuilds'][$useBuild] as $hash) {
|
|
||||||
$temp = @gzdecode(@file_get_contents($internalPacks.'/'.$hash.'.json.gz'));
|
|
||||||
if(!empty($temp)) {
|
|
||||||
$temp = json_decode($temp, 1);
|
|
||||||
$genPack = array_merge_recursive($genPack, $temp);
|
|
||||||
unset($temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} elseif(!isset($metadata['knownBuilds'][$useBuild][$arch])) {
|
|
||||||
return array();
|
|
||||||
} else {
|
|
||||||
$hash = $metadata['knownBuilds'][$useBuild][$arch];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!isset($genPack)) {
|
|
||||||
$genPack = @gzdecode(@file_get_contents($internalPacks.'/'.$hash.'.json.gz'));
|
|
||||||
if(!empty($genPack)) {
|
|
||||||
$genPack = json_decode($genPack, 1);
|
|
||||||
} else {
|
|
||||||
$genPack = array();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $genPack;
|
return $genPack;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Function to regenerate internal packs. Should not be used when not needed.
|
|
||||||
function uupCreateInternalPacksMetadata($internalPacks) {
|
|
||||||
$metadataCreationAllowed = 0;
|
|
||||||
if(!$metadataCreationAllowed) return false;
|
|
||||||
|
|
||||||
$builds = uupListIds();
|
|
||||||
if(isset($ids['error'])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$builds = $builds['builds'];
|
|
||||||
|
|
||||||
if(!file_exists('packs')) return false;
|
|
||||||
|
|
||||||
if(!file_exists($internalPacks)) {
|
|
||||||
if(!mkdir($internalPacks)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rmdir($internalPacks);
|
|
||||||
mkdir($internalPacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = scandir('packs');
|
|
||||||
$files = preg_grep('/\.json.gz$/', $files);
|
|
||||||
|
|
||||||
$packs = array();
|
|
||||||
foreach($builds as $build) {
|
|
||||||
$uuid = $build['uuid'];
|
|
||||||
$file = $uuid.'.json.gz';
|
|
||||||
|
|
||||||
if(!file_exists('packs/'.$file)) continue;
|
|
||||||
|
|
||||||
$genPack = @gzdecode(@file_get_contents('packs/'.$file));
|
|
||||||
$hash = hash('sha1', $genPack);
|
|
||||||
|
|
||||||
if(!file_exists($internalPacks.'/'.$hash.'.json.gz')) {
|
|
||||||
if(!copy('packs/'.$file, $internalPacks.'/'.$hash.'.json.gz')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$packs['knownIds'][$uuid] = $hash;
|
|
||||||
|
|
||||||
$buildNum = explode('.', $build['build']);
|
|
||||||
$buildNum = $buildNum[0];
|
|
||||||
|
|
||||||
$packs['knownBuilds'][$buildNum][$build['arch']] = $hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_put_contents($internalPacks.'/metadata.json', json_encode($packs)."\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Emulation of legacy packs. Do not use in new scripts due to extremely slow process.
|
|
||||||
function uupGetPacks($build = 15063) {
|
|
||||||
$returnArray = uupGetInfoTexts();
|
|
||||||
$genPack = uupGetGenPacks($build);
|
|
||||||
|
|
||||||
foreach($genPack as $lang => $editions) {
|
|
||||||
$packsForLangs[$lang] = array_keys($editions);
|
|
||||||
$packsForLangs[$lang][] = $lang;
|
|
||||||
|
|
||||||
foreach(array_keys($editions) as $edition) {
|
|
||||||
foreach($editions[$edition] as $name) {
|
|
||||||
$newName = preg_replace('/^cabs_|^metadataesd_|~31bf3856ad364e35/i', '', $name);
|
|
||||||
$newName = preg_replace('/~~\.|~\./', '.', $newName);
|
|
||||||
$newName = preg_replace('/~/', '-', $newName);
|
|
||||||
$newName = strtolower($newName);
|
|
||||||
$packs[$lang][$edition][] = $newName;
|
|
||||||
}
|
|
||||||
|
|
||||||
$editionPacks[$edition] = $edition;
|
|
||||||
$packs[$edition][$edition] = array();
|
|
||||||
$skipNeutral[$edition] = 1;
|
|
||||||
$skipLangPack[$edition] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$returnArray['packs'] = $packs;
|
|
||||||
$returnArray['packsForLangs'] = $packsForLangs;
|
|
||||||
$returnArray['editionPacks'] = $editionPacks;
|
|
||||||
$returnArray['skipNeutral'] = $skipNeutral;
|
|
||||||
$returnArray['skipLangPack'] = $skipLangPack;
|
|
||||||
|
|
||||||
return $returnArray;
|
|
||||||
}
|
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user