Compare commits

..

99 Commits

Author SHA1 Message Date
7b3cd4eb10 1.48.0 2024-10-22 23:28:00 +02:00
c1f00cecbd Merge pull request 'Add support for NetFX updates' (#1) from abbodi1406/api:master into master
Reviewed-on: uup-dump/api#1
2024-10-22 23:27:34 +02:00
8b576e4496 Add support for NetFX updates 2024-10-21 17:24:10 +03:00
21b1500490 Fix warning 2024-06-22 18:50:39 +02:00
fb2c89b2f8 Remove DesktopDeployment from appx sets 2024-06-21 21:07:17 +02:00
846feb2629 Update WU parameters 2024-06-21 15:37:16 +02:00
5e31a6f724 Add additional appx presence checks 2024-06-21 13:31:41 +02:00
faa3b7fa45 Add Appx presence check 2024-06-19 13:29:23 +02:00
42b1091c0b Save architecture used to fetch the build to fileinfo 2024-05-09 22:22:29 +02:00
aa2dbd2938 Add ProfessionalCountrySpecific 2024-04-19 23:01:21 +02:00
42c1c12405 Update auto branch detection for 26100 2024-04-17 21:35:02 +02:00
092e968f0c Initial WNC support
The value was revealed to me in a dream
2024-03-18 20:16:47 +01:00
d58f53de42 Fix broken minor support 2024-03-12 20:50:07 +01:00
ca81835609 Branch selection support 2024-02-28 18:38:42 +01:00
d10e24cf5b Ignore case of specified build 2023-11-11 03:39:16 +01:00
140613f657 Minor flags fixes 2023-11-09 20:36:28 +01:00
4694c8dc00 Add flags verification 2023-11-09 20:29:25 +01:00
0477fd5fa6 Gracefully handle lack of the cookie 2023-11-08 23:58:39 +01:00
1ef84cb879 Replace children's toy with real man's computer 2023-11-05 00:08:40 +01:00
9e618c405a 1.43.0 2023-11-03 20:23:10 +01:00
7711645f23 Update readme 2023-11-03 20:22:26 +01:00
d597a83422 Add option to provide optional fetch flags 2023-11-03 20:13:28 +01:00
d0bad95c11 1.42.1 2023-11-03 17:11:47 +01:00
2a57ae0fe6 Add fallback parameters 2023-11-03 17:10:43 +01:00
7bdc01bdb9 1.42.0 2023-10-29 01:40:56 +02:00
b13403cf59 Use uupApiGetPacks in get.php 2023-10-29 00:07:48 +02:00
5777ff09b6 listeditions.php cleanup 2023-10-28 23:17:34 +02:00
954547ea84 listlangs.php cleanup 2023-10-28 23:03:40 +02:00
db1e155c8d uupGetGenPacks -> uupApiGetPacks 2023-10-28 23:02:43 +02:00
543e4c52e4 Fix fltBranch warning 2023-10-24 22:36:44 +02:00
3855dc9ac4 Rewrite WU requests and cookie handling 2023-10-21 02:34:51 +02:00
8959eb14a4
Merge pull request #30 from abbodi1406/master
v1.40.3
2023-09-27 18:31:16 +03:00
abbodi1406
ada8ae6011 v1.40.3 2023-09-27 18:28:08 +03:00
492fd22e46
Merge pull request #29 from abbodi1406/master
Update DeviceAttributes
2023-07-13 17:25:49 +03:00
abbodi1406
03258c7bfe Update DeviceAttributes 2023-07-13 17:23:18 +03:00
c7512dd40d
Merge pull request #27 from abbodi1406/master
Add support for Canary
2023-03-14 18:29:56 +03:00
abbodi1406
b1d8121507 Add support for Canary 2023-03-14 18:09:51 +03:00
eraseyourknees
1fc14b6fd4 1.39.3 2022-10-23 17:58:32 +02:00
eraseyourknees
c5d4090bac get.php: Fix cache 2022-10-23 17:58:14 +02:00
eraseyourknees
b0f78dedbc 1.39.2 2022-10-22 01:20:35 +02:00
eraseyourknees
2cfa0422c1 Improve caching 2022-10-22 01:20:13 +02:00
eraseyourknees
d089aa698c Disable link changes to HTTPS 2022-10-05 16:32:40 +02:00
eraseyourknees
aeb86d4333
Merge pull request #25 from uup-dump-dev/master
1.39.0
2022-09-21 17:03:48 +02:00
eraseyourknees
cf34eea8e1 1.39.0 2022-09-16 00:48:39 +02:00
eraseyourknees
c025da99dc Add fetching specific builds only 2022-09-16 00:45:03 +02:00
eraseyourknees
f5f4795cd9 Add support for the internal corpnet 2022-09-16 00:34:44 +02:00
eraseyourknees
1cc48ae9d8 Add config reader helper 2022-09-16 00:24:18 +02:00
eraseyourknees
79730cdd24 Add pack check helper function 2022-09-15 16:12:10 +02:00
eraseyourknees
cf57876aca
Merge pull request #24 from uup-dump-dev/master
1.38.0
2022-09-14 19:06:05 +02:00
eraseyourknees
541f8d9515 1.38.0 2022-09-13 23:59:43 +02:00
eraseyourknees
6831bb17e9 updateinfo.php: Adjust for the new fileinfo db 2022-09-13 23:42:12 +02:00
eraseyourknees
0d06ee36f5 listid.php: Adjust for the new fileinfo database 2022-09-13 23:41:56 +02:00
eraseyourknees
76092ff092 get.php: Adjust for the new fileinfo database 2022-09-13 23:41:50 +02:00
eraseyourknees
9e3c1c574b fetchupd.php: Adjust for the new fileinfo database 2022-09-13 23:41:43 +02:00
eraseyourknees
16b3bc786d Add new fileinfo database support functions 2022-09-13 23:40:18 +02:00
eraseyourknees
8894bd9cc0 Add helper functions for json files 2022-09-13 23:40:03 +02:00
eraseyourknees
54b605c1d4 1.37.0 2022-09-11 03:47:20 +02:00
eraseyourknees
6d5f3a80f9 Move fileinfo cache to fileinfo directory 2022-09-11 03:46:54 +02:00
eraseyourknees
980863c20e
Merge pull request #23 from uup-dump-dev/master
1.36.0
2022-09-07 01:55:04 +02:00
eraseyourknees
e310ab4246 1.36.0 2022-09-07 01:50:31 +02:00
eraseyourknees
6a524aa0c0 Move download link replacements 2022-09-07 01:28:19 +02:00
eraseyourknees
749fd65769 Fix deprecated usage of str_contains 2022-09-07 01:03:23 +02:00
eraseyourknees
a3c0065706 1.35.1 2022-09-06 17:22:54 +02:00
eraseyourknees
0ea0de8c2c Add curl timeouts 2022-09-06 17:22:36 +02:00
eraseyourknees
6e55605fb2 Update readme 2022-08-29 17:33:10 +02:00
eraseyourknees
4a29784380
Merge pull request #22 from eraseyourknees/master
1.35.0
2022-08-29 17:06:05 +02:00
eraseyourknees
6cd9c0c414 1.35.0 2022-08-29 17:02:26 +02:00
eraseyourknees
64959ebf3d Use shared functions instead of constants 2022-08-29 16:59:10 +02:00
eraseyourknees
6c00b7c16f Merge remote-tracking branch 'uup-dump/master' 2022-08-29 16:23:53 +02:00
eraseyourknees
be2a2f2877 A little cleanup of the caching class 2022-08-29 03:36:33 +02:00
eraseyourknees
067f7f2937 Add some helper functions 2022-08-29 03:01:11 +02:00
eraseyourknees
7011b1ead2
Merge pull request #21 from eraseyourknees/master
1.34.0
2022-08-28 14:54:22 +02:00
eraseyourknees
547aa1512a 1.34.0 2022-08-28 14:49:18 +02:00
eraseyourknees
2d5fcf1f15 Fix 0 being interpreted as false 2022-08-27 02:47:32 +02:00
eraseyourknees
4971a19b8a Add listid response caching 2022-08-26 20:10:15 +02:00
eraseyourknees
2dbb52dc7f
Merge pull request #20 from eraseyourknees/master
1.33.0
2022-08-25 22:15:46 +02:00
eraseyourknees@gmail.com
82070f9c15 1.33.0 2022-08-25 22:12:41 +02:00
eraseyourknees@gmail.com
4dbe52a32b Fix cache compression 2022-08-25 18:46:36 +02:00
eraseyourknees@gmail.com
c85957b8a9 Update listings to ignore files 2022-08-25 18:32:21 +02:00
eraseyourknees@gmail.com
9a80701470 Add option to ignore files from fileinfo 2022-08-25 18:27:28 +02:00
eraseyourknees@gmail.com
d5769f635c Fix uncompressed cache 2022-08-25 18:12:01 +02:00
eraseyourknees@gmail.com
99f6e8d940 Use the new cache where needed 2022-08-25 17:46:16 +02:00
eraseyourknees@gmail.com
c14287dcbd Fix cache expiration 2022-08-25 17:44:37 +02:00
eraseyourknees@gmail.com
aa86232bd3 Use cache version in resource hashes 2022-08-25 17:31:20 +02:00
eraseyourknees@gmail.com
6e4e53ade8 Implement central caching class 2022-08-25 17:19:47 +02:00
eraseyourknees@gmail.com
12db118aae Return if there are additional updates to integrate 2022-08-25 03:59:37 +02:00
eraseyourknees@gmail.com
16d048df08 Get rid of the internal packs 2022-08-25 03:34:25 +02:00
eraseyourknees@gmail.com
a0f0574a81 Change hardware 2022-08-25 02:16:15 +02:00
eraseyourknees@gmail.com
89209ff40c Bump version 2022-08-25 01:19:06 +02:00
d007804b5e
Update Attributes 2022-07-29 15:19:26 +03:00
e4b33f0465
Add branch for 19045 2022-07-01 19:34:49 +03:00
a3c35f89fa
regulate files names
append sha1 name suffix for the smaller duplicate file, thus unify the result for findfiles/get
2022-06-17 02:00:48 +03:00
47b7ee6703
Add ni_release branch 2022-06-12 05:24:06 +03:00
a46a5628c0
ni_release / sha256 changes (#19)
add preliminary support for ni_release Apps as standalone edition
if equivalent cab files exist, exclude updates msu files (from download only)
exclude unnecessary baseless/express files
append 8-sha1 name suffix only for dupliicate files
2022-03-05 19:46:31 +01:00
luzea
972cff36a5 Detect updates for build 22567 and later 2022-03-04 23:27:39 +01:00
luzea
bcabed0d33 Use HTTPS for downloading files from Microsoft 2022-02-08 16:43:26 +01:00
abbodi1406
e889ec6629 Exclude FOD as edition 2021-12-31 13:44:02 +03:00
0665adf5f6
Include W11 LCU MSU reqs 2021-12-01 02:35:43 +03:00
3b884e2086
Rename WIP 11 CU for Server 2021-10-22 20:38:07 +03:00
479 changed files with 874 additions and 485 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
shared/cookie.json

View File

@ -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
) {
uupApiPrintBrand();
[$build, $flags] = uupApiPrivateParseFlags($build);
$arch = strtolower($arch);
$ring = strtoupper($ring);
$flight = ucwords(strtolower($flight));
$flight = 'Active';
$params = [
'arch' => $arch,
'ring' => $ring,
'flight' => $flight,
'build' => $build,
'minor' => $minor,
'sku' => $sku,
'type' => $type,
'flags' => $flags,
];
if($build == 'latest' || (!$build)) {
$builds = array('17134.1');
$ids = uupListIds();
if(isset($ids['error'])) {
$ids['builds'] = array();
return uupFetchUpd2($params, $cacheRequests);
}
$build = $ids['builds'][0]['build'];
unset($builds, $ids);
function uupFetchUpd2($params, $cacheRequests = 0) {
uupApiPrintBrand();
$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'];
$flagsStr = implode(',', $flags);
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,45 +189,22 @@ 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);
}
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);
$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');
}
$out = html_entity_decode($out);
$out = html_entity_decode($out['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);
}
}
preg_match_all('/<UpdateInfo>.*?<\/UpdateInfo>/', $out, $updateInfos);
$updateInfo = preg_grep('/<IsLeaf>true<\/IsLeaf>/', $updateInfos[0]);
sort($updateInfo);
@ -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);
}
function parseFetchUpdate($updateInfo, $out, $arch, $ring, $flight, $build, $sku, $type) {
return $data;
}
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;
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.');
}

