forked from uup-dump/api
Compare commits
99 Commits
sha256-san
...
master
Author | SHA1 | Date | |
---|---|---|---|
7b3cd4eb10 | |||
c1f00cecbd | |||
8b576e4496 | |||
21b1500490 | |||
fb2c89b2f8 | |||
846feb2629 | |||
5e31a6f724 | |||
faa3b7fa45 | |||
42b1091c0b | |||
aa2dbd2938 | |||
42c1c12405 | |||
092e968f0c | |||
d58f53de42 | |||
ca81835609 | |||
d10e24cf5b | |||
140613f657 | |||
4694c8dc00 | |||
0477fd5fa6 | |||
1ef84cb879 | |||
9e618c405a | |||
7711645f23 | |||
d597a83422 | |||
d0bad95c11 | |||
2a57ae0fe6 | |||
7bdc01bdb9 | |||
b13403cf59 | |||
5777ff09b6 | |||
954547ea84 | |||
db1e155c8d | |||
543e4c52e4 | |||
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
|
222
fetchupd.php
222
fetchupd.php
@ -17,8 +17,87 @@ limitations under the License.
|
||||
|
||||
require_once dirname(__FILE__).'/shared/main.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';
|
||||
|
||||
function uupApiPrivateParseFlags($str) {
|
||||
$split = explode('+', $str);
|
||||
$flagsSafe = [];
|
||||
|
||||
if(isset($split[1])) {
|
||||
$flags = array_unique(explode(',', strtolower($split[1])));
|
||||
$flagsSafe = array_intersect(getAllowedFlags(), $flags);
|
||||
}
|
||||
|
||||
return [$split[0], $flagsSafe];
|
||||
}
|
||||
|
||||
function uupApiPrivateGetLatestBuild() {
|
||||
$builds = array('22000.1');
|
||||
|
||||
$ids = uupListIds();
|
||||
if(isset($ids['error'])) {
|
||||
$ids['builds'] = array();
|
||||
}
|
||||
|
||||
if(empty($ids['builds'])) {
|
||||
$build = $builds[0];
|
||||
} else {
|
||||
$build = $ids['builds'][0]['build'];
|
||||
}
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
function uupApiPrivateGetAcceptableBranches() {
|
||||
return [
|
||||
'auto',
|
||||
'rs2_release',
|
||||
'rs3_release',
|
||||
'rs4_release',
|
||||
'rs5_release',
|
||||
'rs5_release_svc_hci',
|
||||
'19h1_release',
|
||||
'vb_release',
|
||||
'fe_release_10x',
|
||||
'fe_release',
|
||||
'co_release',
|
||||
'ni_release',
|
||||
'zn_release',
|
||||
'ge_release',
|
||||
'rs_prerelease',
|
||||
];
|
||||
}
|
||||
|
||||
function uupApiPrivateNormalizeFetchParams($params) {
|
||||
$np = array_replace([
|
||||
'arch' => 'amd64',
|
||||
'ring' => 'WIF',
|
||||
'flight' => 'Active',
|
||||
'branch' => 'ge_release',
|
||||
'build' => 'latest',
|
||||
'minor' => 0,
|
||||
'sku' => 48,
|
||||
'type' => 'Production',
|
||||
'flags' => [],
|
||||
], $params);
|
||||
|
||||
if(!is_array($np['flags'])) $np['flags'] = [];
|
||||
|
||||
$np['arch'] = strtolower($np['arch']);
|
||||
$np['ring'] = strtoupper($np['ring']);
|
||||
$np['flight'] = ucwords(strtolower($np['flight']));
|
||||
$np['branch'] = strtolower($np['branch']);
|
||||
$np['build'] = strtolower($np['build']);
|
||||
$np['minor'] = intval($np['minor']);
|
||||
$np['sku'] = intval($np['sku']);
|
||||
$np['type'] = ucwords(strtolower($np['type']));
|
||||
$np['flags'] = array_map('strtolower', $np['flags']);
|
||||
|
||||
return $np;
|
||||
}
|
||||
|
||||
function uupFetchUpd(
|
||||
$arch = 'amd64',
|
||||
$ring = 'WIF',
|
||||
@ -29,35 +108,52 @@ function uupFetchUpd(
|
||||
$type = 'Production',
|
||||
$cacheRequests = 0
|
||||
) {
|
||||
[$build, $flags] = uupApiPrivateParseFlags($build);
|
||||
|
||||
$params = [
|
||||
'arch' => $arch,
|
||||
'ring' => $ring,
|
||||
'flight' => $flight,
|
||||
'build' => $build,
|
||||
'minor' => $minor,
|
||||
'sku' => $sku,
|
||||
'type' => $type,
|
||||
'flags' => $flags,
|
||||
];
|
||||
|
||||
return uupFetchUpd2($params, $cacheRequests);
|
||||
}
|
||||
|
||||
function uupFetchUpd2($params, $cacheRequests = 0) {
|
||||
uupApiPrintBrand();
|
||||
|
||||
$arch = strtolower($arch);
|
||||
$ring = strtoupper($ring);
|
||||
$flight = ucwords(strtolower($flight));
|
||||
$np = uupApiPrivateNormalizeFetchParams($params);
|
||||
|
||||
$arch = $np['arch'];
|
||||
$ring = $np['ring'];
|
||||
$flight = 'Active';
|
||||
$branch = $np['branch'];
|
||||
$build = $np['build'];
|
||||
$minor = $np['minor'];
|
||||
$sku = $np['sku'];
|
||||
$type = $np['type'];
|
||||
$flags = $np['flags'];
|
||||
|
||||
if($build == 'latest' || (!$build)) {
|
||||
$builds = array('17134.1');
|
||||
$flagsStr = implode(',', $flags);
|
||||
|
||||
$ids = uupListIds();
|
||||
if(isset($ids['error'])) {
|
||||
$ids['builds'] = array();
|
||||
}
|
||||
|
||||
$build = $ids['builds'][0]['build'];
|
||||
unset($builds, $ids);
|
||||
if(strtolower($build) == 'latest' || (!$build)) {
|
||||
$build = uupApiPrivateGetLatestBuild();
|
||||
}
|
||||
|
||||
$build = explode('.', $build);
|
||||
if(isset($build[1])) $minor = intval($build[1]);
|
||||
$build = intval($build[0]);
|
||||
$sku = intval($sku);
|
||||
|
||||
if(!($arch == 'amd64' || $arch == 'x86' || $arch == 'arm64' || $arch == 'arm' || $arch == 'all')) {
|
||||
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');
|
||||
}
|
||||
|
||||
@ -77,6 +173,9 @@ function uupFetchUpd(
|
||||
return array('error' => 'ILLEGAL_MINOR');
|
||||
}
|
||||
|
||||
if(!in_array($branch, uupApiPrivateGetAcceptableBranches()))
|
||||
$branch = 'auto';
|
||||
|
||||
if($ring == 'DEV') $ring = 'WIF';
|
||||
if($ring == 'BETA') $ring = 'WIS';
|
||||
if($ring == 'RELEASEPREVIEW') $ring = 'RP';
|
||||
@ -90,44 +189,21 @@ function uupFetchUpd(
|
||||
$type = 'Production';
|
||||
}
|
||||
|
||||
$cacheHash = hash('sha256', strtolower("api-fetch-$arch-$ring-$flight-$build-$minor-$sku-$type"));
|
||||
$cached = 0;
|
||||
$res = "api-fetch-$arch-$ring-$flight-$branch-$build-$flagsStr-$minor-$sku-$type";
|
||||
$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);
|
||||
consoleLogger('Fetching information from the server...');
|
||||
$composerArgs = [$arch, $flight, $ring, $build, $sku, $type, $flags, $branch];
|
||||
$out = sendWuPostRequestHelper('client', 'composeFetchUpdRequest', $composerArgs);
|
||||
if($out === false || $out['error'] != 200) {
|
||||
consoleLogger('The request has failed');
|
||||
return array('error' => 'WU_REQUEST_FAILED');
|
||||
}
|
||||
|
||||
if(!$cached) {
|
||||
consoleLogger('Fetching information from the server...');
|
||||
$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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
$out = html_entity_decode($out['out']);
|
||||
consoleLogger('Information has been successfully fetched.');
|
||||
|
||||
preg_match_all('/<UpdateInfo>.*?<\/UpdateInfo>/', $out, $updateInfos);
|
||||
$updateInfo = preg_grep('/<IsLeaf>true<\/IsLeaf>/', $updateInfos[0]);
|
||||
@ -147,7 +223,7 @@ function uupFetchUpd(
|
||||
$num++;
|
||||
consoleLogger("Checking build information for update {$num} of {$updatesNum}...");
|
||||
|
||||
$info = parseFetchUpdate($val, $out, $arch, $ring, $flight, $build, $sku, $type);
|
||||
$info = parseFetchUpdate($val, $out, $arch, $ring, $flight, $build, $sku, $type, $flags, $branch);
|
||||
if(isset($info['error'])) {
|
||||
$errorCount++;
|
||||
continue;
|
||||
@ -160,7 +236,7 @@ function uupFetchUpd(
|
||||
return array('error' => 'EMPTY_FILELIST');
|
||||
}
|
||||
|
||||
return array(
|
||||
$data = [
|
||||
'apiVersion' => uupApiVersion(),
|
||||
'updateId' => $updateArray[0]['updateId'],
|
||||
'updateTitle' => $updateArray[0]['updateTitle'],
|
||||
@ -168,10 +244,16 @@ function uupFetchUpd(
|
||||
'arch' => $updateArray[0]['arch'],
|
||||
'fileWrite' => $updateArray[0]['fileWrite'],
|
||||
'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, $flags, $branch) {
|
||||
$updateNumId = preg_replace('/<UpdateInfo><ID>|<\/ID>.*/i', '', $updateInfo);
|
||||
|
||||
$updates = preg_replace('/<Update>/', "\n<Update>", $out);
|
||||
@ -213,6 +295,15 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku
|
||||
$foundBuild = @$info[3];
|
||||
}
|
||||
|
||||
$isNet = 0;
|
||||
if(strpos($foundArch, 'netfx') !== false) {
|
||||
$isNet = 1;
|
||||
preg_match('/ProductReleaseInstalled Name\=".*\.(.*?)\.(.*?)" Version\=".*\.\d{5}\.(.*?)"/', $updateInfo, $info);
|
||||
$foundType = @strtolower($info[1]);
|
||||
$foundArch = @strtolower($info[2]);
|
||||
$foundBuild = @$info[3];
|
||||
}
|
||||
|
||||
$updateTitle = preg_grep('/<Title>.*<\/Title>/', $updateMeta);
|
||||
sort($updateTitle);
|
||||
|
||||
@ -232,13 +323,19 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku
|
||||
$isCumulativeUpdate = 0;
|
||||
if(preg_match('/\d{4}-\d{2}.+Update|Cumulative Update|Microsoft Edge|Windows Feature Experience Pack|Cumulative security Hotpatch/i', $updateTitle)) {
|
||||
$isCumulativeUpdate = 1;
|
||||
$updateTitle = preg_replace('/ for .{3,5}-based systems| \(KB.*?\)/i', '', $updateTitle);
|
||||
if($isNet) {
|
||||
$updateTitle = preg_replace("/3.5 and 4.8.1 |3.5 and 4.8 | for $foundArch| for x64| \(KB.*?\)/i", '', $updateTitle);
|
||||
} else {
|
||||
$updateTitle = preg_replace('/ for .{3,5}-based systems| \(KB.*?\)/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 11', 'Windows Server', $updateTitle);
|
||||
}
|
||||
|
||||
if($sku == 406)
|
||||
$updateTitle = str_replace('Microsoft server operating system', 'Azure Stack HCI', $updateTitle);
|
||||
@ -300,16 +397,16 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku
|
||||
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...');
|
||||
return array('error' => 'CORPNET_ONLY_UPDATE');
|
||||
}
|
||||
|
||||
$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('Parsing information to write...');
|
||||
if(!file_exists('fileinfo')) mkdir('fileinfo');
|
||||
|
||||
$fileList = preg_replace('/<Files>|<\/Files>/', '', $fileList[0]);
|
||||
preg_match_all('/<File.*?<\/File>/', $fileList, $fileList);
|
||||
@ -347,7 +444,9 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku
|
||||
$temp['title'] = $updateTitle;
|
||||
$temp['ring'] = $ring;
|
||||
$temp['flight'] = $flight;
|
||||
$temp['branch'] = $branch;
|
||||
$temp['arch'] = $foundArch;
|
||||
$temp['fetchArch'] = $arch == 'all' ? 'amd64' : $arch;
|
||||
$temp['build'] = $foundBuild;
|
||||
$temp['checkBuild'] = $build;
|
||||
$temp['sku'] = $sku;
|
||||
@ -360,6 +459,10 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku
|
||||
$temp['releasetype'] = $type;
|
||||
}
|
||||
|
||||
if(!empty($flags)) {
|
||||
$temp['flags'] = $flags;
|
||||
}
|
||||
|
||||
$temp['created'] = time();
|
||||
$temp['sha256ready'] = true;
|
||||
$temp['files'] = $shaArray;
|
||||
@ -367,10 +470,11 @@ function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku
|
||||
consoleLogger('Successfully parsed the information.');
|
||||
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) {
|
||||
consoleLogger('Successfully written build information to the disk.');
|
||||
$fileWrite = 'INFO_WRITTEN';
|
||||
uupApiPrivateInvalidateFileinfoCache();
|
||||
} else {
|
||||
consoleLogger('An error has occured while writing the information to the disk.');
|
||||
}
|
||||
|
202
get.php
202
get.php
@ -18,6 +18,8 @@ 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';
|
||||
require_once dirname(__FILE__).'/shared/cache.php';
|
||||
require_once dirname(__FILE__).'/shared/fileinfo.php';
|
||||
|
||||
/*
|
||||
$updateId = Update Identifier
|
||||
@ -42,10 +44,16 @@ function uupGetFiles(
|
||||
}
|
||||
|
||||
if(!uupApiCheckUpdateId($updateId)) {
|
||||
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)) {
|
||||
$info = array(
|
||||
'ring' => 'WIF',
|
||||
@ -55,8 +63,6 @@ function uupGetFiles(
|
||||
'sku' => '48',
|
||||
'files' => array(),
|
||||
);
|
||||
} else {
|
||||
$info = json_decode($info, true);
|
||||
}
|
||||
|
||||
if(isset($info['build'])) {
|
||||
@ -70,8 +76,10 @@ function uupGetFiles(
|
||||
$info['sku'] = 48;
|
||||
}
|
||||
|
||||
$genPack = [];
|
||||
|
||||
if($usePack) {
|
||||
$genPack = uupGetGenPacks($build, $info['arch'], $updateId);
|
||||
$genPack = uupApiGetPacks($updateId);
|
||||
if(empty($genPack)) return array('error' => 'UNSUPPORTED_COMBINATION');
|
||||
|
||||
if(!isset($genPack[$usePack])) {
|
||||
@ -79,6 +87,8 @@ function uupGetFiles(
|
||||
}
|
||||
}
|
||||
|
||||
$appEdition = 0;
|
||||
|
||||
if(!is_array($desiredEdition)) {
|
||||
$desiredEdition = strtoupper($desiredEdition);
|
||||
$fileListSource = $desiredEdition;
|
||||
@ -104,13 +114,19 @@ function uupGetFiles(
|
||||
|
||||
case 'UPDATEONLY': break;
|
||||
|
||||
case 'APP': $appEdition = 1;
|
||||
case 'APP_MOMENT': $appEdition = 1;
|
||||
|
||||
default:
|
||||
if(!isset($genPack[$usePack][$desiredEdition])) {
|
||||
return array('error' => 'UNSUPPORTED_COMBINATION');
|
||||
}
|
||||
|
||||
$filesPacksList = $genPack[$usePack][$desiredEdition];
|
||||
$fileListSource = 'GENERATEDPACKS';
|
||||
$filesPacksList = $genPack[$usePack][$desiredEdition];
|
||||
if($desiredEdition == 'APP' && isset($genPack[$usePack]['APP_MOMENT'])) {
|
||||
$filesPacksList = array_merge($filesPacksList, $genPack[$usePack]['APP_MOMENT']);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -123,6 +139,7 @@ function uupGetFiles(
|
||||
return array('error' => 'UNSUPPORTED_COMBINATION');
|
||||
}
|
||||
|
||||
if($edition == 'APP' || $edition == 'APP_MOMENT') $appEdition = 1;
|
||||
$filesPacksList = array_merge($filesPacksList, $genPack[$usePack][$edition]);
|
||||
}
|
||||
}
|
||||
@ -138,6 +155,7 @@ function uupGetFiles(
|
||||
$updateBuild = (isset($info['build'])) ? $info['build'] : 'UNKNOWN';
|
||||
$updateName = (isset($info['title'])) ? $info['title'] : 'Unknown update: '.$updateId;
|
||||
$sha256capable = isset($info['sha256ready']);
|
||||
$hasUpdates = false;
|
||||
|
||||
if(isset($info['releasetype'])) {
|
||||
$type = $info['releasetype'];
|
||||
@ -164,16 +182,34 @@ function uupGetFiles(
|
||||
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) {
|
||||
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 = 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);
|
||||
if($build < 17763) $psfk = preg_grep('/Windows(10|11)\.0-KB.*_\d\.psf$/i', $psfk, PREG_GREP_INVERT);
|
||||
foreach($psfk as $key => $val) {
|
||||
if(isset($psf[$key])) unset($psf[$key]);
|
||||
}
|
||||
@ -201,24 +237,46 @@ function uupGetFiles(
|
||||
}
|
||||
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);
|
||||
$updatesRegex = '/Windows(10|11)\.0-KB|SSU-.*?\....$/i';
|
||||
|
||||
switch($fileListSource) {
|
||||
case 'UPDATEONLY':
|
||||
$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) {
|
||||
if(isset($filesInfoList[$val])) unset($filesInfoList[$val]);
|
||||
}
|
||||
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) {
|
||||
return array('error' => 'NOT_CUMULATIVE_UPDATE');
|
||||
}
|
||||
|
||||
if($build > 21380) $filesInfoKeys = array_merge($filesInfoKeys, $temp);
|
||||
unset($temp);
|
||||
$hasUpdates = true;
|
||||
break;
|
||||
|
||||
case 'WUBFILE':
|
||||
@ -232,8 +290,24 @@ function uupGetFiles(
|
||||
if($updateSku == 135) $uupCleanFunc = 'uupCleanHolo';
|
||||
|
||||
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);
|
||||
$temp = preg_grep('/Windows10\.0-KB|SSU-\d*?\.\d*?-.*?\.cab/i', $temp);
|
||||
foreach($removeMSUs as $val) {
|
||||
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/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);
|
||||
|
||||
$newFiles = array();
|
||||
@ -285,6 +359,7 @@ function uupGetFiles(
|
||||
$filesNew = array();
|
||||
foreach($filesInfoKeys as $val) {
|
||||
$filesNew[$val] = $filesInfoList[$val];
|
||||
$filesNew[$val]['url'] = uupApiFixDownloadLink($filesInfoList[$val]['url']);
|
||||
}
|
||||
|
||||
$files = $filesNew;
|
||||
@ -292,48 +367,54 @@ function uupGetFiles(
|
||||
|
||||
consoleLogger('Successfully parsed the information.');
|
||||
|
||||
return array(
|
||||
$data = [
|
||||
'apiVersion' => uupApiVersion(),
|
||||
'updateName' => $updateName,
|
||||
'arch' => $updateArch,
|
||||
'build' => $updateBuild,
|
||||
'sku' => $updateSku,
|
||||
'hasUpdates' => $hasUpdates,
|
||||
'appxPresent' => uupAreAppxPresent($genPack),
|
||||
'files' => $files,
|
||||
);
|
||||
];
|
||||
|
||||
if($requestType > 0) {
|
||||
$cacheData = $data;
|
||||
$cache->put($cacheData, 30);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests, $type) {
|
||||
$cacheHash = hash('sha256', strtolower("api-get-${updateId}_rev.$rev"));
|
||||
$cached = 0;
|
||||
$res = "api-get-online-{$updateId}_rev.$rev";
|
||||
$cache = new UupDumpCache($res);
|
||||
$fromCache = $cache->get();
|
||||
$cached = ($fromCache !== false);
|
||||
|
||||
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'];
|
||||
$fetchTime = $cache['fetchTime'];
|
||||
$cached = 1;
|
||||
} else {
|
||||
$cached = 0;
|
||||
}
|
||||
|
||||
unset($cache);
|
||||
}
|
||||
|
||||
if(!$cached) {
|
||||
if($cached) {
|
||||
$out = $fromCache['out'];
|
||||
$fetchTime = $fromCache['fetchTime'];
|
||||
} else {
|
||||
$fetchTime = time();
|
||||
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 === false || $out['error'] != 200) {
|
||||
consoleLogger('The request has failed');
|
||||
return array('error' => 'WU_REQUEST_FAILED');
|
||||
}
|
||||
|
||||
$out = $out['out'];
|
||||
consoleLogger('Information has been successfully fetched.');
|
||||
}
|
||||
|
||||
consoleLogger('Parsing information...');
|
||||
$xmlOut = @simplexml_load_string($out);
|
||||
if($xmlOut === false) {
|
||||
@unlink('cache/'.$cacheHash.'.json.gz');
|
||||
$cache->delete();
|
||||
return array('error' => 'XML_PARSE_ERROR');
|
||||
}
|
||||
|
||||
@ -381,15 +462,11 @@ function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests, $type) {
|
||||
if($sha256capable) {
|
||||
$tempname = uupCleanSha256($name);
|
||||
if(isset($files[$tempname])) {
|
||||
if(preg_match('/\.cab$/i', $tempname)) {
|
||||
if($size > $files[$tempname]['size']) {
|
||||
$express = 'baseless_'.$tempname;
|
||||
$files[$express] = $files[$tempname];
|
||||
unset($files[$tempname]);
|
||||
$newName = $tempname;
|
||||
} else {
|
||||
$newName = 'baseless_'.$tempname;
|
||||
}
|
||||
if($size > $files[$tempname]['size']) {
|
||||
$smaller = uupAppendSha1($tempname, $files[$tempname]['sha1']);
|
||||
$files[$smaller] = $files[$tempname];
|
||||
unset($files[$tempname]);
|
||||
$newName = $tempname;
|
||||
} else {
|
||||
$newName = uupAppendSha1($tempname, $sha1);
|
||||
}
|
||||
@ -433,14 +510,12 @@ function uupGetOnlineFiles($updateId, $rev, $info, $cacheRequests, $type) {
|
||||
}
|
||||
|
||||
if($cacheRequests == 1 && $cached == 0) {
|
||||
$cache = array(
|
||||
'expires' => time()+90,
|
||||
'content' => $out,
|
||||
$cacheData = [
|
||||
'out' => $out,
|
||||
'fetchTime' => $fetchTime,
|
||||
);
|
||||
];
|
||||
|
||||
if(!file_exists('cache')) mkdir('cache');
|
||||
@file_put_contents('cache/'.$cacheHash.'.json.gz', gzencode(json_encode($cache)."\n"));
|
||||
$cache->put($cacheData, 90);
|
||||
}
|
||||
|
||||
return $files;
|
||||
@ -462,24 +537,14 @@ function uupGetOfflineFiles($info) {
|
||||
$sha256 = isset($val['sha256']) ? $val['sha256'] : null;
|
||||
|
||||
if($sha256capable) {
|
||||
// clean file name
|
||||
$tempname = uupCleanSha256($name);
|
||||
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 the existing file is smaller, rename it
|
||||
$express = 'baseless_'.$tempname;
|
||||
$files[$express] = $files[$tempname];
|
||||
unset($files[$tempname]);
|
||||
$newName = $tempname;
|
||||
} else {
|
||||
// if the new file is smaller, rename it
|
||||
$newName = 'baseless_'.$tempname;
|
||||
}
|
||||
if($size > $files[$tempname]['size']) {
|
||||
$smaller = uupAppendSha1($tempname, $files[$tempname]['sha1']);
|
||||
$files[$smaller] = $files[$tempname];
|
||||
unset($files[$tempname]);
|
||||
$newName = $tempname;
|
||||
} else {
|
||||
// not a cab file, append hash to differentiate
|
||||
$newName = uupAppendSha1($tempname, $sha1);
|
||||
}
|
||||
} else {
|
||||
@ -518,8 +583,7 @@ function uupAppendSha1($name, $sha1) {
|
||||
|
||||
function uupCleanSha256($name) {
|
||||
$replace = array(
|
||||
'MetadataESD_' => null,
|
||||
'metadataesd_' => null,
|
||||
'prss_signed_appx_' => null,
|
||||
'~31bf3856ad364e35' => null,
|
||||
'~~.' => '.',
|
||||
'~.' => '.',
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/*
|
||||
Copyright 2019 UUP dump API authors
|
||||
Copyright 2023 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.
|
||||
@ -17,59 +17,35 @@ limitations under the License.
|
||||
|
||||
require_once dirname(__FILE__).'/shared/main.php';
|
||||
require_once dirname(__FILE__).'/shared/packs.php';
|
||||
require_once dirname(__FILE__).'/updateinfo.php';
|
||||
|
||||
function uupListEditions($lang = 'en-us', $updateId = 0) {
|
||||
if($updateId) {
|
||||
$info = uupUpdateInfo($updateId);
|
||||
}
|
||||
|
||||
if(!$lang) {
|
||||
return array('error' => 'UNSUPPORTED_LANG');
|
||||
}
|
||||
|
||||
if(isset($info['info'])) $info = $info['info'];
|
||||
$lang = strtolower($lang);
|
||||
$genPack = uupApiGetPacks($updateId);
|
||||
$fancyEditionNames = uupGetInfoTexts()['fancyEditionNames'];
|
||||
|
||||
if(isset($info['build'])) {
|
||||
$build = explode('.', $info['build']);
|
||||
$build = $build[0];
|
||||
} else {
|
||||
$build = 15063;
|
||||
if(!isset($genPack[$lang])) {
|
||||
return array('error' => 'UNSUPPORTED_LANG');
|
||||
}
|
||||
|
||||
if(!isset($info['arch'])) {
|
||||
$info['arch'] = null;
|
||||
}
|
||||
$editionList = [];
|
||||
$editionListFancy = [];
|
||||
|
||||
$genPack = uupGetGenPacks($build, $info['arch'], $updateId);
|
||||
$fancyTexts = uupGetInfoTexts();
|
||||
$fancyEditionNames = $fancyTexts['fancyEditionNames'];
|
||||
|
||||
if($lang) {
|
||||
$lang = strtolower($lang);
|
||||
if(!isset($genPack[$lang])) {
|
||||
return array('error' => 'UNSUPPORTED_LANG');
|
||||
}
|
||||
}
|
||||
|
||||
$editionList = array();
|
||||
$editionListFancy = array();
|
||||
foreach(array_keys($genPack[$lang]) as $edition) {
|
||||
if($edition == 'LXP') continue;
|
||||
if(in_array($edition, ['LXP', 'FOD'])) continue;
|
||||
|
||||
if(isset($fancyEditionNames[$edition])) {
|
||||
$fancyName = $fancyEditionNames[$edition];
|
||||
} else {
|
||||
$fancyName = $edition;
|
||||
}
|
||||
$fancyName = isset($fancyEditionNames[$edition]) ? $fancyEditionNames[$edition] : $edition;
|
||||
|
||||
$editionList[] = $edition;
|
||||
$editionListFancy[$edition] = $fancyName;
|
||||
}
|
||||
|
||||
return array(
|
||||
return [
|
||||
'apiVersion' => uupApiVersion(),
|
||||
'editionList' => $editionList,
|
||||
'editionFancyNames' => $editionListFancy,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
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/cache.php';
|
||||
require_once dirname(__FILE__).'/shared/fileinfo.php';
|
||||
|
||||
function uupListIds($search = null, $sortByDate = 0) {
|
||||
uupApiPrintBrand();
|
||||
function uupApiPrivateInvalidateFileinfoCache() {
|
||||
$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);
|
||||
|
||||
consoleLogger('Parsing database info...');
|
||||
|
||||
$cacheFile = 'cache/fileinfo_v2.json';
|
||||
$cacheFile = $fileinfoRoot.'/cache.json';
|
||||
$cacheV2Version = 1;
|
||||
|
||||
$database = @file_get_contents($cacheFile);
|
||||
$database = json_decode($database, true);
|
||||
$database = uupApiReadJson($cacheFile);
|
||||
|
||||
if(isset($database['version'])) {
|
||||
$version = $database['version'];
|
||||
@ -50,12 +59,13 @@ function uupListIds($search = null, $sortByDate = 0) {
|
||||
$newDb = array();
|
||||
$builds = array();
|
||||
foreach($files as $file) {
|
||||
if($file == '.' || $file == '..') continue;
|
||||
if($file == '.' || $file == '..')
|
||||
continue;
|
||||
|
||||
$uuid = preg_replace('/\.json$/', '', $file);
|
||||
|
||||
if(!isset($database[$uuid])) {
|
||||
$info = @file_get_contents('fileinfo/'.$file);
|
||||
$info = json_decode($info, true);
|
||||
$info = uupApiReadFileinfoMeta($uuid);
|
||||
|
||||
$title = isset($info['title']) ? $info['title'] : 'UNKNOWN';
|
||||
$build = isset($info['build']) ? $info['build'] : 'UNKNOWN';
|
||||
@ -105,12 +115,7 @@ function uupListIds($search = null, $sortByDate = 0) {
|
||||
$builds[$tmp.$arch.$title.$uuid] = $temp;
|
||||
}
|
||||
|
||||
if(empty($buildAssoc)) {
|
||||
return array(
|
||||
'apiVersion' => uupApiVersion(),
|
||||
'builds' => array(),
|
||||
);
|
||||
}
|
||||
if(empty($buildAssoc)) return [];
|
||||
|
||||
krsort($buildAssoc);
|
||||
$buildsNew = array();
|
||||
@ -141,7 +146,27 @@ function uupListIds($search = null, $sortByDate = 0) {
|
||||
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)) {
|
||||
$searchSafe = preg_quote($search, '/');
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/*
|
||||
Copyright 2019 UUP dump API authors
|
||||
Copyright 2023 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.
|
||||
@ -19,60 +19,45 @@ require_once dirname(__FILE__).'/shared/main.php';
|
||||
require_once dirname(__FILE__).'/shared/packs.php';
|
||||
require_once dirname(__FILE__).'/updateinfo.php';
|
||||
|
||||
function uupListLangs($updateId = 0) {
|
||||
if($updateId) {
|
||||
$info = uupUpdateInfo($updateId);
|
||||
}
|
||||
function uupListLangsInternal($updateId) {
|
||||
$genPack = uupApiGetPacks($updateId);
|
||||
$fancyLangNames = uupGetInfoTexts()['fancyLangNames'];
|
||||
|
||||
if(isset($info['info'])) {
|
||||
$info = $info['info'];
|
||||
unset($info['files']);
|
||||
}
|
||||
$langList = [];
|
||||
$langListFancy = [];
|
||||
|
||||
if(isset($info['build'])) {
|
||||
$build = explode('.', $info['build']);
|
||||
$build = $build[0];
|
||||
} else {
|
||||
$build = 15063;
|
||||
}
|
||||
|
||||
if(!isset($info['arch'])) {
|
||||
$info['arch'] = null;
|
||||
}
|
||||
|
||||
$genPack = uupGetGenPacks($build, $info['arch'], $updateId);
|
||||
$fancyTexts = uupGetInfoTexts();
|
||||
$fancyLangNames = $fancyTexts['fancyLangNames'];
|
||||
|
||||
$langList = array();
|
||||
$langListFancy = array();
|
||||
foreach($genPack as $key => $val) {
|
||||
if(!count(array_diff(array_keys($val), array('LXP')))) {
|
||||
if(!count(array_diff(array_keys($val), ['LXP', 'FOD']))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(isset($fancyLangNames[$key])) {
|
||||
$fancyName = $fancyLangNames[$key];
|
||||
} else {
|
||||
$fancyName = $key;
|
||||
}
|
||||
$fancyName = isset($fancyLangNames[$key]) ? $fancyLangNames[$key] : $key;
|
||||
|
||||
$langList[] = $key;
|
||||
$langListFancy[$key] = $fancyName;
|
||||
}
|
||||
|
||||
if(isset($info)) {
|
||||
return array(
|
||||
'apiVersion' => uupApiVersion(),
|
||||
'langList' => $langList,
|
||||
'langFancyNames' => $langListFancy,
|
||||
'updateInfo' => $info
|
||||
);
|
||||
} else {
|
||||
return array(
|
||||
'apiVersion' => uupApiVersion(),
|
||||
'langList' => $langList,
|
||||
'langFancyNames' => $langListFancy
|
||||
);
|
||||
}
|
||||
|
||||
return [
|
||||
'langList' => $langList,
|
||||
'langFancyNames' => $langListFancy,
|
||||
'appxPresent' => uupAreAppxPresent($genPack),
|
||||
];
|
||||
}
|
||||
|
||||
function uupListLangs($updateId = 0, $returnInfo = true) {
|
||||
if($returnInfo) {
|
||||
$info = uupUpdateInfo($updateId, ignoreFiles: true);
|
||||
$info = isset($info['info']) ? $info['info'] : false;
|
||||
}
|
||||
|
||||
$langList = uupListLangsInternal($updateId);
|
||||
|
||||
$response = array_merge(
|
||||
['apiVersion' => uupApiVersion()],
|
||||
$langList
|
||||
);
|
||||
|
||||
if($returnInfo) $response['updateInfo'] = $info;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
38
readme.md
38
readme.md
@ -10,7 +10,7 @@ Parameters:
|
||||
- **Supported values:** `amd64`, `x86`, `arm64`, `all`
|
||||
|
||||
- `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`
|
||||
|
||||
- `flight` - Content type to use when fetching information (Previously called Flight)
|
||||
@ -18,10 +18,10 @@ Parameters:
|
||||
- **Supported Flight values:** `Active`, `Skip`, `Current`
|
||||
- **NOTE:** `Skip` is for `WIF` ring only. `Current` is for `RP` ring only.
|
||||
|
||||
- `build` - Build number to use when fetching information
|
||||
- **Supported values:** >= 9841 and <= PHP_INT_MAX-1
|
||||
- `build` - Build number to use when fetching information. Can also be used to provide optional fetch flags in `major.minor+flag1,flag2` format.
|
||||
- **Supported values:** Any correctly formatted build (`major` or `major.minor`) from range of 9841 and `PHP_INT_MAX-1`.
|
||||
|
||||
- `minor` - Build minor to use when fetching information
|
||||
- `minor` - Build minor to use when fetching information. Unused when build is formatted in `major.minor` format
|
||||
- **Supported values:** >= 0 and <= PHP_INT_MAX-1
|
||||
|
||||
- `sku` - SKU number to use when fetching information
|
||||
@ -80,9 +80,11 @@ Outputs list of languages supported for specified Update ID.
|
||||
Parameters:
|
||||
- `updateId` - Update identifier (optional)
|
||||
- **Supported values:** any update UUID
|
||||
- `returnInfo` - Should the full update inforation be returned with a list of languages
|
||||
- **Supported values:** `true` or `false`
|
||||
|
||||
|
||||
#### updateinfo.php: `uupUpdateInfo($updateId, $onlyInfo);`
|
||||
#### updateinfo.php: `uupUpdateInfo($updateId, $onlyInfo, $ignoreFiles);`
|
||||
Outputs specified information of specified `updateId`.
|
||||
|
||||
Parameters:
|
||||
@ -92,12 +94,36 @@ Parameters:
|
||||
- `onlyInfo` - Key to output
|
||||
- **Supported values:** any string
|
||||
|
||||
- `ignoreFiles` - Skips the `files` key in the output
|
||||
- **Supported values:** `true` or `false`
|
||||
|
||||
#### shared/main.php: `uupApiVersion();`
|
||||
Returns version of the API.
|
||||
|
||||
Parameters:
|
||||
- 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
|
||||
**fetchupd.php**
|
||||
- UNKNOWN_ARCH
|
||||
@ -108,6 +134,7 @@ Parameters:
|
||||
- ILLEGAL_MINOR
|
||||
- NO_UPDATE_FOUND
|
||||
- EMPTY_FILELIST
|
||||
- WU_REQUEST_FAILED
|
||||
|
||||
**get.php**
|
||||
- UNSUPPORTED_LANG
|
||||
@ -118,6 +145,7 @@ Parameters:
|
||||
- MISSING_FILES
|
||||
- NO_FILES
|
||||
- XML_PARSE_ERROR
|
||||
- WU_REQUEST_FAILED
|
||||
|
||||
**listeditions.php**
|
||||
- UNSUPPORTED_LANG
|
||||
|
@ -25,19 +25,46 @@ function uupDevice() {
|
||||
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() {
|
||||
$cookieInfo = @file_get_contents(dirname(__FILE__).'/cookie.json');
|
||||
$cookieInfo = json_decode($cookieInfo, 1);
|
||||
$cookieStorage = new UupDumpCache('WuRequestCookie', false);
|
||||
$cookieInfo = $cookieStorage->get();
|
||||
|
||||
if(empty($cookieInfo)) {
|
||||
$postData = composeGetCookieRequest(uupDevice());
|
||||
sendWuPostRequest('https://fe3.delivery.mp.microsoft.com/ClientWebService/client.asmx', $postData);
|
||||
$data = sendWuPostRequestHelper('client', 'composeGetCookieRequest', [], false);
|
||||
if($data === false || $data['error'] != 200)
|
||||
return false;
|
||||
|
||||
$encData = uupEncryptedData();
|
||||
} else {
|
||||
$encData = $cookieInfo['encryptedData'];
|
||||
$cookieInfo = uupSaveCookieFromResponse($data['out']);
|
||||
}
|
||||
|
||||
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() {
|
||||
return '1.32.0';
|
||||
return '1.48.0';
|
||||
}
|
||||
|
||||
require_once dirname(__FILE__).'/auths.php';
|
||||
|
172
shared/packs.php
172
shared/packs.php
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/*
|
||||
Copyright 2021 UUP dump API authors
|
||||
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.
|
||||
@ -19,6 +19,7 @@ require_once dirname(__FILE__).'/../listid.php';
|
||||
|
||||
function uupGetInfoTexts() {
|
||||
$fancyLangNames = array(
|
||||
'neutral' => 'Any Language',
|
||||
'ar-sa' => 'Arabic (Saudi Arabia)',
|
||||
'bg-bg' => 'Bulgarian',
|
||||
'cs-cz' => 'Czech',
|
||||
@ -61,6 +62,9 @@ function uupGetInfoTexts() {
|
||||
);
|
||||
|
||||
$fancyEditionNames = array(
|
||||
'APP' => 'Microsoft Store Inbox Apps',
|
||||
'APP_MOMENT' => 'Microsoft Store Moment Apps',
|
||||
'FOD' => 'Features on Demand (Capabilities)',
|
||||
'CLOUD' => 'Windows S',
|
||||
'CLOUDN' => 'Windows S N',
|
||||
'CLOUDE' => 'Windows Lean',
|
||||
@ -79,6 +83,7 @@ function uupGetInfoTexts() {
|
||||
'PPIPRO' => 'Windows Team',
|
||||
'PROFESSIONAL' => 'Windows Pro',
|
||||
'PROFESSIONALN' => 'Windows Pro N',
|
||||
'PROFESSIONALCOUNTRYSPECIFIC' => 'Windows Pro China Only',
|
||||
'SERVERSTANDARD' => 'Windows Server Standard',
|
||||
'SERVERSTANDARDCORE' => 'Windows Server Standard, Core',
|
||||
'SERVERDATACENTER' => 'Windows Server Datacenter',
|
||||
@ -198,166 +203,17 @@ function uupGetInfoTexts() {
|
||||
);
|
||||
}
|
||||
|
||||
function uupGetGenPacks($build = 15063, $arch = null, $updateId = null) {
|
||||
$internalPacks = dirname(__FILE__).'/packs';
|
||||
function uupApiGetPacks($updateId) {
|
||||
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'));
|
||||
if(empty($genPack)) return array();
|
||||
|
||||
$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();
|
||||
}
|
||||
}
|
||||
$genPack = @gzdecode(@file_get_contents('packs/'.$updateId.'.json.gz'));
|
||||
if(empty($genPack)) return [];
|
||||
|
||||
$genPack = json_decode($genPack, 1);
|
||||
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;
|
||||
function uupGetGenPacks($build = 15063, $arch = null, $updateId = null) {
|
||||
return uupApiGetPacks($updateId);
|
||||
}
|
||||
|
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