186
get.php
View File

@ -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
@ -45,7 +47,13 @@ function uupGetFiles(
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;
if($cached) {
$out = $fromCache['out'];
$fetchTime = $fromCache['fetchTime'];
} else {
$cached = 0;
}
unset($cache);
}
if(!$cached) {
$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];
$smaller = uupAppendSha1($tempname, $files[$tempname]['sha1']);
$files[$smaller] = $files[$tempname];
unset($files[$tempname]);
$newName = $tempname;
} else {
$newName = 'baseless_'.$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];
$smaller = uupAppendSha1($tempname, $files[$tempname]['sha1']);
$files[$smaller] = $files[$tempname];
unset($files[$tempname]);
$newName = $tempname;
} 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);
}
} else {
@ -518,8 +583,7 @@ function uupAppendSha1($name, $sha1) {
function uupCleanSha256($name) {
$replace = array(
'MetadataESD_' => null,
'metadataesd_' => null,
'prss_signed_appx_' => null,
'~31bf3856ad364e35' => null,
'~~.' => '.',
'~.' => '.',

View File

@ -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'];
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();
$fancyEditionNames = $fancyTexts['fancyEditionNames'];
if($lang) {
$lang = strtolower($lang);
$genPack = uupApiGetPacks($updateId);
$fancyEditionNames = uupGetInfoTexts()['fancyEditionNames'];
if(!isset($genPack[$lang])) {
return array('error' => 'UNSUPPORTED_LANG');
}
}
$editionList = array();
$editionListFancy = array();
$editionList = [];
$editionListFancy = [];
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,
);
];
}

View File

@ -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, '/');

View File

@ -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(),
return [
'langList' => $langList,
'langFancyNames' => $langListFancy,
'updateInfo' => $info
);
} else {
return array(
'apiVersion' => uupApiVersion(),
'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;
}

View File

@ -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

View File

@ -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
View 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
View 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;
}

View File

@ -16,7 +16,7 @@ limitations under the License.
*/
function uupApiVersion() {
return '1.32.0';
return '1.48.0';
}
require_once dirname(__FILE__).'/auths.php';

View File

@ -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();
if(empty($genPack)) return [];
$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;
}
//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);
}

Some files were not shown because too many files have changed in this diff Show More